Start using KeyParser for command mode
This commit is contained in:
parent
30a6b5610e
commit
55a8da7f1b
@ -129,6 +129,7 @@ class QuteBrowser(QApplication):
|
|||||||
'hint': HintKeyParser(self),
|
'hint': HintKeyParser(self),
|
||||||
'insert': PassthroughKeyParser('keybind.insert', self),
|
'insert': PassthroughKeyParser('keybind.insert', self),
|
||||||
'passthrough': PassthroughKeyParser('keybind.passthrough', self),
|
'passthrough': PassthroughKeyParser('keybind.passthrough', self),
|
||||||
|
'command': PassthroughKeyParser('keybind.command', self),
|
||||||
}
|
}
|
||||||
self._init_cmds()
|
self._init_cmds()
|
||||||
self.mainwindow = MainWindow()
|
self.mainwindow = MainWindow()
|
||||||
@ -140,7 +141,8 @@ class QuteBrowser(QApplication):
|
|||||||
modes.manager.register('passthrough',
|
modes.manager.register('passthrough',
|
||||||
self._keyparsers['passthrough'].handle,
|
self._keyparsers['passthrough'].handle,
|
||||||
passthrough=True)
|
passthrough=True)
|
||||||
modes.manager.register('command', None, passthrough=True)
|
modes.manager.register('command', self._keyparsers['command'].handle,
|
||||||
|
passthrough=True)
|
||||||
self.modeman = modes.manager # for commands
|
self.modeman = modes.manager # for commands
|
||||||
self.installEventFilter(modes.manager)
|
self.installEventFilter(modes.manager)
|
||||||
self.setQuitOnLastWindowClosed(False)
|
self.setQuitOnLastWindowClosed(False)
|
||||||
@ -302,12 +304,11 @@ class QuteBrowser(QApplication):
|
|||||||
tabs.cur_link_hovered.connect(status.url.set_hover_url)
|
tabs.cur_link_hovered.connect(status.url.set_hover_url)
|
||||||
|
|
||||||
# command input / completion
|
# command input / completion
|
||||||
cmd.esc_pressed.connect(tabs.setFocus)
|
modes.manager.left.connect(tabs.on_mode_left)
|
||||||
cmd.clear_completion_selection.connect(
|
cmd.clear_completion_selection.connect(
|
||||||
completion.on_clear_completion_selection)
|
completion.on_clear_completion_selection)
|
||||||
cmd.hide_completion.connect(completion.hide)
|
cmd.hide_completion.connect(completion.hide)
|
||||||
cmd.textChanged.connect(completion.on_cmd_text_changed)
|
cmd.textChanged.connect(completion.on_cmd_text_changed)
|
||||||
cmd.tab_pressed.connect(completion.on_tab_pressed)
|
|
||||||
completion.change_completed_part.connect(cmd.on_change_completed_part)
|
completion.change_completed_part.connect(cmd.on_change_completed_part)
|
||||||
|
|
||||||
def _recover_pages(self):
|
def _recover_pages(self):
|
||||||
|
@ -89,7 +89,12 @@ SECTION_DESC = {
|
|||||||
"supported in this mode.\n"
|
"supported in this mode.\n"
|
||||||
"An useful command to map here is the hidden command leave_mode."),
|
"An useful command to map here is the hidden command leave_mode."),
|
||||||
'keybind.passthrough': (
|
'keybind.passthrough': (
|
||||||
"Keybindings for hint passthrough.\n"
|
"Keybindings for hint mode.\n"
|
||||||
|
"Since normal keypresses are passed through, only special keys are "
|
||||||
|
"supported in this mode.\n"
|
||||||
|
"An useful command to map here is the hidden command leave_mode."),
|
||||||
|
'keybind.command': (
|
||||||
|
"Keybindings for command mode.\n"
|
||||||
"Since normal keypresses are passed through, only special keys are "
|
"Since normal keypresses are passed through, only special keys are "
|
||||||
"supported in this mode.\n"
|
"supported in this mode.\n"
|
||||||
"An useful command to map here is the hidden command leave_mode."),
|
"An useful command to map here is the hidden command leave_mode."),
|
||||||
@ -448,6 +453,15 @@ DATA = OrderedDict([
|
|||||||
('<Escape>', 'leave_mode'),
|
('<Escape>', 'leave_mode'),
|
||||||
)),
|
)),
|
||||||
|
|
||||||
|
('keybind.command', sect.ValueList(
|
||||||
|
types.KeyBindingName(), types.KeyBinding(),
|
||||||
|
('<Escape>', 'leave_mode'),
|
||||||
|
('<Up>', 'command_history_prev'),
|
||||||
|
('<Down>', 'command_history_next'),
|
||||||
|
('<Shift-Tab>', 'command_item_prev'),
|
||||||
|
('<Tab>', 'command_item_next'),
|
||||||
|
)),
|
||||||
|
|
||||||
('aliases', sect.ValueList(
|
('aliases', sect.ValueList(
|
||||||
types.Command(), types.Command(),
|
types.Command(), types.Command(),
|
||||||
)),
|
)),
|
||||||
|
@ -199,6 +199,30 @@ class CompletionView(QTreeView):
|
|||||||
logging.debug("No completion model for {}.".format(compl))
|
logging.debug("No completion model for {}.".format(compl))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _next_prev_item(self, prev):
|
||||||
|
"""Handle a tab press for the CompletionView.
|
||||||
|
|
||||||
|
Select the previous/next item and write the new text to the
|
||||||
|
statusbar.
|
||||||
|
|
||||||
|
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
|
||||||
|
return
|
||||||
|
idx = self._next_idx(prev)
|
||||||
|
self.selectionModel().setCurrentIndex(
|
||||||
|
idx, QItemSelectionModel.ClearAndSelect |
|
||||||
|
QItemSelectionModel.Rows)
|
||||||
|
data = self._model.data(idx)
|
||||||
|
if data is not None:
|
||||||
|
self._ignore_next = True
|
||||||
|
self.change_completed_part.emit(data)
|
||||||
|
|
||||||
def set_model(self, model):
|
def set_model(self, model):
|
||||||
"""Switch completion to a new model.
|
"""Switch completion to a new model.
|
||||||
|
|
||||||
@ -265,31 +289,6 @@ class CompletionView(QTreeView):
|
|||||||
if self._enabled:
|
if self._enabled:
|
||||||
self.show()
|
self.show()
|
||||||
|
|
||||||
@pyqtSlot(bool)
|
|
||||||
def on_tab_pressed(self, shift):
|
|
||||||
"""Handle a tab press for the CompletionView.
|
|
||||||
|
|
||||||
Select the previous/next item and write the new text to the
|
|
||||||
statusbar. Called by key_(s)tab_handler in statusbar.command.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
shift: Whether shift is pressed or not.
|
|
||||||
|
|
||||||
Emit:
|
|
||||||
change_completed_part: When a completion took place.
|
|
||||||
"""
|
|
||||||
if not self._completing:
|
|
||||||
# No completion running at the moment, ignore keypress
|
|
||||||
return
|
|
||||||
idx = self._next_idx(shift)
|
|
||||||
self.selectionModel().setCurrentIndex(
|
|
||||||
idx, QItemSelectionModel.ClearAndSelect |
|
|
||||||
QItemSelectionModel.Rows)
|
|
||||||
data = self._model.data(idx)
|
|
||||||
if data is not None:
|
|
||||||
self._ignore_next = True
|
|
||||||
self.change_completed_part.emit(data)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def on_clear_completion_selection(self):
|
def on_clear_completion_selection(self):
|
||||||
"""Clear the selection model when an item is activated."""
|
"""Clear the selection model when an item is activated."""
|
||||||
@ -298,6 +297,16 @@ class CompletionView(QTreeView):
|
|||||||
selmod.clearSelection()
|
selmod.clearSelection()
|
||||||
selmod.clearCurrentIndex()
|
selmod.clearCurrentIndex()
|
||||||
|
|
||||||
|
@cmdutils.register(instance='mainwindow.completion')
|
||||||
|
def command_item_prev(self):
|
||||||
|
"""Select the previous completion item."""
|
||||||
|
self._next_prev_item(prev=True)
|
||||||
|
|
||||||
|
@cmdutils.register(instance='mainwindow.completion')
|
||||||
|
def command_item_next(self):
|
||||||
|
"""Select the next completion item."""
|
||||||
|
self._next_prev_item(prev=False)
|
||||||
|
|
||||||
|
|
||||||
class _CompletionItemDelegate(QStyledItemDelegate):
|
class _CompletionItemDelegate(QStyledItemDelegate):
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ from PyQt5.QtWidgets import (QWidget, QLineEdit, QProgressBar, QLabel,
|
|||||||
from PyQt5.QtGui import QPainter, QKeySequence, QValidator
|
from PyQt5.QtGui import QPainter, QKeySequence, QValidator
|
||||||
|
|
||||||
import qutebrowser.keyinput.modes as modes
|
import qutebrowser.keyinput.modes as modes
|
||||||
|
import qutebrowser.commands.utils as cmdutils
|
||||||
from qutebrowser.keyinput.normalmode import STARTCHARS
|
from qutebrowser.keyinput.normalmode import STARTCHARS
|
||||||
from qutebrowser.config.style import set_register_stylesheet, get_stylesheet
|
from qutebrowser.config.style import set_register_stylesheet, get_stylesheet
|
||||||
from qutebrowser.utils.url import urlstring
|
from qutebrowser.utils.url import urlstring
|
||||||
@ -214,7 +215,6 @@ class _Command(QLineEdit):
|
|||||||
Attributes:
|
Attributes:
|
||||||
history: The command history object.
|
history: The command history object.
|
||||||
_statusbar: The statusbar (parent) QWidget.
|
_statusbar: The statusbar (parent) QWidget.
|
||||||
_shortcuts: Defined QShortcuts to prevent GCing.
|
|
||||||
_validator: The current command validator.
|
_validator: The current command validator.
|
||||||
|
|
||||||
Signals:
|
Signals:
|
||||||
@ -224,9 +224,6 @@ class _Command(QLineEdit):
|
|||||||
arg: The search term.
|
arg: The search term.
|
||||||
got_rev_search: Emitted when the user started a new reverse search.
|
got_rev_search: Emitted when the user started a new reverse search.
|
||||||
arg: The search term.
|
arg: The search term.
|
||||||
esc_pressed: Emitted when the escape key was pressed.
|
|
||||||
tab_pressed: Emitted when the tab key was pressed.
|
|
||||||
arg: Whether shift has been pressed.
|
|
||||||
clear_completion_selection: Emitted before the completion widget is
|
clear_completion_selection: Emitted before the completion widget is
|
||||||
hidden.
|
hidden.
|
||||||
hide_completion: Emitted when the completion widget should be hidden.
|
hide_completion: Emitted when the completion widget should be hidden.
|
||||||
@ -237,8 +234,6 @@ class _Command(QLineEdit):
|
|||||||
got_cmd = pyqtSignal(str)
|
got_cmd = pyqtSignal(str)
|
||||||
got_search = pyqtSignal(str)
|
got_search = pyqtSignal(str)
|
||||||
got_search_rev = pyqtSignal(str)
|
got_search_rev = pyqtSignal(str)
|
||||||
esc_pressed = pyqtSignal()
|
|
||||||
tab_pressed = pyqtSignal(bool)
|
|
||||||
clear_completion_selection = pyqtSignal()
|
clear_completion_selection = pyqtSignal()
|
||||||
hide_completion = pyqtSignal()
|
hide_completion = pyqtSignal()
|
||||||
show_cmd = pyqtSignal()
|
show_cmd = pyqtSignal()
|
||||||
@ -264,44 +259,6 @@ class _Command(QLineEdit):
|
|||||||
self.returnPressed.connect(self._on_return_pressed)
|
self.returnPressed.connect(self._on_return_pressed)
|
||||||
self.textEdited.connect(self.history.stop)
|
self.textEdited.connect(self.history.stop)
|
||||||
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored)
|
self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Ignored)
|
||||||
self._shortcuts = []
|
|
||||||
for (key, handler) in [
|
|
||||||
(Qt.Key_Escape, self.esc_pressed),
|
|
||||||
(Qt.Key_Up, self._on_key_up_pressed),
|
|
||||||
(Qt.Key_Down, self._on_key_down_pressed),
|
|
||||||
(Qt.Key_Tab | Qt.SHIFT, lambda: self.tab_pressed.emit(True)),
|
|
||||||
(Qt.Key_Tab, lambda: self.tab_pressed.emit(False))
|
|
||||||
]:
|
|
||||||
sc = QShortcut(self)
|
|
||||||
sc.setKey(QKeySequence(key))
|
|
||||||
sc.setContext(Qt.WidgetWithChildrenShortcut)
|
|
||||||
sc.activated.connect(handler)
|
|
||||||
self._shortcuts.append(sc)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _on_key_up_pressed(self):
|
|
||||||
"""Handle Up presses (go back in history)."""
|
|
||||||
try:
|
|
||||||
if not self.history.browsing:
|
|
||||||
item = self.history.start(self.text().strip())
|
|
||||||
else:
|
|
||||||
item = self.history.previtem()
|
|
||||||
except (HistoryEmptyError, HistoryEndReachedError):
|
|
||||||
return
|
|
||||||
if item:
|
|
||||||
self.set_cmd_text(item)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _on_key_down_pressed(self):
|
|
||||||
"""Handle Down presses (go forward in history)."""
|
|
||||||
if not self.history.browsing:
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
item = self.history.nextitem()
|
|
||||||
except HistoryEndReachedError:
|
|
||||||
return
|
|
||||||
if item:
|
|
||||||
self.set_cmd_text(item)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _on_return_pressed(self):
|
def _on_return_pressed(self):
|
||||||
@ -355,6 +312,31 @@ class _Command(QLineEdit):
|
|||||||
self.setFocus()
|
self.setFocus()
|
||||||
self.show_cmd.emit()
|
self.show_cmd.emit()
|
||||||
|
|
||||||
|
@cmdutils.register(instance='mainwindow.status.cmd', hide=True)
|
||||||
|
def command_history_prev(self):
|
||||||
|
"""Handle Up presses (go back in history)."""
|
||||||
|
try:
|
||||||
|
if not self.history.browsing:
|
||||||
|
item = self.history.start(self.text().strip())
|
||||||
|
else:
|
||||||
|
item = self.history.previtem()
|
||||||
|
except (HistoryEmptyError, HistoryEndReachedError):
|
||||||
|
return
|
||||||
|
if item:
|
||||||
|
self.set_cmd_text(item)
|
||||||
|
|
||||||
|
@cmdutils.register(instance='mainwindow.status.cmd', hide=True)
|
||||||
|
def command_history_next(self):
|
||||||
|
"""Handle Down presses (go forward in history)."""
|
||||||
|
if not self.history.browsing:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
item = self.history.nextitem()
|
||||||
|
except HistoryEndReachedError:
|
||||||
|
return
|
||||||
|
if item:
|
||||||
|
self.set_cmd_text(item)
|
||||||
|
|
||||||
def focusInEvent(self, e):
|
def focusInEvent(self, e):
|
||||||
"""Extend focusInEvent to enter command mode."""
|
"""Extend focusInEvent to enter command mode."""
|
||||||
modes.enter("command")
|
modes.enter("command")
|
||||||
@ -368,6 +350,8 @@ class _Command(QLineEdit):
|
|||||||
- Clear completion selection
|
- Clear completion selection
|
||||||
- Hide completion
|
- Hide completion
|
||||||
|
|
||||||
|
FIXME we should rather do this on on_mode_left...
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
e: The QFocusEvent.
|
e: The QFocusEvent.
|
||||||
|
|
||||||
@ -375,7 +359,7 @@ class _Command(QLineEdit):
|
|||||||
clear_completion_selection: Always emitted.
|
clear_completion_selection: Always emitted.
|
||||||
hide_completion: Always emitted so the completion is hidden.
|
hide_completion: Always emitted so the completion is hidden.
|
||||||
"""
|
"""
|
||||||
modes.leave("command")
|
modes.maybe_leave("command")
|
||||||
if e.reason() in [Qt.MouseFocusReason, Qt.TabFocusReason,
|
if e.reason() in [Qt.MouseFocusReason, Qt.TabFocusReason,
|
||||||
Qt.BacktabFocusReason, Qt.OtherFocusReason]:
|
Qt.BacktabFocusReason, Qt.OtherFocusReason]:
|
||||||
self.setText('')
|
self.setText('')
|
||||||
|
@ -343,6 +343,12 @@ class TabbedBrowser(TabWidget):
|
|||||||
else:
|
else:
|
||||||
logging.debug('ignoring title change')
|
logging.debug('ignoring title change')
|
||||||
|
|
||||||
|
@pyqtSlot(str)
|
||||||
|
def on_mode_left(self, mode):
|
||||||
|
"""Focus tabs if command mode was left."""
|
||||||
|
if mode == "command":
|
||||||
|
self.setFocus()
|
||||||
|
|
||||||
def resizeEvent(self, e):
|
def resizeEvent(self, e):
|
||||||
"""Extend resizeEvent of QWidget to emit a resized signal afterwards.
|
"""Extend resizeEvent of QWidget to emit a resized signal afterwards.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user