This commit is contained in:
Florian Bruhin 2018-02-27 09:33:50 +01:00
parent f18b5aa782
commit 362f923f06
8 changed files with 51 additions and 34 deletions

View File

@ -26,7 +26,7 @@ from PyQt5.QtCore import QUrl
from qutebrowser.commands import cmdexc, cmdutils
from qutebrowser.completion.models import configmodel
from qutebrowser.utils import objreg, utils, message, standarddir, urlmatch
from qutebrowser.utils import objreg, message, standarddir, urlmatch
from qutebrowser.config import configtypes, configexc, configfiles, configdata
from qutebrowser.misc import editor
from qutebrowser.keyinput import keyutils

View File

@ -20,8 +20,6 @@
"""Base class for vim-like key sequence parser."""
import enum
import re
import unicodedata
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtGui import QKeySequence
@ -148,7 +146,8 @@ class BaseKeyParser(QObject):
sequence = self._sequence.append_event(e)
match, binding = self._match_key(sequence)
if match == QKeySequence.NoMatch:
mapped = config.val.bindings.key_mappings.get(sequence, None)
mappings = config.val.bindings.key_mappings
mapped = mappings.get(sequence, None)
if mapped is not None:
match, binding = self._match_key(mapped)
@ -241,13 +240,13 @@ class BaseKeyParser(QObject):
assert cmd
self.bindings[key] = cmd
def _parse_key_command(self, modename, key, cmd):
"""Parse the keys and their command and store them in the object."""
# FIXME
# elif self._warn_on_keychains:
# log.keyboard.warning("Ignoring keychain '{}' in mode '{}' because "
# "keychains are not supported there."
# .format(key, modename))
# FIXME
# def _parse_key_command(self, modename, key, cmd):
# """Parse the keys and their command and store them in the object."""
# elif self._warn_on_keychains:
# log.keyboard.warning("Ignoring keychain '{}' in mode '{}' "
# "because keychains are not supported there."
# .format(key, modename))
def execute(self, cmdstr, keytype, count=None):
"""Handle a completed keychain.

View File

@ -27,7 +27,7 @@ import attr
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtGui import QKeySequence, QKeyEvent
from qutebrowser.utils import utils, debug
from qutebrowser.utils import utils
def key_to_string(key):
@ -209,8 +209,8 @@ class KeyInfo:
an empty string if only modifiers are pressed.
"""
if utils.is_mac:
# Qt swaps Ctrl/Meta on macOS, so we switch it back here so the user
# can use it in the config as expected. See:
# Qt swaps Ctrl/Meta on macOS, so we switch it back here so the
# user can use it in the config as expected. See:
# https://github.com/qutebrowser/qutebrowser/issues/110
# http://doc.qt.io/qt-5.4/osx-issues.html#special-keys
modmask2str = collections.OrderedDict([
@ -228,9 +228,9 @@ class KeyInfo:
])
modifier_keys = (Qt.Key_Control, Qt.Key_Alt, Qt.Key_Shift, Qt.Key_Meta,
Qt.Key_AltGr, Qt.Key_Super_L, Qt.Key_Super_R,
Qt.Key_Hyper_L, Qt.Key_Hyper_R, Qt.Key_Direction_L,
Qt.Key_Direction_R)
Qt.Key_AltGr, Qt.Key_Super_L, Qt.Key_Super_R,
Qt.Key_Hyper_L, Qt.Key_Hyper_R, Qt.Key_Direction_L,
Qt.Key_Direction_R)
if self.key in modifier_keys:
# Only modifier pressed
return ''
@ -285,6 +285,18 @@ class KeyInfo:
class KeySequence:
"""A sequence of key presses.
This internally uses chained QKeySequence objects and exposes a nicer
interface over it.
Attributes:
_sequences: A list of QKeySequence
Class attributes:
_MAX_LEN: The maximum amount of keys in a QKeySequence.
"""
_MAX_LEN = 4
def __init__(self, *keys):
@ -293,7 +305,7 @@ class KeySequence:
sequence = QKeySequence(*sub)
self._sequences.append(sequence)
if keys:
assert len(self) > 0
assert self
self._validate()
def __str__(self):
@ -316,15 +328,19 @@ class KeySequence:
return utils.get_repr(self, keys=str(self))
def __lt__(self, other):
# pylint: disable=protected-access
return self._sequences < other._sequences
def __gt__(self, other):
# pylint: disable=protected-access
return self._sequences > other._sequences
def __eq__(self, other):
# pylint: disable=protected-access
return self._sequences == other._sequences
def __ne__(self, other):
# pylint: disable=protected-access
return self._sequences != other._sequences
def __hash__(self):
@ -334,6 +350,9 @@ class KeySequence:
def __len__(self):
return sum(len(seq) for seq in self._sequences)
def __bool__(self):
return bool(self._sequences)
def __getitem__(self, item):
if isinstance(item, slice):
keys = list(self._iter_keys())
@ -351,6 +370,7 @@ class KeySequence:
raise KeyParseError(keystr, "Got unknown key!")
def matches(self, other):
"""Check whether the given KeySequence matches with this one."""
# FIXME test this
# pylint: disable=protected-access
assert self._sequences
@ -369,16 +389,16 @@ class KeySequence:
We don't care about a shift modifier with symbols (Shift-: should match
a : binding even though we typed it with a shift on an US-keyboard)
However, we *do* care about Shift being involved if we got an upper-case
letter, as Shift-A should match a Shift-A binding, but not an "a"
binding.
However, we *do* care about Shift being involved if we got an
upper-case letter, as Shift-A should match a Shift-A binding, but not
an "a" binding.
In addition, Shift also *is* relevant when other modifiers are involved.
In addition, Shift also *is* relevant when other modifiers are
involved.
Shift-Ctrl-X should not be equivalent to Ctrl-X.
FIXME: create test cases!
"""
# pylint: disable=protected-access
modifiers = ev.modifiers()
if (modifiers == Qt.ShiftModifier and
@ -394,6 +414,7 @@ class KeySequence:
@classmethod
def parse(cls, keystr):
"""Parse a keystring like <Ctrl-x> or xyz and return a KeySequence."""
# pylint: disable=protected-access
# FIXME: test stuff like <a, a>
new = cls()
strings = list(_parse_keystring(keystr))
@ -402,7 +423,8 @@ class KeySequence:
new._sequences.append(sequence)
if keystr:
assert len(new) > 0, keystr
assert new, keystr
# pylint: disable=protected-access
new._validate(keystr)
return new

View File

@ -30,7 +30,6 @@ import re
from PyQt5.QtWidgets import QLabel, QSizePolicy
from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt
from PyQt5.QtGui import QKeySequence
from qutebrowser.config import config
from qutebrowser.utils import utils, usertypes

View File

@ -26,18 +26,15 @@ import re
import sys
import enum
import json
import collections
import datetime
import traceback
import functools
import contextlib
import socket
import shlex
import unicodedata
import attr
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtGui import QKeySequence, QColor, QClipboard, QDesktopServices
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor, QClipboard, QDesktopServices
from PyQt5.QtWidgets import QApplication
import pkg_resources
import yaml
@ -49,7 +46,7 @@ except ImportError: # pragma: no cover
YAML_C_EXT = False
import qutebrowser
from qutebrowser.utils import qtutils, log, debug
from qutebrowser.utils import qtutils, log
fake_clipboard = None

View File

@ -18,7 +18,6 @@
"""Tests for qutebrowser.config.config."""
import copy
import types
import unittest.mock

View File

@ -203,7 +203,8 @@ class TestSpecialKeys:
assert not keyparser.execute.called
def test_no_binding(self, monkeypatch, fake_keyevent_factory, keyparser):
monkeypatch.setattr(keyutils, 'keyevent_to_string', lambda binding: None)
monkeypatch.setattr(keyutils, 'keyevent_to_string',
lambda binding: None)
keyparser.handle(fake_keyevent_factory(Qt.Key_A, Qt.NoModifier))
assert not keyparser.execute.called

View File

@ -30,7 +30,7 @@ import re
import shlex
import attr
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor, QClipboard
import pytest