First kinda working version
This commit is contained in:
parent
97ae3adb4a
commit
af0b6901be
@ -54,7 +54,8 @@ from qutebrowser.widgets.mainwindow import MainWindow
|
||||
from qutebrowser.widgets.crash import CrashDialog
|
||||
from qutebrowser.commands.keys import KeyParser
|
||||
from qutebrowser.utils.appdirs import AppDirs
|
||||
from qutebrowser.utils.misc import set_trace
|
||||
from qutebrowser.utils.misc import dotted_getattr
|
||||
from qutebrowser.utils.debug import set_trace
|
||||
|
||||
|
||||
class QuteBrowser(QApplication):
|
||||
@ -180,6 +181,14 @@ class QuteBrowser(QApplication):
|
||||
Registers all commands, connects its signals, and sets up keyparser.
|
||||
|
||||
"""
|
||||
for key, cmd in sorted(cmdutils.cmd_dict.items()):
|
||||
cmd.signal.connect(self.command_handler)
|
||||
if cmd.instance is not None:
|
||||
func = '.'.join([cmd.instance if cmd.instance else 'app',
|
||||
cmd.handler.__name__])
|
||||
else:
|
||||
func = cmd.handler.__name__
|
||||
logging.debug("Registered command: {} -> {}".format(key, func))
|
||||
self.keyparser.from_config_sect(config.config['keybind'])
|
||||
|
||||
def _process_init_args(self):
|
||||
@ -322,7 +331,7 @@ class QuteBrowser(QApplication):
|
||||
logging.debug("maybe_quit quitting.")
|
||||
self.quit()
|
||||
|
||||
@cmdutils.register(instance='app', split_args=False)
|
||||
@cmdutils.register(instance='', split_args=False)
|
||||
def pyeval(self, s):
|
||||
"""Evaluate a python string and display the results as a webpage.
|
||||
|
||||
@ -340,7 +349,7 @@ class QuteBrowser(QApplication):
|
||||
qutescheme.pyeval_output = out
|
||||
self.mainwindow.tabs.cur.openurl('qute:pyeval')
|
||||
|
||||
@cmdutils.register(instance='app', hide=True)
|
||||
@cmdutils.register(instance='', hide=True)
|
||||
def crash(self):
|
||||
"""Crash for debugging purposes.
|
||||
|
||||
@ -353,7 +362,7 @@ class QuteBrowser(QApplication):
|
||||
raise Exception("Forced crash")
|
||||
|
||||
@pyqtSlot()
|
||||
@cmdutils.register(instance='app', name=['q', 'quit'], nargs=0)
|
||||
@cmdutils.register(instance='', name=['q', 'quit'], nargs=0)
|
||||
def shutdown(self, do_quit=True):
|
||||
"""Try to shutdown everything cleanly.
|
||||
|
||||
@ -399,3 +408,28 @@ class QuteBrowser(QApplication):
|
||||
"""
|
||||
logging.debug("Shutdown complete, quitting.")
|
||||
self.quit()
|
||||
|
||||
@pyqtSlot(tuple)
|
||||
def command_handler(self, tpl):
|
||||
"""Handle commands which need an instance..
|
||||
|
||||
Args:
|
||||
tpl: An (instance, func, count, args) tuple.
|
||||
instance: How to get the current instance of the target object
|
||||
from app.py, as a dotted string, e.g.
|
||||
'mainwindow.tabs.cur'.
|
||||
func: The function name to be called (as string).
|
||||
count: The count given to the command, or None.
|
||||
args: A list of arguments given to the command.
|
||||
|
||||
"""
|
||||
(instance, func, count, args) = tpl
|
||||
if instance == '':
|
||||
obj = self
|
||||
else:
|
||||
obj = dotted_getattr(self, instance)
|
||||
handler = getattr(obj, func)
|
||||
if count is not None:
|
||||
handler(*args, count=count)
|
||||
else:
|
||||
handler(*args)
|
||||
|
@ -21,8 +21,10 @@ import logging
|
||||
|
||||
from qutebrowser.commands.exceptions import ArgumentCountError
|
||||
|
||||
from PyQt5.QtCore import pyqtSignal, QObject
|
||||
|
||||
class Command:
|
||||
|
||||
class Command(QObject):
|
||||
|
||||
"""Base skeleton for a command.
|
||||
|
||||
@ -31,11 +33,14 @@ class Command:
|
||||
|
||||
"""
|
||||
|
||||
signal = pyqtSignal(tuple)
|
||||
|
||||
# FIXME:
|
||||
# we should probably have some kind of typing / argument casting for args
|
||||
# this might be combined with help texts or so as well
|
||||
|
||||
def __init__(self, name, split_args, hide, nargs, count, desc, handler):
|
||||
def __init__(self, name, split_args, hide, nargs, count, desc, instance,
|
||||
handler):
|
||||
super().__init__()
|
||||
self.name = name
|
||||
self.split_args = split_args
|
||||
@ -43,6 +48,7 @@ class Command:
|
||||
self.nargs = nargs
|
||||
self.count = count
|
||||
self.desc = desc
|
||||
self.instance = instance
|
||||
self.handler = handler
|
||||
|
||||
def check(self, args):
|
||||
@ -78,7 +84,13 @@ class Command:
|
||||
dbgout.append("(count={})".format(count))
|
||||
logging.debug(' '.join(dbgout))
|
||||
|
||||
if count is not None and self.count:
|
||||
if self.instance is not None and self.count and count is not None:
|
||||
self.signal.emit((self.instance, self.handler.__name__, count,
|
||||
args))
|
||||
elif self.instance is not None:
|
||||
self.signal.emit((self.instance, self.handler.__name__, None,
|
||||
args))
|
||||
elif count is not None and self.count:
|
||||
return self.handler(*args, count=count)
|
||||
else:
|
||||
return self.handler(*args)
|
@ -1,32 +0,0 @@
|
||||
# Copyright 2014 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
|
||||
#
|
||||
# This file is part of qutebrowser.
|
||||
#
|
||||
# qutebrowser is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# qutebrowser is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""All command classes.
|
||||
|
||||
These are automatically propagated from commands.utils
|
||||
via inspect.
|
||||
|
||||
A command class can set the following properties:
|
||||
|
||||
nargs -- Number of arguments. Either a number, '?' (0 or 1), '+' (1 or
|
||||
more), or '*' (any). Default: 0
|
||||
name -- The name of the command, or a list of aliases.
|
||||
split_args -- If arguments should be split or not. Default: True
|
||||
count -- If the command supports a count. Default: False
|
||||
hide -- If the command should be hidden in tab completion. Default: False
|
||||
|
||||
"""
|
@ -15,7 +15,7 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
"""Exception classes for commands.utils and commands.template.
|
||||
"""Exception classes for commands.utils and commands.command.
|
||||
|
||||
Defined here to avoid circular dependency hell.
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
import shlex
|
||||
import inspect
|
||||
import logging
|
||||
import functools
|
||||
|
||||
from PyQt5.QtCore import pyqtSlot, pyqtSignal, QObject
|
||||
@ -26,7 +27,7 @@ from PyQt5.QtWidgets import QApplication
|
||||
from PyQt5.QtWebKitWidgets import QWebPage
|
||||
|
||||
import qutebrowser.config.config as config
|
||||
from qutebrowser.commands.template import Command
|
||||
from qutebrowser.commands.command import Command
|
||||
from qutebrowser.commands.exceptions import (ArgumentCountError,
|
||||
NoSuchCommandError)
|
||||
|
||||
@ -62,12 +63,9 @@ class register:
|
||||
names += name
|
||||
count, nargs = self._get_nargs_count(func)
|
||||
desc = func.__doc__.splitlines()[0].strip().rstrip('.')
|
||||
if self.instance is not None:
|
||||
handler = functools.partial(func, instance])
|
||||
else:
|
||||
handler = func
|
||||
cmd = Command(mainname, self.split_args, self.hide, nargs, count, desc,
|
||||
handler=handler)
|
||||
cmd = Command(name=mainname, split_args=self.split_args,
|
||||
hide=self.hide, nargs=nargs, count=count, desc=desc,
|
||||
instance=self.instance, handler=func)
|
||||
for name in names:
|
||||
cmd_dict[name] = cmd
|
||||
return func
|
||||
|
@ -17,37 +17,11 @@
|
||||
|
||||
"""Other utilities which don't fit anywhere else."""
|
||||
|
||||
import sys
|
||||
import os.path
|
||||
|
||||
from PyQt5.QtCore import pyqtRemoveInputHook
|
||||
|
||||
#import qutebrowser.commands.utils as cmdutils
|
||||
|
||||
try:
|
||||
# pylint: disable=import-error
|
||||
from ipdb import set_trace as pdb_set_trace
|
||||
except ImportError:
|
||||
from pdb import set_trace as pdb_set_trace
|
||||
from functools import reduce
|
||||
|
||||
import qutebrowser
|
||||
|
||||
# FIXME we can';t do this because of circular imports
|
||||
#@cmdutils.register(name='settrace', hide=True)
|
||||
def set_trace():
|
||||
"""Set a tracepoint in the Python debugger that works with Qt.
|
||||
|
||||
Based on http://stackoverflow.com/a/1745965/2085149
|
||||
|
||||
"""
|
||||
print()
|
||||
print("When done debugging, remember to execute:")
|
||||
print(" from PyQt5 import QtCore; QtCore.pyqtRestoreInputHook()")
|
||||
print("before executing c(ontinue).")
|
||||
pyqtRemoveInputHook()
|
||||
return pdb_set_trace()
|
||||
|
||||
|
||||
def read_file(filename):
|
||||
"""Get the contents of a file contained with qutebrowser.
|
||||
|
||||
@ -63,19 +37,15 @@ def read_file(filename):
|
||||
return f.read()
|
||||
|
||||
|
||||
def trace_lines(do_trace):
|
||||
"""Turn on/off printing each executed line.
|
||||
def dotted_getattr(obj, path):
|
||||
"""getattr supporting the dot notation.
|
||||
|
||||
Args:
|
||||
do_trace: Whether to start tracing (True) or stop it (False).
|
||||
obj: The object where to start.
|
||||
path: A dotted object path as a string.
|
||||
|
||||
Return:
|
||||
The object at path.
|
||||
|
||||
"""
|
||||
def trace(frame, event, _):
|
||||
"""Trace function passed to sys.settrace."""
|
||||
print("{}, {}:{}".format(event, frame.f_code.co_filename,
|
||||
frame.f_lineno))
|
||||
return trace
|
||||
if do_trace:
|
||||
sys.settrace(trace)
|
||||
else:
|
||||
sys.settrace(None)
|
||||
return reduce(getattr, path.split('.'), obj)
|
||||
|
Loading…
Reference in New Issue
Block a user