Handle multiple save files when entering save file names

This commit is contained in:
Kovid Goyal
2025-07-11 21:47:11 +05:30
parent 8ce7346616
commit f34007c65a
3 changed files with 76 additions and 37 deletions

View File

@@ -24,6 +24,12 @@ func (h *Handler) draw_footer() (num_lines int, err error) {
lines := []string{}
screen_width := h.screen_size.width
sctx := style.Context{AllowEscapeCodes: true}
if h.state.screen == SAVE_FILE {
m := h.state.filter_map
h.state.filter_map = nil
defer func() { h.state.filter_map = m }()
}
if len(h.state.filter_map)+len(h.state.selections) > 0 {
buf := strings.Builder{}
pos := 0
@@ -36,10 +42,16 @@ func (h *Handler) draw_footer() (num_lines int, err error) {
lines = append(lines, buf.String())
pos = 0
buf.Reset()
} else {
buf.WriteString(presep)
pos += sz
}
buf.WriteString(presep)
pos += sz
sz = wcswidth.Stringwidth(text)
if sz+pos >= screen_width {
lines = append(lines, buf.String())
pos = 0
buf.Reset()
}
if sfunc != nil {
text = sfunc(text)
}
@@ -94,6 +106,9 @@ func (h *Handler) draw_footer() (num_lines int, err error) {
}
if len(lines) > 0 {
h.lp.MoveCursorTo(1, h.screen_size.height-len(lines)+1)
if h.state.screen == SAVE_FILE {
h.lp.ClearToEndOfScreen()
}
h.lp.QueueWriteString(strings.Join(lines, "\r\n"))
}
return len(lines), err

View File

@@ -120,12 +120,11 @@ type State struct {
global_ignores ignorefiles.IgnoreFile
keyboard_shortcuts []*config.KeyAction
save_file_cdir string
selections []string
current_idx CollectionIndex
last_render render_state
mouse_state tui.MouseState
redraw_needed bool
selections []string
current_idx CollectionIndex
last_render render_state
mouse_state tui.MouseState
redraw_needed bool
}
func (s State) ShowHidden() bool { return s.show_hidden }

View File

@@ -19,12 +19,18 @@ func (h *Handler) complete_save_prompt(before_cursor, after_cursor string) *cli.
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 := ""
if path == "" {
path = h.state.CurrentDir()
dir = path
} else {
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 {
@@ -59,57 +65,76 @@ func (h *Handler) current_save_file_path() string {
if ans != "" {
ans = utils.Expanduser(ans)
if !filepath.IsAbs(ans) {
ans = filepath.Join(h.state.save_file_cdir, ans)
ans = filepath.Join(h.state.CurrentDir(), ans)
}
}
return ans
}
func (h *Handler) save_file_name_handle_key(ev *loop.KeyEvent) (err error) {
switch {
case ev.MatchesPressOrRepeat("esc") || ev.MatchesPressOrRepeat("ctrl+c"):
h.state.selections = nil
h.state.screen = NORMAL
ac := h.shortcut_tracker.Match(ev, h.state.keyboard_shortcuts)
if ac != nil {
switch ac.Name {
case "accept":
if p := h.current_save_file_path(); p != "" {
h.state.selections = append(h.state.selections, p)
h.lp.Quit(0)
} else {
h.lp.Beep()
}
ev.Handled = true
return nil
case "select":
if p := h.current_save_file_path(); p != "" {
h.state.selections = append(h.state.selections, p)
}
ev.Handled = true
h.rl.ResetText()
return h.draw_screen()
case "quit":
h.state.screen = NORMAL
ev.Handled = true
return h.draw_screen()
}
}
if err = h.rl.OnKeyEvent(ev); err == nil {
err = h.draw_screen()
case ev.MatchesPressOrRepeat("enter"):
if p := h.current_save_file_path(); p != "" {
h.state.selections = []string{p}
h.lp.Quit(0)
} else {
h.lp.Beep()
}
default:
if err = h.rl.OnKeyEvent(ev); err == nil {
err = h.draw_screen()
}
}
return
}
func (h *Handler) initialize_save_file_name(use_fname_when_no_selections string) {
func (h *Handler) initialize_save_file_name(fname string) {
h.state.screen = SAVE_FILE
h.rl.ResetText()
cdir := h.state.CurrentDir()
fname := use_fname_when_no_selections
if len(h.state.selections) > 0 {
if len(h.state.selections) > 0 && fname == "" {
if q, err := filepath.Abs(h.state.selections[0]); err == nil {
if s, err := os.Stat(q); err == nil {
if s.IsDir() == h.state.mode.OnlyDirs() {
cdir = filepath.Dir(q)
fname = filepath.Base(q)
if fname, err = filepath.Rel(h.state.CurrentDir(), q); err != nil {
fname = q
}
}
}
}
}
h.rl.SetText(fname)
h.state.save_file_cdir = cdir
}
func (h *Handler) draw_save_file_name_screen() (err error) {
h.lp.AllowLineWrapping(true)
desc := utils.IfElse(h.state.mode == SELECT_SAVE_FILE, "file", "directory")
h.lp.Println("Enter the name of the", desc, "below, relative to:")
h.lp.Println(h.lp.SprintStyled("fg=green", h.state.save_file_cdir))
h.lp.Println(h.lp.SprintStyled("fg=green", h.state.CurrentDir()))
if h.state.mode.AllowsMultipleSelection() {
h.lp.Println("Use shift+enter (or whatever you mapped the select action to) to enter multiple filenames")
}
h.lp.Println()
h.rl.RedrawNonAtomic()
h.lp.AllowLineWrapping(false)
if len(h.state.selections) > 0 {
h.lp.SaveCursorPosition()
h.draw_footer()
h.lp.RestoreCursorPosition()
}
return
}