Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Raphael Pierzina 2015-04-04 11:12:39 +02:00
commit dd4096b5a4
10 changed files with 71 additions and 47 deletions

View File

@ -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' ...]+

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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():

View File

@ -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'),
]

View File

@ -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."""

View File

@ -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))

View File

@ -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:

View File

@ -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):