mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-30 17:24:54 +02:00
[NEW_FEATURE] Add new feature: auto-complete matched delimiters (in progress).
git-svn-id: svn://svn.tuxfamily.org/svnroot/notepadplus/repository/trunk@1107 f5eea248-9336-0410-98b8-ebc06183d4e3
This commit is contained in:
parent
01f3148e0e
commit
0b5687052e
@ -424,14 +424,20 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
case SCN_CHARADDED:
|
||||
{
|
||||
bool indentMaintain = NppParameters::getInstance()->getNppGUI()._maitainIndent;
|
||||
if (indentMaintain)
|
||||
MaintainIndentation(static_cast<TCHAR>(notification->ch));
|
||||
|
||||
AutoCompletion * autoC = isFromPrimary?&_autoCompleteMain:&_autoCompleteSub;
|
||||
|
||||
MatchedPairConf matchedPairConf;
|
||||
if (matchedPairConf.hasAnyPairsPair())
|
||||
autoC->insertMatchedChars(notification->ch, matchedPairConf);
|
||||
autoC->update(notification->ch);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3962,7 +3962,71 @@ void NppParameters::feedGUIParameters(TiXmlNode *node)
|
||||
if (funcParams && !lstrcmp(funcParams, TEXT("yes")))
|
||||
{
|
||||
_nppGUI._funcParams = true;
|
||||
}
|
||||
}
|
||||
else if (!lstrcmp(nm, TEXT("auto-insert")))
|
||||
{
|
||||
const TCHAR * optName = element->Attribute(TEXT("htmlXmlTag"));
|
||||
if (optName && !lstrcmp(optName, TEXT("yes")))
|
||||
{
|
||||
_nppGUI._matchedPairConf._doHtmlXmlTag = true;
|
||||
}
|
||||
|
||||
optName = element->Attribute(TEXT("parentheses"));
|
||||
if (optName && !lstrcmp(optName, TEXT("yes")))
|
||||
{
|
||||
_nppGUI._matchedPairConf._doParentheses = true;
|
||||
}
|
||||
|
||||
optName = element->Attribute(TEXT("brackets"));
|
||||
if (optName && !lstrcmp(optName, TEXT("yes")))
|
||||
{
|
||||
_nppGUI._matchedPairConf._doBrackets = true;
|
||||
}
|
||||
|
||||
optName = element->Attribute(TEXT("curlyBrackets"));
|
||||
if (optName && !lstrcmp(optName, TEXT("yes")))
|
||||
{
|
||||
_nppGUI._matchedPairConf._doCurlyBrackets = true;
|
||||
}
|
||||
|
||||
optName = element->Attribute(TEXT("quotes"));
|
||||
if (optName && !lstrcmp(optName, TEXT("yes")))
|
||||
{
|
||||
_nppGUI._matchedPairConf._doQuotes = true;
|
||||
}
|
||||
|
||||
optName = element->Attribute(TEXT("doubleQuotes"));
|
||||
if (optName && !lstrcmp(optName, TEXT("yes")))
|
||||
{
|
||||
_nppGUI._matchedPairConf._doDoubleQuotes = true;
|
||||
}
|
||||
|
||||
for (TiXmlNode *subChildNode = childNode->FirstChildElement(TEXT("UserDefinePair"));
|
||||
subChildNode;
|
||||
subChildNode = subChildNode->NextSibling(TEXT("UserDefinePair")) )
|
||||
{
|
||||
int open = -1;
|
||||
int openVal = 0;
|
||||
const TCHAR *openValStr = (subChildNode->ToElement())->Attribute(TEXT("open"), &openVal);
|
||||
if (openValStr && (openVal >= 0 && openVal <= 255))
|
||||
{
|
||||
open = openVal;
|
||||
}
|
||||
|
||||
int close = -1;
|
||||
int closeVal = 0;
|
||||
const TCHAR *closeValStr = (subChildNode->ToElement())->Attribute(TEXT("close"), &closeVal);
|
||||
if (closeValStr && (closeVal >= 0 && closeVal <= 255))
|
||||
{
|
||||
close = closeVal;
|
||||
}
|
||||
|
||||
if (open != -1 && close != -1)
|
||||
{
|
||||
_nppGUI._matchedPairConf._matchedPairs.push_back(pair<char, char>(char(open), char(close)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!lstrcmp(nm, TEXT("sessionExt")))
|
||||
{
|
||||
|
@ -675,6 +675,23 @@ private:
|
||||
unsigned long _day;
|
||||
};
|
||||
|
||||
struct MatchedPairConf {
|
||||
vector< pair<char, char> > _matchedPairs;
|
||||
bool _doHtmlXmlTag;
|
||||
bool _doParentheses;
|
||||
bool _doBrackets;
|
||||
bool _doCurlyBrackets;
|
||||
bool _doQuotes;
|
||||
bool _doDoubleQuotes;
|
||||
|
||||
MatchedPairConf(): _doHtmlXmlTag(false), _doParentheses(false), _doBrackets(false), _doCurlyBrackets(false),\
|
||||
_doQuotes(false), _doDoubleQuotes(false) {};
|
||||
|
||||
bool hasUserDefinedPairs(){ return _matchedPairs.size() != 0; };
|
||||
bool hasDefaultPairs() { return _doParentheses||_doBrackets||_doCurlyBrackets||_doQuotes||_doDoubleQuotes||_doHtmlXmlTag; };
|
||||
bool hasAnyPairsPair(){ return hasUserDefinedPairs() || hasDefaultPairs(); };
|
||||
};
|
||||
|
||||
struct NppGUI
|
||||
{
|
||||
NppGUI() : _toolBarStatus(TB_LARGE), _toolbarShow(true), _statusBarShow(true), _menuBarShow(true),\
|
||||
@ -758,6 +775,7 @@ struct NppGUI
|
||||
AutocStatus _autocStatus;
|
||||
size_t _autocFromLen;
|
||||
bool _funcParams;
|
||||
MatchedPairConf _matchedPairConf;
|
||||
|
||||
generic_string _definedSessionExt;
|
||||
|
||||
|
@ -162,6 +162,97 @@ bool AutoCompletion::showFunctionComplete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void AutoCompletion::getCloseTag(char *closeTag, size_t closeTagSize, size_t caretPos)
|
||||
{
|
||||
int flags = SCFIND_REGEXP | SCFIND_POSIX;
|
||||
_pEditView->execute(SCI_SETSEARCHFLAGS, flags);
|
||||
TCHAR tag2find[] = TEXT("<[^\\s>]*");
|
||||
int targetStart = _pEditView->searchInTarget(tag2find, lstrlen(tag2find), caretPos, 0);
|
||||
|
||||
if (targetStart == -1 || targetStart == -2)
|
||||
return;
|
||||
|
||||
int targetEnd = int(_pEditView->execute(SCI_GETTARGETEND));
|
||||
int foundTextLen = targetEnd - targetStart;
|
||||
if (foundTextLen < 2) // "<>" will be ignored
|
||||
return;
|
||||
|
||||
if (size_t(foundTextLen) > closeTagSize - 2) // buffer size is not large enough. -2 for '/' & '\0'
|
||||
return;
|
||||
|
||||
char tagHeader[3];
|
||||
_pEditView->getText(tagHeader, targetStart, targetStart+2);
|
||||
|
||||
if (tagHeader[1] == '\\') // "</toto>" will be ignored
|
||||
return;
|
||||
|
||||
closeTag[0] = '<';
|
||||
closeTag[1] = '\\';
|
||||
_pEditView->getText(closeTag + 2, targetStart + 1, targetEnd);
|
||||
closeTag[foundTextLen+1] = '>';
|
||||
closeTag[foundTextLen+2] = '\0';
|
||||
}
|
||||
|
||||
void AutoCompletion::insertMatchedChars(int character, const MatchedPairConf & matchedPairConf)
|
||||
{
|
||||
const vector< pair<char, char> > & matchedPairs = matchedPairConf._matchedPairs;
|
||||
int caretPos = _pEditView->execute(SCI_GETCURRENTPOS);
|
||||
char *matchedChars = NULL;
|
||||
|
||||
// User defined matched pairs should be checked firstly
|
||||
for (size_t i = 0, len = matchedPairs.size(); i < len; ++i)
|
||||
{
|
||||
if (int(matchedPairs[i].first) == character)
|
||||
{
|
||||
_pEditView->execute(SCI_INSERTTEXT, caretPos, (LPARAM)matchedPairs[i].second);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if there's no user defined matched pair found, continue to check notepad++'s one
|
||||
|
||||
const size_t closeTagLen = 256;
|
||||
char closeTag[closeTagLen];
|
||||
closeTag[0] = '\0';
|
||||
switch (character)
|
||||
{
|
||||
case int('('):
|
||||
if (matchedPairConf._doParentheses)
|
||||
matchedChars = ")";
|
||||
break;
|
||||
case int('['):
|
||||
if (matchedPairConf._doBrackets)
|
||||
matchedChars = "]";
|
||||
break;
|
||||
case int('{'):
|
||||
if (matchedPairConf._doCurlyBrackets)
|
||||
matchedChars = "}";
|
||||
break;
|
||||
case int('"'):
|
||||
if (matchedPairConf._doDoubleQuotes)
|
||||
matchedChars = "\"";
|
||||
break;
|
||||
case int('\''):
|
||||
if (matchedPairConf._doQuotes)
|
||||
matchedChars = "'";
|
||||
break;
|
||||
case int('>'):
|
||||
{
|
||||
if (matchedPairConf._doHtmlXmlTag)
|
||||
{
|
||||
getCloseTag(closeTag, closeTagLen, caretPos);
|
||||
if (closeTag[0] != '\0')
|
||||
matchedChars = closeTag;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (matchedChars)
|
||||
_pEditView->execute(SCI_INSERTTEXT, caretPos, (LPARAM)matchedChars);
|
||||
}
|
||||
|
||||
|
||||
void AutoCompletion::update(int character)
|
||||
{
|
||||
const NppGUI & nppGUI = NppParameters::getInstance()->getNppGUI();
|
||||
|
@ -63,8 +63,10 @@ public:
|
||||
//Parameter display from the list
|
||||
bool showFunctionComplete();
|
||||
|
||||
void insertMatchedChars(int character, const MatchedPairConf & matchedPairConf);
|
||||
void update(int character);
|
||||
void callTipClick(int direction);
|
||||
void getCloseTag(char *closeTag, size_t closeTagLen, size_t caretPos);
|
||||
|
||||
private:
|
||||
bool _funcCompletionActive;
|
||||
|
@ -1762,7 +1762,6 @@ void ScintillaEditView::getText(char *dest, int start, int end) const
|
||||
|
||||
void ScintillaEditView::getGenericText(TCHAR *dest, size_t destlen, int start, int end) const
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
char *destA = new char[end - start + 1];
|
||||
getText(destA, start, end);
|
||||
@ -1770,15 +1769,11 @@ void ScintillaEditView::getGenericText(TCHAR *dest, size_t destlen, int start, i
|
||||
const TCHAR *destW = wmc->char2wchar(destA, cp);
|
||||
_tcsncpy_s(dest, destlen, destW, _TRUNCATE);
|
||||
delete [] destA;
|
||||
#else
|
||||
getText(dest, start, end);
|
||||
#endif
|
||||
}
|
||||
|
||||
// "mstart" and "mend" are pointers to indexes in the read string,
|
||||
// which are converted to the corresponding indexes in the returned TCHAR string.
|
||||
|
||||
#ifdef UNICODE
|
||||
void ScintillaEditView::getGenericText(TCHAR *dest, size_t destlen, int start, int end, int *mstart, int *mend) const
|
||||
{
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
@ -1789,24 +1784,13 @@ void ScintillaEditView::getGenericText(TCHAR *dest, size_t destlen, int start, i
|
||||
_tcsncpy_s(dest, destlen, destW, _TRUNCATE);
|
||||
delete [] destA;
|
||||
}
|
||||
#else
|
||||
void ScintillaEditView::getGenericText(TCHAR *dest, int start, int end, int *, int *) const
|
||||
{
|
||||
getText(dest, start, end);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void ScintillaEditView::insertGenericTextFrom(int position, const TCHAR *text2insert) const
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *text2insertA = wmc->wchar2char(text2insert, cp);
|
||||
execute(SCI_INSERTTEXT, position, (WPARAM)text2insertA);
|
||||
#else
|
||||
execute(SCI_INSERTTEXT, position, (WPARAM)text2insert);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScintillaEditView::replaceSelWith(const char * replaceText)
|
||||
@ -1854,7 +1838,6 @@ char * ScintillaEditView::getWordOnCaretPos(char * txt, int size)
|
||||
|
||||
TCHAR * ScintillaEditView::getGenericWordOnCaretPos(TCHAR * txt, int size)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
char *txtA = new char[size + 1];
|
||||
@ -1864,9 +1847,6 @@ TCHAR * ScintillaEditView::getGenericWordOnCaretPos(TCHAR * txt, int size)
|
||||
lstrcpy(txt, txtW);
|
||||
delete [] txtA;
|
||||
return txt;
|
||||
#else
|
||||
return getWordOnCaretPos(txt, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
char * ScintillaEditView::getSelectedText(char * txt, int size, bool expand)
|
||||
@ -1889,7 +1869,6 @@ char * ScintillaEditView::getSelectedText(char * txt, int size, bool expand)
|
||||
|
||||
TCHAR * ScintillaEditView::getGenericSelectedText(TCHAR * txt, int size, bool expand)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
char *txtA = new char[size + 1];
|
||||
@ -1899,16 +1878,13 @@ TCHAR * ScintillaEditView::getGenericSelectedText(TCHAR * txt, int size, bool ex
|
||||
lstrcpy(txt, txtW);
|
||||
delete [] txtA;
|
||||
return txt;
|
||||
#else
|
||||
return getSelectedText(txt, size, expand);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ScintillaEditView::searchInTarget(const TCHAR * text2Find, int lenOfText2Find, int fromPos, int toPos) const
|
||||
{
|
||||
execute(SCI_SETTARGETSTART, fromPos);
|
||||
execute(SCI_SETTARGETEND, toPos);
|
||||
#ifdef UNICODE
|
||||
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *text2FindA = wmc->wchar2char(text2Find, cp);
|
||||
@ -1916,36 +1892,24 @@ int ScintillaEditView::searchInTarget(const TCHAR * text2Find, int lenOfText2Fin
|
||||
int len = (lenOfText2Find > (int)text2FindALen)?lenOfText2Find:text2FindALen;
|
||||
int targetFound = execute(SCI_SEARCHINTARGET, (WPARAM)len, (LPARAM)text2FindA);
|
||||
return targetFound;
|
||||
#else
|
||||
return execute(SCI_SEARCHINTARGET, (WPARAM)lenOfText2Find, (LPARAM)text2Find);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScintillaEditView::appandGenericText(const TCHAR * text2Append) const
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *text2AppendA =wmc->wchar2char(text2Append, cp);
|
||||
execute(SCI_APPENDTEXT, strlen(text2AppendA), (LPARAM)text2AppendA);
|
||||
#else
|
||||
execute(SCI_APPENDTEXT, strlen(text2Append), (LPARAM)text2Append);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScintillaEditView::addGenericText(const TCHAR * text2Append) const
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *text2AppendA =wmc->wchar2char(text2Append, cp);
|
||||
execute(SCI_ADDTEXT, strlen(text2AppendA), (LPARAM)text2AppendA);
|
||||
#else
|
||||
execute(SCI_ADDTEXT, strlen(text2Append), (LPARAM)text2Append);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UNICODE
|
||||
void ScintillaEditView::addGenericText(const TCHAR * text2Append, long *mstart, long *mend) const
|
||||
{
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
@ -1953,12 +1917,6 @@ void ScintillaEditView::addGenericText(const TCHAR * text2Append, long *mstart,
|
||||
const char *text2AppendA =wmc->wchar2char(text2Append, cp, mstart, mend);
|
||||
execute(SCI_ADDTEXT, strlen(text2AppendA), (LPARAM)text2AppendA);
|
||||
}
|
||||
#else
|
||||
void ScintillaEditView::addGenericText(const TCHAR * text2Append, long *, long *) const
|
||||
{
|
||||
execute(SCI_ADDTEXT, strlen(text2Append), (LPARAM)text2Append);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ScintillaEditView::replaceTarget(const TCHAR * str2replace, int fromTargetPos, int toTargetPos) const
|
||||
{
|
||||
@ -1967,14 +1925,10 @@ int ScintillaEditView::replaceTarget(const TCHAR * str2replace, int fromTargetPo
|
||||
execute(SCI_SETTARGETSTART, fromTargetPos);
|
||||
execute(SCI_SETTARGETEND, toTargetPos);
|
||||
}
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *str2replaceA = wmc->wchar2char(str2replace, cp);
|
||||
return execute(SCI_REPLACETARGET, (WPARAM)-1, (LPARAM)str2replaceA);
|
||||
#else
|
||||
return execute(SCI_REPLACETARGET, (WPARAM)-1, (LPARAM)str2replace);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ScintillaEditView::replaceTargetRegExMode(const TCHAR * re, int fromTargetPos, int toTargetPos) const
|
||||
@ -1984,42 +1938,28 @@ int ScintillaEditView::replaceTargetRegExMode(const TCHAR * re, int fromTargetPo
|
||||
execute(SCI_SETTARGETSTART, fromTargetPos);
|
||||
execute(SCI_SETTARGETEND, toTargetPos);
|
||||
}
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *reA = wmc->wchar2char(re, cp);
|
||||
return execute(SCI_REPLACETARGETRE, (WPARAM)-1, (LPARAM)reA);
|
||||
#else
|
||||
return execute(SCI_REPLACETARGETRE, (WPARAM)-1, (LPARAM)re);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScintillaEditView::showAutoComletion(int lenEntered, const TCHAR * list)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *listA = wmc->wchar2char(list, cp);
|
||||
execute(SCI_AUTOCSHOW, lenEntered, WPARAM(listA));
|
||||
#else
|
||||
execute(SCI_AUTOCSHOW, lenEntered, WPARAM(list));
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScintillaEditView::showCallTip(int startPos, const TCHAR * def)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
unsigned int cp = execute(SCI_GETCODEPAGE);
|
||||
const char *defA = wmc->wchar2char(def, cp);
|
||||
execute(SCI_CALLTIPSHOW, startPos, LPARAM(defA));
|
||||
#else
|
||||
execute(SCI_CALLTIPSHOW, startPos, (LPARAM)def);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNICODE
|
||||
void ScintillaEditView::getLine(int lineNumber, TCHAR * line, int lineBufferLen)
|
||||
{
|
||||
WcharMbcsConvertor *wmc = WcharMbcsConvertor::getInstance();
|
||||
@ -2030,14 +1970,6 @@ void ScintillaEditView::getLine(int lineNumber, TCHAR * line, int lineBufferLen)
|
||||
lstrcpy(line, lineW);
|
||||
delete [] lineA;
|
||||
}
|
||||
#else
|
||||
void ScintillaEditView::getLine(int lineNumber, TCHAR * line, int)
|
||||
{
|
||||
execute(SCI_GETLINE, lineNumber, (LPARAM)line);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void ScintillaEditView::addText(int length, const char *buf)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user