diff --git a/kittens/quick_access_terminal/main.go b/kittens/quick_access_terminal/main.go index 837a8deda..0796f9140 100644 --- a/kittens/quick_access_terminal/main.go +++ b/kittens/quick_access_terminal/main.go @@ -3,9 +3,11 @@ package quick_access_terminal import ( "fmt" "os" + "path/filepath" "kitty/kittens/panel" "kitty/tools/cli" + "kitty/tools/config" "golang.org/x/sys/unix" ) @@ -14,13 +16,72 @@ var _ = fmt.Print var complete_kitty_listen_on = panel.CompleteKittyListenOn -func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) { +func load_config(opts *Options) (ans *Config, err error) { + ans = NewConfig() + p := config.ConfigParser{LineHandler: ans.Parse} + err = p.LoadConfig("quick-access-terminal.conf", opts.Config, opts.Override) + if err != nil { + return nil, err + } + return ans, nil +} + +func main(cmd *cli.Command, opts *Options, args []string) (rc int, err error) { + conf, err := load_config(opts) + if err != nil { + return 1, err + } kitty_exe, err := panel.GetQuickAccessKittyExe() if err != nil { return 1, err } - argv := []string{kitty_exe, "+kitten", "panel"} - argv = append(argv, o.AsCommandLine()...) + argv := []string{kitty_exe, "+kitten", "panel", "--toggle-visibility", "--exclusive-zone=0", "--override-exclusive-zone", "--layer=overlay", "--single-instance"} + argv = append(argv, fmt.Sprintf("--lines=%d", conf.Lines)) + argv = append(argv, fmt.Sprintf("--columns=%d", conf.Columns)) + argv = append(argv, fmt.Sprintf("--edge=%s", conf.Edge)) + if conf.Margin_top != 0 { + argv = append(argv, fmt.Sprintf("--margin-top=%d", conf.Margin_top)) + } + if conf.Margin_bottom != 0 { + argv = append(argv, fmt.Sprintf("--margin-bottom=%d", conf.Margin_bottom)) + } + if conf.Margin_left != 0 { + argv = append(argv, fmt.Sprintf("--margin-left=%d", conf.Margin_left)) + } + if conf.Margin_right != 0 { + argv = append(argv, fmt.Sprintf("--margin-right=%d", conf.Margin_right)) + } + if len(conf.Kitty_conf) > 0 { + for _, c := range conf.Kitty_conf { + argv = append(argv, fmt.Sprintf("--config=%s", c)) + } + } + if len(conf.Kitty_override) > 0 { + for _, c := range conf.Kitty_override { + argv = append(argv, fmt.Sprintf("--override=%s", c)) + } + } + + argv = append(argv, fmt.Sprintf("--override=background_opacity=%f", conf.Background_opacity)) + argv = append(argv, fmt.Sprintf("--app-id=%s", conf.App_id)) + argv = append(argv, fmt.Sprintf("--focus-policy=%s", conf.Focus_policy)) + if conf.Start_as_hidden { + argv = append(argv, `--start-as-hidden`) + } + if opts.Detach { + argv = append(argv, `--detach`) + } + if opts.DetachedLog != "" { + if dl, err := filepath.Abs(opts.DetachedLog); err != nil { + return 1, err + } else { + argv = append(argv, dl) + } + } + if opts.InstanceGroup != "" { + argv = append(argv, fmt.Sprintf("--instance-group=%s", opts.InstanceGroup)) + } + argv = append(argv, args...) err = unix.Exec(kitty_exe, argv, os.Environ()) rc = 1 diff --git a/kittens/quick_access_terminal/main.py b/kittens/quick_access_terminal/main.py index 7aba40415..c81077d53 100644 --- a/kittens/quick_access_terminal/main.py +++ b/kittens/quick_access_terminal/main.py @@ -3,34 +3,105 @@ import sys -from kitty.simple_cli_definitions import build_panel_cli_spec +from kitty.conf.types import Definition +from kitty.constants import appname +from kitty.simple_cli_definitions import CONFIG_HELP help_text = 'A quick access terminal window that you can bring up instantly with a keypress or a command.' +definition = Definition( + '!kittens.quick_access_terminal', +) + +agr = definition.add_group +egr = definition.end_group +opt = definition.add_option + +agr('qat', 'Window appearance') + +opt('lines', '25', option_type='positive_int', + long_text=''' +The number of lines shown in the window, when the window is along the top or bottom edges of the screen. +If it has the suffix :code:`px` then it sets the height of the window in pixels instead of lines. +''',) + +opt('columns', '80', option_type='positive_int', + long_text=''' +The number of columns shown in the window, when the window is along the left or right edges of the screen. +If it has the suffix :code:`px` then it sets the width of the window in pixels instead of columns. +''',) + +opt('edge', 'top', choices=('top', 'bottom', 'left', 'right'), + long_text='Which edge of the screen to place the window along') + +opt('background_opacity', '0.85', option_type='unit_float', long_text=''' +The background opacity of the window. This works the same as the kitty +option of the same name, it is present here as it has a different +default value for the quick access terminal. +''') + +opt('margin_left', '0', option_type='int', + long_text='Set the left margin for the window, in pixels. Has no effect for windows on the right edge of the screen.') + +opt('margin_right', '0', option_type='int', + long_text='Set the right margin for the window, in pixels. Has no effect for windows on the left edge of the screen.') + +opt('margin_top', '0', option_type='int', + long_text='Set the top margin for the window, in pixels. Has no effect for windows on the bottom edge of the screen.') + +opt('margin_bottom', '0', option_type='int', + long_text='Set the bottom margin for the window, in pixels. Has no effect for windows on the top edge of the screen.') + +opt('+kitty_conf', '', + long_text='Path to config file to use for kitty when drawing the window. Can be specified multiple times. By default, the' + ' normal kitty.conf is used. Relative paths are resolved with respect to the kitty config directory.' +) + +opt('+kitty_override', '', long_text='Override individual kitty configuration options, can be specified multiple times.' + ' Syntax: :italic:`name=value`. For example: :code:`font_size=20`.' +) + +opt('app_id', f'{appname}-quick-access', + long_text='The Wayland APP_ID assigned to the quick access window') + +opt('start_as_hidden', 'no', option_type='to_bool', + long_text='Whether to start the quick access terminal hidden. Useful if you are starting it as part of system startup.') + +opt('focus_policy', 'exclusive', choices=('exclusive', 'on-demand'), + long_text='How to manage window focus.') + def options_spec() -> str: - if not (ans := getattr(options_spec, 'ans', '')): - ans = build_panel_cli_spec({ - 'lines': '25', - 'columns': '80', - 'edge': 'top', - 'layer': 'overlay', - 'toggle_visibility': 'yes', - 'single_instance': 'yes', - 'instance_group': 'quake', - 'focus_policy': 'exclusive', - 'cls': 'kitty-quick-access', - 'exclusive_zone': '0', - 'override_exclusive_zone': 'yes', - 'override': 'background_opacity=0.8', - }) - setattr(options_spec, 'ans', ans) - return ans + return f''' +--config -c +type=list +completion=type:file ext:conf group:"Config files" kwds:none,NONE +{CONFIG_HELP.format(conf_name='quick-access-terminal', appname=appname)} +--override -o +type=list +Override individual configuration options, can be specified multiple times. +Syntax: :italic:`name=value`. For example: :italic:`-o lines=12` + + +--detach +type=bool-set +Detach from the controlling terminal, if any, running in an independent child process, +the parent process exits immediately. + + +--detached-log +Path to a log file to store STDOUT/STDERR when using :option:`--detach` + + +--instance-group +default=quick-access +The unique name of this quick access terminal Use a different name if you want multiple such terminals. +''' + def main(args: list[str]) -> None: - from ..panel.main import main as panel_main - return panel_main(args) + raise SystemExit('This kitten should be run as: kitten quick-access-terminal') if __name__ == '__main__': @@ -41,3 +112,5 @@ def main(args: list[str]) -> None: cd['options'] = options_spec cd['help_text'] = help_text cd['short_desc'] = help_text +elif __name__ == '__conf__': + sys.options_definition = definition # type: ignore diff --git a/kitty/conf/generate.py b/kitty/conf/generate.py index 0cece6e00..15a7a3ee8 100644 --- a/kitty/conf/generate.py +++ b/kitty/conf/generate.py @@ -466,8 +466,8 @@ def write_output(loc: str, defn: Definition, extra_after_type_defn: str = '') -> def go_type_data(parser_func: ParserFuncType, ctype: str, is_multiple: bool = False) -> tuple[str, str]: - if ctype: - if ctype == 'string': + if ctype or is_multiple: + if ctype in ('string', ''): if is_multiple: return 'string', '[]string{val}, nil' return 'string', 'val, nil' @@ -493,7 +493,7 @@ def go_type_data(parser_func: ParserFuncType, ctype: str, is_multiple: bool = Fa if p == 'positive_float': return 'float64', 'config.PositiveFloat(val, 10, 64)' if p == 'unit_float': - return 'float64', 'config.UnitFloat(val, 10, 64)' + return 'float64', 'config.UnitFloat(val)' if p == 'python_string': return 'string', 'config.StringLiteral(val)' th = get_type_hints(parser_func)