Refactored PromptWidget a bit

This commit is contained in:
Thomas Jentzsch 2021-05-09 19:21:15 +02:00
parent e5e4e542b2
commit a39a03309e
7 changed files with 325 additions and 353 deletions

View File

@ -345,52 +345,52 @@ size can be configured e.g. in the
<p> <p>
<table BORDER=1 cellpadding=4> <table BORDER=1 cellpadding=4>
<tr> <tr>
<th>Key</th>
<th>Function</th> <th>Function</th>
<th>Key</th>
</tr> </tr>
<tr> <tr>
<td>Control + S</td>
<td>Step</td> <td>Step</td>
<td>Control + S</td>
</tr> </tr>
<tr> <tr>
<td>Control + T</td>
<td>Trace</td> <td>Trace</td>
<td>Control + T</td>
</tr> </tr>
<tr> <tr>
<td>Control + L</td>
<td>Scan +1</td> <td>Scan +1</td>
<td>Control + L</td>
</tr> </tr>
<tr> <tr>
<td>Control + F</td>
<td>Frame +1</td> <td>Frame +1</td>
<td>Control + F</td>
</tr> </tr>
<tr> <tr>
<td>Alt + Left arrow</td>
<td>Rewind 1</td> <td>Rewind 1</td>
<td>Alt + Left arrow</td>
</tr> </tr>
<tr> <tr>
<td>Shift-Alt + Left arrow</td>
<td>Rewind 10</td> <td>Rewind 10</td>
<td>Shift-Alt + Left arrow</td>
</tr> </tr>
<tr> <tr>
<td>Alt + Down arrow</td>
<td>Rewind all</td> <td>Rewind all</td>
<td>Alt + Down arrow</td>
</tr> </tr>
<tr> <tr>
<td>Alt + Right arrow</td>
<td>Unwind 1</td> <td>Unwind 1</td>
<td>Alt + Right arrow</td>
</tr> </tr>
<tr> <tr>
<td>Shift-Alt + Right arrow</td>
<td>Unwind 10</td> <td>Unwind 10</td>
<td>Shift-Alt + Right arrow</td>
</tr> </tr>
<tr> <tr>
<td>Alt + Up arrow</td>
<td>Unwind all</td> <td>Unwind all</td>
<td>Alt + Up arrow</td>
</tr> </tr>
<tr> <tr>
<td>Backquote (`)</td>
<td>Run, exits debugger</td> <td>Run, exits debugger</td>
<td>Backquote (`)</td>
</tr> </tr>
</table> </table>
</p> </p>
@ -428,25 +428,28 @@ or Supermon for the C=64.</p>
Bash-style commands are also supported:</p> Bash-style commands are also supported:</p>
<table border="1" cellpadding=4> <table border="1" cellpadding=4>
<tr><th>Key</th><th>Function</th></tr> <tr><th>Function</th><th>Key</th></tr>
<tr><td>Home</td><td>Move cursor to beginning of line</td></tr> <tr><td>Move cursor to beginning of line</td><td>Home</td></tr>
<tr><td>End</td><td>Move cursor to end of line</td></tr> <tr><td>Move cursor to end of line</td><td>End</td></tr>
<tr><td>Delete</td><td>Remove character to right of cursor</td></tr> <tr><td>Remove character to right of cursor</td><td>Delete</td></tr>
<tr><td>Backspace</td><td>Remove character to left of cursor</td></tr> <tr><td>Remove character to left of cursor</td><td>Backspace</td></tr>
<tr><td>Control + A</td><td>Same function as 'Home'</td></tr> <tr><td>Same function as 'Home'</td><td>Control + A</td></tr>
<tr><td>Control + E</td><td>Same function as 'End'</td></tr> <tr><td>Same function as 'End'</td><td>Control + E</td></tr>
<tr><td>Control + D</td><td>Same function as 'Delete'</td></tr> <tr><td>Same function as 'Delete'</td><td>Control + D</td></tr>
<tr><td>Control + K</td><td>Remove all characters from cursor to end of line</td></tr> <tr><td>Remove all characters from cursor to end of line</td><td>Control + K</td></tr>
<tr><td>Control + U</td><td>Remove all characters from cursor to beginning of line</td></tr> <tr><td>Remove all characters from cursor to beginning of line</td><td>Control + U</td></tr>
<tr><td>Control + W</td><td>Remove entire word to left of cursor</td></tr> <tr><td>Remove entire word to left of cursor</td><td>Control + W</td></tr>
<tr><td>Shift + PgUp</td><td>Scroll up through previous commands one screen/page</td></tr> <tr><td>Copy current line</td><td>Control + C</td></tr>
<tr><td>Shift + PgDown</td><td>Scroll down through previous commands one screen/page</td></tr> <tr><td>Cut current line</td><td>Control + X</td></tr>
<tr><td>Shift + Up</td><td>Scroll up through previous commands one line</td></tr> <tr><td>Paste over current line</td><td>Control + V</td></tr>
<tr><td>Shift + Down</td><td>Scroll down through previous commands one line</td></tr> <tr><td>Scroll up through previous commands one screen/page</td><td>Shift + PgUp</td></tr>
<tr><td>Shift + Home</td><td>Scroll to beginning of commands</td></tr> <tr><td>Scroll down through previous commands one screen/page</td><td>Shift + PgDown</td></tr>
<tr><td>Shift + End</td><td>Scroll to end of commands</td></tr> <tr><td>Scroll up through previous commands one line</td><td>Shift + Up</td></tr>
<tr><td>Scroll down through previous commands one line</td><td>Shift + Down</td></tr>
<tr><td>Scroll to beginning of commands</td><td>Shift + Home</td></tr>
<tr><td>Scroll to end of commands</td><td>Shift + End</td></tr>
</table> </table>
<p>You can also scroll with the mouse. Copy and paste is not yet supported.</p> <p>You can also scroll with the mouse. Copy and paste is currently only supported for a complete line.</p>
<p>To see the available commands, enter "help". For extended help, type "help cmd", <p>To see the available commands, enter "help". For extended help, type "help cmd",
where 'cmd' is the command you wish to know about. The available commands are listed where 'cmd' is the command you wish to know about. The available commands are listed

View File

@ -65,7 +65,10 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults); setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults);
#ifdef GUI_SUPPORT #ifdef GUI_SUPPORT
setDefaultMapping(Event::NoType, EventMode::kEditMode, updateDefaults); setDefaultMapping(Event::NoType, EventMode::kEditMode, updateDefaults);
#endif // DEBUG #endif
#ifdef DEBUGGER_SUPPORT
setDefaultMapping(Event::NoType, EventMode::kPromptMode, updateDefaults);
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -195,6 +198,13 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod
setDefaultKey(item, event, EventMode::kEditMode); setDefaultKey(item, event, EventMode::kEditMode);
break; break;
#endif #endif
#ifdef DEBUGGER_SUPPORT
case EventMode::kPromptMode:
// Edit mode events are always set because they are not saved
for(const auto& item : FixedPromptMapping)
setDefaultKey(item, event, EventMode::kPromptMode);
break;
#endif
default: default:
break; break;
@ -470,7 +480,9 @@ bool PhysicalKeyboardHandler::addMapping(Event::Type event, EventMode mode,
myKeyMap.erase(EventMode::kKeypadMode, key, mod); myKeyMap.erase(EventMode::kKeypadMode, key, mod);
myKeyMap.erase(EventMode::kCompuMateMode, key, mod); myKeyMap.erase(EventMode::kCompuMateMode, key, mod);
} }
else if(evMode != EventMode::kMenuMode && evMode != EventMode::kEditMode) else if(evMode != EventMode::kMenuMode
&& evMode != EventMode::kEditMode
&& evMode != EventMode::kPromptMode)
{ {
// erase identical mapping for kCommonMode // erase identical mapping for kCommonMode
myKeyMap.erase(EventMode::kCommonMode, key, mod); myKeyMap.erase(EventMode::kCommonMode, key, mod);
@ -899,7 +911,28 @@ PhysicalKeyboardHandler::FixedEditMapping = {
{Event::EndEdit, KBDK_KP_ENTER}, {Event::EndEdit, KBDK_KP_ENTER},
{Event::AbortEdit, KBDK_ESCAPE}, {Event::AbortEdit, KBDK_ESCAPE},
}; };
#endif #endif // GUI_SUPPORT
#ifdef DEBUGGER_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray
PhysicalKeyboardHandler::FixedPromptMapping = {
{Event::UINavNext, KBDK_TAB},
{Event::UINavPrev, KBDK_TAB, KBDM_SHIFT},
{Event::UIPgUp, KBDK_PAGEUP},
{Event::UIPgUp, KBDK_PAGEUP, KBDM_SHIFT},
{Event::UIPgDown, KBDK_PAGEDOWN},
{Event::UIPgDown, KBDK_PAGEDOWN, KBDM_SHIFT},
{Event::UIHome, KBDK_HOME, KBDM_SHIFT},
{Event::UIEnd, KBDK_END, KBDM_SHIFT},
{Event::UIUp, KBDK_UP, KBDM_SHIFT},
{Event::UIDown, KBDK_DOWN, KBDM_SHIFT},
{Event::UILeft, KBDK_DOWN},
{Event::UIRight, KBDK_UP},
};
#endif // DEBUGGER_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoystickMapping = { PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoystickMapping = {

View File

@ -149,6 +149,9 @@ class PhysicalKeyboardHandler
static EventMappingArray DefaultMenuMapping; static EventMappingArray DefaultMenuMapping;
#ifdef GUI_SUPPORT #ifdef GUI_SUPPORT
static EventMappingArray FixedEditMapping; static EventMappingArray FixedEditMapping;
#endif
#ifdef DEBUGGER_SUPPORT
static EventMappingArray FixedPromptMapping;
#endif #endif
static EventMappingArray DefaultCommonMapping; static EventMappingArray DefaultCommonMapping;
// Controller specific mappings // Controller specific mappings

View File

@ -48,6 +48,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM(JoyHatDir, {
NLOHMANN_JSON_SERIALIZE_ENUM(EventMode, { NLOHMANN_JSON_SERIALIZE_ENUM(EventMode, {
{EventMode::kEditMode, "kEditMode"}, {EventMode::kEditMode, "kEditMode"},
{EventMode::kPromptMode, "kPromptMode"},
{EventMode::kMenuMode, "kMenuMode"}, {EventMode::kMenuMode, "kMenuMode"},
{EventMode::kEmulationMode, "kEmulationMode"}, {EventMode::kEmulationMode, "kEmulationMode"},
{EventMode::kJoystickMode, "kJoystickMode"}, {EventMode::kJoystickMode, "kJoystickMode"},

View File

@ -158,291 +158,158 @@ bool PromptWidget::handleText(char text)
bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod) bool PromptWidget::handleKeyDown(StellaKey key, StellaMod mod)
{ {
bool handled = true; bool handled = true;
bool dirty = false; bool dirty = true;
if(key != KBDK_TAB && !StellaModTest::isShift(mod)) if(key != KBDK_TAB && !StellaModTest::isShift(mod))
_tabCount = -1; _tabCount = -1;
switch(key) // Uses normal edit events + special prompt events
Event::Type event = instance().eventHandler().eventForKey(EventMode::kEditMode, key, mod);
if(event == Event::NoType)
event = instance().eventHandler().eventForKey(EventMode::kPromptMode, key, mod);
switch(event)
{ {
case KBDK_RETURN: case Event::EndEdit:
case KBDK_KP_ENTER:
{ {
nextLine(); if(execute())
return true;
assert(_promptEndPos >= _promptStartPos);
int len = _promptEndPos - _promptStartPos;
if (len > 0)
{
// Copy the user input to command
string command;
for (int i = 0; i < len; i++)
command += buffer(_promptStartPos + i) & 0x7f;
// Add the input to the history
addToHistory(command.c_str());
// Pass the command to the debugger, and print the result
string result = instance().debugger().run(command);
// This is a bit of a hack
// Certain commands remove the debugger dialog from underneath us,
// so we shouldn't print any messages
// Those commands will return '_EXIT_DEBUGGER' as their result
if(result == "_EXIT_DEBUGGER")
{
_exitedEarly = true;
return true;
}
else if(result == "_NO_PROMPT")
return true;
else if(result != "")
print(result + "\n");
}
printPrompt(); printPrompt();
dirty = true;
break; break;
} }
case KBDK_TAB: case Event::UINavNext:
{ dirty = autoComplete(+1);
// Tab completion: we complete either commands or labels, but not
// both at once.
if(_currentPos <= _promptStartPos)
break; // no input
scrollToCurrent();
int len = _promptEndPos - _promptStartPos;
if(_tabCount != -1)
len = int(strlen(_inputStr));
if(len > 255)
len = 255;
int lastDelimPos = -1;
char delimiter = '\0';
for(int i = 0; i < len; i++)
{
// copy the input at first tab press only
if(_tabCount == -1)
_inputStr[i] = buffer(_promptStartPos + i) & 0x7f;
// whitespace characters
if(strchr("{*@<> =[]()+-/&|!^~%", _inputStr[i]))
{
lastDelimPos = i;
delimiter = _inputStr[i];
}
}
if(_tabCount == -1)
_inputStr[len] = '\0';
StringList list;
if(lastDelimPos == -1)
// no delimiters, do only command completion:
instance().debugger().parser().getCompletions(_inputStr, list);
else
{
size_t strLen = len - lastDelimPos - 1;
// do not show ALL commands/labels without any filter as it makes no sense
if(strLen > 0)
{
// Special case for 'help' command
if(BSPF::startsWithIgnoreCase(_inputStr, "help"))
instance().debugger().parser().getCompletions(_inputStr + lastDelimPos + 1, list);
else
{
// we got a delimiter, so this must be a label or a function
const Debugger& dbg = instance().debugger();
dbg.cartDebug().getCompletions(_inputStr + lastDelimPos + 1, list);
dbg.getCompletions(_inputStr + lastDelimPos + 1, list);
}
}
}
if(list.size() < 1)
break;
sort(list.begin(), list.end());
if(StellaModTest::isShift(mod))
{
if(--_tabCount < 0)
_tabCount = int(list.size()) - 1;
}
else
_tabCount = (++_tabCount) % list.size();
nextLine();
_currentPos = _promptStartPos;
killLine(1); // kill whole line
// start with-autocompleted, fixed string...
for(int i = 0; i < lastDelimPos; i++)
putcharIntern(_inputStr[i]);
if(lastDelimPos > 0)
putcharIntern(delimiter);
// ...and add current autocompletion string
print(list[_tabCount]);
putcharIntern(' ');
_promptEndPos = _currentPos;
dirty = true;
break; break;
}
case KBDK_BACKSPACE: case Event::UINavPrev:
if (_currentPos > _promptStartPos) dirty = autoComplete(-1);
break;
case Event::UILeft:
historyScroll(-1);
break;
case Event::UIRight:
historyScroll(+1);
break;
case Event::Backspace:
if(_currentPos > _promptStartPos)
killChar(-1); killChar(-1);
scrollToCurrent(); scrollToCurrent();
dirty = true;
break; break;
case KBDK_DELETE: case Event::Delete:
case KBDK_KP_PERIOD: // actually the num delete killChar(+1);
if(StellaModTest::isShift(mod))
textCut();
else
killChar(+1);
dirty = true;
break; break;
case KBDK_PAGEUP: case Event::MoveHome:
if (StellaModTest::isShift(mod)) _currentPos = _promptStartPos;
{
// Don't scroll up when at top of buffer
if(_scrollLine < _linesPerPage)
break;
_scrollLine -= _linesPerPage - 1;
if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1)
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
updateScrollBuffer();
dirty = true;
}
break; break;
case KBDK_PAGEDOWN: case Event::MoveEnd:
if (StellaModTest::isShift(mod)) _currentPos = _promptEndPos;
{
// Don't scroll down when at bottom of buffer
if(_scrollLine >= _promptEndPos / _lineWidth)
break;
_scrollLine += _linesPerPage - 1;
if (_scrollLine > _promptEndPos / _lineWidth)
_scrollLine = _promptEndPos / _lineWidth;
updateScrollBuffer();
dirty = true;
}
break; break;
case KBDK_HOME: case Event::MoveRightChar:
if (StellaModTest::isShift(mod)) if(_currentPos < _promptEndPos)
{
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
updateScrollBuffer();
}
else
_currentPos = _promptStartPos;
dirty = true;
break;
case KBDK_END:
if (StellaModTest::isShift(mod))
{
_scrollLine = _promptEndPos / _lineWidth;
if (_scrollLine < _linesPerPage - 1)
_scrollLine = _linesPerPage - 1;
updateScrollBuffer();
}
else
_currentPos = _promptEndPos;
dirty = true;
break;
case KBDK_UP:
if (StellaModTest::isShift(mod))
{
if(_scrollLine <= _firstLineInBuffer + _linesPerPage - 1)
break;
_scrollLine -= 1;
updateScrollBuffer();
dirty = true;
}
else
historyScroll(+1);
break;
case KBDK_DOWN:
if (StellaModTest::isShift(mod))
{
// Don't scroll down when at bottom of buffer
if(_scrollLine >= _promptEndPos / _lineWidth)
break;
_scrollLine += 1;
updateScrollBuffer();
dirty = true;
}
else
historyScroll(-1);
break;
case KBDK_RIGHT:
if (_currentPos < _promptEndPos)
_currentPos++; _currentPos++;
dirty = true;
break; break;
case KBDK_LEFT: case Event::MoveLeftChar:
if (_currentPos > _promptStartPos) if(_currentPos > _promptStartPos)
_currentPos--; _currentPos--;
dirty = true;
break; break;
case KBDK_INSERT: case Event::DeleteRightWord:
if(StellaModTest::isShift(mod)) killChar(+1);
{ break;
textPaste();
dirty = true; case Event::DeleteEnd:
} killLine(+1);
else if(StellaModTest::isControl(mod)) break;
{
textCopy(); case Event::DeleteHome:
dirty = true; killLine(-1);
} break;
else
handled = false; case Event::DeleteLeftWord:
killWord();
break;
case Event::UIUp:
if(_scrollLine <= _firstLineInBuffer + _linesPerPage - 1)
break;
_scrollLine -= 1;
updateScrollBuffer();
break;
case Event::UIDown:
// Don't scroll down when at bottom of buffer
if(_scrollLine >= _promptEndPos / _lineWidth)
break;
_scrollLine += 1;
updateScrollBuffer();
break;
case Event::UIPgUp:
// Don't scroll up when at top of buffer
if(_scrollLine < _linesPerPage)
break;
_scrollLine -= _linesPerPage - 1;
if(_scrollLine < _firstLineInBuffer + _linesPerPage - 1)
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
updateScrollBuffer();
break;
case Event::UIPgDown:
// Don't scroll down when at bottom of buffer
if(_scrollLine >= _promptEndPos / _lineWidth)
break;
_scrollLine += _linesPerPage - 1;
if(_scrollLine > _promptEndPos / _lineWidth)
_scrollLine = _promptEndPos / _lineWidth;
updateScrollBuffer();
break;
case Event::UIHome:
_scrollLine = _firstLineInBuffer + _linesPerPage - 1;
updateScrollBuffer();
break;
case Event::UIEnd:
_scrollLine = _promptEndPos / _lineWidth;
if(_scrollLine < _linesPerPage - 1)
_scrollLine = _linesPerPage - 1;
updateScrollBuffer();
break;
//case Event::SelectAll:
// textSelectAll();
// break;
case Event::Cut:
textCut();
break;
case Event::Copy:
textCopy();
break;
case Event::Paste:
textPaste();
break; break;
default: default:
if (StellaModTest::isControl(mod)) handled = false;
{ dirty = false;
specialKeys(key);
}
else if (StellaModTest::isAlt(mod))
{
// Placeholder only - this will never be reached
}
else
handled = false;
break; break;
} }
@ -546,46 +413,6 @@ int PromptWidget::getWidth() const
return _w + ScrollBarWidget::scrollBarWidth(_font); return _w + ScrollBarWidget::scrollBarWidth(_font);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::specialKeys(StellaKey key)
{
bool handled = true;
switch(key)
{
case KBDK_D:
killChar(+1);
break;
case KBDK_K:
killLine(+1);
break;
case KBDK_U:
killLine(-1);
break;
case KBDK_W:
killWord();
break;
case KBDK_A:
textSelectAll();
break;
case KBDK_X:
textCut();
break;
case KBDK_C:
textCopy();
break;
case KBDK_V:
textPaste();
break;
default:
handled = false;
break;
}
if(handled)
setDirty();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::killChar(int direction) void PromptWidget::killChar(int direction)
{ {
@ -807,6 +634,135 @@ void PromptWidget::historyScroll(int direction)
setDirty(); setDirty();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PromptWidget::execute()
{
nextLine();
assert(_promptEndPos >= _promptStartPos);
int len = _promptEndPos - _promptStartPos;
if(len > 0)
{
// Copy the user input to command
string command;
for(int i = 0; i < len; i++)
command += buffer(_promptStartPos + i) & 0x7f;
// Add the input to the history
addToHistory(command.c_str());
// Pass the command to the debugger, and print the result
string result = instance().debugger().run(command);
// This is a bit of a hack
// Certain commands remove the debugger dialog from underneath us,
// so we shouldn't print any messages
// Those commands will return '_EXIT_DEBUGGER' as their result
if(result == "_EXIT_DEBUGGER")
{
_exitedEarly = true;
return true;
}
else if(result == "_NO_PROMPT")
return true;
else if(result != "")
print(result + "\n");
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool PromptWidget::autoComplete(int direction)
{
// Tab completion: we complete either commands or labels, but not
// both at once.
if(_currentPos <= _promptStartPos)
return false; // no input
scrollToCurrent();
int len = _promptEndPos - _promptStartPos;
if(_tabCount != -1)
len = int(strlen(_inputStr));
if(len > 255)
len = 255;
int lastDelimPos = -1;
char delimiter = '\0';
for(int i = 0; i < len; i++)
{
// copy the input at first tab press only
if(_tabCount == -1)
_inputStr[i] = buffer(_promptStartPos + i) & 0x7f;
// whitespace characters
if(strchr("{*@<> =[]()+-/&|!^~%", _inputStr[i]))
{
lastDelimPos = i;
delimiter = _inputStr[i];
}
}
if(_tabCount == -1)
_inputStr[len] = '\0';
StringList list;
if(lastDelimPos == -1)
// no delimiters, do only command completion:
instance().debugger().parser().getCompletions(_inputStr, list);
else
{
size_t strLen = len - lastDelimPos - 1;
// do not show ALL commands/labels without any filter as it makes no sense
if(strLen > 0)
{
// Special case for 'help' command
if(BSPF::startsWithIgnoreCase(_inputStr, "help"))
instance().debugger().parser().getCompletions(_inputStr + lastDelimPos + 1, list);
else
{
// we got a delimiter, so this must be a label or a function
const Debugger& dbg = instance().debugger();
dbg.cartDebug().getCompletions(_inputStr + lastDelimPos + 1, list);
dbg.getCompletions(_inputStr + lastDelimPos + 1, list);
}
}
}
if(list.size() < 1)
return false;
sort(list.begin(), list.end());
if(direction < 0)
{
if(--_tabCount < 0)
_tabCount = int(list.size()) - 1;
}
else
_tabCount = (++_tabCount) % list.size();
nextLine();
_currentPos = _promptStartPos;
killLine(1); // kill whole line
// start with-autocompleted, fixed string...
for(int i = 0; i < lastDelimPos; i++)
putcharIntern(_inputStr[i]);
if(lastDelimPos > 0)
putcharIntern(delimiter);
// ...and add current autocompletion string
print(list[_tabCount]);
putcharIntern(' ');
_promptEndPos = _currentPos;
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::nextLine() void PromptWidget::nextLine()
{ {
@ -971,29 +927,6 @@ string PromptWidget::saveBuffer(const FilesystemNode& file)
return "unable to save session"; return "unable to save session";
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string PromptWidget::getCompletionPrefix(const StringList& completions)
{
// Find the number of characters matching for each of the completions provided
for(uInt32 len = 1;; ++len)
{
for(uInt32 i = 0; i < completions.size(); ++i)
{
string s1 = completions[i];
if(s1.length() < len)
{
return s1.substr(0, len - 1);
}
string find = s1.substr(0, len);
for(uInt32 j = i + 1; j < completions.size(); ++j)
{
if(!BSPF::startsWithIgnoreCase(completions[j], find))
return s1.substr(0, len - 1);
}
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::clearScreen() void PromptWidget::clearScreen()

View File

@ -64,7 +64,6 @@ class PromptWidget : public Widget, public CommandSender
void scrollToCurrent(); void scrollToCurrent();
// Line editing // Line editing
void specialKeys(StellaKey key);
void nextLine(); void nextLine();
void killChar(int direction); void killChar(int direction);
void killLine(int direction); void killLine(int direction);
@ -80,6 +79,9 @@ class PromptWidget : public Widget, public CommandSender
// History // History
void historyScroll(int direction); void historyScroll(int direction);
bool execute();
bool autoComplete(int direction);
void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
void handleMouseWheel(int x, int y, int direction) override; void handleMouseWheel(int x, int y, int direction) override;
bool handleText(char text) override; bool handleText(char text) override;
@ -92,10 +94,6 @@ class PromptWidget : public Widget, public CommandSender
bool wantsFocus() const override { return true; } bool wantsFocus() const override { return true; }
void loadConfig() override; void loadConfig() override;
private:
// Get the longest prefix (initially 's') that is in every string in the list
string getCompletionPrefix(const StringList& completions);
private: private:
enum { enum {
kBufferSize = 32768, kBufferSize = 32768,

View File

@ -84,6 +84,7 @@ enum class EventMode {
kCompuMateMode, // cannot be remapped kCompuMateMode, // cannot be remapped
kCommonMode, // mapping common between controllers kCommonMode, // mapping common between controllers
kEditMode, // mapping used in editable widgets kEditMode, // mapping used in editable widgets
kPromptMode, // extra mappings used in debugger's prompt widget
kNumModes kNumModes
}; };