mirror of https://github.com/stella-emu/stella.git
further improved debugger tab auto complete (see #240)
This commit is contained in:
parent
4ebf3f2203
commit
abde496632
|
@ -467,13 +467,12 @@ just by re-running the relevant commands in the prompt.</p>
|
||||||
<h3><a name="TabCompletion">Tab Key Auto-Complete</a></h3>
|
<h3><a name="TabCompletion">Tab Key Auto-Complete</a></h3>
|
||||||
|
|
||||||
<p>While entering a command, label or function, you can type a partial name and
|
<p>While entering a command, label or function, you can type a partial name and
|
||||||
press the Tab key to attempt to auto-complete it. If you've ever used
|
press the (Shift +) Tab key to attempt to auto-complete it. If you've ever used
|
||||||
"bash", this will be immediately familiar. If not, try it: load up
|
"bash", this will be immediately familiar. If not, try it: load up
|
||||||
a ROM, go to the debugger, type "g" (but don't press Enter),
|
a ROM, go to the debugger, type "g" (but don't press Enter),
|
||||||
then hit Tab. The "g" will change to "gfx" (since this is the only
|
then hit Tab. The "g" will change to "gfx" (since this is the only
|
||||||
built-in command starting with a "g"). If there are multiple possible
|
built-in command starting with a "g"). If there are multiple possible
|
||||||
completions (try with "tr" instead of "g"), you'll see a list of them,
|
completions (try with "tr" instead of "g"), you can tab through them.
|
||||||
and your partial name will be completed as far as possible.
|
|
||||||
After the first character, the autocompletion considers all
|
After the first character, the autocompletion considers all
|
||||||
characters in the right order as a match (e.g. "twf" will be completed to
|
characters in the right order as a match (e.g. "twf" will be completed to
|
||||||
"trapWriteIf"). Alternatively you can make use of the camel case names and type
|
"trapWriteIf"). Alternatively you can make use of the camel case names and type
|
||||||
|
|
|
@ -160,6 +160,9 @@ bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
||||||
bool handled = true;
|
bool handled = true;
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
|
|
||||||
|
if(key != KBDK_TAB && !StellaModTest::isShift(mod))
|
||||||
|
_tabCount = -1;
|
||||||
|
|
||||||
switch(key)
|
switch(key)
|
||||||
{
|
{
|
||||||
case KBDK_RETURN:
|
case KBDK_RETURN:
|
||||||
|
@ -209,121 +212,87 @@ bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod)
|
||||||
// both at once.
|
// both at once.
|
||||||
|
|
||||||
if(_currentPos <= _promptStartPos)
|
if(_currentPos <= _promptStartPos)
|
||||||
break;
|
break; // no input
|
||||||
|
|
||||||
scrollToCurrent();
|
scrollToCurrent();
|
||||||
|
|
||||||
int len = _promptEndPos - _promptStartPos;
|
int len = _promptEndPos - _promptStartPos;
|
||||||
if(len > 255) len = 255;
|
|
||||||
|
if(_tabCount != -1)
|
||||||
|
len = int(strlen(_inputStr));
|
||||||
|
if(len > 255)
|
||||||
|
len = 255;
|
||||||
|
|
||||||
int lastDelimPos = -1;
|
int lastDelimPos = -1;
|
||||||
char delimiter = '\0';
|
char delimiter = '\0';
|
||||||
|
|
||||||
char inputStr[256]; // NOLINT (will be rewritten soon)
|
for(int i = 0; i < len; i++)
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
{
|
||||||
inputStr[i] = buffer(_promptStartPos + i) & 0x7f;
|
// copy the input at first tab press only
|
||||||
|
if(_tabCount == -1)
|
||||||
|
_inputStr[i] = buffer(_promptStartPos + i) & 0x7f;
|
||||||
// whitespace characters
|
// whitespace characters
|
||||||
if(strchr("{*@<> =[]()+-/&|!^~%", inputStr[i]))
|
if(strchr("{*@<> =[]()+-/&|!^~%", _inputStr[i]))
|
||||||
{
|
{
|
||||||
lastDelimPos = i;
|
lastDelimPos = i;
|
||||||
delimiter = inputStr[i];
|
delimiter = _inputStr[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inputStr[len] = '\0';
|
if(_tabCount == -1)
|
||||||
size_t strLen = len - lastDelimPos - 1;
|
_inputStr[len] = '\0';
|
||||||
|
|
||||||
StringList list;
|
StringList list;
|
||||||
string completionList;
|
|
||||||
string prefix;
|
|
||||||
|
|
||||||
if(lastDelimPos < 0)
|
if(lastDelimPos == -1)
|
||||||
{
|
|
||||||
// no delimiters, do only command completion:
|
// no delimiters, do only command completion:
|
||||||
const DebuggerParser& parser = instance().debugger().parser();
|
instance().debugger().parser().getCompletions(_inputStr, list);
|
||||||
parser.getCompletions(inputStr, list);
|
|
||||||
|
|
||||||
if(list.size() < 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
sort(list.begin(), list.end());
|
|
||||||
completionList = list[0];
|
|
||||||
for(uInt32 i = 1; i < list.size(); ++i)
|
|
||||||
completionList += " " + list[i];
|
|
||||||
prefix = getCompletionPrefix(list);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Special case for 'help' command
|
size_t strLen = len - lastDelimPos - 1;
|
||||||
if(BSPF::startsWithIgnoreCase(inputStr, "help"))
|
// do not show ALL commands/labels without any filter as it makes no sense
|
||||||
|
if(strLen > 0)
|
||||||
{
|
{
|
||||||
instance().debugger().parser().getCompletions(inputStr + lastDelimPos + 1, list);
|
// Special case for 'help' command
|
||||||
}
|
if(BSPF::startsWithIgnoreCase(_inputStr, "help"))
|
||||||
else
|
instance().debugger().parser().getCompletions(_inputStr + lastDelimPos + 1, list);
|
||||||
{
|
else
|
||||||
// do not show ALL labels without any filter as it makes no sense
|
|
||||||
if(strLen > 0)
|
|
||||||
{
|
{
|
||||||
// we got a delimiter, so this must be a label or a function
|
// we got a delimiter, so this must be a label or a function
|
||||||
const Debugger& dbg = instance().debugger();
|
const Debugger& dbg = instance().debugger();
|
||||||
|
|
||||||
dbg.cartDebug().getCompletions(inputStr + lastDelimPos + 1, list);
|
dbg.cartDebug().getCompletions(_inputStr + lastDelimPos + 1, list);
|
||||||
dbg.getCompletions(inputStr + lastDelimPos + 1, list);
|
dbg.getCompletions(_inputStr + lastDelimPos + 1, list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(list.size() < 1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
sort(list.begin(), list.end());
|
|
||||||
completionList = list[0];
|
|
||||||
for(uInt32 i = 1; i < list.size(); ++i)
|
|
||||||
completionList += " " + list[i];
|
|
||||||
prefix = getCompletionPrefix(list);
|
|
||||||
}
|
}
|
||||||
|
if(list.size() < 1)
|
||||||
|
break;
|
||||||
|
sort(list.begin(), list.end());
|
||||||
|
|
||||||
// TODO: tab through list
|
if(StellaModTest::isShift(mod))
|
||||||
|
|
||||||
if(list.size() == 1)
|
|
||||||
{
|
{
|
||||||
// add to buffer as though user typed it (plus a space)
|
if(--_tabCount < 0)
|
||||||
_currentPos = _promptStartPos + lastDelimPos + 1;
|
_tabCount = int(list.size()) - 1;
|
||||||
const char* clptr = completionList.c_str();
|
|
||||||
while(*clptr != '\0')
|
|
||||||
putcharIntern(*clptr++);
|
|
||||||
|
|
||||||
putcharIntern(' ');
|
|
||||||
_promptEndPos = _currentPos;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
_tabCount = (++_tabCount) % list.size();
|
||||||
nextLine();
|
|
||||||
// add to buffer as-is, then add PROMPT plus whatever we have so far
|
|
||||||
_currentPos = _promptStartPos + lastDelimPos + 1;
|
|
||||||
|
|
||||||
print("\n");
|
nextLine();
|
||||||
print(completionList);
|
_currentPos = _promptStartPos;
|
||||||
print("\n");
|
killLine(1); // kill whole line
|
||||||
print(PROMPT);
|
|
||||||
|
|
||||||
_promptStartPos = _currentPos;
|
// start with-autocompleted, fixed string...
|
||||||
|
for(int i = 0; i < lastDelimPos; i++)
|
||||||
|
putcharIntern(_inputStr[i]);
|
||||||
|
if(lastDelimPos > 0)
|
||||||
|
putcharIntern(delimiter);
|
||||||
|
|
||||||
if(prefix.length() < strLen)
|
// ...and add current autocompletion string
|
||||||
{
|
print(list[_tabCount]);
|
||||||
for(int i = 0; i < len; i++)
|
putcharIntern(' ');
|
||||||
putcharIntern(inputStr[i]);
|
_promptEndPos = _currentPos;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for(int i = 0; i < lastDelimPos; i++)
|
|
||||||
putcharIntern(inputStr[i]);
|
|
||||||
|
|
||||||
if(lastDelimPos > 0)
|
|
||||||
putcharIntern(delimiter);
|
|
||||||
|
|
||||||
print(prefix);
|
|
||||||
}
|
|
||||||
_promptEndPos = _currentPos;
|
|
||||||
}
|
|
||||||
dirty = true;
|
dirty = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,8 @@ class PromptWidget : public Widget, public CommandSender
|
||||||
int _historySize;
|
int _historySize;
|
||||||
int _historyIndex;
|
int _historyIndex;
|
||||||
int _historyLine;
|
int _historyLine;
|
||||||
|
int _tabCount{-1};
|
||||||
|
char _inputStr[256];
|
||||||
|
|
||||||
int _kConsoleCharWidth, _kConsoleCharHeight, _kConsoleLineHeight;
|
int _kConsoleCharWidth, _kConsoleCharHeight, _kConsoleLineHeight;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue