more work on porting rc command parsing to Go
This commit is contained in:
parent
79c8862d4c
commit
6f4968305a
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import subprocess
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from kitty.conf.generate import write_output
|
from kitty.conf.generate import write_output
|
||||||
@ -11,14 +12,25 @@ from kitty.conf.generate import write_output
|
|||||||
def patch_color_list(path: str, colors: List[str], name: str, spc: str = ' ') -> None:
|
def patch_color_list(path: str, colors: List[str], name: str, spc: str = ' ') -> None:
|
||||||
with open(path, 'r+') as f:
|
with open(path, 'r+') as f:
|
||||||
raw = f.read()
|
raw = f.read()
|
||||||
nraw = re.sub(
|
colors = sorted(colors)
|
||||||
fr'(# {name}_COLORS_START).+?(\s+# {name}_COLORS_END)',
|
if path.endswith('.go'):
|
||||||
r'\1' + f'\n{spc}' + f'\n{spc}'.join(map(lambda x: f'{x!r},', sorted(colors))) + r'\2',
|
spc = '\t'
|
||||||
raw, flags=re.DOTALL | re.MULTILINE)
|
nraw = re.sub(
|
||||||
|
fr'(// {name}_COLORS_START).+?(\s+// {name}_COLORS_END)',
|
||||||
|
r'\1' + f'\n{spc}' + f'\n{spc}'.join(map(lambda x: f'"{x}":true,', colors)) + r'\2',
|
||||||
|
raw, flags=re.DOTALL | re.MULTILINE)
|
||||||
|
else:
|
||||||
|
nraw = re.sub(
|
||||||
|
fr'(# {name}_COLORS_START).+?(\s+# {name}_COLORS_END)',
|
||||||
|
r'\1' + f'\n{spc}' + f'\n{spc}'.join(map(lambda x: f'{x!r},', colors)) + r'\2',
|
||||||
|
raw, flags=re.DOTALL | re.MULTILINE)
|
||||||
if nraw != raw:
|
if nraw != raw:
|
||||||
f.seek(0)
|
f.seek(0)
|
||||||
f.truncate()
|
f.truncate()
|
||||||
f.write(nraw)
|
f.write(nraw)
|
||||||
|
f.flush()
|
||||||
|
if path.endswith('.go'):
|
||||||
|
subprocess.check_call(['gofmt', '-w', path])
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
@ -34,6 +46,7 @@ def main() -> None:
|
|||||||
elif opt.parser_func.__name__ in ('to_color', 'titlebar_color', 'macos_titlebar_color'):
|
elif opt.parser_func.__name__ in ('to_color', 'titlebar_color', 'macos_titlebar_color'):
|
||||||
all_colors.append(opt.name)
|
all_colors.append(opt.name)
|
||||||
patch_color_list('kitty/rc/set_colors.py', nullable_colors, 'NULLABLE')
|
patch_color_list('kitty/rc/set_colors.py', nullable_colors, 'NULLABLE')
|
||||||
|
patch_color_list('tools/cmd/at/set_colors.go', nullable_colors, 'NULLABLE')
|
||||||
patch_color_list('kittens/themes/collection.py', all_colors, 'ALL', ' ' * 8)
|
patch_color_list('kittens/themes/collection.py', all_colors, 'ALL', ' ' * 8)
|
||||||
|
|
||||||
from kittens.diff.options.definition import definition as kd
|
from kittens.diff.options.definition import definition as kd
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
import sys
|
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, Set, Tuple, Union
|
||||||
|
|
||||||
import kitty.constants as kc
|
import kitty.constants as kc
|
||||||
from kittens.tui.operations import Mode
|
from kittens.tui.operations import Mode
|
||||||
@ -123,19 +123,21 @@ def build_go_code(name: str, cmd: RemoteCommand, seq: OptionSpecSeq, template: s
|
|||||||
field_types[f.field] = f.field_type
|
field_types[f.field] = f.field_type
|
||||||
jd.append(f.go_declaration())
|
jd.append(f.go_declaration())
|
||||||
jc: List[str] = []
|
jc: List[str] = []
|
||||||
|
handled_fields: Set[str] = set()
|
||||||
|
try:
|
||||||
|
jc.extend(cmd.args.as_go_code(name, field_types, handled_fields))
|
||||||
|
except TypeError:
|
||||||
|
print(f'Cant parse args for cmd: {name}', file=sys.stderr)
|
||||||
|
|
||||||
for field in json_fields:
|
for field in json_fields:
|
||||||
if field.field in option_map:
|
if field.field in option_map:
|
||||||
o = option_map[field.field]
|
o = option_map[field.field]
|
||||||
jc.append(f'payload.{field.struct_field_name} = options_{name}.{o.go_var_name}')
|
jc.append(f'payload.{field.struct_field_name} = options_{name}.{o.go_var_name}')
|
||||||
|
elif field.field in handled_fields:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
print(f'Cant map field: {field.field} for cmd: {name}', file=sys.stderr)
|
print(f'Cant map field: {field.field} for cmd: {name}', file=sys.stderr)
|
||||||
continue
|
print('TODO: test set_window_logo, set_window_background, set_font_size, send_text, env, scroll_window', file=sys.stderr)
|
||||||
try:
|
|
||||||
jc.extend(cmd.args.as_go_code(name, field_types))
|
|
||||||
except TypeError:
|
|
||||||
print(f'Cant parse args for cmd: {name}', file=sys.stderr)
|
|
||||||
|
|
||||||
print('TODO: test set_window_logo, send_text, env, scroll_window', file=sys.stderr)
|
|
||||||
|
|
||||||
argspec = cmd.args.spec
|
argspec = cmd.args.spec
|
||||||
if argspec:
|
if argspec:
|
||||||
|
|||||||
@ -172,6 +172,7 @@ class ArgsHandling:
|
|||||||
minimum_count: int = -1
|
minimum_count: int = -1
|
||||||
first_rest: Optional[Tuple[str, str]] = None
|
first_rest: Optional[Tuple[str, str]] = None
|
||||||
special_parse: str = ''
|
special_parse: str = ''
|
||||||
|
args_choices: Optional[Callable[[], Iterable[str]]] = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def args_count(self) -> Optional[int]:
|
def args_count(self) -> Optional[int]:
|
||||||
@ -193,6 +194,11 @@ class ArgsHandling:
|
|||||||
yield '}'
|
yield '}'
|
||||||
if self.minimum_count > -1:
|
if self.minimum_count > -1:
|
||||||
yield f'if len(args) < {self.minimum_count} {{ return fmt.Errorf("%s", Must specify at least {self.minimum_count} arguments to {cmd_name}) }}'
|
yield f'if len(args) < {self.minimum_count} {{ return fmt.Errorf("%s", Must specify at least {self.minimum_count} arguments to {cmd_name}) }}'
|
||||||
|
if self.args_choices:
|
||||||
|
achoices = tuple(self.args_choices())
|
||||||
|
yield 'achoices := map[string]bool{' + ' '.join(f'"{x}":true,' for x in achoices) + '}'
|
||||||
|
yield 'for _, a := range args {'
|
||||||
|
yield 'if !achoices[a] { return fmt.Errorf("Not a valid choice: %s. Allowed values are: %s", a, "' + ', '.join(achoices) + '") }'
|
||||||
if self.json_field:
|
if self.json_field:
|
||||||
jf = self.json_field
|
jf = self.json_field
|
||||||
dest = f'payload.{jf.capitalize()}'
|
dest = f'payload.{jf.capitalize()}'
|
||||||
@ -207,6 +213,10 @@ class ArgsHandling:
|
|||||||
if self.special_parse:
|
if self.special_parse:
|
||||||
if self.special_parse.startswith('!'):
|
if self.special_parse.startswith('!'):
|
||||||
yield f'io_data.multiple_payload_generator, err = {self.special_parse[1:]}'
|
yield f'io_data.multiple_payload_generator, err = {self.special_parse[1:]}'
|
||||||
|
elif self.special_parse.startswith('+'):
|
||||||
|
fields, sp = self.special_parse[1:].split(':', 1)
|
||||||
|
handled_fields.update(set(fields.split(',')))
|
||||||
|
yield f'err = {sp}'
|
||||||
else:
|
else:
|
||||||
yield f'{dest}, err = {self.special_parse}'
|
yield f'{dest}, err = {self.special_parse}'
|
||||||
yield 'if err != nil { return err }'
|
yield 'if err != nil { return err }'
|
||||||
|
|||||||
@ -101,7 +101,7 @@ Path to a file whose contents you wish to send. Note that in this case the file
|
|||||||
are sent as is, not interpreted for escapes.
|
are sent as is, not interpreted for escapes.
|
||||||
'''
|
'''
|
||||||
no_response = True
|
no_response = True
|
||||||
argspec = '[TEXT TO SEND]'
|
args = RemoteCommand.Args(spec='[TEXT TO SEND]', json_field='data', special_parse='+session_id:parse_send_text(io_data, args)')
|
||||||
|
|
||||||
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
||||||
limit = 1024
|
limit = 1024
|
||||||
|
|||||||
@ -63,9 +63,8 @@ default=false
|
|||||||
Don't wait for a response from kitty. This means that even if setting the background image
|
Don't wait for a response from kitty. This means that even if setting the background image
|
||||||
failed, the command will exit with a success code.
|
failed, the command will exit with a success code.
|
||||||
''' + '\n\n' + MATCH_WINDOW_OPTION
|
''' + '\n\n' + MATCH_WINDOW_OPTION
|
||||||
argspec = 'PATH_TO_PNG_IMAGE'
|
args = RemoteCommand.Args(spec='PATH_TO_PNG_IMAGE', count=1, special_parse='!read_window_logo(args[0])', completion={
|
||||||
args_count = 1
|
'files': ('PNG Images', ('*.png',))})
|
||||||
args_completion = {'files': ('PNG Images', ('*.png',))}
|
|
||||||
images_in_flight: Dict[str, IO[bytes]] = {}
|
images_in_flight: Dict[str, IO[bytes]] = {}
|
||||||
is_asynchronous = True
|
is_asynchronous = True
|
||||||
|
|
||||||
|
|||||||
@ -37,8 +37,7 @@ By default, background opacity are only changed for the currently active window.
|
|||||||
cause background opacity to be changed in all windows.
|
cause background opacity to be changed in all windows.
|
||||||
|
|
||||||
''' + '\n\n' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t')
|
''' + '\n\n' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t')
|
||||||
argspec = 'OPACITY'
|
args = RemoteCommand.Args(spec='OPACITY', count=1, json_field='opacity')
|
||||||
args_count = 1
|
|
||||||
|
|
||||||
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
||||||
opacity = max(0.1, min(float(args[0]), 1.0))
|
opacity = max(0.1, min(float(args[0]), 1.0))
|
||||||
|
|||||||
@ -89,7 +89,8 @@ type=bool-set
|
|||||||
Restore all colors to the values they had at kitty startup. Note that if you specify
|
Restore all colors to the values they had at kitty startup. Note that if you specify
|
||||||
this option, any color arguments are ignored and :option:`kitty @ set-colors --configured` and :option:`kitty @ set-colors --all` are implied.
|
this option, any color arguments are ignored and :option:`kitty @ set-colors --configured` and :option:`kitty @ set-colors --all` are implied.
|
||||||
''' + '\n\n' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t')
|
''' + '\n\n' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t')
|
||||||
args = RemoteCommand.Args(spec='COLOR_OR_FILE ...', completion={'files': ('CONF files', ('*.conf',))})
|
args = RemoteCommand.Args(spec='COLOR_OR_FILE ...', json_field='colors', special_parse='parse_colors_and_files(args)', completion={
|
||||||
|
'files': ('CONF files', ('*.conf',))})
|
||||||
|
|
||||||
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
||||||
final_colors: Dict[str, Optional[int]] = {}
|
final_colors: Dict[str, Optional[int]] = {}
|
||||||
|
|||||||
@ -41,8 +41,8 @@ type=bool-set
|
|||||||
Change the default enabled layout value so that the new value takes effect for all newly created tabs
|
Change the default enabled layout value so that the new value takes effect for all newly created tabs
|
||||||
as well.
|
as well.
|
||||||
'''
|
'''
|
||||||
argspec = 'LAYOUTS'
|
args = RemoteCommand.Args(
|
||||||
args_completion = {'names': ('Layouts', layout_names)}
|
spec='LAYOUT ...', minimum_count=1, json_field='layouts', completion={'names': ('Layouts', layout_names)}, args_choices=layout_names)
|
||||||
|
|
||||||
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
||||||
if len(args) < 1:
|
if len(args) < 1:
|
||||||
|
|||||||
@ -28,8 +28,7 @@ class SetFontSize(RemoteCommand):
|
|||||||
' with a :code:`+` or :code:`-` increments the font size by the specified'
|
' with a :code:`+` or :code:`-` increments the font size by the specified'
|
||||||
' amount.'
|
' amount.'
|
||||||
)
|
)
|
||||||
argspec = 'FONT_SIZE'
|
args = RemoteCommand.Args(spec='FONT_SIZE', count=1, special_parse='+increment_op:parse_set_font_size(args[0], io_data)', json_field='size')
|
||||||
args_count = 1
|
|
||||||
options_spec = '''\
|
options_spec = '''\
|
||||||
--all -a
|
--all -a
|
||||||
type=bool-set
|
type=bool-set
|
||||||
|
|||||||
@ -95,7 +95,7 @@ type=bool-set
|
|||||||
Also change the configured paddings and margins (i.e. the settings kitty will use for new
|
Also change the configured paddings and margins (i.e. the settings kitty will use for new
|
||||||
windows).
|
windows).
|
||||||
''' + '\n\n' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t')
|
''' + '\n\n' + MATCH_WINDOW_OPTION + '\n\n' + MATCH_TAB_OPTION.replace('--match -m', '--match-tab -t')
|
||||||
argspec = 'MARGIN_OR_PADDING ...'
|
args = RemoteCommand.Args(spec='MARGIN_OR_PADDING ...', minimum_count=1, json_field='settings', special_parse='parse_set_spacing(args)')
|
||||||
|
|
||||||
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
||||||
if not args:
|
if not args:
|
||||||
|
|||||||
@ -57,7 +57,7 @@ the keyword NONE to revert to using the default colors.
|
|||||||
type=bool-set
|
type=bool-set
|
||||||
Close the tab this command is run in, rather than the active tab.
|
Close the tab this command is run in, rather than the active tab.
|
||||||
'''
|
'''
|
||||||
argspec = 'COLORS'
|
args = RemoteCommand.Args(spec='COLORS', json_field='colors', minimum_count=1, special_parse='parse_tab_colors(args)')
|
||||||
|
|
||||||
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@ -28,7 +28,7 @@ class SetTabTitle(RemoteCommand):
|
|||||||
' title of the currently active window in the tab is used.'
|
' title of the currently active window in the tab is used.'
|
||||||
)
|
)
|
||||||
options_spec = MATCH_TAB_OPTION
|
options_spec = MATCH_TAB_OPTION
|
||||||
argspec = 'TITLE ...'
|
args = RemoteCommand.Args(spec='TITLE ...', json_field='title')
|
||||||
|
|
||||||
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
def message_to_kitty(self, global_opts: RCOptions, opts: 'CLIOptions', args: ArgsType) -> PayloadType:
|
||||||
return {'title': ' '.join(args), 'match': opts.match}
|
return {'title': ' '.join(args), 'match': opts.match}
|
||||||
|
|||||||
60
tools/cmd/at/send_text.go
Normal file
60
tools/cmd/at/send_text.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
package at
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type generator_function func(io_data *rc_io_data) (bool, error)
|
||||||
|
|
||||||
|
func parse_send_text(io_data *rc_io_data, args []string) error {
|
||||||
|
generators := make([]generator_function, 0, 1)
|
||||||
|
var payload send_text_json_type = io_data.rc.Payload.(send_text_json_type)
|
||||||
|
|
||||||
|
if len(args) > 0 {
|
||||||
|
text := strings.Join(args, " ")
|
||||||
|
text_gen := func(io_data *rc_io_data) (bool, error) {
|
||||||
|
payload.Data = "text:" + text[:2048]
|
||||||
|
text = text[2048:]
|
||||||
|
return len(text) == 0, nil
|
||||||
|
}
|
||||||
|
generators = append(generators, text_gen)
|
||||||
|
}
|
||||||
|
|
||||||
|
if options_send_text.from_file != "" {
|
||||||
|
f, err := os.Open(options_send_text.from_file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
chunk := make([]byte, 2048)
|
||||||
|
file_gen := func(io_data *rc_io_data) (bool, error) {
|
||||||
|
n, err := f.Read(chunk)
|
||||||
|
if err != nil && !errors.Is(err, io.EOF) {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
payload.Data = "base64:" + base64.StdEncoding.EncodeToString(chunk[:n])
|
||||||
|
return n == 0, nil
|
||||||
|
}
|
||||||
|
generators = append(generators, file_gen)
|
||||||
|
}
|
||||||
|
|
||||||
|
io_data.multiple_payload_generator = func(io_data *rc_io_data) (bool, error) {
|
||||||
|
if len(generators) == 0 {
|
||||||
|
payload.Data = "text:"
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
finished, err := generators[0](io_data)
|
||||||
|
if finished {
|
||||||
|
generators = generators[1:]
|
||||||
|
finished = len(generators) == 0
|
||||||
|
}
|
||||||
|
return finished, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
74
tools/cmd/at/set_colors.go
Normal file
74
tools/cmd/at/set_colors.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
package at
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"kitty/tools/utils"
|
||||||
|
"kitty/tools/utils/style"
|
||||||
|
)
|
||||||
|
|
||||||
|
var nullable_colors = map[string]bool{
|
||||||
|
// generated by gen-config.py do not edit
|
||||||
|
// NULLABLE_COLORS_START
|
||||||
|
"active_border_color": true,
|
||||||
|
"cursor": true,
|
||||||
|
"cursor_text_color": true,
|
||||||
|
"selection_background": true,
|
||||||
|
"selection_foreground": true,
|
||||||
|
"tab_bar_background": true,
|
||||||
|
"tab_bar_margin_color": true,
|
||||||
|
"visual_bell_color": true,
|
||||||
|
// NULLABLE_COLORS_END
|
||||||
|
}
|
||||||
|
|
||||||
|
func set_color_in_color_map(key, val string, ans map[string]interface{}, check_nullable, skip_nullable bool) error {
|
||||||
|
if val == "none" {
|
||||||
|
if check_nullable && !nullable_colors[key] {
|
||||||
|
if skip_nullable {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("The color %s cannot be set to none", key)
|
||||||
|
}
|
||||||
|
ans[key] = nil
|
||||||
|
} else {
|
||||||
|
col, err := style.ParseColor(val)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("%s is not a valid color", val)
|
||||||
|
}
|
||||||
|
ans[key] = col.AsRGB()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse_colors_and_files(args []string) (map[string]interface{}, error) {
|
||||||
|
ans := make(map[string]interface{}, len(args))
|
||||||
|
for _, arg := range args {
|
||||||
|
key, val, found := utils.Cut(strings.ToLower(arg), "=")
|
||||||
|
if found {
|
||||||
|
err := set_color_in_color_map(key, val, ans, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
path := utils.Expanduser(arg)
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
scanner := bufio.NewScanner(f)
|
||||||
|
for scanner.Scan() {
|
||||||
|
key, val, found := utils.Cut(scanner.Text(), " ")
|
||||||
|
if found {
|
||||||
|
set_color_in_color_map(strings.ToLower(key), strings.ToLower(strings.TrimSpace(val)), ans, true, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ans, nil
|
||||||
|
}
|
||||||
20
tools/cmd/at/set_font_size.go
Normal file
20
tools/cmd/at/set_font_size.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
package at
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parse_set_font_size(arg string, io_data *rc_io_data) error {
|
||||||
|
payload := io_data.rc.Payload.(set_font_size_json_type)
|
||||||
|
if len(arg) > 0 && (arg[0] == '+' || arg[0] == '-') {
|
||||||
|
payload.Increment_op = arg[:1]
|
||||||
|
}
|
||||||
|
val, err := strconv.ParseFloat(arg, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
payload.Size = val
|
||||||
|
return nil
|
||||||
|
}
|
||||||
53
tools/cmd/at/set_spacing.go
Normal file
53
tools/cmd/at/set_spacing.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
package at
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"kitty/tools/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parse_set_spacing(args []string) (map[string]interface{}, error) {
|
||||||
|
ans := make(map[string]interface{}, len(args))
|
||||||
|
mapper := make(map[string][]string, 32)
|
||||||
|
types := [2]string{"margin", "padding"}
|
||||||
|
for _, q := range types {
|
||||||
|
mapper[q] = []string{q + "-left", q + "-top", q + "-right", q + "-bottom"}
|
||||||
|
mapper[q+"-h"] = []string{q + "-left", q + "-right"}
|
||||||
|
mapper[q+"-v"] = []string{q + "-top", q + "-bottom"}
|
||||||
|
mapper[q+"-left"] = []string{q + "left"}
|
||||||
|
mapper[q+"-right"] = []string{q + "right"}
|
||||||
|
mapper[q+"-top"] = []string{q + "top"}
|
||||||
|
mapper[q+"-bottom"] = []string{q + "bottom"}
|
||||||
|
}
|
||||||
|
for _, arg := range args {
|
||||||
|
k, v, found := utils.Cut(arg, "=")
|
||||||
|
if !found {
|
||||||
|
return nil, fmt.Errorf("%s is not a valid setting", arg)
|
||||||
|
}
|
||||||
|
k = strings.ToLower(k)
|
||||||
|
v = strings.ToLower(v)
|
||||||
|
which, found := mapper[k]
|
||||||
|
if !found {
|
||||||
|
return nil, fmt.Errorf("%s is not a valid edge specification", k)
|
||||||
|
}
|
||||||
|
if v == "default" {
|
||||||
|
for _, q := range which {
|
||||||
|
ans[q] = nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val, err := strconv.ParseFloat(v, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s is not a number", v)
|
||||||
|
}
|
||||||
|
for _, q := range which {
|
||||||
|
ans[q] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return ans, nil
|
||||||
|
}
|
||||||
30
tools/cmd/at/set_tab_color.go
Normal file
30
tools/cmd/at/set_tab_color.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
package at
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"kitty/tools/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var valid_color_names = map[string]bool{"active_fg": true, "active_bg": true, "inactive_fg": true, "inactive_bg": true}
|
||||||
|
|
||||||
|
func parse_tab_colors(args []string) (map[string]interface{}, error) {
|
||||||
|
ans := make(map[string]interface{}, len(args))
|
||||||
|
for _, arg := range args {
|
||||||
|
key, val, found := utils.Cut(strings.ToLower(arg), "=")
|
||||||
|
if !found {
|
||||||
|
return nil, fmt.Errorf("%s is not a valid setting", arg)
|
||||||
|
}
|
||||||
|
if !valid_color_names[key] {
|
||||||
|
return nil, fmt.Errorf("%s is not a valid color name", key)
|
||||||
|
}
|
||||||
|
err := set_color_in_color_map(key, val, ans, false, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ans, nil
|
||||||
|
}
|
||||||
@ -49,6 +49,6 @@ func read_window_logo(path string) (func(io_data *rc_io_data) (bool, error), err
|
|||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
buf = buf[:n]
|
buf = buf[:n]
|
||||||
return n == 0, nil
|
return false, nil
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,10 @@ func (self *RGBA) parse_rgb_strings(r string, g string, b string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RGBA) AsRGB() uint32 {
|
||||||
|
return uint32(self.Blue) | (uint32(self.Green) << 8) | (uint32(self.Red) << 16)
|
||||||
|
}
|
||||||
|
|
||||||
type color_type struct {
|
type color_type struct {
|
||||||
is_numbered bool
|
is_numbered bool
|
||||||
val RGBA
|
val RGBA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user