Clean up Completer.on_selection_changed.

Remove the dependency on the class variables _empty_item_index
and _cursor_part to make the code easier to follow. If
_update_completion is refactored in a similar way these variables can
be removed.
This commit is contained in:
Ryan Roden-Corrent 2016-09-09 07:26:24 -04:00
parent eb384fdda0
commit 581d7659ba
2 changed files with 32 additions and 23 deletions

View File

@ -179,6 +179,27 @@ class Completer(QObject):
else:
return s
def _partition(self):
parts = [x for x in self._split(keep=True) if x]
pos = self._cmd.cursorPosition() - len(self._cmd.prefix())
log.completion.debug('partitioning {} around position {}'.format(parts,
pos))
for i, part in enumerate(parts):
pos -= len(part)
if pos <= 0:
if part[pos-1:pos+1].isspace():
# cursor is in a space between two existing words
parts.insert(i, '')
prefix = [x.strip() for x in parts[:i]]
center = parts[i].strip()
# strip trailing whitepsace included as a separate token
postfix = [x.strip() for x in parts[i+1:] if not x.isspace()]
log.completion.debug(
'partitioned: {} {} {}'.format(prefix, center, postfix))
return prefix, center, postfix
log.completion.debug('empty partition result')
return [], '', []
@pyqtSlot(QItemSelection)
def on_selection_changed(self, selected):
"""Change the completed part if a new item was selected.
@ -355,29 +376,18 @@ class Completer(QObject):
including a trailing space and we shouldn't continue
completing the current item.
"""
parts = self._split()
log.completion.debug("changing part {} to '{}'".format(
self._cursor_part, newtext))
try:
parts[self._cursor_part] = newtext
except IndexError:
parts.append(newtext)
# We want to place the cursor directly after the part we just changed.
cursor_str = self._cmd.prefix() + ' '.join(
parts[:self._cursor_part + 1])
if immediate:
# If we should complete immediately, we want to move the cursor by
# one more char, to get to the next field.
cursor_str += ' '
text = self._cmd.prefix() + ' '.join(parts)
if immediate and self._cursor_part == len(parts) - 1:
# If we should complete immediately and we're completing the last
# part in the commandline, we automatically add a space.
before, center, after = self._partition()
log.completion.debug("changing {} to '{}'".format(center, newtext))
text = self._cmd.prefix() + ' '.join([*before, newtext])
pos = len(text) + (1 if immediate else 0)
if after:
text += ' ' + ' '.join(after)
elif immediate:
# pad with a space if quick-completing the last entry
text += ' '
log.completion.debug("setting text = '{}', pos = {}".format(text, pos))
self._cmd.setText(text)
log.completion.debug("Placing cursor after '{}'".format(cursor_str))
log.modes.debug("Completion triggered, focusing {!r}".format(self))
self._cmd.setCursorPosition(len(cursor_str))
self._cmd.setCursorPosition(pos)
self._cmd.setFocus()
self._cmd.show_cmd.emit()

View File

@ -204,6 +204,7 @@ def test_update_completion(txt, expected, status_command_stub, completer_obj,
(':|set', 'set', ':set|'),
(':|set ', 'set', ':set|'),
(':|se', 'set', ':set|'),
(':|se ', 'set', ':set|'),
(':s|e', 'set', ':set|'),
(':se|', 'set', ':set|'),
(':|se fonts', 'set', ':set| fonts'),
@ -248,8 +249,6 @@ def test_on_selection_changed(before, newtxt, after, completer_obj,
config_stub.data['completion']['quick-complete'] = quick_complete
model.count = unittest.mock.Mock(return_value=count)
_set_cmd_prompt(status_command_stub, before)
# TODO: refactor so cursor_part is a local rather than class variable
completer_obj._update_cursor_part()
completer_obj.on_selection_changed(selection)
model.data.assert_called_with(indexes[0])
assert status_command_stub.text() == expected_txt