Example #1
0
 def to_py(self, value):
     self._basic_py_validation(value, str)
     if not value:
         return None
     if utils.is_special_key(value):
         value = '<{}>'.format(utils.normalize_keystr(value[1:-1]))
     return value
Example #2
0
    def __init__(self, parent=None):
        super().__init__(parent)
        assert cmdutils.cmd_dict
        cmdlist = []
        for obj in set(cmdutils.cmd_dict.values()):
            if (obj.hide or (obj.debug and not objreg.get('args').debug) or
                    obj.deprecated):
                pass
            else:
                cmdlist.append((obj.name, obj.desc))
        for name, cmd in config.section('aliases').items():
            cmdlist.append((name, "Alias for '{}'".format(cmd)))
        cat = self.new_category("Commands")

        # map each command to its bound keys and show these in the misc column
        keyconf = objreg.get('key-config')
        cmd_to_keys = defaultdict(list)
        for key, cmd in keyconf.get_bindings_for('normal').items():
            # put special bindings last
            if utils.is_special_key(key):
                cmd_to_keys[cmd].append(key)
            else:
                cmd_to_keys[cmd].insert(0, key)
        for (name, desc) in sorted(cmdlist):
            self.new_item(cat, name, desc, ', '.join(cmd_to_keys[name]))
Example #3
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setStyleSheet("""
            background-color: rgba(50, 50, 50, 80%);
            color: white;
            border-radius: 20px;
            padding: 30px;
        """)

        all_bindings = config.key_instance.get_reverse_bindings_for('normal')
        bindings = all_bindings.get('fullscreen --leave')
        if bindings:
            key = bindings[0]
            if utils.is_special_key(key):
                key = key.strip('<>').capitalize()
            self.setText("Press {} to exit fullscreen.".format(key))
        else:
            self.setText("Page is now fullscreen.")

        self.resize(self.sizeHint())
        if config.val.content.windowed_fullscreen:
            geom = self.parentWidget().geometry()
        else:
            geom = QApplication.desktop().screenGeometry(self)
        self.move((geom.width() - self.sizeHint().width()) / 2, 30)
Example #4
0
 def to_py(self, value):
     self._basic_py_validation(value, str)
     if not value:
         return None
     if utils.is_special_key(value):
         value = '<{}>'.format(utils.normalize_keystr(value[1:-1]))
     return value
Example #5
0
    def bind(self, key, command=None, *, mode='normal'):
        """Bind a key to a command.

        Args:
            key: The keychain or special key (inside `<...>`) to bind.
            command: The command to execute, with optional args, or None to
                     print the current binding.
            mode: A comma-separated list of modes to bind the key in
                  (default: `normal`). See `:help bindings.commands` for the
                  available modes.
        """
        if command is None:
            if utils.is_special_key(key):
                # self._keyconfig.get_command does this, but we also need it
                # normalized for the output below
                key = utils.normalize_keystr(key)
            cmd = self._keyconfig.get_command(key, mode)
            if cmd is None:
                message.info("{} is unbound in {} mode".format(key, mode))
            else:
                message.info("{} is bound to '{}' in {} mode".format(
                    key, cmd, mode))
            return

        try:
            self._keyconfig.bind(key, command, mode=mode, save_yaml=True)
        except configexc.KeybindingError as e:
            raise cmdexc.CommandError("bind: {}".format(e))
Example #6
0
 def _prepare(self, key, mode):
     """Make sure the given mode exists and normalize the key."""
     if mode not in configdata.DATA['bindings.default'].default:
         raise configexc.KeybindingError("Invalid mode {}!".format(mode))
     if utils.is_special_key(key):
         # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
         return utils.normalize_keystr(key)
     return key
Example #7
0
 def _prepare(self, key, mode):
     """Make sure the given mode exists and normalize the key."""
     if mode not in configdata.DATA['bindings.default'].default:
         raise configexc.KeybindingError("Invalid mode {}!".format(mode))
     if utils.is_special_key(key):
         # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
         return utils.normalize_keystr(key)
     return key
Example #8
0
    def update_keyhint(self, modename, prefix):
        """Show hints for the given prefix (or hide if prefix is empty).

        Args:
            prefix: The current partial keystring.
        """
        countstr, prefix = re.match(r'^(\d*)(.*)', prefix).groups()
        if not prefix:
            self._show_timer.stop()
            self.hide()
            return

        def blacklisted(keychain):
            return any(fnmatch.fnmatchcase(keychain, glob)
                       for glob in config.val.keyhint.blacklist)

        def takes_count(cmdstr):
            """Return true iff this command can take a count argument."""
            cmdname = cmdstr.split(' ')[0]
            cmd = cmdutils.cmd_dict.get(cmdname)
            return cmd and cmd.takes_count()

        bindings_dict = config.key_instance.get_bindings_for(modename)
        bindings = [(k, v) for (k, v) in sorted(bindings_dict.items())
                    if k.startswith(prefix) and
                    not utils.is_special_key(k) and
                    not blacklisted(k) and
                    (takes_count(v) or not countstr)]

        if not bindings:
            self._show_timer.stop()
            return

        # delay so a quickly typed keychain doesn't display hints
        self._show_timer.setInterval(config.val.keyhint.delay)
        self._show_timer.start()
        suffix_color = html.escape(config.val.colors.keyhint.suffix.fg)

        text = ''
        for key, cmd in bindings:
            text += (
                "<tr>"
                "<td>{}</td>"
                "<td style='color: {}'>{}</td>"
                "<td style='padding-left: 2ex'>{}</td>"
                "</tr>"
            ).format(
                html.escape(prefix),
                suffix_color,
                html.escape(key[len(prefix):]),
                html.escape(cmd)
            )
        text = '<table>{}</table>'.format(text)

        self.setText(text)
        self.adjustSize()
        self.update_geometry.emit()
    def update_keyhint(self, modename, prefix):
        """Show hints for the given prefix (or hide if prefix is empty).

        Args:
            prefix: The current partial keystring.
        """
        countstr, prefix = re.fullmatch(r'(\d*)(.*)', prefix).groups()
        if not prefix:
            self._show_timer.stop()
            self.hide()
            return

        def blacklisted(keychain):
            return any(fnmatch.fnmatchcase(keychain, glob)
                       for glob in config.val.keyhint.blacklist)

        def takes_count(cmdstr):
            """Return true iff this command can take a count argument."""
            cmdname = cmdstr.split(' ')[0]
            cmd = cmdutils.cmd_dict.get(cmdname)
            return cmd and cmd.takes_count()

        bindings_dict = config.key_instance.get_bindings_for(modename)
        bindings = [(k, v) for (k, v) in sorted(bindings_dict.items())
                    if k.startswith(prefix) and
                    not utils.is_special_key(k) and
                    not blacklisted(k) and
                    (takes_count(v) or not countstr)]

        if not bindings:
            self._show_timer.stop()
            return

        # delay so a quickly typed keychain doesn't display hints
        self._show_timer.setInterval(config.val.keyhint.delay)
        self._show_timer.start()
        suffix_color = html.escape(config.val.colors.keyhint.suffix.fg)

        text = ''
        for key, cmd in bindings:
            text += (
                "<tr>"
                "<td>{}</td>"
                "<td style='color: {}'>{}</td>"
                "<td style='padding-left: 2ex'>{}</td>"
                "</tr>"
            ).format(
                html.escape(prefix),
                suffix_color,
                html.escape(key[len(prefix):]),
                html.escape(cmd)
            )
        text = '<table>{}</table>'.format(text)

        self.setText(text)
        self.adjustSize()
        self.update_geometry.emit()
Example #10
0
 def _parse_key_command(self, modename, key, cmd):
     """Parse the keys and their command and store them in the object."""
     if utils.is_special_key(key):
         self.special_bindings[key[1:-1]] = cmd
     elif self._supports_chains:
         self.bindings[key] = cmd
     elif self._warn_on_keychains:
         log.keyboard.warning("Ignoring keychain '{}' in mode '{}' because "
                              "keychains are not supported there."
                              .format(key, modename))
Example #11
0
 def get_reverse_bindings_for(self, section):
     """Get a dict of commands to a list of bindings for the section."""
     cmd_to_keys = collections.defaultdict(list)
     for key, cmd in self.bindings[section].items():
         # put special bindings last
         if utils.is_special_key(key):
             cmd_to_keys[cmd].append(key)
         else:
             cmd_to_keys[cmd].insert(0, key)
     return cmd_to_keys
Example #12
0
 def _parse_key_command(self, modename, key, cmd):
     """Parse the keys and their command and store them in the object."""
     if utils.is_special_key(key):
         self.special_bindings[key[1:-1]] = cmd
     elif self._supports_chains:
         self.bindings[key] = cmd
     elif self._warn_on_keychains:
         log.keyboard.warning("Ignoring keychain '{}' in mode '{}' because "
                              "keychains are not supported there.".format(
                                  key, modename))
Example #13
0
 def get_reverse_bindings_for(self, section):
     """Get a dict of commands to a list of bindings for the section."""
     cmd_to_keys = {}
     for key, cmd in self.get_bindings_for(section).items():
         cmd_to_keys.setdefault(cmd, [])
         # put special bindings last
         if utils.is_special_key(key):
             cmd_to_keys[cmd].append(key)
         else:
             cmd_to_keys[cmd].insert(0, key)
     return cmd_to_keys
Example #14
0
 def get_reverse_bindings_for(self, section):
     """Get a dict of commands to a list of bindings for the section."""
     cmd_to_keys = {}
     for key, cmd in self.get_bindings_for(section).items():
         cmd_to_keys.setdefault(cmd, [])
         # put special bindings last
         if utils.is_special_key(key):
             cmd_to_keys[cmd].append(key)
         else:
             cmd_to_keys[cmd].insert(0, key)
     return cmd_to_keys
    def bind(self,
             win_id,
             key=None,
             command=None,
             *,
             mode='normal',
             default=False):
        """Bind a key to a command.

        If no command is given, show the current binding for the given key.
        Using :bind without any arguments opens a page showing all keybindings.

        Args:
            key: The keychain or special key (inside `<...>`) to bind.
            command: The command to execute, with optional args.
            mode: A comma-separated list of modes to bind the key in
                  (default: `normal`). See `:help bindings.commands` for the
                  available modes.
            default: If given, restore a default binding.
        """
        if key is None:
            tabbed_browser = objreg.get('tabbed-browser',
                                        scope='window',
                                        window=win_id)
            tabbed_browser.openurl(QUrl('qute://bindings'), newtab=True)
            return

        if command is None:
            if default:
                # :bind --default: Restore default
                with self._handle_config_error():
                    self._keyconfig.bind_default(key,
                                                 mode=mode,
                                                 save_yaml=True)
                return

            # No --default -> print binding
            if utils.is_special_key(key):
                # self._keyconfig.get_command does this, but we also need it
                # normalized for the output below
                key = utils.normalize_keystr(key)
            with self._handle_config_error():
                cmd = self._keyconfig.get_command(key, mode)
            if cmd is None:
                message.info("{} is unbound in {} mode".format(key, mode))
            else:
                message.info("{} is bound to '{}' in {} mode".format(
                    key, cmd, mode))
            return

        with self._handle_config_error():
            self._keyconfig.bind(key, command, mode=mode, save_yaml=True)
    def update_keyhint(self, modename, prefix):
        """Show hints for the given prefix (or hide if prefix is empty).

        Args:
            prefix: The current partial keystring.
        """
        if not prefix:
            self._show_timer.stop()
            self.hide()
            return

        blacklist = config.get('ui', 'keyhint-blacklist') or []
        keyconf = objreg.get('key-config')

        def blacklisted(keychain):
            return any(fnmatch.fnmatchcase(keychain, glob)
                       for glob in blacklist)

        bindings = [(k, v) for (k, v)
                    in keyconf.get_bindings_for(modename).items()
                    if k.startswith(prefix) and not utils.is_special_key(k) and
                    not blacklisted(k)]

        if not bindings:
            self._show_timer.stop()
            return

        # delay so a quickly typed keychain doesn't display hints
        self._show_timer.setInterval(config.get('ui', 'keyhint-delay'))
        self._show_timer.start()
        suffix_color = html.escape(config.get('colors', 'keyhint.fg.suffix'))

        text = ''
        for key, cmd in bindings:
            text += (
                "<tr>"
                "<td>{}</td>"
                "<td style='color: {}'>{}</td>"
                "<td style='padding-left: 2ex'>{}</td>"
                "</tr>"
            ).format(
                html.escape(prefix),
                suffix_color,
                html.escape(key[len(prefix):]),
                html.escape(cmd)
            )
        text = '<table>{}</table>'.format(text)

        self.setText(text)
        self.adjustSize()
        self.update_geometry.emit()
Example #17
0
 def get_reverse_bindings_for(self, mode):
     """Get a dict of commands to a list of bindings for the mode."""
     cmd_to_keys = {}
     bindings = self.get_bindings_for(mode)
     for key, full_cmd in sorted(bindings.items()):
         for cmd in full_cmd.split(';;'):
             cmd = cmd.strip()
             cmd_to_keys.setdefault(cmd, [])
             # put special bindings last
             if utils.is_special_key(key):
                 cmd_to_keys[cmd].append(key)
             else:
                 cmd_to_keys[cmd].insert(0, key)
     return cmd_to_keys
Example #18
0
    def update_keyhint(self, modename, prefix):
        """Show hints for the given prefix (or hide if prefix is empty).

        Args:
            prefix: The current partial keystring.
        """
        if not prefix:
            self._show_timer.stop()
            self.hide()
            return

        blacklist = config.get('ui', 'keyhint-blacklist') or []
        keyconf = objreg.get('key-config')

        def blacklisted(keychain):
            return any(fnmatch.fnmatchcase(keychain, glob)
                       for glob in blacklist)

        bindings = [(k, v) for (k, v)
                    in keyconf.get_bindings_for(modename).items()
                    if k.startswith(prefix) and not utils.is_special_key(k) and
                    not blacklisted(k)]

        if not bindings:
            self._show_timer.stop()
            return

        # delay so a quickly typed keychain doesn't display hints
        self._show_timer.start()
        suffix_color = html.escape(config.get('colors', 'keyhint.fg.suffix'))

        text = ''
        for key, cmd in bindings:
            text += (
                "<tr>"
                "<td>{}</td>"
                "<td style='color: {}'>{}</td>"
                "<td style='padding-left: 2ex'>{}</td>"
                "</tr>"
            ).format(
                html.escape(prefix),
                suffix_color,
                html.escape(key[len(prefix):]),
                html.escape(cmd)
            )
        text = '<table>{}</table>'.format(text)

        self.setText(text)
        self.adjustSize()
        self.update_geometry.emit()
Example #19
0
 def get_reverse_bindings_for(self, mode):
     """Get a dict of commands to a list of bindings for the mode."""
     cmd_to_keys = {}
     bindings = self.get_bindings_for(mode)
     for key, full_cmd in sorted(bindings.items()):
         for cmd in full_cmd.split(';;'):
             cmd = cmd.strip()
             cmd_to_keys.setdefault(cmd, [])
             # put special bindings last
             if utils.is_special_key(key):
                 cmd_to_keys[cmd].append(key)
             else:
                 cmd_to_keys[cmd].insert(0, key)
     return cmd_to_keys
Example #20
0
    def _is_new(self, sectname, command, keychain):
        """Check if a given binding is new.

        A binding is considered new if both the command is not bound to any key
        yet, and the key isn't used anywhere else in the same section.
        """
        if utils.is_special_key(keychain):
            keychain = keychain.lower()

        try:
            bindings = self.keybindings[sectname]
        except KeyError:
            return True
        if keychain in bindings:
            return False
        else:
            return command not in bindings.values()
Example #21
0
    def _is_new(self, sectname, command, keychain):
        """Check if a given binding is new.

        A binding is considered new if both the command is not bound to any key
        yet, and the key isn't used anywhere else in the same section.
        """
        if utils.is_special_key(keychain):
            keychain = keychain.lower()

        try:
            bindings = self.keybindings[sectname]
        except KeyError:
            return True
        if keychain in bindings:
            return False
        else:
            return command not in bindings.values()
Example #22
0
    def bind(self, key, win_id, command=None, *, mode='normal', force=False):
        """Bind a key to a command.

        Args:
            key: The keychain or special key (inside `<...>`) to bind.
            command: The command to execute, with optional args, or None to
                     print the current binding.
            mode: A comma-separated list of modes to bind the key in
                  (default: `normal`).
            force: Rebind the key if it is already bound.
        """
        if utils.is_special_key(key):
            # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
            key = key.lower()

        if command is None:
            cmd = self.get_bindings_for(mode).get(key, None)
            if cmd is None:
                message.info(win_id,
                             "{} is unbound in {} mode".format(key, mode))
            else:
                message.info(
                    win_id,
                    "{} is bound to '{}' in {} mode".format(key, cmd, mode))
            return

        mode = self._normalize_sectname(mode)
        for m in mode.split(','):
            if m not in configdata.KEY_DATA:
                raise cmdexc.CommandError("Invalid mode {}!".format(m))
        try:
            self._validate_command(command)
        except KeyConfigError as e:
            raise cmdexc.CommandError(str(e))
        try:
            self._add_binding(mode, key, command, force=force)
        except DuplicateKeychainError as e:
            raise cmdexc.CommandError("Duplicate keychain {} - use --force to "
                                      "override!".format(str(e.keychain)))
        except KeyConfigError as e:
            raise cmdexc.CommandError(e)
        for m in mode.split(','):
            self.changed.emit(m)
            self._mark_config_dirty()
Example #23
0
    def bind(self, key, win_id, command=None, *, mode='normal', force=False):
        """Bind a key to a command.

        Args:
            key: The keychain or special key (inside `<...>`) to bind.
            command: The command to execute, with optional args, or None to
                     print the current binding.
            mode: A comma-separated list of modes to bind the key in
                  (default: `normal`).
            force: Rebind the key if it is already bound.
        """
        if utils.is_special_key(key):
            # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
            key = key.lower()

        if command is None:
            cmd = self.get_bindings_for(mode).get(key, None)
            if cmd is None:
                message.info(win_id, "{} is unbound in {} mode".format(
                    key, mode))
            else:
                message.info(win_id, "{} is bound to '{}' in {} mode".format(
                    key, cmd, mode))
            return

        mode = self._normalize_sectname(mode)
        for m in mode.split(','):
            if m not in configdata.KEY_DATA:
                raise cmdexc.CommandError("Invalid mode {}!".format(m))
        try:
            self._validate_command(command)
        except KeyConfigError as e:
            raise cmdexc.CommandError(str(e))
        try:
            self._add_binding(mode, key, command, force=force)
        except DuplicateKeychainError as e:
            raise cmdexc.CommandError("Duplicate keychain {} - use --force to "
                                      "override!".format(str(e.keychain)))
        except KeyConfigError as e:
            raise cmdexc.CommandError(e)
        for m in mode.split(','):
            self.changed.emit(m)
            self._mark_config_dirty()
Example #24
0
 def _add_binding(self, sectname, keychain, command, *, force=False):
     """Add a new binding from keychain to command in section sectname."""
     if utils.is_special_key(keychain):
         # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
         keychain = keychain.lower()
     log.keyboard.vdebug("Adding binding {} -> {} in mode {}.".format(
         keychain, command, sectname))
     if sectname not in self.keybindings:
         self.keybindings[sectname] = collections.OrderedDict()
     if keychain in self.get_bindings_for(sectname):
         if force or command == self.UNBOUND_COMMAND:
             self.unbind(keychain, mode=sectname)
         else:
             raise DuplicateKeychainError(keychain)
     section = self.keybindings[sectname]
     if (command != self.UNBOUND_COMMAND and
             section.get(keychain, None) == self.UNBOUND_COMMAND):
         # re-binding an unbound keybinding
         del section[keychain]
     self.keybindings[sectname][keychain] = command
Example #25
0
 def _add_binding(self, sectname, keychain, command, *, force=False):
     """Add a new binding from keychain to command in section sectname."""
     if utils.is_special_key(keychain):
         # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
         keychain = keychain.lower()
     log.keyboard.vdebug("Adding binding {} -> {} in mode {}.".format(
         keychain, command, sectname))
     if sectname not in self.keybindings:
         self.keybindings[sectname] = collections.OrderedDict()
     if keychain in self.get_bindings_for(sectname):
         if force or command == self.UNBOUND_COMMAND:
             self.unbind(keychain, mode=sectname)
         else:
             raise DuplicateKeychainError(keychain)
     section = self.keybindings[sectname]
     if (command != self.UNBOUND_COMMAND
             and section.get(keychain, None) == self.UNBOUND_COMMAND):
         # re-binding an unbound keybinding
         del section[keychain]
     self.keybindings[sectname][keychain] = command
Example #26
0
    def update_keyhint(self, modename, prefix):
        """Show hints for the given prefix (or hide if prefix is empty).

        Args:
            prefix: The current partial keystring.
        """
        if not prefix or not self._enabled:
            self.hide()
            return

        keyconf = objreg.get('key-config')
        bindings = [(k, v) for (k, v)
                    in keyconf.get_bindings_for(modename).items()
                    if k.startswith(prefix) and not utils.is_special_key(k)]

        if not bindings:
            return

        self.show()
        suffix_color = html.escape(config.get('colors', 'keyhint.fg.suffix'))

        text = ''
        for key, cmd in bindings:
            text += (
                "<tr>"
                "<td>{}</td>"
                "<td style='color: {}'>{}</td>"
                "<td style='padding-left: 2ex'>{}</td>"
                "</tr>"
            ).format(
                html.escape(prefix),
                suffix_color,
                html.escape(key[len(prefix):]),
                html.escape(cmd)
            )
        text = '<table>{}</table>'.format(text)

        self.setText(text)
        self.adjustSize()
        self.reposition_keyhint.emit()
Example #27
0
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setStyleSheet("""
            background-color: rgba(50, 50, 50, 80%);
            color: white;
            border-radius: 20px;
            padding: 30px;
        """)

        all_bindings = config.key_instance.get_reverse_bindings_for('normal')
        bindings = all_bindings.get('fullscreen --leave')
        if bindings:
            key = bindings[0]
            if utils.is_special_key(key):
                key = key.strip('<>').capitalize()
            self.setText("Press {} to exit fullscreen.".format(key))
        else:
            self.setText("Page is now fullscreen.")

        self.resize(self.sizeHint())
        geom = QApplication.desktop().screenGeometry(self)
        self.move((geom.width() - self.sizeHint().width()) / 2, 30)
Example #28
0
    def bind(self, key, command=None, *, mode='normal', default=False):
        """Bind a key to a command.

        Args:
            key: The keychain or special key (inside `<...>`) to bind.
            command: The command to execute, with optional args, or None to
                     print the current binding.
            mode: A comma-separated list of modes to bind the key in
                  (default: `normal`). See `:help bindings.commands` for the
                  available modes.
            default: If given, restore a default binding.
        """
        if command is None:
            if default:
                # :bind --default: Restore default
                with self._handle_config_error():
                    self._keyconfig.bind_default(key,
                                                 mode=mode,
                                                 save_yaml=True)
                return

            # No --default -> print binding
            if utils.is_special_key(key):
                # self._keyconfig.get_command does this, but we also need it
                # normalized for the output below
                key = utils.normalize_keystr(key)
            with self._handle_config_error():
                cmd = self._keyconfig.get_command(key, mode)
            if cmd is None:
                message.info("{} is unbound in {} mode".format(key, mode))
            else:
                message.info("{} is bound to '{}' in {} mode".format(
                    key, cmd, mode))
            return

        with self._handle_config_error():
            self._keyconfig.bind(key, command, mode=mode, save_yaml=True)
Example #29
0
    def unbind(self, key, mode='normal'):
        """Unbind a keychain.

        Args:
            key: The keychain or special key (inside <...>) to unbind.
            mode: A comma-separated list of modes to unbind the key in
                  (default: `normal`).
        """
        if utils.is_special_key(key):
            # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
            key = key.lower()

        mode = self._normalize_sectname(mode)
        for m in mode.split(','):
            if m not in configdata.KEY_DATA:
                raise cmdexc.CommandError("Invalid mode {}!".format(m))
        try:
            sect = self.keybindings[mode]
        except KeyError:
            raise cmdexc.CommandError("Can't find mode section '{}'!".format(
                mode))
        try:
            del sect[key]
        except KeyError:
            raise cmdexc.CommandError("Can't find binding '{}' in section "
                                      "'{}'!".format(key, mode))
        else:
            if key in itertools.chain.from_iterable(
                    configdata.KEY_DATA[mode].values()):
                try:
                    self._add_binding(mode, key, self.UNBOUND_COMMAND)
                except DuplicateKeychainError:
                    pass
            for m in mode.split(','):
                self.changed.emit(m)
            self._mark_config_dirty()
Example #30
0
    def unbind(self, key, mode='normal'):
        """Unbind a keychain.

        Args:
            key: The keychain or special key (inside <...>) to unbind.
            mode: A comma-separated list of modes to unbind the key in
                  (default: `normal`).
        """
        if utils.is_special_key(key):
            # <Ctrl-t>, <ctrl-T>, and <ctrl-t> should be considered equivalent
            key = key.lower()

        mode = self._normalize_sectname(mode)
        for m in mode.split(','):
            if m not in configdata.KEY_DATA:
                raise cmdexc.CommandError("Invalid mode {}!".format(m))
        try:
            sect = self.keybindings[mode]
        except KeyError:
            raise cmdexc.CommandError(
                "Can't find mode section '{}'!".format(mode))
        try:
            del sect[key]
        except KeyError:
            raise cmdexc.CommandError("Can't find binding '{}' in section "
                                      "'{}'!".format(key, mode))
        else:
            if key in itertools.chain.from_iterable(
                    configdata.KEY_DATA[mode].values()):
                try:
                    self._add_binding(mode, key, self.UNBOUND_COMMAND)
                except DuplicateKeychainError:
                    pass
            for m in mode.split(','):
                self.changed.emit(m)
            self._mark_config_dirty()