First try at using cursor position
This commit is contained in:
parent
4d0649a825
commit
dc655dd40b
@ -65,6 +65,7 @@ class CompletionView(QTreeView):
|
||||
Signals:
|
||||
change_completed_part: Text which should be substituted for the word
|
||||
we're currently completing.
|
||||
arg: The text to change to.
|
||||
"""
|
||||
|
||||
STYLESHEET = """
|
||||
@ -201,13 +202,16 @@ class CompletionView(QTreeView):
|
||||
# Item is a real item, not a category header -> success
|
||||
return idx
|
||||
|
||||
def _get_new_completion(self, parts):
|
||||
def _get_new_completion(self, parts, cursor_part):
|
||||
"""Get a new completion model.
|
||||
|
||||
parts: The command chunks to get a completion for.
|
||||
Args:
|
||||
parts: The command chunks to get a completion for.
|
||||
cursor_part: The part the cursor is over currently.
|
||||
"""
|
||||
if len(parts) == 1:
|
||||
# parts = [''] or something like ['set']
|
||||
logger.debug("cursor part: {}".format(cursor_part))
|
||||
if cursor_part == 0:
|
||||
# '|' or 'set|'
|
||||
return self._models['command']
|
||||
# delegate completion to command
|
||||
try:
|
||||
@ -220,19 +224,18 @@ class CompletionView(QTreeView):
|
||||
# command without any available completions
|
||||
return None
|
||||
try:
|
||||
idx = len(parts[1:]) - 1
|
||||
idx = cursor_part - 1
|
||||
completion_name = completions[idx]
|
||||
logger.debug('partlen: {}, modelname {}'.format(
|
||||
len(parts[1:]), completion_name))
|
||||
logger.debug('modelname {}'.format(completion_name))
|
||||
except IndexError:
|
||||
# More arguments than completions
|
||||
return None
|
||||
if completion_name == 'option':
|
||||
section = parts[-2]
|
||||
section = parts[cursor_part - 1]
|
||||
model = self._models['option'].get(section)
|
||||
elif completion_name == 'value':
|
||||
section = parts[-3]
|
||||
option = parts[-2]
|
||||
section = parts[cursor_part - 2]
|
||||
option = parts[cursor_part - 1]
|
||||
try:
|
||||
model = self._models['value'][section][option]
|
||||
except KeyError:
|
||||
@ -249,9 +252,6 @@ class CompletionView(QTreeView):
|
||||
|
||||
Args:
|
||||
prev: True for prev item, False for next one.
|
||||
|
||||
Emit:
|
||||
change_completed_part: When a completion took place.
|
||||
"""
|
||||
if not self._completing:
|
||||
# No completion running at the moment, ignore keypress
|
||||
@ -283,16 +283,16 @@ class CompletionView(QTreeView):
|
||||
elif section == 'aliases':
|
||||
self._init_command_completion()
|
||||
|
||||
@pyqtSlot(str)
|
||||
def on_update_completion(self, text):
|
||||
@pyqtSlot(str, int)
|
||||
def on_update_completion(self, text, cursor_part):
|
||||
"""Check if completions are available and activate them.
|
||||
|
||||
Slot for the textChanged signal of the statusbar command widget.
|
||||
|
||||
Args:
|
||||
text: The new text
|
||||
cursor_part: The part the cursor is currently over.
|
||||
"""
|
||||
# FIXME we should also consider the cursor position
|
||||
if not text.startswith(':'):
|
||||
# This is a search or gibberish, so we don't need to complete
|
||||
# anything (yet)
|
||||
@ -304,7 +304,7 @@ class CompletionView(QTreeView):
|
||||
text = text.lstrip(':')
|
||||
parts = split_cmdline(text)
|
||||
|
||||
model = self._get_new_completion(parts)
|
||||
model = self._get_new_completion(parts, cursor_part)
|
||||
if model is None:
|
||||
logger.debug("No completion model for {}.".format(parts))
|
||||
else:
|
||||
@ -324,7 +324,8 @@ class CompletionView(QTreeView):
|
||||
if model is None:
|
||||
return
|
||||
|
||||
pattern = parts[-1] if parts else ''
|
||||
pattern = parts[cursor_part] if parts else ''
|
||||
logger.debug("pattern: {}".format(pattern))
|
||||
self._model.pattern = pattern
|
||||
self._model.srcmodel.mark_all_items(pattern)
|
||||
if self._enabled:
|
||||
|
@ -50,7 +50,8 @@ class Command(MinimalLineEdit):
|
||||
hidden.
|
||||
hide_completion: Emitted when the completion widget should be hidden.
|
||||
update_completion: Emitted when the completion should be shown/updated.
|
||||
arg: The new text which was set.
|
||||
arg 0: The new text which was set.
|
||||
arg 1: The part the cursor is currently in.
|
||||
show_cmd: Emitted when command input should be shown.
|
||||
hide_cmd: Emitted when command input can be hidden.
|
||||
"""
|
||||
@ -60,7 +61,7 @@ class Command(MinimalLineEdit):
|
||||
got_search_rev = pyqtSignal(str)
|
||||
clear_completion_selection = pyqtSignal()
|
||||
hide_completion = pyqtSignal()
|
||||
update_completion = pyqtSignal(str)
|
||||
update_completion = pyqtSignal(str, int)
|
||||
show_cmd = pyqtSignal()
|
||||
hide_cmd = pyqtSignal()
|
||||
|
||||
@ -73,10 +74,35 @@ class Command(MinimalLineEdit):
|
||||
self.history = History()
|
||||
self._validator = _CommandValidator(self)
|
||||
self.setValidator(self._validator)
|
||||
self.textEdited.connect(self.history.stop)
|
||||
self.textEdited.connect(self.update_completion)
|
||||
self.textEdited.connect(self.on_text_edited)
|
||||
self.cursorPositionChanged.connect(self.on_cursor_position_changed)
|
||||
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored)
|
||||
|
||||
def _cursor_part(self):
|
||||
"""Get the part index of the commandline where the cursor is over."""
|
||||
prefix, parts = self._split()
|
||||
cursor_pos = self.cursorPosition()
|
||||
cursor_pos -= len(prefix)
|
||||
for i, part in enumerate(parts):
|
||||
logger.debug("part {}, len {}, pos {}".format(i, len(part),
|
||||
cursor_pos))
|
||||
if cursor_pos <= len(part):
|
||||
# foo| bar
|
||||
return i
|
||||
cursor_pos -= (len(part) + 1) # FIXME are spaces always 1 char?
|
||||
|
||||
def _split(self):
|
||||
text = self.text()
|
||||
if not text:
|
||||
return '', []
|
||||
if text[0] in STARTCHARS:
|
||||
prefix = text[0]
|
||||
text = text[1:]
|
||||
else:
|
||||
prefix = ''
|
||||
parts = split_cmdline(text)
|
||||
return prefix, parts
|
||||
|
||||
@pyqtSlot(str)
|
||||
def set_cmd_text(self, text):
|
||||
"""Preset the statusbar to some text.
|
||||
@ -91,7 +117,7 @@ class Command(MinimalLineEdit):
|
||||
self.setText(text)
|
||||
if old_text != text:
|
||||
# We want the completion to pop out here.
|
||||
self.update_completion.emit(text)
|
||||
self.update_completion.emit(text, self._cursor_part())
|
||||
self.setFocus()
|
||||
self.show_cmd.emit()
|
||||
|
||||
@ -102,18 +128,14 @@ class Command(MinimalLineEdit):
|
||||
Args:
|
||||
text: The text to set (string).
|
||||
"""
|
||||
# FIXME we should consider the cursor position.
|
||||
text = self.text()
|
||||
if text[0] in STARTCHARS:
|
||||
prefix = text[0]
|
||||
text = text[1:]
|
||||
else:
|
||||
prefix = ''
|
||||
parts = split_cmdline(text)
|
||||
logger.debug("Old text: '{}' - parts: {}, changing to '{}'".format(
|
||||
text, parts, newtext))
|
||||
parts[-1] = newtext
|
||||
prefix, parts = self._split()
|
||||
cursor_part = self._cursor_part()
|
||||
logger.debug("parts: {}, changing {} to '{}'".format(
|
||||
parts, cursor_part, newtext))
|
||||
parts[cursor_part] = newtext
|
||||
self.blockSignals(True)
|
||||
self.setText(prefix + ' '.join(parts))
|
||||
self.blockSignals(False)
|
||||
self.setFocus()
|
||||
self.show_cmd.emit()
|
||||
|
||||
@ -165,6 +187,17 @@ class Command(MinimalLineEdit):
|
||||
if text[0] in signals:
|
||||
signals[text[0]].emit(text.lstrip(text[0]))
|
||||
|
||||
@pyqtSlot(str)
|
||||
def on_text_edited(self, text):
|
||||
"""Slot for textEdited. Stop history and update completion."""
|
||||
self.history.stop()
|
||||
self.update_completion.emit(text, self._cursor_part())
|
||||
|
||||
@pyqtSlot(int, int)
|
||||
def on_cursor_position_changed(self, _old, _new):
|
||||
"""Slot for cursorPositionChanged to update completion."""
|
||||
self.update_completion.emit(self.text(), self._cursor_part())
|
||||
|
||||
def on_mode_left(self, mode):
|
||||
"""Clear up when ommand mode was left.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user