Merge branch 'Carpetsmoker-jseval'

This commit is contained in:
Florian Bruhin 2015-06-12 11:46:23 +02:00
commit d2e103ecc1
6 changed files with 71 additions and 11 deletions

View File

@ -41,6 +41,7 @@ Added
- New setting `colors -> webpage.bg` to set the background color to use for websites which don't set one.
- New (hidden) command `:clear-keychain` to clear a partially entered keychain (bound to `<Escape>` by default, in addition to clearing search).
- Many new color settings (foreground setting for every background setting).
- New command `:jseval` to run a javascript snippet on the current page.
Changed
~~~~~~~

View File

@ -138,8 +138,8 @@ Contributors, sorted by the number of commits in descending order:
* Raphael Pierzina
* Joel Torstensson
* Claude
* Lamar Pavel
* Martin Tournoij
* Lamar Pavel
* Austin Anderson
* Artur Shaik
* Antoni Boucher

View File

@ -20,6 +20,7 @@
|<<hint,hint>>|Start hinting.
|<<home,home>>|Open main startpage in current tab.
|<<inspector,inspector>>|Toggle the web inspector.
|<<jseval,jseval>>|Evaluate a JavaScript string.
|<<later,later>>|Execute a command after some time.
|<<navigate,navigate>>|Open typical prev/next links or navigate using the URL path.
|<<open,open>>|Open a URL in the current/[count]th tab.
@ -241,6 +242,22 @@ Open main startpage in current tab.
=== inspector
Toggle the web inspector.
[[jseval]]
=== jseval
Syntax: +:jseval [*--quiet*] 'js-code'+
Evaluate a JavaScript string.
==== positional arguments
* +'js-code'+: The string to evaluate.
==== optional arguments
* +*-q*+, +*--quiet*+: Don't show resulting JS object.
==== note
* This command does not split arguments after the last argument and handles quotes literally.
* With this command, +;;+ is interpreted literally instead of splitting off a second command.
[[later]]
=== later
Syntax: +:later 'ms' 'command'+

View File

@ -1563,3 +1563,33 @@ class CommandDispatcher:
view = self._current_widget()
for _ in range(count):
view.triggerPageAction(member)
@cmdutils.register(instance='command-dispatcher', scope='window',
maxsplit=0, no_cmd_split=True)
def jseval(self, js_code, quiet=False):
"""Evaluate a JavaScript string.
Args:
js_code: The string to evaluate.
quiet: Don't show resulting JS object.
"""
frame = self._current_widget().page().mainFrame()
out = frame.evaluateJavaScript(js_code)
if quiet:
return
if out is None:
# Getting the actual error (if any) seems to be difficult. The
# error does end up in BrowserPage.javaScriptConsoleMessage(), but
# distinguishing between :jseval errors and errors from the webpage
# is not trivial...
message.info(self._win_id, 'No output or error')
else:
# The output can be a string, number, dict, array, etc. But *don't*
# output too much data, as this will make qutebrowser hang
out = str(out)
if len(out) > 5000:
message.info(self._win_id, out[:5000] + ' [...trimmed...]')
else:
message.info(self._win_id, out)

View File

@ -29,6 +29,11 @@ from qutebrowser.utils import log, utils, message, docutils, objreg, usertypes
from qutebrowser.utils import debug as debug_utils
def arg_name(name):
"""Get the name an argument should have based on its Python name."""
return name.rstrip('_').replace('_', '-')
class Command:
"""Base skeleton for a command.
@ -288,7 +293,7 @@ class Command:
A list of args.
"""
args = []
name = param.name.rstrip('_').replace('_', '-')
name = arg_name(param.name)
shortname = annotation_info.flag or name[0]
if len(shortname) != 1:
raise ValueError("Flag '{}' of parameter {} (command {}) must be "
@ -304,7 +309,7 @@ class Command:
if typ is not bool:
self.flags_with_args += [short_flag, long_flag]
else:
args.append(name)
args.append(param.name)
if not annotation_info.hide:
self.pos_args.append((param.name, name))
return args
@ -408,17 +413,16 @@ class Command:
raise TypeError("{}: invalid parameter type {} for argument "
"{!r}!".format(self.name, param.kind, param.name))
def _get_param_name_and_value(self, param):
"""Get the converted name and value for an inspect.Parameter."""
name = param.name.rstrip('_')
value = getattr(self.namespace, name)
def _get_param_value(self, param):
"""Get the converted value for an inspect.Parameter."""
value = getattr(self.namespace, param.name)
if param.name in self._type_conv:
# We convert enum types after getting the values from
# argparse, because argparse's choices argument is
# processed after type conversation, which is not what we
# want.
value = self._type_conv[param.name](value)
return name, value
return value
def _get_call_args(self, win_id):
"""Get arguments for a function call.
@ -452,14 +456,14 @@ class Command:
# Special case for win_id parameter.
self._get_win_id_arg(win_id, param, args, kwargs)
continue
name, value = self._get_param_name_and_value(param)
value = self._get_param_value(param)
if param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
args.append(value)
elif param.kind == inspect.Parameter.VAR_POSITIONAL:
if value is not None:
args += value
elif param.kind == inspect.Parameter.KEYWORD_ONLY:
kwargs[name] = value
kwargs[param.name] = value
else:
raise TypeError("{}: Invalid parameter type {} for argument "
"'{}'!".format(

View File

@ -37,7 +37,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
import qutebrowser.app
from scripts import asciidoc2html, utils
from qutebrowser import qutebrowser
from qutebrowser.commands import cmdutils
from qutebrowser.commands import cmdutils, command
from qutebrowser.config import configdata
from qutebrowser.utils import docutils
@ -54,6 +54,14 @@ class UsageFormatter(argparse.HelpFormatter):
"""Override _format_usage to not add the 'usage:' prefix."""
return super()._format_usage(usage, actions, groups, '')
def _get_default_metavar_for_optional(self, action):
"""Do name transforming when getting metavar."""
return command.arg_name(action.dest.upper())
def _get_default_metavar_for_positional(self, action):
"""Do name transforming when getting metavar."""
return command.arg_name(action.dest)
def _metavar_formatter(self, action, default_metavar):
"""Override _metavar_formatter to add asciidoc markup to metavars.