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

в 7:15, , рубрики: linux, qscintilla, qt, Qt Software, Ubuntu, Программирование, метки: , , ,

Добрый день!

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

Это опять я, со своей новой статьей. Сегодня я расскажу вам, как работать с 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: все глубже и глубже

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

На этом я заканчиваю цикл статей о QScintilla.

Спасибо за внимание.

Автор: namespace


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js