Pull to refresh

QScintilla: все глубже и глубже

Reading time2 min
Views4.9K
Добрый день!

Чуть не забыл. Первая и вторая статья цикла.

Это опять я, со своей новой статьей. Сегодня я расскажу вам, как работать с qscintilla почти на полную мощь. А конкретнее: покажу почему полезно наследовать QsciScintilla своим классом, нежели использовать его копию и расскажу как писать какой-никакой автокомплит кода для своего редактора.

Сразу скажу, статья будет небольшая, а как работать со всем этим хламом я покажу на примере моего пока слабо развивающегося проекта Web Development IDE Galactica.

Начнем со второго. Что мы хотим сделать? Мы хотим сделать редактор, который автокомплитит текст. И очевидно, что лучший вариант для этого клавиша Ctrl+Space. Но тут нас поджидает фэйл — после заветного бинда в редактор вставляется символ NULL. Для меня очевидным решением есть наследования QsciScintilla и переопределение keyPressEvent().

Я наведу листинг keyPressEvent():
void MainEditor::keyPressEvent(QKeyEvent *e)
{
    if((e->modifiers() == Qt::CTRL) && (e->key() == Qt::Key_Space)) { // Ctrl+<Space>
        autoCompleteFromAll();
        return; // не дает дописать NULL
    }
    //...
    QsciScintilla::keyPressEvent(e);
}


Отлично. Теперь когда мы нажимаем на Ctrl+Space — мы вызываем автокомплит текста, и только. А теперь я наведу листинг конструктора:
MainEditor::MainEditor(QWidget *parent) :
    QsciScintilla(parent),
    lexerHTML(new QsciLexerHTML)
{
    //! To accept cyrillics
    setUtf8(true);

    setLexer(lexerHTML); // задаем лексер для HTML, PHP

    //...

    //! Autocompleting
    setAutoCompletionSource(QsciScintilla::AcsAll); // автокомплитим из всех источников
    setAutoCompletionCaseSensitivity(true); // конечно чувствительны к регистру
    setAutoCompletionReplaceWord(true); // удаляем слово которое дополняем (пишем заново)
    setAutoCompletionUseSingle(AcusExplicit); // исли в списке один элемент, то сразу дополняем
    setAutoCompletionThreshold(1); // автокомплит после 1го введеного символа

    //...
}


Это обеспечивает нам автокомплит HTML и PHP. Хорошо, да? Все действительно так просто. Но не интересно. Вот если бы можно было настроить автокомплит для своего лексера… А впрочем это не сложно:
MyLexer::MyLexer(QObject *parent) :
    QsciLexerCustom(parent)
{
    //...

    // Настраиваем автокомплит
    QsciAPIs *api = new QsciAPIs(this); // задаем значения по умолчанию
    foreach(const QString &word, listWithKeywords) { // проходимся по списку слов
        api->add(word); // добавляем в список
    }
    api->prepare(); // подготавливаем
    setAPIs(api);
}


А тут, я бы хотел приостанится. Тут мы создаем объект API от текущего API и дополняем его словами из нашего списка. Код списка я не привожу. Потом мы просто задаем новый API.

На практике, это все надо очень сильно дополнять, например анализировать код и дополнять его по мере написания. К примеру дополняя новыми переменными. Т.е. дополнять UserList переменными из AST'а (Abstract Syntax Tree). Но это только на практике).

Вот как выглядит редактор моей IDE:



И кстати, вот ее репозиторий.

На этом я заканчиваю цикл статей о QScintilla. Заранее приношу извинения, если статья получилась слабая. Просто это все что я хотел, но не успел рассказать.

Спасибо за внимание.
Tags:
Hubs:
Total votes 12: ↑9 and ↓3+6
Comments0

Articles