mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-25 17:52:02 +02:00
Automap a bunch of json fields from identically named options
This commit is contained in:
@@ -4,13 +4,15 @@
|
|||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from contextlib import contextmanager, suppress
|
from contextlib import contextmanager, suppress
|
||||||
from typing import Dict, Iterator, List, Tuple, Union
|
from typing import Dict, Iterator, List, Tuple, Union
|
||||||
|
|
||||||
import kitty.constants as kc
|
import kitty.constants as kc
|
||||||
from kittens.tui.operations import Mode
|
from kittens.tui.operations import Mode
|
||||||
from kitty.cli import (
|
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_encoding import config_mod_map
|
||||||
from kitty.key_names import (
|
from kitty.key_names import (
|
||||||
@@ -98,24 +100,34 @@ def build_go_code(name: str, cmd: RemoteCommand, seq: OptionSpecSeq, template: s
|
|||||||
alias_map = {}
|
alias_map = {}
|
||||||
od: List[str] = []
|
od: List[str] = []
|
||||||
ov: List[str] = []
|
ov: List[str] = []
|
||||||
for x in seq:
|
option_map: Dict[str, GoOption] = {}
|
||||||
if isinstance(x, str):
|
for o in go_options_for_seq(seq):
|
||||||
continue
|
field_dest = o.go_var_name.rstrip('_')
|
||||||
o = GoOption(name, x)
|
option_map[field_dest] = o
|
||||||
if o.aliases:
|
if o.aliases:
|
||||||
alias_map[o.long] = tuple(o.aliases)
|
alias_map[o.long] = tuple(o.aliases)
|
||||||
a(o.to_flag_definition())
|
a(o.to_flag_definition())
|
||||||
if o.dest in ('no_response', 'response_timeout'):
|
if o.dest in ('no_response', 'response_timeout'):
|
||||||
continue
|
continue
|
||||||
od.append(f'{o.go_var_name} {o.go_type}')
|
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] = []
|
jd: List[str] = []
|
||||||
|
json_fields = []
|
||||||
for line in cmd.protocol_spec.splitlines():
|
for line in cmd.protocol_spec.splitlines():
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
if ':' not in line:
|
if ':' not in line:
|
||||||
continue
|
continue
|
||||||
f = JSONField(line)
|
f = JSONField(line)
|
||||||
|
json_fields.append(f)
|
||||||
jd.append(f.go_declaration())
|
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(
|
ans = replace(
|
||||||
template,
|
template,
|
||||||
@@ -129,6 +141,7 @@ def build_go_code(name: str, cmd: RemoteCommand, seq: OptionSpecSeq, template: s
|
|||||||
OPTIONS_DECLARATION_CODE='\n'.join(od),
|
OPTIONS_DECLARATION_CODE='\n'.join(od),
|
||||||
SET_OPTION_VALUES_CODE='\n'.join(ov),
|
SET_OPTION_VALUES_CODE='\n'.join(ov),
|
||||||
JSON_DECLARATION_CODE='\n'.join(jd),
|
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',
|
STRING_RESPONSE_IS_ERROR='true' if cmd.string_return_is_error else 'false',
|
||||||
)
|
)
|
||||||
return ans
|
return ans
|
||||||
|
|||||||
13
kitty/cli.py
13
kitty/cli.py
@@ -49,8 +49,7 @@ go_getter_map = {
|
|||||||
|
|
||||||
class GoOption:
|
class GoOption:
|
||||||
|
|
||||||
def __init__(self, cmd_name: str, x: OptionDict) -> None:
|
def __init__(self, x: OptionDict) -> None:
|
||||||
self.cmd_name = cmd_name
|
|
||||||
flags = sorted(x['aliases'], key=len)
|
flags = sorted(x['aliases'], key=len)
|
||||||
short = ''
|
short = ''
|
||||||
self.aliases = []
|
self.aliases = []
|
||||||
@@ -107,13 +106,19 @@ class GoOption:
|
|||||||
else:
|
else:
|
||||||
raise TypeError(f'Unknown type of CLI option: {self.type} for {self.long}')
|
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]
|
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'{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
|
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 = '''\
|
CONFIG_HELP = '''\
|
||||||
Specify a path to the configuration file(s) to use. All configuration files are
|
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.
|
merged onto the builtin :file:`{conf_name}.conf`, overriding the builtin values.
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ class CloseTab(RemoteCommand):
|
|||||||
|
|
||||||
protocol_spec = __doc__ = '''
|
protocol_spec = __doc__ = '''
|
||||||
match/str: Which tab to close
|
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
|
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
|
ignore_no_match/bool: Boolean indicating whether no matches should be ignored or return an error
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ if TYPE_CHECKING:
|
|||||||
class CloseWindow(RemoteCommand):
|
class CloseWindow(RemoteCommand):
|
||||||
protocol_spec = __doc__ = '''
|
protocol_spec = __doc__ = '''
|
||||||
match/str: Which window to close
|
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
|
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
|
ignore_no_match/bool: Boolean indicating whether no matches should be ignored or return an error
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ screen edges).
|
|||||||
|
|
||||||
|
|
||||||
--clear-selection
|
--clear-selection
|
||||||
|
type=bool-set
|
||||||
Clear the selection in the matched window, if any.
|
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_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
|
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
|
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"
|
marker/str: Specification for marker for new window, for example: "text 1 ERROR"
|
||||||
logo/str: Path to window logo
|
logo/str: Path to window logo
|
||||||
logo_position/str: Window logo position as string or empty string to use default
|
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`
|
window_type/choices.kitty.os: One of :code:`kitty` or :code:`os`
|
||||||
new_tab/bool: Boolean indicating whether to open a new tab
|
new_tab/bool: Boolean indicating whether to open a new tab
|
||||||
tab_title/str: Title for the 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'
|
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'
|
And the second item being either 'p' for pages or 'l' for lines or 'u'
|
||||||
for unscrolling by lines.
|
for unscrolling by lines.
|
||||||
match/str: The window to scroll
|
match/str: The window to scroll
|
||||||
no_response/bool: Boolean indicating whether to wait for a response
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
short_desc = 'Scroll the specified windows'
|
short_desc = 'Scroll the specified windows'
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ class SignalChild(RemoteCommand):
|
|||||||
protocol_spec = __doc__ = '''
|
protocol_spec = __doc__ = '''
|
||||||
signals/list.str: The signals, a list of names, such as :code:`SIGTERM`, :code:`SIGKILL`, :code:`SIGUSR1`, etc.
|
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
|
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'
|
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
|
JSON_DECLARATION_CODE
|
||||||
}
|
}
|
||||||
|
|
||||||
var CMD_NAME_json CMD_NAME_json_type
|
func create_payload_CMD_NAME(io_data *rc_io_data, flags *pflag.FlagSet, args []string) (err error) {
|
||||||
|
payload := CMD_NAME_json_type{}
|
||||||
func create_payload_CMD_NAME(io_data *rc_io_data, args []string) (err error) {
|
JSON_INIT_CODE
|
||||||
|
io_data.rc.Payload = payload
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ func run_CMD_NAME(cmd *cobra.Command, args []string) (err error) {
|
|||||||
timeout: time.Duration(timeout * float64(time.Second)),
|
timeout: time.Duration(timeout * float64(time.Second)),
|
||||||
string_response_is_err: STRING_RESPONSE_IS_ERROR,
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
type RemoteControlCmd struct {
|
type RemoteControlCmd struct {
|
||||||
Cmd string `json:"cmd"`
|
Cmd string `json:"cmd"`
|
||||||
Version [3]int `json:"version"`
|
Version [3]int `json:"version"`
|
||||||
NoResponse bool `json:"no_response,omitempty"`
|
NoResponse bool `json:"no_response,omitempty"`
|
||||||
Payload *interface{} `json:"payload,omitempty"`
|
Payload interface{} `json:"payload,omitempty"`
|
||||||
Timestamp int64 `json:"timestamp,omitempty"`
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
Async string `json:"async,omitempty"`
|
Async string `json:"async,omitempty"`
|
||||||
CancelAsync bool `json:"cancel_async,omitempty"`
|
CancelAsync bool `json:"cancel_async,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type EncryptedRemoteControlCmd struct {
|
type EncryptedRemoteControlCmd struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user