Добрый день!
Чуть не забыл. Первая и вторая статья цикла.
Это опять я, со своей новой статьей. Сегодня я расскажу вам, как работать с 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.
Спасибо за внимание.
Автор: namespace