work save

This commit is contained in:
royqh1979@gmail.com 2021-08-26 17:48:23 +08:00
parent bf4d12b89f
commit f8fae59dcc
8 changed files with 262 additions and 46 deletions

View File

@ -1422,6 +1422,131 @@ bool Editor::testInFunc(int x, int y)
return result;
}
void Editor::completionInsert(bool appendFunc)
{
PStatement statement = mCompletionPopup->selectedStatement();
if (!statement)
return;
// if devCodeCompletion.RecordUsage and (Statement^._Kind <> skUserCodeIn) then begin
// idx:=Utils.FastIndexOf(dmMain.SymbolUsage,Statement^._FullName);
// if idx = -1 then begin
// usageCount:=1;
// dmMain.SymbolUsage.AddObject(Statement^._FullName, pointer(1))
// end else begin
// usageCount := 1 + integer(dmMain.SymbolUsage.Objects[idx]);
// dmMain.SymbolUsage.Objects[idx] := pointer( usageCount );
// end;
// Statement^._UsageCount := usageCount;
// end;
QString funcAddOn = "";
// delete the part of the word that's already been typed ...
BufferCoord p = wordEnd();
setBlockBegin(wordStart());
setBlockEnd(p);
// if we are inserting a function,
if (appendFunc) {
if (statement->kind == StatementKind::skFunction
|| statement->kind == StatementKind::skConstructor
|| statement->kind == StatementKind::skDestructor) {
if ((p.Char >= lineText().length()) // it's the last char on line
|| (lineText()[p.Char] != '(')) { // it don't have '(' after it
if (statement->fullName!="std::endl")
funcAddOn = "()";
}
}
}
// ... by replacing the selection
if (statement->kind == StatementKind::skUserCodeIn) { // it's a user code template
//insertUserCodeIn(Statement->value);
} else {
if (
(statement->kind == StatementKind::skKeyword
|| statement->kind == StatementKind::skPreprocessor)
&& (statement->command.startsWith('#')
|| statement->command.startsWith('@'))
) {
setSelText(statement->command.mid(1));
} else
setSelText(statement->command + funcAddOn);
if (!funcAddOn.isEmpty())
mLastIdCharPressed = 0;
// Move caret inside the ()'s, only when the user has something to do there...
if (!funcAddOn.isEmpty()
&& (statement->args != "()")
&& (statement->args != "(void)")) {
setCaretX(caretX() - funcAddOn.length()+1);
//todo: function hint
// immediately activate function hint
// if devEditor.ShowFunctionTip and Assigned(fText.Highlighter) then begin
// fText.SetFocus;
// fFunctionTip.Parser := fParser;
// fFunctionTip.FileName := fFileName;
// fFunctionTip.Show;
// end;
}
}
mCompletionPopup->hide();
}
bool Editor::onCompletionKeyPressed(QKeyEvent *event)
{
bool processed = false;
if (!mCompletionPopup->isEnabled())
return false;
QString phrase;
BufferCoord pBeginPos,pEndPos;
switch (event->key()) {
case Qt::Key_Backspace:
ExecuteCommand(
SynEditorCommand::ecDeleteLastChar,
QChar(), nullptr); // Simulate backspace in editor
phrase = getWordAtPosition(caretXY(),
pBeginPos,pEndPos,
WordPurpose::wpCompletion);
mLastIdCharPressed = phrase.length();
mCompletionPopup->search(phrase, false);
return true;
case Qt::Key_Escape:
mCompletionPopup->hide();
return true;
case Qt::Key_Return:
case Qt::Key_Tab:
//CompletionInsert(devCodeCompletion.AppendFunc);
completionInsert(false);
return true;
default:
if (event->text().isEmpty()) {
//stop completion
mCompletionPopup->hide();
keyPressEvent(event);
return true;
}
}
QChar ch = event->text().front();
if (isIdentChar(ch)) {
setSelText(ch);
phrase = phrase = getWordAtPosition(caretXY(),
pBeginPos,pEndPos,
WordPurpose::wpCompletion);
mLastIdCharPressed = phrase.length();
mCompletionPopup->search(phrase, false);
return true;
} else {
//stop completion
mCompletionPopup->hide();
keyPressEvent(event);
return true;
}
return processed;
}
QString Editor::getWordAtPosition(const BufferCoord &p, BufferCoord &pWordBegin, BufferCoord &pWordEnd, WordPurpose purpose)
{
QString result = "";

View File

@ -167,6 +167,10 @@ private:
bool testInFunc(int x,int y);
void completionInsert(bool appendFunc=false);
bool onCompletionKeyPressed(QKeyEvent* event);
private:
static int newfileCount;
QByteArray mEncodingOption; // the encoding type set by the user

View File

@ -2104,7 +2104,7 @@ void CppParser::handleOtherTypedefs()
while ((mIndex< mTokenizer.tokenCount()) && !mTokenizer[mIndex]->text.startsWith(';'))
mIndex++;
//skip ;
if ((mIndex< mTokenizer.tokenCount()) && !mTokenizer[mIndex]->text.startsWith(';'))
if ((mIndex< mTokenizer.tokenCount()) && mTokenizer[mIndex]->text.startsWith(';'))
mIndex++;
return;
}
@ -2186,7 +2186,7 @@ void CppParser::handleOtherTypedefs()
newType += mTokenizer[mIndex]->text + ' ';
mIndex++;
}
if ((mIndex>= mTokenizer.tokenCount()) || (mTokenizer[mIndex]->text[1] == ';'))
if ((mIndex>= mTokenizer.tokenCount()) || (mTokenizer[mIndex]->text[0] == ';'))
break;
else if (mTokenizer[mIndex]->text.front() == ',')
mIndex++;
@ -2528,14 +2528,14 @@ void CppParser::handleStructs(bool isTypedef)
if (!(mTokenizer[i]->text.front() == '{'
|| mTokenizer[i]->text.front() == ','
|| mTokenizer[i]->text.front() == ';')) {
if ((mTokenizer[i]->text.front() == '_')
&& (mTokenizer[i]->text.back() == '_')) {
// skip possible gcc attributes
// start and end with 2 underscores (i.e. __attribute__)
// so, to avoid slow checks of strings, we just check the first and last letter of the token
// if both are underscores, we split
break;
} else {
// if ((mTokenizer[i]->text.front() == '_')
// && (mTokenizer[i]->text.back() == '_')) {
// // skip possible gcc attributes
// // start and end with 2 underscores (i.e. __attribute__)
// // so, to avoid slow checks of strings, we just check the first and last letter of the token
// // if both are underscores, we split
// break;
// } else {
if (mTokenizer[i]->text.endsWith(']')) { // cut-off array brackets
int pos = mTokenizer[i]->text.indexOf('[');
command += mTokenizer[i]->text.mid(0,pos) + ' ';
@ -2546,7 +2546,7 @@ void CppParser::handleStructs(bool isTypedef)
} else {
command += mTokenizer[i]->text + ' ';
}
}
// }
} else {
command = command.trimmed();
if (!command.isEmpty() &&
@ -2873,9 +2873,9 @@ void CppParser::internalParse(const QString &fileName)
});
// Let the preprocessor augment the include records
// mPreprocessor.setIncludesList(mIncludesList);
// mPreprocessor.setScannedFileList(mScannedFiles);
// mPreprocessor.setIncludePaths(mIncludePaths);
// mPreprocessor.setProjectIncludePaths(mProjectIncludePaths);
// mPreprocessor.setScannedFileList(mScannedFiles);
mPreprocessor.setScanOptions(mParseGlobalHeaders, mParseLocalHeaders);
mPreprocessor.preprocess(fileName, buffer);
#ifdef QT_DEBUG

View File

@ -336,9 +336,10 @@ void CppPreprocessor::handleInclude(const QString &line)
if (fileName.isEmpty())
return;
mCurrentIncludes->includeFiles.insert(fileName,true);
//mCurrentIncludes->includeFiles.insert(fileName,true);
// And open a new entry
openInclude(fileName);
mCurrentIncludes->includeFiles.insert(fileName,true);
}
void CppPreprocessor::handlePreprocessor(const QString &value)
@ -396,7 +397,7 @@ QString CppPreprocessor::expandMacros(const QString &line, int depth)
}
word = "";
if (i< lenLine) {
newLine += ch;
newLine += line[i];
}
}
i++;
@ -410,7 +411,9 @@ QString CppPreprocessor::expandMacros(const QString &line, int depth)
void CppPreprocessor::expandMacro(const QString &line, QString &newLine, QString &word, int &i, int depth)
{
int lenLine = line.length();
if (word == "__attribute__") {
if (word.startsWith("__")
&& word.endsWith("__")) {
// if (word == "__attribute__") {
//skip gcc __attribute__
while ((i<lenLine) && (line[i] == ' ' || line[i]=='\t'))
i++;
@ -487,7 +490,7 @@ QString CppPreprocessor::removeGCCAttributes(const QString &line)
removeGCCAttribute(line,newLine,i,word);
}
word = "";
if (i<=lenLine) {
if (i<lenLine) {
newLine = newLine+line[i];
}
}
@ -500,28 +503,29 @@ QString CppPreprocessor::removeGCCAttributes(const QString &line)
void CppPreprocessor::removeGCCAttribute(const QString &line, QString &newLine, int &i, const QString &word)
{
int lenLine = line.length();
int level = 0;
if (word=="__attribute__") {
while ( (i<lenLine) && isSpaceChar(line[i]))
i++;
if ((i<lenLine) && (line[i]=='(')) {
level=0;
while (i<lenLine) {
switch(line[i].unicode()) {
case '(': level++;
break;
case ')': level--;
break;
}
i++;
if (level==0)
break;
}
}
} else {
newLine += word;
}
//no need it now
// int lenLine = line.length();
// int level = 0;
// if (word=="__attribute__") {
// while ( (i<lenLine) && isSpaceChar(line[i]))
// i++;
// if ((i<lenLine) && (line[i]=='(')) {
// level=0;
// while (i<lenLine) {
// switch(line[i].unicode()) {
// case '(': level++;
// break;
// case ')': level--;
// break;
// }
// i++;
// if (level==0)
// break;
// }
// }
// } else {
// newLine += word;
// }
}
PParsedFile CppPreprocessor::getInclude(int index)
@ -865,18 +869,20 @@ QStringList CppPreprocessor::removeComments(const QStringList &text)
s+=ch;
break;
case '/':
switch(currentType) {
case ContentType::Other:
if (currentType == ContentType::Other) {
if (pos+1<line.length() && line[pos+1]=='/') {
// line comment , skip all remainings of the current line
stopProcess = true;
break;
} else if (pos+1<line.length() && line[pos+1]=='*') {
/* ansi c comment */
pos++;
currentType = ContentType::AnsiCComment;
}
break;
}
}
s+=ch;
break;
case '\\':
switch (currentType) {
case ContentType::String:
@ -1032,7 +1038,7 @@ QString CppPreprocessor::expandDefines(QString line)
while (searchPos < line.length()) {
// We have found an identifier. It is not a number suffix. Try to expand it
if (isMacroIdentChar(line[searchPos]) && (
(searchPos == 1) || !isDigit(line[searchPos - 1]))) {
(searchPos == 0) || !isDigit(line[searchPos - 1]))) {
int head = searchPos;
int tail = searchPos;

View File

@ -5667,6 +5667,56 @@ void SynEdit::setSelLength(int Value)
}
}
BufferCoord SynEdit::wordStart()
{
return wordStart(caretXY());
}
BufferCoord SynEdit::wordStart(const BufferCoord &value)
{
int cx = value.Char-1;
int cy = value.Line;
// valid line?
if ((cy <1) || (cy > lines()->count()))
return value;
QString line = lines()->getString(cy - 1);
if (cx>=line.length()) {
cx=line.length()-1;
}
while (cx>=0 && cx<line.length()) {
if (line[cx]==' ' || line[cx]=='\t')
break;
cx--;
}
if (cx != value.Char-1) {
cx++;
}
return BufferCoord{cx+1,cy};
}
BufferCoord SynEdit::wordEnd()
{
return wordEnd(caretXY());
}
BufferCoord SynEdit::wordEnd(const BufferCoord &value)
{
int cx = value.Char-1;
int cy = value.Line;
// valid line?
if ((cy <1) || (cy > lines()->count()))
return value;
QString line = lines()->getString(cy - 1);
while (cx>=0 && cx<line.length()) {
if (line[cx]==' ' || line[cx]=='\t')
break;
cx++;
}
return BufferCoord{cx+1,cy};
}
BufferCoord SynEdit::blockBegin() const
{
if ((mBlockEnd.Line < mBlockBegin.Line)

View File

@ -215,6 +215,12 @@ public:
void uncollapseAroundLine(int line);
PSynEditFoldRange foldHidesLine(int line);
void setSelText(const QString& Value);
void setSelLength(int Value);
BufferCoord wordStart();
BufferCoord wordStart(const BufferCoord& value);
BufferCoord wordEnd();
BufferCoord wordEnd(const BufferCoord& value);
int searchReplace(const QString& sSearch, const QString& sReplace, SynSearchOptions options,
PSynSearchBase searchEngine, SynSearchMathedProc matchedCallback = nullptr);
@ -261,6 +267,8 @@ public:
BufferCoord blockBegin() const;
BufferCoord blockEnd() const;
void setBlockBegin(BufferCoord value);
void setBlockEnd(BufferCoord Value);
SynSelectionMode activeSelectionMode() const;
void setActiveSelectionMode(const SynSelectionMode &Value);
@ -491,10 +499,6 @@ private:
void doUncomment();
void doToggleComment();
private:
void setBlockBegin(BufferCoord value);
void setBlockEnd(BufferCoord Value);
void setSelLength(int Value);
private slots:
void bookMarkOptionsChanged();

View File

@ -105,6 +105,23 @@ bool CodeCompletionView::search(const QString &phrase, bool autoHideOnSingleResu
return false;
}
PStatement CodeCompletionView::selectedStatement()
{
if (isEnabled()) {
int index = mListView->currentIndex().row();
if (mListView->currentIndex().isValid()
&& (index<mCompletionStatementList.count()) ) {
return mCompletionStatementList[index];
} else {
if (!mCompletionStatementList.isEmpty())
return mCompletionStatementList.front();
else
return PStatement();
}
} else
return PStatement();
}
void CodeCompletionView::addChildren(PStatement scopeStatement, const QString &fileName, int line)
{
if (scopeStatement && !isIncluded(scopeStatement->fileName)
@ -669,6 +686,11 @@ bool CodeCompletionView::isIncluded(const QString &fileName)
return mIncludedFiles.contains(fileName);
}
void CodeCompletionView::showEvent(QShowEvent *)
{
mListView->setFocus();
}
const PStatement &CodeCompletionView::currentStatement() const
{
return mCurrentStatement;
@ -819,6 +841,9 @@ QVariant CodeCompletionListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (index.row()>=mStatements->count())
return QVariant();
if (role == Qt::DisplayRole) {
PStatement statement = mStatements->at(index.row());
return statement->command;

View File

@ -46,6 +46,7 @@ public:
void prepareSearch(const QString& phrase, const QString& filename, int line);
bool search(const QString& phrase, bool autoHideOnSingleResult);
PStatement selectedStatement();
const PCppParser &parser() const;
void setParser(const PCppParser &newParser);
@ -111,6 +112,7 @@ private:
// QWidget interface
protected:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
};