diff --git a/kittens/dnd/main.go b/kittens/dnd/main.go index 121600945..c2e01f009 100644 --- a/kittens/dnd/main.go +++ b/kittens/dnd/main.go @@ -144,6 +144,7 @@ func truncate_at_space(text string, width int) (string, string) { type drop_status struct { offered_mimes []string accepted_mimes []string + uri_list []string cell_x, cell_y int action int in_window bool @@ -162,6 +163,25 @@ func paragraph_as_lines(text string, width int) (ans []string) { return } +func parse_uri_list(src string) (ans []string, err error) { + for _, line := range utils.NewSeparatorScanner("", "\r\n").Split(src) { + line = strings.TrimSpace(line) + if strings.HasPrefix(line, "#") { + continue + } + if !strings.HasPrefix(line, "file://") { + ans = append(ans, "") + continue + } + p, err := url.Parse(line) + if err != nil { + return nil, err + } + ans = append(ans, filepath.Clean(p.Path)) + } + return +} + func run_loop(opts *Options, drop_dests map[string]*drop_dest, drag_sources map[string]drag_source, uri_list_buffer *bytes.Buffer) (err error) { allow_drops, allow_drags := len(drop_dests) > 0, len(drag_sources) > 0 data_has_been_dropped := false @@ -301,15 +321,24 @@ func run_loop(opts *Options, drop_dests map[string]*drop_dest, drag_sources map[ render_screen() } - all_mime_data_dropped := func() error { - if _, found := drop_dests["text/uri-list"]; found && drop_status.is_remote_client { - // TODO: Handle remote client - } else { + all_mime_data_dropped := func() (err error) { + if _, found := drop_dests["text/uri-list"]; found { + if drop_status.uri_list, err = parse_uri_list(uri_list_buffer.String()); err != nil { + return err + } + } + if len(drop_status.uri_list) == 0 { drop_status = reset_drop_status data_has_been_dropped = true render_screen() + return } - return nil + if drop_status.is_remote_client { + // TODO: Handle remote client + } else { + // TODO: copy URLs + } + return } request_mime_data := func() { @@ -506,6 +535,8 @@ func run_loop(opts *Options, drop_dests map[string]*drop_dest, drag_sources map[ } case "DROP_IS_REMOTE": send_test_response(utils.IfElse(drop_status.is_remote_client, "True", "False")) + case "DROP_URI_LIST": + send_test_response(strings.Join(drop_status.uri_list, "|")) default: send_test_response("UNKNOWN TEST COMMAND: " + string(cmd.Payload)) } diff --git a/kitty_tests/dnd_kitten.py b/kitty_tests/dnd_kitten.py index e5983c97f..82e5b9f60 100644 --- a/kitty_tests/dnd_kitten.py +++ b/kitty_tests/dnd_kitten.py @@ -7,6 +7,7 @@ import shutil import tempfile from base64 import standard_b64encode from functools import partial +from urllib.parse import unquote, urlparse from kitty.constants import kitten_exe from kitty.fast_data_types import ( @@ -62,7 +63,7 @@ class TestDnDKitten(BaseTest): capture.window_id = window_id capture.os_window_id = os_window_id self.capture = capture - self.test_dir = self.enterContext(tempfile.TemporaryDirectory()) + self.test_dir = os.path.realpath(self.enterContext(tempfile.TemporaryDirectory())) self.kitten_wd = os.path.join(self.test_dir, 'kitten') os.mkdir(self.kitten_wd) self.src_data_dir = os.path.join(self.test_dir, 'src') @@ -195,11 +196,18 @@ class TestDnDKitten(BaseTest): self.wait_for_state('drop_data_requests', ((1,0,0), (4,0,0))) self.assertEqual('text/uri-list', self.probe_state('drop_getting_data_for_mime')) create_fs(self.src_data_dir) - uri_list = [] + uri_list, path_list = [], [] for x in os.listdir(self.src_data_dir): uri_list.append(as_file_url(self.src_data_dir, x)) - uri_list = ['moose://cow', 'frog:march'] + uri_list + uri_list = ['moose:cow', '# file:///frog/march'] + uri_list uri_list.insert(3, 'ignore://me') + for x in uri_list: + if x.startswith('#'): + continue + if x.startswith('file://'): + path_list.append(unquote(urlparse(x).path)) + else: + path_list.append('') dnd_test_fake_drop_data(self.capture.window_id, 'text/uri-list', '\r\n'.join(uri_list).encode()) self.assertEqual('image/png', self.probe_state('drop_getting_data_for_mime')) @@ -216,6 +224,8 @@ class TestDnDKitten(BaseTest): self.send_dnd_command_to_kitten('DROP_IS_REMOTE') self.wait_for_responses(str(remote_client)) + self.send_dnd_command_to_kitten('DROP_URI_LIST') + self.wait_for_responses('|'.join(path_list)) jn = os.path.join self.assert_files_have_same_content(jn(self.src_data_dir, 'some-image.png'), jn(self.kitten_wd, img_drop_path)) shutil.rmtree(os.path.dirname(jn(self.kitten_wd, img_drop_path)))