implement automatic completion popup and reformat on return

This commit is contained in:
Axel Kohlmeyer
2023-09-01 07:27:52 -04:00
parent 65866156dd
commit b2ba1bbe70
5 changed files with 75 additions and 5 deletions

View File

@ -3,6 +3,9 @@ LAMMPS-GUI TODO list:
# Short term goals
- add "syntax check" with enabled "-skiprun" flag
- implement "static" completion for fix/compute/styles/region etc...
- implement "dynamic" completion for variable names, group names, molecule names, compute/dump/fix/region/group IDs
- implement indenting regions for (nested) loops?
# Long term ideas
- rewrite entire application to build the App and its layout manually

View File

@ -290,9 +290,10 @@ void CodeEditor::setCommandList(const QStringList &words)
void CodeEditor::keyPressEvent(QKeyEvent *event)
{
const auto key = event->key();
if (command_completer && command_completer->popup()->isVisible()) {
// The following keys are forwarded by the completer to the widget
switch (event->key()) {
switch (key) {
case Qt::Key_Enter:
case Qt::Key_Return:
case Qt::Key_Escape:
@ -304,15 +305,47 @@ void CodeEditor::keyPressEvent(QKeyEvent *event)
break;
}
}
if (event->key() == Qt::Key_Tab) {
// reformat current line and consume key event
if (key == Qt::Key_Tab) {
reformatCurrentLine();
return;
}
if (event->key() == Qt::Key_Backtab) {
// run command completion and consume key event
if (key == Qt::Key_Backtab) {
runCompletion();
return;
}
// automatically reformat when hitting the return or enter key
if (reformat_on_return && (key == Qt::Key_Return) || (key == Qt::Key_Enter)) {
reformatCurrentLine();
}
// pass key event on to parent class
QPlainTextEdit::keyPressEvent(event);
// pop up completion automatically after 3 characters
if (automatic_completion) {
auto cursor = textCursor();
auto line = cursor.block().text().trimmed();
if (!line.isEmpty()) {
auto words = split_line(line.toStdString());
cursor.select(QTextCursor::WordUnderCursor);
auto word = cursor.selectedText().trimmed();
if (command_completer) {
if (words[0] == word.toStdString()) {
if (word.length() > 2)
runCompletion();
else if (command_completer->popup()->isVisible())
command_completer->popup()->hide();
} else {
if (command_completer->popup()->isVisible()) command_completer->popup()->hide();
}
}
}
}
}
void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */)
@ -475,7 +508,12 @@ void CodeEditor::runCompletion()
command_completer->setCompletionPrefix(words[0].c_str());
auto popup = command_completer->popup();
QRect cr = cursorRect();
// if the command is already a complete command, remove existing popup
if (words[0] == command_completer->currentCompletion().toStdString()) {
if (popup->isVisible()) popup->hide();
return;
}
QRect cr = cursorRect();
cr.setWidth(popup->sizeHintForColumn(0) +
popup->verticalScrollBar()->sizeHint().width());
popup->setAlternatingRowColors(true);

View File

@ -33,6 +33,8 @@ public:
void setFont(const QFont &newfont);
void setCursor(int block);
void setHighlight(int block, bool error);
void setReformatOnReturn(bool flag) { reformat_on_return = flag; }
void setAutoComplete(bool flag) { automatic_completion = flag; }
QString reformatLine(const QString &line);
void setCommandList(const QStringList &words);
@ -61,6 +63,8 @@ private:
QShortcut *help_action;
QCompleter *command_completer;
int highlight;
bool reformat_on_return;
bool automatic_completion;
QMap<QString, QString> cmd_map;
QMap<QString, QString> fix_map;

View File

@ -317,6 +317,10 @@ LammpsGui::LammpsGui(QWidget *parent, const char *filename) :
}
command_list.sort();
ui->textEdit->setCommandList(command_list);
settings.beginGroup("reformat");
ui->textEdit->setReformatOnReturn(settings.value("return", true).toBool());
ui->textEdit->setAutoComplete(settings.value("automatic", true).toBool());
settings.endGroup();
}
LammpsGui::~LammpsGui()
@ -1256,6 +1260,10 @@ void LammpsGui::preferences()
lammpsstatus->hide();
}
if (imagewindow) imagewindow->createImage();
settings.beginGroup("reformat");
ui->textEdit->setReformatOnReturn(settings.value("return", true).toBool());
ui->textEdit->setAutoComplete(settings.value("automatic", true).toBool());
settings.endGroup();
}
}

View File

@ -178,7 +178,7 @@ void Preferences::accept()
execl(path, arg0, (char *)NULL);
}
// reformattting settings
// reformatting settings
settings->beginGroup("reformat");
auto spin = tabWidget->findChild<QSpinBox *>("cmdval");
@ -189,6 +189,10 @@ void Preferences::accept()
if (spin) settings->setValue("id", spin->value());
spin = tabWidget->findChild<QSpinBox *>("nameval");
if (spin) settings->setValue("name", spin->value());
box = tabWidget->findChild<QCheckBox *>("retval");
if (box) settings->setValue("return", box->isChecked());
box = tabWidget->findChild<QCheckBox *>("autoval");
if (box) settings->setValue("automatic", box->isChecked());
settings->endGroup();
QDialog::accept();
@ -508,10 +512,14 @@ EditorTab::EditorTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s
auto *typelbl = new QLabel("Type width:");
auto *idlbl = new QLabel("ID width:");
auto *namelbl = new QLabel("Name width:");
auto *retlbl = new QLabel("Reformat with 'Return':");
auto *autolbl = new QLabel("Automatic completion:");
auto *cmdval = new QSpinBox;
auto *typeval = new QSpinBox;
auto *idval = new QSpinBox;
auto *nameval = new QSpinBox;
auto *retval = new QCheckBox;
auto *autoval = new QCheckBox;
cmdval->setRange(1, 32);
cmdval->setValue(settings->value("command", "16").toInt());
cmdval->setObjectName("cmdval");
@ -524,6 +532,11 @@ EditorTab::EditorTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s
nameval->setRange(1, 32);
nameval->setValue(settings->value("name", "8").toInt());
nameval->setObjectName("nameval");
retval->setCheckState(settings->value("return", true).toBool() ? Qt::Checked : Qt::Unchecked);
retval->setObjectName("retval");
autoval->setCheckState(settings->value("automatic", true).toBool() ? Qt::Checked
: Qt::Unchecked);
autoval->setObjectName("autoval");
settings->endGroup();
int i = 0;
@ -536,6 +549,10 @@ EditorTab::EditorTab(QSettings *_settings, QWidget *parent) : QWidget(parent), s
grid->addWidget(idval, i++, 1, Qt::AlignTop);
grid->addWidget(namelbl, i, 0, Qt::AlignTop);
grid->addWidget(nameval, i++, 1, Qt::AlignTop);
grid->addWidget(retlbl, i, 0, Qt::AlignTop);
grid->addWidget(retval, i++, 1, Qt::AlignVCenter);
grid->addWidget(autolbl, i, 0, Qt::AlignTop);
grid->addWidget(autoval, i++, 1, Qt::AlignVCenter);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 0);
grid->addItem(new QSpacerItem(100, 100, QSizePolicy::Minimum, QSizePolicy::Expanding), i, 1);