Get rid of the cobra dependency
This commit is contained in:
parent
cbc569af64
commit
4396dede85
@ -13,14 +13,13 @@ import kitty.constants as kc
|
||||
from kittens.tui.operations import Mode
|
||||
from kitty.cli import (
|
||||
CompletionSpec, GoOption, go_options_for_seq, parse_option_spec,
|
||||
serialize_as_go_string
|
||||
serialize_as_go_string,
|
||||
)
|
||||
from kitty.key_encoding import config_mod_map
|
||||
from kitty.key_names import (
|
||||
character_key_name_aliases, functional_key_name_aliases
|
||||
)
|
||||
from kitty.key_names import character_key_name_aliases, functional_key_name_aliases
|
||||
from kitty.options.types import Options
|
||||
from kitty.rc.base import RemoteCommand, all_command_names, command_for_name
|
||||
from kitty.remote_control import global_options_spec
|
||||
from kitty.rgb import color_names
|
||||
|
||||
changed: List[str] = []
|
||||
@ -59,7 +58,9 @@ def generate_completion_for_rc(name: str) -> 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_cli_docs, get_kitten_wrapper_of,
|
||||
)
|
||||
for kitten in sorted(all_kitten_names()):
|
||||
kn = 'kitten_' + kitten
|
||||
print(f'{kn} := plus_kitten.add_command("{kitten}", "Kittens")')
|
||||
@ -84,7 +85,7 @@ def completion_for_launch_wrappers(*names: str) -> None:
|
||||
opts = tuple(go_options_for_seq(parse_option_spec(options_spec())[0]))
|
||||
allowed = clone_safe_opts()
|
||||
for o in opts:
|
||||
if o.dest in allowed:
|
||||
if o.obj_dict['name'] in allowed:
|
||||
for name in names:
|
||||
print(o.as_completion_option(name))
|
||||
|
||||
@ -184,36 +185,19 @@ class JSONField:
|
||||
return self.struct_field_name + ' ' + go_field_type(self.field_type) + f'`json:"{self.field},omitempty"`'
|
||||
|
||||
|
||||
def render_alias_map(alias_map: Dict[str, Tuple[str, ...]]) -> str:
|
||||
if not alias_map:
|
||||
return ''
|
||||
amap = 'switch name {\n'
|
||||
for name, aliases in alias_map.items():
|
||||
for alias in aliases:
|
||||
amap += f'\ncase "{alias}":\nname = "{name}"\n'
|
||||
amap += '}'
|
||||
return amap
|
||||
|
||||
|
||||
def go_code_for_remote_command(name: str, cmd: RemoteCommand, template: str) -> str:
|
||||
template = '\n' + template[len('//go:build exclude'):]
|
||||
NO_RESPONSE_BASE = 'false'
|
||||
af: List[str] = []
|
||||
a = af.append
|
||||
alias_map = {}
|
||||
od: List[str] = []
|
||||
ov: List[str] = []
|
||||
option_map: Dict[str, GoOption] = {}
|
||||
for o in rc_command_options(name):
|
||||
field_dest = o.go_var_name.rstrip('_')
|
||||
option_map[field_dest] = o
|
||||
if o.aliases:
|
||||
alias_map[o.long] = tuple(o.aliases)
|
||||
a(o.to_flag_definition())
|
||||
if o.dest in ('no_response', 'response_timeout'):
|
||||
option_map[o.go_var_name] = o
|
||||
a(o.as_option('ans'))
|
||||
if o.go_var_name in ('NoResponse', 'ResponseTimeout'):
|
||||
continue
|
||||
od.append(f'{o.go_var_name} {o.go_type}')
|
||||
ov.append(o.set_flag_value(f'options_{name}'))
|
||||
od.append(o.struct_declaration())
|
||||
jd: List[str] = []
|
||||
json_fields = []
|
||||
field_types: Dict[str, str] = {}
|
||||
@ -233,6 +217,7 @@ def go_code_for_remote_command(name: str, cmd: RemoteCommand, template: str) ->
|
||||
used_options = set()
|
||||
for field in json_fields:
|
||||
oq = (cmd.field_to_option_map or {}).get(field.field, field.field)
|
||||
oq = ''.join(x.capitalize() for x in oq.split('_'))
|
||||
if oq in option_map:
|
||||
o = option_map[oq]
|
||||
used_options.add(oq)
|
||||
@ -242,16 +227,16 @@ def go_code_for_remote_command(name: str, cmd: RemoteCommand, template: str) ->
|
||||
else:
|
||||
unhandled[field.field] = field
|
||||
for x in tuple(unhandled):
|
||||
if x == 'match_window' and 'match' in option_map and 'match' not in used_options:
|
||||
used_options.add('match')
|
||||
o = option_map['match']
|
||||
if x == 'match_window' and 'Match' in option_map and 'Match' not in used_options:
|
||||
used_options.add('Match')
|
||||
o = option_map['Match']
|
||||
field = unhandled[x]
|
||||
jc.append(f'payload.{field.struct_field_name} = options_{name}.{o.go_var_name}')
|
||||
del unhandled[x]
|
||||
if unhandled:
|
||||
raise SystemExit(f'Cant map fields: {", ".join(unhandled)} for cmd: {name}')
|
||||
if name != 'send_text':
|
||||
unused_options = set(option_map) - used_options - {'no_response', 'response_timeout'}
|
||||
unused_options = set(option_map) - used_options - {'NoResponse', 'ResponseTimeout'}
|
||||
if unused_options:
|
||||
raise SystemExit(f'Unused options: {", ".join(unused_options)} for command: {name}')
|
||||
|
||||
@ -266,9 +251,7 @@ def go_code_for_remote_command(name: str, cmd: RemoteCommand, template: str) ->
|
||||
IS_ASYNC='true' if cmd.is_asynchronous else 'false',
|
||||
NO_RESPONSE_BASE=NO_RESPONSE_BASE, ADD_FLAGS_CODE='\n'.join(af),
|
||||
WAIT_TIMEOUT=str(cmd.response_timeout),
|
||||
ALIAS_NORMALIZE_CODE=render_alias_map(alias_map),
|
||||
OPTIONS_DECLARATION_CODE='\n'.join(od),
|
||||
SET_OPTION_VALUES_CODE='\n'.join(ov),
|
||||
JSON_DECLARATION_CODE='\n'.join(jd),
|
||||
JSON_INIT_CODE='\n'.join(jc), ARGSPEC=argspec,
|
||||
STRING_RESPONSE_IS_ERROR='true' if cmd.string_return_is_error else 'false',
|
||||
@ -352,6 +335,27 @@ def update_at_commands() -> None:
|
||||
dest = f'tools/cmd/at/cmd_{name}_generated.go'
|
||||
with replace_if_needed(dest) as f:
|
||||
f.write(code)
|
||||
struct_def = []
|
||||
opt_def = []
|
||||
for o in go_options_for_seq(parse_option_spec(global_options_spec())[0]):
|
||||
struct_def.append(o.struct_declaration())
|
||||
opt_def.append(o.as_option(depth=1, group="Global options"))
|
||||
sdef = '\n'.join(struct_def)
|
||||
odef = '\n'.join(opt_def)
|
||||
code = f'''
|
||||
package at
|
||||
import "kitty/tools/cli"
|
||||
type rc_global_options struct {{
|
||||
{sdef}
|
||||
}}
|
||||
var rc_global_opts rc_global_options
|
||||
|
||||
func add_rc_global_opts(cmd *cli.Command) {{
|
||||
{odef}
|
||||
}}
|
||||
'''
|
||||
with replace_if_needed('tools/cmd/at/global_opts_generated.go') as f:
|
||||
f.write(code)
|
||||
|
||||
|
||||
def update_completion() -> None:
|
||||
|
||||
9
go.mod
9
go.mod
@ -8,15 +8,10 @@ require (
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/jamesruan/go-rfc1924 v0.0.0-20170108144916-2767ca7c638f
|
||||
github.com/seancfoley/ipaddress-go v1.2.1
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0
|
||||
golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7
|
||||
golang.org/x/exp v0.0.0-20220921164117-439092de6870
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
|
||||
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/seancfoley/bintree v1.1.0 // indirect
|
||||
)
|
||||
require github.com/seancfoley/bintree v1.1.0 // indirect
|
||||
|
||||
15
go.sum
15
go.sum
@ -1,26 +1,17 @@
|
||||
github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924 h1:DG4UyTVIujioxwJc8Zj8Nabz1L1wTgQ/xNBSQDfdP3I=
|
||||
github.com/ALTree/bigfloat v0.0.0-20220102081255-38c8b72a9924/go.mod h1:+NaH2gLeY6RPBPPQf4aRotPPStg+eXc8f9ZaE4vRfD4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jamesruan/go-rfc1924 v0.0.0-20170108144916-2767ca7c638f h1:Ko4+g6K16vSyUrtd/pPXuQnWsiHe5BYptEtTxfwYwCc=
|
||||
github.com/jamesruan/go-rfc1924 v0.0.0-20170108144916-2767ca7c638f/go.mod h1:eHzfhOKbTGJEGPSdMHzU6jft192tHHt2Bu2vIZArvC0=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/seancfoley/bintree v1.1.0 h1:6J0rj9hLNLIcWSsfYdZ4ZHkMHokaK/PHkak8qyBO/mc=
|
||||
github.com/seancfoley/bintree v1.1.0/go.mod h1:CtE6qO6/n9H3V2CAGEC0lpaYr6/OijhNaMG/dt7P70c=
|
||||
github.com/seancfoley/ipaddress-go v1.2.1 h1:yEZxnyC6NQEDDPflyQm4KkWozffx1vHWsx+knKBr/n0=
|
||||
github.com/seancfoley/ipaddress-go v1.2.1/go.mod h1:/UEVHyrBg1ASVap2ffdY2cq5UMYIX9f3QW3uWSVqpbo=
|
||||
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
|
||||
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 h1:a5Yg6ylndHHYJqIPrdq0AhvR6KTvDTAvgBtaidhEevY=
|
||||
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7 h1:WJywXQVIb56P2kAvXeMGTIgQ1ZHQxR60+F9dLsodECc=
|
||||
golang.org/x/crypto v0.0.0-20220924013350-4ba4fb4dd9e7/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20220921164117-439092de6870 h1:j8b6j9gzSigH28O5SjSpQSSh9lFd6f5D/q0aHjNTulc=
|
||||
golang.org/x/exp v0.0.0-20220921164117-439092de6870/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
|
||||
@ -29,5 +20,3 @@ golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 h1:h+EGohizhe9XlX18rfpa8k8RA
|
||||
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
|
||||
76
kitty/cli.py
76
kitty/cli.py
@ -119,10 +119,6 @@ def serialize_as_go_string(x: str) -> str:
|
||||
go_type_map = {
|
||||
'bool-set': 'bool', 'bool-reset': 'bool', 'int': 'int', 'float': 'float64',
|
||||
'': 'string', 'list': '[]string', 'choices': 'string', 'str': 'string'}
|
||||
go_getter_map = {
|
||||
'bool-set': 'GetBool', 'bool-reset': 'GetBool', 'int': 'GetInt', 'float': 'GetFloat64', '': 'GetString',
|
||||
'list': 'GetStringArray', 'choices': 'GetString'
|
||||
}
|
||||
|
||||
|
||||
class GoOption:
|
||||
@ -137,54 +133,38 @@ class GoOption:
|
||||
for f in flags:
|
||||
q = f[2:] if f.startswith('--') else f[1:]
|
||||
self.aliases.append(q)
|
||||
self.usage = serialize_as_go_string(x['help'].strip())
|
||||
self.type = x['type']
|
||||
self.dest = x['dest']
|
||||
if x['choices']:
|
||||
self.type = 'choices'
|
||||
self.default = x['default']
|
||||
self.obj_dict = x
|
||||
self.go_type = go_type_map[self.type]
|
||||
self.go_var_name = self.long.replace('-', '_')
|
||||
if self.go_var_name == 'type':
|
||||
self.go_var_name += '_'
|
||||
|
||||
def to_flag_definition(self, base: str = 'ans.Flags()') -> str:
|
||||
if self.type.startswith('bool-'):
|
||||
defval = 'false' if self.type == 'bool-set' else 'true'
|
||||
if self.short:
|
||||
return f'{base}.BoolP("{self.long}", "{self.short}", {defval}, "{self.usage}")'
|
||||
return f'{base}.Bool("{self.long}", {defval}, "{self.usage}")'
|
||||
elif not self.type:
|
||||
defval = f'''"{serialize_as_go_string(self.default or '')}"'''
|
||||
if self.short:
|
||||
return f'{base}.StringP("{self.long}", "{self.short}", {defval}, "{self.usage}")'
|
||||
return f'{base}.String("{self.long}", {defval}, "{self.usage}")'
|
||||
elif self.type == 'int':
|
||||
if self.short:
|
||||
return f'{base}.IntP("{self.long}", "{self.short}", {self.default or 0}, "{self.usage}")'
|
||||
return f'{base}.Int("{self.long}", {self.default or 0}, "{self.usage}")'
|
||||
elif self.type == 'float':
|
||||
if self.short:
|
||||
return f'{base}.Float64P("{self.long}", "{self.short}", {self.default or 0}, "{self.usage}")'
|
||||
return f'{base}.Float64("{self.long}", {self.default or 0}, "{self.usage}")'
|
||||
elif self.type == 'list':
|
||||
defval = f'[]string{{"{serialize_as_go_string(self.default)}"}}' if self.default else '[]string{}'
|
||||
if self.short:
|
||||
return f'{base}.StringArrayP("{self.long}", "{self.short}", {defval}, "{self.usage}")'
|
||||
return f'{base}.StringArray("{self.long}", {defval}, "{self.usage}")'
|
||||
elif self.type == 'choices':
|
||||
choices = self.sorted_choices
|
||||
cx = ', '.join(f'"{serialize_as_go_string(x)}"' for x in choices)
|
||||
if self.short:
|
||||
return f'cli.ChoicesP({base}, "{self.long}", "{self.short}", "{self.usage}", {cx})'
|
||||
return f'cli.Choices({base}, "{self.long}", "{self.usage}", {cx})'
|
||||
if x['dest']:
|
||||
self.go_var_name = ''.join(x.capitalize() for x in x['dest'].replace('-', '_').split('_'))
|
||||
else:
|
||||
raise TypeError(f'Unknown type of CLI option: {self.type} for {self.long}')
|
||||
self.go_var_name = ''.join(x.capitalize() for x in self.long.replace('-', '_').split('_'))
|
||||
self.help_text = serialize_as_go_string(self.obj_dict['help'].strip())
|
||||
|
||||
def set_flag_value(self, struct_name: str, cmd: str = 'cmd') -> str:
|
||||
func = go_getter_map[self.type]
|
||||
ans = f'{self.go_var_name}_temp, err := {cmd}.Flags().{func}("{self.long}")\n if err != nil {{ return err }}'
|
||||
ans += f'\n{struct_name}.{self.go_var_name} = {self.go_var_name}_temp'
|
||||
return ans
|
||||
def struct_declaration(self) -> str:
|
||||
return f'{self.go_var_name} {self.go_type}'
|
||||
|
||||
def as_option(self, cmd_name: str = 'cmd', depth: int = 0, group: str = '') -> str:
|
||||
add = f'AddToGroup("{serialize_as_go_string(group)}", ' if group else 'Add('
|
||||
aliases = ' '.join(self.obj_dict['aliases'])
|
||||
ans = f'''{cmd_name}.{add}cli.OptionSpec{{
|
||||
Name: "{serialize_as_go_string(aliases)}",
|
||||
Type: "{self.type}",
|
||||
Dest: "{serialize_as_go_string(self.go_var_name)}",
|
||||
Help: "{self.help_text}",
|
||||
'''
|
||||
if self.type in ('choice', 'choices'):
|
||||
c = ', '.join(self.sorted_choices)
|
||||
ans += f'\nChoices: "{serialize_as_go_string(c)}",\n'
|
||||
if depth > 0:
|
||||
ans += f'\nDepth: {depth},\n'
|
||||
if self.default:
|
||||
ans += f'\nDefault: "{serialize_as_go_string(self.default)}",\n'
|
||||
return ans + '})'
|
||||
|
||||
@property
|
||||
def sorted_choices(self) -> List[str]:
|
||||
@ -195,12 +175,12 @@ class GoOption:
|
||||
|
||||
def as_completion_option(self, command_name: str) -> str:
|
||||
ans = f'{command_name}.add_option(&' 'Option{Name: ' f'"{serialize_as_go_string(self.long)}", '
|
||||
ans += f'Description: "{self.usage}", '
|
||||
ans += f'Description: "{self.help_text}", '
|
||||
aliases = (f'"{serialize_as_go_string(x)}"' for x in self.aliases)
|
||||
ans += 'Aliases: []string{' f'{", ".join(aliases)}' '}, '
|
||||
if self.go_type != 'bool':
|
||||
ans += 'Has_following_arg: true, '
|
||||
if self.type == 'choices':
|
||||
if self.type in ('choices', 'choice'):
|
||||
cx = ', '.join(f'"{serialize_as_go_string(x)}"' for x in self.sorted_choices)
|
||||
ans += f'Completion_for_arg: names_completer("Choices for {self.long}", {cx}),'
|
||||
elif self.obj_dict['completion'].type is not CompletionType.none:
|
||||
|
||||
@ -252,7 +252,7 @@ Used if no :option:`kitty @ --password` is supplied. Defaults to checking for th
|
||||
default=KITTY_RC_PASSWORD
|
||||
The name of an environment variable to read the password from.
|
||||
Used if no :option:`kitty @ --password-file` is supplied. Defaults
|
||||
to checking the :envvar:`KITTY_RC_PASSWORD`.
|
||||
to checking the environment variable :envvar:`KITTY_RC_PASSWORD`.
|
||||
|
||||
|
||||
--use-password
|
||||
|
||||
@ -31,7 +31,6 @@ func (self *Command) ShowVersion() {
|
||||
}
|
||||
|
||||
func format_with_indent(output io.Writer, text string, indent string, screen_width int) {
|
||||
text = formatter.Prettify(text)
|
||||
indented := style.WrapText(text, indent, screen_width, "#placeholder_for_formatting#")
|
||||
io.WriteString(output, indented)
|
||||
}
|
||||
@ -41,10 +40,12 @@ func (self *Command) FormatSubCommands(output io.Writer, formatter *markup.Conte
|
||||
if !g.HasVisibleSubCommands() {
|
||||
continue
|
||||
}
|
||||
if g.Title != "" {
|
||||
fmt.Fprintln(output)
|
||||
fmt.Fprintln(output, formatter.Title(g.Title))
|
||||
title := g.Title
|
||||
if title == "" {
|
||||
title = "Commands"
|
||||
}
|
||||
fmt.Fprintln(output)
|
||||
fmt.Fprintln(output, formatter.Title(title)+":")
|
||||
for _, c := range g.SubCommands {
|
||||
if c.Hidden {
|
||||
continue
|
||||
@ -64,22 +65,23 @@ func (self *Option) FormatOption(output io.Writer, formatter *markup.Context, sc
|
||||
fmt.Fprint(output, ", ")
|
||||
}
|
||||
}
|
||||
defval := ""
|
||||
defval := self.Default
|
||||
switch self.OptionType {
|
||||
case BoolOption:
|
||||
default:
|
||||
defval = self.Default
|
||||
fallthrough
|
||||
case StringOption:
|
||||
if self.IsList {
|
||||
defval = ""
|
||||
}
|
||||
case BoolOption, CountOption:
|
||||
defval = ""
|
||||
}
|
||||
if defval != "" {
|
||||
fmt.Fprintf(output, " [=%s]", formatter.Italic(defval))
|
||||
}
|
||||
fmt.Fprintln(output)
|
||||
format_with_indent(output, formatter.Prettify(prepare_help_text_for_display(self.Help)), " ", screen_width)
|
||||
if self.Choices != nil {
|
||||
format_with_indent(output, "Choices: "+strings.Join(self.Choices, ", "), " ", screen_width)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Command) ShowHelp() {
|
||||
@ -111,7 +113,6 @@ func (self *Command) ShowHelp() {
|
||||
|
||||
if self.HasVisibleSubCommands() {
|
||||
fmt.Fprintln(&output)
|
||||
fmt.Fprintln(&output, formatter.Title("Commands")+":")
|
||||
self.FormatSubCommands(&output, formatter, screen_width)
|
||||
fmt.Fprintln(&output)
|
||||
format_with_indent(&output, "Get help for an individual command by running:", "", screen_width)
|
||||
@ -121,12 +122,12 @@ func (self *Command) ShowHelp() {
|
||||
group_titles, gmap := self.GetVisibleOptions()
|
||||
if len(group_titles) > 0 {
|
||||
fmt.Fprintln(&output)
|
||||
fmt.Fprintln(&output, formatter.Title("Options")+":")
|
||||
for _, title := range group_titles {
|
||||
if title != "" {
|
||||
fmt.Fprintln(&output)
|
||||
fmt.Fprintln(&output, formatter.Title(title))
|
||||
ptitle := title
|
||||
if title == "" {
|
||||
ptitle = "Options"
|
||||
}
|
||||
fmt.Fprintln(&output, formatter.Title(ptitle)+":")
|
||||
for _, opt := range gmap[title] {
|
||||
opt.FormatOption(&output, formatter, screen_width)
|
||||
fmt.Fprintln(&output)
|
||||
|
||||
@ -1,265 +0,0 @@
|
||||
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"kitty"
|
||||
"kitty/tools/cli/markup"
|
||||
"kitty/tools/tty"
|
||||
)
|
||||
|
||||
var RootCmd *cobra.Command
|
||||
|
||||
func key_in_slice(vals []string, key string) bool {
|
||||
for _, q := range vals {
|
||||
if q == key {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type ChoicesVal struct {
|
||||
name, Choice string
|
||||
allowed []string
|
||||
}
|
||||
type choicesVal ChoicesVal
|
||||
|
||||
func (i *choicesVal) String() string { return ChoicesVal(*i).Choice }
|
||||
func (i *choicesVal) Type() string { return "string" }
|
||||
func (i *choicesVal) Set(s string) error {
|
||||
(*i).Choice = s
|
||||
return nil
|
||||
}
|
||||
func newChoicesVal(val ChoicesVal, p *ChoicesVal) *choicesVal {
|
||||
*p = val
|
||||
return (*choicesVal)(p)
|
||||
}
|
||||
|
||||
func add_choices(flags *pflag.FlagSet, p *ChoicesVal, choices []string, name string, short string, usage string) {
|
||||
usage = strings.TrimSpace(usage) + "\n" + "Choices: " + strings.Join(choices, ", ")
|
||||
value := ChoicesVal{Choice: choices[0], allowed: choices}
|
||||
flags.VarP(newChoicesVal(value, p), name, short, usage)
|
||||
}
|
||||
|
||||
func Choices(flags *pflag.FlagSet, name string, usage string, choices ...string) *ChoicesVal {
|
||||
p := new(ChoicesVal)
|
||||
add_choices(flags, p, choices, name, "", usage)
|
||||
return p
|
||||
}
|
||||
|
||||
func ChoicesP(flags *pflag.FlagSet, name string, short string, usage string, choices ...string) *ChoicesVal {
|
||||
p := new(ChoicesVal)
|
||||
add_choices(flags, p, choices, name, short, usage)
|
||||
return p
|
||||
}
|
||||
|
||||
var formatter *markup.Context
|
||||
|
||||
func full_command_name(cmd *cobra.Command) string {
|
||||
var parent_names []string
|
||||
cmd.VisitParents(func(p *cobra.Command) {
|
||||
parent_names = append([]string{p.Name()}, parent_names...)
|
||||
})
|
||||
parent_names = append(parent_names, cmd.Name())
|
||||
return strings.Join(parent_names, " ")
|
||||
}
|
||||
|
||||
func show_usage(cmd *cobra.Command, use_pager bool) error {
|
||||
screen_width := 80
|
||||
if formatter.EscapeCodesAllowed() {
|
||||
var sz *unix.Winsize
|
||||
var tty_size_err error
|
||||
for {
|
||||
sz, tty_size_err = unix.IoctlGetWinsize(int(os.Stdout.Fd()), unix.TIOCGWINSZ)
|
||||
if tty_size_err != unix.EINTR {
|
||||
break
|
||||
}
|
||||
}
|
||||
if tty_size_err == nil && sz.Col < 80 {
|
||||
screen_width = int(sz.Col)
|
||||
}
|
||||
}
|
||||
var output strings.Builder
|
||||
use := cmd.Use
|
||||
idx := strings.Index(use, " ")
|
||||
if idx > -1 {
|
||||
use = use[idx+1:]
|
||||
} else {
|
||||
use = ""
|
||||
}
|
||||
fmt.Fprintln(&output, formatter.Title("Usage")+":", formatter.Exe(full_command_name(cmd)), use)
|
||||
fmt.Fprintln(&output)
|
||||
if len(cmd.Long) > 0 {
|
||||
format_with_indent(&output, cmd.Long, "", screen_width)
|
||||
} else if len(cmd.Short) > 0 {
|
||||
format_with_indent(&output, cmd.Short, "", screen_width)
|
||||
}
|
||||
if cmd.HasAvailableSubCommands() {
|
||||
fmt.Fprintln(&output)
|
||||
fmt.Fprintln(&output, formatter.Title("Commands")+":")
|
||||
for _, child := range cmd.Commands() {
|
||||
if child.Hidden {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintln(&output, " ", formatter.Opt(child.Name()))
|
||||
format_with_indent(&output, child.Short, " ", screen_width)
|
||||
}
|
||||
fmt.Fprintln(&output)
|
||||
format_with_indent(&output, "Get help for an individual command by running:", "", screen_width)
|
||||
fmt.Fprintln(&output, " ", full_command_name(cmd), formatter.Italic("command"), "-h")
|
||||
}
|
||||
if cmd.HasAvailableFlags() {
|
||||
options_title := cmd.Annotations["options_title"]
|
||||
if len(options_title) == 0 {
|
||||
options_title = "Options"
|
||||
}
|
||||
fmt.Fprintln(&output)
|
||||
fmt.Fprintln(&output, formatter.Title(options_title)+":")
|
||||
flag_set := cmd.LocalFlags()
|
||||
flag_set.VisitAll(func(flag *pflag.Flag) {
|
||||
fmt.Fprint(&output, formatter.Opt(" --"+flag.Name))
|
||||
if flag.Shorthand != "" {
|
||||
fmt.Fprint(&output, ", ", formatter.Opt("-"+flag.Shorthand))
|
||||
}
|
||||
defval := ""
|
||||
switch flag.Value.Type() {
|
||||
default:
|
||||
if flag.DefValue != "" {
|
||||
defval = fmt.Sprintf("[=%s]", formatter.Italic(flag.DefValue))
|
||||
}
|
||||
case "stringArray":
|
||||
if flag.DefValue != "[]" {
|
||||
defval = fmt.Sprintf("[=%s]", formatter.Italic(flag.DefValue))
|
||||
}
|
||||
case "bool":
|
||||
case "count":
|
||||
}
|
||||
if defval != "" {
|
||||
fmt.Fprint(&output, " ", defval)
|
||||
}
|
||||
fmt.Fprintln(&output)
|
||||
msg := flag.Usage
|
||||
switch flag.Name {
|
||||
case "help":
|
||||
msg = "Print this help message"
|
||||
case "version":
|
||||
msg = "Print the version of " + RootCmd.Name() + ": " + formatter.Italic(RootCmd.Version)
|
||||
}
|
||||
format_with_indent(&output, msg, " ", screen_width)
|
||||
fmt.Fprintln(&output)
|
||||
})
|
||||
}
|
||||
if cmd.Annotations["usage-suffix"] != "" {
|
||||
fmt.Fprintln(&output, cmd.Annotations["usage-suffix"])
|
||||
} else {
|
||||
fmt.Fprintln(&output, formatter.Italic(RootCmd.Name()), formatter.Opt(kitty.VersionString), "created by", formatter.Title("Kovid Goyal"))
|
||||
}
|
||||
output_text := output.String()
|
||||
// fmt.Printf("%#v\n", output_text)
|
||||
if use_pager && formatter.EscapeCodesAllowed() && cmd.Annotations["allow-pager"] != "no" {
|
||||
pager := exec.Command(kitty.DefaultPager[0], kitty.DefaultPager[1:]...)
|
||||
pager.Stdin = strings.NewReader(output_text)
|
||||
pager.Stdout = os.Stdout
|
||||
pager.Stderr = os.Stderr
|
||||
pager.Run()
|
||||
} else {
|
||||
cmd.OutOrStdout().Write([]byte(output_text))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FlagNormalizer(name string) string {
|
||||
return strings.ReplaceAll(name, "_", "-")
|
||||
}
|
||||
|
||||
func DisallowArgs(cmd *cobra.Command, args []string) error {
|
||||
if cmd.HasSubCommands() {
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("No sub-command specified. Use %s -h to get a list of available sub-commands", full_command_name(cmd))
|
||||
}
|
||||
cmd.SuggestionsMinimumDistance = 2
|
||||
suggestions := cmd.SuggestionsFor(args[0])
|
||||
es := "Not a valid subcommand: " + args[0]
|
||||
trailer := fmt.Sprintf("Use %s to get a list of available sub-commands", formatter.Bold(full_command_name(cmd)+" -h"))
|
||||
if len(suggestions) > 0 {
|
||||
es += "\nDid you mean?\n"
|
||||
for _, s := range suggestions {
|
||||
es += fmt.Sprintf("\t%s\n", formatter.Italic(s))
|
||||
}
|
||||
es += trailer
|
||||
} else {
|
||||
es += ". " + trailer
|
||||
}
|
||||
return fmt.Errorf("%s", es)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateCommand(cmd *cobra.Command) *cobra.Command {
|
||||
cmd.Annotations = make(map[string]string)
|
||||
cmd.SilenceErrors = true
|
||||
cmd.SilenceUsage = true
|
||||
cmd.PersistentFlags().SortFlags = false
|
||||
cmd.Flags().SortFlags = false
|
||||
cmd.Flags().SetNormalizeFunc(func(fs *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
return pflag.NormalizedName(FlagNormalizer(name))
|
||||
})
|
||||
cmd.PersistentFlags().SetNormalizeFunc(cmd.Flags().GetNormalizeFunc())
|
||||
if !cmd.Runnable() {
|
||||
cmd.Args = DisallowArgs
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func show_help(cmd *cobra.Command, args []string) {
|
||||
show_usage(cmd, true)
|
||||
}
|
||||
|
||||
func PrintError(err error) {
|
||||
fmt.Println(formatter.Err("Error")+":", err)
|
||||
}
|
||||
|
||||
func Init(root *cobra.Command) {
|
||||
vs := kitty.VersionString
|
||||
if kitty.VCSRevision != "" {
|
||||
vs = vs + " (" + kitty.VCSRevision + ")"
|
||||
}
|
||||
formatter = markup.New(tty.IsTerminal(os.Stdout.Fd()))
|
||||
RootCmd = root
|
||||
root.Version = vs
|
||||
root.SetUsageFunc(func(cmd *cobra.Command) error { return show_usage(cmd, false) })
|
||||
root.SetHelpFunc(show_help)
|
||||
root.SetHelpCommand(&cobra.Command{Hidden: true})
|
||||
root.CompletionOptions.DisableDefaultCmd = true
|
||||
}
|
||||
|
||||
func Execute(root *cobra.Command) error {
|
||||
return root.Execute()
|
||||
}
|
||||
|
||||
type FlagValGetter struct {
|
||||
Flags *pflag.FlagSet
|
||||
Err error
|
||||
}
|
||||
|
||||
func (self *FlagValGetter) String(name string) string {
|
||||
if self.Err != nil {
|
||||
return ""
|
||||
}
|
||||
ans, err := self.Flags.GetString(name)
|
||||
self.Err = err
|
||||
return ans
|
||||
}
|
||||
@ -238,11 +238,11 @@ type OptionGroup struct {
|
||||
}
|
||||
|
||||
func (self *OptionGroup) Clone(parent *Command) *OptionGroup {
|
||||
ans := OptionGroup{Title: self.Title, Options: make([]*Option, 0, len(self.Options))}
|
||||
ans := OptionGroup{Title: self.Title, Options: make([]*Option, len(self.Options))}
|
||||
for i, o := range self.Options {
|
||||
c := *o
|
||||
c.Parent = parent
|
||||
self.Options[i] = &c
|
||||
ans.Options[i] = &c
|
||||
}
|
||||
return &ans
|
||||
}
|
||||
@ -302,8 +302,8 @@ func (self *Command) Clone(parent *Command) *Command {
|
||||
ans := *self
|
||||
ans.Args = make([]string, 0, 8)
|
||||
ans.Parent = parent
|
||||
ans.SubCommandGroups = make([]*CommandGroup, 0, len(self.SubCommandGroups))
|
||||
ans.OptionGroups = make([]*OptionGroup, 0, len(self.OptionGroups))
|
||||
ans.SubCommandGroups = make([]*CommandGroup, len(self.SubCommandGroups))
|
||||
ans.OptionGroups = make([]*OptionGroup, len(self.OptionGroups))
|
||||
|
||||
for i, o := range self.OptionGroups {
|
||||
ans.OptionGroups[i] = o.Clone(&ans)
|
||||
@ -314,14 +314,11 @@ func (self *Command) Clone(parent *Command) *Command {
|
||||
return &ans
|
||||
}
|
||||
|
||||
func (self *Command) AddClone(group string, src *Command) (*Command, error) {
|
||||
func (self *Command) AddClone(group string, src *Command) *Command {
|
||||
c := src.Clone(self)
|
||||
g := self.AddSubCommandGroup(group)
|
||||
if g.FindSubCommand(c.Name) != nil {
|
||||
return nil, fmt.Errorf("A sub command with the name: %s already exists in %s", c.Name, self.Name)
|
||||
}
|
||||
g.SubCommands = append(g.SubCommands, c)
|
||||
return c, nil
|
||||
return c
|
||||
}
|
||||
|
||||
func NewRootCommand() *Command {
|
||||
@ -605,6 +602,19 @@ type Context struct {
|
||||
SeenCommands []*Command
|
||||
}
|
||||
|
||||
func GetOptionValue[T any](self *Command, name string) (ans T, err error) {
|
||||
opt := self.option_map[name]
|
||||
if opt == nil {
|
||||
err = fmt.Errorf("No option with the name: %s", name)
|
||||
return
|
||||
}
|
||||
ans, ok := opt.parsed_value().(T)
|
||||
if !ok {
|
||||
err = fmt.Errorf("The option %s is not of the correct type", name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (self *Command) GetOptionValues(pointer_to_options_struct any) error {
|
||||
val := reflect.ValueOf(pointer_to_options_struct).Elem()
|
||||
if val.Kind() != reflect.Struct {
|
||||
@ -689,7 +699,7 @@ func (self *Command) Exec(args ...string) {
|
||||
} else if cmd.Run != nil {
|
||||
exit_code, err = cmd.Run(cmd, cmd.Args)
|
||||
if err != nil {
|
||||
PrintError(err)
|
||||
ShowError(err)
|
||||
if exit_code == 0 {
|
||||
exit_code = 1
|
||||
}
|
||||
|
||||
@ -13,8 +13,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"kitty"
|
||||
@ -30,13 +28,6 @@ import (
|
||||
|
||||
var ProtocolVersion [3]int = [3]int{0, 26, 0}
|
||||
|
||||
func add_bool_set(cmd *cobra.Command, name string, short string, usage string) *bool {
|
||||
if short == "" {
|
||||
return cmd.Flags().Bool(name, false, usage)
|
||||
}
|
||||
return cmd.Flags().BoolP(name, short, false, usage)
|
||||
}
|
||||
|
||||
type GlobalOptions struct {
|
||||
to_network, to_address, password string
|
||||
to_address_is_from_env_var bool
|
||||
@ -142,7 +133,7 @@ type Response struct {
|
||||
}
|
||||
|
||||
type rc_io_data struct {
|
||||
cmd *cobra.Command
|
||||
cmd *cli.Command
|
||||
rc *utils.RemoteControlCmd
|
||||
serializer serializer_func
|
||||
on_key_event func(lp *loop.Loop, ke *loop.KeyEvent) error
|
||||
@ -294,82 +285,46 @@ func get_password(password string, password_file string, password_env string, us
|
||||
return ans, nil
|
||||
}
|
||||
|
||||
var all_commands map[string]func(*cobra.Command) *cobra.Command = make(map[string]func(*cobra.Command) *cobra.Command)
|
||||
var command_objects map[string]*cobra.Command = make(map[string]*cobra.Command)
|
||||
|
||||
func add_global_options(fs *pflag.FlagSet) {
|
||||
fs.String("to", "",
|
||||
"An address for the kitty instance to control. Corresponds to the address given"+
|
||||
" to the kitty instance via the :option:`kitty --listen-on` option or the :opt:`listen_on` setting in :file:`kitty.conf`. If not"+
|
||||
" specified, the environment variable :envvar:`KITTY_LISTEN_ON` is checked. If that"+
|
||||
" is also not found, messages are sent to the controlling terminal for this"+
|
||||
" process, i.e. they will only work if this process is run within a kitty window.")
|
||||
|
||||
fs.String("password", "",
|
||||
"A password to use when contacting kitty. This will cause kitty to ask the user"+
|
||||
" for permission to perform the specified action, unless the password has been"+
|
||||
" accepted before or is pre-configured in :file:`kitty.conf`.")
|
||||
|
||||
fs.String("password-file", "rc-pass",
|
||||
"A file from which to read the password. Trailing whitespace is ignored. Relative"+
|
||||
" paths are resolved from the kitty configuration directory. Use - to read from STDIN."+
|
||||
" Used if no :option:`--password` is supplied. Defaults to checking for the"+
|
||||
" :file:`rc-pass` file in the kitty configuration directory.")
|
||||
|
||||
fs.String("password-env", "KITTY_RC_PASSWORD",
|
||||
"The name of an environment variable to read the password from."+
|
||||
" Used if no :option:`--password-file` or :option:`--password` is supplied.")
|
||||
|
||||
cli.Choices(fs, "use-password", "If no password is available, kitty will usually just send the remote control command without a password. This option can be used to force it to always or never use the supplied password.", "if-available", "always", "never")
|
||||
var all_commands map[string]func(*cli.Command) *cli.Command = make(map[string]func(*cli.Command) *cli.Command)
|
||||
|
||||
func setup_global_options(cmd *cli.Command) (err error) {
|
||||
err = cmd.GetOptionValues(&rc_global_opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func setup_global_options(cmd *cobra.Command) (err error) {
|
||||
var v = cli.FlagValGetter{Flags: cmd.Flags()}
|
||||
to := v.String("to")
|
||||
password := v.String("password")
|
||||
password_file := v.String("password-file")
|
||||
password_env := v.String("password-env")
|
||||
use_password := v.String("use-password")
|
||||
if v.Err != nil {
|
||||
return v.Err
|
||||
}
|
||||
if to == "" {
|
||||
to = os.Getenv("KITTY_LISTEN_ON")
|
||||
if rc_global_opts.To == "" {
|
||||
rc_global_opts.To = os.Getenv("KITTY_LISTEN_ON")
|
||||
global_options.to_address_is_from_env_var = true
|
||||
}
|
||||
if to != "" {
|
||||
network, address, err := utils.ParseSocketAddress(to)
|
||||
if rc_global_opts.To != "" {
|
||||
network, address, err := utils.ParseSocketAddress(rc_global_opts.To)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
global_options.to_network = network
|
||||
global_options.to_address = address
|
||||
}
|
||||
q, err := get_password(password, password_file, password_env, use_password)
|
||||
q, err := get_password(rc_global_opts.Password, rc_global_opts.PasswordFile, rc_global_opts.PasswordEnv, rc_global_opts.UsePassword)
|
||||
global_options.password = q
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func EntryPoint(tool_root *cobra.Command) *cobra.Command {
|
||||
at_root_command := cli.CreateCommand(&cobra.Command{
|
||||
Use: "@ [global options] command [command options] [command args]",
|
||||
Short: "Control kitty remotely",
|
||||
Long: "Control kitty by sending it commands. Set the allow_remote_control option in :file:`kitty.conf` or use a password, for this to work.",
|
||||
})
|
||||
at_root_command.Annotations["options_title"] = "Global options"
|
||||
add_global_options(at_root_command.PersistentFlags())
|
||||
func EntryPoint(tool_root *cli.Command) *cli.Command {
|
||||
at_root_command := tool_root.AddSubCommand("", "@")
|
||||
at_root_command.Usage = "[global options] [sub-command] [sub-command options] [sub-command args]"
|
||||
at_root_command.ShortDescription = "Control kitty remotely"
|
||||
at_root_command.HelpText = "Control kitty by sending it commands. Set the allow_remote_control option in :file:`kitty.conf` for this to work. When run without any sub-commands this will start an interactive shell to control kitty."
|
||||
add_rc_global_opts(at_root_command)
|
||||
|
||||
for cmd_name, reg_func := range all_commands {
|
||||
global_options_group := at_root_command.OptionGroups[0]
|
||||
|
||||
for _, reg_func := range all_commands {
|
||||
c := reg_func(at_root_command)
|
||||
at_root_command.AddCommand(c)
|
||||
command_objects[cmd_name] = c
|
||||
alias := *c
|
||||
alias.Use = "@" + alias.Use
|
||||
alias.Hidden = true
|
||||
add_global_options(alias.Flags())
|
||||
tool_root.AddCommand(&alias)
|
||||
clone := tool_root.AddClone("", c)
|
||||
clone.Name = "@" + c.Name
|
||||
clone.Hidden = true
|
||||
clone.OptionGroups = append(clone.OptionGroups, global_options_group.Clone(clone))
|
||||
}
|
||||
return at_root_command
|
||||
}
|
||||
|
||||
@ -32,8 +32,8 @@ func parse_send_text(io_data *rc_io_data, args []string) error {
|
||||
generators = append(generators, text_gen)
|
||||
}
|
||||
|
||||
if options_send_text.from_file != "" {
|
||||
f, err := os.Open(options_send_text.from_file)
|
||||
if options_send_text.FromFile != "" {
|
||||
f, err := os.Open(options_send_text.FromFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -49,7 +49,7 @@ func parse_send_text(io_data *rc_io_data, args []string) error {
|
||||
generators = append(generators, file_gen)
|
||||
}
|
||||
|
||||
if options_send_text.stdin {
|
||||
if options_send_text.Stdin {
|
||||
pending_key_events := make([]string, 0, 1)
|
||||
|
||||
io_data.on_key_event = func(lp *loop.Loop, ke *loop.KeyEvent) error {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||
|
||||
// this file is autogenerated by __FILE__ do not edit
|
||||
// Code generated by gen-go-code.py; DO NOT EDIT.
|
||||
|
||||
package at
|
||||
|
||||
@ -11,9 +11,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"kitty/tools/cli"
|
||||
"kitty/tools/utils"
|
||||
)
|
||||
@ -31,7 +28,7 @@ type CMD_NAME_json_type struct {
|
||||
JSON_DECLARATION_CODE
|
||||
}
|
||||
|
||||
func create_payload_CMD_NAME(io_data *rc_io_data, flags *pflag.FlagSet, args []string) (err error) {
|
||||
func create_payload_CMD_NAME(io_data *rc_io_data, cmd *cli.Command, args []string) (err error) {
|
||||
payload := CMD_NAME_json_type{}
|
||||
JSON_INIT_CODE
|
||||
io_data.rc.Payload = payload
|
||||
@ -62,19 +59,22 @@ func create_rc_CMD_NAME(args []string) (*utils.RemoteControlCmd, error) {
|
||||
return &rc, nil
|
||||
}
|
||||
|
||||
func run_CMD_NAME(cmd *cobra.Command, args []string) (err error) {
|
||||
SET_OPTION_VALUES_CODE
|
||||
func run_CMD_NAME(cmd *cli.Command, args []string) (return_code int, err error) {
|
||||
err = cmd.GetOptionValues(&options_CMD_NAME)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rc, err := create_rc_CMD_NAME(args)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
nrv, err := cmd.Flags().GetBool("no-response")
|
||||
nrv, err := cli.GetOptionValue[bool](cmd, "NoResponse")
|
||||
if err == nil {
|
||||
rc.NoResponse = nrv
|
||||
}
|
||||
var timeout float64 = WAIT_TIMEOUT
|
||||
rt, err := cmd.Flags().GetFloat64("response-timeout")
|
||||
rt, err := cli.GetOptionValue[float64](cmd, "ResponseTimeout")
|
||||
if err == nil {
|
||||
timeout = rt
|
||||
}
|
||||
@ -84,31 +84,22 @@ func run_CMD_NAME(cmd *cobra.Command, args []string) (err error) {
|
||||
timeout: time.Duration(timeout * float64(time.Second)),
|
||||
string_response_is_err: STRING_RESPONSE_IS_ERROR,
|
||||
}
|
||||
err = create_payload_CMD_NAME(&io_data, cmd.Flags(), args)
|
||||
err = create_payload_CMD_NAME(&io_data, cmd, args)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
err = send_rc_command(&io_data)
|
||||
return
|
||||
}
|
||||
|
||||
func aliasNormalizeFunc_CMD_NAME(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
name = cli.FlagNormalizer(name)
|
||||
ALIAS_NORMALIZE_CODE
|
||||
return pflag.NormalizedName(name)
|
||||
}
|
||||
|
||||
func setup_CMD_NAME(root *cobra.Command) *cobra.Command {
|
||||
ans := cli.CreateCommand(&cobra.Command{
|
||||
Use: "CLI_NAME [options]" + "ARGSPEC",
|
||||
Short: "SHORT_DESC",
|
||||
Long: "LONG_DESC",
|
||||
RunE: run_CMD_NAME,
|
||||
})
|
||||
func setup_CMD_NAME(parent *cli.Command) *cli.Command {
|
||||
ans := parent.AddSubCommand("", "CMD_NAME")
|
||||
ans.Usage = "ARGSPEC"
|
||||
ans.ShortDescription = "SHORT_DESC"
|
||||
ans.HelpText = "LONG_DESC"
|
||||
ans.Run = run_CMD_NAME
|
||||
ADD_FLAGS_CODE
|
||||
ans.Flags().SetNormalizeFunc(aliasNormalizeFunc_CMD_NAME)
|
||||
|
||||
return ans
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ package main
|
||||
|
||||
import (
|
||||
"kitty/tools/cli"
|
||||
_ "kitty/tools/cmd/at"
|
||||
"kitty/tools/cmd/at"
|
||||
"kitty/tools/completion"
|
||||
)
|
||||
|
||||
@ -12,8 +12,9 @@ func main() {
|
||||
root := cli.NewRootCommand()
|
||||
root.ShortDescription = "Fast, statically compiled implementations for various kitty command-line tools"
|
||||
root.Usage = "command [command options] [command args]"
|
||||
// root.AddCommand(at.EntryPoint(root))
|
||||
|
||||
at.EntryPoint(root)
|
||||
completion.EntryPoint(root)
|
||||
|
||||
root.Exec()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user