Added auto-brace matching for JavaScript.

This commit is contained in:
Roberto Raggi
2010-01-12 14:42:45 +01:00
parent ba55644de3
commit 58f8f7b725
2 changed files with 128 additions and 1 deletions
+122 -1
View File
@@ -33,6 +33,7 @@
#include "qtscripteditorplugin.h"
#include <qscripthighlighter/qscriptindenter.h>
#include <qscripthighlighter/qscriptincrementalscanner.h>
#include "parser/javascriptengine_p.h"
#include "parser/javascriptparser_p.h"
@@ -64,7 +65,7 @@ enum {
};
using namespace JavaScript::AST;
using namespace SharedTools;
namespace QtScriptEditor {
namespace Internal {
@@ -401,5 +402,125 @@ void ScriptEditor::unCommentSelection()
Utils::unCommentSelection(this);
}
bool ScriptEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const
{
QChar ch;
if (! textToInsert.isEmpty())
ch = textToInsert.at(0);
const QString blockText = cursor.block().text();
const int blockState = cursor.block().userState() & 0xFF;
QScriptIncrementalScanner tokenize;
const QList<QScriptIncrementalScanner::Token> tokens = tokenize(blockText, blockState);
const int pos = cursor.columnNumber();
int tokenIndex = tokens.size() - 1;
for (; tokenIndex != -1; --tokenIndex) {
const QScriptIncrementalScanner::Token &token = tokens.at(tokenIndex);
if (pos >= token.begin() && pos <= token.end())
break;
}
if (tokenIndex != -1) {
const QScriptIncrementalScanner::Token &token = tokens.at(tokenIndex);
switch (token.kind) {
case QScriptIncrementalScanner::Token::Comment:
return false;
case QScriptIncrementalScanner::Token::String: {
if (ch == blockText.at(token.begin())) {
if (token.end() - 1 == pos && blockText.at(token.end() - 2) != QLatin1Char('\\'))
break;
}
return false;
}
default:
break;
} // end of switch
}
switch (ch.unicode()) {
case '\'':
case '"':
case '(':
case '[':
case '{':
case ')':
case ']':
case '}':
case ';':
return true;
default:
if (ch.isNull())
return true;
} // end of switch
return false;
}
bool ScriptEditor::isInComment(const QTextCursor &) const
{
// ### implement me
return false;
}
QString ScriptEditor::insertMatchingBrace(const QTextCursor &tc, const QString &text, const QChar &, int *skippedChars) const
{
if (text.length() != 1)
return QString();
const QChar la = characterAt(tc.position());
const QChar ch = text.at(0);
switch (ch.unicode()) {
case '\'':
if (la != ch)
return QString(ch);
++*skippedChars;
break;
case '"':
if (la != ch)
return QString(ch);
++*skippedChars;
break;
case '(':
return QString(QLatin1Char(')'));
case '[':
return QString(QLatin1Char(']'));
case '{':
return QString(); // nothing to do.
case ')':
case ']':
case '}':
case ';':
if (la == ch)
++*skippedChars;
break;
default:
break;
} // end of switch
return QString();
}
QString ScriptEditor::insertParagraphSeparator(const QTextCursor &) const
{
return QLatin1String("}\n");
}
} // namespace Internal
} // namespace QtScriptEditor
@@ -113,6 +113,12 @@ protected:
TextEditor::BaseTextEditorEditable *createEditableInterface();
void createToolBar(ScriptEditorEditable *editable);
//// brace matching
virtual bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert = QString()) const;
virtual bool isInComment(const QTextCursor &cursor) const;
virtual QString insertMatchingBrace(const QTextCursor &tc, const QString &text, const QChar &la, int *skippedChars) const;
virtual QString insertParagraphSeparator(const QTextCursor &tc) const;
private:
virtual bool isElectricCharacter(const QChar &ch) const;
virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);