commit 3287d4e32efbe6c9490ecd4132f19fa13f4ae1ae (HEAD, refs/remotes/origin/master) Author: Eli Zaretskii Date: Sat Jun 4 09:05:35 2022 +0300 Another attempt to void compiler warnings on macOS (bug#55595) * configure.ac (WERROR_CFLAGS): Use "-Wno-unknown-pragmas" with Clang. diff --git a/configure.ac b/configure.ac index ed8ec890ac..313a1436b5 100644 --- a/configure.ac +++ b/configure.ac @@ -1024,6 +1024,7 @@ AS_IF([test $gl_gcc_warnings = no], gl_WARN_ADD([-Wno-pointer-sign]) gl_WARN_ADD([-Wno-string-plus-int]) gl_WARN_ADD([-Wno-unknown-attributes]) + gl_WARN_ADD([-Wno-unknown-pragmas]) ]) ],[ isystem='-isystem ' commit eaff6569e2fd317503c96eeba8e9c515d0734a44 Author: Po Lu Date: Sat Jun 4 13:27:03 2022 +0800 Improve doc of `mouse-drag-mode-line-buffer' * doc/emacs/frames.texi (Mouse Commands): Document `mouse-drag-mode-line-buffer'. * etc/NEWS: Explain where that option is supported. * lisp/mouse.el (mouse-drag-mode-line-buffer): Likewise. diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index 28b4d2d0e4..a853c9a228 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -136,6 +136,12 @@ entirely on the screen. The number of lines scrolled per step depends on how far away from the window edge the mouse has gone; the variable @code{mouse-scroll-min-lines} specifies a minimum step size. +@vindex mouse-drag-mode-line-buffer + If you enable the option @code{mouse-drag-mode-line-buffer} and +dragging files is supported by the window system, then dragging the +mouse on the buffer name portion of the mode line will drag that +buffer's file to another program or frame. + @findex mouse-yank-primary @findex mouse-yank-at-click Clicking with the middle mouse button, @kbd{mouse-2}, moves point to diff --git a/etc/NEWS b/etc/NEWS index d140bb0960..777c8eb341 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -305,9 +305,11 @@ the current Emacs process at the end, it starts a new Emacs process optional parameters to restart instead of just killing the current process. ++++ ** New user option 'mouse-drag-mode-line-buffer'. If non-nil, dragging on the buffer name part of the mode-line will -drag the buffer's associated file to other programs. +drag the buffer's associated file to other programs. This option is +currently only available on X, Haiku and Nextstep (GNUstep or macOS). +++ ** New user option 'mouse-drag-and-drop-region-cross-program'. diff --git a/lisp/mouse.el b/lisp/mouse.el index 1f2e925222..737c507870 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -111,7 +111,10 @@ down and up respectively." (defcustom mouse-drag-mode-line-buffer nil "If non-nil, allow dragging files from the mode line. When the buffer has an associated file, it can be dragged from -the buffer name portion of its mode line to other programs." +the buffer name portion of its mode line to other programs. + +This option is only supported on X, Haiku and Nextstep (GNUstep +or macOS)." :type 'boolean :version "29.1") commit c259ae909f89f8e9895d117ef56d176fd7056a83 Author: Po Lu Date: Sat Jun 4 12:27:11 2022 +0800 Make XTmouse_position faster during dragging with lots of frames * src/xterm.c (x_tooltip_window_to_frame): New function. (XTmouse_position): Use that to find tooltip frames underneath the pointer instead. diff --git a/src/xterm.c b/src/xterm.c index d5f45fbc94..fe7cab7258 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10275,6 +10275,27 @@ x_window_to_frame (struct x_display_info *dpyinfo, int wdesc) return 0; } +/* Like x_any_window_to_frame but only try to find tooltip frames. */ +static struct frame * +x_tooltip_window_to_frame (struct x_display_info *dpyinfo, + Window wdesc) +{ + Lisp_Object tail, frame; + struct frame *f; + + FOR_EACH_FRAME (tail, frame) + { + f = XFRAME (frame); + + if (FRAME_X_P (f) && FRAME_TOOLTIP_P (f) + && FRAME_DISPLAY_INFO (f) == dpyinfo + && FRAME_X_WINDOW (f) == wdesc) + return f; + } + + return NULL; +} + #if defined (USE_X_TOOLKIT) || defined (USE_GTK) /* Like x_window_to_frame but also compares the window with the widget's @@ -11855,9 +11876,9 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, && (EQ (track_mouse, Qdrag_source) || EQ (track_mouse, Qdropping))) { - maybe_tooltip = x_any_window_to_frame (dpyinfo, child); + maybe_tooltip = x_tooltip_window_to_frame (dpyinfo, child); - if (maybe_tooltip && FRAME_TOOLTIP_P (maybe_tooltip)) + if (maybe_tooltip) child = x_get_window_below (dpyinfo->display, child, parent_x, parent_y, &win_x, &win_y); commit 63b3999562d5d76a01b71c6caaa419b97dbc6fa4 Author: Po Lu Date: Sat Jun 4 10:05:44 2022 +0800 Fix leak of toplevel data * src/xterm.c (x_dnd_compute_toplevels): Make sure to free `data'. diff --git a/src/xterm.c b/src/xterm.c index 99aa0ae929..d5f45fbc94 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2961,6 +2961,9 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) SAFE_FREE (); #endif + if (data) + XFree (data); + return 0; } commit d49ea6de2f92cb8f092fe30301010273e8c03f8c Author: Po Lu Date: Sat Jun 4 09:51:33 2022 +0800 Fix leak of DND toplevels when return-frame is non-nil * src/xterm.c (x_dnd_free_toplevels): Don't leak DND toplevels if returning a frame. (x_dnd_begin_drag_and_drop): Make this function reentrant from the IO error handler. diff --git a/src/xterm.c b/src/xterm.c index ecee000439..99aa0ae929 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2292,7 +2292,31 @@ x_dnd_free_toplevels (bool display_alive) { struct x_client_list_window *last; struct x_client_list_window *tem = x_dnd_toplevels; + ptrdiff_t n_windows, i, buffer_size; + Window *destroy_windows; + unsigned long *prev_masks; + specpdl_ref count; + Display *dpy; + + if (!x_dnd_toplevels) + /* Probably called inside an IO error handler. */ + return; + /* Pacify GCC. */ + prev_masks = NULL; + destroy_windows = NULL; + + if (display_alive) + { + buffer_size = 1024; + destroy_windows = xmalloc (sizeof *destroy_windows + * buffer_size); + prev_masks = xmalloc (sizeof *prev_masks * + buffer_size); + n_windows = 0; + } + + block_input (); while (tem) { last = tem; @@ -2300,13 +2324,20 @@ x_dnd_free_toplevels (bool display_alive) if (display_alive) { - x_catch_errors (last->dpy); - XSelectInput (last->dpy, last->window, - last->previous_event_mask); -#ifdef HAVE_XSHAPE - XShapeSelectInput (last->dpy, last->window, None); -#endif - x_uncatch_errors (); + if (++n_windows >= buffer_size) + { + buffer_size += 1024; + destroy_windows + = xrealloc (destroy_windows, (sizeof *destroy_windows + * buffer_size)); + prev_masks + = xrealloc (prev_masks, (sizeof *prev_masks + * buffer_size)); + } + + dpy = last->dpy; + prev_masks[n_windows - 1] = last->previous_event_mask; + destroy_windows[n_windows - 1] = last->window; } #ifdef HAVE_XSHAPE @@ -2320,6 +2351,34 @@ x_dnd_free_toplevels (bool display_alive) } x_dnd_toplevels = NULL; + + if (!display_alive) + { + unblock_input (); + return; + } + + count = SPECPDL_INDEX (); + record_unwind_protect_ptr (xfree, destroy_windows); + record_unwind_protect_ptr (xfree, prev_masks); + + if (display_alive) + { + x_catch_errors (dpy); + + for (i = 0; i < n_windows; ++i) + { + XSelectInput (dpy, destroy_windows[i], prev_masks[i]); +#ifdef HAVE_XSHAPE + XShapeSelectInput (dpy, destroy_windows[i], None); +#endif + } + + x_uncatch_errors (); + } + + unbind_to (count, Qnil); + unblock_input (); } static int @@ -10625,6 +10684,10 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, unblock_input (); } + /* This shouldn't happen. */ + if (x_dnd_toplevels) + x_dnd_free_toplevels (true); + x_dnd_in_progress = true; x_dnd_frame = f; x_dnd_last_seen_window = None; @@ -10990,6 +11053,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); unblock_input (); + if (x_dnd_use_toplevels) + x_dnd_free_toplevels (true); + if (x_dnd_return_frame == 3 && FRAME_LIVE_P (x_dnd_return_frame_object)) { @@ -11008,9 +11074,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, } x_dnd_return_frame_object = NULL; - - if (x_dnd_use_toplevels) - x_dnd_free_toplevels (true); FRAME_DISPLAY_INFO (f)->grabbed = 0; /* Emacs can't respond to DND events inside the nested event commit 7fed00f9ba9f4838633009037a156aa439a6b069 Author: Dmitry Gutov Date: Sat Jun 4 03:42:00 2022 +0300 Post-review additions * lisp/progmodes/project.el (project-vc-include-untracked): Add :version. (project--vc-list-files): Use 'and' instead of 'when'. diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 60fbb302f7..859ad2e047 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -385,6 +385,7 @@ you might have to restart Emacs to see the effect." (defcustom project-vc-include-untracked t "When non-nil, the VC project backend includes untracked files." :type 'boolean + :version "29.1" :safe #'booleanp) ;; FIXME: Using the current approach, major modes are supposed to set @@ -519,7 +520,7 @@ backend implementation of `project-external-roots'.") files) (setq args (append args '("-c" "--exclude-standard") - (when project-vc-include-untracked '("-o")))) + (and project-vc-include-untracked '("-o")))) (when extra-ignores (setq args (append args (cons "--" @@ -571,7 +572,7 @@ backend implementation of `project-external-roots'.") (delete-consecutive-dups files))) (`Hg (let ((default-directory (expand-file-name (file-name-as-directory dir))) - (args (list (concat "-mcard" (when project-vc-include-untracked "u")) + (args (list (concat "-mcard" (and project-vc-include-untracked "u")) "--no-status" "-0"))) (when extra-ignores commit 526971df64bfca3c78f4c2e635b27cadec02b2b9 Author: Jan Synáček Date: Thu Jun 2 20:59:53 2022 +0200 Add new user option project-vc-include-untracked * doc/emacs/maintaining.texi (Projects): Document it. * lisp/progmodes/project.el (project--vc-list-files): Use it. diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 3ddea0ae58..edc5acbd65 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -1666,6 +1666,9 @@ support additional types of projects. Which files do or don't belong to a project is also determined by the project back-end. For example, the VC back-end doesn't consider ``ignored'' files (@pxref{VC Ignore}) to be part of the project. +Also, the VC Project back-end considers ``untracked'' files by default. +That behavior is controllable with the variable +@code{project-vc-include-untracked}. @menu * Project File Commands:: Commands for handling project files. diff --git a/etc/NEWS b/etc/NEWS index 54bc6d80e1..d140bb0960 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1717,6 +1717,11 @@ Enabling this minor mode turns on hiding header material, like 'elide-head' does; disabling it shows the header. The commands 'elide-head' and 'elide-head-show' are now obsolete. ++++ +*** New user option 'project-vc-include-untracked'. +If non-nil, files untracked by a VCS are considered to be part of +the project by a VC project based on that VCS. + --- ** The autoarg.el library is now marked obsolete. This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 6e0874bfc3..60fbb302f7 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -382,6 +382,11 @@ you might have to restart Emacs to see the effect." :package-version '(project . "0.2.0") :safe #'booleanp) +(defcustom project-vc-include-untracked t + "When non-nil, the VC project backend includes untracked files." + :type 'boolean + :safe #'booleanp) + ;; FIXME: Using the current approach, major modes are supposed to set ;; this variable to a buffer-local value. So we don't have access to ;; the "external roots" of language A from buffers of language B, which @@ -512,8 +517,9 @@ backend implementation of `project-external-roots'.") (args '("-z")) (vc-git-use-literal-pathspecs nil) files) - ;; Include unregistered. - (setq args (append args '("-c" "-o" "--exclude-standard"))) + (setq args (append args + '("-c" "--exclude-standard") + (when project-vc-include-untracked '("-o")))) (when extra-ignores (setq args (append args (cons "--" @@ -565,9 +571,9 @@ backend implementation of `project-external-roots'.") (delete-consecutive-dups files))) (`Hg (let ((default-directory (expand-file-name (file-name-as-directory dir))) - args) - ;; Include unregistered. - (setq args (nconc args '("-mcardu" "--no-status" "-0"))) + (args (list (concat "-mcard" (when project-vc-include-untracked "u")) + "--no-status" + "-0"))) (when extra-ignores (setq args (nconc args (mapcan commit db82347269373793107b762d8c3de6b725eaf717 Author: Dmitry Gutov Date: Sat Jun 4 03:13:42 2022 +0300 project-query-replace-regexp: Filter out non-regular files * lisp/progmodes/project.el (project-query-replace-regexp): Filter out non-regular files (bug#55382). diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 4dc4762176..6e0874bfc3 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1092,7 +1092,12 @@ If you exit the `query-replace', you can later continue the (query-replace-read-args "Query replace (regexp)" t t))) (list from to)))) (fileloop-initialize-replace - from to (project-files (project-current t)) 'default) + from to + ;; XXX: Filter out Git submodules, which are not regular files. + ;; `project-files' can return those, which is arguably suboptimal, + ;; but removing them eagerly has performance cost. + (cl-delete-if-not #'file-regular-p (project-files (project-current t))) + 'default) (fileloop-continue)) (defvar compilation-read-command) commit 6f69284ada78a63287de16c866bcbb218fd7ae28 Author: Michael Albinus Date: Fri Jun 3 19:55:30 2022 +0200 Fix Tramp test * test/lisp/net/tramp-tests.el (tramp-test31-signal-process): Skip on MS Windows. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 569e9506d1..621b6ba1c2 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -5135,6 +5135,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." :tags '(:expensive-test :tramp-asynchronous-processes :unstable) (skip-unless (tramp--test-enabled)) (skip-unless (tramp--test-sh-p)) + (skip-unless (not (tramp--test-windows-nt-p))) (skip-unless (not (tramp--test-crypt-p))) ;; Since Emacs 27.1. (skip-unless (macrop 'with-connection-local-variables)) commit 9ea5628b18563a224013b3519f70c54c1989ff2f Author: Michael Albinus Date: Fri Jun 3 19:54:31 2022 +0200 Add remote file functions to shortdoc * lisp/net/tramp-integration.el (shortdoc-add-function) (shortdoc--groups): Declare. (shortdoc): Configure shortdoc.el to recognize file name functions for remote access. diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el index b7f82770c4..5e51074c49 100644 --- a/lisp/net/tramp-integration.el +++ b/lisp/net/tramp-integration.el @@ -39,6 +39,7 @@ (declare-function info-lookup->topic-value "info-look") (declare-function info-lookup-maybe-add-help "info-look") (declare-function recentf-cleanup "recentf") +(declare-function shortdoc-add-function "shortdoc") (declare-function tramp-dissect-file-name "tramp") (declare-function tramp-file-name-equal-p "tramp") (declare-function tramp-tramp-file-p "tramp") @@ -49,6 +50,7 @@ (defvar info-lookup-alist) (defvar ivy-completing-read-handlers-alist) (defvar recentf-exclude) +(defvar shortdoc--groups) (defvar tramp-current-connection) (defvar tramp-postfix-host-format) (defvar tramp-use-ssh-controlmaster-options) @@ -257,6 +259,33 @@ NAME must be equal to `tramp-current-connection'." (delete (info-lookup->mode-cache 'symbol ',mode) (info-lookup->topic-cache 'symbol)))))))) +;;; Integration of shortdoc.el: + +(with-eval-after-load 'shortdoc + (dolist (elem '((file-remote-p + :eval (file-remote-p "/ssh:user@host:/tmp/foo") + :eval (file-remote-p "/ssh:user@host:/tmp/foo" 'method)) + (file-local-name + :eval (file-local-name "/ssh:user@host:/tmp/foo")) + (file-local-copy + :no-eval (file-local-copy "/ssh:user@host:/tmp/foo") + :eg-result "/tmp/tramp.8ihLbO" + :eval (file-local-copy "/tmp/foo")))) + (unless (assoc (car elem) + (member "Remote Files" (assq 'file shortdoc--groups))) + (shortdoc-add-function 'file "Remote Files" elem))) + + (add-hook + 'tramp-integration-unload-hook + (lambda () + (let ((glist (assq 'file shortdoc--groups))) + (while (and (consp glist) + (not (and (stringp (cadr glist)) + (string-equal (cadr glist) "Remote Files")))) + (setq glist (cdr glist))) + (when (consp glist) + (setcdr glist nil)))))) + ;;; Integration of compile.el: ;; Compilation processes use `accept-process-output' such a way that commit e4611107e5b20e9a0c25c61a360220a48e970efd Author: Po Lu Date: Fri Jun 3 20:36:24 2022 +0800 Fix dired drag and drop actions * lisp/dired.el (dired-mouse-drag): Make `link' values work again. diff --git a/lisp/dired.el b/lisp/dired.el index 1ab2c8c38b..4d3d93441b 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -1758,14 +1758,14 @@ other marked file as well. Otherwise, unmark all files." (if (and (consp filename) (cdr filename)) (dnd-begin-drag-files filename nil - (if (eq 'dired-mouse-drag-files 'link) - 'move 'copy) + (if (eq dired-mouse-drag-files 'link) + 'link 'copy) t) (dnd-begin-file-drag (if (stringp filename) filename (car filename)) - nil (if (eq 'dired-mouse-drag-files 'link) - 'move 'copy) + nil (if (eq dired-mouse-drag-files 'link) + 'link 'copy) t)))) (error (when (eq (event-basic-type new-event) 'mouse-1) (push new-event unread-command-events)))))))))) commit 34a681cfc7a08d50ea0616908d007a8c51643c63 Author: Po Lu Date: Fri Jun 3 12:13:27 2022 +0000 Handle dragging multiple files on Haiku * lisp/term/haiku-win.el (haiku-dnd-selection-converters) (haiku-dnd-convert-file-name, x-begin-drag): Handle vector values of selection data. diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 2fa27ed08a..0dcfc1e920 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -61,9 +61,14 @@ two elements TYPE and DATA, where TYPE is a string containing the MIME type of DATA, and DATA is a unibyte string, or nil if the data could not be converted. +DATA may also be a list of items; that means to add every +individual item in DATA to the serialized message, instead of +DATA in its entirety. + DATA can optionally have a text property `type', which specifies the type of DATA inside the system message (see the doc string of -`haiku-drag-message' for more details).") +`haiku-drag-message' for more details). If DATA is a list, then +that property is obtained from the first element of DATA.") (defvar haiku-normal-selection-encoders '(haiku-select-encode-xstring haiku-select-encode-utf-8-string @@ -144,10 +149,16 @@ VALUE as a unibyte string, or nil if VALUE was not a string." (defun haiku-dnd-convert-file-name (value) "Convert VALUE to a file system reference if it is a file name." - (when (and (stringp value) - (not (file-remote-p value)) - (file-exists-p value)) - (list "refs" (propertize (expand-file-name value) 'type 'ref)))) + (cond ((and (stringp value) + (not (file-remote-p value)) + (file-exists-p value)) + (list "refs" (propertize (expand-file-name value) + 'type 'ref))) + ((vectorp value) + (list "refs" + (cl-loop for item across value + collect (propertize (expand-file-name item) + 'type 'ref)))))) (defun haiku-dnd-convert-text-uri-list (value) "Convert VALUE to a list of URLs." @@ -361,28 +372,34 @@ take effect on menu items until the menu bar is updated again." (dolist (target targets) (let* ((target-atom (intern target)) (selection-converter (cdr (assoc target-atom - haiku-dnd-selection-converters)))) + haiku-dnd-selection-converters))) + (value (if (stringp haiku-dnd-selection-value) + (or (get-text-property 0 target-atom + haiku-dnd-selection-value) + haiku-dnd-selection-value) + haiku-dnd-selection-value))) (when selection-converter - (let ((selection-result - (funcall selection-converter - (if (stringp haiku-dnd-selection-value) - (or (get-text-property 0 target-atom - haiku-dnd-selection-value) - haiku-dnd-selection-value) - haiku-dnd-selection-value)))) + (let ((selection-result (funcall selection-converter value))) (when selection-result - (let ((field (cdr (assoc (car selection-result) message)))) + (let* ((field (cdr (assoc (car selection-result) message))) + (maybe-string (if (stringp (cadr selection-result)) + (cadr selection-result) + (caadr selection-result)))) (unless (cadr field) ;; Add B_MIME_TYPE to the message if the type was not ;; previously specified, or the type if it was. - (push (or (get-text-property 0 'type - (cadr selection-result)) + (push (or (get-text-property 0 'type maybe-string) 1296649541) (alist-get (car selection-result) message nil nil #'equal)))) - (push (cadr selection-result) - (cdr (alist-get (car selection-result) message - nil nil #'equal)))))))) + (if (not (consp (cadr selection-result))) + (push (cadr selection-result) + (cdr (alist-get (car selection-result) message + nil nil #'equal))) + (dolist (tem (cadr selection-result)) + (push tem + (cdr (alist-get (car selection-result) message + nil nil #'equal)))))))))) (prog1 (or (and (symbolp action) action) 'XdndActionCopy) commit a0b2239002d0730171c9904bd93b84447e3eb466 Author: Eli Zaretskii Date: Fri Jun 3 15:04:42 2022 +0300 ; Improve documentation of 'battery-update-functions' * lisp/battery.el (battery-update-functions) (display-battery-mode): Improve wording of doc strings. (Bug#55770) diff --git a/lisp/battery.el b/lisp/battery.el index cd68d7601f..3cff3167a6 100644 --- a/lisp/battery.el +++ b/lisp/battery.el @@ -234,11 +234,11 @@ The text being displayed in the echo area is controlled by the variables (defcustom battery-update-functions nil "Functions run by `display-battery-mode' after updating the status. -These functions will be called with one parameter: An alist that -contains data about the current battery status. The key in the -alist is a character, and the values in the alist are strings. -Different battery backends deliver different information, so the -following information may or may not be available: +These functions will be called with one parameter, an alist that +contains data about the current battery status. The keys in the +alist are single characters and the values are strings. +Different battery backends deliver different information, so some +of the following information may or may not be available: v: driver-version V: bios-version @@ -275,9 +275,9 @@ The text displayed in the mode line is controlled by The mode line is be updated every `battery-update-interval' seconds. -The update function will call the functions in -`battery-update-functions', which can be used to trigger actions -based on battery events." +The function which updates the mode-line display will call the +functions in `battery-update-functions', which can be used to +trigger actions based on battery-related events." :global t (setq battery-mode-line-string "") (or global-mode-string (setq global-mode-string '(""))) commit dc7623a59e5e90d310cb1c338790a3df5f90e891 Author: Eli Zaretskii Date: Fri Jun 3 14:50:11 2022 +0300 ; Improve documentation of new drag-and-drop APIs * lisp/dnd.el (dnd-begin-text-drag, dnd-begin-file-drag): * doc/lispref/frames.texi (Drag and Drop): Improve wording of documentation of 'dnd-begin-text-drag' and 'dnd-begin-file-drag'. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 33592e7504..9f7666ac63 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4094,36 +4094,19 @@ specific drag-n-drop protocol being used. Plain text may be On capable window systems, Emacs also supports dragging contents from its frames to windows of other applications. +@cindex drop target, in drag-and-drop operations @defun dnd-begin-text-drag text &optional frame action allow-same-frame This function begins dragging text from @var{frame} to another program -(the drop target), and returns until it is dropped or the -drag-and-drop operation is cancelled. - -The return value is the action that the drop target actually -performed, which can be one of the following symbols: - -@table @code -@item copy -The drop target inserted @var{text}. - -@item move -The drop target inserted @var{text}, but in addition the caller should -delete @var{text} from wherever it originated, such as a buffer. - -@item private -The drop target performed an unspecified action. -@end table - -@code{nil} can also be returned if the drag-and-drop operation was -cancelled. - -@var{text} is the text that will be inserted by the drop target. +(known as the @dfn{drop target}), and returns the result of +drag-and-drop operation when the text is dropped or the drag-and-drop +operation is canceled. @var{text} is the text that will be inserted +by the drop target. @var{action} must be one of the symbols @code{copy} or @code{move}, where @code{copy} means that @var{text} should be inserted by the drop target, and @code{move} means the same as @code{copy}, but in addition the caller may have to delete @var{text} from its source as explained -above. +below. @var{frame} is the frame where the mouse is currently held down, or @code{nil}, which means to use the selected frame. This function may @@ -4133,13 +4116,46 @@ only called immediately after a @code{down-mouse-1} or similar event event was generated (@pxref{Click Events}). @var{allow-same-frame} specifies whether or not drops on top of -@var{frame} itself won't be ignored. +@var{frame} itself are to be ignored. + +The return value specifies the action that the drop target actually +performed, and optionally what the caller should do. It can be one of +the following symbols: + +@table @code +@item copy +The drop target inserted the dropped text. + +@item move +The drop target inserted the dropped text, but in addition the caller +should delete @var{text} from wherever it originated, such as its +buffer. + +@item private +The drop target performed some other unspecified action. + +@item nil +The drag-and-drop operation was canceled. +@end table + @end defun @defun dnd-begin-file-drag file &optional frame action allow-same-frame This function begins dragging @var{file} from @var{frame} to another -program, and returns until it is dropped or the drag-and-drop -operation is cancelled. +program, and returns the result of the drag-and-drop operation when +the file is dropped or the drag-and-drop operation is canceled. + +If @var{file} is a remote file, then a temporary copy will be made. + +@var{action} must be one of the symbols @code{copy}, @code{move} or +@code{link}, where @code{copy} means that @var{file} should be opened +or copied by the drop target, @code{move} means the drop target should +move the file to another location, and @code{link} means the drop +target should create a symbolic link to @var{file}. It is an error to +specify @code{link} as the action if @var{file} is a remote file. + +@var{frame} and @var{allow-same-frame} have the same meaning as in +@code{dnd-begin-text-drag}. The return value is the action that the drop target actually performed, which can be one of the following symbols: @@ -4156,23 +4172,12 @@ The drop target (usually a file manager) created a symbolic link to @var{file}. @item private -The drop target performed an unspecified action. -@end table +The drop target performed some other unspecified action. -@code{nil} can also be returned if the drag-and-drop operation was -cancelled. - -If @var{file} is a remote file, then a temporary copy will be made. - -@var{action} must be one of the symbols @code{copy}, @code{move} or -@code{link}, where @code{copy} means that @var{file} should be opened -or copied by the drop target, @code{move} means the drop target should -move the file to another location, and @code{link} means the drop -target should create a symbolic link to @var{file}. It is an error to -specify @code{link} as the action if @var{file} is a remote file. +@item nil +The drag-and-drop operation was canceled. +@end table -@var{frame} and @var{allow-same-frame} mean the same as in -@code{dnd-begin-text-drag}. @end defun @defun dnd-begin-drag-files files &optional frame action allow-same-frame @@ -4184,7 +4189,7 @@ dropping multiple files, then the first file will be used instead. @cindex initiating drag-and-drop, low-level The high-level interfaces described above are implemented on top of a lower-level primitive. If you need to drag content other than files -or text, the low-level interface @code{x-begin-drag} can be used +or text, use the low-level interface @code{x-begin-drag} instead. However, using it will require detailed knowledge of the data types and actions used by the programs to transfer content via drag-and-drop on each platform you want to support. diff --git a/lisp/dnd.el b/lisp/dnd.el index c5d5788dc4..14d80ac6c5 100644 --- a/lisp/dnd.el +++ b/lisp/dnd.el @@ -313,10 +313,10 @@ in that list instead." "Begin dragging TEXT from FRAME. Initate a drag-and-drop operation allowing the user to drag text from Emacs to another program (the drop target), then block until -the drop happens or is cancelled. +the drop is completed or is cancelled. -Return the action that the drop target actually performed, which -can be one of the following symbols: +If the drop completed, return the action that the drop target +actually performed, which can be one of the following symbols: - `copy', which means TEXT was inserted by the drop target. @@ -331,13 +331,13 @@ Return nil if the drop was cancelled. TEXT is a string containing text that will be inserted by the program where the drop happened. FRAME is the frame where the -mouse is currently held down, or nil (which means to use the -current frame). ACTION is one of the symbols `copy' or `move', +mouse is currently held down, or nil, which stands for the +current frame. ACTION is one of the symbols `copy' or `move', where `copy' means that the text should be inserted by the drop -target, and `move' means the the same as copy, but in addition +target, and `move' means the the same as `copy', but in addition the caller might have to delete TEXT from its source after this -function returns. If ALLOW-SAME-FRAME is nil, any drops on FRAME -itself will be ignored. +function returns. If ALLOW-SAME-FRAME is nil, ignore any drops +on FRAME itself. This function might return immediately if no mouse buttons are currently being held down. It should only be called upon a @@ -367,7 +367,7 @@ currently being held down. It should only be called upon a (defun dnd-begin-file-drag (file &optional frame action allow-same-frame) "Begin dragging FILE from FRAME. -Initate a drag-and-drop operation allowing the user to drag files +Initate a drag-and-drop operation allowing the user to drag a file from Emacs to another program (the drop target), then block until the drop happens or is cancelled. @@ -387,17 +387,17 @@ can be one of the following symbols: Return nil if the drop was cancelled. -FILE is the file name that will be inserted by the program where -the drop happened. If it is a remote file, a temporary copy will -be made. FRAME is the frame where the mouse is currently held -down, or nil (which means to use the current frame). ACTION is -one of the symbols `copy', `move' or `link', where `copy' means -that the file should be opened or copied by the drop target, -`move' means the drop target should move the file to another -location, and `link' means the drop target should create a -symbolic link to FILE. It is an error to specify `link' as the -action if FILE is a remote file. If ALLOW-SAME-FRAME is nil, any -drops on FRAME itself will be ignored. +FILE is the file name that will be sent to the program where the +drop happened. If it is a remote file, Emacs will make a +temporary copy and pass that. FRAME is the frame where the mouse +is currently held down, or nil (which means to use the current +frame). ACTION is one of the symbols `copy', `move' or `link', +where `copy' means that the file should be opened or copied by +the drop target, `move' means the drop target should move the +file to another location, and `link' means the drop target should +create a symbolic link to FILE. It is an error to specify `link' +as the action if FILE is a remote file. If ALLOW-SAME-FRAME is +nil, any drops on FRAME itself will be ignored. This function might return immediately if no mouse buttons are currently being held down. It should only be called upon a commit ca2e7409dcd694742704e424c3f6f5bc5f230f25 Author: Po Lu Date: Fri Jun 3 19:43:06 2022 +0800 Allow dragging multiple files from a Dired buffer * doc/lispref/frames.texi (Drag and Drop): Document new function `dnd-begin-drag-files'. * lisp/dired.el (dired-mouse-drag-files): Update doc string. (dired-map-over-marks): Accept a new value of ARG `marked', meaning to not fall back to the current file if no marks were found. (dired-mouse-drag): Handle marked files in an intuitive way. * lisp/dnd.el (dnd-last-dragged-remote-file): Allow list values as well. (dnd-remove-last-dragged-remote-file): Handle list values. (dnd-begin-file-drag): Fix file name expansion. (dnd-begin-drag-files): New function. * lisp/select.el (xselect-convert-to-filename): Handle mutiple files (a vector of file names):. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 26b519be23..33592e7504 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4175,6 +4175,12 @@ specify @code{link} as the action if @var{file} is a remote file. @code{dnd-begin-text-drag}. @end defun +@defun dnd-begin-drag-files files &optional frame action allow-same-frame +This function is like @code{dnd-begin-file-drag}, except that +@var{files} is a list of files. If the drop target doesn't support +dropping multiple files, then the first file will be used instead. +@end defun + @cindex initiating drag-and-drop, low-level The high-level interfaces described above are implemented on top of a lower-level primitive. If you need to drag content other than files diff --git a/lisp/dired.el b/lisp/dired.el index 94df2ddc4e..1ab2c8c38b 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -253,8 +253,9 @@ The target is used in the prompt for file copy, rename etc." (defcustom dired-mouse-drag-files nil "If non-nil, allow the mouse to drag files from inside a Dired buffer. Dragging the mouse and then releasing it over the window of -another program will result in that program opening the file, or -creating a copy of it. This feature is supported only on X +another program will result in that program opening or creating a +copy of the file underneath the mouse pointer (or all marked +files if it was marked). This feature is supported only on X Windows, Haiku, and Nextstep (macOS or GNUstep). If the value is `link', then a symbolic link will be created to @@ -809,6 +810,9 @@ that commands on the next ARG (instead of the marked) files can be chained easily. For any other non-nil value of ARG, use the current file. +If ARG is `marked', don't return the current file if nothing else +is marked. + If optional third arg SHOW-PROGRESS evaluates to non-nil, redisplay the dired buffer after each file is processed. @@ -830,7 +834,7 @@ marked file, return (t FILENAME) instead of (FILENAME)." ;;This warning should not apply any longer, sk 2-Sep-1991 14:10. `(prog1 (let ((inhibit-read-only t) case-fold-search found results) - (if ,arg + (if (and ,arg (not (eq ,arg 'marked))) (if (integerp ,arg) (progn ;; no save-excursion, want to move point. (dired-repeat-over-lines @@ -841,8 +845,8 @@ marked file, return (t FILENAME) instead of (FILENAME)." (if (< ,arg 0) (nreverse results) results)) - ;; non-nil, non-integer ARG means use current file: - (list ,body)) + ;; non-nil, non-integer, non-marked ARG means use current file: + (list ,body)) (let ((regexp (dired-marker-regexp)) next-position) (save-excursion (goto-char (point-min)) @@ -867,7 +871,8 @@ marked file, return (t FILENAME) instead of (FILENAME)." (setq results (cons t results))) (if found results - (list ,body))))) + (unless (eq ,arg 'marked) + (list ,body)))))) ;; save-excursion loses, again (dired-move-to-filename))) @@ -1706,7 +1711,9 @@ see `dired-use-ls-dired' for more details.") (declare-function x-begin-drag "xfns.c") (defun dired-mouse-drag (event) - "Begin a drag-and-drop operation for the file at EVENT." + "Begin a drag-and-drop operation for the file at EVENT. +If there are marked files and that file is marked, drag every +other marked file as well. Otherwise, unmark all files." (interactive "e") (when mark-active (deactivate-mark)) @@ -1736,12 +1743,30 @@ see `dired-use-ls-dired' for more details.") (condition-case nil (let ((filename (with-selected-window (posn-window (event-end event)) - (dired-file-name-at-point)))) + (let ((marked-files (dired-map-over-marks (dired-get-filename + nil 'no-error-if-not-filep) + 'marked)) + (file-name (dired-get-filename nil 'no-error-if-not-filep))) + (if (and marked-files + (member file-name marked-files)) + marked-files + (when marked-files + (dired-map-over-marks (dired-unmark nil) + 'marked)) + file-name))))) (when filename - (dnd-begin-file-drag filename nil - (if (eq 'dired-mouse-drag-files 'link) - 'move 'copy) - t))) + (if (and (consp filename) + (cdr filename)) + (dnd-begin-drag-files filename nil + (if (eq 'dired-mouse-drag-files 'link) + 'move 'copy) + t) + (dnd-begin-file-drag (if (stringp filename) + filename + (car filename)) + nil (if (eq 'dired-mouse-drag-files 'link) + 'move 'copy) + t)))) (error (when (eq (event-basic-type new-event) 'mouse-1) (push new-event unread-command-events)))))))))) diff --git a/lisp/dnd.el b/lisp/dnd.el index f45f8fc849..c5d5788dc4 100644 --- a/lisp/dnd.el +++ b/lisp/dnd.el @@ -288,18 +288,24 @@ TEXT is the text as a string, WINDOW is the window where the drop happened." (defvar dnd-last-dragged-remote-file nil "If non-nil, the name of a local copy of the last remote file that was dragged. +This may also be a list of files, if multiple files were dragged. It can't be removed immediately after the drag-and-drop operation completes, since there is no way to determine when the drop target has finished opening it. So instead, this file is removed when Emacs exits or the user drags another file.") (defun dnd-remove-last-dragged-remote-file () - "Remove the local copy of the last remote file to be dragged." + "Remove the local copy of the last remote file to be dragged. +If `dnd-last-dragged-remote-file' is a list, remove all the files +in that list instead." (when dnd-last-dragged-remote-file (unwind-protect - (delete-file dnd-last-dragged-remote-file) + (if (consp dnd-last-dragged-remote-file) + (mapc #'delete-file dnd-last-dragged-remote-file) + (delete-file dnd-last-dragged-remote-file)) (setq dnd-last-dragged-remote-file nil))) - (remove-hook 'kill-emacs-hook #'dnd-remove-last-dragged-remote-file)) + (remove-hook 'kill-emacs-hook + #'dnd-remove-last-dragged-remote-file)) (declare-function x-begin-drag "xfns.c") @@ -410,7 +416,7 @@ currently being held down. It should only be called upon a (add-hook 'kill-emacs-hook #'dnd-remove-last-dragged-remote-file))) (gui-set-selection 'XdndSelection - (propertize file 'text/uri-list + (propertize (expand-file-name file) 'text/uri-list (concat "file://" (expand-file-name file)))) (let ((return-value @@ -444,6 +450,67 @@ currently being held down. It should only be called upon a ((not return-value) nil) (t 'private))))) +(defun dnd-begin-drag-files (files &optional frame action allow-same-frame) + "Begin dragging FILES from FRAME. +This is like `dnd-begin-file-drag', except with multiple files. +FRAME, ACTION and ALLOW-SAME-FRAME mean the same as in +`dnd-begin-file-drag'. + +FILES is a list of files that will be dragged. If the drop +target doesn't support dropping multiple files, the first file in +FILES will be dragged." + (unless (fboundp 'x-begin-drag) + (error "Dragging files from Emacs is not supported by this window system")) + (dnd-remove-last-dragged-remote-file) + (let* ((new-files (copy-sequence files)) + (tem new-files)) + (while tem + (setcar tem (expand-file-name (car tem))) + (when (file-remote-p (car tem)) + (when (eq action 'link) + (error "Cannot create symbolic link to remote file")) + (setcar tem (file-local-copy (car tem))) + (push (car tem) dnd-last-dragged-remote-file)) + (setq tem (cdr tem))) + (unless action + (setq action 'copy)) + (gui-set-selection 'XdndSelection + (propertize (car new-files) + 'text/uri-list + (cl-loop for file in new-files + collect (concat "file://" file) + into targets finally return + (apply #'vector targets)) + 'FILE_NAME (apply #'vector new-files))) + (let ((return-value + (x-begin-drag '(;; Xdnd types used by GTK, Qt, and most other + ;; modern programs that expect filenames to + ;; be supplied as URIs. + "text/uri-list" "text/x-dnd-username" + ;; Traditional X selection targets used by + ;; programs supporting the Motif + ;; drag-and-drop protocols. Also used by NS + ;; and Haiku. + "FILE_NAME" "HOST_NAME") + (cl-ecase action + ('copy 'XdndActionCopy) + ('move 'XdndActionMove) + ('link 'XdndActionLink)) + frame nil allow-same-frame))) + (cond + ((eq return-value 'XdndActionCopy) 'copy) + ((eq return-value 'XdndActionMove) + (prog1 'move + ;; If original-file is a remote file, delete it from the + ;; remote as well. + (dolist (original-file files) + (when (file-remote-p original-file) + (ignore-errors + (delete-file original-file)))))) + ((eq return-value 'XdndActionLink) 'link) + ((not return-value) nil) + (t 'private))))) + (provide 'dnd) ;;; dnd.el ends here diff --git a/lisp/select.el b/lisp/select.el index 01e002db70..df1d402655 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -628,10 +628,22 @@ two markers or an overlay. Otherwise, it is nil." (if (not (eq selection 'XdndSelection)) (when (setq value (xselect--selection-bounds value)) (xselect--encode-string 'TEXT (buffer-file-name (nth 2 value)))) - (when (and (stringp value) - (file-exists-p value)) - (xselect--encode-string 'TEXT (expand-file-name value) - nil t)))) + (if (and (stringp value) + (file-exists-p value)) + (xselect--encode-string 'TEXT (expand-file-name value) + nil t) + (when (vectorp value) + (with-temp-buffer + (cl-loop for file across value + do (progn (insert (encode-coding-string + (expand-file-name file) + file-name-coding-system)) + (insert "\0"))) + ;; Get rid of the last NULL byte. + (when (> (point) 1) + (delete-char -1)) + ;; Motif wants STRING. + (cons 'STRING (buffer-string))))))) (defun xselect-convert-to-charpos (_selection _type value) (when (setq value (xselect--selection-bounds value)) commit 977f3f27c549db27a2d6fb33e0112b03f9b57371 Author: Lars Ingebrigtsen Date: Fri Jun 3 13:09:25 2022 +0200 Don't issue warnings for Unicode quotes for now * lisp/emacs-lisp/bytecomp.el (byte-compile-docstring-style-warn): Remove warning for "Unicode quotes" for now (bug#55780). diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 5d16d55089..2e89504e8f 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1761,12 +1761,6 @@ It is too wide if it has any lines longer than the largest of (when (string-match-p "\\( \"\\|[ \t]\\|^\\)'[a-z(]" docs) (byte-compile-warn-x name "%s%sdocstring has wrong usage of unescaped single quotes (use \\= or different quoting)" - kind name)) - ;; There's a "Unicode quote" in the string -- it should probably - ;; be an ASCII one instead. - (when (string-match-p "\\( \"\\|[ \t]\\|^\\)[‘’]" docs) - (byte-compile-warn-x - name "%s%sdocstring has wrong usage of \"fancy\" single quotation marks" kind name))))) form) commit 1ed9c1c7f9fe32ff5123091033350beb1ccae4ca Author: Lars Ingebrigtsen Date: Fri Jun 3 13:04:13 2022 +0200 Revert the `...' documentation back to actual usage * doc/lispref/tips.texi (Documentation Tips): Document how `...' is really used now (bug#55780). ‘...’ is not really used in the Emacs sources. diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi index 061a5d672e..8232550220 100644 --- a/doc/lispref/tips.texi +++ b/doc/lispref/tips.texi @@ -694,26 +694,20 @@ starting double-quote is not part of the string! @cindex curly quotes @cindex curved quotes When a documentation string refers to a Lisp symbol, write it as it -would be printed (which usually means in lower case), surrounding it -with curved single quotes (@t{‘..’}). There are two exceptions: write -@code{t} and @code{nil} without surrounding punctuation. For example: +would be printed (which usually means in lower case), with a grave +accent @samp{`} before and apostrophe @samp{'} after it. There are +two exceptions: write @code{t} and @code{nil} without surrounding +punctuation. For example: @example - CODE can be ‘lambda’, nil, or t. + CODE can be `lambda', nil, or t. @end example -@noindent -@xref{Quotation Marks,,, emacs, The GNU Emacs Manual}, for how to -enter curved single quotes. - -Documentation strings can also use an older single-quoting convention, -which quotes symbols with grave accent @t{`} and apostrophe -@t{'}: @t{`like-this'} rather than @t{‘like-this’}. This -older convention was designed for now-obsolete displays in which grave -accent and apostrophe were mirror images. -Documentation using this convention is converted to the user's -preferred format when it is copied into a help buffer. @xref{Keys in -Documentation}. +Note that when Emacs displays these doc strings, Emacs will usually +display @samp{`} (grave accent) as @samp{‘} (left single quotation +mark) and @samp{'} (apostrophe) as @samp{’} (right single quotation +mark), if the display supports displaying these characters. +@xref{Keys in Documentation}. @cindex hyperlinks in documentation strings Help mode automatically creates a hyperlink when a documentation string commit 28622d4dd0347227a28b7b25c674437239a00a06 Author: Mattias Engdegård Date: Fri Jun 3 10:12:24 2022 +0200 Let ?\LF signal an error (bug#55738) As suggested by Stefan Monnier. * src/lread.c (read_escape): Signal an error for ?\LF since it cannot reasonably be intended. * test/src/lread-tests.el (lread-escaped-lf): Update test. * etc/NEWS: Announce. diff --git a/etc/NEWS b/etc/NEWS index f9409bb24f..54bc6d80e1 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1922,6 +1922,9 @@ It was previously only run by 'clone-indirect-buffer' and called by both of these, the hook is now run by all 3 of these functions. +--- +** '?\' at the end of a line now signals an error. +Previously it produced a nonsense value, -1, that was never intended. * Lisp Changes in Emacs 29.1 diff --git a/src/lread.c b/src/lread.c index 4b7d38a8e6..1d20470a8b 100644 --- a/src/lread.c +++ b/src/lread.c @@ -2664,6 +2664,10 @@ read_escape (Lisp_Object readcharfun) case 'v': return '\v'; + case '\n': + /* ?\LF is an error; it's probably a user mistake. */ + error ("Invalid escape character syntax"); + case 'M': c = READCHAR; if (c != '-') diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el index 99eec9d548..f190f14781 100644 --- a/test/src/lread-tests.el +++ b/test/src/lread-tests.el @@ -318,8 +318,8 @@ literals (Bug#20852)." '(## . 2)))) (ert-deftest lread-escaped-lf () - ;; ?\LF should produce LF (only inside string literals do we ignore \LF). - (should (equal (read-from-string "?\\\n") '(?\n . 3))) + ;; ?\LF should signal an error; \LF is ignored inside string literals. + (should-error (read-from-string "?\\\n x")) (should (equal (read-from-string "\"a\\\nb\"") '("ab" . 6)))) ;;; lread-tests.el ends here commit e48c9181b1c103b42032a5fb6547184da75bd773 Author: Mattias Engdegård Date: Fri Jun 3 11:05:18 2022 +0200 Fix wrong value in idlwave-comment-indent-char * lisp/progmodes/idlwave.el (idlwave-comment-indent-char): Use a space since that is clearly what was meant. ?\ at the end of a line (ie, ?\LF) never was well-defined and produced -1 most of the time, but will soon raise an error (bug#55738). This doesn't matter much becaue this variable is unused. diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el index e3985db64a..edb53793e6 100644 --- a/lisp/progmodes/idlwave.el +++ b/lisp/progmodes/idlwave.el @@ -1353,7 +1353,7 @@ the leftover unidentified statements containing an equal sign.") ;; Note that this is documented in the v18 manuals as being a string ;; of length one rather than a single character. ;; The code in this file accepts either format for compatibility. -(defvar idlwave-comment-indent-char ?\ +(defvar idlwave-comment-indent-char ?\s "Character to be inserted for IDL comment indentation. Normally a space.") commit 4f56ca63761b0270edb58734ce7ac4a3c800bb1b Author: Po Lu Date: Fri Jun 3 15:20:23 2022 +0800 Add new user option `mouse-drag-mode-line-buffer' * etc/NEWS: Announce new option. Also add missing entries for an earlier change. * lisp/mouse.el (mouse-drag-mode-line-buffer): New user option. (mouse-drag-mode-line): Implement that option. diff --git a/etc/NEWS b/etc/NEWS index 3870e937df..f9409bb24f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -305,6 +305,10 @@ the current Emacs process at the end, it starts a new Emacs process optional parameters to restart instead of just killing the current process. +** New user option 'mouse-drag-mode-line-buffer'. +If non-nil, dragging on the buffer name part of the mode-line will +drag the buffer's associated file to other programs. + +++ ** New user option 'mouse-drag-and-drop-region-cross-program'. If non-nil, this option allows dragging text in the region from Emacs @@ -2083,9 +2087,9 @@ list in reported motion events if there is no frame underneath the mouse pointer. +++ -** New function 'x-begin-drag'. -This function initiates a drag-and-drop request with the contents of -the selection 'XdndSelection', and returns when a drop occurs. +** New functions 'x-begin-drag', 'dnd-begin-text-drag' and 'dnd-begin-file-drag'. +These functions allow dragging contents (such as files and text) from +Emacs to other programs. --- ** New function 'ietf-drums-parse-date-string'. diff --git a/lisp/mouse.el b/lisp/mouse.el index 5834d4a666..1f2e925222 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -108,6 +108,13 @@ down and up respectively." (integer :tag "This many lines from window top or bottom")) :version "29.1") +(defcustom mouse-drag-mode-line-buffer nil + "If non-nil, allow dragging files from the mode line. +When the buffer has an associated file, it can be dragged from +the buffer name portion of its mode line to other programs." + :type 'boolean + :version "29.1") + (defvar mouse--last-down nil) (defun mouse--down-1-maybe-follows-link (&optional _prompt) @@ -854,8 +861,29 @@ frame instead." (interactive "e") (let* ((start (event-start start-event)) (window (posn-window start)) - (frame (window-frame window))) + (frame (window-frame window)) + (skip-tracking nil) + filename) + ;; FIXME: is there a better way of determining if the event + ;; started on a buffer name? + (when (and mouse-drag-mode-line-buffer + (eq (car (posn-string start)) + (car (with-selected-window window + (setq filename (buffer-file-name)) + mode-line-buffer-identification))) + filename + (file-exists-p filename)) + (let ((mouse-fine-grained-tracking nil)) + (track-mouse + (setq track-mouse 'drag-source) + (let ((event (read-event))) + (if (not (eq (event-basic-type event) + 'mouse-movement)) + (push event unread-command-events) + (dnd-begin-file-drag filename frame 'copy t) + (setq skip-tracking t)))))) (cond + (skip-tracking t) ((not (window-live-p window))) ((or (not (window-at-side-p window 'bottom)) ;; Allow resizing the minibuffer window if it's on the