Automap a bunch of json fields from identically named options
This commit is contained in:
parent
b33a684357
commit
ef71b071db
11 changed files with 42 additions and 28 deletions
|
|
@ -4,13 +4,15 @@
|
|||
import io
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from contextlib import contextmanager, suppress
|
||||
from typing import Dict, Iterator, List, Tuple, Union
|
||||
|
||||
import kitty.constants as kc
|
||||
from kittens.tui.operations import Mode
|
||||
from kitty.cli import (
|
||||
GoOption, OptionSpecSeq, parse_option_spec, serialize_as_go_string
|
||||
GoOption, OptionSpecSeq, go_options_for_seq, parse_option_spec,
|
||||
serialize_as_go_string
|
||||
)
|
||||
from kitty.key_encoding import config_mod_map
|
||||
from kitty.key_names import (
|
||||
|
|
@ -98,24 +100,34 @@ def build_go_code(name: str, cmd: RemoteCommand, seq: OptionSpecSeq, template: s
|
|||
alias_map = {}
|
||||
od: List[str] = []
|
||||
ov: List[str] = []
|
||||
for x in seq:
|
||||
if isinstance(x, str):
|
||||
continue
|
||||
o = GoOption(name, x)
|
||||
option_map: Dict[str, GoOption] = {}
|
||||
for o in go_options_for_seq(seq):
|
||||
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'):
|
||||
continue
|
||||
od.append(f'{o.go_var_name} {o.go_type}')
|
||||
ov.append(o.set_flag_value())
|
||||
ov.append(o.set_flag_value(f'options_{name}'))
|
||||
jd: List[str] = []
|
||||
json_fields = []
|
||||
for line in cmd.protocol_spec.splitlines():
|
||||
line = line.strip()
|
||||
if ':' not in line:
|
||||
continue
|
||||
f = JSONField(line)
|
||||
json_fields.append(f)
|
||||
jd.append(f.go_declaration())
|
||||
jc: List[str] = []
|
||||
for field in json_fields:
|
||||
if field.field in option_map:
|
||||
o = option_map[field.field]
|
||||
jc.append(f'payload.{field.struct_field_name} = options_{name}.{o.go_var_name}')
|
||||
else:
|
||||
print(f'Cant map field: {field.field} for cmd: {name}', file=sys.stderr)
|
||||
continue
|
||||
|
||||
ans = replace(
|
||||
template,
|
||||
|
|
@ -129,6 +141,7 @@ def build_go_code(name: str, cmd: RemoteCommand, seq: OptionSpecSeq, template: s
|
|||
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),
|
||||
STRING_RESPONSE_IS_ERROR='true' if cmd.string_return_is_error else 'false',
|
||||
)
|
||||
return ans
|
||||
|
|
|
|||
13
kitty/cli.py
13
kitty/cli.py
|
|
@ -49,8 +49,7 @@ def serialize_as_go_string(x: str) -> str:
|
|||
|
||||
class GoOption:
|
||||
|
||||
def __init__(self, cmd_name: str, x: OptionDict) -> None:
|
||||
self.cmd_name = cmd_name
|
||||
def __init__(self, x: OptionDict) -> None:
|
||||
flags = sorted(x['aliases'], key=len)
|
||||
short = ''
|
||||
self.aliases = []
|
||||
|
|
@ -107,13 +106,19 @@ def to_flag_definition(self, base: str = 'ans.Flags()') -> str:
|
|||
else:
|
||||
raise TypeError(f'Unknown type of CLI option: {self.type} for {self.long}')
|
||||
|
||||
def set_flag_value(self, cmd: str = 'cmd') -> str:
|
||||
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'\noptions_{self.cmd_name}.{self.go_var_name} = {self.go_var_name}_temp'
|
||||
ans += f'\n{struct_name}.{self.go_var_name} = {self.go_var_name}_temp'
|
||||
return ans
|
||||
|
||||
|
||||
def go_options_for_seq(seq: 'OptionSpecSeq') -> Iterator[GoOption]:
|
||||
for x in seq:
|
||||
if not isinstance(x, str):
|
||||
yield GoOption(x)
|
||||
|
||||
|
||||
CONFIG_HELP = '''\
|
||||
Specify a path to the configuration file(s) to use. All configuration files are
|
||||
merged onto the builtin :file:`{conf_name}.conf`, overriding the builtin values.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ class CloseTab(RemoteCommand):
|
|||
|
||||
protocol_spec = __doc__ = '''
|
||||
match/str: Which tab to close
|
||||
no_response/bool: Boolean indicating whether to wait for a response
|
||||
self/bool: Boolean indicating whether to close the tab of the window the command is run in
|
||||
ignore_no_match/bool: Boolean indicating whether no matches should be ignored or return an error
|
||||
'''
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
class CloseWindow(RemoteCommand):
|
||||
protocol_spec = __doc__ = '''
|
||||
match/str: Which window to close
|
||||
no_response/bool: Boolean indicating whether to wait for a response
|
||||
self/bool: Boolean indicating whether to close the window the command is run in
|
||||
ignore_no_match/bool: Boolean indicating whether no matches should be ignored or return an error
|
||||
'''
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ class GetText(RemoteCommand):
|
|||
|
||||
|
||||
--clear-selection
|
||||
type=bool-set
|
||||
Clear the selection in the matched window, if any.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ class Launch(RemoteCommand):
|
|||
stdin_add_formatting/bool: Boolean indicating whether to add formatting codes to stdin
|
||||
stdin_add_line_wrap_markers/bool: Boolean indicating whether to add line wrap markers to stdin
|
||||
spacing/list.str: A list of spacing specifications, see the docs for the set-spacing command
|
||||
no_response/bool: Boolean indicating whether to send back the window id
|
||||
marker/str: Specification for marker for new window, for example: "text 1 ERROR"
|
||||
logo/str: Path to window logo
|
||||
logo_position/str: Window logo position as string or empty string to use default
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ class NewWindow(RemoteCommand):
|
|||
window_type/choices.kitty.os: One of :code:`kitty` or :code:`os`
|
||||
new_tab/bool: Boolean indicating whether to open a new tab
|
||||
tab_title/str: Title for the new tab
|
||||
no_response/bool: Boolean indicating whether to send back the window id
|
||||
'''
|
||||
|
||||
short_desc = 'Open new window'
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ class ScrollWindow(RemoteCommand):
|
|||
And the second item being either 'p' for pages or 'l' for lines or 'u'
|
||||
for unscrolling by lines.
|
||||
match/str: The window to scroll
|
||||
no_response/bool: Boolean indicating whether to wait for a response
|
||||
'''
|
||||
|
||||
short_desc = 'Scroll the specified windows'
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ class SignalChild(RemoteCommand):
|
|||
protocol_spec = __doc__ = '''
|
||||
signals/list.str: The signals, a list of names, such as :code:`SIGTERM`, :code:`SIGKILL`, :code:`SIGUSR1`, etc.
|
||||
match/str: Which windows to send the signals to
|
||||
no_response/bool: Boolean indicating whether to wait for a response
|
||||
'''
|
||||
|
||||
short_desc = 'Send a signal to the foreground process in the specified windows'
|
||||
|
|
|
|||
|
|
@ -26,9 +26,10 @@ type CMD_NAME_json_type struct {
|
|||
JSON_DECLARATION_CODE
|
||||
}
|
||||
|
||||
var CMD_NAME_json CMD_NAME_json_type
|
||||
|
||||
func create_payload_CMD_NAME(io_data *rc_io_data, args []string) (err error) {
|
||||
func create_payload_CMD_NAME(io_data *rc_io_data, flags *pflag.FlagSet, args []string) (err error) {
|
||||
payload := CMD_NAME_json_type{}
|
||||
JSON_INIT_CODE
|
||||
io_data.rc.Payload = payload
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -70,7 +71,7 @@ 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, args)
|
||||
err = create_payload_CMD_NAME(&io_data, cmd.Flags(), args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
package utils
|
||||
|
||||
type RemoteControlCmd struct {
|
||||
Cmd string `json:"cmd"`
|
||||
Version [3]int `json:"version"`
|
||||
NoResponse bool `json:"no_response,omitempty"`
|
||||
Payload *interface{} `json:"payload,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Async string `json:"async,omitempty"`
|
||||
CancelAsync bool `json:"cancel_async,omitempty"`
|
||||
Cmd string `json:"cmd"`
|
||||
Version [3]int `json:"version"`
|
||||
NoResponse bool `json:"no_response,omitempty"`
|
||||
Payload interface{} `json:"payload,omitempty"`
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
Async string `json:"async,omitempty"`
|
||||
CancelAsync bool `json:"cancel_async,omitempty"`
|
||||
}
|
||||
|
||||
type EncryptedRemoteControlCmd struct {
|
||||
|
|
|
|||
Loading…
Reference in a new issue