From 9a6f4c3fb808164a05d1c977a7ca9ea7e6b2e1a7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 27 Apr 2026 17:31:23 +0530 Subject: [PATCH] More work on dnd kitten --- kittens/dnd/drop.go | 33 +++++++++++++++++++++++++++++++-- kittens/dnd/main.go | 16 ++++++++++++++++ kittens/dnd/render.go | 16 ++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/kittens/dnd/drop.go b/kittens/dnd/drop.go index bb7098358..5c9647ee6 100644 --- a/kittens/dnd/drop.go +++ b/kittens/dnd/drop.go @@ -453,13 +453,28 @@ func (dnd *dnd) all_drop_data_received() error { var staging_dir *os.File if dnd.drop_status.dropping_to != nil { staging_dir = dnd.drop_status.dropping_to.handle + dnd.drop_status.dropping_to = nil } + defer dnd.end_drop() if staging_dir != nil { - // TODO: either copy all files or check for overwrites if dnd.opts.ConfirmDropOverwrite { + overwrites, err := find_overwrites(staging_dir, dnd.drop_output_dir) + if err != nil { + return err + } + if len(overwrites) > 0 { + dnd.confirm_drop.overwrites = overwrites + dnd.confirm_drop.staging_dir = staging_dir + return dnd.render_screen() + } } + err := rename_contents(staging_dir, dnd.drop_output_dir) + staging_dir.Close() + if err != nil { + return err + } + return dnd.render_screen() } - dnd.end_drop() return nil } @@ -719,3 +734,17 @@ func (dnd *dnd) on_drop_data(cmd DC) error { } return dest.add_data(cmd.Payload, drop_buf, cmd.Has_more) } + +func (dnd *dnd) drop_confirm(accepted bool) error { + staging_dir := dnd.confirm_drop.staging_dir + dnd.confirm_drop.overwrites = nil + dnd.confirm_drop.staging_dir = nil + defer staging_dir.Close() + dnd.data_has_been_dropped = accepted + if accepted { + if err := rename_contents(staging_dir, dnd.drop_output_dir); err != nil { + return err + } + } + return dnd.render_screen() +} diff --git a/kittens/dnd/main.go b/kittens/dnd/main.go index b74b5d89f..e32d362bc 100644 --- a/kittens/dnd/main.go +++ b/kittens/dnd/main.go @@ -89,6 +89,10 @@ type dnd struct { drag_started bool in_test_mode bool copy_button_region, move_button_region button_region + confirm_drop struct { + overwrites []string + staging_dir *os.File + } } func (dnd *dnd) send_test_response(payload string) { @@ -249,6 +253,14 @@ func (dnd *dnd) run_loop() (err error) { dnd.lp.OnKeyEvent = func(e *loop.KeyEvent) (err error) { e.Handled = true + if len(dnd.confirm_drop.overwrites) > 0 { + if e.MatchesPressOrRepeat("esc") { + return dnd.drop_confirm(false) + } + if e.MatchesPressOrRepeat("enter") { + return dnd.drop_confirm(true) + } + } if e.MatchesPressOrRepeat("ctrl+c") || e.MatchesPressOrRepeat("esc") { dnd.lp.Quit(0) return @@ -355,6 +367,10 @@ func dnd_main(cmd *cli.Command, opts *Options, args []string) (rc int, err error dnd := dnd{opts: opts, drop_dests: drop_dests, drag_sources: drag_sources} defer func() { dnd.reset_drop() + if dnd.confirm_drop.staging_dir != nil { + dnd.confirm_drop.staging_dir.Close() + dnd.confirm_drop.staging_dir = nil + } dnd.drop_output_dir.Close() }() if err = dnd.run_loop(); err != nil { diff --git a/kittens/dnd/render.go b/kittens/dnd/render.go index 74487f72d..4b30265c8 100644 --- a/kittens/dnd/render.go +++ b/kittens/dnd/render.go @@ -68,6 +68,22 @@ func (dnd *dnd) render_screen() error { lp.Println() y++ } + + if len(dnd.confirm_drop.overwrites) > 0 { + render_paragraph("Some of the dropped files will overwrite existing files, listed below. Press \x1b[32mEnter\x1b[39m to drop anyway or \x1b[31mEsc\x1b[39m to cancel the drop.") + sz, _ := lp.ScreenSize() + next_line() + next_line() + overwrites := dnd.confirm_drop.overwrites[:min(int(sz.HeightCells)-y-1, len(dnd.confirm_drop.overwrites))] + for _, x := range overwrites { + lp.Println(x) + } + if left := len(dnd.confirm_drop.overwrites) - len(overwrites); left > 0 { + lp.Printf("... (%d more)", left) + } + return nil + } + if dnd.drop_status.in_window { if dnd.drop_status.action == 0 { render_paragraph("A drag is active. Drop it into one of the boxes below to perform that action on the dragged data. Available MIME types in the drag:")