diff --git a/kittens/choose_files/main.go b/kittens/choose_files/main.go index 2fed3266b..78cdb22aa 100644 --- a/kittens/choose_files/main.go +++ b/kittens/choose_files/main.go @@ -21,8 +21,6 @@ import ( "github.com/kovidgoyal/kitty/tools/utils" ) -// TODO: save file name completion - var _ = fmt.Print var debugprintln = tty.DebugPrintln @@ -378,7 +376,15 @@ func (h *Handler) accept_idx(idx CollectionIndex) (accepted bool, err error) { return false, nil } if s.IsDir() { - return true, h.change_to_current_dir_if_possible() + if h.state.mode.CanSelectNonExistent() { + name := h.state.suggested_save_file_name + if h.state.SearchText() != "" { + name = h.state.SearchText() + } + h.initialize_save_file_name(name) + return true, h.draw_screen() + } + return false, nil } } @@ -721,9 +727,10 @@ func main(_ *cli.Command, opts *Options, args []string) (rc int, err error) { return 1, err } lp.MouseTrackingMode(loop.FULL_MOUSE_TRACKING) - handler := Handler{lp: lp, err_chan: make(chan error, 8), rl: readline.New(lp, readline.RlInit{ - Prompt: "> ", ContinuationPrompt: ". ", - })} + handler := Handler{lp: lp, err_chan: make(chan error, 8)} + handler.rl = readline.New(lp, readline.RlInit{ + Prompt: "> ", ContinuationPrompt: ". ", Completer: handler.complete_save_prompt, + }) if err = handler.set_state_from_config(conf, opts); err != nil { return 1, err } diff --git a/kittens/choose_files/save-file.go b/kittens/choose_files/save-file.go index b42330011..c518a568c 100644 --- a/kittens/choose_files/save-file.go +++ b/kittens/choose_files/save-file.go @@ -4,13 +4,56 @@ import ( "fmt" "os" "path/filepath" + "strings" + "github.com/kovidgoyal/kitty/tools/cli" "github.com/kovidgoyal/kitty/tools/tui/loop" "github.com/kovidgoyal/kitty/tools/utils" ) var _ = fmt.Print +func (h *Handler) complete_save_prompt(before_cursor, after_cursor string) *cli.Completions { + path := before_cursor + prefix := "" + if idx := strings.Index(path, string(os.PathSeparator)); idx > -1 { + prefix = filepath.Dir(path) + string(os.PathSeparator) + } + if !filepath.IsAbs(path) { + path = filepath.Join(h.state.CurrentDir(), path) + } + dir := filepath.Dir(path) + if strings.HasSuffix(before_cursor, string(os.PathSeparator)) { + dir = path + } + entries, err := os.ReadDir(dir) + if err != nil { + return nil + } + ans := cli.NewCompletions() + dirs := ans.AddMatchGroup("Directories") + dirs.IsFiles = true + dirs.NoTrailingSpace = true + files := ans.AddMatchGroup("Files") + files.IsFiles = true + files.NoTrailingSpace = true + leading, _ := filepath.Rel(dir, path) + if leading == "." { + leading = "" + } + for _, e := range entries { + word := e.Name() + if leading == "" || strings.HasPrefix(word, leading) { + collection := utils.IfElse(e.Type().IsDir(), dirs, files) + if prefix != "" { + word = prefix + word + } + collection.Matches = append(collection.Matches, &cli.Match{Word: word}) + } + } + return ans +} + func (h *Handler) current_save_file_path() string { ans := h.rl.AllText() if ans != "" {