- implement: user code snippet / template

- implement: auto generate javadoc-style docstring for functions
 - enhancement: use up/down key to navigate function parameter tooltip
 - enhancement: press esc to close function parameter tooltip
This commit is contained in:
royqh1979@gmail.com 2021-10-02 13:29:45 +08:00
parent ae9c90236f
commit 237e86cea0
7 changed files with 150 additions and 65 deletions

View File

@ -1,4 +1,4 @@
Version 0.2.2 Version 0.3.0
- enhancement: support C++ using type alias; - enhancement: support C++ using type alias;
- fix: when press shift, completion popu window will hide - fix: when press shift, completion popu window will hide
- enhancement: options in debugger setting widget, to skip system/project/custom header&project files when step into - enhancement: options in debugger setting widget, to skip system/project/custom header&project files when step into
@ -16,6 +16,10 @@ Version 0.2.2
- implement: search in project - implement: search in project
- enhancement: view memory when debugging - enhancement: view memory when debugging
- implement: symbol usage count - implement: symbol usage count
- implement: user code snippet / template
- implement: auto generate javadoc-style docstring for functions
- enhancement: use up/down key to navigate function parameter tooltip
- enhancement: press esc to close function parameter tooltip
Version 0.2.1 Version 0.2.1
- fix: crash when load last opens - fix: crash when load last opens

View File

@ -510,52 +510,107 @@ void Editor::keyPressEvent(QKeyEvent *event)
setSelText(""); setSelText("");
} }
handled = true; handled = true;
QStringList params;
QStringList insertString; QStringList insertString;
insertString.append(""); insertString.append("");
bool isVoid; PStatement function = mParser->findFunctionAt(mFilename,caretY()+1);
QString funcName = mParser->FindFunctionDoc(mFilename, if (function) {
caretY()+1, QStringList params;
params,isVoid); QString funcName = function->command;
if funcName <> '' then begin bool isVoid = (function->type == "void");
insertString.Add(' * @brief '+USER_CODE_IN_INSERT_POS); foreach (const PStatement& child, function->children) {
insertString.Add(' * '); if (child->kind == StatementKind::skParameter)
for i:=0 to params.Count-1 do begin params.append(child->command);
insertString.Add(' * @param '+params[i]+' '+USER_CODE_IN_INSERT_POS); }
end; insertString.append(QString(" * @brief ")+USER_CODE_IN_INSERT_POS);
if not isVoid then begin insertString.append(" * ");
insertString.Add(' * '); foreach (const QString& param, params) {
insertString.Add(' * @return '+USER_CODE_IN_INSERT_POS); insertString.append(QString(" * @param %1 %2")
end; .arg(param, USER_CODE_IN_INSERT_POS));
insertString.Add(' **/'); }
end else begin if (!isVoid) {
insertString.Add(' * '+USER_CODE_IN_INSERT_POS); insertString.append(" * ");
insertString.Add(' **/'); insertString.append(QString(" * @return ")+USER_CODE_IN_INSERT_POS);
end; }
InsertUserCodeIn(insertString.Text); insertString.append(" **/");
} else {
end else if fText.Highlighter.GetIsLastLineCommentNotFinish(fText.Lines.Ranges[fText.CaretY-2]) then insertString.append(QString(" * ")+USER_CODE_IN_INSERT_POS);
s:=trimLeft(fText.LineText); insertString.append(" **/");
if StartsStr('* ',s) then begin }
Key:=0; insertCodeSnippet(LinesToText(insertString));
s:=#13#10+'* '; } else if (highlighter()
self.insertString(s,false); && caretY()>=2
p:=fText.CaretXY; && highlighter()->isLastLineCommentNotFinished(
inc(p.Line); lines()->ranges(caretY()-2).state)) {
p.Char := length(fText.Lines[p.Line-1])+1; s=TrimLeft(lineText());
fText.CaretXY := p; if (s.startsWith("* ")) {
end; handled = true;
end; s+=lineBreak()+"* ";
end; insertString(s,false);
BufferCoord p = caretXY();
p.Line++;
p.Char = lines()->getString(p.Line-1).length()+1;
setCaretXY(p);
}
}
}
return;
case Qt::Key_Escape: // Update function tip
mLastIdCharPressed = 0;
if (mTabStopBegin>=0) {
mTabStopBegin = -1;
invalidateLine(caretY());
clearUserCodeInTabStops();
}
pMainWindow->functionTip()->hide();
return;
case Qt::Key_Tab:
if (mUserCodeInTabStops.count()>0) {
handled = true;
int oldLine = caretY();
popUserCodeInTabStops();
if (oldLine!=caretY()) {
invalidateLine(oldLine);
}
invalidateLine(caretY());
} else {
if (mTabStopBegin >= 0) {
handled = true;
mTabStopBegin = -1;
invalidateLine(caretY());
}
}
return;
case Qt::Key_Up:
if (pMainWindow->functionTip()->isVisible()) {
handled = true;
pMainWindow->functionTip()->previousTip();
} else {
mLastIdCharPressed = 0;
clearUserCodeInTabStops();
}
return;
case Qt::Key_Down:
if (pMainWindow->functionTip()->isVisible()) {
handled = true;
pMainWindow->functionTip()->nextTip();
} else {
mLastIdCharPressed = 0;
clearUserCodeInTabStops();
}
return;
case Qt::Key_Delete: case Qt::Key_Delete:
// remove completed character // remove completed character
mLastIdCharPressed = 0; mLastIdCharPressed = 0;
undoSymbolCompletion(caretX()); if (!selAvail()) {
undoSymbolCompletion(caretX());
}
return; return;
case Qt::Key_Backspace: case Qt::Key_Backspace:
// remove completed character // remove completed character
mLastIdCharPressed = 0; mLastIdCharPressed = 0;
undoSymbolCompletion(caretX()-1); if (!selAvail()) {
undoSymbolCompletion(caretX()-1);
}
return; return;
} }
@ -1170,19 +1225,31 @@ void Editor::onStatusChanged(SynStatusChanges changes)
if (changes.testFlag(SynStatusChange::scCaretX) if (changes.testFlag(SynStatusChange::scCaretX)
|| changes.testFlag(SynStatusChange::scCaretY)) { || changes.testFlag(SynStatusChange::scCaretY)) {
if (mTabStopBegin >=0 && mTabStopY==caretY()) { if (mTabStopBegin >=0) {
if (lineText().startsWith(mLineBeforeTabStop) if (mTabStopY==caretY()) {
&& lineText().endsWith(mLineAfterTabStop)) if (mLineAfterTabStop.isEmpty()) {
mTabStopBegin = mLineBeforeTabStop.length(); if (lineText().startsWith(mLineBeforeTabStop))
if (mLineAfterTabStop.isEmpty()) mTabStopBegin = mLineBeforeTabStop.length()+1;
mTabStopEnd = lineText().length()+1; mTabStopEnd = lineText().length()+1;
else } else {
mTabStopEnd = lineText().length() if (lineText().startsWith(mLineBeforeTabStop)
- mLineAfterTabStop.length(); && lineText().endsWith(mLineAfterTabStop))
mXOffsetSince = mTabStopEnd - caretX(); mTabStopBegin = mLineBeforeTabStop.length();
if (caretX() < mTabStopBegin || mTabStopEnd = lineText().length()
caretX() > (mTabStopEnd+1)) - mLineAfterTabStop.length();
mTabStopBegin = -1; }
mXOffsetSince = mTabStopEnd - caretX();
if (caretX() < mTabStopBegin ||
caretX() > (mTabStopEnd+1)) {
mTabStopBegin = -1;
}
} else {
if (mTabStopBegin>=0) {
invalidateLine(mTabStopY);
mTabStopBegin = -1;
clearUserCodeInTabStops();
}
}
} }
} }
@ -1804,10 +1871,10 @@ void Editor::insertCodeSnippet(const QString &code)
leftSpaces(lineText()),true).length(); leftSpaces(lineText()),true).length();
QStringList newSl; QStringList newSl;
for (int i=0;i<sl.count();i++) { for (int i=0;i<sl.count();i++) {
int lastPos = 0; int lastPos = -1;
QString s = sl[i]; QString s = sl[i];
if (i>0) if (i>0)
lastPos = -spaceCount; lastPos = -spaceCount-1;
while (true) { while (true) {
int insertPos = s.indexOf(USER_CODE_IN_INSERT_POS); int insertPos = s.indexOf(USER_CODE_IN_INSERT_POS);
if (insertPos < 0) // no %INSERT% macro in this line now if (insertPos < 0) // no %INSERT% macro in this line now
@ -1822,7 +1889,9 @@ void Editor::insertCodeSnippet(const QString &code)
lastI = i; lastI = i;
mUserCodeInTabStops.append(p); mUserCodeInTabStops.append(p);
} }
lastPos = 0; lastPos = -1;
if (i>0)
lastPos = -spaceCount-1;
while (true) { while (true) {
int insertPos = s.indexOf(USER_CODE_IN_REPL_POS_BEGIN); int insertPos = s.indexOf(USER_CODE_IN_REPL_POS_BEGIN);
if (insertPos < 0) // no %INSERT% macro in this line now if (insertPos < 0) // no %INSERT% macro in this line now
@ -1832,7 +1901,6 @@ void Editor::insertCodeSnippet(const QString &code)
insertPos--; insertPos--;
p->x = insertPos - lastPos; p->x = insertPos - lastPos;
int insertEndPos = insertPos + int insertEndPos = insertPos +
s.mid(insertPos).indexOf(USER_CODE_IN_REPL_POS_END); s.mid(insertPos).indexOf(USER_CODE_IN_REPL_POS_END);
if (insertEndPos < insertPos) { if (insertEndPos < insertPos) {
@ -2067,8 +2135,8 @@ void Editor::completionInsert(bool appendFunc)
// delete the part of the word that's already been typed ... // delete the part of the word that's already been typed ...
BufferCoord p = wordEnd(); BufferCoord p = wordEnd();
setBlockBegin(wordStart()); BufferCoord pStart = wordStart();
setBlockEnd(p); setCaretAndSelection(pStart,pStart,p);
// if we are inserting a function, // if we are inserting a function,
if (appendFunc) { if (appendFunc) {
@ -2086,6 +2154,7 @@ void Editor::completionInsert(bool appendFunc)
// ... by replacing the selection // ... by replacing the selection
if (statement->kind == StatementKind::skUserCodeSnippet) { // it's a user code template if (statement->kind == StatementKind::skUserCodeSnippet) { // it's a user code template
// insertUserCodeIn(Statement->value); // insertUserCodeIn(Statement->value);
//first move caret to the begin of the word to be replaced
insertCodeSnippet(statement->value); insertCodeSnippet(statement->value);
} else { } else {
if ( if (
@ -2620,20 +2689,21 @@ void Editor::popUserCodeInTabStops()
newCursorPos.Char = mTabStopEnd + p->x; newCursorPos.Char = mTabStopEnd + p->x;
tabStopEnd = mTabStopEnd + p->endX; tabStopEnd = mTabStopEnd + p->endX;
} else { } else {
newCursorPos.Char = p->x; newCursorPos.Char = p->x+1;
tabStopEnd = p->endX; tabStopEnd = p->endX+1;
} }
newCursorPos.Line = caretY() + p->y; mTabStopY = caretY() + p->y;
newCursorPos.Line = mTabStopY;
setCaretXY(newCursorPos); setCaretXY(newCursorPos);
mTabStopY = caretY();
setBlockBegin(newCursorPos); setBlockBegin(newCursorPos);
newCursorPos.Char = tabStopEnd; newCursorPos.Char = tabStopEnd;
setBlockEnd(newCursorPos); setBlockEnd(newCursorPos);
mTabStopBegin= caretX(); mTabStopBegin= caretX();
mTabStopEnd = tabStopEnd; mTabStopEnd = tabStopEnd;
mLineBeforeTabStop = lineText().mid(0, mTabStopBegin) ; mLineBeforeTabStop = lineText().mid(0, mTabStopBegin) ;
mLineAfterTabStop = lineText().mid(mTabStopEnd+1) ; mLineAfterTabStop = lineText().mid(mTabStopEnd) ;
mXOffsetSince=0; mXOffsetSince=0;
mUserCodeInTabStops.pop_front(); mUserCodeInTabStops.pop_front();
} }

View File

@ -214,7 +214,6 @@ private:
void clearUserCodeInTabStops(); void clearUserCodeInTabStops();
void popUserCodeInTabStops(); void popUserCodeInTabStops();
private: private:
QByteArray mEncodingOption; // the encoding type set by the user QByteArray mEncodingOption; // the encoding type set by the user
QByteArray mFileEncoding; // the real encoding of the file (auto detected) QByteArray mFileEncoding; // the real encoding of the file (auto detected)

View File

@ -83,8 +83,8 @@ MainWindow::MainWindow(QWidget *parent)
ui->tblStackTrace->setModel(mDebugger->backtraceModel()); ui->tblStackTrace->setModel(mDebugger->backtraceModel());
ui->watchView->setModel(mDebugger->watchModel()); ui->watchView->setModel(mDebugger->watchModel());
ui->actionIndent->setShortcut(Qt::Key_Tab); // ui->actionIndent->setShortcut(Qt::Key_Tab);
ui->actionUnIndent->setShortcut(Qt::Key_Tab | Qt::ShiftModifier); // ui->actionUnIndent->setShortcut(Qt::Key_Tab | Qt::ShiftModifier);
ui->tableIssues->setErrorColor(QColor("Red")); ui->tableIssues->setErrorColor(QColor("Red"));
ui->tableIssues->setWarningColor(QColor("Orange")); ui->tableIssues->setWarningColor(QColor("Orange"));

View File

@ -5395,6 +5395,16 @@ void SynEdit::timerEvent(QTimerEvent *event)
bool SynEdit::event(QEvent *event) bool SynEdit::event(QEvent *event)
{ {
switch(event->type()) { switch(event->type()) {
case QEvent::KeyPress:{
QKeyEvent* keyEvent = static_cast<QKeyEvent *>(event);
if(keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab)
{
// process tab key presse event
keyPressEvent(keyEvent);
return true;
}
}
break;
case QEvent::FontChange: case QEvent::FontChange:
synFontChanged(); synFontChanged();
break; break;

View File

@ -807,4 +807,5 @@ QString parseMacros(const QString &s)
result.replace("<SOURCEPATH>", ""); result.replace("<SOURCEPATH>", "");
result.replace("<WORDXY>", ""); result.replace("<WORDXY>", "");
} }
return result;
} }

View File

@ -474,6 +474,7 @@ void CodeCompletionPopup::getCompletionFor(const QString &fileName, const QStrin
foreach (const PCodeSnippet& codeIn,mCodeSnippets) { foreach (const PCodeSnippet& codeIn,mCodeSnippets) {
PStatement statement = std::make_shared<Statement>(); PStatement statement = std::make_shared<Statement>();
statement->command = codeIn->prefix; statement->command = codeIn->prefix;
statement->value = codeIn->code;
statement->kind = StatementKind::skUserCodeSnippet; statement->kind = StatementKind::skUserCodeSnippet;
statement->fullName = codeIn->prefix; statement->fullName = codeIn->prefix;
statement->usageCount = 0; statement->usageCount = 0;