Здравствуйте, господа!
Я был достаточно приятно удивлен, когда узнал, что проект Ajax.org, именуемый Ace почти ни разу не упоминался на хабре. Ace — это веб-редактор исходного кода нового поколения. Он поддерживает уйму различных функций, среди которых: наличие режимов подсветки синтаксиса для более чем 60 языков программирования, сумасшедщего количества цветовых схем из различных поопулярный IDE, широкой кастомизации вида и функционала, syntax checkers для нескольких скриптовых языков. Так уж получилось, что эта статья скорее всего будет разносторонняя, т.е. содержать материал для веб-разработчиков и С++ программистов, которых я так успешно агитирую в сторону Qt. Итак, что вы можете прочитать в этой статье?
- Быстрый старт с Ace. Где я могу использовать Ace? Почему?
- Портирование Ace на Qt и обертка его API: How-To для создателей Qt5-based библиотек
Сейчас позволю себе показать пару скриншотов example-приложения, которое использует мою библиотеку Novile:
Что такое Ace?
Ace (англ. Ajax.org Cloud9 Editor) — онлайн-редактор исходного кода с подсветкой синтаксиса, темами, и горячими клавишами, написанный на Javascript, распространяющийся по лицензиям MPL/LGPL/GPL и легко встраиваемый в любую веб-страницу. Ace разработан в качестве основного редактора Cloud9 IDE является продолжением проекта Mozilla Skywriter (Bespin). Сейчас проек хостится на GitHub и активно развивается.
Ace может заинтересовать того, кому необходимо установить красивый, и главное — удобный редактор исходного кода на сайт или встроить в свое приложение. Из приемуществ редактора можно выделить такие:
- Подсветка для более чем 60 языков (есть импорт файлов .tmlanguage)
- Есть более 20 тем оформления (.tmtheme также импортируются)
- Проверка синтаксиса в режиме реального времени (JavaScript/PHP/CSS/etc.)
- Работает на больших документах (говорят, тянет 4 000 000 строчках кода)
- Сворачивание кода, при наличии его языка программирования
- Легко настраиваемые «горячие» клавиши и комбинации
- Несколько курсоров и выделений
- Отображение непечатных символов (что очень не маловажно)
- Автоматическое выравнивание кода
- Поиск и замена на регулярках
- Режимы soft и hard табуляций
Это и делает Ace очень удобным и легко встраиваемым редактором!
API и документации
Присутствие документации определяет ее отсутсвие. Короче говоря, нормальной документации у Ace’a нету. На сайте таковое есть, но назвать его API Reference — это слишком громко сказать. Сейчас, давайте как-то интеративненько настроим этот редактор. Stey-by-step, так сказать.
Шаг 1. Элементарная настройка
Начнем с создания предпологаемой страницы с редактором. Создадим шаблон:
<!DOCTYPE html> <html lang="en"> <head> <title>Ace Editor Demo</title> <style type="text/css"> #editor { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } </style> </head> <body> <div id="editor"></div> <script src="http://d1n0x3qji82z53.cloudfront.net/src-min-noconflict/ace.js" type="text/javascript" charset="utf-8"></script> <script> var editor = ace.edit("editor"); // теперь обращаться к редактору будем через editor // Далее весь экшон будет проходить тут! </script> </body> </html>
Отлично! Теперь у нас есть простая страничка с простым редактором кода. Это уже что-то. Кстати, можно использовать другие источники Ace.js. Не говоря о том, что вам понадобятся другие файлы, лучше вообще собирать его самостоятельно (node-ом) или собирать по-кусочком из built-файлов с различным функционалом.
Шаг 2. Больше красок!
Сейчас настало время добавить красок нашему предпологаемому JavaScript коду. Это можно легко сделать путем нескольких нехитрых call-ов. Ну что, давайте допишем пару строчек:
editor.setTheme("ace/theme/monokai"); editor.getSession().setMode("ace/mode/javascript");
Что же мы сделали? Тема редактора задается строкой, содержащей путь формата ace/theme/<theme_name>. Важно отметить, что тема — это именно атрибут Editor. Далее мы задаем режим подсветки, подсветка — атрибут EditSession. Она задается аналогично теме, за исключением того, что задается не редактору на прямую, а его сессии. Теперь, давайте что-то памалякаем. Например, можете поупражняться в написании навороченого jquery-based AJAX-запроса 🙂
Шаг 3. Управляем текстом на API-level
Писать код — хорошо, но еще лучше уметь что-то с ним делать на программном уровне. На этом шаге я постараюсь разобраться в основных функциях редактора и их API. Как сказал Гагарин, Поехали!
Получаем и задаем содержимое:
editor.setValue("<source code>"); // задаем editor.getValue(); // -> String (получаем)
Немного работы с выделением:
var selectionRange = editor.getSelectionRange(); // Range - название говорит само за себя var selectionText = editor.getSession().getTextRange(selectionRange); // -> String (текст выделения)
А теперь немного поиграемся с курсором:
var pos = editor.getCursorPosition(); // Object {row: N, column: M} editor.insert("I know how to insert text"); // вставляем в точку, где находится курсор editor.gotoLine(lineNumber); // переходим на линию #lineNumber (нумерация с нуля)
Что насчет расширенного управление кодингом?
var lines = editor.session.getLength(); // колличество строчек в документе editor.getSession().setUseSoftTabs(true); // использования "мягкого" выравнивания Tab-ами. document.getElementById('editor').style.fontSize='12px'; // достаточно только поменять размер шрифта #editor editor.getSession().setUseWrapMode(true); // включаем text wrapping editor.setShowPrintMargin(false); // такая полоска-граница (40, 80 или свободно число символов, считая слева) editor.setReadOnly(true); // нельзя редактировать, false - можно
Кстати, если вдруг вам захочется поменять размер div#editor, не меняя размеров самого окна, то нужно выполнить
editor.resize()
Шаг 4. Поиск и события (events)
К сожалению, о поиске я скажу только пару слов, так как почему-то нет желания сейчас сдесь описывать его работу. Вкраце, поддерживает регулярные выражения, чувствительность к регистру, и много других параметров. API сводится к
editor.find('needle', { // ищем текст "needle" backwards: false, // только спереди курсора wrap: false, // циклируем по документу caseSensitive: false, // все равно на регистр wholeWord: false, // только слово целиком regExp: false // без регулярок }); editor.findNext(); editor.findPrevious(); editor.replaceAll('pub');
Слушаем различные события:
// Что-то изменилось в сессии editor.getSession().on('change', function(e) { // e.type, etc }); // Поменялось выделение editor.getSession().selection.on('changeSelection', function(e) { // e.type, etc }); // Смена локации курсора editor.getSession().selection.on('changeCursor', function(e) { // e.type, etc });
А теперь очень классное, «горячие» клавиши и сочетания:
editor.commands.addCommand({ name: 'myCommand', // название комманды bindKey: {win: 'Ctrl-M', mac: 'Command-M'}, // вызов на PC и Mac exec: function(editor) { // судный час // editor.* }, readOnly: true // false, если мы не хотим чтобы в readOnly работало });
В теории, обладая этими знаниями (+ специфика из полного api reference) можно написать редактор, аналогичный редактору Cloud9 IDE. Конечно нужно очень сильно его extend-ить, но оно того стоит.
Novile Component for Qt
Сейчас речь пойдет о проекте Novile, проекте над которым я работал последнюю неделю. Смелые продолжат читать, а те, кому не особо оно-то и колышется, могут пролистать к Заключению. А джедаев я попрошу остаться. Я собираюсь рассказать о том, как использовать Novile, зачем он нужен, и главное, расскажу,
Кому оно надо?
Когда я начинал работу над Novile, я в первую очередь думал о том, какое она сможет найти применение. По отзывам знакомых программистов, я решил, что использовать Novile можна в различных десктопных (и не только) приложениях, где нужно редактировать код или как минимум, конфигурационные файлы. Таких приложений есть достаточно много, а с Novile их должно стать больше.
Novile, в частности, created with Qt, created for Qt. Кто не знает, Qt — это фреймворк для разработки кросс-платформенного ПО на C++ (еще можно на Python, Java, но это не тот случай). Погуглив, можно понять что Qt — это нечто, что Qt — это Linux Mac Window Symbian Android iOS Embedded. Novile — это мост между низкоуровневым API редактора на JavaScript к высокоуровневому коду на С++ через QtWebKit.
Сборочная система
Не смотря на то, что Qt очень активно пропагандирует QMake, а уже скоро начнется QBS-мания, я считаю что для библиотек самый лучший вариант, одназначно CMake. Он дает тот уровень кастомизации зборки, который действительно нужен.
Сейчас для зборки и установки Novile с документацией, debug output и примером нужно выполнить (Linux):
cd path/to/novile mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=path -DVERBOSE_OUTPUT=Yes -DBUILD_DOCS=Yes -DBUILD_EXAMPLE=Yes .. make # можно пропустить make install
Удобно, не так-ли? Сегодня я попробую научить вас делать такие библиотеки (в данном случае для Qt 5). Кстати, я не буду рассказывать как работает СMake, и как с ним работать, так как на хабре уже есть такая статья. Она отнимет у вас буквально пару минут. А сейчас, если вам неинтересен CMake, вы можете пролистать следующую статью.
Qt 5 в CMake 2.8.8+
Как же заставить CMake собирать Qt 5 проекты? Да очень просто. Читаем код и комментарии (кстати, приятно, что на хабре есть хайлайтер для CMake):
# .h файлы будут автоматически подвержены мета-объектному компилятору set(CMAKE_AUTOMOC ON) # будет добавлять текущую папку в инклюды автоматически # (не нужно будет везде писать include_directories(.) set(CMAKE_INCLUDE_CURRENT_DIR ON) # ищем QtWebKitWidgets и находим (я надеюсь) # кстати, чтобы оно его нашло, cmake-файлы Qt должны быть в $PATH find_package(Qt5WebKitWidgets REQUIRED) # я люблю записывть все .cpp файлы в такой манер set(NOVILE_SOURCES # .cpp editor.cpp ) # аналогично set(NOVILE_HEADERS # .h editor.h novile_export.h novile_debug.h editor_p.h ) # QRC - файлы ресурсов Qt. Утилита uic собирает .qrc файлы в qrc_*.cpp файлы, которые # можна использовать для ресурсов. NOVUILE_RCC_SRC - готовые qrc_*.cpp файлы qt5_add_resources(NOVILE_RCC_SRC ../data/shared.qrc) # скармливаем файл ресурсов и получаем qrc_*.cpp файл add_library(novile SHARED ${NOVILE_SOURCES} # создаем shared-библиотеку ${NOVILE_HEADERS} ${NOVILE_RCC_SRC} ../data/shared.qrc # только чтобы этот файл отображался в дереве проекта IDE (.cbp файл) ) qt5_use_modules(novile WebKitWidgets) # linkуем к таргету модуль Qt 5 set_target_properties(novile PROPERTIES # свойства библиотеки DEFINE_SYMBOL NOVILE_MAKEDLL # define для свитчера EXPORT/IMPORT PUBLIC_HEADER "${NOVILE_HEADERS}" # хедеры для установки ) install(TARGETS novile LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_PREFIX}/include )
Если вы создаете свою библиотеку, то этого вам не избежать. Еще вам может понадобится собирать .ui файлы пользовательского интерфейса. Для этого есть специальный макрос:
# EXAMPLE_UIC_HDR - переменная со сгенерированными ui_*.h qt5_wrap_ui(EXAMPLE_UIC_HDR mainwindow.ui)
Import/Export свитчеры
При работе с библиотекой, некоторые символы должны уйти в експорт, а потом, на этапе использования либы, быть импортироваными из нее, поэтому удобно использовать такую конструкцию:
#ifndef NOVILE_EXPORT # if defined(NOVILE_MAKEDLL) # define NOVILE_EXPORT Q_DECL_EXPORT // кьютовый макрос экспорта # else # define NOVILE_EXPORT Q_DECL_IMPORT // импорта # endif #endif class NOVILE_EXPORT MyClass { Q_OBJECT // ...
Итак, теперь, во время зборки, нужно объявить -DNOVILE_MAKEDLL (помните, выше мы его установили в cmake). При использовании библиотеки, макроса не будет, и будет вызван экспорт.
Как пользоваться Novile?
Пример использования Novile классно описан в проекте из папки example, который хорошо собирается с ключем конфигурации -DBUILD_EXAMPLE=Yes, который сделает все за вас.
Но тут я готов привести маленький пример того, как же удобно это все делается из плюсов (С++11 + Qt 5)
#include <Novile/Editor> using namespace std; // somewhere in the code... Editor *editor = new Editor; editor->setHighlightMode(Editor::ModePython); editor->setTheme(Editor::ThemeMonokai); editor->setFontSize(13); editor->setPrintMarginShown(false); connect(editor, &Editor::textChanged, [=]() { // код будет выполнен асинхронно на событии const QString &text = editor->text(); doSmth(text); }); editor->show(); // показать его миру
C++11, мощный Qt и дописанная Novile позволяют построить быструю и кросс-платформенную IDE со всем необходимым функционалом.
Заключение
Я надеюсь что эта статья действительно помогла и веб-разработчикам и программистам. Представить не могу, насколько удачно я сагитировал народ на Qt, но я старался. Честно. Хотелось бы сказать пару слов в сторону Novile. Признаться говоря, сейчас Novile не совсем хороший продукт, чтобы я про него не говорил. Сейчас она покрывает от силы 50% функционала Ace. Если есть кто-то заинтересованый, вы всегда можете помочь проекту на GitHub. Даже самый маленький pull request будет кстати.
Ссылочки
Спасибо за внимание,
namespace
ссылка на оригинал статьи http://habrahabr.ru/post/174987/
Добавить комментарий