Allow running the launch actions by invoking the kitty executable with +open

This commit is contained in:
Kovid Goyal 2022-02-05 17:39:48 +05:30
parent ced61096df
commit 39c77a9486
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 56 additions and 15 deletions

View File

@ -42,6 +42,13 @@ def complete(args: List[str]) -> None:
complete_main(args[1:], entry_points, namespaced_entry_points)
def open_urls(args: List[str]) -> None:
setattr(sys, 'cmdline_args_for_open', True)
sys.argv = ['kitty'] + args[1:]
from kitty.main import main as kitty_main
kitty_main()
def launch(args: List[str]) -> None:
import runpy
sys.argv = args[1:]
@ -129,6 +136,7 @@ def namespaced(args: List[str]) -> None:
namespaced_entry_points['complete'] = complete
namespaced_entry_points['runpy'] = runpy
namespaced_entry_points['launch'] = launch
namespaced_entry_points['open'] = open_urls
namespaced_entry_points['kitten'] = run_kitten
namespaced_entry_points['edit-config'] = edit_config_file
namespaced_entry_points['shebang'] = shebang

View File

@ -114,6 +114,12 @@ URLs onto the kitty dock icon to open them with kitty. The default actions are:
* Run shell scripts in a shell
* Open SSH urls using the ssh command
These actions can also be executed from the command line by running::
open -a kitty.app file_or_url ... (on macOS only)
or
kitty +open file_or_url ...
You can customize these actions by creating a :file:`launch-actions.conf` file
in the kitty config directory, just like
the :file:`open-actions.conf` file above. For example:

View File

@ -5,12 +5,13 @@
import json
import os
import re
import sys
from contextlib import suppress
from functools import partial
from gettext import gettext as _
from typing import (
Any, Callable, Container, Dict, Iterable, Iterator, List, Optional, Tuple,
Union
Any, Callable, Container, Dict, Iterable, Iterator, List, Optional,
Sequence, Tuple, Union
)
from weakref import WeakValueDictionary
@ -273,8 +274,8 @@ def update_keymap(self) -> None:
for sc in self.global_shortcuts.values():
self.keymap.pop(sc, None)
def startup_first_child(self, os_window_id: Optional[int]) -> None:
startup_sessions = create_sessions(get_options(), self.args, default_session=get_options().startup_session)
def startup_first_child(self, os_window_id: Optional[int], startup_sessions: Sequence[Optional[Session]] = ()) -> None:
startup_sessions = startup_sessions or create_sessions(get_options(), self.args, default_session=get_options().startup_session)
for startup_session in startup_sessions:
self.add_os_window(startup_session, os_window_id=os_window_id)
os_window_id = None
@ -546,6 +547,10 @@ def peer_message_received(self, msg_bytes: bytes, peer_id: int) -> Union[bytes,
from .cli_stub import CLIOptions
startup_id = data.get('startup_id')
args, rest = parse_args(data['args'][1:], result_class=CLIOptions)
cmdline_args_for_open = data.get('cmdline_args_for_open')
if cmdline_args_for_open:
self.launch_urls(*cmdline_args_for_open, no_replace_window=True)
return None
args.args = rest
opts = create_opts(args)
if args.session == '-':
@ -746,7 +751,14 @@ def start(self, first_os_window_id: int) -> None:
if not getattr(self, 'io_thread_started', False):
self.child_monitor.start()
self.io_thread_started = True
self.startup_first_child(first_os_window_id)
urls: List[str] = getattr(sys, 'cmdline_args_for_open', [])
sess = create_sessions(get_options(), self.args, special_window=SpecialWindow([kitty_exe(), '+runpy', 'input()']))
if urls:
delattr(sys, 'cmdline_args_for_open')
self.startup_first_child(first_os_window_id, startup_sessions=tuple(sess))
self.launch_urls(*urls)
else:
self.startup_first_child(first_os_window_id)
if get_options().update_check_interval > 0 and not hasattr(self, 'update_check_started'):
from .update_check import run_update_check
@ -2234,19 +2246,21 @@ def show_kitty_env_vars(self) -> None:
output = '\n'.join(f'{k}={v}' for k, v in os.environ.items())
self.display_scrollback(w, output, title=_('Current kitty env vars'), report_cursor=False)
def launch_url(self, url: str) -> None:
if url == ":cocoa::application launched::":
def launch_urls(self, *urls: str, no_replace_window: bool = False) -> None:
if urls == (":cocoa::application launched::",):
self.cocoa_application_launched = True
return
from .open_actions import actions_for_launch
from .launch import force_window_launch
actions = list(actions_for_launch(url))
from .open_actions import actions_for_launch
actions = []
for url in urls:
actions.extend(actions_for_launch(url))
tab = self.active_tab
if tab is not None:
w = tab.active_window
else:
w = None
needs_window_replaced = not self.cocoa_application_launched or not self.os_window_map and w is not None and w.id == 1
needs_window_replaced = not no_replace_window and (not self.cocoa_application_launched or not self.os_window_map) and w is not None and w.id == 1
def clear_initial_window() -> None:
if needs_window_replaced and tab is not None and w is not None:
@ -2254,7 +2268,7 @@ def clear_initial_window() -> None:
if not actions:
with force_window_launch(needs_window_replaced):
self.launch(kitty_exe(), '+runpy', f'print("The url:", {url!r}, "is of unknown type, cannot open it.");'
self.launch(kitty_exe(), '+runpy', f'print("The url:", {urls[0]!r}, "is of unknown type, cannot open it.");'
'from kitty.utils import hold_till_enter; hold_till_enter(); raise SystemExit(1)')
clear_initial_window()
else:

View File

@ -1050,7 +1050,7 @@ process_cocoa_pending_actions(void) {
if (cocoa_pending_actions_data.open_urls_count) {
for (unsigned cpa = 0; cpa < cocoa_pending_actions_data.open_urls_count; cpa++) {
if (cocoa_pending_actions_data.open_urls[cpa]) {
call_boss(launch_url, "s", cocoa_pending_actions_data.open_urls[cpa]);
call_boss(launch_urls, "s", cocoa_pending_actions_data.open_urls[cpa]);
free(cocoa_pending_actions_data.open_urls[cpa]);
cocoa_pending_actions_data.open_urls[cpa] = NULL;
}

View File

@ -60,7 +60,7 @@ def talk_to_instance(args: CLIOptions) -> None:
stdin = ''
if args.session == '-':
stdin = sys.stdin.read()
data = {'cmd': 'new_instance', 'args': tuple(sys.argv),
data = {'cmd': 'new_instance', 'args': tuple(sys.argv), 'cmdline_args_for_open': getattr(sys, 'cmdline_args_for_open', []),
'startup_id': os.environ.get('DESKTOP_STARTUP_ID'),
'cwd': os.getcwd(), 'stdin': stdin}
notify_socket = None
@ -367,8 +367,21 @@ def _main() -> None:
cwd_ok = False
if not cwd_ok:
os.chdir(os.path.expanduser('~'))
cli_opts, rest = parse_args(args=args, result_class=CLIOptions)
cli_opts.args = rest
if getattr(sys, 'cmdline_args_for_open', False):
usage = 'file_or_url ...'
appname = 'kitty +open'
msg = (
'Run kitty and open the specified files or URLs in it, using launch-actions.conf. For details'
' see https://sw.kovidgoyal.net/kitty/open_actions/#scripting-the-opening-of-files-with-kitty-on-macos'
'\n\nAll the normal kitty options can be used.')
else:
usage = msg = appname = None
cli_opts, rest = parse_args(args=args, result_class=CLIOptions, usage=usage, message=msg, appname=appname)
if getattr(sys, 'cmdline_args_for_open', False):
setattr(sys, 'cmdline_args_for_open', rest)
cli_opts.args = []
else:
cli_opts.args = rest
if cli_opts.detach:
if cli_opts.session == '-':
from .session import PreReadSession