Start moving clipboard kitten to kitty-tool
This commit is contained in:
parent
fbce5e7524
commit
4d3f3b5e91
104
gen-go-code.py
104
gen-go-code.py
@ -8,7 +8,7 @@ import subprocess
|
||||
import sys
|
||||
from contextlib import contextmanager, suppress
|
||||
from functools import lru_cache
|
||||
from typing import Dict, Iterator, List, Set, Tuple, Union, Sequence
|
||||
from typing import Any, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Union
|
||||
|
||||
import kitty.constants as kc
|
||||
from kittens.tui.operations import Mode
|
||||
@ -50,10 +50,24 @@ def replace(template: str, **kw: str) -> str:
|
||||
|
||||
|
||||
# Completions {{{
|
||||
|
||||
@lru_cache
|
||||
def kitten_cli_docs(kitten: str) -> Any:
|
||||
from kittens.runner import get_kitten_cli_docs
|
||||
return get_kitten_cli_docs(kitten)
|
||||
|
||||
|
||||
@lru_cache
|
||||
def go_options_for_kitten(kitten: str) -> Tuple[Sequence[GoOption], Optional[CompletionSpec]]:
|
||||
kcd = kitten_cli_docs(kitten)
|
||||
if kcd:
|
||||
ospec = kcd['options']
|
||||
return (tuple(go_options_for_seq(parse_option_spec(ospec())[0])), kcd.get('args_completion'))
|
||||
return (), None
|
||||
|
||||
|
||||
def generate_kittens_completion() -> None:
|
||||
from kittens.runner import (
|
||||
all_kitten_names, get_kitten_cli_docs, get_kitten_wrapper_of,
|
||||
)
|
||||
from kittens.runner import all_kitten_names, get_kitten_wrapper_of
|
||||
for kitten in sorted(all_kitten_names()):
|
||||
kn = 'kitten_' + kitten
|
||||
print(f'{kn} := plus_kitten.AddSubCommand(&cli.Command{{Name:"{kitten}", Group: "Kittens"}})')
|
||||
@ -62,12 +76,10 @@ def generate_kittens_completion() -> None:
|
||||
print(f'{kn}.ArgCompleter = cli.CompletionForWrapper("{serialize_as_go_string(wof)}")')
|
||||
print(f'{kn}.OnlyArgsAllowed = true')
|
||||
continue
|
||||
kcd = get_kitten_cli_docs(kitten)
|
||||
if kcd:
|
||||
ospec = kcd['options']
|
||||
for opt in go_options_for_seq(parse_option_spec(ospec())[0]):
|
||||
gopts, ac = go_options_for_kitten(kitten)
|
||||
if gopts or ac:
|
||||
for opt in gopts:
|
||||
print(opt.as_option(kn))
|
||||
ac = kcd.get('args_completion')
|
||||
if ac is not None:
|
||||
print(''.join(ac.as_go_code(kn + '.ArgCompleter', ' = ')))
|
||||
else:
|
||||
@ -265,6 +277,48 @@ def go_code_for_remote_command(name: str, cmd: RemoteCommand, template: str) ->
|
||||
# }}}
|
||||
|
||||
|
||||
# kittens {{{
|
||||
|
||||
@lru_cache
|
||||
def wrapped_kittens() -> Sequence[str]:
|
||||
with open('shell-integration/ssh/kitty') as f:
|
||||
for line in f:
|
||||
if line.startswith(' wrapped_kittens="'):
|
||||
val = line.strip().partition('"')[2][:-1]
|
||||
return tuple(sorted(filter(None, val.split())))
|
||||
raise Exception('Failed to read wrapped kittens from kitty wrapper script')
|
||||
|
||||
|
||||
def kitten_clis() -> None:
|
||||
for kitten in wrapped_kittens():
|
||||
with replace_if_needed(f'tools/cmd/{kitten}/cli_generated.go'):
|
||||
kcd = kitten_cli_docs(kitten)
|
||||
has_underscore = '_' in kitten
|
||||
print(f'package {kitten}')
|
||||
print('import "kitty/tools/cli"')
|
||||
print('func create_cmd(root *cli.Command, run_func cli.RunFunc) {')
|
||||
print('ans := root.AddSubCommand(&cli.Command{')
|
||||
print(f'Name: "{kitten}",')
|
||||
print(f'ShortDescription: "{serialize_as_go_string(kcd["short_desc"])}",')
|
||||
print(f'Usage: "{serialize_as_go_string(kcd["usage"])}",')
|
||||
print(f'HelpText: "{serialize_as_go_string(kcd["help_text"])}",')
|
||||
print('Run: run_func,')
|
||||
if has_underscore:
|
||||
print('Hidden: true,')
|
||||
print('})')
|
||||
gopts, ac = go_options_for_kitten(kitten)
|
||||
for opt in gopts:
|
||||
print(opt.as_option('ans'))
|
||||
if ac is not None:
|
||||
print(''.join(ac.as_go_code('ans.ArgCompleter', ' = ')))
|
||||
if has_underscore:
|
||||
print("clone := root.AddClone(ans.Group, ans)")
|
||||
print('clone.Hidden = false')
|
||||
print(f'clone.Name = "{serialize_as_go_string(kitten.replace("_", "-"))}"')
|
||||
print('}')
|
||||
# }}}
|
||||
|
||||
|
||||
# Constants {{{
|
||||
|
||||
def generate_spinners() -> str:
|
||||
@ -335,7 +389,12 @@ var DocTitleMap = map[string]string{serialize_go_dict(ref_map['doc'])}
|
||||
@contextmanager
|
||||
def replace_if_needed(path: str, show_diff: bool = False) -> Iterator[io.StringIO]:
|
||||
buf = io.StringIO()
|
||||
yield buf
|
||||
origb = sys.stdout
|
||||
sys.stdout = buf
|
||||
try:
|
||||
yield buf
|
||||
finally:
|
||||
sys.stdout = origb
|
||||
orig = ''
|
||||
with suppress(FileNotFoundError), open(path, 'r') as f:
|
||||
orig = f.read()
|
||||
@ -391,21 +450,15 @@ func add_rc_global_opts(cmd *cli.Command) {{
|
||||
|
||||
|
||||
def update_completion() -> None:
|
||||
orig = sys.stdout
|
||||
try:
|
||||
with replace_if_needed('tools/cmd/completion/kitty_generated.go') as f:
|
||||
sys.stdout = f
|
||||
generate_completions_for_kitty()
|
||||
with replace_if_needed('tools/cmd/edit_in_kitty/launch_generated.go') as f:
|
||||
sys.stdout = f
|
||||
print('package edit_in_kitty')
|
||||
print('import "kitty/tools/cli"')
|
||||
print('func AddCloneSafeOpts(cmd *cli.Command) {')
|
||||
completion_for_launch_wrappers('cmd')
|
||||
print(''.join(CompletionSpec.from_string('type:file mime:text/* group:"Text files"').as_go_code('cmd.ArgCompleter', ' = ')))
|
||||
print('}')
|
||||
finally:
|
||||
sys.stdout = orig
|
||||
with replace_if_needed('tools/cmd/completion/kitty_generated.go'):
|
||||
generate_completions_for_kitty()
|
||||
with replace_if_needed('tools/cmd/edit_in_kitty/launch_generated.go'):
|
||||
print('package edit_in_kitty')
|
||||
print('import "kitty/tools/cli"')
|
||||
print('func AddCloneSafeOpts(cmd *cli.Command) {')
|
||||
completion_for_launch_wrappers('cmd')
|
||||
print(''.join(CompletionSpec.from_string('type:file mime:text/* group:"Text files"').as_go_code('cmd.ArgCompleter', ' = ')))
|
||||
print('}')
|
||||
|
||||
|
||||
def define_enum(package_name: str, type_name: str, items: str, underlying_type: str = 'uint') -> str:
|
||||
@ -496,6 +549,7 @@ def main() -> None:
|
||||
f.write(generate_spinners())
|
||||
update_completion()
|
||||
update_at_commands()
|
||||
kitten_clis()
|
||||
print(json.dumps(changed, indent=2))
|
||||
|
||||
|
||||
|
||||
@ -147,3 +147,4 @@ elif __name__ == '__doc__':
|
||||
cd['usage'] = usage
|
||||
cd['options'] = OPTIONS
|
||||
cd['help_text'] = help_text
|
||||
cd['short_desc'] = 'Copy/paste with the system clipboard, even over SSH'
|
||||
|
||||
@ -216,6 +216,23 @@ get_docs_ref_map(PyObject *self UNUSED, PyObject *args UNUSED) {
|
||||
return PyBytes_FromStringAndSize(docs_ref_map, sizeof(docs_ref_map));
|
||||
}
|
||||
|
||||
#include "wrapped_kitten_names_generated.h"
|
||||
|
||||
static PyObject*
|
||||
wrapped_kittens(PyObject *self UNUSED, PyObject *args UNUSED) {
|
||||
PyObject *ans = PyFrozenSet_New(NULL);
|
||||
if (ans != NULL) {
|
||||
for (int i = 0; wrapped_kitten_names[i] != NULL; i++) {
|
||||
PyObject *n = PyUnicode_FromString(wrapped_kitten_names[i]);
|
||||
if (n == NULL) break;
|
||||
if (PySet_Add(ans, n) != 0) { Py_DECREF(n); break; }
|
||||
Py_DECREF(n);
|
||||
}
|
||||
}
|
||||
if (PyErr_Occurred()) { Py_CLEAR(ans); }
|
||||
return ans;
|
||||
}
|
||||
|
||||
static PyMethodDef module_methods[] = {
|
||||
{"wcwidth", (PyCFunction)wcwidth_wrap, METH_O, ""},
|
||||
{"get_docs_ref_map", (PyCFunction)get_docs_ref_map, METH_NOARGS, ""},
|
||||
@ -234,6 +251,7 @@ static PyMethodDef module_methods[] = {
|
||||
{"locale_is_valid", (PyCFunction)locale_is_valid, METH_VARARGS, ""},
|
||||
{"shm_open", (PyCFunction)py_shm_open, METH_VARARGS, ""},
|
||||
{"shm_unlink", (PyCFunction)py_shm_unlink, METH_VARARGS, ""},
|
||||
{"wrapped_kitten_names", (PyCFunction)wrapped_kittens, METH_NOARGS, ""},
|
||||
#ifdef __APPLE__
|
||||
METHODB(user_cache_dir, METH_NOARGS),
|
||||
METHODB(process_group_map, METH_NOARGS),
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import termios
|
||||
from ctypes import Array, c_ubyte
|
||||
from typing import (
|
||||
Any, Callable, Dict, List, NewType, Optional, Tuple, TypedDict,
|
||||
Union, Iterator
|
||||
Any, Callable, Dict, FrozenSet, Iterator, List, NewType, Optional, Tuple, TypedDict,
|
||||
Union,
|
||||
)
|
||||
|
||||
from kitty.boss import Boss
|
||||
@ -1493,3 +1493,4 @@ def get_clipboard_mime(ct: int, mime: Optional[str], callback: Callable[[bytes],
|
||||
def run_with_activation_token(func: Callable[[str], None]) -> None: ...
|
||||
def make_x11_window_a_dock_window(x11_window_id: int, strut: Tuple[int, int, int, int, int, int, int, int, int, int, int, int]) -> None: ...
|
||||
def unicode_database_version() -> Tuple[int, int, int]: ...
|
||||
def wrapped_kittens() -> FrozenSet[str]: ...
|
||||
|
||||
26
setup.py
26
setup.py
@ -860,11 +860,37 @@ def build_ref_map() -> str:
|
||||
return dest
|
||||
|
||||
|
||||
@lru_cache
|
||||
def wrapped_kittens() -> Sequence[str]:
|
||||
with open('shell-integration/ssh/kitty') as f:
|
||||
for line in f:
|
||||
if line.startswith(' wrapped_kittens="'):
|
||||
val = line.strip().partition('"')[2][:-1]
|
||||
return tuple(sorted(filter(None, val.split())))
|
||||
raise Exception('Failed to read wrapped kittens from kitty wrapper script')
|
||||
|
||||
|
||||
def build_wrapped_kittens() -> str:
|
||||
h = 'static const char* wrapped_kitten_names[] = {\n'
|
||||
h += ', '.join(f'"{x}"' for x in wrapped_kittens())
|
||||
h += ', NULL'
|
||||
h += '\n};\n'
|
||||
dest = 'kitty/wrapped_kitten_names_generated.h'
|
||||
q = ''
|
||||
with suppress(FileNotFoundError), open(dest) as f:
|
||||
q = f.read()
|
||||
if q != h:
|
||||
with open(dest, 'w') as f:
|
||||
f.write(h)
|
||||
return dest
|
||||
|
||||
|
||||
def build(args: Options, native_optimizations: bool = True, call_init: bool = True) -> None:
|
||||
if call_init:
|
||||
init_env_from_args(args, native_optimizations)
|
||||
sources, headers = find_c_files()
|
||||
headers.append(build_ref_map())
|
||||
headers.append(build_wrapped_kittens())
|
||||
compile_c_extension(
|
||||
kitty_env(), 'kitty/fast_data_types', args.compilation_database, sources, headers
|
||||
)
|
||||
|
||||
@ -22,6 +22,21 @@ exec_kitty() {
|
||||
die "Failed to execute kitty"
|
||||
}
|
||||
|
||||
|
||||
is_wrapped_kitten() {
|
||||
wrapped_kittens="clipboard"
|
||||
[ -n "$1" ] && {
|
||||
case " $wrapped_kittens " in
|
||||
*" $1 "*) printf "%s" "$1" ;;
|
||||
esac
|
||||
}
|
||||
}
|
||||
|
||||
test "(" "$1" = "+kitten" -a -n "$(is_wrapped_kitten "$2")" ")" -o "(" "$1" = "+" -a "$2" = "kitten" -a "$(is_wrapped_kitten "$3")" ")" && {
|
||||
if [ "$1" = "+kitten" ]; then shift "1"; else shift "2"; fi
|
||||
exec kitty-tool "$@"
|
||||
}
|
||||
|
||||
lock_dir=""
|
||||
script_path="$(command readlink -f "$0" 2> /dev/null)"
|
||||
[ $? = 0 ] || script_path="$0"
|
||||
|
||||
@ -14,6 +14,8 @@ import (
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
type RunFunc = func(cmd *Command, args []string) (int, error)
|
||||
|
||||
type Command struct {
|
||||
Name, Group string
|
||||
Usage, ShortDescription, HelpText string
|
||||
@ -26,7 +28,7 @@ type Command struct {
|
||||
// If true subcommands are ignored unless they are the first non-option argument
|
||||
SubCommandMustBeFirst bool
|
||||
// The entry point for this command
|
||||
Run func(cmd *Command, args []string) (int, error)
|
||||
Run RunFunc
|
||||
// The completer for args
|
||||
ArgCompleter CompletionFunc
|
||||
// Stop completion processing at this arg num
|
||||
|
||||
18
tools/cmd/clipboard/main.go
Normal file
18
tools/cmd/clipboard/main.go
Normal file
@ -0,0 +1,18 @@
|
||||
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||
|
||||
package clipboard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"kitty/tools/cli"
|
||||
)
|
||||
|
||||
var _ = fmt.Print
|
||||
|
||||
func clipboard_main(cmd *cli.Command, args []string) (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func EntryPoint(parent *cli.Command) {
|
||||
create_cmd(parent, clipboard_main)
|
||||
}
|
||||
@ -4,8 +4,10 @@ package tool
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/cmd/at"
|
||||
"kitty/tools/cmd/clipboard"
|
||||
"kitty/tools/cmd/edit_in_kitty"
|
||||
"kitty/tools/cmd/update_self"
|
||||
)
|
||||
@ -21,4 +23,6 @@ func KittyToolEntryPoints(root *cli.Command) {
|
||||
update_self.EntryPoint(root)
|
||||
// edit-in-kitty
|
||||
edit_in_kitty.EntryPoint(root)
|
||||
// clipboard
|
||||
clipboard.EntryPoint(root)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user