Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
dd4096b5a4
@ -463,13 +463,16 @@ If the option name ends with '?', the value of the option is shown instead. If t
|
||||
|
||||
[[set-cmd-text]]
|
||||
=== set-cmd-text
|
||||
Syntax: +:set-cmd-text 'text'+
|
||||
Syntax: +:set-cmd-text [*--space*] 'text'+
|
||||
|
||||
Preset the statusbar to some text.
|
||||
|
||||
==== positional arguments
|
||||
* +'text'+: The commandline to set.
|
||||
|
||||
==== optional arguments
|
||||
* +*-s*+, +*--space*+: If given, a space is added to the end.
|
||||
|
||||
[[spawn]]
|
||||
=== spawn
|
||||
Syntax: +:spawn [*--userscript*] 'args' ['args' ...]+
|
||||
|
@ -1332,7 +1332,7 @@ Default: +pass:[\bprev(ious)?\b,\bback\b,\bolder\b,\b[<←≪]\b,\b(<<|
|
||||
|
||||
== searchengines
|
||||
Definitions of search engines which can be used via the address bar.
|
||||
The searchengine named `DEFAULT` is used when `general -> auto-search` is true and something else than a URL was entered to be opened. Other search engines can be used via the bang-syntax, e.g. `:open qutebrowser !google`. The string `{}` will be replaced by the search term, use `{{` and `}}` for literal `{`/`}` signs.
|
||||
The searchengine named `DEFAULT` is used when `general -> auto-search` is true and something else than a URL was entered to be opened. Other search engines can be used by prepending the search engine name to the search term, e.g. `:open google qutebrowser`. The string `{}` will be replaced by the search term, use `{{` and `}}` for literal `{`/`}` signs.
|
||||
|
||||
== aliases
|
||||
Aliases for commands.
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
"""Module containing command managers (SearchRunner and CommandRunner)."""
|
||||
|
||||
import re
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject, QUrl
|
||||
from PyQt5.QtWebKitWidgets import QWebPage
|
||||
|
||||
@ -266,16 +264,8 @@ class CommandRunner(QObject):
|
||||
else:
|
||||
self._args = []
|
||||
maxsplit = i + self._cmd.maxsplit + flag_arg_count
|
||||
args = split.simple_split(argstr, keep=keep,
|
||||
maxsplit=maxsplit)
|
||||
for s in args:
|
||||
# remove quotes and replace \" by "
|
||||
if s == '""' or s == "''":
|
||||
s = ''
|
||||
else:
|
||||
s = re.sub(r"""(^|[^\\])["']""", r'\1', s)
|
||||
s = re.sub(r"""\\(["'])""", r'\1', s)
|
||||
self._args.append(s)
|
||||
self._args = split.simple_split(argstr, keep=keep,
|
||||
maxsplit=maxsplit)
|
||||
break
|
||||
else:
|
||||
# If there are only flags, we got it right on the first try
|
||||
|
@ -196,7 +196,13 @@ class Completer(QObject):
|
||||
data = model.data(indexes[0])
|
||||
if data is None:
|
||||
return
|
||||
data = self._quote(data)
|
||||
parts = self.split()
|
||||
try:
|
||||
needs_quoting = cmdutils.cmd_dict[parts[0]].maxsplit is None
|
||||
except KeyError:
|
||||
needs_quoting = True
|
||||
if needs_quoting:
|
||||
data = self._quote(data)
|
||||
if model.count() == 1 and config.get('completion', 'quick-complete'):
|
||||
# If we only have one item, we want to apply it immediately
|
||||
# and go on to the next part.
|
||||
|
@ -171,8 +171,9 @@ def _init_key_config():
|
||||
save_manager = objreg.get('save-manager')
|
||||
filename = os.path.join(standarddir.config(), 'keys.conf')
|
||||
save_manager.add_saveable(
|
||||
'key-config', key_config.save, key_config.changed,
|
||||
config_opt=('general', 'auto-save-config'), filename=filename)
|
||||
'key-config', key_config.save, key_config.config_dirty,
|
||||
config_opt=('general', 'auto-save-config'), filename=filename,
|
||||
dirty=key_config.is_dirty)
|
||||
|
||||
|
||||
def _init_misc():
|
||||
|
@ -80,10 +80,10 @@ SECTION_DESC = {
|
||||
"bar.\n"
|
||||
"The searchengine named `DEFAULT` is used when "
|
||||
"`general -> auto-search` is true and something else than a URL was "
|
||||
"entered to be opened. Other search engines can be used via the "
|
||||
"bang-syntax, e.g. `:open qutebrowser !google`. The string `{}` will "
|
||||
"be replaced by the search term, use `{{` and `}}` for literal "
|
||||
"`{`/`}` signs."),
|
||||
"entered to be opened. Other search engines can be used by prepending "
|
||||
"the search engine name to the search term, e.g. "
|
||||
"`:open google qutebrowser`. The string `{}` will be replaced by the "
|
||||
"search term, use `{{` and `}}` for literal `{`/`}` signs."),
|
||||
'aliases': (
|
||||
"Aliases for commands.\n"
|
||||
"By default, no aliases are defined. Example which adds a new command "
|
||||
@ -1029,14 +1029,14 @@ KEY_DATA = collections.OrderedDict([
|
||||
|
||||
('normal', collections.OrderedDict([
|
||||
('search ""', ['<Escape>']),
|
||||
('set-cmd-text ":open "', ['o']),
|
||||
('set-cmd-text ":open {url}"', ['go']),
|
||||
('set-cmd-text ":open -t "', ['O']),
|
||||
('set-cmd-text ":open -t {url}"', ['gO']),
|
||||
('set-cmd-text ":open -b "', ['xo']),
|
||||
('set-cmd-text ":open -b {url}"', ['xO']),
|
||||
('set-cmd-text ":open -w "', ['wo']),
|
||||
('set-cmd-text ":open -w {url}"', ['wO']),
|
||||
('set-cmd-text -s :open', ['o']),
|
||||
('set-cmd-text :open {url}', ['go']),
|
||||
('set-cmd-text -s :open -t', ['O']),
|
||||
('set-cmd-text :open -t {url}', ['gO']),
|
||||
('set-cmd-text -s :open -b', ['xo']),
|
||||
('set-cmd-text :open -b {url}', ['xO']),
|
||||
('set-cmd-text -s :open -w', ['wo']),
|
||||
('set-cmd-text :open -w {url}', ['wO']),
|
||||
('open -t', ['ga']),
|
||||
('tab-close', ['d', '<Ctrl-W>']),
|
||||
('tab-close -o', ['D']),
|
||||
@ -1181,13 +1181,14 @@ KEY_DATA = collections.OrderedDict([
|
||||
])
|
||||
|
||||
|
||||
# A dict of {old_cmd: new_cmd} strings.
|
||||
# A list of (regex, replacement) tuples of changed key commands.
|
||||
|
||||
CHANGED_KEY_COMMNADS = {
|
||||
'open -t about:blank': 'open -t',
|
||||
'open -b about:blank': 'open -b',
|
||||
'open -w about:blank': 'open -w',
|
||||
'download-page': 'download',
|
||||
'cancel-download': 'download-cancel',
|
||||
'search ""': 'search',
|
||||
}
|
||||
CHANGED_KEY_COMMANDS = [
|
||||
(re.compile(r'^open -([twb]) about:blank$'), r'open -\1'),
|
||||
(re.compile(r'^download-page$'), r'download'),
|
||||
(re.compile(r'^cancel-download$'), r'download-cancel'),
|
||||
(re.compile(r'^search ""$'), r'search'),
|
||||
(re.compile(r"^search ''$"), r'search'),
|
||||
(re.compile(r"""^set-cmd-text ['"](.*) ['"]$"""), r'set-cmd-text -s \1'),
|
||||
(re.compile(r"""^set-cmd-text ['"](.*)['"]$"""), r'set-cmd-text \1'),
|
||||
]
|
||||
|
@ -55,13 +55,16 @@ class KeyConfigParser(QObject):
|
||||
_configfile: The filename of the config or None.
|
||||
_cur_section: The section currently being processed by _read().
|
||||
_cur_command: The command currently being processed by _read().
|
||||
is_dirty: Whether the config is currently dirty.
|
||||
|
||||
Signals:
|
||||
changed: Emitted when the config has changed.
|
||||
changed: Emitted when the internal data has changed.
|
||||
arg: Name of the mode which was changed.
|
||||
config_dirty: Emitted when the config should be re-saved.
|
||||
"""
|
||||
|
||||
changed = pyqtSignal(str)
|
||||
config_dirty = pyqtSignal()
|
||||
|
||||
def __init__(self, configdir, fname, parent=None):
|
||||
"""Constructor.
|
||||
@ -71,6 +74,7 @@ class KeyConfigParser(QObject):
|
||||
fname: The filename of the config.
|
||||
"""
|
||||
super().__init__(parent)
|
||||
self.is_dirty = False
|
||||
self._cur_section = None
|
||||
self._cur_command = None
|
||||
# Mapping of section name(s) to key binding -> command dicts.
|
||||
@ -165,6 +169,7 @@ class KeyConfigParser(QObject):
|
||||
raise cmdexc.CommandError(e)
|
||||
for m in mode.split(','):
|
||||
self.changed.emit(m)
|
||||
self._mark_config_dirty()
|
||||
|
||||
@cmdutils.register(instance='key-config')
|
||||
def unbind(self, key, mode=None):
|
||||
@ -194,6 +199,7 @@ class KeyConfigParser(QObject):
|
||||
else:
|
||||
for m in mode.split(','):
|
||||
self.changed.emit(m)
|
||||
self._mark_config_dirty()
|
||||
|
||||
def _normalize_sectname(self, s):
|
||||
"""Normalize a section string like 'foo, bar,baz' to 'bar,baz,foo'."""
|
||||
@ -246,6 +252,11 @@ class KeyConfigParser(QObject):
|
||||
for sectname in self.keybindings:
|
||||
self.changed.emit(sectname)
|
||||
|
||||
def _mark_config_dirty(self):
|
||||
"""Mark the config as dirty."""
|
||||
self.is_dirty = True
|
||||
self.config_dirty.emit()
|
||||
|
||||
def _read_command(self, line):
|
||||
"""Read a command from a line."""
|
||||
if self._cur_section is None:
|
||||
@ -255,7 +266,12 @@ class KeyConfigParser(QObject):
|
||||
command = line.split(maxsplit=1)[0]
|
||||
if command not in cmdutils.cmd_dict:
|
||||
raise KeyConfigError("Invalid command '{}'!".format(command))
|
||||
self._cur_command = configdata.CHANGED_KEY_COMMNADS.get(line, line)
|
||||
for rgx, repl in configdata.CHANGED_KEY_COMMANDS:
|
||||
if rgx.match(line):
|
||||
line = rgx.sub(repl, line)
|
||||
self._mark_config_dirty()
|
||||
break
|
||||
self._cur_command = line
|
||||
|
||||
def _read_keybinding(self, line):
|
||||
"""Read a key binding from a line."""
|
||||
|
@ -98,7 +98,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
|
||||
@cmdutils.register(instance='status-command', name='set-cmd-text',
|
||||
scope='window', maxsplit=0)
|
||||
def set_cmd_text_command(self, text):
|
||||
def set_cmd_text_command(self, text, space=False):
|
||||
"""Preset the statusbar to some text.
|
||||
|
||||
//
|
||||
@ -108,6 +108,7 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
|
||||
Args:
|
||||
text: The commandline to set.
|
||||
space: If given, a space is added to the end.
|
||||
"""
|
||||
tabbed_browser = objreg.get('tabbed-browser', scope='window',
|
||||
window=self._win_id)
|
||||
@ -127,6 +128,8 @@ class Command(misc.MinimalLineEditMixin, misc.CommandLineEdit):
|
||||
# I'm not sure what's the best thing to do here
|
||||
# https://github.com/The-Compiler/qutebrowser/issues/123
|
||||
text = text.replace('{url}', url)
|
||||
if space:
|
||||
text += ' '
|
||||
if not text or text[0] not in modeparsers.STARTCHARS:
|
||||
raise cmdexc.CommandError(
|
||||
"Invalid command text '{}'.".format(text))
|
||||
|
@ -93,7 +93,7 @@ class TabWidget(QTabWidget):
|
||||
|
||||
def set_page_title(self, idx, title):
|
||||
"""Set the tab title user data."""
|
||||
self.tabBar().set_tab_data(idx, 'page-title', title.replace('&', '&&'))
|
||||
self.tabBar().set_tab_data(idx, 'page-title', title)
|
||||
self.update_tab_title(idx)
|
||||
|
||||
def page_title(self, idx):
|
||||
@ -103,7 +103,7 @@ class TabWidget(QTabWidget):
|
||||
def update_tab_title(self, idx):
|
||||
"""Update the tab text for the given tab."""
|
||||
widget = self.widget(idx)
|
||||
page_title = self.page_title(idx)
|
||||
page_title = self.page_title(idx).replace('&', '&&')
|
||||
|
||||
fields = {}
|
||||
if widget.load_status == webview.LoadStatus.loading:
|
||||
|
@ -22,7 +22,7 @@
|
||||
import os.path
|
||||
import collections
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, QObject
|
||||
from PyQt5.QtCore import pyqtSlot, QObject, QTimer
|
||||
|
||||
from qutebrowser.config import config
|
||||
from qutebrowser.commands import cmdutils
|
||||
@ -139,7 +139,7 @@ class SaveManager(QObject):
|
||||
self._save_timer.start()
|
||||
|
||||
def add_saveable(self, name, save, changed=None, config_opt=None,
|
||||
filename=None):
|
||||
filename=None, dirty=False):
|
||||
"""Add a new saveable.
|
||||
|
||||
Args:
|
||||
@ -150,11 +150,15 @@ class SaveManager(QObject):
|
||||
or not.
|
||||
filename: The filename of the underlying file, so we can force
|
||||
saving if it doesn't exist.
|
||||
dirty: Whether the saveable is already dirty.
|
||||
"""
|
||||
if name in self.saveables:
|
||||
raise ValueError("Saveable {} already registered!".format(name))
|
||||
self.saveables[name] = Saveable(name, save, changed, config_opt,
|
||||
filename)
|
||||
saveable = Saveable(name, save, changed, config_opt, filename)
|
||||
self.saveables[name] = saveable
|
||||
if dirty:
|
||||
saveable.mark_dirty()
|
||||
QTimer.singleShot(0, saveable.save)
|
||||
|
||||
def save(self, name, is_exit=False, explicit=False, silent=False,
|
||||
force=False):
|
||||
|
Loading…
Reference in New Issue
Block a user