def later(ms: int, command: str, win_id: int) -> None: """Execute a command after some time. Args: ms: How many milliseconds to wait. command: The command to run, with optional args. """ if ms < 0: raise cmdutils.CommandError("I can't run something in the past!") commandrunner = runners.CommandRunner(win_id) app = objreg.get('app') timer = usertypes.Timer(name='later', parent=app) try: timer.setSingleShot(True) try: timer.setInterval(ms) except OverflowError: raise cmdutils.CommandError("Numeric argument is too large for " "internal int representation.") timer.timeout.connect( functools.partial(commandrunner.run_safely, command)) timer.timeout.connect(timer.deleteLater) timer.start() except: timer.deleteLater() raise
def run_async(tab, cmd, *args, win_id, env, verbose=False): """Run a userscript after dumping page html/source. Raises: UnsupportedError if userscripts are not supported on the current platform. NotFoundError if the command could not be found. Args: tab: The WebKitTab/WebEngineTab to get the source from. cmd: The userscript binary to run. *args: The arguments to pass to the userscript. win_id: The window id the userscript is executed in. env: A dictionary of variables to add to the process environment. verbose: Show notifications when the command started/exited. """ tabbed_browser = objreg.get('tabbed-browser', scope='window', window=win_id) commandrunner = runners.CommandRunner(win_id, parent=tabbed_browser) if utils.is_posix: runner = _POSIXUserscriptRunner(tabbed_browser) elif utils.is_windows: # pragma: no cover runner = _WindowsUserscriptRunner(tabbed_browser) else: # pragma: no cover raise UnsupportedError runner.got_cmd.connect(lambda cmd: log.commands.debug( "Got userscript command: {}".format(cmd))) runner.got_cmd.connect(commandrunner.run_safely) user_agent = config.val.content.headers.user_agent if user_agent is not None: env['QUTE_USER_AGENT'] = user_agent env['QUTE_CONFIG_DIR'] = standarddir.config() env['QUTE_DATA_DIR'] = standarddir.data() env['QUTE_DOWNLOAD_DIR'] = downloads.download_dir() env['QUTE_COMMANDLINE_TEXT'] = objreg.get('status-command', scope='window', window=win_id).text() cmd_path = os.path.expanduser(cmd) # if cmd is not given as an absolute path, look it up # ~/.local/share/glimpsebrowser/userscripts (or $XDG_DATA_HOME) if not os.path.isabs(cmd_path): log.misc.debug("{} is no absolute path".format(cmd_path)) cmd_path = _lookup_path(cmd) elif not os.path.exists(cmd_path): raise NotFoundError(cmd_path) log.misc.debug("Userscript to run: {}".format(cmd_path)) runner.finished.connect(commandrunner.deleteLater) runner.finished.connect(runner.deleteLater) runner.prepare_run(cmd_path, *args, env=env, verbose=verbose) tab.dump_async(runner.store_html) tab.dump_async(runner.store_text, plain=True) return runner
def spawn(self, url, context): """Spawn a simple command from a hint. Args: url: The URL to open as a QUrl. context: The HintContext to use. """ urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword) args = context.get_args(urlstr) commandrunner = runners.CommandRunner(self._win_id) commandrunner.run_safely('spawn ' + ' '.join(args))
def run_cmd(self, url, context): """Run the command based on a hint URL. Args: url: The URL to open as a QUrl. context: The HintContext to use. """ urlstr = url.toString(QUrl.FullyEncoded) args = context.get_args(urlstr) commandrunner = runners.CommandRunner(self._win_id) commandrunner.run_safely(' '.join(args))
def repeat_command(win_id, count=None): """Repeat the last executed command. Args: count: Which count to pass the command. """ mode_manager = objreg.get('mode-manager', scope='window', window=win_id) if mode_manager.mode not in runners.last_command: raise cmdutils.CommandError("You didn't do anything yet.") cmd = runners.last_command[mode_manager.mode] commandrunner = runners.CommandRunner(win_id) commandrunner.run(cmd[0], count if count is not None else cmd[1])
def run_with_count(count_arg: int, command: str, win_id: int, count: int = 1) -> None: """Run a command with the given count. If run_with_count itself is run with a count, it multiplies count_arg. Args: count_arg: The count to pass to the command. command: The command to run, with optional args. count: The count that run_with_count itself received. """ runners.CommandRunner(win_id).run(command, count_arg * count)
def run_macro(self, win_id, register): """Run a recorded macro.""" if register == '@': if self._last_register is None: raise cmdutils.CommandError("No previous macro") register = self._last_register self._last_register = register if register not in self._macros: raise cmdutils.CommandError( "No macro recorded in '{}'!".format(register)) commandrunner = runners.CommandRunner(win_id) for _ in range(self._macro_count[win_id]): for cmd in self._macros[register]: commandrunner.run_safely(*cmd)
def repeat(times: int, command: str, win_id: int, count: int = None) -> None: """Repeat a given command. Args: times: How many times to repeat. command: The command to run, with optional args. count: Multiplies with 'times' when given. """ if count is not None: times *= count if times < 0: raise cmdutils.CommandError("A negative count doesn't make sense.") commandrunner = runners.CommandRunner(win_id) for _ in range(times): commandrunner.run_safely(command)
def process_pos_args(args, via_ipc=False, cwd=None, target_arg=None): """Process positional commandline args. URLs to open have no prefix, commands to execute begin with a colon. Args: args: A list of arguments to process. via_ipc: Whether the arguments were transmitted over IPC. cwd: The cwd to use for fuzzy_url. target_arg: Command line argument received by a running instance via ipc. If the --target argument was not specified, target_arg will be an empty string. """ if via_ipc and not args: win_id = mainwindow.get_window(via_ipc, force_window=True) _open_startpage(win_id) return win_id = None for cmd in args: if cmd.startswith(':'): if win_id is None: win_id = mainwindow.get_window(via_ipc, force_tab=True) log.init.debug("Startup cmd {!r}".format(cmd)) commandrunner = runners.CommandRunner(win_id) commandrunner.run_safely(cmd[1:]) elif not cmd: log.init.debug("Empty argument") win_id = mainwindow.get_window(via_ipc, force_window=True) else: if via_ipc and target_arg and target_arg != 'auto': open_target = target_arg else: open_target = None if not cwd: # could also be an empty string due to the PyQt signal cwd = None try: url = urlutils.fuzzy_url(cmd, cwd, relative=True) except urlutils.InvalidUrlError as e: message.error("Error in startup argument '{}': {}".format( cmd, e)) else: win_id = open_url(url, target=open_target, via_ipc=via_ipc)
def __init__(self, *, private, geometry=None, parent=None): """Create a new main window. Args: geometry: The geometry to load, as a bytes-object (or None). private: Whether the window is in private browsing mode. parent: The parent the window should get. """ super().__init__(parent) # Late import to avoid a circular dependency # - browsertab -> hints -> webelem -> mainwindow -> bar -> browsertab from glimpsebrowser.mainwindow import tabbedbrowser from glimpsebrowser.mainwindow.statusbar import bar self.setAttribute(Qt.WA_DeleteOnClose) self._commandrunner = None self._overlays = [] self.win_id = next(win_id_gen) self.registry = objreg.ObjectRegistry() objreg.window_registry[self.win_id] = self objreg.register('main-window', self, scope='window', window=self.win_id) tab_registry = objreg.ObjectRegistry() objreg.register('tab-registry', tab_registry, scope='window', window=self.win_id) message_bridge = message.MessageBridge(self) objreg.register('message-bridge', message_bridge, scope='window', window=self.win_id) self.setWindowTitle('glimpsebrowser') self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) self._init_downloadmanager() self._downloadview = downloadview.DownloadView(self.win_id) if config.val.content.private_browsing: # This setting always trumps what's passed in. private = True else: private = bool(private) self._private = private self.tabbed_browser = tabbedbrowser.TabbedBrowser(win_id=self.win_id, private=private, parent=self) objreg.register('tabbed-browser', self.tabbed_browser, scope='window', window=self.win_id) self._init_command_dispatcher() # We need to set an explicit parent for StatusBar because it does some # show/hide magic immediately which would mean it'd show up as a # window. self.status = bar.StatusBar(win_id=self.win_id, private=private, parent=self) self._add_widgets() self._downloadview.show() self._init_completion() log.init.debug("Initializing modes...") modeman.init(self.win_id, self) self._commandrunner = runners.CommandRunner(self.win_id, partial_match=True) self._keyhint = keyhintwidget.KeyHintView(self.win_id, self) self._add_overlay(self._keyhint, self._keyhint.update_geometry) self._prompt_container = prompt.PromptContainer(self.win_id, self) self._add_overlay(self._prompt_container, self._prompt_container.update_geometry, centered=True, padding=10) objreg.register('prompt-container', self._prompt_container, scope='window', window=self.win_id) self._prompt_container.hide() self._messageview = messageview.MessageView(parent=self) self._add_overlay(self._messageview, self._messageview.update_geometry) self._init_geometry(geometry) self._connect_signals() # When we're here the statusbar might not even really exist yet, so # resizing will fail. Therefore, we use singleShot QTimers to make sure # we defer this until everything else is initialized. QTimer.singleShot(0, self._connect_overlay_signals) config.instance.changed.connect(self._on_config_changed) objreg.get("app").new_window.emit(self) self._set_decoration(config.val.window.hide_decoration) self.state_before_fullscreen = self.windowState() config.set_register_stylesheet(self)
def __init__(self, win_id, parent=None, supports_count=None): super().__init__(win_id, parent, supports_count) self._commandrunner = runners.CommandRunner(win_id)