diff --git a/docs/conf.py b/docs/conf.py index 628ae55fd..adb8f01b3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -8,6 +8,8 @@ import subprocess from collections import defaultdict +from functools import partial + from docutils import nodes from docutils.parsers.rst.roles import set_classes @@ -269,6 +271,20 @@ def write_cli_docs(): from kitty.cli import option_spec_as_rst with open('generated/cli-kitty.rst', 'w') as f: f.write(option_spec_as_rst(appname='kitty').replace('kitty --to', 'kitty @ --to')) + as_rst = partial(option_spec_as_rst, heading_char='_') + from kitty.remote_control import global_options_spec, cli_msg, cmap, all_commands + with open('generated/cli-kitty-at.rst', 'w') as f: + p = partial(print, file=f) + p('kitty @\n' + '-' * 80) + p('.. program::', 'kitty @') + p('\n\n' + as_rst( + global_options_spec, message=cli_msg, usage='command ...', appname='kitty @')) + from kitty.cmds import cli_params_for + for cmd_name in all_commands: + func = cmap[cmd_name] + p('kitty @', func.name + '\n' + '-' * 120) + p('.. program::', 'kitty @', func.name) + p('\n\n' + as_rst(*cli_params_for(func))) # }}} diff --git a/docs/remote-control.rst b/docs/remote-control.rst index ceb2f36da..3b1ceb4a4 100644 --- a/docs/remote-control.rst +++ b/docs/remote-control.rst @@ -1,3 +1,5 @@ +:tocdepth: 2 + Controlling kitty from scripts or the shell ============================================== @@ -29,7 +31,7 @@ Let's send some text to this new window:: kitty @ send-text --match cmdline:cat Hello, World This will make ``Hello, World`` show up in the window running the ``cat`` program. -The :option:`--match` option is very powerful, it allows selecting windows by their +The :option:`kitty @ send-text --match` option is very powerful, it allows selecting windows by their titles, the command line of the program running in the window, the working directory of the program running in the window, etc. See ``kitty @ send-text --help`` for details. @@ -80,7 +82,7 @@ This outputs a tree of data in JSON format. The top level of the tree is all operating system kitty windows. Each OS window has an id and a list of tabs. Each tab has its own id, a title and a list of windows. Each window has an id, title, current working directory, process id (PID) and command-line of the -process running in the window. You can use this information with :option:`--match` +process running in the window. You can use this information with :option:`kitty @ focus-window --match` to control individual windows. As you can see, it is very easy to control |kitty| using the @@ -94,9 +96,9 @@ extra steps. First start |kitty| as:: kitty -o allow_remote_control=yes --listen-on unix:/tmp/mykitty -The :option:`--listen-on` option tells |kitty| to listen for control messages at the +The :option:`kitty --listen-on` option tells |kitty| to listen for control messages at the specified path. See ``kitty --help`` for details. Now you can control this -instance of |kitty| using the :option:`--to` command line argument to ``kitty @``. For example:: +instance of |kitty| using the :option:`kitty @ --to` command line argument to ``kitty @``. For example:: kitty @ --to unix:/tmp/mykitty ls @@ -115,3 +117,7 @@ shell with completion for |kitty| command names and options. You can even open the |kitty| shell inside a running |kitty| using a simple keyboard shortcut (|sc_kitty_shell_window| by default). This has the added advantage that you dont need to use ``allow_remote_control`` to make it work. + + +.. include:: generated/cli-kitty-at.rst + diff --git a/kitty/cli.py b/kitty/cli.py index ce27a90cc..06eaf1e7c 100644 --- a/kitty/cli.py +++ b/kitty/cli.py @@ -376,7 +376,7 @@ def print_help_for_seq(seq, usage, message, appname): print_help_for_seq.allow_pager = True -def seq_as_rst(seq, usage, message, appname): +def seq_as_rst(seq, usage, message, appname, heading_char='-'): import textwrap blocks = [] a = blocks.append @@ -393,7 +393,7 @@ def seq_as_rst(seq, usage, message, appname): a('') if seq: a('Options') - a('----------------') + a(heading_char * 30) for opt in seq: if isinstance(opt, str): a(opt) @@ -558,11 +558,11 @@ def options_spec(): return options_spec.ans -def option_spec_as_rst(ospec=options_spec, usage=None, message=None, appname=None): +def option_spec_as_rst(ospec=options_spec, usage=None, message=None, appname=None, heading_char='-'): options = parse_option_spec(ospec()) seq, disabled = options oc = Options(seq, usage, message, appname) - return seq_as_rst(oc.seq, oc.usage, oc.message, oc.appname) + return seq_as_rst(oc.seq, oc.usage, oc.message, oc.appname, heading_char=heading_char) def parse_args(args=None, ospec=options_spec, usage=None, message=None, appname=None): diff --git a/kitty/cmds.py b/kitty/cmds.py index c596dfde5..cd24f9d64 100644 --- a/kitty/cmds.py +++ b/kitty/cmds.py @@ -635,8 +635,12 @@ def set_background_opacity(boss, window, payload): cmap = {v.name: v for v in globals().values() if hasattr(v, 'is_cmd')} +def cli_params_for(func): + return (func.options_spec or '\n').format, func.argspec, func.desc, '{} @ {}'.format(appname, func.name) + + def parse_subcommand_cli(func, args): - opts, items = parse_args(args[1:], (func.options_spec or '\n').format, func.argspec, func.desc, '{} @ {}'.format(appname, func.name)) + opts, items = parse_args(args[1:], *cli_params_for(func)) if func.args_count is not None and func.args_count != len(items): if func.args_count == 0: raise SystemExit('Unknown extra argument(s) supplied to {}'.format(func.name)) diff --git a/kitty/remote_control.py b/kitty/remote_control.py index 69e5a5a40..3c20543da 100644 --- a/kitty/remote_control.py +++ b/kitty/remote_control.py @@ -33,7 +33,7 @@ def handle_cmd(boss, window, cmd): global_options_spec = partial('''\ --to An address for the kitty instance to control. Corresponds to the address -given to the kitty instance via the --listen-on option. If not specified, +given to the kitty instance via the :option:`kitty --listen-on` option. If not specified, messages are sent to the controlling terminal for this process, i.e. they will only work if this process is run within an existing kitty window. '''.format, appname=appname) @@ -84,18 +84,19 @@ def do_io(to, send, no_response): all_commands = tuple(sorted(cmap)) +cli_msg = ( + 'Control {appname} by sending it commands. Add' + ' :italic:`allow_remote_control yes` to |kitty.conf| for this' + ' to work.' +).format(appname=appname) def parse_rc_args(args): cmds = (' :green:`{}`\n {}'.format(cmap[c].name, cmap[c].short_desc) for c in all_commands) - msg = ( - 'Control {appname} by sending it commands. Add' - ' :italic:`allow_remote_control yes` to |kitty.conf| for this' - ' to work.\n\n:title:`Commands`:\n{cmds}\n\n' - 'You can get help for each individual command by using:\n' - '{appname} @ :italic:`command` -h' - ).format(appname=appname, cmds='\n'.join(cmds)) - + msg = cli_msg + ( + '\n\n:title:`Commands`:\n{cmds}\n\n' + 'You can get help for each individual command by using:\n' + '{appname} @ :italic:`command` -h').format(appname=appname, cmds='\n'.join(cmds)) return parse_args(args[1:], global_options_spec, 'command ...', msg, '{} @'.format(appname))