diff --git a/tools/cmd/ssh/main.go b/tools/cmd/ssh/main.go index 6fdf98968..da4ffc3d4 100644 --- a/tools/cmd/ssh/main.go +++ b/tools/cmd/ssh/main.go @@ -25,6 +25,7 @@ import ( "time" "kitty/tools/cli" + "kitty/tools/themes" "kitty/tools/tty" "kitty/tools/tui" "kitty/tools/tui/loop" @@ -549,6 +550,38 @@ func drain_potential_tty_garbage(term *tty.Term) { } } +func change_colors(color_scheme string) (ans string, err error) { + if color_scheme == "" { + return + } + var theme *themes.Theme + if !strings.HasSuffix(color_scheme, ".conf") { + cs := os.ExpandEnv(color_scheme) + tc, closer, err := themes.LoadThemes(-1) + if err != nil && errors.Is(err, themes.ErrNoCacheFound) { + tc, closer, err = themes.LoadThemes(time.Hour * 24) + } + if err != nil { + return "", err + } + defer closer.Close() + theme = tc.ThemeByName(cs) + if theme == nil { + return "", fmt.Errorf("No theme named %#v found", cs) + } + } else { + theme, err = themes.ThemeFromFile(utils.ResolveConfPath(color_scheme)) + if err != nil { + return "", err + } + } + ans, err = theme.AsEscapeCodes() + if err == nil { + ans = "\033[#P" + ans + } + return +} + func run_ssh(ssh_args, server_args, found_extra_args []string) (rc int, err error) { go Data() go RelevantKittyOpts() @@ -611,12 +644,21 @@ func run_ssh(ssh_args, server_args, found_extra_args []string) (rc int, err erro cd.host_opts, cd.literal_env = host_opts, literal_env cd.request_data = need_to_request_data cd.hostname_for_match, cd.username = hostname_for_match, uname - err = term.WriteAllString(loop.SAVE_PRIVATE_MODE_VALUES + loop.HANDLE_TERMIOS_SIGNALS.EscapeCodeToSet()) + escape_codes_to_set_colors, err := change_colors(cd.host_opts.Color_scheme) + if err == nil { + err = term.WriteAllString(escape_codes_to_set_colors + loop.SAVE_PRIVATE_MODE_VALUES + loop.HANDLE_TERMIOS_SIGNALS.EscapeCodeToSet()) + } if err != nil { return 1, err } - defer term.WriteAllString(loop.RESTORE_PRIVATE_MODE_VALUES) - defer term.RestoreAndClose() + restore_escape_codes := loop.RESTORE_PRIVATE_MODE_VALUES + if escape_codes_to_set_colors != "" { + restore_escape_codes += "\x1b[#Q" + } + defer func() { + term.WriteAllString(restore_escape_codes) + term.RestoreAndClose() + }() err = get_remote_command(&cd) if err != nil { return 1, err diff --git a/tools/themes/collection.go b/tools/themes/collection.go index 2d8945a2a..dd1f45d7e 100644 --- a/tools/themes/collection.go +++ b/tools/themes/collection.go @@ -263,7 +263,6 @@ func (self *Theme) AsEscapeCodes() (string, error) { w := strings.Builder{} w.Grow(4096) - w.WriteString("\033]4") set_color := func(i int, sharp string) { w.WriteByte(';') w.WriteString(strconv.Itoa(i)) @@ -296,6 +295,7 @@ func (self *Theme) AsEscapeCodes() (string, error) { set_default_color("selection_background", style.DefaultColors.SelectionBg, 17) set_default_color("selection_foreground", style.DefaultColors.SelectionFg, 19) + w.WriteString("\033]4") for i := 0; i < 256; i++ { key := "color" + strconv.Itoa(i) val := settings[key] @@ -330,6 +330,20 @@ func theme_name_from_file_name(fname string) string { return strings.Join(utils.Map(strings.Split(fname, " "), strings.Title), " ") } +func (self *Themes) AddFromFile(path string) (*Theme, error) { + m, conf, err := parse_theme_metadata(path) + if err != nil { + return nil, err + } + if m.Name == "" { + m.Name = theme_name_from_file_name(filepath.Base(path)) + } + t := Theme{metadata: m, is_user_defined: true, settings: conf} + self.name_map[m.Name] = &t + return &t, nil + +} + func (self *Themes) add_from_dir(dirpath string) error { entries, err := os.ReadDir(dirpath) if err != nil { @@ -340,15 +354,9 @@ func (self *Themes) add_from_dir(dirpath string) error { } for _, e := range entries { if !e.IsDir() && strings.HasSuffix(e.Name(), ".conf") { - m, conf, err := parse_theme_metadata(filepath.Join(dirpath, e.Name())) - if err != nil { + if _, err = self.AddFromFile(filepath.Join(dirpath, e.Name())); err != nil { return err } - if m.Name == "" { - m.Name = theme_name_from_file_name(e.Name()) - } - t := Theme{metadata: m, is_user_defined: true, settings: conf} - self.name_map[m.Name] = &t } } return nil @@ -399,17 +407,14 @@ func (self *Themes) ThemeByName(name string) *Theme { return self.name_map[name] } -func LoadThemes(cache_age time.Duration, ignore_no_cache bool) (ans *Themes, closer io.Closer, err error) { +func LoadThemes(cache_age time.Duration) (ans *Themes, closer io.Closer, err error) { zip_path, err := FetchCached(cache_age) ans = &Themes{name_map: make(map[string]*Theme)} if err != nil { - if !errors.Is(err, ErrNoCacheFound) || ignore_no_cache { - return nil, nil, err - } - } else { - if closer, err = ans.add_from_zip_file(zip_path); err != nil { - return nil, nil, err - } + return nil, nil, err + } + if closer, err = ans.add_from_zip_file(zip_path); err != nil { + return nil, nil, err } if err = ans.add_from_dir(filepath.Join(utils.ConfigDir(), "themes")); err != nil { return nil, nil, err @@ -418,3 +423,8 @@ func LoadThemes(cache_age time.Duration, ignore_no_cache bool) (ans *Themes, clo ans.index_map = utils.StableSortWithKey(ans.index_map, strings.ToLower) return ans, closer, nil } + +func ThemeFromFile(path string) (*Theme, error) { + ans := &Themes{name_map: make(map[string]*Theme)} + return ans.AddFromFile(path) +} diff --git a/tools/utils/paths.go b/tools/utils/paths.go index bb12d3dda..a41d3e78a 100644 --- a/tools/utils/paths.go +++ b/tools/utils/paths.go @@ -274,3 +274,11 @@ func RandomFilename() string { return base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(b) } + +func ResolveConfPath(path string) string { + cs := os.ExpandEnv(Expanduser(path)) + if !filepath.IsAbs(cs) { + cs = filepath.Join(ConfigDir(), cs) + } + return cs +}