work save
This commit is contained in:
parent
bf4d12b89f
commit
f8fae59dcc
|
@ -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 = "";
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue