Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scintilla autocomplete #42

Closed
wants to merge 42 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
340cecb
First attempt at Scintilla autocomplete
Dec 6, 2023
a2e4666
Use SCI_GETTEXTRANGEFULL to get selection instead of actually selecting
Dec 8, 2023
ff087ae
Fix blink
Dec 8, 2023
b743855
Remove cancel selection if not found and add at least 1 character
Dec 8, 2023
9e5e000
Do not prompt for database creation on Scintilla autocomplete
Dec 8, 2023
090d7fd
Make code a bit cleaner
Dec 8, 2023
92b2176
Add autocomplete icon
Dec 8, 2023
f188d21
Do a little code cleanup
Dec 9, 2023
56aa994
Force ignore case on Scintilla autocomplete
Dec 9, 2023
8ef03ce
Better way to force ignore case on Scintilla autocomplete
Dec 10, 2023
c191bd2
Add SciAutoC enable and ignore case options to local database config
Dec 10, 2023
376c232
Add forgotten piece to copy default DB config to local DB config
Dec 10, 2023
4aed71d
Add SciAutoC "from nth character" to config file
Dec 11, 2023
a0730da
Always set ignore case based on local database config setting
Dec 11, 2023
a98fbca
Add SciAutoC enable and ignore case to Settings dialog
Dec 11, 2023
a0121ed
Add SciAutoC "from nth character" to Settings dialog as ComboBox
Dec 11, 2023
5c06ae5
Make SciAutoC min and max hard-coded numbers as defines
Dec 12, 2023
ecca3a5
First attempt at Scintilla autocomplete
Dec 6, 2023
6394a27
Use SCI_GETTEXTRANGEFULL to get selection instead of actually selecting
Dec 8, 2023
333a2c3
Fix blink
Dec 8, 2023
2207aba
Remove cancel selection if not found and add at least 1 character
Dec 8, 2023
92a0a8b
Do not prompt for database creation on Scintilla autocomplete
Dec 8, 2023
48fb459
Make code a bit cleaner
Dec 8, 2023
2fd9985
Add autocomplete icon
Dec 8, 2023
1a670a8
Do a little code cleanup
Dec 9, 2023
7554b65
Force ignore case on Scintilla autocomplete
Dec 9, 2023
0c4e168
Better way to force ignore case on Scintilla autocomplete
Dec 10, 2023
875f1d0
Add SciAutoC enable and ignore case options to local database config
Dec 10, 2023
87b1da4
Add forgotten piece to copy default DB config to local DB config
Dec 10, 2023
d77eb0e
Add SciAutoC "from nth character" to config file
Dec 11, 2023
5297a97
Always set ignore case based on local database config setting
Dec 11, 2023
65be928
Add SciAutoC enable and ignore case to Settings dialog
Dec 11, 2023
aeaf884
Add SciAutoC "from nth character" to Settings dialog as ComboBox
Dec 11, 2023
a2b05e3
Make SciAutoC min and max hard-coded numbers as defines
Dec 12, 2023
86e3286
Merge branch 'sciautoc' of ssh://github.com/vinsworldcom/nppgtags int…
Dec 14, 2023
c6d4de9
Try to add some optimization to the Scintilla Autocomplete
Dec 22, 2023
a90d028
Make Sci-Autocomplete list length define
Dec 23, 2023
49ae3cc
Add better check for word characters to trigger or not Scintilla auto…
Jan 2, 2024
52b8a35
Never show activity window for Scintilla autocomplete
Jan 2, 2024
e4181ad
Marginal improvements of word checking
Jan 2, 2024
6c86772
Casting change
Jan 3, 2024
2b1f61d
Merge remote-tracking branch 'upstream/master' into sciautoc
Aug 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/Cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ const TCHAR* Cmd::CmdName[] = {
_T("Search in Source Files"), // GREP
_T("Search in Other Files"), // GREP_TEXT
_T("About"), // VERSION
_T("About CTags") // CTAGS_VERSION
_T("About CTags"), // CTAGS_VERSION
_T("AutoComplete Scintilla"), // AUTOCOMPLETE_SCINTILLA
_T("AutoComplete Scintilla") // AUTOCOMPLETE_SCINTILLA_SYMBOL
};


Expand Down
4 changes: 3 additions & 1 deletion src/CmdDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ enum CmdId_t
GREP,
GREP_TEXT,
VERSION,
CTAGS_VERSION
CTAGS_VERSION,
AUTOCOMPLETE_SCINTILLA,
AUTOCOMPLETE_SCINTILLA_SYMBOL
};


Expand Down
7 changes: 6 additions & 1 deletion src/CmdEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ const TCHAR* CmdEngine::CmdLine[] = {
_T("\"%s\\global.exe\" -g --result=grep \"%s\""), // GREP
_T("\"%s\\global.exe\" -gO --result=grep \"%s\""), // GREP_TEXT
_T("\"%s\\global.exe\" --version"), // VERSION
_T("\"%s\\ctags.exe\" --version") // CTAGS_VERSION
_T("\"%s\\ctags.exe\" --version"), // CTAGS_VERSION
_T("\"%s\\global.exe\" -cT \"%s\""), // AUTOCOMPLETE_SCINTILLA
_T("\"%s\\global.exe\" -cs \"%s\"") // AUTOCOMPLETE_SCINTILLA_SYMBOL
};


Expand Down Expand Up @@ -125,6 +127,9 @@ unsigned CmdEngine::start()
return 1;

bool showActivityWin = true;
if (_cmd->_id == AUTOCOMPLETE_SCINTILLA || _cmd->_id == AUTOCOMPLETE_SCINTILLA_SYMBOL)
showActivityWin = false;

if (_cmd->_id != CREATE_DATABASE && _cmd->_id != UPDATE_SINGLE)
{
// Wait 300 ms and if process has finished don't show Activity Window
Expand Down
39 changes: 38 additions & 1 deletion src/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ const TCHAR DbConfig::cUseLibDbKey[] = _T("UseLibraryDBs = ");
const TCHAR DbConfig::cLibDbPathsKey[] = _T("LibraryDBPaths = ");
const TCHAR DbConfig::cUsePathFilterKey[] = _T("UsePathFilters = ");
const TCHAR DbConfig::cPathFiltersKey[] = _T("PathFilters = ");
const TCHAR DbConfig::cUseSciAutoCKey[] = _T("UseSciAutoC = ");
const TCHAR DbConfig::cSciAutoCIgnoreCaseKey[] = _T("SciAutoCIgnoreCase = ");
const TCHAR DbConfig::cSciAutoCFromNCharKey[] = _T("SciAutoFromNChar = ");

const TCHAR DbConfig::cDefaultParser[] = _T("default");
const TCHAR DbConfig::cCtagsParser[] = _T("ctags");
Expand Down Expand Up @@ -85,6 +88,9 @@ void DbConfig::SetDefaults()
_libDbPaths.clear();
_usePathFilter = false;
_pathFilters.clear();
_useSciAutoC = false;
_SciAutoCIgnoreCase = false;
_SciAutoCFromNChar = 3;
}


Expand Down Expand Up @@ -137,6 +143,29 @@ bool DbConfig::ReadOption(TCHAR* line)
const unsigned pos = _countof(cPathFiltersKey) - 1;
FiltersFromBuf(&line[pos], _T(";"));
}
else if (!_tcsncmp(line, cUseSciAutoCKey, _countof(cUseSciAutoCKey) - 1))
{
const unsigned pos = _countof(cUseSciAutoCKey) - 1;
if (!_tcsncmp(&line[pos], _T("yes"), _countof(_T("yes")) - 1))
_useSciAutoC = true;
else
_useSciAutoC = false;
}
else if (!_tcsncmp(line, cSciAutoCIgnoreCaseKey, _countof(cSciAutoCIgnoreCaseKey) - 1))
{
const unsigned pos = _countof(cSciAutoCIgnoreCaseKey) - 1;
if (!_tcsncmp(&line[pos], _T("yes"), _countof(_T("yes")) - 1))
_SciAutoCIgnoreCase = true;
else
_SciAutoCIgnoreCase = false;
}
else if (!_tcsncmp(line, cSciAutoCFromNCharKey, _countof(cSciAutoCFromNCharKey) - 1))
{
const unsigned pos = _countof(cSciAutoCFromNCharKey) - 1;
_SciAutoCFromNChar = _tstoi(&line[pos]);
if (_SciAutoCFromNChar < SCIAUTOCNCHAR_MIN || _SciAutoCFromNChar > SCIAUTOCNCHAR_MAX)
_SciAutoCFromNChar = 3;
}
else
{
return false;
Expand Down Expand Up @@ -166,6 +195,9 @@ bool DbConfig::Write(FILE* fp) const
if (_ftprintf_s(fp, _T("%s%s\n"), cLibDbPathsKey, libDbPaths.C_str()) > 0)
if (_ftprintf_s(fp, _T("%s%s\n"), cUsePathFilterKey, (_usePathFilter ? _T("yes") : _T("no"))) > 0)
if (_ftprintf_s(fp, _T("%s%s\n"), cPathFiltersKey, pathFilters.C_str()) > 0)
if (_ftprintf_s(fp, _T("%s%s\n"), cUseSciAutoCKey, (_useSciAutoC ? _T("yes") : _T("no"))) > 0)
if (_ftprintf_s(fp, _T("%s%s\n"), cSciAutoCIgnoreCaseKey, (_SciAutoCIgnoreCase ? _T("yes") : _T("no"))) > 0)
if (_ftprintf_s(fp, _T("%s%i\n"), cSciAutoCFromNCharKey, _SciAutoCFromNChar) > 0)
success = true;

return success;
Expand Down Expand Up @@ -294,6 +326,9 @@ const DbConfig& DbConfig::operator=(const DbConfig& rhs)
_libDbPaths = rhs._libDbPaths;
_usePathFilter = rhs._usePathFilter;
_pathFilters = rhs._pathFilters;
_useSciAutoC = rhs._useSciAutoC;
_SciAutoCIgnoreCase = rhs._SciAutoCIgnoreCase;
_SciAutoCFromNChar = rhs._SciAutoCFromNChar;
}

return *this;
Expand All @@ -310,7 +345,9 @@ bool DbConfig::operator==(const DbConfig& rhs) const

return (_parserIdx == rhs._parserIdx && _autoUpdate == rhs._autoUpdate &&
_useLibDb == rhs._useLibDb && _libDbPaths == rhs._libDbPaths &&
_usePathFilter == rhs._usePathFilter && _pathFilters == rhs._pathFilters);
_usePathFilter == rhs._usePathFilter && _pathFilters == rhs._pathFilters &&
_useSciAutoC == rhs._useSciAutoC && _SciAutoCIgnoreCase == rhs._SciAutoCIgnoreCase &&
_SciAutoCFromNChar == rhs._SciAutoCFromNChar);
}


Expand Down
6 changes: 6 additions & 0 deletions src/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class DbConfig
std::vector<CPath> _libDbPaths;
bool _usePathFilter;
std::vector<CPath> _pathFilters;
bool _useSciAutoC;
bool _SciAutoCIgnoreCase;
int _SciAutoCFromNChar;

private:
bool ReadOption(TCHAR* line);
Expand All @@ -91,6 +94,9 @@ class DbConfig
static const TCHAR cLibDbPathsKey[];
static const TCHAR cUsePathFilterKey[];
static const TCHAR cPathFiltersKey[];
static const TCHAR cUseSciAutoCKey[];
static const TCHAR cSciAutoCIgnoreCaseKey[];
static const TCHAR cSciAutoCFromNCharKey[];

static const TCHAR cDefaultParser[];
static const TCHAR cCtagsParser[];
Expand Down
213 changes: 212 additions & 1 deletion src/GTags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,47 @@ constexpr int MIN_NOTEPADPP_VERSION = ((MIN_NOTEPADPP_VERSION_MAJOR << 16) | MIN
std::unique_ptr<CPath> ChangedFile;
bool DeInitCOM = false;

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define REGIMGIDL 22680
const char *xpmGtL[] = {
/* columns rows colors chars-per-pixel */
"16 16 14 1 ",
" c #000000",
". c #800000",
"X c #FF0000",
"o c #008000",
"O c #00FF00",
"+ c #808000",
"@ c #FFFF00",
"# c #000080",
"$ c #0000FF",
"% c #800080",
"& c #008080",
"* c #808080",
"= c #C0C0C0",
"- c None",
/* pixels */
"-----=*=**=-----",
"----#O$&&&$ =---",
"--=@$$OOoOO$o---",
"-=@#**&&&&$O$O=-",
"-+@+=#%%$$$$$$o-",
"=@*++%$%$$$$$$&*",
"*@@=#$#%X$$$$$$=",
"-@*+=+$*$$$$$$$=",
"=@+@%*&$$$$$$$$=",
"=@=**$=*$&$$&$$=",
"-+%+@+$%&&*&$$$*",
"-=$&+*++%*$$$$o-",
"-=+$*+%@.%*$$&*-",
"---$$*%$*$$$&o--",
"---=$$$$$$$#=---",
"------*=*==-----"
};
std::string sciAutoCList;
std::string _defaultCharList;
#define SCIAUTOCLIST_LONG 256

/**
* \brief
Expand Down Expand Up @@ -147,7 +188,7 @@ void dbWriteCB(const CmdPtr_t& cmd);
/**
* \brief
*/
DbHandle getDatabase(bool writeEn = false)
DbHandle getDatabase(bool writeEn = false, bool createDb = true)
{
INpp& npp = INpp::Get();
bool success;
Expand All @@ -160,6 +201,9 @@ DbHandle getDatabase(bool writeEn = false)
if (!db && !writeEn && GTagsSettings._useDefDb && !GTagsSettings._defDbPath.IsEmpty())
db = DbManager::Get().GetDbAt(GTagsSettings._defDbPath, writeEn, &success);

if (!createDb)
return db;

if (!db)
{
if (writeEn)
Expand Down Expand Up @@ -260,6 +304,115 @@ void halfComplCB(const CmdPtr_t& cmd)
}


/**
* \brief
*/
std::string ws2s(const std::wstring& wstr)
{
int size_needed = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), 0, 0, 0, 0);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), int(wstr.length() + 1), &strTo[0], size_needed, 0, 0);
return strTo;
}


/**
* \brief
*/
std::wstring s2ws(const std::string& str)
{
int size_needed = MultiByteToWideChar(CP_ACP, 0, str.c_str(), int(str.length() + 1), 0, 0);
std::wstring strTo(size_needed, 0);
MultiByteToWideChar(CP_ACP, 0, str.c_str(), int(str.length() + 1), &strTo[0], size_needed);
return strTo;
}


/**
* \brief
*/
void ShowSciAutoComplete(BOOL ignoreCase, size_t len)
{
SendMessage(INpp::Get().GetSciHandle(), SCI_AUTOCSETSEPARATOR, ' ', 0);
SendMessage(INpp::Get().GetSciHandle(), SCI_AUTOCSETTYPESEPARATOR, WPARAM('\x1E'), 0 );
SendMessage(INpp::Get().GetSciHandle(), SCI_AUTOCSETIGNORECASE, ignoreCase, 0);
SendMessage(INpp::Get().GetSciHandle(), SCI_REGISTERIMAGE, REGIMGIDL, (LPARAM)xpmGtL);
SendMessage(INpp::Get().GetSciHandle(), SCI_AUTOCSHOW, len, (LPARAM) sciAutoCList.c_str());
}


/**
* \brief
*/
void sciAutoComplCB(const CmdPtr_t& cmd)
{
DbManager::Get().PutDb(cmd->Db());

if (cmd->Status() == OK && cmd->Result())
{
size_t size = cmd->Parser()->GetList().size();
if (size == 0)
return;

sciAutoCList.clear();
int i = 0;
for (const auto& complEntry : cmd->Parser()->GetList())
{
sciAutoCList += ws2s(complEntry).c_str();
sciAutoCList += '\x1E';
sciAutoCList += STR(REGIMGIDL);
i++;
if (i < size)
sciAutoCList += " ";
}
ShowSciAutoComplete(cmd->IgnoreCase(), cmd->Tag().Len());
return;
}

if (cmd->Status() == FAILED)
{
CText msg(cmd->Result());
msg += _T("\nTry re-creating database.");
MessageBox(INpp::Get().GetHandle(), msg.C_str(), cmd->Name(), MB_OK | MB_ICONEXCLAMATION);
}
else if (cmd->Status() == RUN_ERROR)
{
MessageBox(INpp::Get().GetHandle(), _T("Running GTags failed"), cmd->Name(), MB_OK | MB_ICONERROR);
}
}


/**
* \brief
*/
void sciHalfComplCB(const CmdPtr_t& cmd)
{
if (cmd->Status() == OK)
{
cmd->Id(AUTOCOMPLETE_SCINTILLA_SYMBOL);

ParserPtr_t parser(new LineParser);
cmd->Parser(parser);

CmdEngine::Run(cmd, sciAutoComplCB);
return;
}

DbManager::Get().PutDb(cmd->Db());

if (cmd->Status() == FAILED)
{
CText msg(cmd->Result());
msg += _T("\nTry re-creating database.");
MessageBox(INpp::Get().GetHandle(), msg.C_str(), cmd->Name(), MB_OK | MB_ICONEXCLAMATION);
}
else if (cmd->Status() == RUN_ERROR)
{
MessageBox(INpp::Get().GetHandle(), _T("Running GTags failed"), cmd->Name(), MB_OK | MB_ICONERROR);
}
}


/**
* \brief
*/
Expand Down Expand Up @@ -941,6 +1094,13 @@ void OnNppReady()

::DrawMenuBar(npp.GetHandle());
}

auto defaultCharListLen = SendMessage(npp.GetSciHandle(), SCI_GETWORDCHARS, 0, 0);
char *defaultCharList = new char[defaultCharListLen + 1];
SendMessage(npp.GetSciHandle(), SCI_GETWORDCHARS, 0, reinterpret_cast<LPARAM>(defaultCharList));
defaultCharList[defaultCharListLen] = '\0';
_defaultCharList = defaultCharList;
delete[] defaultCharList;
}


Expand Down Expand Up @@ -1024,4 +1184,55 @@ void OnFileDelete(const CPath& file)
}
}


/**
* \brief
*/
void SciAutoComplete(int ch)
{
INpp& npp = INpp::Get();
Sci_Position curPos, startPos, endPos;
char tagStr[32 + 1] = { 0 };

DbHandle db = getDatabase(false, false);
if (!db)
return;

if (!db->GetConfig()._useSciAutoC)
return;

curPos = static_cast<Sci_Position>(npp.GetPos());
startPos = static_cast<Sci_Position>(npp.GetWordStartPos(curPos));
endPos = static_cast<Sci_Position>(npp.GetWordEndPos(curPos));
if ((curPos - startPos) > 32)
return;

if (_defaultCharList.find(char(ch)) == std::string::npos)
{
sciAutoCList.clear();
return;
}


if ((0 < sciAutoCList.length()) && (sciAutoCList.length() < SCIAUTOCLIST_LONG))
ShowSciAutoComplete(db->GetConfig()._SciAutoCIgnoreCase, (size_t)(curPos - startPos));
else
{
Sci_TextRangeFull tr;
tr.chrg.cpMin = startPos;
tr.chrg.cpMax = endPos;
tr.lpstrText = tagStr;
::SendMessage(npp.GetSciHandle(), SCI_GETTEXTRANGEFULL, 0, (LPARAM)&tr);

if (strlen(tagStr) < db->GetConfig()._SciAutoCFromNChar)
return;

std::wstring tag = s2ws(tagStr);

CmdPtr_t cmd(new Cmd(AUTOCOMPLETE_SCINTILLA, db, NULL, tag.c_str(), db->GetConfig()._SciAutoCIgnoreCase));

CmdEngine::Run(cmd, sciHalfComplCB);
}
}

} // namespace GTags
Loading