commit edabfe4ff66090b3b2c433962df4cfe1a68259fd (HEAD, refs/remotes/origin/master) Author: Po Lu Date: Sat Jul 9 04:50:06 2022 +0000 Fix race conditions handling selection clear events on Haiku * src/haiku_select.cc (be_handle_clipboard_changed_message): Include current clipboard count. (be_selection_outdated_p): New function. * src/haikuselect.c (haiku_handle_selection_clear): Ignore outdated events. (haiku_selection_disowned): New argument `count'. Include it in the timestamp field of the selection clear event. * src/haikuselect.h: Update prototypes. * src/systime.h: Define `Time' to an appropriate value on Haiku. diff --git a/src/haiku_select.cc b/src/haiku_select.cc index edb821e313..e1f2a81524 100644 --- a/src/haiku_select.cc +++ b/src/haiku_select.cc @@ -451,31 +451,37 @@ be_unlock_clipboard (enum haiku_clipboard clipboard, bool discard) void be_handle_clipboard_changed_message (void) { + int64 n_clipboard, n_primary, n_secondary; + + n_clipboard = system_clipboard->SystemCount (); + n_primary = primary->SystemCount (); + n_secondary = secondary->SystemCount (); + if (count_clipboard != -1 - && (system_clipboard->SystemCount () - > count_clipboard + 1) + && (n_clipboard > count_clipboard + 1) && owned_clipboard) { owned_clipboard = false; - haiku_selection_disowned (CLIPBOARD_CLIPBOARD); + haiku_selection_disowned (CLIPBOARD_CLIPBOARD, + n_clipboard); } if (count_primary != -1 - && (primary->SystemCount () - > count_primary + 1) + && (n_primary > count_primary + 1) && owned_primary) { owned_primary = false; - haiku_selection_disowned (CLIPBOARD_PRIMARY); + haiku_selection_disowned (CLIPBOARD_PRIMARY, + n_primary); } if (count_secondary != -1 - && (secondary->SystemCount () - > count_secondary + 1) + && (n_secondary > count_secondary + 1) && owned_secondary) { owned_secondary = false; - haiku_selection_disowned (CLIPBOARD_SECONDARY); + haiku_selection_disowned (CLIPBOARD_SECONDARY, + n_secondary); } } @@ -487,3 +493,18 @@ be_start_watching_selection (enum haiku_clipboard id) clipboard = get_clipboard_object (id); clipboard->StartWatching (be_app); } + +bool +be_selection_outdated_p (enum haiku_clipboard id, int64 count) +{ + if (id == CLIPBOARD_CLIPBOARD && count_clipboard > count) + return true; + + if (id == CLIPBOARD_PRIMARY && count_primary > count) + return true; + + if (id == CLIPBOARD_SECONDARY && count_secondary > count) + return true; + + return false; +} diff --git a/src/haikuselect.c b/src/haikuselect.c index 03aba1f9ba..9d8c4a2cd1 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -1024,6 +1024,13 @@ init_haiku_select (void) void haiku_handle_selection_clear (struct input_event *ie) { + enum haiku_clipboard id; + + id = haiku_get_clipboard_name (ie->arg); + + if (be_selection_outdated_p (id, ie->timestamp)) + return; + CALLN (Frun_hook_with_args, Qhaiku_lost_selection_functions, ie->arg); @@ -1033,7 +1040,7 @@ haiku_handle_selection_clear (struct input_event *ie) } void -haiku_selection_disowned (enum haiku_clipboard id) +haiku_selection_disowned (enum haiku_clipboard id, int64 count) { struct input_event ie; @@ -1055,6 +1062,7 @@ haiku_selection_disowned (enum haiku_clipboard id) break; } + ie.timestamp = count; kbd_buffer_store_event (&ie); } diff --git a/src/haikuselect.h b/src/haikuselect.h index d027834e8b..61efeb9cd9 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h @@ -39,7 +39,7 @@ extern "C" { #endif /* Defined in haikuselect.c. */ -extern void haiku_selection_disowned (enum haiku_clipboard); +extern void haiku_selection_disowned (enum haiku_clipboard, int64); /* Defined in haiku_select.cc. */ extern void be_clipboard_init (void); @@ -66,6 +66,7 @@ extern int be_lock_clipboard_message (enum haiku_clipboard, void **, bool); extern void be_unlock_clipboard (enum haiku_clipboard, bool); extern void be_handle_clipboard_changed_message (void); extern void be_start_watching_selection (enum haiku_clipboard); +extern bool be_selection_outdated_p (enum haiku_clipboard, int64); #ifdef __cplusplus }; diff --git a/src/systime.h b/src/systime.h index 75088bd4a6..085a7ddeab 100644 --- a/src/systime.h +++ b/src/systime.h @@ -26,6 +26,9 @@ INLINE_HEADER_BEGIN #ifdef HAVE_X_WINDOWS # include +#elif defined HAVE_HAIKU +# include +typedef int64 Time; #else typedef unsigned long Time; #endif commit f400c60237f04781b60423492c583beea6c77e8e Merge: 29c8866c7f 3442de2edd Author: Stefan Kangas Date: Sat Jul 9 06:30:38 2022 +0200 Merge from origin/emacs-28 3442de2edd Doc fix; don't mention obsolete variable c4e251103b ; * lisp/textmodes/rst.el: Update URLs. commit 29c8866c7fcd325995c6fc9b2b18537855fee52c Author: Po Lu Date: Sat Jul 9 01:16:05 2022 +0000 Fix redisplay after running selection hook on Haiku * src/haikuselect.c (haiku_handle_selection_clear): Call redisplay_preserve_echo_area. diff --git a/src/haikuselect.c b/src/haikuselect.c index 999a0f5ac2..03aba1f9ba 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -1026,6 +1026,10 @@ haiku_handle_selection_clear (struct input_event *ie) { CALLN (Frun_hook_with_args, Qhaiku_lost_selection_functions, ie->arg); + + /* This is required for redisplay to happen if something changed the + display inside the selection loss functions. */ + redisplay_preserve_echo_area (20); } void commit 35ae8d9f3b18c34a6e6c594afcc442e7aaa5fe29 Author: Po Lu Date: Sat Jul 9 09:07:07 2022 +0800 Add new minor mode to deactivate the region once PRIMARY is lost * doc/emacs/killing.texi (Primary Selection): Document new minor mode `lost-selection-mode'. * etc/NEWS: Announce new minor mode. * lisp/select.el (lost-selection-function): New function. (lost-selection-mode): New global minor mode. diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi index 4435f6e494..bb8d51158a 100644 --- a/doc/emacs/killing.texi +++ b/doc/emacs/killing.texi @@ -610,14 +610,14 @@ yanks the contents of the clipboard at point. @cindex primary selection @cindex selection, primary - Under the X Window System, there exists a @dfn{primary selection} -containing the last stretch of text selected in an X application -(usually by dragging the mouse). Typically, this text can be inserted -into other X applications by @kbd{mouse-2} clicks. The primary -selection is separate from the clipboard. Its contents are more -fragile; they are overwritten each time you select text with the -mouse, whereas the clipboard is only overwritten by explicit cut -or copy commands. + Under the X Window System, PGTK and Haiku, there exists a +@dfn{primary selection} containing the last stretch of text selected +in an X application (usually by dragging the mouse). Typically, this +text can be inserted into other X applications by @kbd{mouse-2} +clicks. The primary selection is separate from the clipboard. Its +contents are more fragile; they are overwritten each time you select +text with the mouse, whereas the clipboard is only overwritten by +explicit cut or copy commands. Under X, whenever the region is active (@pxref{Mark}), the text in the region is saved in the primary selection. This applies regardless @@ -639,6 +639,13 @@ regions to the primary selection entirely. (@kbd{C-y}) to insert this text if @code{select-enable-primary} is set (@pxref{Clipboard}). +@cindex lost-selection-mode + By default, Emacs keeps the region active even after text is +selected in another program; this is contrary to typical X behavior. +To make Emacs deactivate the region after another program places data +in the primary selection, enable the global minor mode +@code{lost-selection-mode}. + @cindex MS-Windows, and primary selection MS-Windows provides no primary selection, but Emacs emulates it within a single Emacs session by storing the selected text internally. diff --git a/etc/NEWS b/etc/NEWS index 925bd9a212..5831bbefd4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2421,6 +2421,11 @@ This is meant to be used in modes that have a header line that should be kept aligned with the buffer contents when the user switches 'display-line-numbers-mode' on or off. ++++ +** New minor mode 'lost-selection-mode'. +This minor mode makes Emacs deactivate the mark in all buffers when +the primary selection is obtained by another program. + +++ ** New predicate 'char-uppercase-p'. This returns non-nil if its argument its an uppercase character. diff --git a/lisp/select.el b/lisp/select.el index d977a8714b..6002b2615e 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -475,6 +475,45 @@ are not available to other programs." (symbolp data) (integerp data))) + +;; Minor mode to make losing ownership of PRIMARY behave more like +;; other X programs. + +(defun lost-selection-function (selection) + "Handle losing of ownership of SELECTION. +If SELECTION is `PRIMARY', deactivate the mark in every +non-temporary buffer." + (let ((select-active-regions nil)) + (when (eq selection 'PRIMARY) + (dolist (buffer (buffer-list)) + (unless (string-match-p "^ " + (buffer-name buffer)) + (with-current-buffer buffer + (deactivate-mark t))))))) + +(define-minor-mode lost-selection-mode + "Toggle `lost-selection-mode'. + +When this is enabled, selecting some text in another program will +cause the mark to be deactivated in all buffers, mimicking the +behavior of most X Windows programs." + :global t + :group 'x + (if lost-selection-mode + (cond ((featurep 'x) (add-hook 'x-lost-selection-functions + #'lost-selection-function)) + ((featurep 'pgtk) (add-hook 'pgtk-lost-selection-functions + #'lost-selection-function)) + ((featurep 'haiku) (add-hook 'haiku-lost-selection-functions + #'lost-selection-function))) + (cond ((featurep 'x) (remove-hook 'x-lost-selection-functions + #'lost-selection-function)) + ((featurep 'pgtk) (remove-hook 'pgtk-lost-selection-functions + #'lost-selection-function)) + ((featurep 'haiku) (remove-hook 'haiku-lost-selection-functions + #'lost-selection-function))))) + + ;; Functions to convert the selection into various other selection types. ;; Every selection type that Emacs handles is implemented this way, except ;; for TIMESTAMP, which is a special case. commit 3d3aaf3af3e497e5ed1aa5924c73fadf45ea3eef Author: Sean Whitton Date: Fri Jul 8 17:28:51 2022 -0700 ; * message.el (message-auto-save-directory): Clarify docstring. diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 48115a4165..7c2b24c6ee 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -1411,7 +1411,7 @@ text and it replaces `self-insert-command' with the other command, e.g. (file-name-as-directory (expand-file-name "drafts" message-directory)) "~/") "Directory where Message auto-saves buffers if Gnus isn't running. -If nil, Message won't auto-save." +If nil, Message won't auto-save, whether or not Gnus is running." :group 'message-buffers :link '(custom-manual "(message)Various Message Variables") :type '(choice directory (const :tag "Don't auto-save" nil))) commit ee5814178503c327f703e03f372f792fa1689632 Author: Po Lu Date: Sat Jul 9 08:05:30 2022 +0800 Speed up querying for window manager support * src/xterm.c (handle_one_xevent): Clear net_supported_window if it is destroyed. (x_get_wm_check_window): New function. (x_wm_supports_1): First try net_supported_window. If it still exists, don't ask for _NET_SUPPORTING_WM_CHECK. diff --git a/src/xterm.c b/src/xterm.c index 23a784ade8..1afb8adcfe 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -19215,6 +19215,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto OTHER; case DestroyNotify: + if (event->xdestroywindow.window + == dpyinfo->net_supported_window) + dpyinfo->net_supported_window = None; + xft_settings_event (dpyinfo, event); break; @@ -24076,6 +24080,36 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) unblock_input (); } +static Window +x_get_wm_check_window (struct x_display_info *dpyinfo) +{ + Window result; + unsigned char *tmp_data = NULL; + int rc, actual_format; + unsigned long actual_size, bytes_remaining; + Atom actual_type; + + rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, + dpyinfo->Xatom_net_supporting_wm_check, + 0, 1, False, XA_WINDOW, &actual_type, + &actual_format, &actual_size, + &bytes_remaining, &tmp_data); + + if (rc != Success || actual_type != XA_WINDOW + || actual_format != 32 || actual_size != 1) + { + if (tmp_data) + XFree (tmp_data); + + return None; + } + + result = *(Window *) tmp_data; + XFree (tmp_data); + + return result; +} + /* Return true if _NET_SUPPORTING_WM_CHECK window exists and _NET_SUPPORTED on the root window for frame F contains ATOMNAME. This is how a WM check shall be done according to the Window Manager @@ -24099,30 +24133,32 @@ x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom) block_input (); x_catch_errors (dpy); - rc = XGetWindowProperty (dpy, target_window, - dpyinfo->Xatom_net_supporting_wm_check, - 0, max_len, False, target_type, - &actual_type, &actual_format, &actual_size, - &bytes_remaining, &tmp_data); - if (rc != Success || actual_type != XA_WINDOW || x_had_errors_p (dpy)) - { - if (tmp_data) XFree (tmp_data); - x_uncatch_errors (); - unblock_input (); - return false; - } + wmcheck_window = dpyinfo->net_supported_window; - wmcheck_window = *(Window *) tmp_data; - XFree (tmp_data); + if (wmcheck_window == None) + wmcheck_window = x_get_wm_check_window (dpyinfo); - /* Check if window exists. */ - XSelectInput (dpy, wmcheck_window, StructureNotifyMask); - if (x_had_errors_p (dpy)) + if (!x_special_window_exists_p (dpyinfo, wmcheck_window)) { - x_uncatch_errors_after_check (); - unblock_input (); - return false; + if (dpyinfo->net_supported_window != None) + { + dpyinfo->net_supported_window = None; + wmcheck_window = x_get_wm_check_window (dpyinfo); + + if (!x_special_window_exists_p (dpyinfo, wmcheck_window)) + { + x_uncatch_errors (); + unblock_input (); + return false; + } + } + else + { + x_uncatch_errors (); + unblock_input (); + return false; + } } if (dpyinfo->net_supported_window != wmcheck_window) commit 0508d7c4d6637d63a823b66e9f87ab54c2e73b09 Author: Alan Mackenzie Date: Fri Jul 8 20:19:03 2022 +0000 Remove now unused parameter TRACK from do_switch_frame. * src/lisp.h (extern do_swith_frame declaration) * src/frame.c (do_switch_frame): Remove parameter TRACK and its comment. * src/frame.c (Fselect_frame, Fhandle_switch_frame, delete_frame) * src/keyboard.c (quit_throw_to_read_char) * src/minibuf.c (read_minibuf_unwind (twice)) * src/window.c (Fset_window_configuration): Remove argument TRACK. diff --git a/src/frame.c b/src/frame.c index 4828595b93..923ef2d609 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1444,10 +1444,6 @@ affects all frames on the same terminal device. */) If FRAME is a switch-frame event `(switch-frame FRAME1)', use FRAME1 as frame. - If TRACK is non-zero and the frame that currently has the focus - redirects its focus to the selected frame, redirect that focused - frame's focus to FRAME instead. - FOR_DELETION non-zero means that the selected frame is being deleted, which includes the possibility that the frame's terminal is dead. @@ -1455,7 +1451,7 @@ affects all frames on the same terminal device. */) The value of NORECORD is passed as argument to Fselect_window. */ Lisp_Object -do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord) +do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) { struct frame *sf = SELECTED_FRAME (), *f; @@ -1574,7 +1570,7 @@ This function returns FRAME, or nil if FRAME has been deleted. */) /* Do not select a tooltip frame (Bug#47207). */ error ("Cannot select a tooltip frame"); else - return do_switch_frame (frame, 1, 0, norecord); + return do_switch_frame (frame, 0, norecord); } DEFUN ("handle-switch-frame", Fhandle_switch_frame, @@ -1590,7 +1586,7 @@ necessarily represent user-visible input focus. */) kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); run_hook (Qmouse_leave_buffer_hook); - return do_switch_frame (event, 0, 0, Qnil); + return do_switch_frame (event, 0, Qnil); } DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0, @@ -2105,7 +2101,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) Fraise_frame (frame1); #endif - do_switch_frame (frame1, 0, 1, Qnil); + do_switch_frame (frame1, 1, Qnil); sf = SELECTED_FRAME (); } else diff --git a/src/keyboard.c b/src/keyboard.c index a520e53397..7c13ac9611 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -11459,7 +11459,7 @@ quit_throw_to_read_char (bool from_signal) if (FRAMEP (internal_last_event_frame) && !EQ (internal_last_event_frame, selected_frame)) do_switch_frame (make_lispy_switch_frame (internal_last_event_frame), - 0, 0, Qnil); + 0, Qnil); sys_longjmp (getcjmp, 1); } diff --git a/src/lisp.h b/src/lisp.h index 35cc7f5a09..5ffc2bb038 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4842,7 +4842,7 @@ extern void syms_of_indent (void); /* Defined in frame.c. */ extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object); extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object); -extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object); +extern Lisp_Object do_switch_frame (Lisp_Object, int, Lisp_Object); extern Lisp_Object get_frame_param (struct frame *, Lisp_Object); extern void frames_discard_buffer (Lisp_Object); extern void init_frame_once (void); diff --git a/src/minibuf.c b/src/minibuf.c index c2e270a450..0fba334b22 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -1123,8 +1123,8 @@ read_minibuf_unwind (void) found: if (!EQ (exp_MB_frame, saved_selected_frame) && !NILP (exp_MB_frame)) - do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets - minibuf_window */ + do_switch_frame (exp_MB_frame, 0, Qt); /* This also sets + minibuf_window */ /* To keep things predictable, in case it matters, let's be in the minibuffer when we reset the relevant variables. Don't depend on @@ -1236,7 +1236,7 @@ read_minibuf_unwind (void) /* Restore the selected frame. */ if (!EQ (exp_MB_frame, saved_selected_frame) && !NILP (exp_MB_frame)) - do_switch_frame (saved_selected_frame, 0, 0, Qt); + do_switch_frame (saved_selected_frame, 0, Qt); } /* Replace the expired minibuffer in frame exp_MB_frame with the next less diff --git a/src/window.c b/src/window.c index af463b90ce..70438b70b8 100644 --- a/src/window.c +++ b/src/window.c @@ -7299,7 +7299,7 @@ the return value is nil. Otherwise the value is t. */) do_switch_frame (NILP (dont_set_frame) ? data->selected_frame : old_frame - , 0, 0, Qnil); + , 0, Qnil); } FRAME_WINDOW_CHANGE (f) = true; commit 3442de2edd8770bae8541257dc5a65fcb932d8da (refs/remotes/origin/emacs-28) Author: Stefan Kangas Date: Fri Jul 8 21:15:15 2022 +0200 Doc fix; don't mention obsolete variable * src/window.c (Fset_window_hscroll): Doc fix; don't mention obsolete variable. diff --git a/src/window.c b/src/window.c index cbb2a9e0e1..0cf6373e0b 100644 --- a/src/window.c +++ b/src/window.c @@ -1232,7 +1232,7 @@ WINDOW must be a live window and defaults to the selected one. Clip the number to a reasonable value if out of range. Return the new number. NCOL should be zero or positive. -Note that if `automatic-hscrolling' is non-nil, you cannot scroll the +Note that if `auto-hscroll-mode' is non-nil, you cannot scroll the window so that the location of point moves off-window. */) (Lisp_Object window, Lisp_Object ncol) { commit df157953612910e26cab7d1aa31b7ac5cd58d945 Author: Juri Linkov Date: Fri Jul 8 20:58:33 2022 +0300 * lisp/isearch.el (isearch-search-fun-in-noncontiguous-region): New function. (isearch-search-fun-in-text-property): Refactor body to 'search-within-boundaries', then call it (bug#14013). (search-within-boundaries): New function refactored from isearch-search-fun-in-text-property. * test/lisp/isearch-tests.el: Add tests for new search functions. (isearch--test-search-within-boundaries): New function. (isearch--test-search-fun-in-text-property) (isearch--test-search-fun-in-noncontiguous-region): New tests. diff --git a/lisp/isearch.el b/lisp/isearch.el index ad8897dda2..8f480a87d9 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -4489,89 +4489,117 @@ LAX-WHITESPACE: The value of `isearch-lax-whitespace' and (funcall after-change nil nil nil))))) +(defun isearch-search-fun-in-noncontiguous-region (search-fun bounds) + "Return the function that searches inside noncontiguous regions. +A noncontiguous region is defined by the argument BOUNDS that +is a list of cons cells of the form (START . END)." + (apply-partially + #'search-within-boundaries + search-fun + (lambda (pos) + (seq-some (lambda (b) (if isearch-forward + (and (>= pos (car b)) (< pos (cdr b))) + (and (> pos (car b)) (<= pos (cdr b))))) + bounds)) + (lambda (pos) + (let ((bounds (flatten-list bounds)) + found) + (unless isearch-forward + (setq bounds (nreverse bounds))) + (while (and bounds (not found)) + (if (if isearch-forward (< pos (car bounds)) (> pos (car bounds))) + (setq found (car bounds)) + (setq bounds (cdr bounds)))) + found)))) + (defun isearch-search-fun-in-text-property (search-fun property) "Return the function to search inside text that has the specified PROPERTY. The function will limit the search for matches only inside text which has this property in the current buffer. The argument SEARCH-FUN provides the function to search text, and defaults to the value of `isearch-search-fun-default' when nil." - (lambda (string &optional bound noerror count) - (let* ((old (point)) - ;; Check if point is already on the property. - (beg (when (get-text-property - (if isearch-forward old (max (1- old) (point-min))) - property) - old)) - end found (i 0) - (subregexp - (and isearch-regexp - (save-match-data - (catch 'subregexp - (while (string-match "\\^\\|\\$" string i) - (setq i (match-end 0)) - (when (subregexp-context-p string (match-beginning 0)) - ;; The ^/$ is not inside a char-range or escaped. - (throw 'subregexp t)))))))) - ;; Otherwise, try to search for the next property. - (unless beg - (setq beg (if isearch-forward - (next-single-property-change old property) - (previous-single-property-change old property))) - (when beg (goto-char beg))) - ;; Non-nil `beg' means there are more properties. - (while (and beg (not found)) - ;; Search for the end of the current property. - (setq end (if isearch-forward - (next-single-property-change beg property) - (previous-single-property-change beg property))) - ;; Handle ^/$ specially by matching in a temporary buffer. - (if subregexp - (let* ((prop-beg - (if (or (if isearch-forward (bobp) (eobp)) - (null (get-text-property - (+ (point) (if isearch-forward -1 0)) - property))) - ;; Already at the beginning of the field. - beg - ;; Get the real beginning of the field when - ;; the search was started in the middle. - (if isearch-forward - (previous-single-property-change beg property) - (next-single-property-change beg property)))) - (substring (buffer-substring prop-beg end)) - (offset (if isearch-forward prop-beg end)) - match-data) - (with-temp-buffer - (insert substring) - (goto-char (- beg offset -1)) - ;; Apply ^/$ regexp on the whole extracted substring. - (setq found (funcall - (or search-fun (isearch-search-fun-default)) - string (and bound (max (point-min) - (min (point-max) - (- bound offset -1)))) - noerror count)) - ;; Adjust match data as if it's matched in original buffer. - (when found - (setq found (+ found offset -1) - match-data (mapcar (lambda (m) (+ m offset -1)) - (match-data))))) - (when match-data (set-match-data match-data))) - (setq found (funcall - (or search-fun (isearch-search-fun-default)) - string (if bound (if isearch-forward - (min bound end) - (max bound end)) - end) - noerror count))) - ;; Get the next text property. - (unless found - (setq beg (if isearch-forward - (next-single-property-change end property) - (previous-single-property-change end property))) - (when beg (goto-char beg)))) - (unless found (goto-char old)) - found))) + (apply-partially + #'search-within-boundaries + search-fun + (lambda (pos) (get-text-property (if isearch-forward pos + (max (1- pos) (point-min))) + property)) + (lambda (pos) (if isearch-forward + (next-single-property-change pos property) + (previous-single-property-change pos property))))) + +(defun search-within-boundaries ( search-fun get-fun next-fun + string &optional bound noerror count) + (let* ((old (point)) + ;; Check if point is already on the property. + (beg (when (funcall get-fun old) old)) + end found (i 0) + (subregexp + (and isearch-regexp + (save-match-data + (catch 'subregexp + (while (string-match "\\^\\|\\$" string i) + (setq i (match-end 0)) + (when (subregexp-context-p string (match-beginning 0)) + ;; The ^/$ is not inside a char-range or escaped. + (throw 'subregexp t)))))))) + ;; Otherwise, try to search for the next property. + (unless beg + (setq beg (funcall next-fun old)) + (when beg (goto-char beg))) + ;; Non-nil `beg' means there are more properties. + (while (and beg (not found)) + ;; Search for the end of the current property. + (setq end (funcall next-fun beg)) + ;; Handle ^/$ specially by matching in a temporary buffer. + (if subregexp + (let* ((prop-beg + (if (or (if isearch-forward (bobp) (eobp)) + (null (funcall get-fun + (+ (point) + (if isearch-forward -1 1))))) + ;; Already at the beginning of the field. + beg + ;; Get the real beginning of the field when + ;; the search was started in the middle. + (let ((isearch-forward (not isearch-forward))) + ;; Search in the reverse direction. + (funcall next-fun beg)))) + (substring (buffer-substring prop-beg end)) + (offset (if isearch-forward prop-beg end)) + match-data) + (with-temp-buffer + (insert substring) + (goto-char (- beg offset -1)) + ;; Apply ^/$ regexp on the whole extracted substring. + (setq found (funcall + (or search-fun (isearch-search-fun-default)) + string (and bound (max (point-min) + (min (point-max) + (- bound offset -1)))) + noerror count)) + ;; Adjust match data as if it's matched in original buffer. + (when found + (setq found (+ found offset -1) + match-data (mapcar (lambda (m) (+ m offset -1)) + (match-data))))) + (when found (goto-char found)) + (when match-data (set-match-data + (mapcar (lambda (m) (copy-marker m)) + match-data)))) + (setq found (funcall + (or search-fun (isearch-search-fun-default)) + string (if bound (if isearch-forward + (min bound end) + (max bound end)) + end) + noerror count))) + ;; Get the next text property. + (unless found + (setq beg (funcall next-fun end)) + (when beg (goto-char beg)))) + (unless found (goto-char old)) + found)) (defun isearch-resume (string regexp word forward message case-fold) diff --git a/test/lisp/isearch-tests.el b/test/lisp/isearch-tests.el index 4600757d94..8cb5e5e454 100644 --- a/test/lisp/isearch-tests.el +++ b/test/lisp/isearch-tests.el @@ -38,5 +38,85 @@ ;; Bug #21091: let `isearch-done' work without `isearch-update'. (isearch-done)) + +;; Search functions. + +(defun isearch--test-search-within-boundaries (pairs) + (goto-char (point-min)) + (let ((isearch-forward t) + (isearch-regexp nil)) + (dolist (pos (append pairs nil)) + (should (eq (cdr pos) (isearch-search-string "foo" nil t))) + (should (equal (match-string 0) "foo")) + (when (car pos) (should (eq (car pos) (match-beginning 0)))))) + + (goto-char (point-max)) + (let ((isearch-forward nil) + (isearch-regexp nil)) + (dolist (pos (append (reverse pairs) nil)) + (should (eq (car pos) (isearch-search-string "foo" nil t))) + (should (equal (match-string 0) "foo")) + (when (cdr pos) (should (eq (cdr pos) (match-end 0)))))) + + (goto-char (point-min)) + (let ((isearch-forward t) + (isearch-regexp t)) + (dolist (pos (append pairs nil)) + (should (eq (cdr pos) (isearch-search-string ".*" nil t))) + (should (equal (match-string 0) "foo")) + (when (car pos) (should (eq (car pos) (match-beginning 0)))))) + + (goto-char (point-min)) + (let ((isearch-forward t) + (isearch-regexp t)) + (dolist (pos (append pairs nil)) + (should (eq (cdr pos) (isearch-search-string "^.*" nil t))) + (should (equal (match-string 0) "foo")) + (when (car pos) (should (eq (car pos) (match-beginning 0)))))) + + (goto-char (point-min)) + (let ((isearch-forward t) + (isearch-regexp t)) + (dolist (pos (append pairs nil)) + (should (eq (cdr pos) (isearch-search-string ".*$" nil t))) + (should (equal (match-string 0) "foo")) + (when (car pos) (should (eq (car pos) (match-beginning 0)))))) + + (goto-char (point-max)) + (let ((isearch-forward nil) + (isearch-regexp t)) + (dolist (pos (append (reverse pairs) nil)) + (should (eq (car pos) (isearch-search-string "^.*" nil t))) + (should (equal (match-string 0) "foo")) + (when (cdr pos) (should (eq (cdr pos) (match-end 0)))))) + + (goto-char (point-max)) + (let ((isearch-forward nil) + (isearch-regexp t)) + (dolist (pos (append (reverse pairs) nil)) + (should (eq (car pos) (isearch-search-string "foo$" nil t))) + (should (equal (match-string 0) "foo")) + (when (cdr pos) (should (eq (cdr pos) (match-end 0))))))) + +(ert-deftest isearch--test-search-fun-in-text-property () + (let* ((pairs '((4 . 7) (11 . 14) (21 . 24))) + (isearch-search-fun-function + (lambda () (isearch-search-fun-in-text-property nil 'dired-filename)))) + (with-temp-buffer + (insert "foo" (propertize "foo" 'dired-filename t) "foo\n") + (insert (propertize "foo" 'dired-filename t) "foo\n") + (insert "foo" (propertize "foo" 'dired-filename t) "\n") + (isearch--test-search-within-boundaries pairs)))) + +(ert-deftest isearch--test-search-fun-in-noncontiguous-region () + (let* ((pairs '((4 . 7) (11 . 14) (21 . 24))) + (isearch-search-fun-function + (lambda () (isearch-search-fun-in-noncontiguous-region nil pairs)))) + (with-temp-buffer + (insert "foofoofoo\n") + (insert "foofoo\n") + (insert "foofoo\n") + (isearch--test-search-within-boundaries pairs)))) + (provide 'isearch-tests) ;;; isearch-tests.el ends here commit 3cfac1fe073815bdbba96e3a35a1c15626022c07 Author: Juri Linkov Date: Fri Jul 8 20:47:11 2022 +0300 Display the number of invisible matches for isearch-lazy-count (bug#40808) * lisp/isearch.el (lazy-count-invisible-format): New variable. (isearch-mode): Set isearch-lazy-count-invisible to nil. (isearch-lazy-count-format): Use lazy-count-invisible-format and isearch-lazy-count-invisible. (isearch-range-invisible): Handle the value 'can-be-opened' of 'search-invisible' and don't open overlays for it, just check if these overlays can be opened. (isearch-lazy-count-invisible): New variable. (isearch-lazy-highlight-new-loop): Set isearch-lazy-count-invisible to nil. (isearch-lazy-highlight-search): Let-bind search-invisible either to t for non-nil isearch-lazy-count, or to 'can-be-opened'. (isearch-lazy-highlight-match): Don't highlight matches intended to be counted only, not highlighted. (isearch-lazy-highlight-buffer-update): Separately count invisible matches by isearch-lazy-count-invisible. * lisp/info.el (Info-isearch-filter): Check if search-invisible is t. diff --git a/lisp/info.el b/lisp/info.el index 906385fdc7..0d0dda8c06 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -2208,7 +2208,7 @@ and is not in the header line or a tag table." (let ((backward (< found beg-found))) (not (or - (and (not search-invisible) + (and (not (eq search-invisible t)) (if backward (or (text-property-not-all found beg-found 'invisible nil) (text-property-not-all found beg-found 'display nil)) diff --git a/lisp/isearch.el b/lisp/isearch.el index db7b53c014..ad8897dda2 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -466,6 +466,12 @@ and doesn't remove full-buffer highlighting after a search." :group 'lazy-count :version "27.1") +(defvar lazy-count-invisible-format " (invisible %s)" + "Format of the number of invisible matches for the prompt. +When invisible matches exist, their number is appended +after the total number of matches. Display nothing when +this variable is nil.") + ;; Define isearch help map. @@ -1277,6 +1283,7 @@ used to set the value of `isearch-regexp-function'." isearch-lazy-count-current nil isearch-lazy-count-total nil + isearch-lazy-count-invisible nil ;; Save the original value of `minibuffer-message-timeout', and ;; set it to nil so that isearch's messages don't get timed out. @@ -3529,7 +3536,12 @@ isearch-message-suffix prompt. Otherwise, for isearch-message-prefix." (- isearch-lazy-count-total isearch-lazy-count-current -1))) - (or isearch-lazy-count-total "?")) + (if (and isearch-lazy-count-invisible + lazy-count-invisible-format) + (concat (format "%s" (or isearch-lazy-count-total "?")) + (format lazy-count-invisible-format + isearch-lazy-count-invisible)) + (or isearch-lazy-count-total "?"))) ""))) @@ -3780,10 +3792,11 @@ Optional third argument, if t, means if fail just return nil (no error). (save-excursion (goto-char beg) (let (;; can-be-opened keeps track if we can open some overlays. - (can-be-opened (eq search-invisible 'open)) + (can-be-opened (memq search-invisible '(open can-be-opened))) ;; the list of overlays that could be opened (crt-overlays nil)) - (when (and can-be-opened isearch-hide-immediately) + (when (and can-be-opened isearch-hide-immediately + (not (eq search-invisible 'can-be-opened))) (isearch-close-unnecessary-overlays beg end)) ;; If the following character is currently invisible, ;; skip all characters with that same `invisible' property value. @@ -3822,9 +3835,10 @@ Optional third argument, if t, means if fail just return nil (no error). (if (>= (point) end) (if (and can-be-opened (consp crt-overlays)) (progn - (setq isearch-opened-overlays - (append isearch-opened-overlays crt-overlays)) - (mapc 'isearch-open-overlay-temporary crt-overlays) + (unless (eq search-invisible 'can-be-opened) + (setq isearch-opened-overlays + (append isearch-opened-overlays crt-overlays)) + (mapc 'isearch-open-overlay-temporary crt-overlays)) nil) (setq isearch-hidden t))))))) @@ -4008,6 +4022,7 @@ since they have special meaning in a regexp." (defvar isearch-lazy-highlight-error nil) (defvar isearch-lazy-count-current nil) (defvar isearch-lazy-count-total nil) +(defvar isearch-lazy-count-invisible nil) (defvar isearch-lazy-count-hash (make-hash-table)) (defvar lazy-count-update-hook nil "Hook run after new lazy count results are computed.") @@ -4086,7 +4101,8 @@ by other Emacs features." ;; Reset old counter before going to count new numbers (clrhash isearch-lazy-count-hash) (setq isearch-lazy-count-current nil - isearch-lazy-count-total nil) + isearch-lazy-count-total nil + isearch-lazy-count-invisible nil) ;; Delay updating the message if possible, to avoid flicker (when (string-equal isearch-string "") (when (and isearch-mode (null isearch-message-function)) @@ -4166,10 +4182,10 @@ Attempt to do the search exactly the way the pending Isearch would." (isearch-regexp-lax-whitespace isearch-lazy-highlight-regexp-lax-whitespace) (isearch-forward isearch-lazy-highlight-forward) - ;; Don't match invisible text unless it can be opened - ;; or when counting matches and user can visit hidden matches - (search-invisible (or (eq search-invisible 'open) - (and isearch-lazy-count search-invisible))) + ;; Count all invisible matches, but highlight only + ;; matches that can be opened by visiting them later + (search-invisible (or (not (null isearch-lazy-count)) + 'can-be-opened)) (retry t) (success nil)) ;; Use a loop like in `isearch-search'. @@ -4186,15 +4202,20 @@ Attempt to do the search exactly the way the pending Isearch would." (error nil))) (defun isearch-lazy-highlight-match (mb me) - (let ((ov (make-overlay mb me))) - (push ov isearch-lazy-highlight-overlays) - ;; 1000 is higher than ediff's 100+, - ;; but lower than isearch main overlay's 1001 - (overlay-put ov 'priority 1000) - (overlay-put ov 'face 'lazy-highlight) - (unless (or (eq isearch-lazy-highlight 'all-windows) - isearch-lazy-highlight-buffer) - (overlay-put ov 'window (selected-window))))) + (when (or (not isearch-lazy-count) + ;; Recheck the match that possibly was intended + ;; for counting only, but not for highlighting + (let ((search-invisible 'can-be-opened)) + (funcall isearch-filter-predicate mb me))) + (let ((ov (make-overlay mb me))) + (push ov isearch-lazy-highlight-overlays) + ;; 1000 is higher than ediff's 100+, + ;; but lower than isearch main overlay's 1001 + (overlay-put ov 'priority 1000) + (overlay-put ov 'face 'lazy-highlight) + (unless (or (eq isearch-lazy-highlight 'all-windows) + isearch-lazy-highlight-buffer) + (overlay-put ov 'window (selected-window)))))) (defun isearch-lazy-highlight-start () "Start a new lazy-highlight updating loop." @@ -4328,11 +4349,22 @@ Attempt to do the search exactly the way the pending Isearch would." (setq found nil) (forward-char -1))) (when isearch-lazy-count - (setq isearch-lazy-count-total - (1+ (or isearch-lazy-count-total 0))) - (puthash (if isearch-lazy-highlight-forward me mb) - isearch-lazy-count-total - isearch-lazy-count-hash)) + ;; Count as invisible when can't open overlay, + ;; but don't leave search-invisible with the + ;; value `open' since then lazy-highlight + ;; will open all overlays with matches. + (if (not (let ((search-invisible + (if (eq search-invisible 'open) + 'can-be-opened + search-invisible))) + (funcall isearch-filter-predicate mb me))) + (setq isearch-lazy-count-invisible + (1+ (or isearch-lazy-count-invisible 0))) + (setq isearch-lazy-count-total + (1+ (or isearch-lazy-count-total 0))) + (puthash (if isearch-lazy-highlight-forward me mb) + isearch-lazy-count-total + isearch-lazy-count-hash))) ;; Don't highlight the match when this loop is used ;; only to count matches or when matches were already ;; highlighted within the current window boundaries commit ef559dcd2ab3ec6e1f714180cbdf3b4e0965c13d Author: Stefan Kangas Date: Fri Jul 8 19:00:32 2022 +0200 Don't mention moved variable in dired-x manual * doc/misc/dired-x.texi (Technical Details): Remove mention of 'dired-clean-up-buffers-too'; it has been moved to dired.el. diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi index e3a2832cb0..0e8f969b29 100644 --- a/doc/misc/dired-x.texi +++ b/doc/misc/dired-x.texi @@ -165,10 +165,8 @@ When @file{dired-x.el} is loaded, some standard Dired functions from Dired}), if it is active. @code{dired-find-buffer-nocreate} and @code{dired-initial-position} respect the value of @code{dired-find-subdir} (@pxref{Miscellaneous Commands}). -@code{dired-clean-up-after-deletion} respects the value of -@code{dired-clean-up-buffers-too}. @code{dired-read-shell-command} uses -@code{dired-guess-shell-command} (@pxref{Shell Command Guessing}) to -offer a smarter default command. +@code{dired-read-shell-command} uses @code{dired-guess-shell-command} +(@pxref{Shell Command Guessing}) to offer a smarter default command. @node Installation @chapter Installation commit fc50847b406481485f87a49aa58bb81ef6893e52 Author: Stefan Kangas Date: Fri Jul 8 18:50:47 2022 +0200 Delete redundant defgroup dired-keys * lisp/dired-x.el (dired-keys): Delete defgroup. (dired-bind-vm): Move to :group dired-x. diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 08daef71c6..796625058b 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -50,11 +50,6 @@ "Extended directory editing (dired-x)." :group 'dired) -(defgroup dired-keys nil - "Dired keys customizations." - :prefix "dired-" - :group 'dired-x) - (defcustom dired-bind-vm nil "Non-nil means \"V\" runs `dired-vm', otherwise \"V\" runs `dired-rmail'. RMAIL files in the old Babyl format (used before Emacs 23.1) @@ -62,7 +57,7 @@ contain \"-*- rmail -*-\" at the top, so `dired-find-file' will run `rmail' on these files. New RMAIL files use the standard mbox format, and so cannot be distinguished in this way." :type 'boolean - :group 'dired-keys) + :group 'dired-x) (defvar dired-bind-jump t) (make-obsolete-variable 'dired-bind-jump "not used." "28.1") commit 99c96f50ed2058bec44612134ccaf9aa51c9730e Author: Stefan Kangas Date: Fri Jul 8 18:31:17 2022 +0200 Move dired-do-relsymlink from dired-x.el to dired.el * lisp/dired-x.el (dired-do-relsymlink, dired-make-relative-symlink) (dired-do-relsymlink-regexp): Move from here... * lisp/dired-aux.el (dired-do-relsymlink, dired-make-relative-symlink) (dired-do-relsymlink-regexp): ...to here. (Bug#21981) * lisp/dired-x.el: Move keybinding and menu binding from here... * lisp/dired.el (dired-mode-map, dired-mode-regexp-menu): ...to here. * lisp/dired-x.el (dired-keep-marker-relsymlink): Move from here... * lisp/dired.el (dired-keep-marker-relsymlink): ...to here. Improve docstring. * doc/misc/dired-x.texi (Miscellaneous Commands): Move documentation of above commands from here... * doc/emacs/dired.texi (Operating on Files) (Transforming File Names): ...to here. diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index c7ef097bfb..69450c82d6 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -844,6 +844,26 @@ This is like @samp{ln -s}. The argument @var{new} is the directory to make the links in, or (if making just one link) the name to give the link. +@findex dired-do-relsymlink +@kindex Y @r{(Dired)} +@item Y @var{new} @key{RET} +Make relative symbolic links to the specified files +(@code{dired-do-relsymlink}). The argument @var{new} is the directory +to make the links in, or (if making just one link) the name to give +the link. This is like @code{dired-do-symlink} but creates relative +symbolic links. For example: + +@example + foo -> ../bar/foo +@end example + +@noindent +It does not create absolute ones like: + +@example + foo -> /path/that/may/change/any/day/bar/foo +@end example + @findex dired-do-chmod @kindex M @r{(Dired)} @cindex changing file permissions (in Dired) @@ -1150,9 +1170,12 @@ Rename each of the selected files to a lower-case name @itemx % S @var{from} @key{RET} @var{to} @key{RET} @kindex % S @r{(Dired)} @findex dired-do-symlink-regexp -These four commands rename, copy, make hard links and make soft links, -in each case computing the new name by regular-expression substitution -from the name of the old file. +@itemx % Y @var{from} @key{RET} @var{to} @key{RET} +@kindex % Y @r{(Dired)} +@findex dired-do-relsymlink-regexp +These five commands rename, copy, make hard links, make soft links, +and make relative soft links, in each case computing the new name by +regular-expression substitution from the name of the old file. @end table The four regular-expression substitution commands effectively diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi index 504060f41f..e3a2832cb0 100644 --- a/doc/misc/dired-x.texi +++ b/doc/misc/dired-x.texi @@ -920,33 +920,6 @@ to @kbd{V}. Otherwise, @code{dired-bind-rmail} will be bound. @findex dired-rmail Bound to @kbd{V} if @code{dired-bind-vm} is @code{nil}. Run Rmail on this file (assumed to be mail folder in Rmail format). - -@item dired-do-relsymlink -@cindex relative symbolic links. -@kindex Y -@findex dired-do-relsymlink -Bound to @kbd{Y}. Relative symlink all marked (or next ARG) files into a -directory, or make a relative symbolic link to the current file. This creates -relative symbolic links like - -@example - foo -> ../bar/foo -@end example - -@noindent -not absolute ones like - -@example - foo -> /ugly/path/that/may/change/any/day/bar/foo -@end example - -@item dired-do-relsymlink-regexp -@kindex %Y -@findex dired-do-relsymlink-regexp -Bound to @kbd{%Y}. Relative symlink all marked files containing -@var{regexp} to @var{newname}. See functions -@code{dired-do-rename-regexp} and @code{dired-do-relsymlink} for more -info. @end table @node Bugs diff --git a/etc/NEWS b/etc/NEWS index 1e6fb06bdc..925bd9a212 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1057,6 +1057,14 @@ customize the user option 'dired-clean-up-buffers-too' to nil. The related user option 'dired-clean-confirm-killing-deleted-buffers' (which see) has also been moved to 'dired'. ++++ +*** 'dired-do-relsymlink' moved from dired-x to dired. +The corresponding key "Y" is now bound by default in Dired. + ++++ +*** 'dired-do-relsymlink-regexp' moved from dired-x to dired. +The corresponding key "% Y" is now bound by default in Dired. + +++ *** 'dired-info' and 'dired-man' moved from dired-x to dired. The 'dired-info' and 'dired-man' commands have been moved from the diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 5f2d1cfc9f..b9f33036e3 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -2521,6 +2521,73 @@ Also see `dired-do-revert-buffer'." (dired-do-create-files 'symlink #'make-symbolic-link "Symlink" arg dired-keep-marker-symlink)) +;;;###autoload +(defun dired-do-relsymlink (&optional arg) + "Relative symlink all marked (or next ARG) files into a directory. +Otherwise make a relative symbolic link to the current file. +This creates relative symbolic links like + + foo -> ../bar/foo + +not absolute ones like + + foo -> /ugly/file/name/that/may/change/any/day/bar/foo + +For absolute symlinks, use \\[dired-do-symlink]." + (interactive "P") + (dired-do-create-files 'relsymlink #'dired-make-relative-symlink + "RelSymLink" arg dired-keep-marker-relsymlink)) + +(defun dired-make-relative-symlink (file1 file2 &optional ok-if-already-exists) + "Make a symbolic link (pointing to FILE1) in FILE2. +The link is relative (if possible), for example + + \"/vol/tex/bin/foo\" \"/vol/local/bin/foo\" + +results in + + \"../../tex/bin/foo\" \"/vol/local/bin/foo\"" + (interactive "FRelSymLink: \nFRelSymLink %s: \np") + (let (name1 name2 len1 len2 (index 0) sub) + (setq file1 (expand-file-name file1) + file2 (expand-file-name file2) + len1 (length file1) + len2 (length file2)) + ;; Find common initial file name components: + (let (next) + (while (and (setq next (string-search "/" file1 index)) + (< (setq next (1+ next)) (min len1 len2)) + ;; For the comparison, both substrings must end in + ;; `/', so NEXT is *one plus* the result of the + ;; string-search. + ;; E.g., consider the case of linking "/tmp/a/abc" + ;; to "/tmp/abc" erroneously giving "/tmp/a" instead + ;; of "/tmp/" as common initial component + (string-equal (substring file1 0 next) + (substring file2 0 next))) + (setq index next)) + (setq name2 file2 + sub (substring file1 0 index) + name1 (substring file1 index))) + (if (string-equal sub "/") + ;; No common initial file name found + (setq name1 file1) + ;; Else they have a common parent directory + (let ((tem (substring file2 index)) + (start 0) + (count 0)) + ;; Count number of slashes we must compensate for ... + (while (setq start (string-search "/" tem start)) + (setq count (1+ count) + start (1+ start))) + ;; ... and prepend a "../" for each slash found: + (dotimes (_ count) + (setq name1 (concat "../" name1))))) + (make-symbolic-link + (directory-file-name name1) ; must not link to foo/ + ; (trailing slash!) + name2 ok-if-already-exists))) + ;;;###autoload (defun dired-do-hardlink (&optional arg) "Add names (hard links) current file or all marked (or next ARG) files. @@ -2681,6 +2748,16 @@ See function `dired-do-rename-regexp' for more info." #'make-symbolic-link "SymLink" arg regexp newname whole-name dired-keep-marker-symlink)) +;;;###autoload +(defun dired-do-relsymlink-regexp (regexp newname &optional arg whole-name) + "RelSymlink all marked files containing REGEXP to NEWNAME. +See functions `dired-do-rename-regexp' and `dired-do-relsymlink' +for more info." + (interactive (dired-mark-read-regexp "RelSymLink")) + (dired-do-create-files-regexp + #'dired-make-relative-symlink + "RelSymLink" arg regexp newname whole-name dired-keep-marker-relsymlink)) + ;;; Change case of file names diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 1e1bf9efd6..08daef71c6 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -238,15 +238,11 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used." (define-key dired-mode-map "*O" 'dired-mark-omitted) (define-key dired-mode-map "*." 'dired-mark-extension)) -(when (keymapp (lookup-key dired-mode-map "%")) - (define-key dired-mode-map "%Y" 'dired-do-relsymlink-regexp)) - (define-key dired-mode-map "\C-x\M-o" 'dired-omit-mode) (define-key dired-mode-map "\M-(" 'dired-mark-sexp) (define-key dired-mode-map "\M-!" 'dired-smart-shell-command) (define-key dired-mode-map "\M-G" 'dired-goto-subdir) (define-key dired-mode-map "F" 'dired-do-find-marked-files) -(define-key dired-mode-map "Y" 'dired-do-relsymlink) (define-key dired-mode-map "V" 'dired-do-run-mail) @@ -257,12 +253,6 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used." ["Find Files" dired-do-find-marked-files :help "Find current or marked files"] "Shell Command...") - (easy-menu-add-item menu '("Operate") - ["Relative Symlink to..." dired-do-relsymlink - :visible (fboundp 'make-symbolic-link) - :help "Make relative symbolic links for current or \ -marked files"] - "Hardlink to...") (easy-menu-add-item menu '("Mark") ["Flag Extension..." dired-flag-extension :help "Flag files with a certain extension for deletion"] @@ -276,12 +266,6 @@ marked files"] :help "Mark files matching `dired-omit-files' \ and `dired-omit-extensions'"] "Unmark All") - (easy-menu-add-item menu '("Regexp") - ["Relative Symlink..." dired-do-relsymlink-regexp - :visible (fboundp 'make-symbolic-link) - :help "Make relative symbolic links for files \ -matching regexp"] - "Hardlink...") (easy-menu-add-item menu '("Immediate") ["Omit Mode" dired-omit-mode :style toggle :selected dired-omit-mode @@ -1044,95 +1028,6 @@ See `dired-guess-shell-alist-user'." ;; If we got a return, then return default. (if (equal val "") default val)))) - -;;; Relative symbolic links - -(declare-function make-symbolic-link "fileio.c") - -(defvar dired-keep-marker-relsymlink ?S - "See variable `dired-keep-marker-move'.") - -(defun dired-make-relative-symlink (file1 file2 &optional ok-if-already-exists) - "Make a symbolic link (pointing to FILE1) in FILE2. -The link is relative (if possible), for example - - \"/vol/tex/bin/foo\" \"/vol/local/bin/foo\" - -results in - - \"../../tex/bin/foo\" \"/vol/local/bin/foo\"" - (interactive "FRelSymLink: \nFRelSymLink %s: \np") - (let (name1 name2 len1 len2 (index 0) sub) - (setq file1 (expand-file-name file1) - file2 (expand-file-name file2) - len1 (length file1) - len2 (length file2)) - ;; Find common initial file name components: - (let (next) - (while (and (setq next (string-search "/" file1 index)) - (< (setq next (1+ next)) (min len1 len2)) - ;; For the comparison, both substrings must end in - ;; `/', so NEXT is *one plus* the result of the - ;; string-search. - ;; E.g., consider the case of linking "/tmp/a/abc" - ;; to "/tmp/abc" erroneously giving "/tmp/a" instead - ;; of "/tmp/" as common initial component - (string-equal (substring file1 0 next) - (substring file2 0 next))) - (setq index next)) - (setq name2 file2 - sub (substring file1 0 index) - name1 (substring file1 index))) - (if (string-equal sub "/") - ;; No common initial file name found - (setq name1 file1) - ;; Else they have a common parent directory - (let ((tem (substring file2 index)) - (start 0) - (count 0)) - ;; Count number of slashes we must compensate for ... - (while (setq start (string-search "/" tem start)) - (setq count (1+ count) - start (1+ start))) - ;; ... and prepend a "../" for each slash found: - (dotimes (_ count) - (setq name1 (concat "../" name1))))) - (make-symbolic-link - (directory-file-name name1) ; must not link to foo/ - ; (trailing slash!) - name2 ok-if-already-exists))) - -(autoload 'dired-do-create-files "dired-aux") - -;;;###autoload -(defun dired-do-relsymlink (&optional arg) - "Relative symlink all marked (or next ARG) files into a directory. -Otherwise make a relative symbolic link to the current file. -This creates relative symbolic links like - - foo -> ../bar/foo - -not absolute ones like - - foo -> /ugly/file/name/that/may/change/any/day/bar/foo - -For absolute symlinks, use \\[dired-do-symlink]." - (interactive "P") - (dired-do-create-files 'relsymlink #'dired-make-relative-symlink - "RelSymLink" arg dired-keep-marker-relsymlink)) - -(autoload 'dired-mark-read-regexp "dired-aux") -(autoload 'dired-do-create-files-regexp "dired-aux") - -(defun dired-do-relsymlink-regexp (regexp newname &optional arg whole-name) - "RelSymlink all marked files containing REGEXP to NEWNAME. -See functions `dired-do-rename-regexp' and `dired-do-relsymlink' -for more info." - (interactive (dired-mark-read-regexp "RelSymLink")) - (dired-do-create-files-regexp - #'dired-make-relative-symlink - "RelSymLink" arg regexp newname whole-name dired-keep-marker-relsymlink)) - ;;; Visit all marked files simultaneously diff --git a/lisp/dired.el b/lisp/dired.el index 48dffa0e36..5769b73f63 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -210,6 +210,11 @@ If a character, new links are unconditionally marked with that character." (character :tag "Mark")) :group 'dired-mark) +(defvar dired-keep-marker-relsymlink ?S + "Controls marking of newly made relative symbolic links. +If t, they are marked if and as the files linked to were marked. +If a character, new links are unconditionally marked with that character.") + (defcustom dired-free-space 'first "Whether and how to display the amount of free disk space in Dired buffers. If nil, don't display. @@ -2090,6 +2095,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." "S" #'dired-do-symlink "T" #'dired-do-touch "X" #'dired-do-shell-command + "Y" #'dired-do-relsymlink "Z" #'dired-do-compress "c" #'dired-do-compress-to "!" #'dired-do-shell-command @@ -2119,6 +2125,7 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." "% H" #'dired-do-hardlink-regexp "% R" #'dired-do-rename-regexp "% S" #'dired-do-symlink-regexp + "% Y" #'dired-do-relsymlink-regexp "% &" #'dired-flag-garbage-files ;; Commands for marking and unmarking. "* *" #'dired-mark-executables @@ -2296,6 +2303,9 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." ["Symlink..." dired-do-symlink-regexp :visible (fboundp 'make-symbolic-link) :help "Make symbolic links for files matching regexp"] + ["Relative Symlink..." dired-do-relsymlink-regexp + :visible (fboundp 'make-symbolic-link) + :help "Make relative symbolic links for files matching regexp"] ["Hardlink..." dired-do-hardlink-regexp :help "Make hard links for files matching regexp"] ["Upcase" dired-upcase @@ -2365,6 +2375,9 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." ["Symlink to..." dired-do-symlink :visible (fboundp 'make-symbolic-link) :help "Make symbolic links for current or marked files"] + ["Relative Symlink to..." dired-do-relsymlink + :visible (fboundp 'make-symbolic-link) + :help "Make relative symbolic links for current or marked files"] ["Hardlink to..." dired-do-hardlink :help "Make hard links for current or marked files"] ["Print..." dired-do-print commit 033d370a5140aaba79cbac37399a387390d4c18e Author: Juri Linkov Date: Fri Jul 8 20:17:29 2022 +0300 * lisp/progmodes/ruby-mode.el (ruby-mode): Set outline-regexp, outline-level. Suggested by Yilkal Argaw . diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index a197724634..87bb92908d 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -2457,6 +2457,13 @@ If there is no Rubocop config file, Rubocop will be passed a flag (setq-local beginning-of-defun-function #'ruby-beginning-of-defun) (setq-local end-of-defun-function #'ruby-end-of-defun) + ;; `outline-regexp' contains the first part of `ruby-indent-beg-re' + (setq-local outline-regexp (concat "^\\s *" + (regexp-opt '("class" "module" "def")) + "\\_>")) + (setq-local outline-level (lambda () (1+ (/ (current-indentation) + ruby-indent-level)))) + (add-hook 'after-save-hook #'ruby-mode-set-encoding nil 'local) (add-hook 'electric-indent-functions #'ruby--electric-indent-p nil 'local) (add-hook 'flymake-diagnostic-functions #'ruby-flymake-auto nil 'local) commit 1c300c983f60a15413cfd0b31abb7d8294a1a5cc Author: Mattias Engdegård Date: Fri Jul 8 18:24:26 2022 +0200 Remove unused member of internal struct * src/fns.c (struct textprop_rec, concat_to_string): Remove `from`. diff --git a/src/fns.c b/src/fns.c index f4ba67b40e..49d76a0e7c 100644 --- a/src/fns.c +++ b/src/fns.c @@ -712,7 +712,6 @@ the same empty object instead of its copy. */) struct textprop_rec { ptrdiff_t argnum; /* refer to ARGS (arguments of `concat') */ - ptrdiff_t from; /* refer to ARGS[argnum] (argument string) */ ptrdiff_t to; /* refer to VAL (the target string) */ }; @@ -843,7 +842,6 @@ concat_to_string (ptrdiff_t nargs, Lisp_Object *args) if (string_intervals (arg)) { textprops[num_textprops].argnum = i; - textprops[num_textprops].from = 0; textprops[num_textprops].to = toindex; num_textprops++; } commit 58790a5266c60a935e6f6f1c3bda7c8fc7b72a6d Author: Stefan Kangas Date: Fri Jul 8 16:13:56 2022 +0200 * lisp/dired.el (dired-jump-map): Bind also "j" to dired-jump. diff --git a/lisp/dired.el b/lisp/dired.el index 3eff218728..48dffa0e36 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -4807,6 +4807,7 @@ Interactively with prefix argument, read FILE-NAME." (defvar-keymap dired-jump-map :doc "Keymap to repeat `dired-jump'. Used in `repeat-mode'." + "j" #'dired-jump "C-j" #'dired-jump) (put 'dired-jump 'repeat-map 'dired-jump-map) commit 9e0f52b7d941d55b658d39d452d84652026bdb84 Author: Po Lu Date: Fri Jul 8 21:16:15 2022 +0800 Ensure correct position is returned after child frame movement * src/xterm.c (x_set_offset): Synchronize child frame movement correctly. diff --git a/src/xterm.c b/src/xterm.c index 9651c4e119..23a784ade8 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -24067,6 +24067,11 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) && FRAME_X_OUTPUT (f)->move_offset_top == 0)))) x_check_expected_move (f, modified_left, modified_top); } + /* Instead, just wait for the last ConfigureWindow request to + complete. No window manager is involved when moving child + frames. */ + else + XSync (FRAME_X_DISPLAY (f), False); unblock_input (); } @@ -24769,7 +24774,6 @@ x_sync_with_move (struct frame *f, int left, int top, bool fuzzy) wait_reading_process_output (0, 500000000, 0, false, Qnil, NULL, 0); } - /* Wait for an event on frame F matching EVENTTYPE. */ void x_wait_for_event (struct frame *f, int eventtype) commit 6791165b2a0e707f719efec08aad62cdf6ed8ad3 Author: Mattias Engdegård Date: Fri Jul 8 15:09:16 2022 +0200 Fix file-name-case-insensitive-p in ffap (bug#56443) Don't crash if the file name argument to file-name-case-insensitive-p, after expansion, doesn't have a parent directory. This occurs when calling ffap on something that looks like an email address. * src/fileio.c (Ffile_name_case_insensitive_p): Return nil if no file or parent directory could be found. * test/src/fileio-tests.el (fileio-tests--identity-expand-handler) (fileio--file-name-case-insensitive-p): New test. diff --git a/src/fileio.c b/src/fileio.c index d07e62a121..9697f6c8cf 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -2601,9 +2601,9 @@ is case-insensitive. */) if (err <= 0) return err < 0 ? Qt : Qnil; Lisp_Object parent = file_name_directory (filename); - /* Avoid infinite loop if the root has trouble - (impossible?). */ - if (!NILP (Fstring_equal (parent, filename))) + /* Avoid infinite loop if the root has trouble (if that's even possible). + Without a parent, we just don't know and return nil as well. */ + if (!STRINGP (parent) || !NILP (Fstring_equal (parent, filename))) return Qnil; filename = parent; } diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el index c137ce06f1..08582c8a86 100644 --- a/test/src/fileio-tests.el +++ b/test/src/fileio-tests.el @@ -201,4 +201,20 @@ Also check that an encoding error can appear in a symlink." (insert-file-contents "/dev/urandom" nil nil 10) (should (= (buffer-size) 10)))) +(defun fileio-tests--identity-expand-handler (_ file &rest _) + file) +(put 'fileio-tests--identity-expand-handler 'operations '(expand-file-name)) + +(ert-deftest fileio--file-name-case-insensitive-p () + ;; Check that we at least don't crash if given nonexisting files + ;; without a directory (bug#56443). + + ;; Use an identity file-name handler, as if called by `ffap'. + (let* ((file-name-handler-alist + '(("^mailto:" . fileio-tests--identity-expand-handler))) + (file "mailto:snowball@hell.com")) + ;; Check that `expand-file-name' is identity for this name. + (should (equal (expand-file-name file nil) file)) + (file-name-case-insensitive-p file))) + ;;; fileio-tests.el ends here commit 739e3dbe050468e1d9aa0a48bfc656ae20fd8f9d Author: Stefan Kangas Date: Fri Dec 3 23:17:04 2021 +0100 Remove many items obsolete since 24.1 * lisp/allout.el (allout-abbreviate-flattened-numbering) (allout-mode-deactivate-hook): * lisp/ansi-color.el (ansi-color-unfontify-region): * lisp/auth-source.el (auth-source-hide-passwords) (auth-source-user-or-password) (auth-source-forget-user-or-password): * lisp/cedet/data-debug.el (data-debug-map): * lisp/cedet/semantic/grammar.el (semantic-grammar-syntax-table) (semantic-grammar-map): * lisp/chistory.el (command-history-map): * lisp/comint.el (comint-dynamic-complete) (comint-dynamic-complete-as-filename) (comint-dynamic-simple-complete): * lisp/dired-x.el (read-filename-at-point) (dired-x-submit-report): * lisp/dos-fns.el (register-name-alist, make-register) (register-value, set-register-value, intdos, mode25, mode4350): * lisp/emacs-lisp/bytecomp.el (byte-compile-disable-print-circle): * lisp/emacs-lisp/chart.el (chart-map): * lisp/emacs-lisp/package.el (package-menu-view-commentary): * lisp/emacs-lock.el (toggle-emacs-lock, emacs-lock-from-exiting): * lisp/erc/erc.el (erc-complete-word): * lisp/eshell/em-cmpl.el (eshell-cmpl-suffix-list): * lisp/eshell/esh-util.el (eshell-for): * lisp/files.el (inhibit-first-line-modes-regexps) (inhibit-first-line-modes-suffixes): * lisp/gnus/gnus-msg.el (gnus-outgoing-message-group) (gnus-debug-files, gnus-debug-exclude-variables): * lisp/gnus/gnus-registry.el (gnus-registry-user-format-function-M): * lisp/gnus/gnus.el (gnus-local-domain, gnus-carpal): * lisp/gnus/nnimap.el (nnimap-split-rule): * lisp/iimage.el (turn-on-iimage-mode): * lisp/image.el (image-extension-data, image-library-alist): * lisp/mail/emacsbug.el (report-emacs-bug-pretest-address): * lisp/mail/mail-utils.el (rmail-dont-reply-to): * lisp/mail/mailalias.el (mail-complete-function) (mail-completion-at-point-function): * lisp/mail/rmail.el (rmail-dont-reply-to-names) (rmail-default-dont-reply-to-names): * lisp/mail/sendmail.el (mail-mailer-swallows-blank-line) (mail-sent-via): * lisp/menu-bar.el (menu-bar-kill-ring-save): * lisp/minibuffer.el (completion-annotate-function) (minibuffer-local-filename-must-match-map): * lisp/msb.el (msb-after-load-hooks): * lisp/obsolete/eieio-compat.el (eieio-defmethod) (eieio-defgeneric): * lisp/obsolete/info-edit.el (Info-edit-map): * lisp/obsolete/starttls.el (starttls-any-program-available): * lisp/progmodes/cfengine.el (cfengine-mode-abbrevs): * lisp/progmodes/cwarn.el (turn-on-cwarn-mode): * lisp/progmodes/make-mode.el (makefile-complete): * lisp/progmodes/meta-mode.el (meta-complete-symbol) (meta-mode-map): * lisp/progmodes/pascal.el (pascal-toggle-completions) (pascal-last-completions, pascal-show-completions): * lisp/progmodes/prolog.el (prolog-char-quote-workaround): * lisp/progmodes/which-func.el (which-func-mode): [FUNCTION] * lisp/simple.el (count-lines-region, minibuffer-completing-symbol): * lisp/speedbar.el (speedbar-syntax-table, speedbar-key-map): * lisp/strokes.el (strokes-report-bug): * lisp/subr.el (condition-case-no-debug): * lisp/term/ns-win.el (ns-alternatives-map) (ns-store-cut-buffer-internal): * lisp/term/w32-win.el (w32-default-color-map): * lisp/term/x-win.el (x-cut-buffer-or-selection-value): * lisp/textmodes/bibtex.el (bibtex-complete) (bibtex-entry-field-alist): * lisp/textmodes/reftex-index.el (reftex-index-map) (reftex-index-phrases-map): * lisp/textmodes/reftex-sel.el (reftex-select-label-map) (reftex-select-bib-map): * lisp/textmodes/reftex-toc.el (reftex-toc-map): * lisp/textmodes/rst.el (rst-block-face, rst-external-face) (rst-definition-face, rst-directive-face, rst-comment-face) (rst-emphasis1-face, rst-emphasis2-face, rst-literal-face) (rst-reference-face): * lisp/vc/vc-hooks.el (vc-toggle-read-only): * lisp/view.el (view-return-to-alist) (view-return-to-alist-update): Remove many functions and variables obsolete since 24.1. * lisp/textmodes/bibtex.el (bibtex-entry-alist): Don't use above removed variable 'bibtex-entry-field-alist'. * lisp/cedet/data-debug.el (data-debug-edebug-expr) (data-debug-eval-expression): * lisp/emacs-lisp/trace.el (trace--read-args): * lisp/files-x.el (read-file-local-variable-value): * lisp/simple.el (read--expression): Don't use above removed variable 'minibuffer-completing-symbol'. * lisp/textmodes/rst.el (rst-font-lock-keywords): Don't use above removed variables. * src/w32fns.c (Fw32_default_color_map): Delete obsolete function. (syms_of_w32fns): Delete defsubr for above defun. * src/keyboard.c (syms_of_keyboard) : Delete DEFVARs. : Delete DEFSYM. (syms_of_keyboard_for_pdumper): Adjust for above change. (command_loop_1): Don't run deferred-action-function hook. * lisp/subr.el (deferred-action-list, deferred-action-function): Delete obsoletion statements. * lisp/emacs-lisp/ert-x.el (ert-simulate-command): Don't run 'deferred-action-list' hook. * doc/lispref/hooks.texi (Standard Hooks): Delete 'deferred-action-function'. * lisp/emacs-lisp/lisp.el (field-complete): * lisp/eshell/em-cmpl.el (eshell-cmpl-initialize): * lisp/gnus/gnus-msg.el (gnus-inews-insert-gcc): * lisp/gnus/nnmail.el (nnmail-fancy-expiry-target): * lisp/mail/mail-utils.el (mail-dont-reply-to): * lisp/mail/sendmail.el (sendmail-send-it): * lisp/mail/smtpmail.el (smtpmail-send-it): * lisp/minibuffer.el (minibuffer-completion-help): * lisp/progmodes/python.el: Don't use above removed items. * lisp/emacs-lisp/eieio-core.el: * lisp/mail/mailalias.el (mail-complete-alist): Doc fixes; don't refer to above removed items. ; * etc/NEWS: List removed items. diff --git a/doc/lispref/hooks.texi b/doc/lispref/hooks.texi index 107d036202..59b7930732 100644 --- a/doc/lispref/hooks.texi +++ b/doc/lispref/hooks.texi @@ -290,7 +290,6 @@ auto-fill-function command-error-function compose-chars-after-function composition-function-table -deferred-action-function input-method-function load-read-function load-source-file-function diff --git a/etc/NEWS b/etc/NEWS index 226af8d7d6..1e6fb06bdc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2247,6 +2247,53 @@ Use 'exif-parse-file' and 'exif-field' instead. ** 'insert-directory' alternatives should not change the free disk space line. This change is now applied in 'dired-insert-directory'. +--- +** Some functions and variables obsolete since Emacs 24 have been removed: +'Info-edit-map', 'allout-abbreviate-flattened-numbering', +'allout-mode-deactivate-hook', 'ansi-color-unfontify-region', +'auth-source-forget-user-or-password', 'auth-source-hide-passwords', +'auth-source-user-or-password', 'bibtex-complete', +'bibtex-entry-field-alist', 'byte-compile-disable-print-circle', +'cfengine-mode-abbrevs', 'chart-map', 'comint-dynamic-complete', +'comint-dynamic-complete-as-filename', +'comint-dynamic-simple-complete', 'command-history-map', +'completion-annotate-function', 'condition-case-no-debug', +'count-lines-region', 'data-debug-map', 'deferred-action-list', +'deferred-action-function', 'dired-x-submit-report', +'eieio-defgeneric', 'eieio-defmethod', 'emacs-lock-from-exiting', +'erc-complete-word', 'eshell-cmpl-suffix-list', 'eshell-for', +'gnus-carpal', 'gnus-debug-exclude-variables', 'gnus-debug-files', +'gnus-local-domain', 'gnus-outgoing-message-group', +'gnus-registry-user-format-function-M', 'image-extension-data', +'image-library-alist', 'inhibit-first-line-modes-regexps', +'inhibit-first-line-modes-suffixes', 'intdos', +'mail-complete-function', 'mail-completion-at-point-function', +'mail-mailer-swallows-blank-line', 'mail-sent-via', 'make-register', +'makefile-complete', 'menu-bar-kill-ring-save', +'meta-complete-symbol', 'meta-mode-map', +'minibuffer-completing-symbol', +'minibuffer-local-filename-must-match-map', 'mode25', 'mode4350', +'msb-after-load-hooks', 'nnimap-split-rule', 'ns-alternatives-map', +'ns-store-cut-buffer-internal', 'package-menu-view-commentary', +'pascal-last-completions', 'pascal-show-completions', +'pascal-toggle-completions', 'prolog-char-quote-workaround', +'read-filename-at-point', 'reftex-index-map', +'reftex-index-phrases-map', 'reftex-select-bib-map', +'reftex-select-label-map', 'reftex-toc-map', 'register-name-alist', +'register-value', 'report-emacs-bug-pretest-address', +'rmail-default-dont-reply-to-names', 'rmail-dont-reply-to', +'rmail-dont-reply-to-names', 'rst-block-face', 'rst-comment-face', +'rst-definition-face', 'rst-directive-face', 'rst-emphasis1-face', +'rst-emphasis2-face', 'rst-external-face', 'rst-literal-face', +'rst-reference-face', 'semantic-grammar-map', +'semantic-grammar-syntax-table', 'set-register-value', +'speedbar-key-map', 'speedbar-syntax-table', +'starttls-any-program-available', 'strokes-report-bug', +'toggle-emacs-lock', 'turn-on-cwarn-mode', 'turn-on-iimage-mode', +'vc-toggle-read-only', 'view-return-to-alist', +'view-return-to-alist-update', 'w32-default-color-map' (function), +'which-func-mode' (function), 'x-cut-buffer-or-selection-value'. + --- ** Some functions and variables obsolete since Emacs 23 have been removed: 'find-emacs-lisp-shadows', 'newsticker-cache-filename', diff --git a/lisp/allout.el b/lisp/allout.el index de8ee85b39..e07bac4ef9 100644 --- a/lisp/allout.el +++ b/lisp/allout.el @@ -733,8 +733,6 @@ Set this var to the bullet you want to use for file cross-references." (put 'allout-presentation-padding 'safe-local-variable #'integerp) ;;;_ = allout-flattened-numbering-abbreviation -(define-obsolete-variable-alias 'allout-abbreviate-flattened-numbering - 'allout-flattened-numbering-abbreviation "24.1") (defcustom allout-flattened-numbering-abbreviation nil "If non-nil, `allout-flatten-exposed-to-buffer' abbreviates topic numbers to minimal amount with some context. Otherwise, entire @@ -1350,11 +1348,6 @@ their settings before `allout-mode' was started." ;;;_ = allout-mode-hook (defvar allout-mode-hook nil "Hook run when allout mode starts.") -;;;_ = allout-mode-deactivate-hook -(define-obsolete-variable-alias 'allout-mode-deactivate-hook - 'allout-mode-off-hook "24.1") -(defvar allout-mode-deactivate-hook nil - "Hook run when allout mode ends.") ;;;_ = allout-exposure-category (defvar allout-exposure-category nil "Symbol for use as allout invisible-text overlay category.") @@ -1779,7 +1772,6 @@ hooks, by which independent code can cooperate with allout without changes to the allout core. Here are key ones: `allout-mode-hook' -`allout-mode-deactivate-hook' (deprecated) `allout-mode-off-hook' `allout-exposure-change-functions' `allout-structure-added-functions' diff --git a/lisp/ansi-color.el b/lisp/ansi-color.el index d5db9ecfed..6f1c270c23 100644 --- a/lisp/ansi-color.el +++ b/lisp/ansi-color.el @@ -456,9 +456,6 @@ variable, and is meant to be used in `compilation-filter-hook'." (_ (ansi-color-apply-on-region compilation-filter-start (point)))))) -(define-obsolete-function-alias 'ansi-color-unfontify-region - 'font-lock-default-unfontify-region "24.1") - ;; Working with strings (defvar-local ansi-color-context nil "Context saved between two calls to `ansi-color-apply'. diff --git a/lisp/auth-source.el b/lisp/auth-source.el index fc62e36dfc..12da2c3d73 100644 --- a/lisp/auth-source.el +++ b/lisp/auth-source.el @@ -164,8 +164,6 @@ Overrides `password-cache-expiry' through a let-binding." (defvar auth-source-creation-prompts nil "Default prompts for token values. Usually let-bound.") -(make-obsolete 'auth-source-hide-passwords nil "24.1") - (defcustom auth-source-save-behavior 'ask "If set, auth-source will respect it for save behavior." :version "23.2" ;; No Gnus @@ -2325,89 +2323,6 @@ See `auth-source-search' for details on SPEC." (push item all))) (nreverse all))) -;;; older API - -;; (auth-source-user-or-password '("login" "password") "imap.myhost.com" t "tzz") - -;; deprecate the old interface -(make-obsolete 'auth-source-user-or-password - 'auth-source-search "24.1") -(make-obsolete 'auth-source-forget-user-or-password - 'auth-source-forget "24.1") - -(defun auth-source-user-or-password - (mode host port &optional username create-missing delete-existing) - "Find MODE (string or list of strings) matching HOST and PORT. - -DEPRECATED in favor of `auth-source-search'! - -USERNAME is optional and will be used as \"login\" in a search -across the Secret Service API (see secrets.el) if the resulting -items don't have a username. This means that if you search for -username \"joe\" and it matches an item but the item doesn't have -a :user attribute, the username \"joe\" will be returned. - -A non-nil DELETE-EXISTING means deleting any matching password -entry in the respective sources. This is useful only when -CREATE-MISSING is non-nil as well; the intended use case is to -remove wrong password entries. - -If no matching entry is found, and CREATE-MISSING is non-nil, -the password will be retrieved interactively, and it will be -stored in the password database which matches best (see -`auth-sources'). - -MODE can be \"login\" or \"password\"." - (auth-source-do-debug - "auth-source-user-or-password: DEPRECATED get %s for %s (%s) + user=%s" - mode host port username) - - (let* ((listy (listp mode)) - (mode (if listy mode (list mode))) - ;; (cname (if username - ;; (format "%s %s:%s %s" mode host port username) - ;; (format "%s %s:%s" mode host port))) - (search (list :host host :port port)) - (search (if username (append search (list :user username)) search)) - (search (if create-missing - (append search (list :create t)) - search)) - (search (if delete-existing - (append search (list :delete t)) - search)) - ;; (found (if (not delete-existing) - ;; (gethash cname auth-source-cache) - ;; (remhash cname auth-source-cache) - ;; nil))) - (found nil)) - (if found - (progn - (auth-source-do-debug - "auth-source-user-or-password: DEPRECATED cached %s=%s for %s (%s) + %s" - mode - ;; don't show the password - (if (and (member "password" mode) t) - "SECRET" - found) - host port username) - found) ; return the found data - ;; else, if not found, search with a max of 1 - (let ((choice (nth 0 (apply #'auth-source-search - (append '(:max 1) search))))) - (when choice - (dolist (m mode) - (cond - ((equal "password" m) - (push (if (plist-get choice :secret) - (funcall (plist-get choice :secret)) - nil) found)) - ((equal "login" m) - (push (plist-get choice :user) found))))) - (setq found (nreverse found)) - (setq found (if listy found (car-safe found))))) - - found)) - (defun auth-source-user-and-password (host &optional user) (let* ((auth-info (car (if user diff --git a/lisp/cedet/data-debug.el b/lisp/cedet/data-debug.el index 0edc853edd..e7635c0aec 100644 --- a/lisp/cedet/data-debug.el +++ b/lisp/cedet/data-debug.el @@ -854,7 +854,6 @@ If PARENT is non-nil, it is somehow related as a parent to thing." table) "Syntax table used in data-debug macro buffers.") -(define-obsolete-variable-alias 'data-debug-map 'data-debug-mode-map "24.1") (defvar data-debug-mode-map (let ((km (make-sparse-keymap))) (suppress-keymap km) @@ -1028,11 +1027,9 @@ Do nothing if already contracted." (defun data-debug-edebug-expr (expr) "Dump out the contents of some expression EXPR in edebug with ddebug." (interactive - (list (let ((minibuffer-completing-symbol t)) - (read-from-minibuffer "Eval: " - nil read-expression-map t - 'read-expression-history)) - )) + (list (read-from-minibuffer "Eval: " + nil read-expression-map t + 'read-expression-history))) (let ((v (eval expr t))) (if (not v) (message "Expression %s is nil." expr) @@ -1043,10 +1040,9 @@ Do nothing if already contracted." If the result is something simple, show it in the echo area. If the result is a list or vector, then use the data debugger to display it." (interactive - (list (let ((minibuffer-completing-symbol t)) - (read-from-minibuffer "Eval: " - nil read-expression-map t - 'read-expression-history)))) + (list (read-from-minibuffer "Eval: " + nil read-expression-map t + 'read-expression-history))) (let (result) (if (null eval-expression-debug-on-error) diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el index 74d4a229fa..97456265ea 100644 --- a/lisp/cedet/semantic/grammar.el +++ b/lisp/cedet/semantic/grammar.el @@ -1123,8 +1123,6 @@ END is the limit of the search." ;;;; Define major mode ;;;; -(define-obsolete-variable-alias 'semantic-grammar-syntax-table - 'semantic-grammar-mode-syntax-table "24.1") (defvar semantic-grammar-mode-syntax-table (let ((table (make-syntax-table (standard-syntax-table)))) (modify-syntax-entry ?\: "." table) ;; COLON @@ -1197,8 +1195,6 @@ END is the limit of the search." semantic-grammar-mode-keywords-1 "Font Lock keywords used to highlight Semantic grammar buffers.") -(define-obsolete-variable-alias 'semantic-grammar-map - 'semantic-grammar-mode-map "24.1") (defvar semantic-grammar-mode-map (let ((km (make-sparse-keymap))) diff --git a/lisp/chistory.el b/lisp/chistory.el index 33b2142211..9dce60a19f 100644 --- a/lisp/chistory.el +++ b/lisp/chistory.el @@ -119,8 +119,6 @@ The buffer is left in Command History mode." (error "No command history") (command-history-mode))))) -(define-obsolete-variable-alias 'command-history-map - 'command-history-mode-map "24.1") (defvar command-history-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map (make-composed-keymap lisp-mode-shared-map diff --git a/lisp/comint.el b/lisp/comint.el index 7e22aa78fc..d52623c00a 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -3299,10 +3299,6 @@ Magic characters are those in `comint-file-name-quote-list'." (defun comint-completion-at-point () (run-hook-with-args-until-success 'comint-dynamic-complete-functions)) -(define-obsolete-function-alias - 'comint-dynamic-complete - 'completion-at-point "24.1") - (defun comint-dynamic-complete-filename () "Dynamically complete the filename at point. Completes if after a filename. @@ -3383,13 +3379,6 @@ See `completion-table-with-quoting' and `comint-unquote-function'.") (goto-char (match-end 0)) (insert filesuffix))))))))) -(defun comint-dynamic-complete-as-filename () - "Dynamically complete at point as a filename. -See `comint-dynamic-complete-filename'. Returns t if successful." - (declare (obsolete comint-filename-completion "24.1")) - (let ((data (comint--complete-file-name-data))) - (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data)))) - (defun comint-replace-by-expanded-filename () "Dynamically expand and complete the filename at point. Replace the filename with an expanded, canonicalized and @@ -3404,65 +3393,6 @@ filename absolute. For expansion see `expand-file-name' and (replace-match (expand-file-name filename) t t) (comint-dynamic-complete-filename)))) - -(defun comint-dynamic-simple-complete (stub candidates) - "Dynamically complete STUB from CANDIDATES list. -This function inserts completion characters at point by -completing STUB from the strings in CANDIDATES. If completion is -ambiguous, possibly show a completions listing in a separate -buffer. - -Return nil if no completion was inserted. -Return `sole' if completed with the only completion match. -Return `shortest' if completed with the shortest match. -Return `partial' if completed as far as possible. -Return `listed' if a completion listing was shown. - -See also `comint-dynamic-complete-filename'." - (declare (obsolete completion-in-region "24.1")) - (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt cygwin))) - (minibuffer-p (window-minibuffer-p)) - (suffix (cond ((not comint-completion-addsuffix) "") - ((not (consp comint-completion-addsuffix)) " ") - (t (cdr comint-completion-addsuffix)))) - (completions (all-completions stub candidates))) - (cond ((null completions) - (if minibuffer-p - (minibuffer-message "No completions of %s" stub) - (message "No completions of %s" stub)) - nil) - ((= 1 (length completions)) ; Gotcha! - (let ((completion (car completions))) - (if (string-equal completion stub) - (unless minibuffer-p - (message "Sole completion")) - (insert (substring completion (length stub))) - (unless minibuffer-p - (message "Completed"))) - (insert suffix) - 'sole)) - (t ; There's no unique completion. - (let ((completion (try-completion stub candidates))) - ;; Insert the longest substring. - (insert (substring completion (length stub))) - (cond ((and comint-completion-recexact comint-completion-addsuffix - (string-equal stub completion) - (member completion completions)) - ;; It's not unique, but user wants shortest match. - (insert suffix) - (unless minibuffer-p - (message "Completed shortest")) - 'shortest) - ((or comint-completion-autolist - (string-equal stub completion)) - ;; It's not unique, list possible completions. - (comint-dynamic-list-completions completions stub) - 'listed) - (t - (unless minibuffer-p - (message "Partially completed")) - 'partial))))))) - (defun comint-dynamic-list-filename-completions () "Display a list of possible completions for the filename at point." (interactive) diff --git a/lisp/dired-x.el b/lisp/dired-x.el index db5a93b60c..1e1bf9efd6 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -1531,13 +1531,6 @@ If `current-prefix-arg' is non-nil, uses name at point as guess." nil (file-name-nondirectory guess))) (read-file-name prompt default-directory))) -(define-obsolete-function-alias 'read-filename-at-point - 'dired-x-read-filename-at-point "24.1") ; is this even needed? - - -;;; Epilog - -(define-obsolete-function-alias 'dired-x-submit-report 'report-emacs-bug "24.1") (define-obsolete-function-alias 'dired-man #'dired-do-man "29.1") (define-obsolete-function-alias 'dired-info #'dired-do-info "29.1") diff --git a/lisp/dos-fns.el b/lisp/dos-fns.el index ea54eea603..edbe9e494f 100644 --- a/lisp/dos-fns.el +++ b/lisp/dos-fns.el @@ -231,9 +231,6 @@ returned unaltered." (add-hook 'before-init-hook 'dos-reevaluate-defcustoms) -(define-obsolete-variable-alias - 'register-name-alist 'dos-register-name-alist "24.1") - (defvar dos-register-name-alist '((ax . 0) (bx . 1) (cx . 2) (dx . 3) (si . 4) (di . 5) (cflag . 6) (flags . 7) @@ -243,8 +240,6 @@ returned unaltered." (defun dos-make-register () (make-vector 8 0)) -(define-obsolete-function-alias 'make-register 'dos-make-register "24.1") - (defun dos-register-value (regs name) (let ((where (cdr (assoc name dos-register-name-alist)))) (cond ((consp where) @@ -256,8 +251,6 @@ returned unaltered." (aref regs where)) (t nil)))) -(define-obsolete-function-alias 'register-value 'dos-register-value "24.1") - (defun dos-set-register-value (regs name value) (and (numberp value) (>= value 0) @@ -274,9 +267,6 @@ returned unaltered." (aset regs where (logand value 65535)))))) regs) -(define-obsolete-function-alias - 'set-register-value 'dos-set-register-value "24.1") - (defsubst dos-intdos (regs) "Issue the DOS Int 21h with registers REGS. @@ -284,8 +274,6 @@ REGS should be a vector produced by `dos-make-register' and `dos-set-register-value', which see." (int86 33 regs)) -(define-obsolete-function-alias 'intdos 'dos-intdos "24.1") - ;; Backward compatibility for obsolescent functions which ;; set screen size. @@ -294,8 +282,6 @@ and `dos-set-register-value', which see." (interactive) (set-frame-size (selected-frame) 80 25)) -(define-obsolete-function-alias 'mode25 'dos-mode25 "24.1") - (defun dos-mode4350 () "Change the number of rows to 43 or 50. Emacs always tries to set the screen height to 50 rows first. @@ -307,8 +293,6 @@ that your video hardware might not support 50-line mode." nil ; the original built-in function returned nil (set-frame-size (selected-frame) 80 43))) -(define-obsolete-function-alias 'mode4350 'dos-mode4350 "24.1") - (provide 'dos-fns) ;;; dos-fns.el ends here diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 5ef517d7e3..8df4133b6b 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -244,11 +244,6 @@ the functions you loaded will not be able to run.") (make-obsolete-variable 'byte-compile-dynamic "not worthwhile any more." "27.1") ;;;###autoload(put 'byte-compile-dynamic 'safe-local-variable 'booleanp) -(defvar byte-compile-disable-print-circle nil - "If non-nil, disable `print-circle' on printing a byte-compiled code.") -(make-obsolete-variable 'byte-compile-disable-print-circle nil "24.1") -;;;###autoload(put 'byte-compile-disable-print-circle 'safe-local-variable 'booleanp) - (defcustom byte-compile-dynamic-docstrings t "If non-nil, compile doc strings for lazy access. We bury the doc strings of functions and variables inside comments in @@ -2423,8 +2418,7 @@ Call from the source buffer." (print-level nil) (print-quoted t) (print-gensym t) - (print-circle ; Handle circular data structures. - (not byte-compile-disable-print-circle))) + (print-circle t)) ; Handle circular data structures. (if (and (memq (car-safe form) '(defvar defvaralias defconst autoload custom-declare-variable)) (stringp (nth 3 form))) @@ -2482,8 +2476,7 @@ list that represents a doc string reference. (print-level nil) (print-quoted t) (print-gensym t) - (print-circle ; Handle circular data structures. - (not byte-compile-disable-print-circle))) + (print-circle t)) ; Handle circular data structures. (if preface (progn ;; FIXME: We don't handle uninterned names correctly. diff --git a/lisp/emacs-lisp/chart.el b/lisp/emacs-lisp/chart.el index 29fbcce773..716b236d3a 100644 --- a/lisp/emacs-lisp/chart.el +++ b/lisp/emacs-lisp/chart.el @@ -63,7 +63,6 @@ (eval-when-compile (require 'cl-generic)) ;;; Code: -(define-obsolete-variable-alias 'chart-map 'chart-mode-map "24.1") (defvar chart-mode-map (make-sparse-keymap) "Keymap used in chart mode.") (defvar-local chart-local-object nil diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index d9864e6965..25f2dd4098 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el @@ -24,8 +24,8 @@ ;;; Commentary: ;; ;; The "core" part of EIEIO is the implementation for the object -;; system (such as eieio-defclass, or eieio-defmethod) but not the -;; base classes for the object system, which are defined in EIEIO. +;; system (such as eieio-defclass-internal, or cl-defmethod) but not +;; the base classes for the object system, which are defined in EIEIO. ;; ;; See the commentary for eieio.el for more about EIEIO itself. diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el index de18adff5b..ae72a47c2f 100644 --- a/lisp/emacs-lisp/ert-x.el +++ b/lisp/emacs-lisp/ert-x.el @@ -158,9 +158,6 @@ test for `called-interactively' in the command will fail." (run-hooks 'pre-command-hook) (setq return-value (apply (car command) (cdr command))) (run-hooks 'post-command-hook) - (and (boundp 'deferred-action-list) - deferred-action-list - (run-hooks 'deferred-action-function)) (setq real-last-command (car command) last-command this-command) (when (boundp 'last-repeatable-command) diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index 641ce0d5c0..4b85414943 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -943,14 +943,7 @@ character." (defun field-complete (table &optional predicate) (declare (obsolete completion-in-region "24.4")) (let ((minibuffer-completion-table table) - (minibuffer-completion-predicate predicate) - ;; This made sense for lisp-complete-symbol, but for - ;; field-complete, this is out of place. --Stef - ;; (completion-annotate-function - ;; (unless (eq predicate 'fboundp) - ;; (lambda (str) - ;; (if (fboundp (intern-soft str)) " ")))) - ) + (minibuffer-completion-predicate predicate)) (call-interactively 'minibuffer-complete))) (defun lisp-complete-symbol (&optional _predicate) diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index c8b6667597..8d0d5d57a2 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -3520,9 +3520,6 @@ The full list of keys can be viewed with \\[describe-mode]." (message (mapconcat #'package--prettify-quick-help-key package--quick-help-keys "\n"))) -(define-obsolete-function-alias - 'package-menu-view-commentary 'package-menu-describe-package "24.1") - (defun package-menu-get-status () "Return status text of package at point in Package Menu." (package--ensure-package-menu-mode) diff --git a/lisp/emacs-lisp/trace.el b/lisp/emacs-lisp/trace.el index 7377ac9403..c2f6c16226 100644 --- a/lisp/emacs-lisp/trace.el +++ b/lisp/emacs-lisp/trace.el @@ -275,10 +275,9 @@ If `current-prefix-arg' is non-nil, also read a buffer and a \"context\" (list (read-buffer "Output to buffer" trace-buffer) (let ((exp - (let ((minibuffer-completing-symbol t)) - (read-from-minibuffer "Context expression: " - nil read-expression-map t - 'read-expression-history)))) + (read-from-minibuffer "Context expression: " + nil read-expression-map t + 'read-expression-history))) (lambda () (let ((print-circle t) (print-escape-newlines t)) diff --git a/lisp/emacs-lock.el b/lisp/emacs-lock.el index 3d2eda99a9..1818e22a92 100644 --- a/lisp/emacs-lock.el +++ b/lisp/emacs-lock.el @@ -88,9 +88,6 @@ The functions get one argument, the first locked buffer found." :group 'emacs-lock :version "24.3") -(define-obsolete-variable-alias 'emacs-lock-from-exiting - 'emacs-lock-mode "24.1") - (defvar-local emacs-lock-mode nil "If non-nil, the current buffer is locked. It can be one of the following values: @@ -247,14 +244,6 @@ some major modes from being locked under some circumstances." ;; continue standard unloading nil)) -;;; Compatibility - -(defun toggle-emacs-lock () - "Toggle `emacs-lock-from-exiting' for the current buffer." - (declare (obsolete emacs-lock-mode "24.1")) - (interactive) - (call-interactively 'emacs-lock-mode)) - (provide 'emacs-lock) ;;; emacs-lock.el ends here diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 239d8ebdcb..0a16831fba 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -4566,8 +4566,6 @@ This places `point' just after the prompt, or at the beginning of the line." (defun erc-complete-word-at-point () (run-hook-with-args-until-success 'erc-complete-functions)) -(define-obsolete-function-alias 'erc-complete-word #'completion-at-point "24.1") - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; IRC SERVER INPUT HANDLING diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el index f4c1302629..822cc94149 100644 --- a/lisp/eshell/em-cmpl.el +++ b/lisp/eshell/em-cmpl.el @@ -158,14 +158,6 @@ to writing a completion function." (eshell-cmpl--custom-variable-docstring 'pcomplete-autolist) :type (get 'pcomplete-autolist 'custom-type)) -(defcustom eshell-cmpl-suffix-list (list ?/ ?:) - (eshell-cmpl--custom-variable-docstring 'pcomplete-suffix-list) - :type (get 'pcomplete-suffix-list 'custom-type) - :group 'pcomplete) -;; Only labeled obsolete in 26.1, but all it does it set -;; pcomplete-suffix-list, which is itself obsolete since 24.1. -(make-obsolete-variable 'eshell-cmpl-suffix-list nil "24.1") - (defcustom eshell-cmpl-recexact nil (eshell-cmpl--custom-variable-docstring 'pcomplete-recexact) :type (get 'pcomplete-recexact 'custom-type)) @@ -262,9 +254,6 @@ to writing a completion function." eshell-cmpl-ignore-case) (setq-local pcomplete-autolist eshell-cmpl-autolist) - (if (boundp 'pcomplete-suffix-list) - (setq-local pcomplete-suffix-list - eshell-cmpl-suffix-list)) (setq-local pcomplete-recexact eshell-cmpl-recexact) (setq-local pcomplete-man-function diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el index 6b86498399..5144e30512 100644 --- a/lisp/eshell/esh-util.el +++ b/lisp/eshell/esh-util.el @@ -301,15 +301,6 @@ Prepend remote identification of `default-directory', if any." (setq text (replace-match " " t t text))) text)) -(defmacro eshell-for (for-var for-list &rest forms) - "Iterate through a list." - (declare (obsolete dolist "24.1") (indent 2)) - `(let ((list-iter ,for-list)) - (while list-iter - (let ((,for-var (car list-iter))) - ,@forms) - (setq list-iter (cdr list-iter))))) - (define-obsolete-function-alias 'eshell-flatten-list #'flatten-tree "27.1") (defun eshell-stringify (object) diff --git a/lisp/files-x.el b/lisp/files-x.el index 8224a57450..da1e44e250 100644 --- a/lisp/files-x.el +++ b/lisp/files-x.el @@ -81,8 +81,7 @@ Intended to be used in the `interactive' spec of (let ((default (format "%S" (cond ((eq variable 'unibyte) t) ((boundp variable) - (symbol-value variable))))) - (minibuffer-completing-symbol t)) + (symbol-value variable)))))) (read-from-minibuffer (format "Add %s with value: " variable) nil read-expression-map t 'set-variable-value-history diff --git a/lisp/files.el b/lisp/files.el index 992f987943..2ea9d1e467 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3161,9 +3161,6 @@ major mode MODE. See also `auto-mode-alist'.") -(define-obsolete-variable-alias 'inhibit-first-line-modes-regexps - 'inhibit-file-local-variables-regexps "24.1") - ;; TODO really this should be a list of modes (eg tar-mode), not regexps, ;; because we are duplicating info from auto-mode-alist. ;; TODO many elements of this list are also in auto-coding-alist. @@ -3184,9 +3181,6 @@ member files with their own local variable sections, which are not appropriate for the containing file. The function `inhibit-local-variables-p' uses this.") -(define-obsolete-variable-alias 'inhibit-first-line-modes-suffixes - 'inhibit-local-variables-suffixes "24.1") - (defvar inhibit-local-variables-suffixes nil "List of regexps matching suffixes to remove from file names. The function `inhibit-local-variables-p' uses this: when checking diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el index 17a87134be..3fc5ce2408 100644 --- a/lisp/gnus/gnus-msg.el +++ b/lisp/gnus/gnus-msg.el @@ -52,24 +52,6 @@ method to use when posting." (const current) (sexp :tag "Methods" ,gnus-select-method))) -(defcustom gnus-outgoing-message-group nil - "All outgoing messages will be put in this group. -If you want to store all your outgoing mail and articles in the group -\"nnml:archive\", you set this variable to that value. This variable -can also be a list of group names. - -If you want to have greater control over what group to put each -message in, you can set this variable to a function that checks the -current newsgroup name and then returns a suitable group name (or list -of names)." - :group 'gnus-message - :type '(choice (const nil) - (function) - (string :tag "Group") - (repeat :tag "List of groups" (string :tag "Group")))) - -(make-obsolete-variable 'gnus-outgoing-message-group 'gnus-message-archive-group "24.1") - (defcustom gnus-mailing-list-groups nil "If non-nil a regexp matching groups that are really mailing lists. This is useful when you're reading a mailing list that has been @@ -215,30 +197,6 @@ use this option with care." :parameter-document "\ List of charsets that are permitted to be unencoded.") -(defcustom gnus-debug-files - '("gnus.el" "gnus-sum.el" "gnus-group.el" - "gnus-art.el" "gnus-start.el" "gnus-async.el" - "gnus-msg.el" "gnus-score.el" "gnus-win.el" "gnus-topic.el" - "gnus-agent.el" "gnus-cache.el" "gnus-srvr.el" - "mm-util.el" "mm-decode.el" "nnmail.el" "message.el") - "Files whose variables will be reported in `gnus-bug'." - :version "22.1" - :group 'gnus-message - :type '(repeat file)) - -(make-obsolete-variable 'gnus-debug-files "it is no longer used." "24.1") - -(defcustom gnus-debug-exclude-variables - '(mm-mime-mule-charset-alist - nnmail-split-fancy message-minibuffer-local-map) - "Variables that should not be reported in `gnus-bug'." - :version "22.1" - :group 'gnus-message - :type '(repeat variable)) - -(make-obsolete-variable - 'gnus-debug-exclude-variables "it is no longer used." "24.1") - (defcustom gnus-discouraged-post-methods '(nndraft nnml nnimap nnmaildir nnmh nnfolder nndir) "A list of back ends that are not used in \"real\" newsgroups. @@ -1665,7 +1623,7 @@ this is a reply." (defun gnus-inews-insert-gcc (&optional group) "Insert the Gcc to say where the article is to be archived." (let* ((group (or group gnus-newsgroup-name)) - (var (or gnus-outgoing-message-group gnus-message-archive-group)) + (var gnus-message-archive-group) (gcc-self-val (and group (not (gnus-virtual-group-p group)) (gnus-group-find-parameter group 'gcc-self t))) diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el index 8cefb09b66..ceeb184854 100644 --- a/lisp/gnus/gnus-registry.el +++ b/lisp/gnus/gnus-registry.el @@ -1004,9 +1004,6 @@ Uses `gnus-registry-marks' to find what shortcuts to install." nil (cons "Registry Marks" gnus-registry-misc-menus))))) -(define-obsolete-function-alias 'gnus-registry-user-format-function-M - #'gnus-registry-article-marks-to-chars "24.1") - ;; use like this: ;; (defalias 'gnus-user-format-function-M #'gnus-registry-article-marks-to-chars) (defun gnus-registry-article-marks-to-chars (headers) diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index 2119e68509..7eea08f174 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el @@ -1130,16 +1130,6 @@ you could set this variable: :group 'gnus-server :type '(repeat gnus-select-method)) -(defcustom gnus-local-domain nil - "Local domain name without a host name. -The DOMAINNAME environment variable is used instead if it is defined. -If the function `system-name' returns the full Internet name, there is -no need to set this variable." - :group 'gnus-message - :type '(choice (const :tag "default" nil) - string)) -(make-obsolete-variable 'gnus-local-domain nil "24.1") - ;; Customization variables (defcustom gnus-refer-article-method 'current @@ -2316,11 +2306,6 @@ automatically cache the article in the agent cache." (defvar gnus-server-method-cache nil) (defvar gnus-extended-servers nil) -;; The carpal mode has been removed, but define the variable for -;; backwards compatibility. -(defvar gnus-carpal nil) -(make-obsolete-variable 'gnus-carpal nil "24.1") - (defvar gnus-agent-fetching nil "Whether Gnus agent is in fetching mode.") diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index c629cb85d9..746109f26f 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -95,9 +95,6 @@ Uses the same syntax as `nnmail-split-methods'.") (defvoo nnimap-unsplittable-articles '(%Deleted %Seen) "Articles with the flags in the list will not be considered when splitting.") -(make-obsolete-variable 'nnimap-split-rule "see `nnimap-split-methods'." - "24.1") - (defvoo nnimap-authenticator nil "How nnimap authenticate itself to the server. Possible choices are nil (use default methods), `anonymous', diff --git a/lisp/iimage.el b/lisp/iimage.el index 8a765d5e5d..baeb4bb6a7 100644 --- a/lisp/iimage.el +++ b/lisp/iimage.el @@ -87,9 +87,6 @@ Examples of image filename patterns to match: (iimage-mode-buffer t) (recenter-top-bottom arg)) -;;;###autoload -(define-obsolete-function-alias 'turn-on-iimage-mode 'iimage-mode "24.1") - (defun turn-off-iimage-mode () "Unconditionally turn off iimage mode." (interactive) diff --git a/lisp/image.el b/lisp/image.el index e90cccaa09..bdaaec608e 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -446,15 +446,6 @@ type if we can't otherwise guess it." (error "Invalid image type `%s'" type)) type) - -(if (fboundp 'image-metadata) ; eg not --without-x - (define-obsolete-function-alias 'image-extension-data - 'image-metadata "24.1")) - -(define-obsolete-variable-alias - 'image-library-alist - 'dynamic-library-alist "24.1") - ;;;###autoload (defun image-type-available-p (type) "Return t if image type TYPE is available. diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el index 9d2e20ae04..d743802ead 100644 --- a/lisp/mail/emacsbug.el +++ b/lisp/mail/emacsbug.el @@ -42,9 +42,6 @@ :group 'maint :group 'mail) -(define-obsolete-variable-alias 'report-emacs-bug-pretest-address - 'report-emacs-bug-address "24.1") - (defcustom report-emacs-bug-no-confirmation nil "If non-nil, suppress the confirmations asked for the sake of novice users." :type 'boolean) diff --git a/lisp/mail/mail-utils.el b/lisp/mail/mail-utils.el index 952970d07c..9ea2cc92e9 100644 --- a/lisp/mail/mail-utils.el +++ b/lisp/mail/mail-utils.el @@ -239,12 +239,8 @@ comma-separated list, and return the pruned list." ;; Or just set the default directly in the defcustom. (if (null mail-dont-reply-to-names) (setq mail-dont-reply-to-names - ;; `rmail-default-dont-reply-to-names' is obsolete. - (let ((a (bound-and-true-p rmail-default-dont-reply-to-names)) - (b (if (> (length user-mail-address) 0) - (concat "\\`" (regexp-quote user-mail-address) "\\'")))) - (cond ((and a b) (concat a "\\|" b)) - ((or a b)))))) + (if (> (length user-mail-address) 0) + (concat "\\`" (regexp-quote user-mail-address) "\\'")))) ;; Split up DESTINATIONS and match each element separately. (let ((start-pos 0) (cur-pos 0) (case-fold-search t)) @@ -281,9 +277,6 @@ comma-separated list, and return the pruned list." (substring destinations (match-end 0)) destinations)) -;; Legacy name -(define-obsolete-function-alias 'rmail-dont-reply-to #'mail-dont-reply-to "24.1") - ;;;###autoload (defun mail-fetch-field (field-name &optional last all list delete) diff --git a/lisp/mail/mailalias.el b/lisp/mail/mailalias.el index ba7cf58d38..c97786190c 100644 --- a/lisp/mail/mailalias.el +++ b/lisp/mail/mailalias.el @@ -72,8 +72,7 @@ When t this still needs to be initialized.") ) "Alist of header field and expression to return alist for completion. The expression may reference the variable `pattern' -which will hold the string being completed. -If not on matching header, `mail-complete-function' gets called instead." +which will hold the string being completed." :type 'alist :group 'mailalias) (put 'mail-complete-alist 'risky-local-variable t) @@ -90,13 +89,6 @@ If `angles', they look like: :type '(choice (const angles) (const parens) (const nil)) :group 'mailalias) -(defcustom mail-complete-function 'ispell-complete-word - "Function to call when completing outside `mail-complete-alist'-header." - :type '(choice function (const nil)) - :group 'mailalias) -(make-obsolete-variable 'mail-complete-function - 'completion-at-point-functions "24.1") - (defcustom mail-directory-function nil "Function to get completions from directory service or nil for none. See `mail-directory-requery'." @@ -433,25 +425,6 @@ For use on `completion-at-point-functions'." (let ((pattern prefix)) (eval list-exp)))))) (list beg end table))))) -;;;###autoload -(defun mail-complete (arg) - "Perform completion on header field or word preceding point. -Completable headers are according to `mail-complete-alist'. If none matches -current header, calls `mail-complete-function' and passes prefix ARG if any." - (declare (obsolete mail-completion-at-point-function "24.1")) - (interactive "P") - ;; Read the defaults first, if we have not done so. - (sendmail-sync-aliases) - (if (eq mail-aliases t) - (progn - (setq mail-aliases nil) - (if (file-exists-p mail-personal-alias-file) - (build-mail-aliases)))) - (let ((data (mail-completion-at-point-function))) - (if data - (apply #'completion-in-region data) - (funcall mail-complete-function arg)))) - (defun mail-completion-expand (table) "Build new completion table that expands aliases. Completes like TABLE except that if the completion is a valid alias, diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index b2b21b88ef..467375dbe1 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el @@ -314,20 +314,6 @@ Setting this variable has an effect only before reading a mail." :group 'rmail-retrieve :version "21.1") -;;;###autoload -(define-obsolete-variable-alias 'rmail-dont-reply-to-names - 'mail-dont-reply-to-names "24.1") - -;; Prior to 24.1, this used to contain "\\`info-". -;;;###autoload -(defvar rmail-default-dont-reply-to-names nil - "Regexp specifying part of the default value of `mail-dont-reply-to-names'. -This is used when the user does not set `mail-dont-reply-to-names' -explicitly.") -;;;###autoload -(make-obsolete-variable 'rmail-default-dont-reply-to-names - 'mail-dont-reply-to-names "24.1") - ;;;###autoload (defcustom rmail-ignored-headers (purecopy diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el index c55cdc8412..6afadca6bb 100644 --- a/lisp/mail/sendmail.el +++ b/lisp/mail/sendmail.el @@ -430,20 +430,6 @@ support Delivery Status Notification." (const :tag "Success" success))) :version "22.1") -;; Note: could use /usr/ucb/mail instead of sendmail; -;; options -t, and -v if not interactive. -(defvar mail-mailer-swallows-blank-line nil - "Set this non-nil if the system's mailer runs the header and body together. -The actual value should be an expression to evaluate that returns -non-nil if the problem will actually occur. -\(As far as we know, this is not an issue on any system still supported -by Emacs.)") - -(put 'mail-mailer-swallows-blank-line 'risky-local-variable t) ; gets evalled -(make-obsolete-variable 'mail-mailer-swallows-blank-line - "no need to set this on any modern system." - "24.1" 'set) - (defvar mail-mode-syntax-table ;; define-derived-mode will make it inherit from text-mode-syntax-table. (let ((st (make-syntax-table))) @@ -1309,8 +1295,6 @@ external program defined by `sendmail-program'." ;; Insert an extra newline if we need it to work around ;; Sun's bug that swallows newlines. (goto-char (1+ delimline)) - (if (eval mail-mailer-swallows-blank-line) - (newline)) ;; Find and handle any Fcc fields. (goto-char (point-min)) (if (re-search-forward "^Fcc:" delimline t) @@ -1495,28 +1479,6 @@ just append to the file, in Babyl format if necessary." (with-current-buffer buffer (set-visited-file-modtime))))))))) -(defun mail-sent-via () - "Make a Sent-via header line from each To or Cc header line." - (declare (obsolete "nobody can remember what it is for." "24.1")) - (interactive) - (save-excursion - ;; put a marker at the end of the header - (let ((end (copy-marker (mail-header-end))) - (case-fold-search t)) - (goto-char (point-min)) - ;; search for the To: lines and make Sent-via: lines from them - ;; search for the next To: line - (while (re-search-forward "^\\(to\\|cc\\):" end t) - ;; Grab this line plus all its continuations, sans the `to:'. - (let ((to-line - (buffer-substring (point) - (progn - (if (re-search-forward "^[^ \t\n]" end t) - (backward-char 1) - (goto-char end)) - (point))))) - ;; Insert a copy, with altered header field name. - (insert-before-markers "Sent-via:" to-line)))))) (defun mail-to () "Move point to end of To field, creating it if necessary." @@ -1839,8 +1801,6 @@ If the current line has `mail-yank-prefix', insert it on the new line." (or (bolp) (newline)) (goto-char start)))) -(define-obsolete-function-alias 'mail-attach-file #'mail-insert-file "24.1") - (declare-function mml-attach-file "mml" (file &optional type description disposition)) diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el index da786dec00..8cba2b14e1 100644 --- a/lisp/mail/smtpmail.el +++ b/lisp/mail/smtpmail.el @@ -342,8 +342,6 @@ for `smtpmail-try-auth-method'.") ;; Insert an extra newline if we need it to work around ;; Sun's bug that swallows newlines. (goto-char (1+ delimline)) - (if (eval mail-mailer-swallows-blank-line t) - (newline)) ;; Find and handle any Fcc fields. (goto-char (point-min)) (if (re-search-forward "^Fcc:" delimline t) diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index a134654a02..12a0b4d328 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -584,9 +584,6 @@ menu)) -(define-obsolete-function-alias - 'menu-bar-kill-ring-save 'kill-ring-save "24.1") - ;; These are alternative definitions for the cut, paste and copy ;; menu items. Use them if your system expects these to use the clipboard. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index e029dfe414..9d2abbd118 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2225,25 +2225,6 @@ These include: `exact' - text is a valid completion but may be further completed.") -(defvar completion-annotate-function - nil - ;; Note: there's a lot of scope as for when to add annotations and - ;; what annotations to add. E.g. completing-help.el allowed adding - ;; the first line of docstrings to M-x completion. But there's - ;; a tension, since such annotations, while useful at times, can - ;; actually drown the useful information. - ;; So completion-annotate-function should be used parsimoniously, or - ;; else only used upon a user's request (e.g. we could add a command - ;; to completion-list-mode to add annotations to the current - ;; completions). - "Function to add annotations in the *Completions* buffer. -The function takes a completion and should either return nil, or a string that -will be displayed next to the completion. The function can access the -completion table and predicates via `minibuffer-completion-table' and related -variables.") -(make-obsolete-variable 'completion-annotate-function - 'completion-extra-properties "24.1") - (defun completion--done (string &optional finished message) (let* ((exit-fun (plist-get completion-extra-properties :exit-function)) (pre-msg (and exit-fun (current-message)))) @@ -2314,8 +2295,7 @@ variables.") minibuffer-completion-predicate)) (ann-fun (or (completion-metadata-get all-md 'annotation-function) (plist-get completion-extra-properties - :annotation-function) - completion-annotate-function)) + :annotation-function))) (aff-fun (or (completion-metadata-get all-md 'affixation-function) (plist-get completion-extra-properties :affixation-function))) @@ -2790,9 +2770,6 @@ Gets combined either with `minibuffer-local-completion-map' or with `minibuffer-local-must-match-map'." "SPC" nil) -(defvar minibuffer-local-filename-must-match-map (make-sparse-keymap)) -(make-obsolete-variable 'minibuffer-local-filename-must-match-map nil "24.1") - (defvar-keymap minibuffer-local-ns-map :doc "Local keymap for the minibuffer when spaces are not allowed." :parent minibuffer-local-map diff --git a/lisp/msb.el b/lisp/msb.el index 616799f067..19f0afed73 100644 --- a/lisp/msb.el +++ b/lisp/msb.el @@ -353,9 +353,6 @@ This is instead of the groups in `msb-menu-cond'." :type 'boolean :set #'msb-custom-set) -(define-obsolete-variable-alias 'msb-after-load-hooks - 'msb-after-load-hook "24.1") - (defcustom msb-after-load-hook nil "Hook run after the msb package has been loaded." :type 'hook diff --git a/lisp/obsolete/eieio-compat.el b/lisp/obsolete/eieio-compat.el index b31bde4efb..2ac75293fc 100644 --- a/lisp/obsolete/eieio-compat.el +++ b/lisp/obsolete/eieio-compat.el @@ -248,21 +248,6 @@ Summary: (message "next-method-p called outside of a primary or around method") nil) -;;;###autoload -(defun eieio-defmethod (method args) - "Obsolete work part of an old version of the `defmethod' macro." - (declare (obsolete cl-defmethod "24.1")) - (eval `(defmethod ,method ,@args)) - method) - -;;;###autoload -(defun eieio-defgeneric (method doc-string) - "Obsolete work part of an old version of the `defgeneric' macro." - (declare (obsolete cl-defgeneric "24.1")) - (eval `(defgeneric ,method (x) ,@(if doc-string `(,doc-string)))) - ;; Return the method - 'method) - ;;;###autoload (defun eieio-defclass (cname superclasses slots options) (declare (obsolete eieio-defclass-internal "25.1")) diff --git a/lisp/obsolete/info-edit.el b/lisp/obsolete/info-edit.el index 6c1be1078f..6c4c10ca6c 100644 --- a/lisp/obsolete/info-edit.el +++ b/lisp/obsolete/info-edit.el @@ -33,7 +33,6 @@ (make-obsolete-variable 'Info-edit-mode-hook "editing Info nodes by hand is not recommended." "24.4") -(define-obsolete-variable-alias 'Info-edit-map 'Info-edit-mode-map "24.1") (defvar Info-edit-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map text-mode-map) (define-key map "\C-c\C-c" #'Info-cease-edit) diff --git a/lisp/obsolete/starttls.el b/lisp/obsolete/starttls.el index 6f0685d3dd..2f1f0e9773 100644 --- a/lisp/obsolete/starttls.el +++ b/lisp/obsolete/starttls.el @@ -287,9 +287,6 @@ GnuTLS requires a port number." starttls-gnutls-program starttls-program)))) -(define-obsolete-function-alias 'starttls-any-program-available - #'starttls-available-p "24.1") - (provide 'starttls) ;;; starttls.el ends here diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el index 00348ac0bb..32031d1946 100644 --- a/lisp/progmodes/cfengine.el +++ b/lisp/progmodes/cfengine.el @@ -793,14 +793,6 @@ bundle agent rcfiles (cdr (assq 'functions cfengine3-fallback-syntax))) 'symbols)) -(defcustom cfengine-mode-abbrevs nil - "Abbrevs for CFEngine2 mode." - :type '(repeat (list (string :tag "Name") - (string :tag "Expansion") - (choice :tag "Hook" (const nil) function)))) - -(make-obsolete-variable 'cfengine-mode-abbrevs 'edit-abbrevs "24.1") - ;; Taken from the doc for pre-release 2.1. (eval-and-compile (defconst cfengine2-actions @@ -1409,7 +1401,6 @@ to the action header." (setq-local outline-regexp "[ \t]*\\(\\sw\\|\\s_\\)+:+") (setq-local outline-level #'cfengine2-outline-level) (setq-local fill-paragraph-function #'cfengine-fill-paragraph) - (define-abbrev-table 'cfengine2-mode-abbrev-table cfengine-mode-abbrevs) (setq font-lock-defaults '(cfengine2-font-lock-keywords nil nil nil beginning-of-line)) ;; Fixme: set the args of functions in evaluated classes to string diff --git a/lisp/progmodes/cwarn.el b/lisp/progmodes/cwarn.el index 971e3f6174..03469b9f55 100644 --- a/lisp/progmodes/cwarn.el +++ b/lisp/progmodes/cwarn.el @@ -180,9 +180,6 @@ C++ modes are included." (cwarn-font-lock-keywords cwarn-mode) (font-lock-flush)) -;;;###autoload -(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "24.1") - ;;}}} ;;{{{ Help functions diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el index 91307f6c09..bd01786e08 100644 --- a/lisp/progmodes/make-mode.el +++ b/lisp/progmodes/make-mode.el @@ -1170,7 +1170,6 @@ and adds all qualifying names to the list of known targets." (goto-char (match-end 0)) (insert suffix)))))))) -(define-obsolete-function-alias 'makefile-complete 'completion-at-point "24.1") ;; Backslashification. Stolen from cc-mode.el. diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el index 34288e0e4f..f0fd23f3bc 100644 --- a/lisp/progmodes/meta-mode.el +++ b/lisp/progmodes/meta-mode.el @@ -438,8 +438,6 @@ If the list was changed, sort the list and remove duplicates first." (insert close))))))) (nth 1 entry)))) -(define-obsolete-function-alias 'meta-complete-symbol - 'completion-at-point "24.1") ;;; Indentation. @@ -803,7 +801,6 @@ The environment marked is the one that contains point or follows point." st) "Syntax table used in Metafont or MetaPost mode.") -(define-obsolete-variable-alias 'meta-mode-map 'meta-common-mode-map "24.1") (defvar meta-common-mode-map (let ((map (make-sparse-keymap))) ;; Comment Paragraphs: diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el index 351ea6e3a9..8d3194e6a4 100644 --- a/lisp/progmodes/pascal.el +++ b/lisp/progmodes/pascal.el @@ -239,14 +239,6 @@ will do all lineups." (const :tag "Declarations" declaration) (const :tag "Case statements" case))) -(defvar pascal-toggle-completions nil - "If non-nil, `pascal-complete-word' tries all possible completions. -Repeated use of \\[pascal-complete-word] then shows all -completions in turn, instead of displaying a list of all possible -completions.") -(make-obsolete-variable 'pascal-toggle-completions - 'completion-cycle-threshold "24.1") - (defcustom pascal-type-keywords '("array" "file" "packed" "char" "integer" "real" "string" "record") "Keywords for types used when completing a word in a declaration or parmlist. @@ -1297,13 +1289,6 @@ indent of the current line in parameterlist." (when (> e b) (list b e #'pascal-completion)))) -(define-obsolete-function-alias 'pascal-complete-word - 'completion-at-point "24.1") - -(define-obsolete-function-alias 'pascal-show-completions - 'completion-help-at-point "24.1") - - (defun pascal-get-default-symbol () "Return symbol around current point as a string." (save-excursion diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el index 9598209f5e..5aba95d4c7 100644 --- a/lisp/progmodes/prolog.el +++ b/lisp/progmodes/prolog.el @@ -742,14 +742,6 @@ Relevant only when `prolog-imenu-flag' is non-nil." :group 'prolog-other :type 'boolean) -(defcustom prolog-char-quote-workaround nil - "If non-nil, declare 0 as a quote character to handle 0'. -This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24." - :version "24.1" - :group 'prolog-other - :type 'boolean) -(make-obsolete-variable 'prolog-char-quote-workaround nil "24.1") - ;;------------------------------------------------------------------- ;; Internal variables @@ -1303,7 +1295,7 @@ To find out what version of Prolog mode you are running, enter (t t))) ;; This statement was missing in Emacs 24.1, 24.2, 24.3. -(define-obsolete-function-alias 'switch-to-prolog 'run-prolog "24.1") +(define-obsolete-function-alias 'switch-to-prolog 'run-prolog "24.1") ; "24.4" ; for grep ;;;###autoload (defun run-prolog (arg) "Run an inferior Prolog process, input and output via buffer *prolog*. diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index f1191b8faa..1c99937c4b 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -248,7 +248,6 @@ (eval-when-compile (require 'subr-x)) ;For `string-empty-p'. ;; Avoid compiler warnings -(defvar view-return-to-alist) (defvar compilation-error-regexp-alist) (defvar outline-heading-end-regexp) diff --git a/lisp/progmodes/which-func.el b/lisp/progmodes/which-func.el index 3c8d4f43db..2e8e8d2319 100644 --- a/lisp/progmodes/which-func.el +++ b/lisp/progmodes/which-func.el @@ -234,9 +234,6 @@ It creates the Imenu index for the buffer, if necessary." (setq which-func-mode nil) (error "Error in which-func-update: %S" info)))))) -;;;###autoload -(define-obsolete-function-alias 'which-func-mode 'which-function-mode "24.1") - (defvar which-func-update-timer nil) (unless (or (assq 'which-func-mode mode-line-misc-info) diff --git a/lisp/simple.el b/lisp/simple.el index 66640916a2..1d251dbf5e 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1732,8 +1732,6 @@ from Lisp." words (if (= words 1) "" "s") chars (if (= chars 1) "" "s")))) -(define-obsolete-function-alias 'count-lines-region 'count-words-region "24.1") - (defun what-line () "Print the current buffer line number and narrowed line number of point." (interactive) @@ -1951,10 +1949,6 @@ Such arguments are used as in `read-from-minibuffer'.)" ;; Used for interactive spec `X'. (eval (read--expression prompt initial-contents))) -(defvar minibuffer-completing-symbol nil - "Non-nil means completing a Lisp symbol in the minibuffer.") -(make-obsolete-variable 'minibuffer-completing-symbol nil "24.1" 'get) - (defvar minibuffer-default nil "The current default value or list of default values in the minibuffer. The functions `read-from-minibuffer' and `completing-read' bind @@ -2015,20 +2009,19 @@ display the result of expression evaluation." PROMPT and optional argument INITIAL-CONTENTS do the same as in function `read-from-minibuffer'." - (let ((minibuffer-completing-symbol t)) - (minibuffer-with-setup-hook - (lambda () - ;; FIXME: instead of just applying the syntax table, maybe - ;; use a special major mode tailored to reading Lisp - ;; expressions from the minibuffer? (`emacs-lisp-mode' - ;; doesn't preserve the necessary keybindings.) - (set-syntax-table emacs-lisp-mode-syntax-table) - (add-hook 'completion-at-point-functions - #'elisp-completion-at-point nil t) - (run-hooks 'eval-expression-minibuffer-setup-hook)) - (read-from-minibuffer prompt initial-contents - read-expression-map t - 'read-expression-history)))) + (minibuffer-with-setup-hook + (lambda () + ;; FIXME: instead of just applying the syntax table, maybe + ;; use a special major mode tailored to reading Lisp + ;; expressions from the minibuffer? (`emacs-lisp-mode' + ;; doesn't preserve the necessary keybindings.) + (set-syntax-table emacs-lisp-mode-syntax-table) + (add-hook 'completion-at-point-functions + #'elisp-completion-at-point nil t) + (run-hooks 'eval-expression-minibuffer-setup-hook)) + (read-from-minibuffer prompt initial-contents + read-expression-map t + 'read-expression-history))) (defun read--expression-try-read () "Try to read an Emacs Lisp expression in the minibuffer. diff --git a/lisp/speedbar.el b/lisp/speedbar.el index da85d54863..9184d6c525 100644 --- a/lisp/speedbar.el +++ b/lisp/speedbar.el @@ -703,8 +703,6 @@ If you want to change this while speedbar is active, either use (defvar speedbar-update-flag-disable nil "Permanently disable changing of the update flag.") -(define-obsolete-variable-alias - 'speedbar-syntax-table 'speedbar-mode-syntax-table "24.1") (defvar speedbar-mode-syntax-table (let ((st (make-syntax-table))) ;; Turn off paren matching around here. @@ -719,8 +717,6 @@ If you want to change this while speedbar is active, either use st) "Syntax-table used on the speedbar.") - -(define-obsolete-variable-alias 'speedbar-key-map 'speedbar-mode-map "24.1") (defvar speedbar-mode-map (let ((map (make-keymap))) (suppress-keymap map t) diff --git a/lisp/strokes.el b/lisp/strokes.el index 376cbc0cfe..d7a9539316 100644 --- a/lisp/strokes.el +++ b/lisp/strokes.el @@ -1031,8 +1031,6 @@ o Strokes are a bit computer-dependent in that they depend somewhat on (help-mode) (help-print-return-message))) -(define-obsolete-function-alias 'strokes-report-bug #'report-emacs-bug "24.1") - (defun strokes-window-configuration-changed-p () "Non-nil if the `strokes-window-configuration' frame properties changed. This is based on the last time `strokes-window-configuration' was updated." diff --git a/lisp/subr.el b/lisp/subr.el index 6bf12fd757..f8b386e563 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1856,8 +1856,6 @@ be a list of the form returned by `event-start' and `event-end'." ;;;; Obsolescence declarations for variables, and aliases. (make-obsolete-variable 'redisplay-end-trigger-functions 'jit-lock-register "23.1") -(make-obsolete-variable 'deferred-action-list 'post-command-hook "24.1") -(make-obsolete-variable 'deferred-action-function 'post-command-hook "24.1") (make-obsolete-variable 'redisplay-dont-pause nil "24.5") (make-obsolete 'window-redisplay-end-trigger nil "23.1") (make-obsolete 'set-window-redisplay-end-trigger nil "23.1") @@ -4707,9 +4705,6 @@ even if this catches the signal." ,@(cdr handler))) handlers))) -(define-obsolete-function-alias 'condition-case-no-debug - 'condition-case-unless-debug "24.1") - (defmacro with-demoted-errors (format &rest body) "Run BODY and demote any errors to simple messages. FORMAT is a string passed to `message' to format any error message. diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index 84c5b087b9..e26191b33b 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -97,8 +97,6 @@ The properties returned may include `top', `left', `height', and `width'." ;;;; Keyboard mapping. -(define-obsolete-variable-alias 'ns-alternatives-map 'x-alternatives-map "24.1") - ;; Here are some Nextstep-like bindings for command key sequences. (define-key global-map [?\s-,] 'customize) (define-key global-map [?\s-'] 'next-window-any-frame) @@ -682,10 +680,6 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") ;;;; Pasteboard support. -(define-obsolete-function-alias 'ns-store-cut-buffer-internal - 'gui-set-selection "24.1") - - (defun ns-copy-including-secondary () (interactive) (call-interactively 'kill-ring-save) diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el index 7eaa604776..993f1d4320 100644 --- a/lisp/term/w32-win.el +++ b/lisp/term/w32-win.el @@ -81,7 +81,6 @@ (&optional frame exclude-proportional)) (defvar w32-color-map) ;; defined in w32fns.c -(make-obsolete 'w32-default-color-map nil "24.1") (declare-function w32-send-sys-command "w32fns.c") (declare-function set-message-beep "w32fns.c") diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 7c88c85cef..3a0bd65f29 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1171,9 +1171,6 @@ as returned by `x-server-vendor'." ;;;; Selections -(define-obsolete-function-alias 'x-cut-buffer-or-selection-value - 'x-selection-value "24.1") - ;; Arrange for the kill and yank functions to set and check the clipboard. (defun x-clipboard-yank () diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index 544e0da827..6763da046f 100644 --- a/lisp/textmodes/bibtex.el +++ b/lisp/textmodes/bibtex.el @@ -316,8 +316,6 @@ If parsing fails, try to set this variable to nil." (option (choice :tag "Alternative" :value nil (const nil) integer))))))) -(define-obsolete-variable-alias 'bibtex-entry-field-alist - 'bibtex-BibTeX-entry-alist "24.1") (defcustom bibtex-BibTeX-entry-alist '(("Article" "Article in Journal" (("author") @@ -3673,14 +3671,6 @@ if that value is non-nil. (if (not (consp (nth 1 (car entry-alist)))) ;; new format entry-alist - ;; Convert old format of `bibtex-entry-field-alist' - (unless (get var 'entry-list-format) - (put var 'entry-list-format "pre-24") - (message "Old format of `%s' (pre GNU Emacs 24). -Please convert to the new format." - (if (eq (indirect-variable 'bibtex-entry-field-alist) var) - 'bibtex-entry-field-alist var)) - (sit-for 3)) (let (lst) (dolist (entry entry-alist) (let ((fl (nth 1 entry)) req xref opt) @@ -5318,7 +5308,6 @@ entries from minibuffer." (goto-char (point-max)) (message "Buffer is now parsable. Please save it."))) -(define-obsolete-function-alias 'bibtex-complete #'completion-at-point "24.1") (defun bibtex-completion-at-point-function () (let ((pnt (point)) (case-fold-search t) diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el index aeae389da6..b517cc1663 100644 --- a/lisp/textmodes/reftex-index.el +++ b/lisp/textmodes/reftex-index.el @@ -269,8 +269,6 @@ will prompt for other arguments." (and newtag (cdr cell) (not (member newtag (cdr cell))) (push newtag (cdr cell))))) -(define-obsolete-variable-alias - 'reftex-index-map 'reftex-index-mode-map "24.1") (defvar reftex-index-mode-map (let ((map (make-sparse-keymap))) ;; Index map @@ -1198,8 +1196,6 @@ This gets refreshed in every phrases command.") '((reftex-index-phrases-font-lock-keywords) nil t nil beginning-of-line) "Font lock defaults for `reftex-index-phrases-mode'.") -(define-obsolete-variable-alias - 'reftex-index-phrases-map 'reftex-index-phrases-mode-map "24.1") (defvar reftex-index-phrases-mode-map (let ((map (make-sparse-keymap))) ;; Keybindings and Menu for phrases buffer diff --git a/lisp/textmodes/reftex-sel.el b/lisp/textmodes/reftex-sel.el index d77411483f..5942801a8a 100644 --- a/lisp/textmodes/reftex-sel.el +++ b/lisp/textmodes/reftex-sel.el @@ -59,8 +59,6 @@ (define-key map [follow-link] 'mouse-face) map)) -(define-obsolete-variable-alias - 'reftex-select-label-map 'reftex-select-label-mode-map "24.1") (defvar reftex-select-label-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map reftex-select-shared-map) @@ -109,8 +107,6 @@ During a selection process, these are the local bindings. ;; We do not set a local map - reftex-select-item does this. ) -(define-obsolete-variable-alias - 'reftex-select-bib-map 'reftex-select-bib-mode-map "24.1") (defvar reftex-select-bib-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map reftex-select-shared-map) diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el index 89c734a0d7..5599eaee02 100644 --- a/lisp/textmodes/reftex-toc.el +++ b/lisp/textmodes/reftex-toc.el @@ -28,7 +28,6 @@ (require 'reftex) ;;; -(define-obsolete-variable-alias 'reftex-toc-map 'reftex-toc-mode-map "24.1") (defvar reftex-toc-mode-map (let ((map (make-sparse-keymap))) diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el index 964baed03c..f6bbda02e6 100644 --- a/lisp/textmodes/rst.el +++ b/lisp/textmodes/rst.el @@ -3584,125 +3584,46 @@ Region is from BEG to END. With WITH-EMPTY prefix empty lines too." :version "24.1" :group 'rst-faces) -(defcustom rst-block-face 'rst-block - "All syntax marking up a special block." - :version "24.1" - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-block-face - "customize the face `rst-block' instead." - "24.1") - (defface rst-external '((t :inherit font-lock-type-face)) "Face used for field names and interpreted text." :version "24.1" :group 'rst-faces) -(defcustom rst-external-face 'rst-external - "Field names and interpreted text." - :version "24.1" - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-external-face - "customize the face `rst-external' instead." - "24.1") - (defface rst-definition '((t :inherit font-lock-function-name-face)) "Face used for all other defining constructs." :version "24.1" :group 'rst-faces) -(defcustom rst-definition-face 'rst-definition - "All other defining constructs." - :version "24.1" - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-definition-face - "customize the face `rst-definition' instead." - "24.1") - (defface rst-directive '((t :inherit font-lock-builtin-face)) "Face used for directives and roles." :version "24.1" :group 'rst-faces) -(defcustom rst-directive-face 'rst-directive - "Directives and roles." - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-directive-face - "customize the face `rst-directive' instead." - "24.1") - (defface rst-comment '((t :inherit font-lock-comment-face)) "Face used for comments." :version "24.1" :group 'rst-faces) -(defcustom rst-comment-face 'rst-comment - "Comments." - :version "24.1" - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-comment-face - "customize the face `rst-comment' instead." - "24.1") - (defface rst-emphasis1 '((t :inherit italic)) "Face used for simple emphasis." :version "24.1" :group 'rst-faces) -(defcustom rst-emphasis1-face 'rst-emphasis1 - "Simple emphasis." - :version "24.1" - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-emphasis1-face - "customize the face `rst-emphasis1' instead." - "24.1") - (defface rst-emphasis2 '((t :inherit bold)) "Face used for double emphasis." :version "24.1" :group 'rst-faces) -(defcustom rst-emphasis2-face 'rst-emphasis2 - "Double emphasis." - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-emphasis2-face - "customize the face `rst-emphasis2' instead." - "24.1") - (defface rst-literal '((t :inherit font-lock-string-face)) "Face used for literal text." :version "24.1" :group 'rst-faces) -(defcustom rst-literal-face 'rst-literal - "Literal text." - :version "24.1" - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-literal-face - "customize the face `rst-literal' instead." - "24.1") - (defface rst-reference '((t :inherit font-lock-variable-name-face)) "Face used for references to a definition." :version "24.1" :group 'rst-faces) -(defcustom rst-reference-face 'rst-reference - "References to a definition." - :version "24.1" - :group 'rst-faces - :type '(face)) -(make-obsolete-variable 'rst-reference-face - "customize the face `rst-reference' instead." - "24.1") - (defface rst-transition '((t :inherit font-lock-keyword-face)) "Face used for a transition." :package-version '(rst . "1.3.0") @@ -3794,23 +3715,23 @@ of your own." ;; `Bullet Lists`_ ;; FIXME: A bullet directly after a field name is not recognized. (,(rst-re 'lin-beg '(:grp bul-sta)) - 1 rst-block-face) + 1 'rst-block) ;; `Enumerated Lists`_ (,(rst-re 'lin-beg '(:grp enmany-sta)) - 1 rst-block-face) + 1 'rst-block) ;; `Definition Lists`_ ;; FIXME: missing. ;; `Field Lists`_ (,(rst-re 'lin-beg '(:grp fld-tag) 'bli-sfx) - 1 rst-external-face) + 1 'rst-external) ;; `Option Lists`_ (,(rst-re 'lin-beg '(:grp opt-tag (:shy optsep-tag opt-tag) "*") '(:alt "$" (:seq hws-prt "\\{2\\}"))) - 1 rst-block-face) + 1 'rst-block) ;; `Line Blocks`_ ;; Only for lines containing no more bar - to distinguish from tables. (,(rst-re 'lin-beg '(:grp "|" bli-sfx) "[^|\n]*$") - 1 rst-block-face) + 1 'rst-block) ;; `Tables`_ ;; FIXME: missing @@ -3818,22 +3739,22 @@ of your own." ;; All the `Explicit Markup Blocks`_ ;; `Footnotes`_ / `Citations`_ (,(rst-re 'lin-beg 'fnc-sta-2) - (1 rst-definition-face) - (2 rst-definition-face)) + (1 'rst-definition) + (2 'rst-definition)) ;; `Directives`_ / `Substitution Definitions`_ (,(rst-re 'lin-beg 'dir-sta-3) - (1 rst-directive-face) - (2 rst-definition-face) - (3 rst-directive-face)) + (1 'rst-directive) + (2 'rst-definition) + (3 'rst-directive)) ;; `Hyperlink Targets`_ (,(rst-re 'lin-beg '(:grp exm-sta "_" (:alt (:seq "`" ilcbkqdef-tag "`") (:seq (:alt "[^:\\\n]" "\\\\.") "+")) ":") 'bli-sfx) - 1 rst-definition-face) + 1 'rst-definition) (,(rst-re 'lin-beg '(:grp "__") 'bli-sfx) - 1 rst-definition-face) + 1 'rst-definition) ;; All `Inline Markup`_ ;; Most of them may be multiline though this is uninteresting. @@ -3841,16 +3762,16 @@ of your own." ;; FIXME: Condition 5 preventing fontification of e.g. "*" not implemented ;; `Strong Emphasis`_. (,(rst-re 'ilm-pfx '(:grp "\\*\\*" ilcast-tag "\\*\\*") 'ilm-sfx) - 1 rst-emphasis2-face) + 1 'rst-emphasis2) ;; `Emphasis`_ (,(rst-re 'ilm-pfx '(:grp "\\*" ilcast-tag "\\*") 'ilm-sfx) - 1 rst-emphasis1-face) + 1 'rst-emphasis1) ;; `Inline Literals`_ (,(rst-re 'ilm-pfx '(:grp "``" ilcbkq-tag "``") 'ilm-sfx) - 1 rst-literal-face) + 1 'rst-literal) ;; `Inline Internal Targets`_ (,(rst-re 'ilm-pfx '(:grp "_`" ilcbkq-tag "`") 'ilm-sfx) - 1 rst-definition-face) + 1 'rst-definition) ;; `Hyperlink References`_ ;; FIXME: `Embedded URIs and Aliases`_ not considered. ;; FIXME: Directly adjacent marked up words are not fontified correctly @@ -3858,28 +3779,28 @@ of your own." (,(rst-re 'ilm-pfx '(:grp (:alt (:seq "`" ilcbkq-tag "`") (:seq "\\sw" (:alt "\\sw" "-") "+\\sw")) "__?") 'ilm-sfx) - 1 rst-reference-face) + 1 'rst-reference) ;; `Interpreted Text`_ (,(rst-re 'ilm-pfx '(:grp (:shy ":" sym-tag ":") "?") '(:grp "`" ilcbkq-tag "`") '(:grp (:shy ":" sym-tag ":") "?") 'ilm-sfx) - (1 rst-directive-face) - (2 rst-external-face) - (3 rst-directive-face)) + (1 'rst-directive) + (2 'rst-external) + (3 'rst-directive)) ;; `Footnote References`_ / `Citation References`_ (,(rst-re 'ilm-pfx '(:grp fnc-tag "_") 'ilm-sfx) - 1 rst-reference-face) + 1 'rst-reference) ;; `Substitution References`_ ;; FIXME: References substitutions like |this|_ or |this|__ are not ;; fontified correctly. (,(rst-re 'ilm-pfx '(:grp sub-tag) 'ilm-sfx) - 1 rst-reference-face) + 1 'rst-reference) ;; `Standalone Hyperlinks`_ ;; FIXME: This takes it easy by using a whitespace as delimiter. (,(rst-re 'ilm-pfx '(:grp uri-tag ":\\S +") 'ilm-sfx) - 1 rst-definition-face) + 1 'rst-definition) (,(rst-re 'ilm-pfx '(:grp sym-tag "@" sym-tag ) 'ilm-sfx) - 1 rst-definition-face) + 1 'rst-definition) ;; Do all block fontification as late as possible so 'append works. @@ -3906,18 +3827,18 @@ of your own." ;; `Comments`_ ;; This is multiline. (,(rst-re 'lin-beg 'cmt-sta-1) - (1 rst-comment-face) + (1 'rst-comment) (rst-font-lock-find-unindented-line-match (rst-font-lock-find-unindented-line-limit (match-end 1)) nil - (0 rst-comment-face append))) + (0 'rst-comment append))) (,(rst-re 'lin-beg '(:grp exm-tag) '(:grp hws-tag) "$") - (1 rst-comment-face) - (2 rst-comment-face) + (1'rst-comment) + (2'rst-comment) (rst-font-lock-find-unindented-line-match (rst-font-lock-find-unindented-line-limit 'next) nil - (0 rst-comment-face append))) + (0 'rst-comment append))) ;; FIXME: This is not rendered as comment:: ;; .. .. list-table:: @@ -3941,11 +3862,11 @@ of your own." ;; `Indented Literal Blocks`_ ;; This is multiline. (,(rst-re 'lin-beg 'lit-sta-2) - (2 rst-block-face) + (2 'rst-block) (rst-font-lock-find-unindented-line-match (rst-font-lock-find-unindented-line-limit t) nil - (0 rst-literal-face append))) + (0 'rst-literal append))) ;; FIXME: `Quoted Literal Blocks`_ missing. ;; This is multiline. @@ -3972,8 +3893,8 @@ of your own." ;; ;; Indentation is not required for doctest blocks. (,(rst-re 'lin-beg '(:grp (:alt ">>>" ell-tag)) '(:grp ".+")) - (1 rst-block-face) - (2 rst-literal-face))) + (1 'rst-block) + (2 'rst-literal))) "Keywords to highlight in rst mode.") (defvar font-lock-beg) diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 46e40f29c0..80508570f3 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -556,15 +556,6 @@ this function." templates)))) -;; toggle-read-only is obsolete since 24.3, but since vc-t-r-o was made -;; obsolete earlier, it is ok for the latter to be an alias to the former, -;; since the latter will be removed first. We can't just make it -;; an alias for read-only-mode, since that is not 100% the same. -(defalias 'vc-toggle-read-only 'toggle-read-only) -(make-obsolete 'vc-toggle-read-only - "use `read-only-mode' instead (or `toggle-read-only' in older versions of Emacs)." - "24.1") - (defun vc-default-make-version-backups-p (_backend _file) "Return non-nil if unmodified versions should be backed up locally. The default is to switch off this feature." diff --git a/lisp/view.el b/lisp/view.el index 17bc46d4c4..287112f2d4 100644 --- a/lisp/view.el +++ b/lisp/view.el @@ -112,18 +112,6 @@ If nil that means use half the window size.") (defvar-local view-last-regexp nil) ; Global is better??? -(defvar-local view-return-to-alist nil - "What to do with used windows and where to go when finished viewing buffer. -This is local in each buffer being viewed. -It is added to by `view-mode-enter' when starting to view a buffer and -subtracted from by `view-mode-exit' when finished viewing the buffer. - -See RETURN-TO-ALIST argument of function `view-mode-exit' for the format of -`view-return-to-alist'.") -(make-obsolete-variable - 'view-return-to-alist "this variable is no longer used." "24.1") -(put 'view-return-to-alist 'permanent-local t) - (defvar-local view-exit-action nil "If non-nil, a function called when finished viewing. The function should take one argument (a buffer). @@ -476,40 +464,6 @@ Entry to view-mode runs the normal hook `view-mode-hook'." (if buffer-read-only (setq buffer-read-only view-old-buffer-read-only))) -;;;###autoload -(defun view-return-to-alist-update (buffer &optional item) - "Update `view-return-to-alist' of buffer BUFFER. -Remove from `view-return-to-alist' all entries referencing dead -windows. Optional argument ITEM non-nil means add ITEM to -`view-return-to-alist' after purging. For a description of items -that can be added see the RETURN-TO-ALIST argument of the -function `view-mode-exit'. If `view-return-to-alist' contains an -entry for the selected window, purge that entry from -`view-return-to-alist' before adding ITEM." - (declare (obsolete "this function has no effect." "24.1")) - (with-current-buffer buffer - (when view-return-to-alist - (let* ((list view-return-to-alist) - entry entry-window last) - (while list - (setq entry (car list)) - (setq entry-window (car entry)) - (if (and (windowp entry-window) - (or (and item (eq entry-window (selected-window))) - (not (window-live-p entry-window)))) - ;; Remove that entry. - (if last - (setcdr last (cdr list)) - (setq view-return-to-alist - (cdr view-return-to-alist))) - ;; Leave entry alone. - (setq last entry)) - (setq list (cdr list))))) - ;; Add ITEM. - (when item - (setq view-return-to-alist - (cons item view-return-to-alist))))) - ;;;###autoload (defun view-mode-enter (&optional quit-restore exit-action) "Enter View mode and set up exit from view mode depending on optional arguments. diff --git a/src/keyboard.c b/src/keyboard.c index 84a7a0a38a..a520e53397 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1305,9 +1305,6 @@ command_loop_1 (void) /* If there are warnings waiting, process them. */ if (!NILP (Vdelayed_warnings_list)) safe_run_hooks (Qdelayed_warnings_hook); - - if (!NILP (Vdeferred_action_list)) - safe_run_hooks (Qdeferred_action_function); } /* Do this after running Vpost_command_hook, for consistency. */ @@ -1537,8 +1534,6 @@ command_loop_1 (void) if (!NILP (Vdelayed_warnings_list)) safe_run_hooks (Qdelayed_warnings_hook); - safe_run_hooks (Qdeferred_action_function); - kset_last_command (current_kboard, Vthis_command); kset_real_last_command (current_kboard, Vreal_this_command); if (!CONSP (last_command_event)) @@ -12089,7 +12084,6 @@ syms_of_keyboard (void) DEFSYM (Qundo_auto__undoably_changed_buffers, "undo-auto--undoably-changed-buffers"); - DEFSYM (Qdeferred_action_function, "deferred-action-function"); DEFSYM (Qdelayed_warnings_hook, "delayed-warnings-hook"); DEFSYM (Qfunction_key, "function-key"); @@ -12807,17 +12801,6 @@ This keymap works like `input-decode-map', but comes after `function-key-map'. Another difference is that it is global rather than terminal-local. */); Vkey_translation_map = Fmake_sparse_keymap (Qnil); - DEFVAR_LISP ("deferred-action-list", Vdeferred_action_list, - doc: /* List of deferred actions to be performed at a later time. -The precise format isn't relevant here; we just check whether it is nil. */); - Vdeferred_action_list = Qnil; - - DEFVAR_LISP ("deferred-action-function", Vdeferred_action_function, - doc: /* Function to call to handle deferred actions, after each command. -This function is called with no arguments after each command -whenever `deferred-action-list' is non-nil. */); - Vdeferred_action_function = Qnil; - DEFVAR_LISP ("delayed-warnings-list", Vdelayed_warnings_list, doc: /* List of warnings to be displayed after this command. Each element must be a list (TYPE MESSAGE [LEVEL [BUFFER-NAME]]), @@ -13072,7 +13055,6 @@ syms_of_keyboard_for_pdumper (void) PDUMPER_RESET (num_input_keys, 0); PDUMPER_RESET (num_nonmacro_input_events, 0); PDUMPER_RESET_LV (Vlast_event_frame, Qnil); - PDUMPER_RESET_LV (Vdeferred_action_list, Qnil); PDUMPER_RESET_LV (Vdelayed_warnings_list, Qnil); /* Create the initial keyboard. Qt means 'unset'. */ diff --git a/src/w32fns.c b/src/w32fns.c index 468073c917..51540e1880 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -797,13 +797,6 @@ w32_default_color_map (void) return (cmap); } -DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map, - 0, 0, 0, doc: /* Return the default color map. */) - (void) -{ - return w32_default_color_map (); -} - static Lisp_Object w32_color_map_lookup (const char *colorname) { @@ -10879,7 +10872,6 @@ keys when IME input is received. */); /* W32 specific functions */ defsubr (&Sw32_define_rgb_color); - defsubr (&Sw32_default_color_map); defsubr (&Sw32_display_monitor_attributes_list); defsubr (&Sw32_send_sys_command); defsubr (&Sw32_shell_execute); commit ca7b5dbfcac36be79e2e1d3a7fb3d14c5404d7ca Author: Stefan Kangas Date: Fri Jul 8 13:07:39 2022 +0200 Put safe-local-variable property on auto-insert * lisp/autoinsert.el (auto-insert): Put safe-local-variable property to allow disabling auto-inserting without a warning. diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el index c12c554498..29d10bc629 100644 --- a/lisp/autoinsert.el +++ b/lisp/autoinsert.el @@ -67,7 +67,7 @@ Possible values: other insert if possible, but mark as unmodified. Insertion is possible when something appropriate is found in `auto-insert-alist'. When the insertion is marked as unmodified, you can -save it with \\[write-file] RET. +save it with \\[write-file] \\`RET'. This variable is used when the function `auto-insert' is called, e.g. when you do (add-hook \\='find-file-hook \\='auto-insert). With \\[auto-insert], this is always treated as if it were t." @@ -76,6 +76,9 @@ With \\[auto-insert], this is always treated as if it were t." (other :tag "insert if possible, mark as unmodified." not-modified))) +;;;###autoload +(put 'auto-insert 'safe-local-variable #'null) + (defcustom auto-insert-query 'function "Non-nil means ask user before auto-inserting. When this is `function', only ask when called non-interactively." commit 9abf841429257a3e1008bedc4d857ea7a25ab9a6 Author: Stefan Kangas Date: Fri Jul 8 12:04:17 2022 +0200 Stop ffap-machine-at-point from pinging random hosts Having this on by default is highly problematic from a security and privacy standpoint, as it risks having outgoing traffic that could potentially reveal sensitive data (passwords, names, etc.). It also seems to be causing issues for users, see e.g. https://github.com/emacs-helm/helm/issues/648 * lisp/ffap.el (ffap-machine-p-known): Change default to 'accept'. diff --git a/etc/NEWS b/etc/NEWS index 39c3aabb11..226af8d7d6 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2042,6 +2042,12 @@ back the old behavior. This command prompts for a recently opened file in the minibuffer, and visits it. +--- +*** 'ffap-machine-at-point' no longer pings hosts by default. +It will now simply look at a hostname to determine if it is valid, +instead of also trying to ping it. Customize the user option +'ffap-machine-p-known' to 'ping' to get the old behavior back. + --- *** The 'run-dig' command is now obsolete; use 'dig' instead. diff --git a/lisp/ffap.el b/lisp/ffap.el index 20929c659d..65e0779e40 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -1,6 +1,6 @@ ;;; ffap.el --- find file (or url) at point -*- lexical-binding: t -*- -;; Copyright (C) 1995-1997, 2000-2022 Free Software Foundation, Inc. +;; Copyright (C) 1995-2022 Free Software Foundation, Inc. ;; Author: Michelangelo Grigni ;; Maintainer: emacs-devel@gnu.org @@ -394,7 +394,7 @@ Value should be a symbol, one of `ping', `accept', and `reject'." :safe #'ffap--accept-or-reject-p :group 'ffap) -(defcustom ffap-machine-p-known 'ping ; `accept' for higher speed +(defcustom ffap-machine-p-known 'accept "What `ffap-machine-p' does with hostnames that have a known domain. Value should be a symbol, one of `ping', `accept', and `reject'. See `mail-extr.el' for the known domains." @@ -402,7 +402,8 @@ See `mail-extr.el' for the known domains." (const accept) (const reject)) :safe #'ffap--accept-or-reject-p - :group 'ffap) + :group 'ffap + :version "29.1") (defcustom ffap-machine-p-unknown 'reject "What `ffap-machine-p' does with hostnames that have an unknown domain. commit 38697a07c0f2b99b76c41cb1096543681342a405 Author: Stefan Kangas Date: Fri Jul 8 11:30:32 2022 +0200 Add :safe property to ffap-machine-p-* variables * lisp/ffap.el (ffap--accept-or-reject-p): New predicate defun. (ffap-machine-p-local, ffap-machine-p-known) (ffap-machine-p-unknown): Add :safe property using above new predicate. diff --git a/lisp/ffap.el b/lisp/ffap.el index 8628222936..20929c659d 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -377,6 +377,11 @@ Actual search is done by the function `ffap-next-guess'." ;;; Machines (`ffap-machine-p'): +(defun ffap--accept-or-reject-p (symbol) + "Return non-nil if SYMBOL is `accept' or `reject'. +Otherwise, return nil." + (memq symbol '(accept reject))) + ;; I cannot decide a "best" strategy here, so these are variables. In ;; particular, if `Pinging...' is broken or takes too long on your ;; machine, try setting these all to accept or reject. @@ -385,16 +390,20 @@ Actual search is done by the function `ffap-next-guess'." Value should be a symbol, one of `ping', `accept', and `reject'." :type '(choice (const ping) (const accept) - (const reject)) + (const reject)) + :safe #'ffap--accept-or-reject-p :group 'ffap) + (defcustom ffap-machine-p-known 'ping ; `accept' for higher speed "What `ffap-machine-p' does with hostnames that have a known domain. Value should be a symbol, one of `ping', `accept', and `reject'. See `mail-extr.el' for the known domains." :type '(choice (const ping) (const accept) - (const reject)) + (const reject)) + :safe #'ffap--accept-or-reject-p :group 'ffap) + (defcustom ffap-machine-p-unknown 'reject "What `ffap-machine-p' does with hostnames that have an unknown domain. Value should be a symbol, one of `ping', `accept', and `reject'. @@ -402,6 +411,7 @@ See `mail-extr.el' for the known domains." :type '(choice (const ping) (const accept) (const reject)) + :safe #'ffap--accept-or-reject-p :group 'ffap) (defun ffap-what-domain (domain) commit f85683c434ffdb72b4c33bd5231b08d288a0b9b2 Author: Stefan Kangas Date: Fri Jul 8 11:02:17 2022 +0200 Add tests for mail-extr.el * test/lisp/mail/mail-extr-tests.el: New file. diff --git a/test/lisp/mail/mail-extr-tests.el b/test/lisp/mail/mail-extr-tests.el new file mode 100644 index 0000000000..a8f0c605cb --- /dev/null +++ b/test/lisp/mail/mail-extr-tests.el @@ -0,0 +1,41 @@ +;;; mail-extr-tests.el --- Tests for mail-extr.el -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; Code: + +(require 'ert) +(require 'mail-extr) + +(defconst mail-extract-test-cases + '(("foo@example.org" . (nil "foo@example.org")) + ("J. Random Hacker " . ("J. Random Hacker" "foo@example.org")) + ("\"J. Random Hacker\" " . ("J. Random Hacker" "foo@example.org")) + ("Ååå Äää " . ("Ååå Äää" "foo@example.org")))) + +(ert-deftest mail-extract-address-components () + (dolist (test mail-extract-test-cases) + (should (equal (mail-extract-address-components (car test)) (cdr test))))) + +(ert-deftest what-domain () + (should (equal (what-domain "cu") "CU: Cuba"))) + +(provide 'mail-extr-tests) +;;; mail-extr-tests.el ends here commit c4e251103b98ffb1bc1e8ddb54c7d9e08e71edc1 Author: Stefan Kangas Date: Fri Jul 8 10:35:31 2022 +0200 ; * lisp/textmodes/rst.el: Update URLs. diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el index 9d3e9effe6..104812f43c 100644 --- a/lisp/textmodes/rst.el +++ b/lisp/textmodes/rst.el @@ -48,10 +48,10 @@ ;; the contents of this package and how to use it. ;; ;; For more information about reStructuredText, see -;; http://docutils.sourceforge.net/rst.html +;; https://docutils.sourceforge.io/rst.html ;; ;; For full details on how to use the contents of this file, see -;; http://docutils.sourceforge.net/docs/user/emacs.html +;; https://docutils.sourceforge.io/docs/user/emacs.html ;; ;; There are a number of convenient key bindings provided by rst-mode. For the ;; bindings, try C-c C-h when in rst-mode. There are also many variables that @@ -72,7 +72,7 @@ ;;; DOWNLOAD ;; The latest release of this file lies in the docutils source code repository: -;; http://docutils.svn.sourceforge.net/svnroot/docutils/trunk/docutils/tools/editors/emacs/rst.el +;; https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/tools/editors/emacs/rst.el ;;; INSTALLATION @@ -81,7 +81,7 @@ ;; (require 'rst) ;; ;; If you are using `.txt' as a standard extension for reST files as -;; http://docutils.sourceforge.net/FAQ.html#what-s-the-standard-filename-extension-for-a-restructuredtext-file +;; https://docutils.sourceforge.io/FAQ.html#what-s-the-standard-filename-extension-for-a-restructuredtext-file ;; suggests you may use one of the `Local Variables in Files' mechanism Emacs ;; provides to set the major mode automatically. For instance you may use:: ;; @@ -274,7 +274,7 @@ in parentheses follows the development revision and the time stamp.") (defgroup rst nil "Support for reStructuredText documents." :group 'text :version "23.1" - :link '(url-link "http://docutils.sourceforge.net/rst.html")) + :link '(url-link "https://docutils.sourceforge.io/rst.html")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -3786,7 +3786,7 @@ of your own." (defvar rst-font-lock-keywords ;; The reST-links in the comments below all relate to sections in - ;; http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html. + ;; https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html. `(;; FIXME: Block markup is not recognized in blocks after explicit markup ;; start. @@ -4402,7 +4402,7 @@ buffer, if the region is not selected." ;; FIXME: Add `rst-compile-html-preview'. -;; FIXME: Add support for `restview` (http://mg.pov.lt/restview/). May be a +;; FIXME: Add support for `restview` (https://mg.pov.lt/restview/). May be a ;; more general facility for calling commands on a reST file would make ;; sense. commit 989908eee8d78d70c5e475a9cb1bb710d7b54b5f Author: Stefan Kangas Date: Fri Jul 8 10:26:35 2022 +0200 Avoid obsolete initial-input argument in net-utils.el * lisp/net/net-utils.el (ping, nslookup-host, dns-lookup-host) (run-dig, ftp, smbclient, smbclient-list-shares, finger) (network-connection-to-service): Don't use obsolete initial-input argument. Use 'format-prompt'. (Bug#56436) diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index b74400cd96..c7ff175e08 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el @@ -430,7 +430,8 @@ This variable is only used if the variable If your system's ping continues until interrupted, you can try setting `ping-program-options'." (interactive - (list (read-from-minibuffer "Ping host: " (ffap-machine-at-point)))) + (list (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Ping host" default) nil nil default)))) (let ((options (if ping-program-options (append ping-program-options (list host)) @@ -463,7 +464,8 @@ See also: `nslookup-host-ipv4', `nslookup-host-ipv6' for non-interactive versions of this function more suitable for use in Lisp code." (interactive - (list (read-from-minibuffer "Lookup host: " (ffap-machine-at-point)) + (list (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Lookup host" default) nil nil default)) (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (let ((options (append nslookup-program-options (list host) @@ -575,7 +577,8 @@ Interactively, prompt for NAME-SERVER if invoked with prefix argument. This command uses `dns-lookup-program' for looking up the DNS information." (interactive - (list (read-from-minibuffer "Lookup host: " (ffap-machine-at-point)) + (list (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Lookup host" default) nil nil default)) (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (let ((options (append dns-lookup-program-options (list host) @@ -599,7 +602,8 @@ Interactively, prompt for NAME-SERVER if invoked with prefix argument. This command uses `dig-program' for looking up the DNS information." (declare (obsolete dig "29.1")) (interactive - (list (read-from-minibuffer "Lookup host: " (ffap-machine-at-point)) + (list (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Lookup host" default) nil nil default)) (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (dig host nil nil nil nil name-server)) @@ -611,9 +615,8 @@ This command uses `dig-program' for looking up the DNS information." (defun ftp (host) "Run `ftp-program' to connect to HOST." (interactive - (list - (read-from-minibuffer - "Ftp to Host: " (ffap-machine-at-point)))) + (list (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Ftp to Host" default) nil nil default)))) (let ((buf (get-buffer-create (concat "*ftp [" host "]*")))) (set-buffer buf) (ftp-mode) @@ -648,8 +651,8 @@ This command uses `dig-program' for looking up the DNS information." This command uses `smbclient-program' to connect to HOST." (interactive (list - (read-from-minibuffer - "Connect to Host: " (ffap-machine-at-point)) + (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Connect to Host" default) nil nil default)) (read-from-minibuffer "SMB Service: "))) (let* ((name (format "smbclient [%s\\%s]" host service)) (buf (get-buffer-create (concat "*" name "*"))) @@ -667,8 +670,8 @@ This command uses `smbclient-program' to connect to HOST." This command uses `smbclient-program' to connect to HOST." (interactive (list - (read-from-minibuffer - "Connect to Host: " (ffap-machine-at-point)))) + (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Connect to Host" default) nil nil default)))) (let ((buf (get-buffer-create (format "*SMB Shares on %s*" host)))) (set-buffer buf) (smbclient-mode) @@ -767,15 +770,15 @@ and `network-connection-service-alist', which see." ;; uses a string like "pbreton@cs.umb.edu", we won't ask for the ;; host name. If we don't see an "@", we'll prompt for the host. (interactive - (let* ((answer (read-from-minibuffer "Finger User: " - (ffap-url-at-point))) + (let* ((answer (let ((default (ffap-url-at-point))) + (read-string (format-prompt "Finger User" default) nil nil default))) (index (string-match (regexp-quote "@") answer))) (if index (list (substring answer 0 index) (substring answer (1+ index))) (list answer - (read-from-minibuffer "At Host: " - (ffap-machine-at-point)))))) + (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "At Host" default) nil nil default)))))) (let* ((user-and-host (concat user "@" host)) (process-name (concat "Finger [" user-and-host "]")) (regexps finger-X.500-host-regexps) @@ -908,7 +911,8 @@ The port is deduced from `network-connection-service-alist'." This command uses `network-connection-service-alist', which see." (interactive (list - (read-from-minibuffer "Host: " (ffap-machine-at-point)) + (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Host" default) nil nil default)) (completing-read "Service: " (mapcar (lambda (elt) commit 0fc9808dedc24e843bfbbfe3d3a3930167873fa7 Author: Po Lu Date: Fri Jul 8 07:34:45 2022 +0000 Improve behavior of sticky tooltips on Haiku * src/haiku_support.cc (class EmacsView, MouseMoved): Remove `tooltip_position'. (class EmacsMotionSuppressionView): New class. (BView_set_and_show_sticky_tooltip): Rename to `be_show_sticky_tooltip'. Add motion suppression view. * src/haiku_support.h: Update prototypes. * src/haikufns.c (Fx_show_tip): Update for renamed function. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 332321e2db..a3d3b7a17d 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1517,7 +1517,6 @@ class EmacsView : public BView BLocker cr_surface_lock; #endif - BPoint tooltip_position; BMessage *wait_for_release_message; EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", @@ -1797,11 +1796,8 @@ class EmacsView : public BView struct haiku_mouse_motion_event rq; int32 windowid; EmacsWindow *window; - BToolTip *tooltip; - BPoint target_tooltip_position; window = (EmacsWindow *) Window (); - tooltip = ToolTip (); if (transit == B_EXITED_VIEW) rq.just_exited_p = true; @@ -1821,16 +1817,6 @@ class EmacsView : public BView else rq.dnd_message = false; - if (tooltip) - { - target_tooltip_position - = BPoint (-(point.x - tooltip_position.x), - -(point.y - tooltip_position.y)); - tooltip->SetMouseRelativeLocation (target_tooltip_position); - tooltip->SetSticky (true); - ShowToolTip (tooltip); - } - if (!grab_view_locker.Lock ()) gui_abort ("Couldn't lock grab view locker"); @@ -3282,6 +3268,41 @@ class EmacsFilePanelCallbackLooper : public BLooper } }; +/* A view that is added as a child of a tooltip's text view, and + prevents motion events from reaching it (thereby moving the + tooltip). */ +class EmacsMotionSuppressionView : public BView +{ + void + AttachedToWindow (void) + { + BView *text_view, *tooltip_view; + + /* We know that this view is a child of the text view, whose + parent is the tooltip view, and that the tooltip view has + already set its mouse event mask. */ + + text_view = Parent (); + + if (!text_view) + return; + + tooltip_view = text_view->Parent (); + + if (!tooltip_view) + return; + + tooltip_view->SetEventMask (B_KEYBOARD_EVENTS, 0); + } + +public: + EmacsMotionSuppressionView (void) : BView (BRect (-1, -1, 1, 1), + NULL, 0, 0) + { + return; + } +}; + static int32 start_running_application (void *data) { @@ -4320,36 +4341,46 @@ BView_set_tooltip (void *view, const char *tooltip) /* Set VIEW's tooltip to a sticky tooltip at X by Y. */ void -BView_set_and_show_sticky_tooltip (void *view, const char *tooltip_text, - int x, int y) +be_show_sticky_tooltip (void *view, const char *tooltip_text, + int x, int y) { BToolTip *tooltip; - BView *vw; - EmacsView *ev; - BPoint pt; + BView *vw, *tooltip_view; + BPoint point; vw = (BView *) view; if (!vw->LockLooper ()) gui_abort ("Failed to lock view while showing sticky tooltip"); + vw->SetToolTip ((const char *) NULL); + + /* If the tooltip text is empty, then a tooltip object won't be + created by SetToolTip. */ + if (tooltip_text[0] == '\0') + tooltip_text = " "; + vw->SetToolTip (tooltip_text); + tooltip = vw->ToolTip (); - ev = dynamic_cast (vw); + vw->GetMouse (&point, NULL, 1); + point.x -= x; + point.y -= y; - if (ev) - ev->tooltip_position = BPoint (x, y); + point.x = -point.x; + point.y = -point.y; - vw->GetMouse (&pt, NULL, 1); - pt.x -= x; - pt.y -= y; + /* We don't have to make the tooltip sticky since not receiving + mouse movement is enough to prevent it from being hidden. */ + tooltip->SetMouseRelativeLocation (point); - pt.x = -pt.x; - pt.y = -pt.y; + /* Prevent the tooltip from moving in response to mouse + movement. */ + tooltip_view = tooltip->View (); - tooltip->SetMouseRelativeLocation (pt); - tooltip->SetSticky (true); + if (tooltip_view) + tooltip_view->AddChild (new EmacsMotionSuppressionView); vw->ShowToolTip (tooltip); vw->UnlockLooper (); diff --git a/src/haiku_support.h b/src/haiku_support.h index d73f15560b..5f44494a8d 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -648,8 +648,7 @@ extern int32 BAlert_go (void *, void (*) (void), void (*) (void), extern void BButton_set_enabled (void *, int); extern void BView_set_tooltip (void *, const char *); extern void BView_show_tooltip (void *); -extern void BView_set_and_show_sticky_tooltip (void *, const char *, - int, int); +extern void be_show_sticky_tooltip (void *, const char *, int, int); extern void BAlert_delete (void *); diff --git a/src/haikufns.c b/src/haikufns.c index 878917eeef..e0a65b499f 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -2392,8 +2392,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, reliable way to get it. */ compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y); BView_convert_from_screen (FRAME_HAIKU_VIEW (f), &root_x, &root_y); - BView_set_and_show_sticky_tooltip (FRAME_HAIKU_VIEW (f), SSDATA (string), - root_x, root_y); + be_show_sticky_tooltip (FRAME_HAIKU_VIEW (f), SSDATA (string), + root_x, root_y); unblock_input (); goto start_timer; } commit bc015a7b44ab0803cfc35f69987eb28d9f4597e1 Author: Po Lu Date: Fri Jul 8 06:55:01 2022 +0000 Fix flickering system tooltips on Haiku * src/haiku_support.cc (class EmacsView, MouseMoved): Restore sticky status and mouse relative position. (BView_set_and_show_sticky_tooltip): * src/haikufns.c (haiku_hide_tip): Fix coding style. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 9e38d9556f..332321e2db 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1517,7 +1517,7 @@ class EmacsView : public BView BLocker cr_surface_lock; #endif - BPoint tt_absl_pos; + BPoint tooltip_position; BMessage *wait_for_release_message; EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", @@ -1798,11 +1798,16 @@ class EmacsView : public BView int32 windowid; EmacsWindow *window; BToolTip *tooltip; + BPoint target_tooltip_position; window = (EmacsWindow *) Window (); tooltip = ToolTip (); - rq.just_exited_p = transit == B_EXITED_VIEW; + if (transit == B_EXITED_VIEW) + rq.just_exited_p = true; + else + rq.just_exited_p = false; + rq.x = point.x; rq.y = point.y; rq.window = window; @@ -1817,8 +1822,14 @@ class EmacsView : public BView rq.dnd_message = false; if (tooltip) - tooltip->SetMouseRelativeLocation (BPoint (-(point.x - tt_absl_pos.x), - -(point.y - tt_absl_pos.y))); + { + target_tooltip_position + = BPoint (-(point.x - tooltip_position.x), + -(point.y - tooltip_position.y)); + tooltip->SetMouseRelativeLocation (target_tooltip_position); + tooltip->SetSticky (true); + ShowToolTip (tooltip); + } if (!grab_view_locker.Lock ()) gui_abort ("Couldn't lock grab view locker"); @@ -4309,19 +4320,26 @@ BView_set_tooltip (void *view, const char *tooltip) /* Set VIEW's tooltip to a sticky tooltip at X by Y. */ void -BView_set_and_show_sticky_tooltip (void *view, const char *tooltip, +BView_set_and_show_sticky_tooltip (void *view, const char *tooltip_text, int x, int y) { - BToolTip *tip; - BView *vw = (BView *) view; + BToolTip *tooltip; + BView *vw; + EmacsView *ev; + BPoint pt; + + vw = (BView *) view; + if (!vw->LockLooper ()) gui_abort ("Failed to lock view while showing sticky tooltip"); - vw->SetToolTip (tooltip); - tip = vw->ToolTip (); - BPoint pt; - EmacsView *ev = dynamic_cast (vw); + + vw->SetToolTip (tooltip_text); + tooltip = vw->ToolTip (); + + ev = dynamic_cast (vw); + if (ev) - ev->tt_absl_pos = BPoint (x, y); + ev->tooltip_position = BPoint (x, y); vw->GetMouse (&pt, NULL, 1); pt.x -= x; @@ -4330,9 +4348,10 @@ BView_set_and_show_sticky_tooltip (void *view, const char *tooltip, pt.x = -pt.x; pt.y = -pt.y; - tip->SetMouseRelativeLocation (pt); - tip->SetSticky (1); - vw->ShowToolTip (tip); + tooltip->SetMouseRelativeLocation (pt); + tooltip->SetSticky (true); + + vw->ShowToolTip (tooltip); vw->UnlockLooper (); } diff --git a/src/haikufns.c b/src/haikufns.c index b79443203f..878917eeef 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -1290,16 +1290,17 @@ compute_tip_xy (struct frame *f, static Lisp_Object haiku_hide_tip (bool delete) { + Lisp_Object it, frame; + if (!NILP (tip_timer)) { call1 (Qcancel_timer, tip_timer); tip_timer = Qnil; } - Lisp_Object it, frame; FOR_EACH_FRAME (it, frame) - if (FRAME_WINDOW_P (XFRAME (frame)) && - FRAME_HAIKU_VIEW (XFRAME (frame))) + if (FRAME_WINDOW_P (XFRAME (frame)) + && FRAME_HAIKU_VIEW (XFRAME (frame))) BView_set_tooltip (FRAME_HAIKU_VIEW (XFRAME (frame)), NULL); if (NILP (tip_frame) commit eb86a375e8ca75c297a1408aa6aa918f92914614 Author: Po Lu Date: Fri Jul 8 13:41:50 2022 +0800 Reduce synchronization setting frame alpha * src/xterm.c (x_set_frame_alpha): Don't synchronize while setting alpha property, and don't ask for the current value of the opacity property, which is much more expensive than changing it. diff --git a/src/xterm.c b/src/xterm.c index 094449e1d5..9651c4e119 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -6450,20 +6450,6 @@ x_set_frame_alpha (struct frame *f) unsigned long opac; Window parent; -#ifndef USE_XCB - unsigned char *data = NULL; - Atom actual; - int rc, format; - unsigned long n, left; - unsigned long value; -#else - xcb_get_property_cookie_t opacity_cookie; - xcb_get_property_reply_t *opacity_reply; - xcb_generic_error_t *error; - bool rc; - uint32_t value; -#endif - if (dpyinfo->highlight_frame == f) alpha = f->alpha[0]; else @@ -6484,8 +6470,6 @@ x_set_frame_alpha (struct frame *f) opac = alpha * OPAQUE; - x_catch_errors (dpy); - /* If there is a parent from the window manager, put the property there also, to work around broken window managers that fail to do that. Do this unconditionally as this function is called on reparent when @@ -6494,77 +6478,23 @@ x_set_frame_alpha (struct frame *f) if (!FRAME_PARENT_FRAME (f)) { parent = x_find_topmost_parent (f); + if (parent != None) - XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity, - XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) &opac, 1); + { + x_ignore_errors_for_next_request (dpyinfo); + XChangeProperty (dpy, parent, + dpyinfo->Xatom_net_wm_window_opacity, + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) &opac, 1); + x_stop_ignoring_errors (dpyinfo); + } } - /* return unless necessary */ - { -#ifndef USE_XCB - rc = XGetWindowProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, - 0, 1, False, XA_CARDINAL, - &actual, &format, &n, &left, - &data); - - if (rc == Success && actual != None - && n && format == XA_CARDINAL && data) - { - value = *(unsigned long *) data; - - /* Xlib sign-extends values greater than 0x7fffffff on 64-bit - machines. Get the low bits by ourself. */ - - value &= 0xffffffff; - - if (value == opac) - { - x_uncatch_errors (); - XFree (data); - return; - } - } - - if (data) - XFree (data); -#else - /* Avoid the confusing Xlib sign-extension mess by using XCB - instead. */ - opacity_cookie - = xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) win, - (xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity, - XCB_ATOM_CARDINAL, 0, 1); - opacity_reply - = xcb_get_property_reply (dpyinfo->xcb_connection, - opacity_cookie, &error); - - rc = opacity_reply; - - if (!opacity_reply) - free (error); - else - { - rc = (opacity_reply->format == 32 - && opacity_reply->type == XCB_ATOM_CARDINAL - && (xcb_get_property_value_length (opacity_reply) >= 4)); - - if (rc) - value = *(uint32_t *) xcb_get_property_value (opacity_reply); - } - - if (opacity_reply) - free (opacity_reply); - - if (rc && value == opac) - return; -#endif - } - + x_ignore_errors_for_next_request (dpyinfo); XChangeProperty (dpy, win, dpyinfo->Xatom_net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opac, 1); - x_uncatch_errors (); + x_stop_ignoring_errors (dpyinfo); } /*********************************************************************** commit 7397d0fd1910aee37c287bb02c5bb2b7811be860 Merge: b6a90b71a2 2ac0ddc4ac Author: Stefan Kangas Date: Fri Jul 8 06:31:54 2022 +0200 Merge from origin/emacs-28 2ac0ddc4ac ; * lisp/net/net-utils.el: Minor doc fixes. commit b6a90b71a2e421d3eef52d4d9e9a82592b7ad277 Author: Po Lu Date: Fri Jul 8 10:44:49 2022 +0800 Fix returned action symbol upon "xterm" drop * src/xterm.c (x_dnd_do_unsupported_drop): Set x_dnd_action_symbol. (x_dnd_begin_drag_and_drop): Don't clear it afterwards. diff --git a/src/xterm.c b/src/xterm.c index d057bbf06c..094449e1d5 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3921,6 +3921,8 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, True, ButtonReleaseMask, &event); x_stop_ignoring_errors (dpyinfo); + x_dnd_action_symbol = QXdndActionPrivate; + return; cancel: @@ -11873,8 +11875,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, XFIXNUM (Fnth (make_fixnum (4), x_dnd_unsupported_drop_data)), x_dnd_unsupported_drop_time); - - if (SYMBOLP (val)) + else if (SYMBOLP (val)) x_dnd_action_symbol = val; x_dnd_unwind_flag = false; commit 139eb1f845d1ec3e2a26aec5d7fafbcdcbaa5f07 Author: Stefan Kangas Date: Thu Jul 7 23:19:03 2022 +0200 * lisp/emacs-lisp/ert.el (Commentary): Refer to the Info manual. diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 262d85f9b4..21bee4c6d8 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -1,6 +1,6 @@ ;;; ert.el --- Emacs Lisp Regression Testing -*- lexical-binding: t -*- -;; Copyright (C) 2007-2008, 2010-2022 Free Software Foundation, Inc. +;; Copyright (C) 2007-2022 Free Software Foundation, Inc. ;; Author: Christian Ohler ;; Keywords: lisp, tools @@ -46,12 +46,10 @@ ;; processing further, this is useful for checking the test ;; environment (like availability of features, external binaries, etc). ;; -;; See ERT's info manual as well as the docstrings for more details. -;; -;; To see some examples of tests written in ERT, see its self-tests in -;; ert-tests.el. Some of these are tricky due to the bootstrapping -;; problem of writing tests for a testing tool, others test simple -;; functions and are straightforward. +;; See ERT's Info manual `(ert) Top' as well as the docstrings for +;; more details. To see some examples of tests written in ERT, see +;; the test suite distributed with the Emacs source distribution (in +;; the "test" directory). ;;; Code: commit cbfd959e26da13ae872ee11a1c8365abd6906d96 Author: Stefan Kangas Date: Thu Jul 7 17:25:39 2022 +0200 Prefer keymap inheritance in shr-image-map * lisp/net/shr.el (shr-image-map): Replace copy-keymap with inheritance. diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 63f313bbf4..c4f0d3b940 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -290,11 +290,10 @@ and other things: "O" #'shr-save-contents "RET" #'shr-browse-url) -(defvar shr-image-map - (let ((map (copy-keymap shr-map))) - (when (boundp 'image-map) - (set-keymap-parent map image-map)) - map)) +(defvar-keymap shr-image-map + :parent (if (boundp 'image-map) + (make-composed-keymap shr-map image-map) + shr-map)) ;; Public functions and commands. (declare-function libxml-parse-html-region "xml.c" commit a371298d2a2fd1c24f29c6c4ca8026a62f5bdd33 Author: Lars Ingebrigtsen Date: Thu Jul 7 20:21:38 2022 +0200 Make imenu--create-keymap more resilient * lisp/imenu.el (imenu--create-keymap): Ignore nil items in the alist (bug#56430). diff --git a/lisp/imenu.el b/lisp/imenu.el index 040e373fb4..dcd816cb7a 100644 --- a/lisp/imenu.el +++ b/lisp/imenu.el @@ -471,7 +471,7 @@ Non-nil arguments are in recursive calls." (t (lambda () (interactive) (if cmd (funcall cmd item) item)))))) - alist))) + (seq-filter #'identity alist)))) (defun imenu--in-alist (str alist) "Check whether the string STR is contained in multi-level ALIST." commit d397b0421567e4e52bccfa15dc23f4a9b8e6e9f0 Author: Eli Zaretskii Date: Thu Jul 7 19:34:30 2022 +0300 Fix buffer-tests * test/src/buffer-tests.el (test-restore-buffer-modified-p): Don't assume turning on auto-save-mode cannot auto-save immediately. diff --git a/test/src/buffer-tests.el b/test/src/buffer-tests.el index 13d48b31a4..cba10a0502 100644 --- a/test/src/buffer-tests.el +++ b/test/src/buffer-tests.el @@ -1503,9 +1503,12 @@ with parameters from the *Messages* buffer modification." (ert-deftest test-restore-buffer-modified-p () (ert-with-temp-file file + ;; This avoids the annoying "foo and bar are the same file" on + ;; MS-Windows. + (setq file (file-truename file)) (with-current-buffer (find-file file) (auto-save-mode 1) - (should-not (buffer-modified-p)) + (should-not (eq (buffer-modified-p) t)) (insert "foo") (should (buffer-modified-p)) (restore-buffer-modified-p nil) @@ -1522,9 +1525,10 @@ with parameters from the *Messages* buffer modification." (delete-file buffer-auto-save-file-name)))) (ert-with-temp-file file + (setq file (file-truename file)) (with-current-buffer (find-file file) (auto-save-mode 1) - (should-not (buffer-modified-p)) + (should-not (eq (buffer-modified-p) t)) (insert "foo") (should (buffer-modified-p)) (should-not (eq (buffer-modified-p) 'autosaved)) commit 53c0690fa28f338071703f1567d2d1c4054416f0 Author: Mattias Engdegård Date: Wed Jan 26 12:30:39 2022 +0100 Faster append and vconcat By separating the code paths for append and vconcat, each becomes simpler and faster. * src/fns.c (concat_strings): Rename to... (concat_to_string): ...this. (concat): Split into concat_to_list and concat_to_vector. (concat_to_list, concat_to_vector): New, specialised and streamlined from earlier combined code. (concat2, concat3, Fappend, Fconcat, Fvconcat): Adjust calls. diff --git a/src/fns.c b/src/fns.c index f30b2f6fb3..f4ba67b40e 100644 --- a/src/fns.c +++ b/src/fns.c @@ -589,20 +589,21 @@ Do NOT use this function to compare file names for equality. */) #endif /* !__STDC_ISO_10646__, !WINDOWSNT */ } -static Lisp_Object concat (ptrdiff_t nargs, Lisp_Object *args, - Lisp_Object last_tail, bool vector_target); -static Lisp_Object concat_strings (ptrdiff_t nargs, Lisp_Object *args); +static Lisp_Object concat_to_list (ptrdiff_t nargs, Lisp_Object *args, + Lisp_Object last_tail); +static Lisp_Object concat_to_vector (ptrdiff_t nargs, Lisp_Object *args); +static Lisp_Object concat_to_string (ptrdiff_t nargs, Lisp_Object *args); Lisp_Object concat2 (Lisp_Object s1, Lisp_Object s2) { - return concat_strings (2, ((Lisp_Object []) {s1, s2})); + return concat_to_string (2, ((Lisp_Object []) {s1, s2})); } Lisp_Object concat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3) { - return concat_strings (3, ((Lisp_Object []) {s1, s2, s3})); + return concat_to_string (3, ((Lisp_Object []) {s1, s2, s3})); } DEFUN ("append", Fappend, Sappend, 0, MANY, 0, @@ -615,7 +616,7 @@ usage: (append &rest SEQUENCES) */) { if (nargs == 0) return Qnil; - return concat (nargs - 1, args, args[nargs - 1], false); + return concat_to_list (nargs - 1, args, args[nargs - 1]); } DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0, @@ -628,7 +629,7 @@ to be `eq'. usage: (concat &rest SEQUENCES) */) (ptrdiff_t nargs, Lisp_Object *args) { - return concat_strings (nargs, args); + return concat_to_string (nargs, args); } DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0, @@ -638,7 +639,7 @@ Each argument may be a list, vector or string. usage: (vconcat &rest SEQUENCES) */) (ptrdiff_t nargs, Lisp_Object *args) { - return concat (nargs, args, Qnil, true); + return concat_to_vector (nargs, args); } @@ -706,8 +707,8 @@ the same empty object instead of its copy. */) wrong_type_argument (Qsequencep, arg); } -/* This structure holds information of an argument of `concat_strings' that is - a string and has text properties to be copied. */ +/* This structure holds information of an argument of `concat_to_string' + that is a string and has text properties to be copied. */ struct textprop_rec { ptrdiff_t argnum; /* refer to ARGS (arguments of `concat') */ @@ -716,7 +717,7 @@ struct textprop_rec }; static Lisp_Object -concat_strings (ptrdiff_t nargs, Lisp_Object *args) +concat_to_string (ptrdiff_t nargs, Lisp_Object *args) { USE_SAFE_ALLOCA; @@ -912,19 +913,100 @@ concat_strings (ptrdiff_t nargs, Lisp_Object *args) return result; } -/* Concatenate sequences into a list or vector. */ +/* Concatenate sequences into a list. */ +Lisp_Object +concat_to_list (ptrdiff_t nargs, Lisp_Object *args, Lisp_Object last_tail) +{ + /* Copy the contents of the args into the result. */ + Lisp_Object result = Qnil; + Lisp_Object last = Qnil; /* Last cons in result if nonempty. */ + + for (ptrdiff_t i = 0; i < nargs; i++) + { + Lisp_Object arg = args[i]; + /* List arguments are treated specially since this is the common case. */ + if (CONSP (arg)) + { + Lisp_Object head = Fcons (XCAR (arg), Qnil); + Lisp_Object prev = head; + arg = XCDR (arg); + FOR_EACH_TAIL (arg) + { + Lisp_Object next = Fcons (XCAR (arg), Qnil); + XSETCDR (prev, next); + prev = next; + } + CHECK_LIST_END (arg, arg); + if (NILP (result)) + result = head; + else + XSETCDR (last, head); + last = prev; + } + else if (NILP (arg)) + ; + else if (VECTORP (arg) || STRINGP (arg) + || BOOL_VECTOR_P (arg) || COMPILEDP (arg)) + { + ptrdiff_t arglen = XFIXNUM (Flength (arg)); + ptrdiff_t argindex_byte = 0; + /* Copy element by element. */ + for (ptrdiff_t argindex = 0; argindex < arglen; argindex++) + { + /* Fetch next element of `arg' arg into `elt', or break if + `arg' is exhausted. */ + Lisp_Object elt; + if (STRINGP (arg)) + { + int c; + if (STRING_MULTIBYTE (arg)) + { + ptrdiff_t char_idx = argindex; + c = fetch_string_char_advance_no_check (arg, &char_idx, + &argindex_byte); + } + else + c = SREF (arg, argindex); + elt = make_fixed_natnum (c); + } + else if (BOOL_VECTOR_P (arg)) + elt = bool_vector_ref (arg, argindex); + else + elt = AREF (arg, argindex); + + /* Store this element into the result. */ + Lisp_Object node = Fcons (elt, Qnil); + if (NILP (result)) + result = node; + else + XSETCDR (last, node); + last = node; + } + } + else + wrong_type_argument (Qsequencep, arg); + } + + if (NILP (result)) + result = last_tail; + else + XSETCDR (last, last_tail); + + return result; +} + +/* Concatenate sequences into a vector. */ Lisp_Object -concat (ptrdiff_t nargs, Lisp_Object *args, Lisp_Object last_tail, - bool vector_target) +concat_to_vector (ptrdiff_t nargs, Lisp_Object *args) { /* Check argument types and compute total length of arguments. */ EMACS_INT result_len = 0; for (ptrdiff_t i = 0; i < nargs; i++) { Lisp_Object arg = args[i]; - if (!(CONSP (arg) || NILP (arg) || VECTORP (arg) || STRINGP (arg) - || COMPILEDP (arg) || BOOL_VECTOR_P (arg))) + if (!(VECTORP (arg) || CONSP (arg) || NILP (arg) || STRINGP (arg) + || BOOL_VECTOR_P (arg) || COMPILEDP (arg))) wrong_type_argument (Qsequencep, arg); EMACS_INT len = XFIXNAT (Flength (arg)); result_len += len; @@ -932,90 +1014,61 @@ concat (ptrdiff_t nargs, Lisp_Object *args, Lisp_Object last_tail, memory_full (SIZE_MAX); } - /* When the target is a list, return the tail directly if all other - arguments are empty. */ - if (!vector_target && result_len == 0) - return last_tail; - - /* Create the output object. */ - Lisp_Object result = vector_target - ? make_nil_vector (result_len) - : Fmake_list (make_fixnum (result_len), Qnil); + /* Create the output vector. */ + Lisp_Object result = make_uninit_vector (result_len); + Lisp_Object *dst = XVECTOR (result)->contents; /* Copy the contents of the args into the result. */ - Lisp_Object tail = Qnil; - ptrdiff_t toindex = 0; - if (CONSP (result)) - { - tail = result; - toindex = -1; /* -1 in toindex is flag we are making a list */ - } - - Lisp_Object prev = Qnil; for (ptrdiff_t i = 0; i < nargs; i++) { - ptrdiff_t arglen = 0; - ptrdiff_t argindex = 0; - ptrdiff_t argindex_byte = 0; - Lisp_Object arg = args[i]; - if (!CONSP (arg)) - arglen = XFIXNUM (Flength (arg)); - - /* Copy element by element. */ - while (1) + if (VECTORP (arg)) { - /* Fetch next element of `arg' arg into `elt', or break if - `arg' is exhausted. */ - Lisp_Object elt; - if (CONSP (arg)) - { - elt = XCAR (arg); - arg = XCDR (arg); - } - else if (NILP (arg) || argindex >= arglen) - break; - else if (STRINGP (arg)) + ptrdiff_t size = ASIZE (arg); + memcpy (dst, XVECTOR (arg)->contents, size * sizeof *dst); + dst += size; + } + else if (CONSP (arg)) + do + { + *dst++ = XCAR (arg); + arg = XCDR (arg); + } + while (!NILP (arg)); + else if (NILP (arg)) + ; + else if (STRINGP (arg)) + { + ptrdiff_t size = SCHARS (arg); + if (STRING_MULTIBYTE (arg)) { - int c; - if (STRING_MULTIBYTE (arg)) - c = fetch_string_char_advance_no_check (arg, &argindex, - &argindex_byte); - else + ptrdiff_t byte = 0; + for (ptrdiff_t i = 0; i < size;) { - c = SREF (arg, argindex); - argindex++; + int c = fetch_string_char_advance_no_check (arg, &i, &byte); + *dst++ = make_fixnum (c); } - XSETFASTINT (elt, c); - } - else if (BOOL_VECTOR_P (arg)) - { - elt = bool_vector_ref (arg, argindex); - argindex++; - } - else - { - elt = AREF (arg, argindex); - argindex++; - } - - /* Store this element into the result. */ - if (toindex < 0) - { - XSETCAR (tail, elt); - prev = tail; - tail = XCDR (tail); } else - { - ASET (result, toindex, elt); - toindex++; - } + for (ptrdiff_t i = 0; i < size; i++) + *dst++ = make_fixnum (SREF (arg, i)); + } + else if (BOOL_VECTOR_P (arg)) + { + ptrdiff_t size = bool_vector_size (arg); + for (ptrdiff_t i = 0; i < size; i++) + *dst++ = bool_vector_ref (arg, i); + } + else + { + eassert (COMPILEDP (arg)); + ptrdiff_t size = PVSIZE (arg); + memcpy (dst, XVECTOR (arg)->contents, size * sizeof *dst); + dst += size; } } - if (!NILP (prev)) - XSETCDR (prev, last_tail); + eassert (dst == XVECTOR (result)->contents + result_len); return result; } commit 9cd72b02b67e92e89b83791b66fe40c4b50d8357 Author: Alan Mackenzie Date: Thu Jul 7 15:38:09 2022 +0000 Remove obscure, obsolete code from do_switch_frame This is relevant for bug #56305, and might solve that bug. The code being removed went into Emacs between 1992 and 1994, and looks to have been a workaround for switching frames, before the command 'other-frame' had been written. Nowadays, that code has harmful effects, causing frames' focus to be redirected at random, sometimes back to the frame itself. * src/frame.c (do_switch_frame): Remove 53 lines of code. diff --git a/src/frame.c b/src/frame.c index 02c90ea651..4828595b93 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1477,59 +1477,6 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor else if (f == sf) return frame; - /* If a frame's focus has been redirected toward the currently - selected frame, we should change the redirection to point to the - newly selected frame. This means that if the focus is redirected - from a minibufferless frame to a surrogate minibuffer frame, we - can use `other-window' to switch between all the frames using - that minibuffer frame, and the focus redirection will follow us - around. */ -#if 0 - /* This is too greedy; it causes inappropriate focus redirection - that's hard to get rid of. */ - if (track) - { - Lisp_Object tail; - - for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail)) - { - Lisp_Object focus; - - if (!FRAMEP (XCAR (tail))) - emacs_abort (); - - focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail))); - - if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ()) - Fredirect_frame_focus (XCAR (tail), frame); - } - } -#else /* ! 0 */ - /* Instead, apply it only to the frame we're pointing to. */ -#ifdef HAVE_WINDOW_SYSTEM - if (track && FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->get_focus_frame) - { - Lisp_Object focus, gfocus; - - gfocus = FRAME_TERMINAL (f)->get_focus_frame (f); - if (FRAMEP (gfocus)) - { - focus = FRAME_FOCUS_FRAME (XFRAME (gfocus)); - if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ()) - /* Redirect frame focus also when FRAME has its minibuffer - window on the selected frame (see Bug#24500). - - Don't do that: It causes redirection problem with a - separate minibuffer frame (Bug#24803) and problems - when updating the cursor on such frames. - || (NILP (focus) - && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window))) */ - Fredirect_frame_focus (gfocus, frame); - } - } -#endif /* HAVE_X_WINDOWS */ -#endif /* ! 0 */ - if (!for_deletion && FRAME_HAS_MINIBUF_P (sf)) resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1); commit f32808ce98d0612bc5ad949f41563001768ab87a Author: Stefan Kangas Date: Thu Jul 7 15:32:48 2022 +0200 * lisp/net/dig.el (dig): Provide default. diff --git a/lisp/net/dig.el b/lisp/net/dig.el index 0ac6399e87..7157d0cb58 100644 --- a/lisp/net/dig.el +++ b/lisp/net/dig.el @@ -154,10 +154,12 @@ for the QUERY-TYPE parameter. If given a \\[universal-argument] \\[universal-argument] \ prefix, also prompt for the SERVER parameter." (interactive - (list (read-string "Host: ") + (list (let ((default (ffap-machine-at-point))) + (read-string (format-prompt "Host" default) nil nil default)) (and current-prefix-arg (read-string "Query type: ")))) - (when (>= (car current-prefix-arg) 16) + (when (and (numberp (car current-prefix-arg)) + (>= (car current-prefix-arg) 16)) (let ((serv (read-from-minibuffer "Name server: "))) (when (not (equal serv "")) (setq server serv)))) commit 6d95b4e6ec35c11820e5733a3a13c05d2debc68a Author: Stefan Kangas Date: Thu Jul 7 14:54:16 2022 +0200 Make net-utils-url at point funs obsolete in favor of ffap * lisp/net/net-utils.el (net-utils-machine-at-point) (net-utils-url-at-point): Redefine as obsolete function alias for 'ffap-machine-at-point' and 'ffap-url-at-point'. Update callers. * lisp/ffap.el (ffap-machine-at-point, ffap-url-at-point): Autoload. diff --git a/lisp/ffap.el b/lisp/ffap.el index ae86e55490..8628222936 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -544,6 +544,7 @@ The optional NOMODIFY argument suppresses the extra search." (string-match ffap-rfs-regexp filename) filename))) +;;;###autoload (defun ffap-machine-at-point () "Return machine name at point if it exists, or nil." (let ((mach (ffap-string-at-point 'machine))) @@ -1329,6 +1330,7 @@ Assumes the buffer has not changed." ;; External. (declare-function w3-view-this-url "ext:w3" (&optional no-show)) +;;;###autoload (defun ffap-url-at-point () "Return URL from around point if it exists, or nil. diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index 016fdec921..ab7770e04a 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el @@ -280,31 +280,6 @@ This variable is only used if the variable ;; Utility functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Simplified versions of some at-point functions from ffap.el. -;; It's not worth loading all of ffap just for these. -(defun net-utils-machine-at-point () - (let ((pt (point))) - (buffer-substring-no-properties - (save-excursion - (skip-chars-backward "-a-zA-Z0-9.") - (point)) - (save-excursion - (skip-chars-forward "-a-zA-Z0-9.") - (skip-chars-backward "." pt) - (point))))) - -(defun net-utils-url-at-point () - (let ((pt (point))) - (buffer-substring-no-properties - (save-excursion - (skip-chars-backward "--:=&?$+@-Z_a-z~#,%") - (skip-chars-forward "^A-Za-z0-9" pt) - (point)) - (save-excursion - (skip-chars-forward "--:=&?$+@-Z_a-z~#,%") - (skip-chars-backward ":;.,!?" pt) - (point))))) - (defun net-utils-remove-ctrl-m-filter (process output-string) "Remove trailing control Ms." (with-current-buffer (process-buffer process) @@ -456,7 +431,7 @@ This variable is only used if the variable If your system's ping continues until interrupted, you can try setting `ping-program-options'." (interactive - (list (read-from-minibuffer "Ping host: " (net-utils-machine-at-point)))) + (list (read-from-minibuffer "Ping host: " (ffap-machine-at-point)))) (let ((options (if ping-program-options (append ping-program-options (list host)) @@ -489,7 +464,7 @@ See also: `nslookup-host-ipv4', `nslookup-host-ipv6' for non-interactive versions of this function more suitable for use in Lisp code." (interactive - (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) + (list (read-from-minibuffer "Lookup host: " (ffap-machine-at-point)) (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (let ((options (append nslookup-program-options (list host) @@ -601,7 +576,7 @@ Interactively, prompt for NAME-SERVER if invoked with prefix argument. This command uses `dns-lookup-program' for looking up the DNS information." (interactive - (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) + (list (read-from-minibuffer "Lookup host: " (ffap-machine-at-point)) (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (let ((options (append dns-lookup-program-options (list host) @@ -625,7 +600,7 @@ Interactively, prompt for NAME-SERVER if invoked with prefix argument. This command uses `dig-program' for looking up the DNS information." (declare (obsolete dig "29.1")) (interactive - (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) + (list (read-from-minibuffer "Lookup host: " (ffap-machine-at-point)) (if current-prefix-arg (read-from-minibuffer "Name server: ")))) (dig host nil nil nil nil name-server)) @@ -639,7 +614,7 @@ This command uses `dig-program' for looking up the DNS information." (interactive (list (read-from-minibuffer - "Ftp to Host: " (net-utils-machine-at-point)))) + "Ftp to Host: " (ffap-machine-at-point)))) (let ((buf (get-buffer-create (concat "*ftp [" host "]*")))) (set-buffer buf) (ftp-mode) @@ -675,7 +650,7 @@ This command uses `smbclient-program' to connect to HOST." (interactive (list (read-from-minibuffer - "Connect to Host: " (net-utils-machine-at-point)) + "Connect to Host: " (ffap-machine-at-point)) (read-from-minibuffer "SMB Service: "))) (let* ((name (format "smbclient [%s\\%s]" host service)) (buf (get-buffer-create (concat "*" name "*"))) @@ -694,7 +669,7 @@ This command uses `smbclient-program' to connect to HOST." (interactive (list (read-from-minibuffer - "Connect to Host: " (net-utils-machine-at-point)))) + "Connect to Host: " (ffap-machine-at-point)))) (let ((buf (get-buffer-create (format "*SMB Shares on %s*" host)))) (set-buffer buf) (smbclient-mode) @@ -794,14 +769,14 @@ and `network-connection-service-alist', which see." ;; host name. If we don't see an "@", we'll prompt for the host. (interactive (let* ((answer (read-from-minibuffer "Finger User: " - (net-utils-url-at-point))) + (ffap-url-at-point))) (index (string-match (regexp-quote "@") answer))) (if index (list (substring answer 0 index) (substring answer (1+ index))) (list answer (read-from-minibuffer "At Host: " - (net-utils-machine-at-point)))))) + (ffap-machine-at-point)))))) (let* ((user-and-host (concat user "@" host)) (process-name (concat "Finger [" user-and-host "]")) (regexps finger-X.500-host-regexps) @@ -934,7 +909,7 @@ The port is deduced from `network-connection-service-alist'." This command uses `network-connection-service-alist', which see." (interactive (list - (read-from-minibuffer "Host: " (net-utils-machine-at-point)) + (read-from-minibuffer "Host: " (ffap-machine-at-point)) (completing-read "Service: " (mapcar (lambda (elt) @@ -987,6 +962,9 @@ This command uses `network-connection-service-alist', which see." (and old-comint-input-ring (setq comint-input-ring old-comint-input-ring))))) +(define-obsolete-function-alias 'net-utils-machine-at-point #'ffap-machine-at-point "29.1") +(define-obsolete-function-alias 'net-utils-url-at-point #'ffap-url-at-point "29.1") + (provide 'net-utils) ;;; net-utils.el ends here commit 1fa5f0428fc9f141d7ae9973a9cc92c3e6a2b623 Author: Po Lu Date: Thu Jul 7 21:12:49 2022 +0800 Fix selection disowning upon frame deletion on Wayland * src/pgtkselect.c (pgtk_clear_frame_selections): Manually disown cleared selections. (bug#56434) diff --git a/src/pgtkselect.c b/src/pgtkselect.c index fff163c92a..e0230003b3 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -790,8 +790,8 @@ pgtk_handle_selection_event (struct selection_input_event *event) void pgtk_clear_frame_selections (struct frame *f) { - Lisp_Object frame; - Lisp_Object rest; + Lisp_Object frame, rest, timestamp, symbol; + guint32 time; struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); struct terminal *t = dpyinfo->terminal; @@ -801,9 +801,22 @@ pgtk_clear_frame_selections (struct frame *f) while (CONSP (t->Vselection_alist) && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist))))))) { + symbol = Fcar (Fcar (t->Vselection_alist)); + /* Run the `pgtk-lost-selection-functions' abnormal hook. */ CALLN (Frun_hook_with_args, Qpgtk_lost_selection_functions, - Fcar (Fcar (t->Vselection_alist))); + symbol); + + timestamp = Fcar (Fcdr (Fcdr (Fcar (t->Vselection_alist)))); + CONS_TO_INTEGER (timestamp, guint32, time); + + /* On Wayland, GDK will still ask the (now non-existent) frame for + selection data, even though we no longer think the selection is + owned by us. Manually relinquish ownership of the selection. */ + gdk_selection_owner_set_for_display (dpyinfo->display, + NULL, + symbol_to_gdk_atom (symbol), + time, TRUE); tset_selection_alist (t, XCDR (t->Vselection_alist)); } @@ -813,8 +826,18 @@ pgtk_clear_frame_selections (struct frame *f) if (CONSP (XCDR (rest)) && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest)))))))) { + symbol = XCAR (XCAR (XCDR (rest))); CALLN (Frun_hook_with_args, Qpgtk_lost_selection_functions, - XCAR (XCAR (XCDR (rest)))); + symbol); + + timestamp = XCAR (XCDR (XCDR (XCAR (XCDR (rest))))); + CONS_TO_INTEGER (timestamp, guint32, time); + + gdk_selection_owner_set_for_display (dpyinfo->display, + NULL, + symbol_to_gdk_atom (symbol), + time, TRUE); + XSETCDR (rest, XCDR (XCDR (rest))); break; } commit 0aa0dac799d692bac36a379c40bd178cff6cb80b Author: Stefan Kangas Date: Thu Jul 7 14:43:46 2022 +0200 * lisp/net/eww.el (eww-browse-url): Add 'browser-kind' property. diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 1671e062b2..995a755135 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -1207,6 +1207,8 @@ instead of `browse-url-new-window-flag'." (let ((url-allow-non-local-files t)) (eww url))) +(function-put 'eww-browse-url 'browse-url-browser-kind 'internal) + (defun eww-back-url () "Go to the previously displayed page." (interactive nil eww-mode) commit 49b10a95c3b7e5bf61b881d34467e0b5f4c68eca Author: Stefan Kangas Date: Thu Jul 7 13:21:07 2022 +0200 * lisp/woman.el (woman): Fix comment; don't mention gnudoit. diff --git a/lisp/woman.el b/lisp/woman.el index 73e068a822..6bb775115a 100644 --- a/lisp/woman.el +++ b/lisp/woman.el @@ -1151,7 +1151,7 @@ updated (e.g. to re-interpret the current directory). Used non-interactively, arguments are optional: if given then TOPIC should be a topic string and non-nil RE-CACHE forces re-caching." (interactive (list nil current-prefix-arg)) - ;; The following test is for non-interactive calls via gnudoit etc. + ;; The following test is for non-interactive calls via emacsclient, etc. (if (or (not (stringp topic)) (string-match-p "\\S " topic)) (let ((file-name (woman-file-name topic re-cache))) (if file-name commit 9155f2ada3e2a290a0d0bfc99ee0a0426902f6df Author: Stefan Kangas Date: Thu Jul 7 13:18:01 2022 +0200 Make two XEmacs related variables obsolete * lisp/net/browse-url.el (browse-url-gnudoit-program) (browse-url-gnudoit-args): Make obsolete. The corresponding command 'browse-url-w3-gnudoit' is already obsolete since 25.1. diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 1cfe90895f..7cffe3e32e 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -437,11 +437,13 @@ These might set its size, for instance." (defcustom browse-url-gnudoit-program "gnudoit" "The name of the `gnudoit' program used by `browse-url-w3-gnudoit'." :type 'string) +(make-obsolete-variable 'browse-url-gnudoit-program nil "29.1") (defcustom browse-url-gnudoit-args '("-q") "A list of strings defining options for `browse-url-gnudoit-program'. These might set the port, for instance." :type '(repeat (string :tag "Argument"))) +(make-obsolete-variable 'browse-url-gnudoit-args nil "29.1") (defcustom browse-url-generic-program nil "The name of the browser program used by `browse-url-generic'." commit 59a798b3f0bd91e6112c080a8c80c22998e8ee3e Author: Po Lu Date: Thu Jul 7 20:16:43 2022 +0800 Fix GTK build * src/xterm.c (x_dnd_begin_drag_and_drop): Update GTK quitting code for last change too. Reported by Norbert Koch . diff --git a/src/xterm.c b/src/xterm.c index 98a5beed17..d057bbf06c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11889,55 +11889,10 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (xg_pending_quit_event.kind != NO_EVENT) { xg_pending_quit_event.kind = NO_EVENT; - - if (x_dnd_in_progress) - { - if (x_dnd_last_seen_window != None - && x_dnd_last_protocol_version != -1) - x_dnd_send_leave (f, x_dnd_last_seen_window); - else if (x_dnd_last_seen_window != None - && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) - && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE - && x_dnd_motif_setup_p) - { - dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, - XM_DRAG_REASON_DROP_START); - dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; - dmsg.timestamp = xg_pending_quit_event.timestamp; - dmsg.side_effects - = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), - x_dnd_wanted_action), - XM_DROP_SITE_VALID, x_dnd_motif_operations, - XM_DROP_ACTION_DROP_CANCEL); - dmsg.x = 0; - dmsg.y = 0; - dmsg.index_atom = x_dnd_motif_atom; - dmsg.source_window = FRAME_X_WINDOW (f); - - x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, - x_dnd_last_seen_window, - xg_pending_quit_event.timestamp); - xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), - x_dnd_last_seen_window, &dmsg); - } - - x_dnd_end_window = x_dnd_last_seen_window; - x_dnd_last_seen_window = None; - x_dnd_last_seen_toplevel = None; - x_dnd_in_progress = false; - x_dnd_frame = NULL; - } - - x_dnd_waiting_for_finish = false; - x_dnd_return_frame_object = NULL; - x_dnd_movement_frame = NULL; - - FRAME_DISPLAY_INFO (f)->grabbed = 0; current_hold_quit = NULL; - /* Restore the old event mask. */ + x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time); x_restore_events_after_dnd (f, &root_window_attrs); - quit (); } #else commit 7a9f8ed6fba0d6728cbf185696bdc1a95b1acfea Author: Po Lu Date: Thu Jul 7 18:36:56 2022 +0800 Fix quitting out of selection converters during drag and drop * src/xterm.c (x_dnd_process_quit): New function. (x_dnd_begin_drag_and_drop): Use it instead. Also quit if quit-flag is true immediately after a selection converter is run. diff --git a/src/xterm.c b/src/xterm.c index a21daa2dfc..98a5beed17 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11362,6 +11362,57 @@ x_dnd_lose_ownership (Lisp_Object timestamp_and_frame) XCDR (timestamp_and_frame)); } +/* Clean up an existing drag-and-drop operation in preparation for its + sudden termination. */ + +static void +x_dnd_process_quit (struct frame *f, Time timestamp) +{ + xm_drop_start_message dmsg; + + if (x_dnd_in_progress) + { + if (x_dnd_last_seen_window != None + && x_dnd_last_protocol_version != -1) + x_dnd_send_leave (f, x_dnd_last_seen_window); + else if (x_dnd_last_seen_window != None + && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) + && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE + && x_dnd_motif_setup_p) + { + dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, + XM_DRAG_REASON_DROP_START); + dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; + dmsg.timestamp = timestamp; + dmsg.side_effects + = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), + x_dnd_wanted_action), + XM_DROP_SITE_VALID, x_dnd_motif_operations, + XM_DROP_ACTION_DROP_CANCEL); + dmsg.x = 0; + dmsg.y = 0; + dmsg.index_atom = x_dnd_motif_atom; + dmsg.source_window = FRAME_X_WINDOW (f); + + x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, + x_dnd_last_seen_window, + timestamp); + xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), + x_dnd_last_seen_window, &dmsg); + } + + x_dnd_end_window = x_dnd_last_seen_window; + x_dnd_last_seen_window = None; + x_dnd_last_seen_toplevel = None; + x_dnd_in_progress = false; + x_dnd_frame = NULL; + } + + x_dnd_waiting_for_finish = false; + x_dnd_return_frame_object = NULL; + x_dnd_movement_frame = NULL; +} + /* This function is defined far away from the rest of the XDND code so it can utilize `x_any_window_to_frame'. */ @@ -11398,7 +11449,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, specpdl_ref ref, count, base; ptrdiff_t i, end, fill; XTextProperty prop; - xm_drop_start_message dmsg; Lisp_Object frame_object, x, y, frame, local_value; bool signals_were_pending, need_sync; #ifdef HAVE_XKB @@ -11750,50 +11800,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (hold_quit.kind != NO_EVENT) { - if (x_dnd_in_progress) - { - if (x_dnd_last_seen_window != None - && x_dnd_last_protocol_version != -1) - x_dnd_send_leave (f, x_dnd_last_seen_window); - else if (x_dnd_last_seen_window != None - && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) - && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE - && x_dnd_motif_setup_p) - { - dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, - XM_DRAG_REASON_DROP_START); - dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; - dmsg.timestamp = hold_quit.timestamp; - dmsg.side_effects - = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), - x_dnd_wanted_action), - XM_DROP_SITE_VALID, x_dnd_motif_operations, - XM_DROP_ACTION_DROP_CANCEL); - dmsg.x = 0; - dmsg.y = 0; - dmsg.index_atom = x_dnd_motif_atom; - dmsg.source_window = FRAME_X_WINDOW (f); - - x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, - x_dnd_last_seen_window, - hold_quit.timestamp); - xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), - x_dnd_last_seen_window, &dmsg); - } - - x_dnd_end_window = x_dnd_last_seen_window; - x_dnd_last_seen_window = None; - x_dnd_last_seen_toplevel = None; - x_dnd_in_progress = false; - x_dnd_frame = NULL; - } - - x_dnd_waiting_for_finish = false; - x_dnd_return_frame_object = NULL; - x_dnd_movement_frame = NULL; - - /* Don't clear dpyinfo->grabbed if we're quitting. */ - + x_dnd_process_quit (f, hold_quit.timestamp); #ifdef USE_GTK current_hold_quit = NULL; #endif @@ -11821,6 +11828,19 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, unbind_to (ref, Qnil); } + /* Sometimes C-g can be pressed inside a selection + converter, where quitting is inhibited. We want + to quit after the converter exits. */ + if (!NILP (Vquit_flag) && !NILP (Vinhibit_quit)) + { + x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time); +#ifdef USE_GTK + current_hold_quit = NULL; +#endif + x_restore_events_after_dnd (f, &root_window_attrs); + quit (); + } + if (x_dnd_run_unsupported_drop_function && x_dnd_waiting_for_finish) { commit a40a4d3a0964f0428033744f77b67376700e963f Author: Stefan Kangas Date: Thu Jul 7 12:05:35 2022 +0200 Mark comint modes in net-utils.el as non-interactive * lisp/net/net-utils.el (net-utils-mode, nslookup-mode, ftp-mode) (smbclient-mode, network-connection-mode): Mark as non-interactive. (nslookup-mode-map, ftp-mode-map): Prefer defvar-keymap. diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index ea1dd0f3ca..016fdec921 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el @@ -271,6 +271,7 @@ This variable is only used if the variable (define-derived-mode net-utils-mode special-mode "NetworkUtil" "Major mode for interacting with an external network utility." + :interactive nil (setq-local font-lock-defaults '((net-utils-font-lock-keywords))) (setq-local revert-buffer-function #'net-utils--revert-function)) @@ -580,14 +581,12 @@ This command uses `nslookup-program' to look up DNS records." (autoload 'comint-mode "comint" nil t) -(defvar nslookup-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\t" #'completion-at-point) - map)) +(defvar-keymap nslookup-mode-map + "TAB" #'completion-at-point) -;; Using a derived mode gives us keymaps, hooks, etc. (define-derived-mode nslookup-mode comint-mode "Nslookup" "Major mode for interacting with the nslookup program." + :interactive nil (setq-local font-lock-defaults '((nslookup-font-lock-keywords))) (setq comint-prompt-regexp nslookup-prompt-regexp) @@ -650,14 +649,12 @@ This command uses `dig-program' for looking up the DNS information." (list host))) (pop-to-buffer buf))) -(defvar ftp-mode-map - (let ((map (make-sparse-keymap))) - ;; Occasionally useful - (define-key map "\t" #'completion-at-point) - map)) +(defvar-keymap ftp-mode-map + "TAB" #'completion-at-point) (define-derived-mode ftp-mode comint-mode "FTP" "Major mode for interacting with the ftp program." + :interactive nil (setq comint-prompt-regexp ftp-prompt-regexp) (setq comint-input-autoexpand t) ;; Only add the password-prompting hook if it's not already in the @@ -707,6 +704,7 @@ This command uses `smbclient-program' to connect to HOST." (define-derived-mode smbclient-mode comint-mode "smbclient" "Major mode for interacting with the smbclient program." + :interactive nil (setq comint-prompt-regexp smbclient-prompt-regexp) (setq comint-input-autoexpand t) ;; Only add the password-prompting hook if it's not already in the @@ -922,10 +920,9 @@ The port is deduced from `network-connection-service-alist'." ;;; General Network connection ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Using a derived mode gives us keymaps, hooks, etc. -(define-derived-mode - network-connection-mode comint-mode "Network-Connection" - "Major mode for interacting with the `network-connection' program.") +(define-derived-mode network-connection-mode comint-mode "Network-Connection" + "Major mode for interacting with the `network-connection' program." + :interactive nil) (defun network-connection-mode-setup (host service) (setq-local network-connection-host host) commit 2ac0ddc4ac406b04b258f535aaa09a0e3859953b Author: Stefan Kangas Date: Thu Jul 7 12:15:48 2022 +0200 ; * lisp/net/net-utils.el: Minor doc fixes. diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index 411b6ed413..47b5271ef0 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el @@ -23,11 +23,10 @@ ;;; Commentary: -;; ;; There are three main areas of functionality: ;; ;; * Wrap common network utility programs (ping, traceroute, netstat, -;; nslookup, arp, route). Note that these wrappers are of the diagnostic +;; nslookup, arp, route). Note that these wrappers are of the diagnostic ;; functions of these programs only. ;; ;; * Implement some very basic protocols in Emacs Lisp (finger and whois) @@ -39,7 +38,7 @@ ;;; Code: ;; On some systems, programs like ifconfig are not in normal user -;; path, but rather in /sbin, /usr/sbin, etc (but non-root users can +;; path, but rather in /sbin, /usr/sbin, etc. (but non-root users can ;; still use them for queries). Actually the trend these ;; days is for /sbin to be a symlink to /usr/sbin, but we still need to ;; search both for older systems. commit 707124d2b92780b4f21d72c7c62899e074fa8ced Author: Stefan Kangas Date: Thu Jul 7 11:11:34 2022 +0200 Make 'run-dig' command obsolete in favor of 'dig' * lisp/net/net-utils.el (run-dig): Redefine in terms of `dig' and make obsolete. (Bug#56432). (dig-program): Delete duplicate defcustom; it is also in dig.el. (dig-program-options): Move from here... * lisp/net/dig.el (dig-program-options): ...to here. (dig-invoke): Respect 'dig-program-options'. (dig): Prompt for DNS server when given double prefix argument. diff --git a/etc/NEWS b/etc/NEWS index 2013260c15..39c3aabb11 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2042,6 +2042,9 @@ back the old behavior. This command prompts for a recently opened file in the minibuffer, and visits it. +--- +*** The 'run-dig' command is now obsolete; use 'dig' instead. + --- ** The autoarg.el library is now marked obsolete. This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor diff --git a/lisp/net/dig.el b/lisp/net/dig.el index 81ddade109..0ac6399e87 100644 --- a/lisp/net/dig.el +++ b/lisp/net/dig.el @@ -44,6 +44,11 @@ "Name of dig (domain information groper) binary." :type 'file) +(defcustom dig-program-options nil + "Options for the dig program." + :type '(repeat string) + :version "26.1") + (defcustom dig-dns-server nil "DNS server to query. If nil, use system defaults." @@ -59,8 +64,8 @@ If nil, use system defaults." :type 'sexp) (defun dig-invoke (domain &optional - query-type query-class query-option - dig-option server) + query-type query-class query-option + dig-option server) "Call dig with given arguments and return buffer containing output. DOMAIN is a string with a DNS domain. QUERY-TYPE is an optional string with a DNS type. QUERY-CLASS is an optional string with a DNS @@ -79,7 +84,8 @@ and is a commonly available debugging tool." (push domain cmdline) (if server (push (concat "@" server) cmdline) (if dig-dns-server (push (concat "@" dig-dns-server) cmdline))) - (apply #'call-process dig-program nil buf nil cmdline) + (apply #'call-process dig-program nil buf nil + (append dig-program-options cmdline)) buf)) (defun dig-extract-rr (domain &optional type class) @@ -140,12 +146,21 @@ Buffer should contain output generated by `dig-invoke'." query-type query-class query-option dig-option server) "Query addresses of a DOMAIN using dig. See `dig-invoke' for an explanation for the parameters. -When called interactively, DOMAIN is prompted for. If given a prefix, -also prompt for the QUERY-TYPE parameter." +When called interactively, DOMAIN is prompted for. + +If given a \\[universal-argument] prefix, also prompt \ +for the QUERY-TYPE parameter. + +If given a \\[universal-argument] \\[universal-argument] \ +prefix, also prompt for the SERVER parameter." (interactive (list (read-string "Host: ") (and current-prefix-arg (read-string "Query type: ")))) + (when (>= (car current-prefix-arg) 16) + (let ((serv (read-from-minibuffer "Name server: "))) + (when (not (equal serv "")) + (setq server serv)))) (pop-to-buffer-same-window (dig-invoke domain query-type query-class query-option dig-option server)) (goto-char (point-min)) diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el index 411b6ed413..ea1dd0f3ca 100644 --- a/lisp/net/net-utils.el +++ b/lisp/net/net-utils.el @@ -176,15 +176,6 @@ This variable is only used if the variable `comint-use-prompt-regexp' is non-nil." :type 'regexp) -(defcustom dig-program "dig" - "Program to query DNS information." - :type 'string) - -(defcustom dig-program-options nil - "Options for the dig program." - :type '(repeat string) - :version "26.1") - (defcustom ftp-program "ftp" "Program to run to do FTP transfers." :type 'string) @@ -633,20 +624,11 @@ DNS resolution. Interactively, prompt for NAME-SERVER if invoked with prefix argument. This command uses `dig-program' for looking up the DNS information." + (declare (obsolete dig "29.1")) (interactive (list (read-from-minibuffer "Lookup host: " (net-utils-machine-at-point)) (if current-prefix-arg (read-from-minibuffer "Name server: ")))) - (let ((options - (append dig-program-options (list host) - (if name-server (list (concat "@" name-server)))))) - (net-utils-run-program - "Dig" - (concat "** " - (mapconcat #'identity - (list "Dig" host dig-program) - " ** ")) - dig-program - options))) + (dig host nil nil nil nil name-server)) (autoload 'comint-exec "comint") (declare-function comint-watch-for-password-prompt "comint" (string)) commit 74f43f82e6b4702027d99edb6ca125f3243ce4ba Author: Eli Zaretskii Date: Thu Jul 7 11:56:31 2022 +0300 Fix undo of changes in cloned indirect buffers * lisp/simple.el (primitive-undo): If the visited-modtime of the indirect buffer's file is bogus, use the modtime of the file visited by its base buffer. * src/undo.c (record_first_change): Call 'buffer_visited_file_modtime' with the correct buffer, instead of always calling 'Fvisited_file_modtime', which returns possibly bogus values for indirect buffers. * src/fileio.c (Fset_visited_file_modtime): Signal a meaningful error for indirect buffers. (buffer_visited_file_modtime): New function, with implementation taken from 'Fvisited_file_modtime'. (Fvisited_file_modtime): Call 'buffer_visited_file_modtime'. * src/lisp.h: Add prototype for 'buffer_visited_file_modtime'. (Bug#56397) diff --git a/lisp/simple.el b/lisp/simple.el index 6313ce81ef..66640916a2 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -3525,12 +3525,22 @@ Return what remains of the list." ;; If this records an obsolete save ;; (not matching the actual disk file) ;; then don't mark unmodified. - (when (or (equal time (visited-file-modtime)) - (and (consp time) - (equal (list (car time) (cdr time)) - (visited-file-modtime)))) - (unlock-buffer) - (set-buffer-modified-p nil))) + (let ((visited-file-time (visited-file-modtime))) + ;; Indirect buffers don't have a visited file, so their + ;; file-modtime can be bogus. In that case, use the + ;; modtime of the base buffer instead. + (if (and (numberp visited-file-time) + (= visited-file-time 0) + (buffer-base-buffer)) + (setq visited-file-time + (with-current-buffer (buffer-base-buffer) + (visited-file-modtime)))) + (when (or (equal time visited-file-time) + (and (consp time) + (equal (list (car time) (cdr time)) + visited-file-time))) + (unlock-buffer) + (set-buffer-modified-p nil)))) ;; Element (nil PROP VAL BEG . END) is property change. (`(nil . ,(or `(,prop ,val ,beg . ,end) pcase--dontcare)) (when (or (> (point-min) beg) (< (point-max) end)) diff --git a/src/fileio.c b/src/fileio.c index 10d4b8bc15..d07e62a121 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -5832,6 +5832,15 @@ See Info node `(elisp)Modification Time' for more details. */) return Qnil; } +Lisp_Object +buffer_visited_file_modtime (struct buffer *buf) +{ + int ns = buf->modtime.tv_nsec; + if (ns < 0) + return make_fixnum (UNKNOWN_MODTIME_NSECS - ns); + return make_lisp_time (buf->modtime); +} + DEFUN ("visited-file-modtime", Fvisited_file_modtime, Svisited_file_modtime, 0, 0, 0, doc: /* Return the current buffer's recorded visited file modification time. @@ -5841,10 +5850,7 @@ visited file doesn't exist. See Info node `(elisp)Modification Time' for more details. */) (void) { - int ns = current_buffer->modtime.tv_nsec; - if (ns < 0) - return make_fixnum (UNKNOWN_MODTIME_NSECS - ns); - return make_lisp_time (current_buffer->modtime); + return buffer_visited_file_modtime (current_buffer); } DEFUN ("set-visited-file-modtime", Fset_visited_file_modtime, @@ -5871,6 +5877,8 @@ in `current-time' or an integer flag as returned by `visited-file-modtime'. */) current_buffer->modtime = mtime; current_buffer->modtime_size = -1; } + else if (current_buffer->base_buffer) + error ("An indirect buffer does not have a visited file"); else { register Lisp_Object filename; diff --git a/src/lisp.h b/src/lisp.h index e4a49b8ef9..35cc7f5a09 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4733,6 +4733,7 @@ extern bool internal_delete_file (Lisp_Object); extern Lisp_Object check_emacs_readlinkat (int, Lisp_Object, char const *); extern bool file_directory_p (Lisp_Object); extern bool file_accessible_directory_p (Lisp_Object); +extern Lisp_Object buffer_visited_file_modtime (struct buffer *); extern void init_fileio (void); extern void syms_of_fileio (void); diff --git a/src/undo.c b/src/undo.c index 36664d1642..f76977dbe5 100644 --- a/src/undo.c +++ b/src/undo.c @@ -218,7 +218,7 @@ record_first_change (void) base_buffer = base_buffer->base_buffer; bset_undo_list (current_buffer, - Fcons (Fcons (Qt, Fvisited_file_modtime ()), + Fcons (Fcons (Qt, buffer_visited_file_modtime (base_buffer)), BVAR (current_buffer, undo_list))); } commit b075a59a1a4ddfd0668da4fb2312a6ec747dd53b Author: Stefan Kangas Date: Thu Jul 7 10:38:45 2022 +0200 * lisp/net/dig.el (dig-exit): Mark for 'dig-mode'. diff --git a/lisp/net/dig.el b/lisp/net/dig.el index f7f1500454..81ddade109 100644 --- a/lisp/net/dig.el +++ b/lisp/net/dig.el @@ -132,7 +132,7 @@ Buffer should contain output generated by `dig-invoke'." (defun dig-exit () "Quit dig output buffer." - (interactive) + (interactive nil dig-mode) (quit-window t)) ;;;###autoload commit f703b64da0cb20dee42a47770f9d22ec335f29c2 Author: Visuwesh Date: Wed Jul 6 10:03:59 2022 +0530 Make the Indian itrans methods more phonetic The characters ऋ and ॠ are pronunced as ru in languages such as Marathi, Gujarati, Telugu, etc. so add new translation rules that reflects this sound. (bug#56414) * lisp/language/ind-util.el (indian-itrans-v5-table): Add new translation rules to make the input method more phonetic. (indian-tml-base-table, indian-tml-base-digits-table): Fix typo. diff --git a/lisp/language/ind-util.el b/lisp/language/ind-util.el index fa380dbde7..27facaa858 100644 --- a/lisp/language/ind-util.el +++ b/lisp/language/ind-util.el @@ -269,7 +269,7 @@ ?ய ?ர ?ற ?ல ?ள ?ழ ?வ ;; SEMIVOWELS ?ஶ ?ஷ ?ஸ ?ஹ ;; SIBILANTS nil nil nil nil nil nil nil nil ;; NUKTAS - "ஜ்ஞ" "க்ஷ" "க்‌ஷ்") + "ஜ்ஞ" "க்ஷ" "க்‌ஷ") (;; Misc Symbols nil ?ஂ ?ஃ nil ?் ?ௐ nil) (;; Digits @@ -292,7 +292,7 @@ ?ய ?ர ?ற ?ல ?ள ?ழ ?வ ;; SEMIVOWELS ?ஶ ?ஷ ?ஸ ?ஹ ;; SIBILANTS nil nil nil nil nil nil nil nil ;; NUKTAS - "ஜ்ஞ" "க்ஷ" "க்‌ஷ்") + "ஜ்ஞ" "க்ஷ" "க்‌ஷ") (;; Misc Symbols nil ?ஂ ?ஃ nil ?் ?ௐ nil) (;; Digits @@ -315,8 +315,8 @@ '(;; for encode/decode (;; vowels -- 18 "a" ("aa" "A") "i" ("ii" "I") "u" ("uu" "U") - ("RRi" "R^i") ("LLi" "L^i") (".c" "e.c") "E" "e" "ai" - "o.c" "O" "o" "au" ("RRI" "R^I") ("LLI" "L^I")) + ("RRi" "R^i" "RRu" "R^u") ("LLi" "L^i") (".c" "e.c") "E" "e" "ai" + "o.c" "O" "o" "au" ("RRI" "R^I" "RRU" "R^U") ("LLI" "L^I")) (;; consonants -- 40 "k" "kh" "g" "gh" ("~N" "N^") "ch" ("Ch" "chh") "j" "jh" ("~n" "JN") commit 455495b2154844f9f0e7465c9f0ccfc864c0290b Merge: e93aa8d586 6f872ea8e7 Author: Eli Zaretskii Date: Thu Jul 7 09:31:49 2022 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 6f872ea8e70e777f07e19f3eb1ff0c77dcdcba63 Author: Juri Linkov Date: Thu Jul 7 09:31:02 2022 +0300 Don't accumulate trailing newlines on every save of .dir-locals.el * lisp/files-x.el (modify-dir-local-variable): Insert a newline only after creating a new file. (dir-locals-to-string): Remove newline to not add more newlines on every save. diff --git a/lisp/files-x.el b/lisp/files-x.el index a89fc26d60..8224a57450 100644 --- a/lisp/files-x.el +++ b/lisp/files-x.el @@ -502,12 +502,13 @@ from the MODE alist ignoring the input argument VALUE." ((and (symbolp (car b)) (stringp (car a))) nil) (t (string< (car a) (car b))))))) (current-buffer)) + (when (eobp) (insert "\n")) (goto-char (point-min)) (indent-sexp)))) (defun dir-locals-to-string (variables) "Output alists of VARIABLES to string in dotted pair notation syntax." - (format "(%s)\n" + (format "(%s)" (mapconcat (lambda (mode-variables) (format "(%S . %s)" commit e93aa8d58670f013b9a457e7136a6284f173a8ce Author: Eli Zaretskii Date: Thu Jul 7 09:29:51 2022 +0300 ; Improve documentation of 'set-transient-map' changes * lisp/subr.el (set-transient-map-timeout, set-transient-map): Doc fixes. * etc/NEWS: Improve wording of the 'set-transient-map' entry. * doc/lispref/keymaps.texi (Controlling Active Maps): Fix wording and passive tense, and improve indexing. (Bug#21634) diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 8df4b6f2b4..f5341f40f0 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1063,15 +1063,19 @@ The optional argument @var{on-exit}, if non-@code{nil}, specifies a function that is called, with no arguments, after @var{keymap} is deactivated. -The optional argument @var{message}, if a string, specifies the format -string for the message to display after activating the transient map. -When the string contains the specifier @samp{%k}, it's replaced with -the list of keys from the transient map. - -The optional argument @var{timeout}, if a number, specifies the number -of seconds of idle time after which @var{keymap} is deactivated. The -value of the argument @var{timeout} can be overridden by the variable -@code{set-transient-map-timeout}. +The optional argument @var{message} specifies the message to display +after activating the transient map. If @var{message} is a string, it +is the format string for the message, and any @samp{%k} specifier in +that string is replaced with the list of keys from the transient map. +Any other non-@code{nil} value of @var{message} stands for the default +message format @samp{Repeat with %k}. + +@vindex set-transient-map-timeout +If the optional argument @var{timeout} is non-@code{nil}, it should be +a number that specifies how many seconds of idle time to wait before +deactivating @var{keymap}. The value of the variable +@code{set-transient-map-timeout}, if non-@code{nil}, overrides the +value of this argument. This function works by adding and removing @var{keymap} from the variable @code{overriding-terminal-local-map}, which takes precedence diff --git a/etc/NEWS b/etc/NEWS index e169447025..2013260c15 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2279,10 +2279,11 @@ patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el. +++ ** New arguments MESSAGE and TIMEOUT of 'set-transient-map'. -MESSAGE specifies a string that lists available keys, -and TIMEOUT deactivates the transient map after the specified -number of seconds. The default timeout is defined by -the new variable 'set-transient-map-timeout'. +MESSAGE specifies a message to display after activating the transient +map, including a special formatting spec to list available keys. +TIMEOUT is the idle time after which to deactivate the transient map. +The default timeout value can be defined by the new variable +'set-transient-map-timeout'. +++ ** New function 'seq-split'. diff --git a/lisp/subr.el b/lisp/subr.el index 44d094d28d..6bf12fd757 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -6014,9 +6014,10 @@ To test whether a function can be called interactively, use 'set-temporary-overlay-map #'set-transient-map "24.4") (defvar set-transient-map-timeout nil - "Deactivate the transient map after specified timeout. -When a number, after idle time of the specified number of seconds -deactivate the map set by the previous call of `set-transient-map'.") + "Timeout in seconds for deactivation of a transient keymap. +If this is a number, it specifies the amount of idle time +after which to deactivate the keymap set by `set-transient-map', +thus overriding the value of the TIMEOUT argument to that function.") (defvar set-transient-map-timer nil "Timer for `set-transient-map-timeout'.") @@ -6032,16 +6033,18 @@ if it returns non-nil, then MAP stays active. Optional arg ON-EXIT, if non-nil, specifies a function that is called, with no arguments, after MAP is deactivated. -Optional arg MESSAGE, if a string, specifies the format string for the -message to display after activating the transient map. When the string -contains the specifier %k, it's replaced with the list of keys from the -transient map. Other non-nil values of MESSAGE use the message format -\"Repeat with %k\". On deactivating the map the displayed message -is cleared out. - -Optional arg TIMEOUT, if a number, specifies the number of seconds -of idle time after which the map is deactivated. The variable -`set-transient-map-timeout' overrides the argument TIMEOUT. +Optional arg MESSAGE, if non-nil, requests display of an informative +message after activating the transient map. If MESSAGE is a string, +it specifies the format string for the message to display, and the %k +specifier in the string is replaced with the list of keys from the +transient map. Any other non-nil value of MESSAGE means to use the +message format string \"Repeat with %k\". Upon deactivating the map, +the displayed message will be cleared out. + +Optional arg TIMEOUT, if non-nil, should be a number specifying the +number of seconds of idle time after which the map is deactivated. +The variable `set-transient-map-timeout', if non-nil, overrides the +value of TIMEOUT. This function uses `overriding-terminal-local-map', which takes precedence over all other keymaps. As usual, if no match for a key is found in MAP, commit ba63d8783bfd9a484106718346c7dbf6729c4c0f Author: Po Lu Date: Thu Jul 7 13:37:31 2022 +0800 Fix `trace-function' default buffer * lisp/emacs-lisp/trace.el (trace--read-args): Don't use format-prompt; instead, use DEF arg to read-buffer. diff --git a/lisp/emacs-lisp/trace.el b/lisp/emacs-lisp/trace.el index 165f5c7bfe..7377ac9403 100644 --- a/lisp/emacs-lisp/trace.el +++ b/lisp/emacs-lisp/trace.el @@ -273,7 +273,7 @@ If `current-prefix-arg' is non-nil, also read a buffer and a \"context\" (if default (symbol-name default))))) (when current-prefix-arg (list - (read-buffer (format-prompt "Output to buffer" trace-buffer)) + (read-buffer "Output to buffer" trace-buffer) (let ((exp (let ((minibuffer-completing-symbol t)) (read-from-minibuffer "Context expression: " commit b1565431270a3596311f898ab51eccd969dca810 Merge: dafbdb87ec f9d01e5047 Author: Stefan Kangas Date: Thu Jul 7 06:30:37 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: f9d01e5047 ; * lisp/emacs-lisp/ert.el: Remove installation instructions. commit dafbdb87ecccd347bc120816c29f4b7909bc73ca Author: Sean Whitton Date: Wed Jul 6 20:34:33 2022 -0700 gnus-advanced-body: Fix return value * gnus-logic.el (gnus-advanced-body): Return whether the search succeeded, not the value of one of the cleanup forms. diff --git a/lisp/gnus/gnus-logic.el b/lisp/gnus/gnus-logic.el index 3fb2ed3c62..c1b559ba6f 100644 --- a/lisp/gnus/gnus-logic.el +++ b/lisp/gnus/gnus-logic.el @@ -224,8 +224,8 @@ (goto-char (point-min)) (prog1 (funcall search-func match nil t) - (widen))) - (when handles (mm-destroy-parts handles)))))) + (widen) + (when handles (mm-destroy-parts handles)))))))) (provide 'gnus-logic) commit ca58872a5370bc9683c8bc0128c1f896410fdb6b Author: Po Lu Date: Thu Jul 7 10:50:49 2022 +0800 Fix NS build * src/keyboard.c (process_special_events): Don't define copy and moved events on the wrong toolkit. diff --git a/src/keyboard.c b/src/keyboard.c index 76dc3732b5..84a7a0a38a 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4361,12 +4361,14 @@ static void process_special_events (void) { union buffered_input_event *event; +#if defined HAVE_X11 || defined HAVE_PGTK || defined HAVE_HAIKU #ifndef HAVE_HAIKU struct selection_input_event copy; #else struct input_event copy; #endif int moved_events; +#endif for (event = kbd_fetch_ptr; event != kbd_store_ptr; event = next_kbd_event (event)) commit fd016ea99724f7abedfddbb470ab96ece6ddf4ae Author: Po Lu Date: Thu Jul 7 02:48:19 2022 +0000 Port `x-lost-selection-functions' to Haiku * src/haiku_io.c (haiku_len): Add `CLIPBOARD_CHANGED_EVENT'. * src/haiku_select.cc (be_update_clipboard_count): Set ownership flags. (be_handle_clipboard_changed_message): (be_start_watching_selection): New functions. * src/haiku_support.cc (class Emacs): Handle B_CLIPBOARD_CHANGED. * src/haiku_support.h (enum haiku_event_type): New event `CLIPBOARD_CHANGED_EVENT'. (struct haiku_clipboard_changed_event): New struct. * src/haikuselect.c (haiku_handle_selection_clear) (haiku_selection_disowned, haiku_start_watching_selections): New functions. (syms_of_haikuselect): New defsym and defvar. * src/haikuselect.h: Update prototypes. * src/haikuterm.c (haiku_read_socket): Handle selection events. (haiku_term_init): Start watching selections. * src/haikuterm.h: Update prototypes. * src/keyboard.c (kbd_buffer_get_event, process_special_events) (mark_kboards): Handle SELECTON_CLEAR_EVENTs correctly on Haiku. diff --git a/src/haiku_io.c b/src/haiku_io.c index d345527685..5cc70f6f71 100644 --- a/src/haiku_io.c +++ b/src/haiku_io.c @@ -107,6 +107,8 @@ haiku_len (enum haiku_event_type type) return sizeof (struct haiku_scroll_bar_part_event); case SCREEN_CHANGED_EVENT: return sizeof (struct haiku_screen_changed_event); + case CLIPBOARD_CHANGED_EVENT: + return sizeof (struct haiku_clipboard_changed_event); } emacs_abort (); diff --git a/src/haiku_select.cc b/src/haiku_select.cc index 80c5d29482..edb821e313 100644 --- a/src/haiku_select.cc +++ b/src/haiku_select.cc @@ -18,6 +18,7 @@ along with GNU Emacs. If not, see . */ #include +#include #include #include #include @@ -47,6 +48,16 @@ static int64 count_primary = -1; /* The number of times the secondary selection has changed. */ static int64 count_secondary = -1; +/* Whether or not we currently think Emacs owns the primary + selection. */ +static bool owned_primary; + +/* Likewise for the secondary selection. */ +static bool owned_secondary; + +/* And the clipboard. */ +static bool owned_clipboard; + static BClipboard * get_clipboard_object (enum haiku_clipboard clipboard) { @@ -150,14 +161,17 @@ be_update_clipboard_count (enum haiku_clipboard id) { case CLIPBOARD_CLIPBOARD: count_clipboard = system_clipboard->SystemCount (); + owned_clipboard = true; break; case CLIPBOARD_PRIMARY: count_primary = primary->SystemCount (); + owned_primary = true; break; case CLIPBOARD_SECONDARY: count_secondary = secondary->SystemCount (); + owned_secondary = true; break; } } @@ -433,3 +447,43 @@ be_unlock_clipboard (enum haiku_clipboard clipboard, bool discard) board->Unlock (); } + +void +be_handle_clipboard_changed_message (void) +{ + if (count_clipboard != -1 + && (system_clipboard->SystemCount () + > count_clipboard + 1) + && owned_clipboard) + { + owned_clipboard = false; + haiku_selection_disowned (CLIPBOARD_CLIPBOARD); + } + + if (count_primary != -1 + && (primary->SystemCount () + > count_primary + 1) + && owned_primary) + { + owned_primary = false; + haiku_selection_disowned (CLIPBOARD_PRIMARY); + } + + if (count_secondary != -1 + && (secondary->SystemCount () + > count_secondary + 1) + && owned_secondary) + { + owned_secondary = false; + haiku_selection_disowned (CLIPBOARD_SECONDARY); + } +} + +void +be_start_watching_selection (enum haiku_clipboard id) +{ + BClipboard *clipboard; + + clipboard = get_clipboard_object (id); + clipboard->StartWatching (be_app); +} diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 7819cef568..9e38d9556f 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -21,6 +21,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include @@ -648,8 +649,12 @@ class Emacs : public BApplication void MessageReceived (BMessage *msg) { + struct haiku_clipboard_changed_event rq; + if (msg->what == QUIT_APPLICATION) Quit (); + else if (msg->what == B_CLIPBOARD_CHANGED) + haiku_write (CLIPBOARD_CHANGED_EVENT, &rq); else BApplication::MessageReceived (msg); } diff --git a/src/haiku_support.h b/src/haiku_support.h index 6260b35cbc..d73f15560b 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -114,8 +114,14 @@ enum haiku_event_type DUMMY_EVENT, SCREEN_CHANGED_EVENT, MENU_BAR_LEFT, + CLIPBOARD_CHANGED_EVENT, }; +struct haiku_clipboard_changed_event +{ + char dummy; +}; + struct haiku_screen_changed_event { bigtime_t when; diff --git a/src/haikuselect.c b/src/haikuselect.c index fe76e09810..999a0f5ac2 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see . */ #include "haikuselect.h" #include "haikuterm.h" #include "haiku_support.h" +#include "keyboard.h" #include @@ -1020,6 +1021,47 @@ init_haiku_select (void) be_clipboard_init (); } +void +haiku_handle_selection_clear (struct input_event *ie) +{ + CALLN (Frun_hook_with_args, + Qhaiku_lost_selection_functions, ie->arg); +} + +void +haiku_selection_disowned (enum haiku_clipboard id) +{ + struct input_event ie; + + EVENT_INIT (ie); + ie.kind = SELECTION_CLEAR_EVENT; + + switch (id) + { + case CLIPBOARD_CLIPBOARD: + ie.arg = QCLIPBOARD; + break; + + case CLIPBOARD_PRIMARY: + ie.arg = QPRIMARY; + break; + + case CLIPBOARD_SECONDARY: + ie.arg = QSECONDARY; + break; + } + + kbd_buffer_store_event (&ie); +} + +void +haiku_start_watching_selections (void) +{ + be_start_watching_selection (CLIPBOARD_CLIPBOARD); + be_start_watching_selection (CLIPBOARD_PRIMARY); + be_start_watching_selection (CLIPBOARD_SECONDARY); +} + void syms_of_haikuselect (void) { @@ -1035,12 +1077,21 @@ The function is called without any arguments. `mouse-position' can be used to retrieve the current position of the mouse. */); Vhaiku_drag_track_function = Qnil; + DEFVAR_LISP ("haiku-lost-selection-functions", Vhaiku_lost_selection_functions, + doc: /* A list of functions to be called when Emacs loses an X selection. +These are only called if a connection to the Haiku display was opened. */); + Vhaiku_lost_selection_functions = Qnil; + DEFSYM (QSECONDARY, "SECONDARY"); DEFSYM (QCLIPBOARD, "CLIPBOARD"); DEFSYM (QSTRING, "STRING"); DEFSYM (QUTF8_STRING, "UTF8_STRING"); DEFSYM (Qforeign_selection, "foreign-selection"); DEFSYM (QTARGETS, "TARGETS"); + + DEFSYM (Qhaiku_lost_selection_functions, + "haiku-lost-selection-functions"); + DEFSYM (Qmessage, "message"); DEFSYM (Qstring, "string"); DEFSYM (Qref, "ref"); diff --git a/src/haikuselect.h b/src/haikuselect.h index ac8e069895..d027834e8b 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h @@ -38,7 +38,10 @@ enum haiku_clipboard extern "C" { #endif +/* Defined in haikuselect.c. */ +extern void haiku_selection_disowned (enum haiku_clipboard); +/* Defined in haiku_select.cc. */ extern void be_clipboard_init (void); extern char *be_find_clipboard_data (enum haiku_clipboard, const char *, ssize_t *); extern void be_set_clipboard_data (enum haiku_clipboard, const char *, const char *, @@ -61,6 +64,8 @@ extern int be_add_point_data (void *, const char *, float, float); extern int be_add_message_message (void *, const char *, void *); extern int be_lock_clipboard_message (enum haiku_clipboard, void **, bool); extern void be_unlock_clipboard (enum haiku_clipboard, bool); +extern void be_handle_clipboard_changed_message (void); +extern void be_start_watching_selection (enum haiku_clipboard); #ifdef __cplusplus }; diff --git a/src/haikuterm.c b/src/haikuterm.c index d7247c99e0..bcb3af0e2c 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -32,6 +32,7 @@ along with GNU Emacs. If not, see . */ #include "haiku_support.h" #include "thread.h" #include "window.h" +#include "haikuselect.h" #include #include @@ -4010,6 +4011,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) inev.timestamp = b->when / 1000; break; } + case CLIPBOARD_CHANGED_EVENT: + be_handle_clipboard_changed_message (); + break; case APP_QUIT_REQUESTED_EVENT: inev.kind = SAVE_SESSION_EVENT; inev.arg = Qt; @@ -4403,6 +4407,7 @@ haiku_term_init (void) else dpyinfo->default_name = build_string ("GNU Emacs"); + haiku_start_watching_selections (); unblock_input (); return dpyinfo; diff --git a/src/haikuterm.h b/src/haikuterm.h index ea20289b5d..46a2218e49 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -357,4 +357,6 @@ extern void haiku_end_cr_clip (cairo_t *); extern void haiku_merge_cursor_foreground (struct glyph_string *, unsigned long *, unsigned long *); +extern void haiku_handle_selection_clear (struct input_event *); +extern void haiku_start_watching_selections (void); #endif /* _HAIKU_TERM_H_ */ diff --git a/src/keyboard.c b/src/keyboard.c index bed8307b6f..76dc3732b5 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4012,6 +4012,7 @@ kbd_buffer_get_event (KBOARD **kbp, We return nil for them. */ switch (event->kind) { +#ifndef HAVE_HAIKU case SELECTION_REQUEST_EVENT: case SELECTION_CLEAR_EVENT: { @@ -4035,6 +4036,20 @@ kbd_buffer_get_event (KBOARD **kbp, #endif } break; +#else + case SELECTION_REQUEST_EVENT: + emacs_abort (); + + case SELECTION_CLEAR_EVENT: + { + struct input_event copy = event->ie; + + kbd_fetch_ptr = next_kbd_event (event); + input_pending = readable_events (0); + haiku_handle_selection_clear (©); + } + break; +#endif case MONITORS_CHANGED_EVENT: { @@ -4345,8 +4360,16 @@ kbd_buffer_get_event (KBOARD **kbp, static void process_special_events (void) { - for (union buffered_input_event *event = kbd_fetch_ptr; - event != kbd_store_ptr; event = next_kbd_event (event)) + union buffered_input_event *event; +#ifndef HAVE_HAIKU + struct selection_input_event copy; +#else + struct input_event copy; +#endif + int moved_events; + + for (event = kbd_fetch_ptr; event != kbd_store_ptr; + event = next_kbd_event (event)) { /* If we find a stored X selection request, handle it now. */ if (event->kind == SELECTION_REQUEST_EVENT @@ -4360,8 +4383,7 @@ process_special_events (void) between kbd_fetch_ptr and EVENT one slot to the right, cyclically. */ - struct selection_input_event copy = event->sie; - int moved_events; + copy = event->sie; if (event < kbd_fetch_ptr) { @@ -4383,6 +4405,27 @@ process_special_events (void) #else pgtk_handle_selection_event (©); #endif +#elif defined HAVE_HAIKU + if (event->ie.kind != SELECTION_CLEAR_EVENT) + emacs_abort (); + + copy = event->ie; + + if (event < kbd_fetch_ptr) + { + memmove (kbd_buffer + 1, kbd_buffer, + (event - kbd_buffer) * sizeof *kbd_buffer); + kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1]; + moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr; + } + else + moved_events = event - kbd_fetch_ptr; + + memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr, + moved_events * sizeof *kbd_fetch_ptr); + kbd_fetch_ptr = next_kbd_event (kbd_fetch_ptr); + input_pending = readable_events (0); + haiku_handle_selection_clear (©); #else /* We're getting selection request events, but we don't have a window system. */ @@ -13149,7 +13192,10 @@ mark_kboards (void) { /* These two special event types have no Lisp_Objects to mark. */ if (event->kind != SELECTION_REQUEST_EVENT - && event->kind != SELECTION_CLEAR_EVENT) +#ifndef HAVE_HAIKU + && event->kind != SELECTION_CLEAR_EVENT +#endif + ) { mark_object (event->ie.x); mark_object (event->ie.y); commit 8575962d46d1f1d08836bf00cb74ccd344953bcb Author: Po Lu Date: Thu Jul 7 09:21:22 2022 +0800 Avoid excessive synchronization performing "xterm" drops * src/xterm.c (x_dnd_do_unsupported_drop): Asynchronously catch errors around XSendEvent. diff --git a/src/xterm.c b/src/xterm.c index 225c45ff7c..a21daa2dfc 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3860,6 +3860,7 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, event.xbutton.root = dpyinfo->root_window; event.xbutton.x_root = root_x; event.xbutton.y_root = root_y; + x_catch_errors (dpyinfo->display); child = dpyinfo->root_window; @@ -3892,6 +3893,8 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, if (owner != FRAME_X_WINDOW (f)) goto cancel; + x_uncatch_errors (); + event.xbutton.window = child; event.xbutton.subwindow = None; event.xbutton.x = dest_x; @@ -3905,14 +3908,20 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, event.xbutton.type = ButtonPress; event.xbutton.time = before + 1; + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, child, True, ButtonPressMask, &event); + x_stop_ignoring_errors (dpyinfo); event.xbutton.type = ButtonRelease; event.xbutton.time = before + 2; + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, child, True, ButtonReleaseMask, &event); + x_stop_ignoring_errors (dpyinfo); + + return; cancel: x_uncatch_errors (); commit 7ac9c22636cc2d6c56bf238ca4311924a6ee0cd0 Author: Stefan Kangas Date: Thu Jul 7 02:09:30 2022 +0200 End new .dir-locals.el files with a newline * lisp/files-x.el (dir-locals-to-string): Add newline at the end of newly created .dir-locals.el files. This avoids git complaining about "No newline at end of file". diff --git a/lisp/files-x.el b/lisp/files-x.el index 4db6fbd22c..a89fc26d60 100644 --- a/lisp/files-x.el +++ b/lisp/files-x.el @@ -507,19 +507,20 @@ from the MODE alist ignoring the input argument VALUE." (defun dir-locals-to-string (variables) "Output alists of VARIABLES to string in dotted pair notation syntax." - (format "(%s)" (mapconcat - (lambda (mode-variables) - (format "(%S . %s)" - (car mode-variables) - (format "(%s)" (mapconcat - (lambda (variable-value) - (format "(%S . %s)" - (car variable-value) - (string-trim-right - (pp-to-string - (cdr variable-value))))) - (cdr mode-variables) "\n")))) - variables "\n"))) + (format "(%s)\n" + (mapconcat + (lambda (mode-variables) + (format "(%S . %s)" + (car mode-variables) + (format "(%s)" (mapconcat + (lambda (variable-value) + (format "(%S . %s)" + (car variable-value) + (string-trim-right + (pp-to-string + (cdr variable-value))))) + (cdr mode-variables) "\n")))) + variables "\n"))) ;;;###autoload (defun add-dir-local-variable (mode variable value) commit ab9b55d617fe1235548d368e416e07aeb25504b8 Author: Stefan Kangas Date: Wed Jul 6 20:53:52 2022 +0200 Autoload safe local property for plstore-encrypt-to * lisp/plstore.el (plstore-encrypt-to): Autoload 'safe-local-variable' property for improved security. diff --git a/lisp/plstore.el b/lisp/plstore.el index b37d39ce1b..de3f828016 100644 --- a/lisp/plstore.el +++ b/lisp/plstore.el @@ -107,6 +107,7 @@ symmetric encryption will be used." :type '(choice (const nil) (repeat :tag "Recipient(s)" string)) :group 'plstore) +;;;###autoload (put 'plstore-encrypt-to 'safe-local-variable (lambda (val) (or (stringp val) commit 3e7f6ff4b09760c92b1a6b1a193d08c52f37675a Author: Stefan Kangas Date: Wed Jul 6 19:56:32 2022 +0200 Prefer defcustom :safe to putting 'safe-local-variable' * lisp/emacs-lisp/lisp-mode.el (lisp-indent-offset) (lisp-body-indent, emacs-lisp-docstring-fill-column): * lisp/files.el (version-control): * lisp/progmodes/modula2.el (m2-indent): * lisp/progmodes/octave.el (octave-block-offset): * lisp/progmodes/sh-script.el (sh-basic-offset): * lisp/progmodes/tcl.el (tcl-indent-level) (tcl-continued-indent-level): * lisp/simple.el (fill-prefix): * lisp/textmodes/fill.el (colon-double-space): * lisp/textmodes/paragraphs.el (paragraph-start) (paragraph-separate, sentence-end-double-space) (sentence-end-without-period, sentence-end-without-space) (sentence-end, sentence-end-base, page-delimiter) (paragraph-ignore-fill-prefix): * lisp/textmodes/tex-mode.el (tex-fontify-script): * lisp/vc/add-log.el (add-log-dont-create-changelog-file): * lisp/vc/vc-hooks.el (vc-follow-symlinks): Prefer defcustom :safe to putting 'safe-local-variable'. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index c559dd427c..68528e199f 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -838,9 +838,8 @@ or to switch back to an existing one." (defcustom lisp-indent-offset nil "If non-nil, indent second line of expressions that many more columns." :group 'lisp - :type '(choice (const nil) integer)) -(put 'lisp-indent-offset 'safe-local-variable - (lambda (x) (or (null x) (integerp x)))) + :type '(choice (const nil) integer) + :safe (lambda (x) (or (null x) (integerp x)))) (defcustom lisp-indent-function 'lisp-indent-function "A function to be called by `calculate-lisp-indent'. @@ -1252,8 +1251,8 @@ Lisp function does not specify a special indentation." (defcustom lisp-body-indent 2 "Number of columns to indent the second line of a `(def...)' form." :group 'lisp - :type 'integer) -(put 'lisp-body-indent 'safe-local-variable 'integerp) + :type 'integer + :safe #'integerp) (defun lisp-indent-specform (count state indent-point normal-indent) (let ((containing-form-start (elt state 1)) @@ -1414,9 +1413,8 @@ Any non-integer value means do not use a different value of `fill-column' when filling docstrings." :type '(choice (integer) (const :tag "Use the current `fill-column'" t)) + :safe (lambda (x) (or (eq x t) (integerp x))) :group 'lisp) -(put 'emacs-lisp-docstring-fill-column 'safe-local-variable - (lambda (x) (or (eq x t) (integerp x)))) (defun lisp-fill-paragraph (&optional justify) "Like \\[fill-paragraph], but handle Emacs Lisp comments and docstrings. diff --git a/lisp/files.el b/lisp/files.el index f84fe7e085..992f987943 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -304,16 +304,14 @@ When nil, make them for files that have some already. The value `never' means do not make them." :type '(choice (const :tag "Never" never) (const :tag "If existing" nil) - (other :tag "Always" t)) + (other :tag "Always" t)) + :safe #'version-control-safe-local-p :group 'backup) (defun version-control-safe-local-p (x) "Return whether X is safe as local value for `version-control'." (or (booleanp x) (equal x 'never))) -(put 'version-control 'safe-local-variable - #'version-control-safe-local-p) - (defcustom dired-kept-versions 2 "When cleaning directory, number of versions to keep." :type 'natnum diff --git a/lisp/progmodes/modula2.el b/lisp/progmodes/modula2.el index a8d644dba0..e668570ba1 100644 --- a/lisp/progmodes/modula2.el +++ b/lisp/progmodes/modula2.el @@ -101,9 +101,8 @@ (defcustom m2-indent 5 "This variable gives the indentation in Modula-2 mode." - :type 'integer) -(put 'm2-indent 'safe-local-variable - (lambda (v) (or (null v) (integerp v)))) + :type 'integer + :safe (lambda (v) (or (null v) (integerp v)))) (defconst m2-smie-grammar ;; An official definition can be found as "M2R10.pdf". This grammar does diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el index 7b7c675873..721dfa51ad 100644 --- a/lisp/progmodes/octave.el +++ b/lisp/progmodes/octave.el @@ -197,8 +197,8 @@ newline or semicolon after an else or end keyword." (defcustom octave-block-offset 2 "Extra indentation applied to statements in Octave block structures." - :type 'integer) -(put 'octave-block-offset 'safe-local-variable 'integerp) + :type 'integer + :safe #'integerp) (defvar octave-block-comment-start (concat (make-string 2 octave-comment-char) " ") diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index 71fb0cd2e0..be9f325d93 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -1156,8 +1156,8 @@ Can be set to a number, or to nil which means leave it as is." "The default indentation increment. This value is used for the `+' and `-' symbols in an indentation variable." :type 'integer + :safe #'integerp :group 'sh-indentation) -(put 'sh-basic-offset 'safe-local-variable 'integerp) (defcustom sh-indent-comment t "How a comment line is to be indented. diff --git a/lisp/progmodes/tcl.el b/lisp/progmodes/tcl.el index 8c179879ce..7dae14f9e0 100644 --- a/lisp/progmodes/tcl.el +++ b/lisp/progmodes/tcl.el @@ -120,13 +120,13 @@ (defcustom tcl-indent-level 4 "Indentation of Tcl statements with respect to containing block." - :type 'integer) -(put 'tcl-indent-level 'safe-local-variable #'integerp) + :type 'integer + :safe #'integerp) (defcustom tcl-continued-indent-level 4 "Indentation of continuation line relative to first line of command." - :type 'integer) -(put 'tcl-continued-indent-level 'safe-local-variable #'integerp) + :type 'integer + :safe #'integerp) (defcustom tcl-auto-newline nil "Non-nil means automatically newline before and after braces you insert." diff --git a/lisp/simple.el b/lisp/simple.el index e79487eba8..6313ce81ef 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8609,10 +8609,10 @@ constitute a word." (defcustom fill-prefix nil "String for filling to insert at front of new line, or nil for none." :type '(choice (const :tag "None" nil) - string) + string) + :safe #'string-or-null-p :group 'fill) (make-variable-buffer-local 'fill-prefix) -(put 'fill-prefix 'safe-local-variable 'string-or-null-p) (defcustom auto-fill-inhibit-regexp nil "Regexp to match lines that should not be auto-filled." diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el index 88a8395c88..23ba1a24f1 100644 --- a/lisp/textmodes/fill.el +++ b/lisp/textmodes/fill.el @@ -46,8 +46,8 @@ A value of nil means that any change in indentation starts a new paragraph." (defcustom colon-double-space nil "Non-nil means put two spaces after a colon when filling." - :type 'boolean) -(put 'colon-double-space 'safe-local-variable #'booleanp) + :type 'boolean + :safe #'booleanp) (defcustom fill-separate-heterogeneous-words-with-space nil "Non-nil means to use a space to separate words of a different kind. diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el index 98eb494823..cd726ad477 100644 --- a/lisp/textmodes/paragraphs.el +++ b/lisp/textmodes/paragraphs.el @@ -96,8 +96,8 @@ lines that start paragraphs from lines that separate them. If the variable `use-hard-newlines' is non-nil, then only lines following a hard newline are considered to match." - :type 'regexp) -(put 'paragraph-start 'safe-local-variable #'stringp) + :type 'regexp + :safe #'stringp) ;; paragraph-start requires a hard newline, but paragraph-separate does not: ;; It is assumed that paragraph-separate is distinctive enough to be believed @@ -113,8 +113,8 @@ This is matched against the text at the left margin, which is not necessarily the beginning of the line, so it should not use \"^\" as an anchor. This ensures that the paragraph functions will work equally within a region of text indented by a margin setting." - :type 'regexp) -(put 'paragraph-separate 'safe-local-variable #'stringp) + :type 'regexp + :safe #'stringp) (defcustom sentence-end-double-space t "Non-nil means a single space does not end a sentence. @@ -125,8 +125,8 @@ This value is used by the function `sentence-end' to construct the regexp describing the end of a sentence, when the value of the variable `sentence-end' is nil. See Info node `(elisp)Standard Regexps'." :type 'boolean + :safe #'booleanp :group 'fill) -(put 'sentence-end-double-space 'safe-local-variable #'booleanp) (defcustom sentence-end-without-period nil "Non-nil means a sentence will end without a period. @@ -137,8 +137,8 @@ This value is used by the function `sentence-end' to construct the regexp describing the end of a sentence, when the value of the variable `sentence-end' is nil. See Info node `(elisp)Standard Regexps'." :type 'boolean + :safe #'booleanp :group 'fill) -(put 'sentence-end-without-period 'safe-local-variable #'booleanp) (defcustom sentence-end-without-space "。.?!" @@ -147,8 +147,8 @@ regexp describing the end of a sentence, when the value of the variable This value is used by the function `sentence-end' to construct the regexp describing the end of a sentence, when the value of the variable `sentence-end' is nil. See Info node `(elisp)Standard Regexps'." - :type 'string) -(put 'sentence-end-without-space 'safe-local-variable #'stringp) + :type 'string + :safe #'stringp) (defcustom sentence-end nil "Regexp describing the end of a sentence. @@ -158,14 +158,14 @@ All paragraph boundaries also end sentences, regardless. The value nil means to use the default value defined by the function `sentence-end'. You should always use this function to obtain the value of this variable." - :type '(choice regexp (const :tag "Use default value" nil))) -(put 'sentence-end 'safe-local-variable #'string-or-null-p) + :type '(choice regexp (const :tag "Use default value" nil)) + :safe #'string-or-null-p) (defcustom sentence-end-base "[.?!…‽][]\"'”’)}»›]*" "Regexp matching the basic end of a sentence, not including following space." :type 'regexp + :safe #'stringp :version "25.1") -(put 'sentence-end-base 'safe-local-variable #'stringp) (defun sentence-end () "Return the regexp describing the end of a sentence. @@ -192,14 +192,14 @@ in between. See Info node `(elisp)Standard Regexps'." (defcustom page-delimiter "^\014" "Regexp describing line-beginnings that separate pages." - :type 'regexp) -(put 'page-delimiter 'safe-local-variable #'stringp) + :type 'regexp + :safe #'stringp) (defcustom paragraph-ignore-fill-prefix nil "Non-nil means the paragraph commands are not affected by `fill-prefix'. This is desirable in modes where blank lines are the paragraph delimiters." - :type 'boolean) -(put 'paragraph-ignore-fill-prefix 'safe-local-variable #'booleanp) + :type 'boolean + :safe #'booleanp) ;; Silence the compiler. (defun forward-paragraph (&optional arg) diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el index e90d214a12..d34133f856 100644 --- a/lisp/textmodes/tex-mode.el +++ b/lisp/textmodes/tex-mode.el @@ -248,9 +248,9 @@ Normally set to either `plain-tex-mode' or `latex-mode'." (defcustom tex-fontify-script t "If non-nil, fontify subscript and superscript strings." :type 'boolean + :safe #'booleanp :group 'tex :version "23.1") -(put 'tex-fontify-script 'safe-local-variable #'booleanp) (defcustom tex-font-script-display '(-0.2 0.2) "How much to lower and raise subscript and superscript content. diff --git a/lisp/vc/add-log.el b/lisp/vc/add-log.el index beaad2e835..e02d84f1f5 100644 --- a/lisp/vc/add-log.el +++ b/lisp/vc/add-log.el @@ -789,10 +789,9 @@ Optional arg BUFFER-FILE overrides `buffer-file-name'." If a ChangeLog file does not already exist, a non-nil value means to put log entries in a suitably named buffer." :type 'boolean + :safe #'booleanp :version "27.1") -(put 'add-log-dont-create-changelog-file 'safe-local-variable #'booleanp) - (defun add-log--pseudo-changelog-buffer-name (changelog-file-name) "Compute a suitable name for a non-file visiting ChangeLog buffer. CHANGELOG-FILE-NAME is the file name of the actual ChangeLog file diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index cc08767ade..46e40f29c0 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -141,9 +141,9 @@ confirmation whether it should follow the link. If nil, the link is visited and a warning displayed." :type '(choice (const :tag "Ask for confirmation" ask) (const :tag "Visit link and warn" nil) - (const :tag "Follow link" t)) + (const :tag "Follow link" t)) + :safe #'null :group 'vc) -(put 'vc-follow-symlinks 'safe-local-variable #'null) (defcustom vc-display-status t "If non-nil, display revision number and lock status in mode line. commit 5866fd5fecd93116f0885f55887a449d739c369c Author: Juri Linkov Date: Wed Jul 6 20:40:48 2022 +0300 * lisp/repeat.el (describe-repeat-maps): Handle non-symbol keymap (bug#21634). diff --git a/lisp/repeat.el b/lisp/repeat.el index d69640a29c..a32f3a4c50 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -563,13 +563,17 @@ Used in `repeat-mode'." (insert "A list of keymaps used by commands with the symbol property `repeat-map'.\n\n") (dolist (keymap (sort keymaps (lambda (a b) - (string-lessp (car a) (car b))))) + (when (and (symbolp (car a)) + (symbolp (car b))) + (string-lessp (car a) (car b)))))) (insert (format-message "`%s' keymap is repeatable by these commands:\n" (car keymap))) (dolist (command (sort (cdr keymap) #'string-lessp)) (let* ((info (help-fns--analyze-function command)) - (map (list (symbol-value (car keymap)))) + (map (list (if (symbolp (car keymap)) + (symbol-value (car keymap)) + (car keymap)))) (desc (mapconcat (lambda (key) (propertize (key-description key) 'face 'help-key-binding)) commit 0e99046d62e71fb874cb9010e60ecfee289f84e9 Author: Juri Linkov Date: Wed Jul 6 20:39:41 2022 +0300 Add new args MESSAGE and TIMEOUT to set-transient-map (bug#21634) * lisp/subr.el (set-transient-map): Add new args MESSAGE and TIMEOUT. (set-transient-map-timeout, set-transient-map-timer): New variables. * lisp/international/emoji.el (emoji-zoom-increase): * lisp/indent.el (indent-rigidly): * lisp/face-remap.el (text-scale-adjust, global-text-scale-adjust): Use the arg MESSAGE of set-transient-map. * doc/lispref/keymaps.texi (Controlling Active Maps): Mention new args MESSAGE and TIMEOUT of set-transient-map. diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 9488c4d7b3..8df4b6f2b4 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1063,6 +1063,16 @@ The optional argument @var{on-exit}, if non-@code{nil}, specifies a function that is called, with no arguments, after @var{keymap} is deactivated. +The optional argument @var{message}, if a string, specifies the format +string for the message to display after activating the transient map. +When the string contains the specifier @samp{%k}, it's replaced with +the list of keys from the transient map. + +The optional argument @var{timeout}, if a number, specifies the number +of seconds of idle time after which @var{keymap} is deactivated. The +value of the argument @var{timeout} can be overridden by the variable +@code{set-transient-map-timeout}. + This function works by adding and removing @var{keymap} from the variable @code{overriding-terminal-local-map}, which takes precedence over all other active keymaps (@pxref{Searching Keymaps}). diff --git a/etc/NEWS b/etc/NEWS index 7a1b7a856a..e169447025 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2277,6 +2277,13 @@ patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el. * Lisp Changes in Emacs 29.1 ++++ +** New arguments MESSAGE and TIMEOUT of 'set-transient-map'. +MESSAGE specifies a string that lists available keys, +and TIMEOUT deactivates the transient map after the specified +number of seconds. The default timeout is defined by +the new variable 'set-transient-map-timeout'. + +++ ** New function 'seq-split'. This returns a list of sub-sequences of the specified sequence. diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 467ccbc299..fd49c81ab3 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -408,20 +408,15 @@ See also the related command `global-text-scale-adjust'." (?0 0) (_ inc)))) (text-scale-increase step) - ;; (unless (zerop step) - (message (substitute-command-keys - "Use \\`+',\\`-',\\`0' for further adjustment")) (set-transient-map (let ((map (make-sparse-keymap))) (dolist (mods '(() (control))) - (dolist (key '(?- ?+ ?= ?0)) ;; = is often unshifted +. + (dolist (key '(?+ ?= ?- ?0)) ;; = is often unshifted +. (define-key map (vector (append mods (list key))) (lambda () (interactive) (text-scale-adjust (abs inc)))))) map) - nil - ;; Clear the prompt after exiting. - (lambda () - (message "")))))) + nil nil + "Use %k for further adjustment")))) (defvar-local text-scale--pinch-start-scale 0 "The text scale at the start of a pinch sequence.") @@ -515,15 +510,15 @@ See also the related command `text-scale-adjust'." (not global-text-scale-adjust-resizes-frames))) (set-face-attribute 'default nil :height new))) (when (characterp key) - (message (substitute-command-keys - "Use \\`+',\\`-',\\`0' for further adjustment")) (set-transient-map (let ((map (make-sparse-keymap))) (dolist (mod '(() (control meta))) (dolist (key '(?+ ?= ?- ?0)) (define-key map (vector (append mod (list key))) 'global-text-scale-adjust))) - map)))))) + map) + nil nil + "Use %k for further adjustment"))))) ;; ---------------------------------------------------------------- diff --git a/lisp/indent.el b/lisp/indent.el index d6dee94016..f52b729051 100644 --- a/lisp/indent.el +++ b/lisp/indent.el @@ -270,11 +270,8 @@ Negative values of ARG indent backward, so you can remove all indentation by specifying a large negative ARG." (interactive "r\nP\np") (if (and (not arg) interactive) - (progn - (message - (substitute-command-keys - "Indent region with \\\\[indent-rigidly-left], \\[indent-rigidly-right], \\[indent-rigidly-left-to-tab-stop], or \\[indent-rigidly-right-to-tab-stop].")) - (set-transient-map indent-rigidly-map t #'deactivate-mark)) + (set-transient-map indent-rigidly-map t #'deactivate-mark + "Indent region with %k") (save-excursion (goto-char end) (setq end (point-marker)) diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index 341b44cc11..4f4d4f4832 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -704,10 +704,7 @@ We prefer the earliest unique letter." "Increase the size of the character under point. FACTOR is the multiplication factor for the size." (interactive) - (message - (substitute-command-keys - "Zoom with \\\\[emoji-zoom-increase] and \\[emoji-zoom-decrease]")) - (set-transient-map emoji-zoom-map t) + (set-transient-map emoji-zoom-map t nil "Zoom with %k") (let* ((factor (or factor 1.1)) (old (get-text-property (point) 'face)) (height (or (and (consp old) diff --git a/lisp/subr.el b/lisp/subr.el index 2f9d37ffd6..44d094d28d 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -6013,7 +6013,15 @@ To test whether a function can be called interactively, use (define-obsolete-function-alias 'set-temporary-overlay-map #'set-transient-map "24.4") -(defun set-transient-map (map &optional keep-pred on-exit) +(defvar set-transient-map-timeout nil + "Deactivate the transient map after specified timeout. +When a number, after idle time of the specified number of seconds +deactivate the map set by the previous call of `set-transient-map'.") + +(defvar set-transient-map-timer nil + "Timer for `set-transient-map-timeout'.") + +(defun set-transient-map (map &optional keep-pred on-exit message timeout) "Set MAP as a temporary keymap taking precedence over other keymaps. Normally, MAP is used only once, to look up the very next key. However, if the optional argument KEEP-PRED is t, MAP stays @@ -6024,24 +6032,50 @@ if it returns non-nil, then MAP stays active. Optional arg ON-EXIT, if non-nil, specifies a function that is called, with no arguments, after MAP is deactivated. -This uses `overriding-terminal-local-map', which takes precedence over all -other keymaps. As usual, if no match for a key is found in MAP, the normal -key lookup sequence then continues. +Optional arg MESSAGE, if a string, specifies the format string for the +message to display after activating the transient map. When the string +contains the specifier %k, it's replaced with the list of keys from the +transient map. Other non-nil values of MESSAGE use the message format +\"Repeat with %k\". On deactivating the map the displayed message +is cleared out. + +Optional arg TIMEOUT, if a number, specifies the number of seconds +of idle time after which the map is deactivated. The variable +`set-transient-map-timeout' overrides the argument TIMEOUT. + +This function uses `overriding-terminal-local-map', which takes precedence +over all other keymaps. As usual, if no match for a key is found in MAP, +the normal key lookup sequence then continues. This returns an \"exit function\", which can be called with no argument to deactivate this transient map, regardless of KEEP-PRED." - (let* ((clearfun (make-symbol "clear-transient-map")) + (let* ((timeout (or set-transient-map-timeout timeout)) + (message + (when message + (let (keys) + (map-keymap (lambda (key cmd) (and cmd (push key keys))) map) + (format-spec (if (stringp message) message "Repeat with %k") + `((?k . ,(mapconcat + (lambda (key) + (substitute-command-keys + (format "\\`%s'" + (key-description (vector key))))) + keys ", "))))))) + (clearfun (make-symbol "clear-transient-map")) (exitfun (lambda () (internal-pop-keymap map 'overriding-terminal-local-map) (remove-hook 'pre-command-hook clearfun) + ;; Clear the prompt after exiting. + (when message (message "")) + (when set-transient-map-timer (cancel-timer set-transient-map-timer)) (when on-exit (funcall on-exit))))) ;; Don't use letrec, because equal (in add/remove-hook) could get trapped ;; in a cycle. (bug#46326) (fset clearfun (lambda () (with-demoted-errors "set-transient-map PCH: %S" - (unless (cond + (if (cond ((null keep-pred) nil) ((and (not (eq map (cadr overriding-terminal-local-map))) (memq map (cddr overriding-terminal-local-map))) @@ -6066,9 +6100,15 @@ to deactivate this transient map, regardless of KEEP-PRED." ;; nil and so is `mc`. (and mc (eq this-command mc)))) (t (funcall keep-pred))) + ;; Repeat the message for the next command. + (when message (message "%s" message)) (funcall exitfun))))) (add-hook 'pre-command-hook clearfun) (internal-push-keymap map 'overriding-terminal-local-map) + (when timeout + (when set-transient-map-timer (cancel-timer set-transient-map-timer)) + (setq set-transient-map-timer (run-with-idle-timer timeout nil exitfun))) + (when message (message "%s" message)) exitfun)) ;;;; Progress reporters. commit 6a7bb1ddbc9837b2d2af60236be58723114855ac Author: Stefan Kangas Date: Wed Jul 6 19:29:51 2022 +0200 Make some additional defcustom types more restrictive * lisp/desktop.el (desktop-lazy-idle-delay): * lisp/files.el (dired-kept-versions) (kept-old-versions, kept-new-versions): * lisp/filesets.el (filesets-max-submenu-length) (filesets-max-entry-length, filesets-tree-max-level) (filesets-query-user-limit): * lisp/hi-lock.el (hi-lock-file-patterns-range) (hi-lock-highlight-range): * lisp/ido.el (ido-max-work-directory-list): * lisp/image/gravatar.el (gravatar-cache-ttl): * lisp/imenu.el (imenu-auto-rescan-maxout, imenu-max-items): * lisp/informat.el (Info-split-threshold): * lisp/mail/hashcash.el (hashcash-default-payment) (hashcash-default-accept-payment): * lisp/mail/mail-hist.el (mail-hist-history-size): * lisp/mail/smtpmail.el (smtpmail-retries): * lisp/msb.el (msb-display-most-recently-used): * lisp/nxml/rng-valid.el (rng-state-cache-distance) (rng-validate-chunk-size): * lisp/progmodes/gdb-mi.el (gdb-max-source-window-count): * lisp/recentf.el (recentf-arrange-by-rules-min-items): * lisp/simple.el (kill-ring-max, mark-ring-max) (global-mark-ring-max): * lisp/tab-line.el (tab-line-tab-name-truncated-max): * lisp/term.el (term-buffer-maximum-size, term-input-chunk-size): * lisp/thumbs.el (thumbs-max-image-number) (thumbs-thumbsdir-max-size, thumbs-relief, thumbs-margin) (thumbs-image-resizing-step): * lisp/type-break.el (type-break-interval) (type-break-good-rest-interval, type-break-query-interval) (type-break-warning-repeat): * lisp/vc/compare-w.el (compare-windows-sync-string-size): * lisp/woman.el (woman-fill-column): Use defcustom :type natnum. * lisp/emacs-lisp/backtrace.el (backtrace-line-length): * lisp/doc-view.el (doc-view-conversion-refresh-interval): Use defcustom :type natnum and allow the nil value. * lisp/gnus/spam-stat.el (spam-stat-process-directory-age): Use defcustom :type integer. diff --git a/lisp/desktop.el b/lisp/desktop.el index 947f7cff5c..850d2a86ef 100644 --- a/lisp/desktop.el +++ b/lisp/desktop.el @@ -481,7 +481,7 @@ If value is t, all buffers are restored immediately." (defcustom desktop-lazy-idle-delay 5 "Idle delay before starting to create buffers. See `desktop-restore-eager'." - :type 'integer + :type 'natnum :group 'desktop :version "22.1") diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 25c476b99b..0f659fb8b3 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -378,7 +378,8 @@ After such a refresh newly converted pages will be available for viewing. If set to nil there won't be any refreshes and the pages won't be displayed before conversion of the whole document has finished." - :type 'integer) + :type '(choice natnum + (const :value nil :tag "No refreshes"))) (defcustom doc-view-continuous nil "In Continuous mode reaching the page edge advances to next/previous page. diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el index e305822af1..4f98bf3f4f 100644 --- a/lisp/emacs-lisp/backtrace.el +++ b/lisp/emacs-lisp/backtrace.el @@ -58,7 +58,8 @@ Backtrace mode will attempt to abbreviate printing of backtrace frames by setting `print-level' and `print-length' to make them shorter than this, but success is not guaranteed. If set to nil or zero, backtrace mode will not abbreviate the forms it prints." - :type 'integer + :type '(choice natnum + (const :value nil :tag "Don't abbreviate")) :group 'backtrace :version "27.1") diff --git a/lisp/files.el b/lisp/files.el index b2f035d4df..f84fe7e085 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -316,7 +316,7 @@ The value `never' means do not make them." (defcustom dired-kept-versions 2 "When cleaning directory, number of versions to keep." - :type 'integer + :type 'natnum :group 'backup :group 'dired) @@ -330,16 +330,16 @@ If nil, ask confirmation. Any other value prevents any trimming." (defcustom kept-old-versions 2 "Number of oldest versions to keep when a new numbered backup is made." - :type 'integer + :type 'natnum + :safe #'natnump :group 'backup) -(put 'kept-old-versions 'safe-local-variable 'integerp) (defcustom kept-new-versions 2 "Number of newest versions to keep when a new numbered backup is made. Includes the new backup. Must be greater than 0." - :type 'integer + :type 'natnum + :safe #'natnump :group 'backup) -(put 'kept-new-versions 'safe-local-variable 'integerp) (defcustom require-final-newline nil "Whether to add a newline automatically at the end of the file. diff --git a/lisp/filesets.el b/lisp/filesets.el index b97dda3cd6..b1829793f1 100644 --- a/lisp/filesets.el +++ b/lisp/filesets.el @@ -414,12 +414,12 @@ time to time or if the fileset cache causes troubles." Set this value to 0 to turn menu splitting off. BTW, parts of submenus will not be rewrapped if their length exceeds this value." :set #'filesets-set-default - :type 'integer) + :type 'natnum) (defcustom filesets-max-entry-length 50 "Truncate names of split submenus to this length." :set #'filesets-set-default - :type 'integer) + :type 'natnum) (defcustom filesets-browse-dir-function #'dired "A function or command used for browsing directories. @@ -518,7 +518,7 @@ i.e. how deep the menu should be. Try something like and it should become clear what this option is about. In any case, including directory trees to the menu can take a lot of memory." :set #'filesets-set-default - :type 'integer) + :type 'natnum) (defcustom filesets-commands '(("Isearch" @@ -1027,7 +1027,7 @@ defined in `filesets-ingroup-patterns'." (defcustom filesets-query-user-limit 15 "Query the user before opening a fileset with that many files." :set #'filesets-set-default - :type 'integer) + :type 'natnum) (defun filesets-filter-dir-names (lst &optional negative) diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el index b0d258d67a..084eb3d774 100644 --- a/lisp/gnus/spam-stat.el +++ b/lisp/gnus/spam-stat.el @@ -189,7 +189,7 @@ When using `spam-stat-process-spam-directory' or been touched in this many days will be considered. Without this filter, re-training spam-stat with several thousand messages will start to take a very long time." - :type 'number) + :type 'integer) (defvar spam-stat-last-saved-at nil "Time stamp of last change of spam-stat-file on this run") diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index 8cddd64482..b56f26d529 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -97,7 +97,7 @@ When a file is visited and hi-lock mode is on, patterns starting up to this limit are added to font-lock's patterns. See documentation of functions `hi-lock-mode' and `hi-lock-find-patterns'." - :type 'integer + :type 'natnum :group 'hi-lock) (defcustom hi-lock-highlight-range 2000000 @@ -107,7 +107,7 @@ such as the buffer created by `list-colors-display'. In those buffers hi-lock patterns will only be applied over a range of `hi-lock-highlight-range' characters. If font-lock is active then highlighting will be applied throughout the buffer." - :type 'integer + :type 'natnum :group 'hi-lock) (defcustom hi-lock-exclude-modes diff --git a/lisp/ido.el b/lisp/ido.el index b3365059d2..134081d675 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -554,7 +554,7 @@ See `ido-last-directory-list' and `ido-save-directory-list-file'." "Maximum number of working directories to record. This is the list of directories where files have most recently been opened. See `ido-work-directory-list' and `ido-save-directory-list-file'." - :type 'integer) + :type 'natnum) (defcustom ido-work-directory-list-ignore-regexps nil "List of regexps matching directories which should not be recorded. diff --git a/lisp/image/gravatar.el b/lisp/image/gravatar.el index 78a2df72c4..8c49c1edf2 100644 --- a/lisp/image/gravatar.el +++ b/lisp/image/gravatar.el @@ -45,7 +45,7 @@ "Time to live in seconds for gravatar cache entries. If a requested gravatar has been cached for longer than this, it is retrieved anew. The default value is 30 days." - :type 'integer + :type 'natnum ;; Restricted :type to number of seconds. :version "27.1" :group 'gravatar) diff --git a/lisp/imenu.el b/lisp/imenu.el index 4393c6ed6c..040e373fb4 100644 --- a/lisp/imenu.el +++ b/lisp/imenu.el @@ -87,7 +87,7 @@ This might not yet be honored by all index-building functions." (defcustom imenu-auto-rescan-maxout 600000 "Imenu auto-rescan is disabled in buffers larger than this size (in bytes). Also see `imenu-max-index-time'." - :type 'integer + :type 'natnum :version "26.2") (defcustom imenu-use-popup-menu 'on-mouse @@ -132,7 +132,7 @@ element should come before the second. The arguments are cons cells; (defcustom imenu-max-items 25 "Maximum number of elements in a mouse menu for Imenu." - :type 'integer) + :type 'natnum) (defcustom imenu-space-replacement "." "The replacement string for spaces in index names. diff --git a/lisp/informat.el b/lisp/informat.el index e7595fa541..c126ab5b1a 100644 --- a/lisp/informat.el +++ b/lisp/informat.el @@ -158,7 +158,7 @@ ;;;###autoload (defcustom Info-split-threshold 262144 "The number of characters by which `Info-split' splits an info file." - :type 'integer + :type 'natnum :version "23.1" :group 'texinfo) diff --git a/lisp/mail/hashcash.el b/lisp/mail/hashcash.el index b343a017e3..8d274d9cac 100644 --- a/lisp/mail/hashcash.el +++ b/lisp/mail/hashcash.el @@ -57,7 +57,7 @@ "The default number of bits to pay to unknown users. If this is zero, no payment header will be generated. See `hashcash-payment-alist'." - :type 'integer + :type 'natnum :group 'hashcash) (defcustom hashcash-payment-alist '() @@ -77,7 +77,7 @@ present, is the string to be hashed; if not present ADDR will be used." (defcustom hashcash-default-accept-payment 20 "The default minimum number of bits to accept on incoming payments." - :type 'integer + :type 'natnum :group 'hashcash) (defcustom hashcash-accept-resources `((,user-mail-address nil)) diff --git a/lisp/mail/mail-hist.el b/lisp/mail/mail-hist.el index e02d4218dd..a13f9de174 100644 --- a/lisp/mail/mail-hist.el +++ b/lisp/mail/mail-hist.el @@ -80,7 +80,7 @@ previous/next input.") (defcustom mail-hist-history-size (or kill-ring-max 1729) "The maximum number of elements in a mail field's history. Oldest elements are dumped first." - :type 'integer) + :type 'natnum) ;;;###autoload (defcustom mail-hist-keep-history t diff --git a/lisp/mail/smtpmail.el b/lisp/mail/smtpmail.el index 88e55e968c..da786dec00 100644 --- a/lisp/mail/smtpmail.el +++ b/lisp/mail/smtpmail.el @@ -171,7 +171,7 @@ attempt." "The number of times smtpmail will retry sending when getting transient errors. These are errors with a code of 4xx from the SMTP server, which mean \"try again\"." - :type 'integer + :type 'natnum :version "27.1") (defcustom smtpmail-store-queue-variables nil diff --git a/lisp/msb.el b/lisp/msb.el index 6e1d03ac27..616799f067 100644 --- a/lisp/msb.el +++ b/lisp/msb.el @@ -299,7 +299,7 @@ If the value is not a number, then the value 10 is used." (defcustom msb-display-most-recently-used 15 "How many buffers should be in the most-recently-used menu. No buffers at all if less than 1 or nil (or any non-number)." - :type 'integer + :type 'natnum :set #'msb-custom-set) (defcustom msb-most-recently-used-title "Most recently used (%d)" diff --git a/lisp/nxml/rng-valid.el b/lisp/nxml/rng-valid.el index 56ff3b66c0..b9c980222e 100644 --- a/lisp/nxml/rng-valid.el +++ b/lisp/nxml/rng-valid.el @@ -110,14 +110,14 @@ (defcustom rng-state-cache-distance 2000 "Distance in characters between each parsing and validation state cache." - :type 'integer) + :type 'natnum) (defcustom rng-validate-chunk-size 8000 "Number of characters in a RELAX NG validation chunk. A validation chunk will be the smallest chunk that is at least this size and ends with a tag. After validating a chunk, validation will continue only if Emacs is still idle." - :type 'integer) + :type 'natnum) (defcustom rng-validate-delay 1.5 "Time in seconds that Emacs must be idle before starting a full validation. diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 03beb06569..21bb75ae0c 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -684,7 +684,7 @@ Note that this variable only takes effect when variable Until there are such number of source windows on screen, GDB tries to open a new window when visiting a new source file; after that GDB starts to reuse existing source windows." - :type 'number + :type 'natnum :group 'gdb :version "28.1") diff --git a/lisp/recentf.el b/lisp/recentf.el index 4bc1ab5c21..b80ee3dd7d 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -837,7 +837,7 @@ corresponding sub-menu items are displayed in the main recent files menu or in the `recentf-arrange-by-rule-others' sub-menu if defined." :group 'recentf-filters - :type 'number) + :type 'natnum) (defcustom recentf-arrange-by-rule-subfilter nil "Function called by a rule based filter to filter sub-menu elements. diff --git a/lisp/simple.el b/lisp/simple.el index 042384bbe7..e79487eba8 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -5456,7 +5456,7 @@ ring directly.") (defcustom kill-ring-max 120 "Maximum length of kill ring before oldest elements are thrown away." - :type 'integer + :type 'natnum :group 'killing :version "29.1") @@ -7026,7 +7026,7 @@ is set to the buffer displayed in that window.") (defcustom mark-ring-max 16 "Maximum size of mark ring. Start discarding off end if gets this big." - :type 'integer + :type 'natnum :group 'editing-basics) (defvar global-mark-ring nil @@ -7035,7 +7035,7 @@ is set to the buffer displayed in that window.") (defcustom global-mark-ring-max 16 "Maximum size of global mark ring. \ Start discarding off end if gets this big." - :type 'integer + :type 'natnum :group 'editing-basics) (defun pop-to-mark-command () diff --git a/lisp/tab-line.el b/lisp/tab-line.el index 80b0aabd77..3e3b4c9559 100644 --- a/lisp/tab-line.el +++ b/lisp/tab-line.el @@ -288,7 +288,7 @@ variable `tab-line-tab-name-function'." "Maximum length of the tab name from the current buffer. Effective when `tab-line-tab-name-function' is customized to `tab-line-tab-name-truncated-buffer'." - :type 'integer + :type 'natnum :group 'tab-line :version "27.1") diff --git a/lisp/term.el b/lisp/term.el index c129ed976d..a28d8c5d76 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -915,7 +915,7 @@ Term buffers are truncated from the top to be no greater than this number. Notice that a setting of 0 means \"don't truncate anything\". This variable is buffer-local." :group 'term - :type 'integer + :type 'natnum :version "27.1") (defcustom term-bind-function-keys nil @@ -2473,7 +2473,7 @@ Checks if STRING contains a password prompt as defined by "Long inputs send to term processes are broken up into chunks of this size. If your process is choking on big inputs, try lowering the value." :group 'term - :type 'integer) + :type 'natnum) (defun term-send-string (proc str) "Send to PROC the contents of STR as input. diff --git a/lisp/thumbs.el b/lisp/thumbs.el index e622bcedc4..158597d7c8 100644 --- a/lisp/thumbs.el +++ b/lisp/thumbs.el @@ -73,16 +73,16 @@ (defcustom thumbs-per-line 4 "Number of thumbnails per line to show in directory." - :type 'integer) + :type 'natnum) (defcustom thumbs-max-image-number 16 - "Maximum number of images initially displayed in thumbs buffer." - :type 'integer) + "Maximum number of images initially displayed in thumbs buffer." + :type 'natnum) (defcustom thumbs-thumbsdir-max-size 50000000 "Maximum size for thumbnails directory. -When it reaches that size (in bytes), a warning is sent." - :type 'integer) +When it reaches that size (in bytes), a warning is displayed." + :type 'natnum) ;; Unfortunately Windows XP has a program called CONVERT.EXE in ;; C:/WINDOWS/SYSTEM32/ for partitioning NTFS systems. So Emacs @@ -106,12 +106,12 @@ This must be the ImageMagick \"convert\" utility." (defcustom thumbs-relief 5 "Size of button-like border around thumbnails." - :type 'integer) + :type 'natnum) (defcustom thumbs-margin 2 "Size of the margin around thumbnails. This is where you see the cursor." - :type 'integer) + :type 'natnum) (defcustom thumbs-thumbsdir-auto-clean t "If set, delete older file in the thumbnails directory. @@ -121,7 +121,7 @@ than `thumbs-thumbsdir-max-size'." (defcustom thumbs-image-resizing-step 10 "Step by which to resize image as a percentage." - :type 'integer) + :type 'natnum) (defcustom thumbs-temp-dir temporary-file-directory "Temporary directory to use. diff --git a/lisp/type-break.el b/lisp/type-break.el index 267facccc4..dca5a43b89 100644 --- a/lisp/type-break.el +++ b/lisp/type-break.el @@ -69,7 +69,7 @@ (defcustom type-break-interval (* 60 60) "Number of seconds between scheduled typing breaks." - :type 'integer + :type 'natnum :group 'type-break) (defcustom type-break-good-rest-interval (/ type-break-interval 6) @@ -82,7 +82,7 @@ rest from typing, then the next typing break is simply rescheduled for later. If a break is interrupted before this much time elapses, the user will be asked whether or not really to interrupt the break." :set-after '(type-break-interval) - :type 'integer + :type 'natnum :group 'type-break) (defcustom type-break-good-break-interval nil @@ -148,7 +148,7 @@ To avoid being queried at all, set `type-break-query-mode' to nil." "Number of seconds between queries to take a break, if put off. The user will continue to be prompted at this interval until he or she finally submits to taking a typing break." - :type 'integer + :type 'natnum :group 'type-break) (defcustom type-break-time-warning-intervals '(300 120 60 30) @@ -171,7 +171,7 @@ will occur." "Number of keystrokes for which warnings should be repeated. That is, for each of this many keystrokes the warning is redisplayed in the echo area to make sure it's really seen." - :type 'integer + :type 'natnum :group 'type-break) (defcustom type-break-time-stamp-format "[%H:%M] " diff --git a/lisp/vc/compare-w.el b/lisp/vc/compare-w.el index b56b4c0d83..64d5d1081a 100644 --- a/lisp/vc/compare-w.el +++ b/lisp/vc/compare-w.el @@ -1,7 +1,6 @@ ;;; compare-w.el --- compare text between windows for Emacs -*- lexical-binding: t; -*- -;; Copyright (C) 1986, 1989, 1993, 1997, 2001-2022 Free Software -;; Foundation, Inc. +;; Copyright (C) 1986-2022 Free Software Foundation, Inc. ;; Maintainer: emacs-devel@gnu.org ;; Keywords: convenience files vc @@ -99,7 +98,7 @@ may fail by finding the wrong match. The bigger number makes difference regions more coarse-grained. The default value 32 is good for the most cases." - :type 'integer + :type 'natnum :version "22.1") (defcustom compare-windows-recenter nil diff --git a/lisp/woman.el b/lisp/woman.el index fd5fee2005..73e068a822 100644 --- a/lisp/woman.el +++ b/lisp/woman.el @@ -843,7 +843,7 @@ Only useful when run on a graphic display such as X or MS-Windows." (defcustom woman-fill-column 65 "Right margin for formatted text -- default is 65." - :type 'integer + :type 'natnum :group 'woman-formatting) (defcustom woman-fill-frame nil commit 22bcbf8e2cc271555a737c176c48e89daa0c17be Author: Stefan Kangas Date: Wed Jul 6 15:25:56 2022 +0200 Fix missing :value with defcustom const :type * lisp/calendar/calendar.el (calendar-intermonth-header) (calendar-intermonth-text, calendar-date-style): * lisp/calendar/diary-lib.el (diary-face-attrs): * lisp/emacs-lisp/package.el (package-check-signature): * lisp/erc/erc-dcc.el (erc-dcc-get-default-directory): * lisp/gnus/gnus-art.el (gnus-auto-select-part): * lisp/gnus/gnus-cus.el (gnus-agent-parameters): * lisp/gnus/gnus.el (gnus-user-agent): * lisp/mail/rmail.el (rmail-retry-ignored-headers): * lisp/progmodes/sh-script.el (sh-indent-after-continuation): Fix missing :value with defcustom const :type. diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el index 0d9e697644..c1f176050c 100644 --- a/lisp/calendar/calendar.el +++ b/lisp/calendar/calendar.el @@ -565,7 +565,7 @@ See `calendar-intermonth-text'." :set (lambda (sym val) (set sym val) (calendar-redraw)) - :type '(choice (const nil :tag "Nothing") + :type '(choice (const :value nil :tag "Nothing") (string :tag "Fixed string") (sexp :value (propertize "WK" 'font-lock-face @@ -597,7 +597,7 @@ See also `calendar-intermonth-header'." :set (lambda (sym val) (set sym val) (calendar-redraw)) - :type '(choice (const nil :tag "Nothing") + :type '(choice (const :value nil :tag "Nothing") (string :tag "Fixed string") (sexp :value (propertize @@ -742,9 +742,9 @@ Setting this variable directly does not take effect (if the calendar package is already loaded). Rather, use either \\[customize] or the function `calendar-set-date-style'." :version "23.1" - :type '(choice (const american :tag "Month/Day/Year") - (const european :tag "Day/Month/Year") - (const iso :tag "Year/Month/Day")) + :type '(choice (const :value american :tag "American (Month/Day/Year)") + (const :value european :tag "European (Day/Month/Year)") + (const :value iso :tag "ISO 8601 (Year/Month/Day)")) :initialize 'custom-initialize-default :set (lambda (_symbol value) (calendar-set-date-style value)) diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el index 48dbf33adf..084d2d7d55 100644 --- a/lisp/calendar/diary-lib.el +++ b/lisp/calendar/diary-lib.el @@ -100,11 +100,11 @@ are: `string', `symbol', `int', `tnil', `stringtnil'." :type '(repeat (list (regexp :tag "Regular expression") (integer :tag "Sub-expression") (symbol :tag "Attribute (e.g. :foreground)") - (choice (const string :tag "A string") - (const symbol :tag "A symbol") - (const int :tag "An integer") - (const tnil :tag "t or nil") - (const stringtnil + (choice (const :value string :tag "A string") + (const :value symbol :tag "A symbol") + (const :value int :tag "An integer") + (const :value tnil :tag "t or nil") + (const :value stringtnil :tag "A string, t, or nil")))) :group 'diary) diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 85a154a8e0..c8b6667597 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -355,10 +355,10 @@ More specifically the value can be: This also applies to the \"archive-contents\" file that lists the contents of the archive." - :type '(choice (const nil :tag "Never") - (const allow-unsigned :tag "Allow unsigned") - (const t :tag "Check always") - (const all :tag "Check all signatures")) + :type '(choice (const :value nil :tag "Never") + (const :value allow-unsigned :tag "Allow unsigned") + (const :value t :tag "Check always") + (const :value all :tag "Check all signatures")) :risky t :version "27.1") diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el index ff486b2d4e..d0e1848e0e 100644 --- a/lisp/erc/erc-dcc.el +++ b/lisp/erc/erc-dcc.el @@ -391,7 +391,7 @@ the accepted connection." (defcustom erc-dcc-get-default-directory nil "Default directory for incoming DCC file transfers. If this is nil, then the current value of `default-directory' is used." - :type '(choice (const nil :tag "Default directory") directory)) + :type '(choice (const :value nil :tag "Default directory") directory)) ;;;###autoload (defun erc-cmd-DCC (cmd &rest args) diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 2a56a12dbb..4b68a54ce8 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -1091,9 +1091,9 @@ positive (negative), move point forward (backwards) this many parts. When nil, redisplay article." :version "23.1" ;; No Gnus :group 'gnus-article-mime - :type '(choice (const nil :tag "Redisplay article.") - (const 1 :tag "Next part.") - (const 0 :tag "Current part.") + :type '(choice (const :value nil :tag "Redisplay article") + (const :value 1 :tag "Next part") + (const :value 0 :tag "Current part") integer)) ;;; diff --git a/lisp/gnus/gnus-cus.el b/lisp/gnus/gnus-cus.el index f8714a95d4..ddd939794d 100644 --- a/lisp/gnus/gnus-cus.el +++ b/lisp/gnus/gnus-cus.el @@ -273,7 +273,7 @@ DOC is a documentation string for the parameter.") gnus-agent-cat-predicate) (agent-score (choice :tag "Score File" :value nil - (const file :tag "Use group's score files") + (const :value file :tag "Use group's score files") (repeat (list (string :format "%v" :tag "File name")))) "Which score files to use when using score to select articles to fetch. diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index f60c11f985..2119e68509 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el @@ -2263,12 +2263,12 @@ a string, be sure to use a valid format, see RFC 2616." :version "22.1" :group 'gnus-message :type '(choice (list (set :inline t - (const gnus :tag "Gnus version") - (const emacs :tag "Emacs version") + (const :value gnus :tag "Gnus version") + (const :value emacs :tag "Emacs version") (choice :tag "system" - (const type :tag "system type") - (const config :tag "system configuration")) - (const codename :tag "Emacs codename"))) + (const :value type :tag "system type") + (const :value config :tag "system configuration")) + (const :value codename :tag "Emacs codename"))) (string))) ;; Convert old (< 2005-01-10) symbol type values: diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index adb61aa09d..b2b21b88ef 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el @@ -388,7 +388,7 @@ If nil, display all header fields except those matched by ;;;###autoload (defcustom rmail-retry-ignored-headers (purecopy "^x-authentication-warning:\\|^x-detected-operating-system:\\|^x-spam[-a-z]*:\\|content-type:\\|content-transfer-encoding:\\|mime-version:\\|message-id:") "Headers that should be stripped when retrying a failed message." - :type '(choice regexp (const nil :tag "None")) + :type '(choice regexp (const :value nil :tag "None")) :group 'rmail-headers :version "23.2") ; added x-detected-operating-system, x-spam diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index c3e93c397a..71fb0cd2e0 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -1926,9 +1926,9 @@ With t, you get the latter as long as that would indent the continuation line deeper than the initial line." :version "25.1" :type '(choice - (const nil :tag "Never") - (const t :tag "Only if needed to make it deeper") - (const always :tag "Always")) + (const :value nil :tag "Never") + (const :value t :tag "Only if needed to make it deeper") + (const :value always :tag "Always")) :group 'sh-indentation) (defun sh-smie--continuation-start-indent () commit b5cd9343aea2d7939209c35eef3247946df24dfa Author: Po Lu Date: Wed Jul 6 12:23:19 2022 +0000 Fix infinite looping around Haiku menus * src/haikumenu.c (haiku_menu_show): Block SIGIO around menu event loop. * src/haikuterm.c (haiku_read_socket): Flush tooltip frames after resize. diff --git a/src/haikumenu.c b/src/haikumenu.c index 5729bed4a9..3f68eadfd9 100644 --- a/src/haikumenu.c +++ b/src/haikumenu.c @@ -422,11 +422,13 @@ haiku_menu_show (struct frame *f, int x, int y, int menuflags, BView_convert_to_screen (view, &x, &y); unblock_input (); + unrequest_sigio (); popup_activated_p++; menu_item_selection = BMenu_run (menu, x, y, haiku_menu_show_help, block_input, unblock_input, haiku_process_pending_signals_for_menu, NULL); popup_activated_p--; + request_sigio (); FRAME_DISPLAY_INFO (f)->grabbed = 0; diff --git a/src/haikuterm.c b/src/haikuterm.c index 9f8aceae64..d7247c99e0 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3202,6 +3202,11 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) FRAME_PIXEL_HEIGHT (f) = height; haiku_clear_under_internal_border (f); + + /* Flush the frame and flip buffers here. It is + necessary for tooltips displayed inside menus, as + redisplay cannot happen. */ + haiku_flush (f); continue; } @@ -4438,6 +4443,7 @@ haiku_clear_under_internal_border (struct frame *f) : INTERNAL_BORDER_FACE_ID)); struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); void *view = FRAME_HAIKU_VIEW (f); + block_input (); BView_draw_lock (view, true, 0, 0, FRAME_PIXEL_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); commit a2e56a8d659d31466c248a38a954a1b165087781 Author: Davide Masserut Date: Wed Jul 6 13:45:40 2022 +0200 Send region to the subshell specified by the current file interpreter * sh-script.el (sh-execute-region): Send region to the subshell specified by the current file interpreter (bug#56406). diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index 75758fd39a..c3e93c397a 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -2410,6 +2410,8 @@ Lines containing only comments are considered empty." The working directory is that of the buffer, and only environment variables are already set which is why you can mark a header within the script. +The executed subshell is `sh-shell-file'. + With a positive prefix ARG, instead of sending region, define header from beginning of buffer to point. With a negative prefix ARG, instead of sending region, clear header." @@ -2417,17 +2419,18 @@ region, clear header." (if flag (setq sh-header-marker (if (> (prefix-numeric-value flag) 0) (point-marker))) - (if sh-header-marker - (save-excursion - (let (buffer-undo-list) - (goto-char sh-header-marker) - (append-to-buffer (current-buffer) start end) - (shell-command-on-region (point-min) - (setq end (+ sh-header-marker - (- end start))) - sh-shell-file) - (delete-region sh-header-marker end))) - (shell-command-on-region start end (concat sh-shell-file " -"))))) + (let ((shell-file-name sh-shell-file)) + (if sh-header-marker + (save-excursion + (let (buffer-undo-list) + (goto-char sh-header-marker) + (append-to-buffer (current-buffer) start end) + (shell-command-on-region (point-min) + (setq end (+ sh-header-marker + (- end start))) + sh-shell-file) + (delete-region sh-header-marker end))) + (shell-command-on-region start end (concat sh-shell-file " -")))))) (defun sh-remember-variable (var) commit 706d1fb5ec3151adf4886bd867710acdc88b9786 Author: Manuel Giraud Date: Wed Jul 6 13:18:09 2022 +0200 Remove soft newlines in longlines-mode * lisp/longlines.el (longlines-mode, longlines-encode-string): Update from `buffer-substring-filters' to `filter-buffer-substring-function'. Remove soft newlines in substring (bug#56335). diff --git a/lisp/longlines.el b/lisp/longlines.el index a6cf93a039..6dc2f61ed9 100644 --- a/lisp/longlines.el +++ b/lisp/longlines.el @@ -118,7 +118,6 @@ newlines are indicated with a symbol." (add-to-list 'buffer-file-format 'longlines) (add-hook 'change-major-mode-hook #'longlines-mode-off nil t) (add-hook 'before-revert-hook #'longlines-before-revert-hook nil t) - (make-local-variable 'buffer-substring-filters) (make-local-variable 'longlines-auto-wrap) (set (make-local-variable 'isearch-search-fun-function) #'longlines-search-function) @@ -126,7 +125,8 @@ newlines are indicated with a symbol." #'longlines-search-forward) (set (make-local-variable 'replace-re-search-function) #'longlines-re-search-forward) - (add-to-list 'buffer-substring-filters 'longlines-encode-string) + (add-function :filter-return (local 'filter-buffer-substring-function) + #'longlines-encode-string) (when longlines-wrap-follows-window-size (let ((dw (if (and (integerp longlines-wrap-follows-window-size) (>= longlines-wrap-follows-window-size 0) @@ -143,7 +143,7 @@ newlines are indicated with a symbol." (inhibit-modification-hooks t) (mod (buffer-modified-p)) buffer-file-name buffer-file-truename) - ;; Turning off undo is OK since (spaces + newlines) is + ;; Turning off undo is OK since (separators + newlines) is ;; conserved, except for a corner case in ;; longlines-wrap-lines that we'll never encounter from here (save-restriction @@ -202,7 +202,8 @@ newlines are indicated with a symbol." (kill-local-variable 'replace-search-function) (kill-local-variable 'replace-re-search-function) (kill-local-variable 'require-final-newline) - (kill-local-variable 'buffer-substring-filters) + (remove-function (local 'filter-buffer-substring-function) + #'longlines-encode-string) (kill-local-variable 'use-hard-newlines))) (defun longlines-mode-off () @@ -385,15 +386,22 @@ compatibility with `format-alist', and is ignored." end))) (defun longlines-encode-string (string) - "Return a copy of STRING with each soft newline replaced by a space. + "Return a copy of STRING with each soft newline removed. Hard newlines are left intact." - (let* ((str (copy-sequence string)) - (pos (string-search "\n" str))) - (while pos - (if (null (get-text-property pos 'hard str)) - (aset str pos ? )) - (setq pos (string-search "\n" str (1+ pos)))) - str)) + (let ((start 0) + (result nil) + pos) + (while (setq pos (string-search "\n" string start)) + (unless (= start pos) + (push (substring string start pos) result)) + (when (get-text-property pos 'hard string) + (push (substring string pos (1+ pos)) result)) + (setq start (1+ pos))) + (if (null result) + (copy-sequence string) + (unless (= start (length string)) + (push (substring string start) result)) + (apply #'concat (nreverse result))))) ;;; Auto wrap commit f9d01e504711676d7c223ad9543256a9d34fde55 Author: Stefan Kangas Date: Wed Jul 6 12:31:01 2022 +0200 ; * lisp/emacs-lisp/ert.el: Remove installation instructions. (cherry picked from commit ef218ac936c3ffe219b57e37e684fd8400389c38) diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 41180f9914..156eeadb5d 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -47,8 +47,6 @@ ;; environment (like availability of features, external binaries, etc). ;; ;; See ERT's info manual as well as the docstrings for more details. -;; To compile the manual, run `makeinfo ert.texinfo' in the ERT -;; directory, then C-u M-x info ert.info in Emacs to view it. ;; ;; To see some examples of tests written in ERT, see its self-tests in ;; ert-tests.el. Some of these are tricky due to the bootstrapping commit ef218ac936c3ffe219b57e37e684fd8400389c38 Author: Stefan Kangas Date: Wed Jul 6 12:31:01 2022 +0200 ; * lisp/emacs-lisp/ert.el: Remove installation instructions. diff --git a/lisp/emacs-lisp/ert.el b/lisp/emacs-lisp/ert.el index 82722add42..262d85f9b4 100644 --- a/lisp/emacs-lisp/ert.el +++ b/lisp/emacs-lisp/ert.el @@ -47,8 +47,6 @@ ;; environment (like availability of features, external binaries, etc). ;; ;; See ERT's info manual as well as the docstrings for more details. -;; To compile the manual, run `makeinfo ert.texinfo' in the ERT -;; directory, then C-u M-x info ert.info in Emacs to view it. ;; ;; To see some examples of tests written in ERT, see its self-tests in ;; ert-tests.el. Some of these are tricky due to the bootstrapping commit f65e4c46a3418c7f24f53503feda42e844951997 Author: F. Jason Park Date: Tue Jul 5 03:46:00 2022 -0700 * lisp/erc/erc-track.el (erc-track-minor-mode-map): Doc fix. diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el index d02a8d13e5..ef9a8c243e 100644 --- a/lisp/erc/erc-track.el +++ b/lisp/erc/erc-track.el @@ -458,7 +458,7 @@ START is the minimum length of the name used." (define-key map (kbd "C-c C-@") #'erc-track-switch-buffer) (define-key map (kbd "C-c C-SPC") #'erc-track-switch-buffer) map) - "Keymap for rcirc track minor mode.") + "Keymap for ERC track minor mode.") ;;;###autoload (define-minor-mode erc-track-minor-mode commit 0bacb8f9e74aefd39c492d34b01800aeb1e53c98 Author: dickmao Date: Fri Jul 1 11:06:51 2022 -0400 Use compatibility macro for ISUPPORT caching in ERC * lisp/erc/erc-backend.el (erc--with-memoization): Defalias was a kung-fu I've never seen before. (Bug#56340) diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index bee2551d76..bc7a7d14dc 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -1673,12 +1673,15 @@ Then display the welcome message." (split-string value ",") (list value))))) -;; FIXME move to erc-compat (once we decide how to load it) -(defalias 'erc--with-memoization - (cond - ((fboundp 'with-memoization) #'with-memoization) ; 29.1 - ((fboundp 'cl--generic-with-memoization) #'cl--generic-with-memoization) - (t (lambda (_ v) v)))) +(defmacro erc--with-memoization (table &rest forms) + "Adapter to be migrated to erc-compat." + (declare (indent defun)) + `(cond + ((fboundp 'with-memoization) + (with-memoization ,table ,@forms)) ; 29.1 + ((fboundp 'cl--generic-with-memoization) + (cl--generic-with-memoization ,table ,@forms)) + (t ,@forms))) (defun erc--get-isupport-entry (key &optional single) "Return an item for \"ISUPPORT\" token KEY, a symbol. commit e6504c3eda12c72268d2db6598764f043b74c24d Author: Po Lu Date: Wed Jul 6 16:31:54 2022 +0800 Stop synchronizing after sending XEmbed events * src/xterm.c (xembed_send_message): Don't sync and handle errors, which is actually why the XSync call in the spec exists. diff --git a/src/xterm.c b/src/xterm.c index 0180ea3c78..225c45ff7c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -25208,9 +25208,14 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg, event.xclient.data.l[3] = data1; event.xclient.data.l[4] = data2; + /* XXX: the XEmbed spec tells us to trap errors around this request, + but I don't understand why: there is no way for clients to + survive the death of the parent anyway. */ + + x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f)); XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc, False, NoEventMask, &event); - XSync (FRAME_X_DISPLAY (f), False); + x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f)); } /* Change of visibility. */ commit 939dc2ff126dbca1f1c31989f2c11a4fdc35648c Author: Martin Rudalics Date: Wed Jul 6 09:25:43 2022 +0200 Fix 'fit-frame-to-buffer' (Bug#56102) * lisp/window.el (fit-frame-to-buffer-sizes): Fix doc-string. Give calls to 'max' a second argument so they do something useful. If ONLY equals 'vertically', call 'window-text-pixel-size' with X-LIMIT nil (Bug#56102). For minimum sizes of the window to fit, use 'window-safe-min-size' by default. * doc/lispref/windows.texi (Resizing Windows): Fix descriptions of 'fit-frame-to-buffer' and 'fit-frame-to-buffer-sizes'. diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 704ed30366..535571b316 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -1158,11 +1158,13 @@ frame to its buffer using the command @code{fit-frame-to-buffer}. This command adjusts the size of @var{frame} to display the contents of its buffer exactly. @var{frame} can be any live frame and defaults to the selected one. Fitting is done only if @var{frame}'s root window is -live. The arguments @var{max-height}, @var{min-height}, @var{max-width} -and @var{min-width} specify bounds on the new total size of -@var{frame}'s root window. @var{min-height} and @var{min-width} default -to the values of @code{window-min-height} and @code{window-min-width} -respectively. +live. + +The arguments @var{max-height}, @var{min-height}, @var{max-width} and +@var{min-width}, if non-@code{nil}, specify bounds on the new body size +of @var{frame}'s root window. A non-@code{nil} value specified by any +of these arguments overrides the corresponding value specified by +the option @code{fit-frame-to-buffer-sizes} described below. If the optional argument @var{only} is @code{vertically}, this function may resize the frame vertically only. If @var{only} is @@ -1187,10 +1189,10 @@ here can be overridden for a specific frame by that frame's @defopt fit-frame-to-buffer-sizes This option specifies size boundaries for @code{fit-frame-to-buffer}. -It specifies the total maximum and minimum lines and maximum and minimum -columns of the root window of any frame that shall be fit to its buffer. -If any of these values is non-@code{nil}, it overrides the corresponding -argument of @code{fit-frame-to-buffer}. +It specifies the maximum and minimum lines and maximum and minimum +columns of the root window's body of any frame that shall be fit to its +buffer. Any value this option specifies will be overridden by the +corresponding argument of @code{fit-frame-to-buffer}, if non-@code{nil}. @end defopt @deffn Command shrink-window-if-larger-than-buffer &optional window diff --git a/lisp/window.el b/lisp/window.el index a3ef2521bb..4d88ffa903 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -9179,10 +9179,11 @@ present. See also `fit-frame-to-buffer-sizes'." (defcustom fit-frame-to-buffer-sizes '(nil nil nil nil) "Size boundaries of frame for `fit-frame-to-buffer'. -This list specifies the total maximum and minimum lines and -maximum and minimum columns of the root window of any frame that -shall be fit to its buffer. If any of these values is non-nil, -it overrides the corresponding argument of `fit-frame-to-buffer'. +This list specifies the total maximum and minimum numbers of +lines and the maximum and minimum numbers of columns of the body +of the root window of any frame that shall be fit to its buffer. +Any value specified by ths variable will be overridden by the +corresponding argument of `fit-frame-to-buffer', if non-nil. On window systems where the menubar can wrap, fitting a frame to its buffer may swallow the last line(s). Specifying an @@ -9378,30 +9379,30 @@ for `fit-frame-to-buffer'." (t parent-or-display-height)) ;; The following is the maximum height that fits into the ;; top and bottom margins. - (max (- bottom-margin top-margin outer-minus-body-height)))) + (max (- bottom-margin top-margin outer-minus-body-height) 0))) (min-height (cond ((numberp min-height) (* min-height line-height)) ((numberp (nth 1 sizes)) (* (nth 1 sizes) line-height)) - (t (window-min-size window nil nil t)))) + (t (window-safe-min-size window nil t)))) (max-width - (min - (cond - ((numberp max-width) (* max-width char-width)) - ((numberp (nth 2 sizes)) (* (nth 2 sizes) char-width)) - (t parent-or-display-width)) - ;; The following is the maximum width that fits into the - ;; left and right margins. - (max (- right-margin left-margin outer-minus-body-width)))) + (unless (eq only 'vertically) + (min + (cond + ((numberp max-width) (* max-width char-width)) + ((numberp (nth 2 sizes)) (* (nth 2 sizes) char-width)) + (t parent-or-display-width)) + ;; The following is the maximum width that fits into the + ;; left and right margins. + (max (- right-margin left-margin outer-minus-body-width) 0)))) (min-width (cond ((numberp min-width) (* min-width char-width)) - ((numberp (nth 3 sizes)) (nth 3 sizes)) - (t (window-min-size window t nil t)))) + ((numberp (nth 3 sizes)) (* (nth 3 sizes) char-width)) + (t (window-safe-min-size window t t)))) ;; Note: Currently, for a new frame the sizes of the header ;; and mode line may be estimated incorrectly - (size - (window-text-pixel-size window from to max-width max-height)) + (size (window-text-pixel-size window from to max-width max-height)) (width (max (car size) min-width)) (height (max (cdr size) min-height))) ;; Don't change height or width when the window's size is fixed commit 15404818503e0d3df7a8c56af13e4123bd231989 Author: Po Lu Date: Wed Jul 6 14:09:51 2022 +0800 Fix the MS-DOS build * msdos/sedlibmk.inp: Define GL_GNULIB_RAWMEMCHR. * src/process.c (Fsignal_names): Disable on MS-DOS and use SIGNUM_BOUND, which is always provided by gnulib. diff --git a/msdos/sedlibmk.inp b/msdos/sedlibmk.inp index 302fefe19f..9847e710c0 100644 --- a/msdos/sedlibmk.inp +++ b/msdos/sedlibmk.inp @@ -192,6 +192,9 @@ s/@PACKAGE@/emacs/ /^GL_GNULIB_TIMEGM *=/s/@GL_GNULIB_TIMEGM@/1/ /^GL_GNULIB_TIME_RZ *=/s/@GL_GNULIB_TIME_RZ@/1/ /^GL_GNULIB_UNSETENV *=/s/@GL_GNULIB_UNSETENV@/1/ +# Apparently without this `rawmemchr' isn't declared, so +# we get warnings building canonicalize-lgpl.o +/^GL_GNULIB_RAWMEMCHR *=/s/@GL_GNULIB_RAWMEMCHR@/1/ /^GL_GNULIB_[^ =]* *= *@/s/@[^@\n]*@/0/ /^GL_GSETTINGS_CFLAGS *=/s/@[^@\n]*@// /^GL_GSETTINGS_LIBS *=/s/@[^@\n]*@// diff --git a/src/process.c b/src/process.c index af402c8edb..d6d51b26e1 100644 --- a/src/process.c +++ b/src/process.c @@ -8321,14 +8321,21 @@ DEFUN ("signal-names", Fsignal_names, Ssignal_names, 0, 0, 0, doc: /* Return a list of known signal names on this system. */) (void) { +#ifndef MSDOS + int i; char name[SIG2STR_MAX]; Lisp_Object names = Qnil; - for (int i = 0; i < 256; ++i) + + for (i = 0; i <= SIGNUM_BOUND; ++i) { if (!sig2str (i, name)) names = Fcons (build_string (name), names); } + return names; +#else + return Qnil; +#endif } #ifdef subprocesses commit 18050712a4189dcc467f5345d2efcc77d43d1393 Author: Po Lu Date: Wed Jul 6 13:43:24 2022 +0800 Speed up interning XDS atoms * src/xselect.c (symbol_to_x_atom, x_atom_to_symbol) (syms_of_xselect): Handle new atoms. * src/xterm.c (x_atom_refs): * src/xterm.h (struct x_display_info): New atoms `XdndDirectSave0', `XdndActionDirectSave' and `text/plain'. diff --git a/src/xselect.c b/src/xselect.c index 1fda300c43..d1b6d454ab 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -165,6 +165,12 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) return dpyinfo->Xatom_XmTRANSFER_SUCCESS; if (EQ (sym, QXmTRANSFER_FAILURE)) return dpyinfo->Xatom_XmTRANSFER_FAILURE; + if (EQ (sym, QXdndDirectSave0)) + return dpyinfo->Xatom_XdndDirectSave0; + if (EQ (sym, Qtext_plain)) + return dpyinfo->Xatom_text_plain; + if (EQ (sym, QXdndActionDirectSave)) + return dpyinfo->Xatom_XdndActionDirectSave; if (!SYMBOLP (sym)) emacs_abort (); @@ -233,6 +239,12 @@ x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) return QXmTRANSFER_SUCCESS; if (atom == dpyinfo->Xatom_XmTRANSFER_FAILURE) return QXmTRANSFER_FAILURE; + if (atom == dpyinfo->Xatom_XdndDirectSave0) + return QXdndDirectSave0; + if (atom == dpyinfo->Xatom_text_plain) + return Qtext_plain; + if (atom == dpyinfo->Xatom_XdndActionDirectSave) + return QXdndActionDirectSave; x_catch_errors (dpyinfo->display); str = x_get_atom_name (dpyinfo, atom, NULL); @@ -2998,6 +3010,9 @@ Note that this does not affect setting or owning selections. */); DEFSYM (QCLIPBOARD_MANAGER, "CLIPBOARD_MANAGER"); DEFSYM (QSAVE_TARGETS, "SAVE_TARGETS"); DEFSYM (QNULL, "NULL"); + DEFSYM (QXdndDirectSave0, "XdndDirectSave0"); + DEFSYM (QXdndActionDirectSave, "XdndActionDirectSave"); + DEFSYM (Qtext_plain, "text/plain"); DEFSYM (Qforeign_selection, "foreign-selection"); DEFSYM (Qx_lost_selection_functions, "x-lost-selection-functions"); DEFSYM (Qx_sent_selection_functions, "x-sent-selection-functions"); diff --git a/src/xterm.c b/src/xterm.c index 996a441fda..0180ea3c78 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1022,6 +1022,10 @@ static const struct x_atom_ref x_atom_refs[] = ATOM_REFS_INIT ("XdndLeave", Xatom_XdndLeave) ATOM_REFS_INIT ("XdndDrop", Xatom_XdndDrop) ATOM_REFS_INIT ("XdndFinished", Xatom_XdndFinished) + /* XDS source and target. */ + ATOM_REFS_INIT ("XdndDirectSave0", Xatom_XdndDirectSave0) + ATOM_REFS_INIT ("XdndActionDirectSave", Xatom_XdndActionDirectSave) + ATOM_REFS_INIT ("text/plain", Xatom_text_plain) /* Motif drop protocol support. */ ATOM_REFS_INIT ("_MOTIF_DRAG_WINDOW", Xatom_MOTIF_DRAG_WINDOW) ATOM_REFS_INIT ("_MOTIF_DRAG_TARGETS", Xatom_MOTIF_DRAG_TARGETS) diff --git a/src/xterm.h b/src/xterm.h index b0f9200eea..6684d7839f 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -638,6 +638,9 @@ struct x_display_info Xatom_XdndPosition, Xatom_XdndStatus, Xatom_XdndLeave, Xatom_XdndDrop, Xatom_XdndFinished; + /* XDS source and target. */ + Atom Xatom_XdndDirectSave0, Xatom_XdndActionDirectSave, Xatom_text_plain; + #ifdef HAVE_XKB /* Virtual modifiers */ Atom Xatom_Meta, Xatom_Super, Xatom_Hyper, Xatom_ShiftLock, Xatom_Alt; commit 27436451ecbf250db4d1704c586763cb40e6dfeb Author: Paul Eggert Date: Tue Jul 5 23:57:32 2022 -0500 Update from Gnulib by running admin/merge-gnulib * admin/merge-gnulib (AVOIDED_MODULES): Add chmod. diff --git a/admin/merge-gnulib b/admin/merge-gnulib index ea3d23686f..4dd6a4d222 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -51,7 +51,7 @@ GNULIB_MODULES=' ' AVOIDED_MODULES=' - btowc close crypto/af_alg dup fchdir fstat langinfo lock + btowc chmod close crypto/af_alg dup fchdir fstat langinfo lock mbrtowc mbsinit memchr mkdir msvc-inval msvc-nothrow nl_langinfo openat-die opendir pthread-h raise save-cwd select setenv sigprocmask stat stdarg stdbool diff --git a/build-aux/config.guess b/build-aux/config.guess index 160ecf0951..1817bdce90 100755 --- a/build-aux/config.guess +++ b/build-aux/config.guess @@ -4,7 +4,7 @@ # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2022-05-08' +timestamp='2022-05-25' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -1378,8 +1378,11 @@ EOF BePC:Haiku:*:*) # Haiku running on Intel PC compatible. GUESS=i586-pc-haiku ;; - x86_64:Haiku:*:*) - GUESS=x86_64-unknown-haiku + ppc:Haiku:*:*) # Haiku running on Apple PowerPC + GUESS=powerpc-apple-haiku + ;; + *:Haiku:*:*) # Haiku modern gcc (not bound by BeOS compat) + GUESS=$UNAME_MACHINE-unknown-haiku ;; SX-4:SUPER-UX:*:*) GUESS=sx4-nec-superux$UNAME_RELEASE diff --git a/build-aux/config.sub b/build-aux/config.sub index 9b62e37c43..dba16e84c7 100755 --- a/build-aux/config.sub +++ b/build-aux/config.sub @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2021 Free Software Foundation, Inc. +# Copyright 1992-2022 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2021-12-25' +timestamp='2022-01-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -76,7 +76,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright 1992-2021 Free Software Foundation, Inc. +Copyright 1992-2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index aa16f51aa4..8872e5e055 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -7651,7 +7651,7 @@ % If SUBTOPIC is present, precede it with a space, and call \doind. % (At some time during the 20th century, this made a two-level entry in an % index such as the operation index. Nobody seemed to notice the change in -% behavior though.) +% behaviour though.) \def\dosubind#1#2#3{% \def\thirdarg{#3}% \ifx\thirdarg\empty diff --git a/lib/fchmodat.c b/lib/fchmodat.c index dc53583366..164e2c4a95 100644 --- a/lib/fchmodat.c +++ b/lib/fchmodat.c @@ -83,9 +83,10 @@ fchmodat (int dir, char const *file, mode_t mode, int flags) # if NEED_FCHMODAT_NONSYMLINK_FIX if (flags == AT_SYMLINK_NOFOLLOW) { - struct stat st; +# if HAVE_READLINKAT + char readlink_buf[1]; -# if defined O_PATH && defined AT_EMPTY_PATH +# ifdef O_PATH /* Open a file descriptor with O_NOFOLLOW, to make sure we don't follow symbolic links, if /proc is mounted. O_PATH is used to avoid a failure if the file is not readable. @@ -94,49 +95,29 @@ fchmodat (int dir, char const *file, mode_t mode, int flags) if (fd < 0) return fd; - /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the - chmod call below will change the permissions of the symbolic link - - which is undesired - and on many file systems (ext4, btrfs, jfs, - xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is - misleading. Therefore test for a symbolic link explicitly. - Use fstatat because fstat does not work on O_PATH descriptors - before Linux 3.6. */ - if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0) + int err; + if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) + err = EOPNOTSUPP; + else if (errno == EINVAL) { - int stat_errno = errno; - close (fd); - errno = stat_errno; - return -1; - } - if (S_ISLNK (st.st_mode)) - { - close (fd); - errno = EOPNOTSUPP; - return -1; + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; } + else + err = errno == ENOENT ? -1 : errno; -# if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__ - static char const fmt[] = "/proc/self/fd/%d"; - char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; - sprintf (buf, fmt, fd); - int chmod_result = chmod (buf, mode); - int chmod_errno = errno; close (fd); - if (chmod_result == 0) - return chmod_result; - if (chmod_errno != ENOENT) - { - errno = chmod_errno; - return chmod_result; - } + + errno = err; + if (0 <= err) + return err == 0 ? 0 : -1; # endif - /* /proc is not mounted or would not work as in GNU/Linux. */ -# else - int fstatat_result = fstatat (dir, file, &st, AT_SYMLINK_NOFOLLOW); - if (fstatat_result != 0) - return fstatat_result; - if (S_ISLNK (st.st_mode)) + /* O_PATH + /proc is not supported. */ + + if (0 <= readlinkat (dir, file, readlink_buf, sizeof readlink_buf)) { errno = EOPNOTSUPP; return -1; diff --git a/lib/filevercmp.c b/lib/filevercmp.c index d546e79054..7e54793e61 100644 --- a/lib/filevercmp.c +++ b/lib/filevercmp.c @@ -29,6 +29,8 @@ /* Return the length of a prefix of S that corresponds to the suffix defined by this extended regular expression in the C locale: (\.[A-Za-z~][A-Za-z0-9~]*)*$ + Use the longest suffix matching this regular expression, + except do not use all of S as a suffix if S is nonempty. If *LEN is -1, S is a string; set *LEN to S's length. Otherwise, *LEN should be nonnegative, S is a char array, and *LEN does not change. */ @@ -36,20 +38,22 @@ static idx_t file_prefixlen (char const *s, ptrdiff_t *len) { size_t n = *len; /* SIZE_MAX if N == -1. */ + idx_t prefixlen = 0; - for (idx_t i = 0; ; i++) + for (idx_t i = 0; ; ) { - idx_t prefixlen = i; - while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1]) - || s[i + 1] == '~')) - for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++) - continue; - if (*len < 0 ? !s[i] : i == n) { *len = i; return prefixlen; } + + i++; + prefixlen = i; + while (i + 1 < n && s[i] == '.' && (c_isalpha (s[i + 1]) + || s[i + 1] == '~')) + for (i += 2; i < n && (c_isalnum (s[i]) || s[i] == '~'); i++) + continue; } } diff --git a/lib/filevercmp.h b/lib/filevercmp.h index 5a33677671..57949760b2 100644 --- a/lib/filevercmp.h +++ b/lib/filevercmp.h @@ -61,7 +61,9 @@ without them, using version sort without special priority; if they do not compare equal, this comparison result is used and the suffixes are effectively ignored. Otherwise, the entire - strings are compared using version sort. + strings are compared using version sort. When removing a suffix + from a nonempty string, remove the maximal-length suffix such that + the remaining string is nonempty. This function is intended to be a replacement for strverscmp. */ int filevercmp (char const *a, char const *b) _GL_ATTRIBUTE_PURE; diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index bf0df878a5..2ffe89d423 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -35,6 +35,7 @@ # --macro-prefix=gl \ # --no-vc-files \ # --avoid=btowc \ +# --avoid=chmod \ # --avoid=close \ # --avoid=crypto/af_alg \ # --avoid=dup \ @@ -327,6 +328,7 @@ GL_GNULIB_CALLOC_GNU = @GL_GNULIB_CALLOC_GNU@ GL_GNULIB_CALLOC_POSIX = @GL_GNULIB_CALLOC_POSIX@ GL_GNULIB_CANONICALIZE_FILE_NAME = @GL_GNULIB_CANONICALIZE_FILE_NAME@ GL_GNULIB_CHDIR = @GL_GNULIB_CHDIR@ +GL_GNULIB_CHMOD = @GL_GNULIB_CHMOD@ GL_GNULIB_CHOWN = @GL_GNULIB_CHOWN@ GL_GNULIB_CLOSE = @GL_GNULIB_CLOSE@ GL_GNULIB_CLOSEDIR = @GL_GNULIB_CLOSEDIR@ @@ -1029,6 +1031,7 @@ REPLACE_ALIGNED_ALLOC = @REPLACE_ALIGNED_ALLOC@ REPLACE_CALLOC_FOR_CALLOC_GNU = @REPLACE_CALLOC_FOR_CALLOC_GNU@ REPLACE_CALLOC_FOR_CALLOC_POSIX = @REPLACE_CALLOC_FOR_CALLOC_POSIX@ REPLACE_CANONICALIZE_FILE_NAME = @REPLACE_CANONICALIZE_FILE_NAME@ +REPLACE_CHMOD = @REPLACE_CHMOD@ REPLACE_CHOWN = @REPLACE_CHOWN@ REPLACE_CLOSE = @REPLACE_CLOSE@ REPLACE_CLOSEDIR = @REPLACE_CLOSEDIR@ @@ -1196,6 +1199,7 @@ SETTINGS_LIBS = @SETTINGS_LIBS@ SHELL = @SHELL@ SIG_ATOMIC_T_SUFFIX = @SIG_ATOMIC_T_SUFFIX@ SIZE_T_SUFFIX = @SIZE_T_SUFFIX@ +SMALL_JA_DIC = @SMALL_JA_DIC@ SQLITE3_LIBS = @SQLITE3_LIBS@ STDALIGN_H = @STDALIGN_H@ STDDEF_H = @STDDEF_H@ @@ -3497,6 +3501,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's|@''NEXT_SYS_STAT_H''@|$(NEXT_SYS_STAT_H)|g' \ -e 's|@''WINDOWS_64_BIT_ST_SIZE''@|$(WINDOWS_64_BIT_ST_SIZE)|g' \ -e 's|@''WINDOWS_STAT_TIMESPEC''@|$(WINDOWS_STAT_TIMESPEC)|g' \ + -e 's/@''GNULIB_CHMOD''@/$(GL_GNULIB_CHMOD)/g' \ -e 's/@''GNULIB_FCHMODAT''@/$(GL_GNULIB_FCHMODAT)/g' \ -e 's/@''GNULIB_FSTAT''@/$(GL_GNULIB_FSTAT)/g' \ -e 's/@''GNULIB_FSTATAT''@/$(GL_GNULIB_FSTATAT)/g' \ @@ -3528,6 +3533,7 @@ sys/stat.h: sys_stat.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNU -e 's|@''HAVE_MKNOD''@|$(HAVE_MKNOD)|g' \ -e 's|@''HAVE_MKNODAT''@|$(HAVE_MKNODAT)|g' \ -e 's|@''HAVE_UTIMENSAT''@|$(HAVE_UTIMENSAT)|g' \ + -e 's|@''REPLACE_CHMOD''@|$(REPLACE_CHMOD)|g' \ -e 's|@''REPLACE_FCHMODAT''@|$(REPLACE_FCHMODAT)|g' \ -e 's|@''REPLACE_FSTAT''@|$(REPLACE_FSTAT)|g' \ -e 's|@''REPLACE_FSTATAT''@|$(REPLACE_FSTATAT)|g' \ diff --git a/lib/lchmod.c b/lib/lchmod.c index 706dddff7b..8410a2d835 100644 --- a/lib/lchmod.c +++ b/lib/lchmod.c @@ -25,17 +25,9 @@ #include #include #include +#include #include -#ifdef __osf__ -/* Write "sys/stat.h" here, not , otherwise OSF/1 5.1 DTK cc - eliminates this include because of the preliminary #include - above. */ -# include "sys/stat.h" -#else -# include -#endif - #include /* Work like chmod, except when FILE is a symbolic link. @@ -45,7 +37,9 @@ int lchmod (char const *file, mode_t mode) { -#if defined O_PATH && defined AT_EMPTY_PATH + char readlink_buf[1]; + +#ifdef O_PATH /* Open a file descriptor with O_NOFOLLOW, to make sure we don't follow symbolic links, if /proc is mounted. O_PATH is used to avoid a failure if the file is not readable. @@ -54,56 +48,46 @@ lchmod (char const *file, mode_t mode) if (fd < 0) return fd; - /* Up to Linux 5.3 at least, when FILE refers to a symbolic link, the - chmod call below will change the permissions of the symbolic link - - which is undesired - and on many file systems (ext4, btrfs, jfs, - xfs, ..., but not reiserfs) fail with error EOPNOTSUPP - which is - misleading. Therefore test for a symbolic link explicitly. - Use fstatat because fstat does not work on O_PATH descriptors - before Linux 3.6. */ - struct stat st; - if (fstatat (fd, "", &st, AT_EMPTY_PATH) != 0) + int err; + if (0 <= readlinkat (fd, "", readlink_buf, sizeof readlink_buf)) + err = EOPNOTSUPP; + else if (errno == EINVAL) { - int stat_errno = errno; - close (fd); - errno = stat_errno; - return -1; - } - if (S_ISLNK (st.st_mode)) - { - close (fd); - errno = EOPNOTSUPP; - return -1; + static char const fmt[] = "/proc/self/fd/%d"; + char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; + sprintf (buf, fmt, fd); + err = chmod (buf, mode) == 0 ? 0 : errno == ENOENT ? -1 : errno; } + else + err = errno == ENOENT ? -1 : errno; -# if defined __linux__ || defined __ANDROID__ || defined __CYGWIN__ - static char const fmt[] = "/proc/self/fd/%d"; - char buf[sizeof fmt - sizeof "%d" + INT_BUFSIZE_BOUND (int)]; - sprintf (buf, fmt, fd); - int chmod_result = chmod (buf, mode); - int chmod_errno = errno; close (fd); - if (chmod_result == 0) - return chmod_result; - if (chmod_errno != ENOENT) + + errno = err; + if (0 <= err) + return err == 0 ? 0 : -1; +#endif + + size_t len = strlen (file); + if (len && file[len - 1] == '/') { - errno = chmod_errno; - return chmod_result; + struct stat st; + if (lstat (file, &st) < 0) + return -1; + if (!S_ISDIR (st.st_mode)) + { + errno = ENOTDIR; + return -1; + } } -# endif - /* /proc is not mounted or would not work as in GNU/Linux. */ - -#elif HAVE_LSTAT - struct stat st; - int lstat_result = lstat (file, &st); - if (lstat_result != 0) - return lstat_result; - if (S_ISLNK (st.st_mode)) + + /* O_PATH + /proc is not supported. */ + + if (0 <= readlink (file, readlink_buf, sizeof readlink_buf)) { errno = EOPNOTSUPP; return -1; } -#endif /* Fall back on chmod, despite a possible race. */ return chmod (file, mode); diff --git a/lib/mini-gmp.h b/lib/mini-gmp.h index 508712d235..59c24cf511 100644 --- a/lib/mini-gmp.h +++ b/lib/mini-gmp.h @@ -8,7 +8,7 @@ The GNU MP Library is free software; you can redistribute it and/or modify it under the terms of either: * the GNU Lesser General Public License as published by the Free - Software Foundation, either version 3 of the License, or (at your + Software Foundation; either version 3 of the License, or (at your option) any later version. or diff --git a/lib/str-two-way.h b/lib/str-two-way.h index 7ee344aea1..b00017c0b4 100644 --- a/lib/str-two-way.h +++ b/lib/str-two-way.h @@ -231,7 +231,7 @@ critical_factorization (const unsigned char *needle, size_t needle_len, most 2 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching. */ -static RETURN_TYPE +static RETURN_TYPE _GL_ATTRIBUTE_PURE two_way_short_needle (const unsigned char *haystack, size_t haystack_len, const unsigned char *needle, size_t needle_len) { @@ -325,7 +325,7 @@ two_way_short_needle (const unsigned char *haystack, size_t haystack_len, If AVAILABLE modifies HAYSTACK_LEN (as in strstr), then at most 3 * HAYSTACK_LEN - NEEDLE_LEN comparisons occur in searching, and sublinear performance is not possible. */ -static RETURN_TYPE +static RETURN_TYPE _GL_ATTRIBUTE_PURE two_way_long_needle (const unsigned char *haystack, size_t haystack_len, const unsigned char *needle, size_t needle_len) { diff --git a/lib/string.in.h b/lib/string.in.h index 33160b2525..3996da9fcb 100644 --- a/lib/string.in.h +++ b/lib/string.in.h @@ -122,8 +122,12 @@ _GL_EXTERN_C void rpl_free (void *); # undef _GL_ATTRIBUTE_DEALLOC_FREE # define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (rpl_free, 1) # else -# if defined _MSC_VER -_GL_EXTERN_C void __cdecl free (void *); +# if defined _MSC_VER && !defined free +_GL_EXTERN_C +# if defined _DLL + __declspec (dllimport) +# endif + void __cdecl free (void *); # else # if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) _GL_EXTERN_C void free (void *) throw (); @@ -133,8 +137,12 @@ _GL_EXTERN_C void free (void *); # endif # endif #else -# if defined _MSC_VER -_GL_EXTERN_C void __cdecl free (void *); +# if defined _MSC_VER && !defined free +_GL_EXTERN_C +# if defined _DLL + __declspec (dllimport) +# endif + void __cdecl free (void *); # else # if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2) _GL_EXTERN_C void free (void *) throw (); diff --git a/lib/sys_stat.in.h b/lib/sys_stat.in.h index 28ddd42f81..714c3cb189 100644 --- a/lib/sys_stat.in.h +++ b/lib/sys_stat.in.h @@ -391,7 +391,33 @@ struct stat #endif -#if @GNULIB_MDA_CHMOD@ +#if @GNULIB_CHMOD@ +# if @REPLACE_CHMOD@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chmod +# define chmod rpl_chmod +# endif +_GL_FUNCDECL_RPL (chmod, int, (const char *filename, mode_t mode) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (chmod, int, (const char *filename, mode_t mode)); +# elif defined _WIN32 && !defined __CYGWIN__ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef chmod +# define chmod _chmod +# endif +/* Need to cast, because in mingw the last argument is 'int mode'. */ +_GL_CXXALIAS_MDA_CAST (chmod, int, (const char *filename, mode_t mode)); +# else +_GL_CXXALIAS_SYS (chmod, int, (const char *filename, mode_t mode)); +# endif +_GL_CXXALIASWARN (chmod); +#elif defined GNULIB_POSIXCHECK +# undef chmod +# if HAVE_RAW_DECL_CHMOD +_GL_WARN_ON_USE (chmod, "chmod has portability problems - " + "use gnulib module chmod for portability"); +# endif +#elif @GNULIB_MDA_CHMOD@ /* On native Windows, map 'chmod' to '_chmod', so that -loldnames is not required. In C++ with GNULIB_NAMESPACE, avoid differences between platforms by defining GNULIB_NAMESPACE::chmod always. */ diff --git a/m4/fchmodat.m4 b/m4/fchmodat.m4 index a5cf95a88b..f743ce1b02 100644 --- a/m4/fchmodat.m4 +++ b/m4/fchmodat.m4 @@ -1,4 +1,4 @@ -# fchmodat.m4 serial 6 +# fchmodat.m4 serial 7 dnl Copyright (C) 2004-2022 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -97,6 +97,6 @@ AC_DEFUN([gl_FUNC_FCHMODAT], # Prerequisites of lib/fchmodat.c. AC_DEFUN([gl_PREREQ_FCHMODAT], [ - AC_CHECK_FUNCS_ONCE([lchmod]) + AC_CHECK_FUNCS_ONCE([readlinkat]) : ]) diff --git a/m4/lchmod.m4 b/m4/lchmod.m4 index 5baee738ef..cd43beed85 100644 --- a/m4/lchmod.m4 +++ b/m4/lchmod.m4 @@ -1,4 +1,4 @@ -#serial 8 +#serial 10 dnl Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation @@ -15,9 +15,7 @@ AC_DEFUN([gl_FUNC_LCHMOD], dnl Persuade glibc to declare lchmod(). AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS]) - AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles - - AC_CHECK_FUNCS_ONCE([lchmod lstat]) + AC_CHECK_FUNCS_ONCE([lchmod]) if test "$ac_cv_func_lchmod" = no; then HAVE_LCHMOD=0 fi diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4 index b5a9789b81..2adbfdeef4 100644 --- a/m4/sys_stat_h.m4 +++ b/m4/sys_stat_h.m4 @@ -1,4 +1,4 @@ -# sys_stat_h.m4 serial 41 -*- Autoconf -*- +# sys_stat_h.m4 serial 42 -*- Autoconf -*- dnl Copyright (C) 2006-2022 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -46,7 +46,7 @@ AC_DEFUN_ONCE([gl_SYS_STAT_H], dnl Check for declarations of anything we want to poison if the dnl corresponding gnulib module is not in use. gl_WARN_ON_USE_PREPARE([[#include - ]], [fchmodat fstat fstatat futimens getumask lchmod lstat + ]], [chmod fchmodat fstat fstatat futimens getumask lchmod lstat mkdirat mkfifo mkfifoat mknod mknodat stat utimensat]) AC_REQUIRE([AC_C_RESTRICT]) @@ -72,6 +72,7 @@ AC_DEFUN([gl_SYS_STAT_H_REQUIRE_DEFAULTS], [ m4_defun(GL_MODULE_INDICATOR_PREFIX[_SYS_STAT_H_MODULE_INDICATOR_DEFAULTS], [ gl_UNISTD_H_REQUIRE_DEFAULTS dnl for REPLACE_FCHDIR + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CHMOD]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FCHMODAT]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FSTAT]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_FSTATAT]) @@ -112,6 +113,7 @@ AC_DEFUN([gl_SYS_STAT_H_DEFAULTS], HAVE_MKNOD=1; AC_SUBST([HAVE_MKNOD]) HAVE_MKNODAT=1; AC_SUBST([HAVE_MKNODAT]) HAVE_UTIMENSAT=1; AC_SUBST([HAVE_UTIMENSAT]) + REPLACE_CHMOD=0; AC_SUBST([REPLACE_CHMOD]) REPLACE_FCHMODAT=0; AC_SUBST([REPLACE_FCHMODAT]) REPLACE_FSTAT=0; AC_SUBST([REPLACE_FSTAT]) REPLACE_FSTATAT=0; AC_SUBST([REPLACE_FSTATAT]) commit 2be06b13dd9582d7216c479e9874f0df6d32746b Merge: 54e0b14a69 6b5d829d9d Author: Stefan Kangas Date: Wed Jul 6 06:30:39 2022 +0200 Merge from origin/emacs-28 6b5d829d9d Add index entry for "ignore case" 29e1459965 ; * lisp/files.el (remote-file-name-inhibit-cache): Minor ... commit 54e0b14a6981a317210493f0fead1e2c5b6508ea Author: Paul Eggert Date: Tue Jul 5 23:25:44 2022 -0500 Adjust better to Autoconf quoting style change * admin/gitmerge.el (gitmerge-emacs-version): * admin/nt/dist-build/build-zips.sh (ACTUAL_VERSION): * admin/quick-install-emacs (VERSION): * lisp/cedet/ede/emacs.el (ede-emacs-version): Adjust to change in configure.ac’s Autoconf quoting style. * etc/srecode/ede-autoconf.srt: * test/lisp/progmodes/autoconf-tests.el: (autoconf-tests-current-defun-function-define) (autoconf-tests-current-defun-function-subst): Use better Autoconf quoting. * make-dist (version): Simplify. diff --git a/admin/gitmerge.el b/admin/gitmerge.el index 5da70a4028..a214dcbcb7 100644 --- a/admin/gitmerge.el +++ b/admin/gitmerge.el @@ -124,7 +124,7 @@ If nil, the function `gitmerge-default-branch' guesses.") (let ((coding-system-for-read vc-git-log-output-coding-system)) (call-process "git" nil t nil "show" (format "%s:configure.ac" branch))) (goto-char (point-min))) - (re-search-forward "^AC_INIT([^,]+, \\([0-9]+\\)\\.") + (re-search-forward "^AC_INIT([^,]+, \\[?\\([0-9]+\\)\\.") (string-to-number (match-string 1)))) (defun gitmerge-default-branch () diff --git a/admin/nt/dist-build/build-zips.sh b/admin/nt/dist-build/build-zips.sh index 77d20a5a7b..39ac1fde60 100755 --- a/admin/nt/dist-build/build-zips.sh +++ b/admin/nt/dist-build/build-zips.sh @@ -148,7 +148,7 @@ done if [ -z $ACTUAL_VERSION ]; then ACTUAL_VERSION=` - sed -n 's/^AC_INIT(GNU Emacs,[ ]*\([^ ,)]*\).*/\1/p' < ../../../configure.ac + sed -n 's/^AC_INIT(\[*GNU Emacs]*,[ ]*\[*\([^] ,)]*\).*/\1/p' < ../../../configure.ac ` fi diff --git a/admin/quick-install-emacs b/admin/quick-install-emacs index 9a73cf5a40..b0a1d34251 100755 --- a/admin/quick-install-emacs +++ b/admin/quick-install-emacs @@ -172,10 +172,10 @@ test x"$prefix" = x && { prefix="`get_config_var prefix`" || exit 4 ; } test x"$ARCH" = x && { ARCH="`get_config_var host`" || exit 4 ; } VERSION=` - sed -n 's/^AC_INIT([ ]*emacs[ ]*,[ ]*\([^ ),]*\).*/\1/p' <$SRC/configure.ac + sed -n 's/^AC_INIT([ ]*\[*emacs]*[ ]*,[ ]*\[*\([^] ),]*\).*/\1/p' <$SRC/configure.ac ` || exit 4 test -n "$VERSION" || VERSION=` - sed -n 's/^AC_INIT([ ]*GNU Emacs[ ]*,[ ]*\([^ ),]*\).*/\1/p' <$SRC/configure.ac + sed -n 's/^AC_INIT([ ]*\[*GNU Emacs]*[ ]*,[ ]*\[*\([^] ),]*\).*/\1/p' <$SRC/configure.ac ` || exit 4 test -n "$VERSION" || { printf '%s\n' >&2 "$me: no version in configure.ac"; exit 4; } diff --git a/etc/srecode/ede-autoconf.srt b/etc/srecode/ede-autoconf.srt index 19dc14202d..ecca7afd00 100644 --- a/etc/srecode/ede-autoconf.srt +++ b/etc/srecode/ede-autoconf.srt @@ -44,10 +44,10 @@ template ede-empty :project AC_INIT({{PROJECT_NAME}}, {{PROJECT_VERSION}}) AM_INIT_AUTOMAKE([{{PROGRAM}}], 0) -AM_CONFIG_HEADER(config.h) +AM_CONFIG_HEADER([config.h]) {{comment_prefix}} End the configure script. -AC_OUTPUT(Makefile, [date > stamp-h] ) +AC_OUTPUT([Makefile], [date > stamp-h] ) ---- diff --git a/lisp/cedet/ede/emacs.el b/lisp/cedet/ede/emacs.el index 5a23f504f7..cbe766cedb 100644 --- a/lisp/cedet/ede/emacs.el +++ b/lisp/cedet/ede/emacs.el @@ -59,7 +59,7 @@ Return a tuple of ( EMACSNAME . VERSION )." (file-exists-p (setq configure_ac "configure.in"))) (insert-file-contents configure_ac) (goto-char (point-min)) - (re-search-forward "AC_INIT(\\(?:GNU \\)?[eE]macs,\\s-*\\([0-9.]+\\)\\s-*[,)]") + (re-search-forward "AC_INIT(\\[?\\(?:GNU \\)?[eE]macs]?,\\s-*\\[?\\([0-9.]+\\)]?\\s-*[,)]") (setq ver (match-string 1)) ) ) diff --git a/make-dist b/make-dist index c1e7942d60..4646a2809b 100755 --- a/make-dist +++ b/make-dist @@ -174,7 +174,7 @@ fi ### Find out which version of Emacs this is. version=` - sed -n 's/^AC_INIT(\[GNU Emacs],[ ]*\[\([^ ,)]*\)].*/\1/p' . */ EMACS_CHECK_MODULES([XFIXES], [$XFIXES_MODULES]) if test $HAVE_XFIXES = no; then # Test old way in case pkg-config doesn't have it (older machines). - AC_CHECK_HEADER(X11/extensions/Xfixes.h, - [AC_CHECK_LIB(Xfixes, XFixesHideCursor, HAVE_XFIXES=yes)]) + AC_CHECK_HEADER([X11/extensions/Xfixes.h], + [AC_CHECK_LIB([Xfixes], [XFixesHideCursor], [HAVE_XFIXES=yes])]) if test $HAVE_XFIXES = yes; then XFIXES_LIBS=-lXfixes fi fi if test $HAVE_XFIXES = yes; then - AC_DEFINE(HAVE_XFIXES, 1, [Define to 1 if you have the Xfixes extension.]) + AC_DEFINE([HAVE_XFIXES], [1], + [Define to 1 if you have the Xfixes extension.]) fi fi - AC_SUBST(XFIXES_CFLAGS) - AC_SUBST(XFIXES_LIBS) + AC_SUBST([XFIXES_CFLAGS]) + AC_SUBST([XFIXES_LIBS]) Then, make sure to adjust CFLAGS and LIBES in src/Makefile.in and add the new XFIXES_CFLAGS and XFIXES_LIBS variables to diff --git a/test/lisp/progmodes/autoconf-tests.el b/test/lisp/progmodes/autoconf-tests.el index e383b4bb6c..7c609f3c2a 100644 --- a/test/lisp/progmodes/autoconf-tests.el +++ b/test/lisp/progmodes/autoconf-tests.el @@ -31,18 +31,18 @@ (ert-deftest autoconf-tests-current-defun-function-define () (with-temp-buffer - (insert "AC_DEFINE(HAVE_RSVG, 1, [Define to 1 if using librsvg.])") + (insert "AC_DEFINE([HAVE_RSVG], [1], [Define to 1 if using librsvg.])") (goto-char (point-min)) (should-not (autoconf-current-defun-function)) - (forward-char 10) + (forward-char 11) (should (equal (autoconf-current-defun-function) "HAVE_RSVG")))) (ert-deftest autoconf-tests-current-defun-function-subst () (with-temp-buffer - (insert "AC_SUBST(srcdir)") + (insert "AC_SUBST([srcdir])") (goto-char (point-min)) (should-not (autoconf-current-defun-function)) - (forward-char 9) + (forward-char 10) (should (equal (autoconf-current-defun-function) "srcdir")))) (ert-deftest autoconf-tests-autoconf-mode-comment-syntax () commit e482379a65e99cb61aba86876587b499eeeef007 Author: Po Lu Date: Wed Jul 6 10:42:12 2022 +0800 Reduce duplicate code cleaning up DND processes * src/xterm.c (x_restore_events_after_dnd): New function. (x_dnd_cleanup_drag_and_drop, x_dnd_begin_drag_and_drop): Use that instead of manually cleaning up properties and events. diff --git a/src/xterm.c b/src/xterm.c index 2643d1120f..45aef51ecb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4597,6 +4597,34 @@ x_free_dnd_toplevels (void) x_dnd_free_toplevels (true); } +/* Restore event masks and window properties changed during a + drag-and-drop operation, after it finishes. */ +static void +x_restore_events_after_dnd (struct frame *f, XWindowAttributes *wa) +{ + struct x_display_info *dpyinfo; + + dpyinfo = FRAME_DISPLAY_INFO (f); + + /* Restore the old event mask. */ + XSelectInput (dpyinfo->display, dpyinfo->root_window, + wa->your_event_mask); +#ifdef HAVE_XKB + if (dpyinfo->supports_xkb) + XkbSelectEvents (dpyinfo->display, XkbUseCoreKbd, + XkbStateNotifyMask, 0); +#endif + /* Delete the Motif drag initiator info if it was set up. */ + if (x_dnd_motif_setup_p) + XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f), + x_dnd_motif_atom); + + /* Remove any type list set as well. */ + if (x_dnd_init_type_lists && x_dnd_n_targets > 3) + XDeleteProperty (dpyinfo->display, FRAME_X_WINDOW (f), + dpyinfo->Xatom_XdndTypeList); +} + static void x_dnd_cleanup_drag_and_drop (void *frame) { @@ -4656,32 +4684,9 @@ x_dnd_cleanup_drag_and_drop (void *frame) #endif x_dnd_return_frame_object = NULL; x_dnd_movement_frame = NULL; - - block_input (); - /* Restore the old event mask. */ - XSelectInput (FRAME_X_DISPLAY (f), - FRAME_DISPLAY_INFO (f)->root_window, - x_dnd_old_window_attrs.your_event_mask); - -#ifdef HAVE_XKB - if (FRAME_DISPLAY_INFO (f)->supports_xkb) - XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd, - XkbStateNotifyMask, 0); -#endif - - /* Delete the Motif drag initiator info if it was set up. */ - if (x_dnd_motif_setup_p) - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); - - /* Remove any type list set as well. */ - if (x_dnd_init_type_lists && x_dnd_n_targets > 3) - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); - - unblock_input (); - x_dnd_frame = NULL; + + x_restore_events_after_dnd (f, &x_dnd_old_window_attrs); } static void @@ -11779,24 +11784,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, current_hold_quit = NULL; #endif /* Restore the old event mask. */ - XSelectInput (FRAME_X_DISPLAY (f), - FRAME_DISPLAY_INFO (f)->root_window, - root_window_attrs.your_event_mask); -#ifdef HAVE_XKB - if (FRAME_DISPLAY_INFO (f)->supports_xkb) - XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd, - XkbStateNotifyMask, 0); -#endif - /* Delete the Motif drag initiator info if it was set up. */ - if (x_dnd_motif_setup_p) - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - x_dnd_motif_atom); - - - /* Remove any type list set as well. */ - if (x_dnd_init_type_lists && x_dnd_n_targets > 3) - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); + x_restore_events_after_dnd (f, &root_window_attrs); /* Call kbd_buffer_store event, which calls handle_interrupt and sets `last-event-frame' along @@ -11913,27 +11901,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, FRAME_DISPLAY_INFO (f)->grabbed = 0; current_hold_quit = NULL; - block_input (); /* Restore the old event mask. */ - XSelectInput (FRAME_X_DISPLAY (f), - FRAME_DISPLAY_INFO (f)->root_window, - root_window_attrs.your_event_mask); -#ifdef HAVE_XKB - if (FRAME_DISPLAY_INFO (f)->supports_xkb) - XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd, - XkbStateNotifyMask, 0); -#endif - /* Delete the Motif drag initiator info if it was set up. */ - if (x_dnd_motif_setup_p) - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - x_dnd_motif_atom); - - - /* Remove any type list set as well. */ - if (x_dnd_init_type_lists && x_dnd_n_targets > 3) - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); - unblock_input (); + x_restore_events_after_dnd (f, &root_window_attrs); quit (); } @@ -11956,27 +11925,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, current_hold_quit = NULL; #endif x_dnd_movement_frame = NULL; - - block_input (); - /* Restore the old event mask. */ - XSelectInput (FRAME_X_DISPLAY (f), - FRAME_DISPLAY_INFO (f)->root_window, - root_window_attrs.your_event_mask); -#ifdef HAVE_XKB - if (FRAME_DISPLAY_INFO (f)->supports_xkb) - XkbSelectEvents (FRAME_X_DISPLAY (f), XkbUseCoreKbd, - XkbStateNotifyMask, 0); -#endif - /* Delete the Motif drag initiator info if it was set up. */ - if (x_dnd_motif_setup_p) - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - x_dnd_motif_atom); - - /* Remove any type list set as well. */ - if (x_dnd_init_type_lists && x_dnd_n_targets > 3) - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); - unblock_input (); + x_restore_events_after_dnd (f, &root_window_attrs); if (x_dnd_return_frame == 3 && FRAME_LIVE_P (x_dnd_return_frame_object)) commit cd18cee96ee17562a276ea84bc9313e5bcbccb55 Author: Po Lu Date: Wed Jul 6 09:01:02 2022 +0800 Don't select for unnecessary properties during DND * src/xterm.c (x_dnd_begin_drag_and_drop): Don't select for property changes when not using toplevels. diff --git a/src/xterm.c b/src/xterm.c index 8373222cfc..2643d1120f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11388,6 +11388,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #ifndef USE_GTK struct x_display_info *event_display; #endif + unsigned int additional_mask; base = SPECPDL_INDEX (); @@ -11598,7 +11599,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (EQ (return_frame, Qnow)) x_dnd_return_frame = 2; - /* Now select for SubstructureNotifyMask and PropertyNotifyMask on + /* Now select for SubstructureNotifyMask and PropertyChangeMask on the root window, so we can get notified when window stacking changes, a common operation during drag-and-drop. */ @@ -11606,11 +11607,15 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, FRAME_DISPLAY_INFO (f)->root_window, &root_window_attrs); + additional_mask = SubstructureNotifyMask; + + if (x_dnd_use_toplevels) + additional_mask |= PropertyChangeMask; + XSelectInput (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, root_window_attrs.your_event_mask - | SubstructureNotifyMask - | PropertyChangeMask); + | additional_mask); if (EQ (return_frame, Qnow)) x_dnd_update_state (FRAME_DISPLAY_INFO (f), CurrentTime); commit 6230ed6d63a9867212d0aa20db6cd6c73581d56e Author: Po Lu Date: Tue Jul 5 21:56:50 2022 +0800 Fix announcements of XDND mouse rectangles * lisp/x-dnd.el (x-dnd-handle-xdnd): Use correct meaning of "2", which isn't well documented. * src/xterm.c (handle_one_xevent): Likewise. Also fix unpacking of mouse rects. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 9c1c98a1bf..92899e7a0c 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -695,13 +695,13 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (list-to-send (list (string-to-number (frame-parameter frame 'outer-window-id)) - (+ 2 accept) ;; 1 = accept, 0 = reject. 2 = - ;; "want position updates". - (if dnd-indicate-insertion-point 0 - (x-dnd-get-drop-x-y frame window)) - (if dnd-indicate-insertion-point 0 - (x-dnd-get-drop-width-height - frame window (eq accept 1))) + ;; 1 = accept, 0 = reject. 2 = "want position + ;; updates even for movement inside the given + ;; widget bounds". + (+ (if dnd-indicate-insertion-point 2 0) accept) + (x-dnd-get-drop-x-y frame window) + (x-dnd-get-drop-width-height + frame window (eq accept 1)) ;; The no-toolkit Emacs build can actually ;; receive drops from programs that speak ;; versions of XDND earlier than 3 (such as diff --git a/src/xterm.c b/src/xterm.c index 4a47fdfd45..8373222cfc 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -16468,10 +16468,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (x_dnd_last_protocol_version != -1 && x_dnd_in_progress && target == x_dnd_last_seen_window - && event->xclient.data.l[1] & 2) + /* The XDND documentation is not very clearly worded. + But this should be the correct behavior, since + "kDNDStatusSendHereFlag" in the reference + implementation is 2, and means the mouse rect + should be ignored. */ + && !(event->xclient.data.l[1] & 2)) { r1 = event->xclient.data.l[2]; - r2 = event->xclient.data.l[2]; + r2 = event->xclient.data.l[3]; x_dnd_mouse_rect_target = target; x_dnd_mouse_rect.x = (r1 & 0xffff0000) >> 16; commit 0463368a7b70dfc7914e5c5577c9690f8d0c4f7c Author: Glenn Morris Date: Tue Jul 5 14:50:17 2022 -0700 * make-dist: Fix after recent configure.ac quoting changes. diff --git a/make-dist b/make-dist index 67e49382d0..c1e7942d60 100755 --- a/make-dist +++ b/make-dist @@ -174,7 +174,7 @@ fi ### Find out which version of Emacs this is. version=` - sed -n 's/^AC_INIT(GNU Emacs,[ ]*\([^ ,)]*\).*/\1/p' Date: Tue Jul 5 22:42:25 2022 +0200 Fix custom-initialize-reset bootstrap error * lisp/custom.el (custom-initialize-reset): Fix bootstrap problem by avoiding when-let. diff --git a/lisp/custom.el b/lisp/custom.el index a6e2ab351d..bbbe70c5ea 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -93,13 +93,17 @@ or (last of all) the value of EXP." ;; If this value has been set with `setopt' (for instance in ;; ~/.emacs), we didn't necessarily know the type of the user option ;; then. So check now, and issue a warning if it's wrong. - (when-let ((value (get symbol 'custom-check-value)) - (type (get symbol 'custom-type))) - (when (and (boundp symbol) - (eq (car value) (symbol-value symbol)) - ;; Check that the type is correct. - (not (widget-apply (widget-convert type) :match (car value)))) - (warn "Value `%S' for `%s' does not match type %s" value symbol type))) + (let ((value (get symbol 'custom-check-value))) + (when value + (let ((type (get symbol 'custom-type))) + (when (and type + (boundp symbol) + (eq (car value) (symbol-value symbol)) + ;; Check that the type is correct. + (not (widget-apply (widget-convert type) + :match (car value)))) + (warn "Value `%S' for `%s' does not match type %s" + value symbol type))))) (funcall (or (get symbol 'custom-set) #'set-default-toplevel-value) symbol (condition-case nil commit 7f298bab5234073b1565a7008f63b89979a925d4 Author: Lars Ingebrigtsen Date: Tue Jul 5 21:06:36 2022 +0200 Fix rcirc buffer name collisions * lisp/net/rcirc.el (rcirc-handler-NICK): Avoid naming collisions when renaming buffers (bug#45872). diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index dc0946fb09..775cff9730 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -3302,7 +3302,7 @@ PROCESS is the process object for the current connection." (with-current-buffer chat-buffer (rcirc-print process sender "NICK" old-nick new-nick) (setq rcirc-target new-nick) - (rename-buffer (rcirc-generate-new-buffer-name process new-nick))) + (rename-buffer (rcirc-generate-new-buffer-name process new-nick) t)) (setf rcirc-buffer-alist (cons (cons new-nick chat-buffer) (delq (assoc-string old-nick rcirc-buffer-alist t) commit ad1baff0a12cb22c5c515e0ba3ed29d4b876451b Author: Michael Albinus Date: Tue Jul 5 21:19:51 2022 +0200 Mention remote-file-name-inhibit-auto-save-visited in Tramp manual * doc/misc/tramp.texi (Auto-save File Lock and Backup): Explain remote-file-name-inhibit-auto-save-visited. diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index a8230ac945..76e2ea0f36 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -312,7 +312,7 @@ I hope this has provided you with a basic overview of what happens behind the scenes when you open a file with @value{tramp}. -@c For the end user +@c For the end user. @node Obtaining @value{tramp} @chapter Obtaining @value{tramp} @cindex obtaining @value{tramp} @@ -3124,6 +3124,14 @@ auto-saved files to the same directory as the original file. Alternatively, set the user option @code{tramp-auto-save-directory} to direct all auto saves to that location. +@c Since Emacs 29. +@vindex remote-file-name-inhibit-auto-save-visited +An alternative to @code{auto-save-mode} is +@code{auto-save-visited-mode}. In this mode, auto-saving is identical +to explicit saving. If you want to disable this behavior for remote +files, set user option +@code{remote-file-name-inhibit-auto-save-visited} to non-@code{nil}. + @vindex lock-file-name-transforms And still more issues to handle. Since @w{Emacs 28}, file locks use a similar user option as auto-save files, called @@ -5675,7 +5683,7 @@ Unloading @value{tramp} resets Ange FTP plugins also. @end itemize -@c For the developer +@c For the developer. @node Files directories and localnames @chapter How file names, directories and localnames are mangled and managed commit 6b5d829d9dff0fa4bee28434c48c059107ae6c68 Author: Stefan Kangas Date: Tue Jul 5 19:57:34 2022 +0200 Add index entry for "ignore case" * doc/emacs/glossary.texi (Glossary): Add index entry for "ignore case" pointing to "Case Folding". diff --git a/doc/emacs/glossary.texi b/doc/emacs/glossary.texi index a78a2c9e2d..5224e31340 100644 --- a/doc/emacs/glossary.texi +++ b/doc/emacs/glossary.texi @@ -182,6 +182,7 @@ corresponding Control character. @xref{User Input,C-M-}. Case conversion means changing text from upper case to lower case or vice versa. @xref{Case}. +@cindex ignore case @item Case Folding Case folding means ignoring the differences between case variants of the same letter: upper-case, lower-case, and title-case. Emacs commit fe82c0743b3feecb9b80549ef4bb3dc8529891a8 Author: Stefan Kangas Date: Tue Jul 5 19:37:55 2022 +0200 Rename new option to remote-file-name-inhibit-auto-save-visited * lisp/files.el (remote-file-name-inhibit-auto-save-visited): Rename from 'auto-save-visited-remote-files' and invert logic. (auto-save-visited-mode): Adjust accordingly. (Bug#41333) Suggested by Michael Albinus . diff --git a/etc/NEWS b/etc/NEWS index 682ab6d721..7a1b7a856a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2009,9 +2009,9 @@ You can use it to automatically save only specific buffers, for example buffers using a particular mode or in some directory. --- -*** New user option 'auto-save-visited-remote-files'. -This user option controls whether or not 'auto-save-visited-mode' will -auto-save remote buffers. The default is t. +*** New user option 'remote-file-name-inhibit-auto-save-visited'. +If this user option is non-nil, 'auto-save-visited-mode' will not +auto-save remote buffers. The default is nil. +++ *** New package vtable.el for formatting tabular data. diff --git a/lisp/files.el b/lisp/files.el index 9eeed836c9..31e450355f 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -469,8 +469,9 @@ non-nil." :risky t :version "29.1") -(defcustom auto-save-visited-remote-files t - "If non-nil, `auto-save-visited-mode' will auto-save remote files." +(defcustom remote-file-name-inhibit-auto-save-visited nil + "When nil, `auto-save-visited-mode' will auto-save remote files. +Any other value means that it will not." :group 'auto-save :type 'boolean :version "29.1") @@ -509,7 +510,7 @@ For more details, see Info node `(emacs) Auto Save Files'." (not (and buffer-auto-save-file-name auto-save-visited-file-name)) (or (not (file-remote-p buffer-file-name)) - auto-save-visited-remote-files) + (not remote-file-name-inhibit-auto-save-visited)) (or (not (functionp auto-save-visited-predicate)) (funcall auto-save-visited-predicate)))))))) commit 89c589bae47fa7faa7273a9df0f4be836e9da29b Author: Lars Ingebrigtsen Date: Tue Jul 5 19:37:52 2022 +0200 Regenerate ldefs-boot.el diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index c38ede4d67..98dad181f4 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -313,8 +313,8 @@ Interactively, BEG and END are the mark/point of the current region. Many modes define specific alignment rules, and some of these rules in some modes react to the current prefix argument. For -instance, in `text-mode', `M-x align' will align into columns -based on space delimiters, while `C-u - M-x align' will align +instance, in `text-mode', \\`M-x align' will align into columns +based on space delimiters, while \\`C-u -' \\`M-x align' will align into columns based on the \"$\" character. See the `align-rules-list' variable definition for the specific rules. @@ -2119,10 +2119,10 @@ a reflection. ;;; Generated autoloads from bookmark.el - (define-key ctl-x-r-map "b" 'bookmark-jump) - (define-key ctl-x-r-map "m" 'bookmark-set) - (define-key ctl-x-r-map "M" 'bookmark-set-no-overwrite) - (define-key ctl-x-r-map "l" 'bookmark-bmenu-list) + (keymap-set ctl-x-r-map "b" #'bookmark-jump) + (keymap-set ctl-x-r-map "m" #'bookmark-set) + (keymap-set ctl-x-r-map "M" #'bookmark-set-no-overwrite) + (keymap-set ctl-x-r-map "l" #'bookmark-bmenu-list) (defvar-keymap bookmark-map :doc "\ Keymap containing bindings to bookmark functions. It is not bound to any key by default: to bind it @@ -4289,11 +4289,11 @@ The buffer is left in Command History mode." t nil) Examine commands from variable `command-history' in a buffer. The number of commands listed is controlled by `list-command-history-max'. The command history is filtered by `list-command-history-filter' if non-nil. -Use \\\\[command-history-repeat] to repeat the command on the current line. +Use \\\\[command-history-repeat] to repeat the command on the current line. Otherwise much like Emacs-Lisp Mode except that there is no self-insertion and digits provide prefix arguments. Tab does not indent. -\\{command-history-map} +\\{command-history-mode-map} This command always recompiles the Command History listing and runs the normal hook `command-history-hook'." t nil) @@ -7382,7 +7382,7 @@ Type \\[dired-do-copy] to Copy files. Type \\[dired-sort-toggle-or-edit] to toggle Sorting by name/date or change the `ls' switches. Type \\[revert-buffer] to read all currently expanded directories aGain. This retains all marks and hides subdirs again that were hidden before. -Use `SPC' and `DEL' to move down and up by lines. +Use \\`SPC' and \\`DEL' to move down and up by lines. If Dired ever gets confused, you can either type \\[revert-buffer] to read the directories again, type \\[dired-do-redisplay] to relist the file at point or the marked files or a @@ -8368,7 +8368,7 @@ Major mode for Ebrowse class tree buffers. Each line corresponds to a class in a class tree. Letters do not insert themselves, they are commands. File operations in the tree buffer work on class tree data structures. -E.g.\\[save-buffer] writes the tree to the file it was loaded from. +E.g. \\[save-buffer] writes the tree to the file it was loaded from. Tree mode key bindings: \\{ebrowse-tree-mode-map} @@ -9477,12 +9477,7 @@ Emerge two RCS revisions of a file, with another revision as ancestor. ;;; Generated autoloads from international/emoji.el (autoload 'emoji-insert "emoji" "\ -Choose and insert an emoji glyph. -If TEXT (interactively, the prefix argument), choose the emoji -by typing its Unicode Standard name (with completion), instead -of selecting from emoji display. - -(fn &optional TEXT)" t nil) +Choose and insert an emoji glyph." t nil) (autoload 'emoji-recent "emoji" "\ Choose and insert one of the recently-used emoji glyphs." t nil) (autoload 'emoji-search "emoji" "\ @@ -9509,13 +9504,9 @@ the name is not known. Increase the size of the character under point. FACTOR is the multiplication factor for the size. -This command will be repeatable if `repeat-mode' is switched on. - (fn &optional FACTOR)" t nil) (autoload 'emoji-zoom-decrease "emoji" "\ -Decrease the size of the character under point. - -This command will be repeatable if `repeat-mode' is switched on." t nil) +Decrease the size of the character under point." t nil) (register-definition-prefixes "emoji" '("emoji-")) @@ -9906,8 +9897,10 @@ Non-interactively, it takes the keyword arguments (server (erc-compute-server)) (port (erc-compute-port)) (nick (erc-compute-nick)) + (user (erc-compute-user)) password (full-name (erc-compute-full-name)) + id That is, if called with @@ -9917,7 +9910,11 @@ then the server and full-name will be set to those values, whereas `erc-compute-port' and `erc-compute-nick' will be invoked for the values of the other parameters. -(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)))" '((erc-select-read-args)) nil) +When present, ID should be an opaque object used to identify the +connection unequivocally. This is rarely needed and not available +interactively. + +(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) (USER (erc-compute-user)) PASSWORD (FULL-NAME (erc-compute-full-name)) ID)" '((erc-select-read-args)) nil) (defalias 'erc-select #'erc) (autoload 'erc-tls "erc" "\ ERC is a powerful, modular, and extensible IRC client. @@ -9933,6 +9930,7 @@ Non-interactively, it takes the keyword arguments password (full-name (erc-compute-full-name)) client-certificate + id That is, if called with @@ -9957,7 +9955,13 @@ Example usage: \\='(\"/home/bandali/my-cert.key\" \"/home/bandali/my-cert.crt\")) -(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)) CLIENT-CERTIFICATE)" '((let ((erc-default-port erc-default-port-tls)) (erc-select-read-args))) nil) +When present, ID should be an opaque object for identifying the +connection unequivocally. (In most cases, this would be a string or a +symbol composed of letters from the Latin alphabet.) This option is +generally unneeded, however. See info node `(erc) Connecting' for use +cases. Not available interactively. + +(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) (USER (erc-compute-user)) PASSWORD (FULL-NAME (erc-compute-full-name)) CLIENT-CERTIFICATE ID)" '((let ((erc-default-port erc-default-port-tls)) (erc-select-read-args))) nil) (autoload 'erc-handle-irc-url "erc" "\ Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD. If ERC is already connected to HOST:PORT, simply /join CHANNEL. @@ -10073,6 +10077,7 @@ Otherwise, connect to HOST:PORT as USER and /join CHANNEL. Return the name of the network or \"Unknown\" as a symbol. Use the server parameter NETWORK if provided, otherwise parse the server name and search for a match in `erc-networks-alist'." nil nil) +(make-obsolete 'erc-determine-network '"maybe see `erc-networks--determine'" "29.1") (autoload 'erc-server-select "erc-networks" "\ Interactively select a server to connect to using `erc-server-alist'." t nil) (register-definition-prefixes "erc-networks" '("erc-")) @@ -11244,9 +11249,9 @@ INC may be passed as a numeric prefix argument. The actual adjustment made depends on the final component of the keybinding used to invoke the command, with all modifiers removed: - +, = Increase font size in current buffer by one step - - Decrease font size in current buffer by one step - 0 Reset the font size to the global default + \\`+', \\`=' Increase font size in current buffer by one step + \\`-' Decrease font size in current buffer by one step + \\`0' Reset the font size to the global default After adjusting, continue to read input events and further adjust the font size as long as the input event read @@ -11268,12 +11273,43 @@ that have an explicit `:height' setting. The two exceptions to this are the `default' and `header-line' faces: they will both be scaled even if they have an explicit `:height' setting. +See also the related command `global-text-scale-adjust'. + (fn INC)" t nil) (define-key global-map [pinch] 'text-scale-pinch) (autoload 'text-scale-pinch "face-remap" "\ Adjust the height of the default face by the scale in the pinch event EVENT. (fn EVENT)" t nil) + (define-key ctl-x-map [(control meta ?+)] 'global-text-scale-adjust) + (define-key ctl-x-map [(control meta ?=)] 'global-text-scale-adjust) + (define-key ctl-x-map [(control meta ?-)] 'global-text-scale-adjust) + (define-key ctl-x-map [(control meta ?0)] 'global-text-scale-adjust) +(autoload 'global-text-scale-adjust "face-remap" "\ +Globally adjust the font size by INCREMENT. + +Interactively, INCREMENT may be passed as a numeric prefix argument. + +The adjustment made depends on the final component of the key binding +used to invoke the command, with all modifiers removed: + + \\`+', \\`=' Globally increase the height of the default face + \\`-' Globally decrease the height of the default face + \\`0' Globally reset the height of the default face + +After adjusting, further adjust the font size as long as the key, +with all modifiers removed, is one of the above characters. + +Buffer-local face adjustements have higher priority than global +face adjustments. + +The variable `global-text-scale-adjust-resizes-frames' controls +whether the frames are resized to keep the same number of lines +and characters per line when the font size is adjusted. + +See also the related command `text-scale-adjust'. + +(fn INCREMENT)" t nil) (autoload 'buffer-face-mode "face-remap" "\ Minor mode for a buffer-specific default face. @@ -11329,7 +11365,7 @@ An interface to `buffer-face-mode' which uses the `variable-pitch' face. Besides the choice of face, it is the same as `buffer-face-mode'. (fn &optional ARG)" t nil) -(register-definition-prefixes "face-remap" '("buffer-face-mode-" "face-" "internal-lisp-face-attributes" "text-scale-")) +(register-definition-prefixes "face-remap" '("buffer-face-mode-" "face-" "global-text-scale-adjust-" "internal-lisp-face-attributes" "text-scale-")) ;;; Generated autoloads from facemenu.el @@ -13791,7 +13827,7 @@ Return intersection of LIST1 and LIST2. LIST1 and LIST2 have to be sorted over <. (fn LIST1 LIST2)" nil nil) -(defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection) +(defalias 'gnus-set-sorted-intersection #'gnus-sorted-nintersection) (autoload 'gnus-sorted-nintersection "gnus-range" "\ Return intersection of LIST1 and LIST2 by modifying cdr pointers of LIST1. LIST1 and LIST2 have to be sorted over <. @@ -14235,7 +14271,7 @@ to specify a command to run. If CONFIRM is non-nil, the user will be given an opportunity to edit the command before it's run. -Interactively, the user can use the `M-c' command while entering +Interactively, the user can use the \\`M-c' command while entering the regexp to indicate whether the grep should be case sensitive or not. @@ -18675,6 +18711,41 @@ Major mode for browsing CVS log output. (fn)" t nil) (register-definition-prefixes "log-view" '("log-view-")) + +;;; Generated autoloads from longlines.el + +(autoload 'longlines-mode "longlines" "\ +Toggle Long Lines mode in this buffer. + +When Long Lines mode is enabled, long lines are wrapped if they +extend beyond `fill-column'. The soft newlines used for line +wrapping will not show up when the text is yanked or saved to +disk. + +If the variable `longlines-auto-wrap' is non-nil, lines are +automatically wrapped whenever the buffer is changed. You can +always call `fill-paragraph' to fill individual paragraphs. + +If the variable `longlines-show-hard-newlines' is non-nil, hard +newlines are indicated with a symbol. + +This is a minor mode. If called interactively, toggle the +`Longlines mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `longlines-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +(fn &optional ARG)" t nil) +(register-definition-prefixes "longlines" '("longlines-")) + ;;; Generated autoloads from lpr.el @@ -20011,7 +20082,7 @@ ripples outward, changing the flow of the eddy currents in the upper atmosphere. These cause momentary pockets of higher-pressure air to form, which act as lenses that deflect incoming cosmic rays, focusing them to strike the drive platter and flip the desired bit. -You can type `M-x butterfly C-M-c' to run it. This is a permuted +You can type \\`M-x butterfly C-M-c' to run it. This is a permuted variation of `C-x M-c M-butterfly' from url `https://xkcd.com/378/'." t nil) (autoload 'list-dynamic-libraries "misc" "\ Display a list of all dynamic libraries known to Emacs. @@ -30309,7 +30380,7 @@ commands to use in that buffer. (autoload 'ansi-term "term" "\ Start a terminal-emulator in a new buffer. This is almost the same as `term' apart from always creating a new buffer, -and `C-x' being marked as a `term-escape-char'. +and \\`C-x' being marked as a `term-escape-char'. (fn PROGRAM &optional NEW-BUFFER-NAME)" t nil) (autoload 'serial-term "term" "\ @@ -35114,6 +35185,11 @@ The optional ARGS are additional keyword arguments. Delete WIDGET. (fn WIDGET)" nil nil) +(autoload 'widget-convert "wid-edit" "\ +Convert TYPE to a widget without inserting it in the buffer. +The optional ARGS are additional keyword arguments. + +(fn TYPE &rest ARGS)" nil nil) (autoload 'widget-insert "wid-edit" "\ Call `insert' with ARGS even if surrounding text is read only. @@ -35321,8 +35397,8 @@ Winner mode is a global minor mode that records the changes in the window configuration (i.e. how the frames are partitioned into windows) so that the changes can be \"undone\" using the command `winner-undo'. By default this one is bound to the key -sequence `C-c '. If you change your mind (while undoing), -you can press `C-c ' (calling `winner-redo'). +sequence \\`C-c '. If you change your mind (while undoing), +you can press \\`C-c ' (calling `winner-redo'). This is a global minor mode. If called interactively, toggle the `Winner mode' mode. If the prefix argument is positive, enable commit 6d8638e5e494fb0ceafffe19bbf349fff643e12d Author: Lars Ingebrigtsen Date: Tue Jul 5 19:32:37 2022 +0200 Give a warning if setopt has been used with an invalid value * lisp/cus-edit.el (setopt--set): Mark the variable for checking. * lisp/custom.el (custom-initialize-reset): Give a warning if the type is wrong (bug#56400). * lisp/wid-edit.el (widget-convert): Autoload. diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 1f496af7d5..50dce5ee28 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1075,6 +1075,7 @@ plain variables. This means that `setopt' will execute any (when-let ((type (get variable 'custom-type))) (unless (widget-apply (widget-convert type) :match value) (user-error "Value `%S' does not match type %s" value type))) + (put variable 'custom-check-value (list value)) (funcall (or (get variable 'custom-set) #'set-default) variable value)) ;;;###autoload diff --git a/lisp/custom.el b/lisp/custom.el index 2b7621229d..a6e2ab351d 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -90,6 +90,16 @@ The value is either the symbol's current value (as obtained using the `:get' function), if any, or the value in the symbol's `saved-value' property if any, or (last of all) the value of EXP." + ;; If this value has been set with `setopt' (for instance in + ;; ~/.emacs), we didn't necessarily know the type of the user option + ;; then. So check now, and issue a warning if it's wrong. + (when-let ((value (get symbol 'custom-check-value)) + (type (get symbol 'custom-type))) + (when (and (boundp symbol) + (eq (car value) (symbol-value symbol)) + ;; Check that the type is correct. + (not (widget-apply (widget-convert type) :match (car value)))) + (warn "Value `%S' for `%s' does not match type %s" value symbol type))) (funcall (or (get symbol 'custom-set) #'set-default-toplevel-value) symbol (condition-case nil diff --git a/lisp/wid-edit.el b/lisp/wid-edit.el index 29b6e13bc6..5362618247 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -880,6 +880,7 @@ The child is converted, using the keyword arguments ARGS." "Make a deep copy of WIDGET." (widget-apply (copy-sequence widget) :copy)) +;;;###autoload (defun widget-convert (type &rest args) "Convert TYPE to a widget without inserting it in the buffer. The optional ARGS are additional keyword arguments." commit 29e1459965784cf37ad27324318aa4776481d173 Author: Stefan Kangas Date: Tue Jul 5 19:32:15 2022 +0200 ; * lisp/files.el (remote-file-name-inhibit-cache): Minor doc fix. diff --git a/lisp/files.el b/lisp/files.el index 752986b478..bccf7d56ba 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -1226,8 +1226,8 @@ Tip: You can use this expansion of remote identifier components (defcustom remote-file-name-inhibit-cache 10 "Whether to use the remote file-name cache for read access. -When nil, never expire cached values (caution) -When t, never use the cache (safe, but may be slow) +When nil, never expire cached values (caution). +When t, never use the cache (safe, but may be slow). A number means use cached values for that amount of seconds since caching. The attributes of remote files are cached for better performance. commit 99872bedf07315f642d143feaed9075a7ea20cba Author: Eli Zaretskii Date: Tue Jul 5 19:45:35 2022 +0300 ; * lisp/emacs-lisp/subr-x.el (string-limit): Clarify doc string. diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 39697a8e72..5159e8784a 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -170,11 +170,10 @@ limit the string to. The result will be a unibyte string that is shorter than LENGTH, but will not contain \"partial\" characters (or glyphs), even if CODING-SYSTEM encodes characters with several bytes per character. If the coding system specifies -things like byte order marks (aka \"BOM\") or language tags, they -will normally be part of the calculation. This is the case, for -instance, with `utf-16'. If this isn't desired, use a coding -system that doesn't specify a BOM, like `utf-16le' or -`utf-16be'. +prefix like the byte order mark (aka \"BOM\") or a shift-in sequence, +their bytes will be normally counted as part of LENGTH. This is +the case, for instance, with `utf-16'. If this isn't desired, use a +coding system that doesn't specify a BOM, like `utf-16le' or `utf-16be'. When shortening strings for display purposes, `truncate-string-to-width' is almost always a better alternative commit 23e4a30da283472a55b12ab1d120d703de435523 Author: Stefan Kangas Date: Tue Jul 5 17:54:43 2022 +0200 ; * etc/NEWS: Clarify entry. diff --git a/etc/NEWS b/etc/NEWS index 1d12938c0f..682ab6d721 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2289,7 +2289,7 @@ These function now take an optional comparison predicate argument. ** 'read-multiple-choice' can now use long-form answers. +++ -** 'read-regexp' now allows the user to indicate whether to use case folding. +** 'M-c' in 'read-regexp' now toggles case folding. +++ ** 'completing-read' now allows a function as its REQUIRE-MATCH argument. commit bc8e2565431da27dbe4e3c3377760911f1e6432e Author: Stefan Kangas Date: Tue Jul 5 17:53:06 2022 +0200 Re-fix narrowing problem in tramp-debug-buffer-command-completion-p * lisp/net/tramp.el (tramp-debug-buffer-command-completion-p): Respect narrowing also for end of substring. (Bug#56225) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index b580987e91..3725910714 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1957,7 +1957,7 @@ The outline level is equal to the verbosity of the Tramp message." They are completed by \"M-x TAB\" only in Tramp debug buffers." (with-current-buffer buffer (string-equal - (buffer-substring (point-min) (min 10 (point-max))) ";; Emacs:"))) + (buffer-substring (point-min) (min (+ (point-min) 10) (point-max))) ";; Emacs:"))) (put #'tramp-debug-buffer-command-completion-p 'tramp-suppress-trace t) commit 9d866a1f8da870dcf82f87d5ed9d5ca932d5477b Author: Stefan Kangas Date: Tue Jul 5 16:26:45 2022 +0200 Make some defcustom types more restrictive * lisp/abbrev.el (abbrev-suggest-hint-threshold): * lisp/bookmark.el (bookmark-bmenu-file-column) (bookmark-menu-length): * lisp/buff-menu.el (Buffer-menu-size-width) (Buffer-menu-mode-width): * lisp/calendar/calendar.el (calendar-week-start-day) (calendar-intermonth-spacing, calendar-column-width) (calendar-day-digit-width): * lisp/calc/calc.el (calc-undo-length): * lisp/calendar/timeclock.el (timeclock-workday): * lisp/comint.el (comint-buffer-maximum-size) (comint-input-ring-size): * lisp/doc-view.el (doc-view-resolution, doc-view-image-width): * lisp/emacs-lisp/bytecomp.el (byte-compile-docstring-max-column): * lisp/emacs-lisp/comp.el (native-comp-debug) (native-comp-verbose, native-comp-async-jobs-number): * lisp/emacs-lisp/package.el (package-name-column-width) (package-version-column-width, package-status-column-width) (package-archive-column-width): * lisp/eshell/esh-mode.el (eshell-buffer-maximum-lines): * lisp/frame.el (blink-cursor-blinks): * lisp/info.el (Info-breadcrumbs-depth): * lisp/jit-lock.el (jit-lock-chunk-size): * lisp/kmacro.el (kmacro-ring-max): * lisp/menu-bar.el (yank-menu-length, yank-menu-max-items): * lisp/midnight.el (clean-buffer-list-delay-general) (clean-buffer-list-delay-special): * lisp/net/dictionary.el (dictionary-port) (dictionary-proxy-port): * lisp/net/ldap.el (ldap-default-port): * lisp/net/pop3.el (pop3-port, pop3-stream-length): * lisp/net/rcirc.el (rcirc-default-port): * lisp/net/sieve-manage.el (sieve-manage-default-port): * lisp/play/spook.el (spook-phrase-default-count): * lisp/play/tetris.el (tetris-buffer-width) (tetris-buffer-height, tetris-width, tetris-height) (tetris-top-left-x, tetris-top-left-y): * lisp/profiler.el (profiler-sampling-interval): * lisp/progmodes/sql.el (sql-port): * lisp/recentf.el (recentf-max-menu-items): * lisp/strokes.el (strokes-grid-resolution): * lisp/tab-bar.el (tab-bar-tab-name-truncated-max): * lisp/term/xterm.el (xterm-max-cut-length): * lisp/time.el (display-time-interval, world-clock-timer-second): * lisp/url/url-cache.el (url-cache-expire-time): * lisp/url/url-cookie.el (url-cookie-save-interval): * lisp/url/url-history.el (url-history-save-interval): * lisp/url/url-queue.el (url-queue-parallel-processes) (url-queue-timeout): * lisp/url/url-vars.el (url-max-password-attempts) (url-max-redirections): * lisp/vc/emerge.el (emerge-min-visible-lines): * lisp/vc/vc.el (vc-log-show-limit): * lisp/window.el (window-min-height, window-min-width): * lisp/winner.el (winner-ring-size): Use :type natnum. * lisp/savehist.el (savehist-file-modes): Fix setting to nil value and use :type natnum. diff --git a/lisp/abbrev.el b/lisp/abbrev.el index e875d77faa..21aa3311d6 100644 --- a/lisp/abbrev.el +++ b/lisp/abbrev.el @@ -885,8 +885,8 @@ longer than the abbrev, the benefit of informing the user is not significant. If you always want to be informed about existing abbrevs for the text you type, set this value to zero or less. This setting only applies if `abbrev-suggest' is non-nil." - :type 'number - :version "28.1") + :type 'natnum + :version "28.1") (defun abbrev--suggest-get-active-tables-including-parents () "Return a list of all active abbrev tables, including parent tables." diff --git a/lisp/bookmark.el b/lisp/bookmark.el index 7138822447..b2130557dc 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -160,7 +160,7 @@ This includes the annotations column.") (defcustom bookmark-bmenu-file-column 30 "Column at which to display filenames in a buffer listing bookmarks. You can toggle whether files are shown with \\\\[bookmark-bmenu-toggle-filenames]." - :type 'integer) + :type 'natnum) (defcustom bookmark-bmenu-toggle-filenames t @@ -174,7 +174,7 @@ A non-nil value may result in truncated bookmark names." (defcustom bookmark-menu-length 70 "Maximum length of a bookmark name displayed on a popup menu." - :type 'integer) + :type 'natnum) ;; FIXME: Is it really worth a customization option? (defcustom bookmark-search-delay 0.2 diff --git a/lisp/buff-menu.el b/lisp/buff-menu.el index 179cc5484c..539ef673f0 100644 --- a/lisp/buff-menu.el +++ b/lisp/buff-menu.el @@ -92,13 +92,13 @@ number." (defcustom Buffer-menu-size-width 7 "Width of buffer size column in the Buffer Menu." - :type 'number + :type 'natnum :group 'Buffer-menu :version "24.3") (defcustom Buffer-menu-mode-width 16 "Width of mode name column in the Buffer Menu." - :type 'number + :type 'natnum :group 'Buffer-menu) (defcustom Buffer-menu-use-frame-buffer-list t diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el index b03dcfeb5b..254c703ee2 100644 --- a/lisp/calc/calc.el +++ b/lisp/calc/calc.el @@ -412,7 +412,7 @@ and deleted by `calc-pop'." (defcustom calc-undo-length 100 "The number of undo steps that will be preserved when Calc is quit." - :type 'integer) + :type 'natnum) (defcustom calc-highlight-selections-with-faces nil "If non-nil, use a separate face to indicate selected sub-formulas. diff --git a/lisp/calendar/calendar.el b/lisp/calendar/calendar.el index 9a77ae72d0..0d9e697644 100644 --- a/lisp/calendar/calendar.el +++ b/lisp/calendar/calendar.el @@ -211,7 +211,7 @@ If you change this variable directly (without using customize) after starting `calendar', you should call `calendar-redraw' to update the calendar display to reflect the change, otherwise movement commands will not work correctly." - :type 'integer + :type 'natnum ;; Change the initialize so that if you reload calendar.el, it will not ;; cause a redraw. :initialize 'custom-initialize-default @@ -511,7 +511,7 @@ Then redraw the calendar, if necessary." :initialize #'custom-initialize-default :set (lambda (sym val) (calendar-set-layout-variable sym val 1)) - :type 'integer + :type 'natnum :version "23.1") ;; FIXME calendar-month-column-width? @@ -520,7 +520,7 @@ Then redraw the calendar, if necessary." :initialize #'custom-initialize-default :set (lambda (sym val) (calendar-set-layout-variable sym val 3)) - :type 'integer + :type 'natnum :version "23.1") (defun calendar-day-header-construct (&optional width) @@ -553,7 +553,7 @@ Must be at least one less than `calendar-column-width'." :initialize #'custom-initialize-default :set (lambda (sym val) (calendar-set-layout-variable sym val 2)) - :type 'integer + :type 'natnum :version "23.1") (defcustom calendar-intermonth-header nil diff --git a/lisp/calendar/timeclock.el b/lisp/calendar/timeclock.el index 1c6a557a0d..7bdaf7ceff 100644 --- a/lisp/calendar/timeclock.el +++ b/lisp/calendar/timeclock.el @@ -86,7 +86,7 @@ (defcustom timeclock-workday (* 8 60 60) "The length of a work period in seconds." - :type 'integer) + :type 'natnum) (defvar timeclock--previous-workday nil) diff --git a/lisp/comint.el b/lisp/comint.el index 4fc1ffcf0c..7e22aa78fc 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -330,12 +330,12 @@ This variable is buffer-local in all Comint buffers." "The maximum size in lines for Comint buffers. Comint buffers are truncated from the top to be no greater than this number, if the function `comint-truncate-buffer' is on `comint-output-filter-functions'." - :type 'integer + :type 'natnum :group 'comint) (defcustom comint-input-ring-size 500 "Size of the input history ring in `comint-mode'." - :type 'integer + :type 'natnum :group 'comint :version "23.2") diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 63be1b16f3..25c476b99b 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -225,7 +225,7 @@ are available (see Info node `(emacs)Document View')" (defcustom doc-view-resolution 100 "Dots per inch resolution used to render the documents. Higher values result in larger images." - :type 'number) + :type 'natnum) (defvar doc-view-doc-type nil "The type of document in the current buffer. @@ -301,7 +301,7 @@ scaling." Has only an effect if `doc-view-scale-internally' is non-nil and support for scaling is compiled into Emacs." :version "24.1" - :type 'number) + :type 'natnum) (defcustom doc-view-dvipdfm-program "dvipdfm" "Program to convert DVI files to PDF. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 6545c8d961..5ef517d7e3 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1725,8 +1725,8 @@ The byte-compiler will emit a warning for documentation strings containing lines wider than this. If `fill-column' has a larger value, it will override this variable." :group 'bytecomp - :type 'integer - :safe #'integerp + :type 'natnum + :safe #'natnump :version "28.1") (define-obsolete-function-alias 'byte-compile-docstring-length-warn diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 2109aa9923..73285e0f24 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -63,7 +63,7 @@ This is intended for debugging the compiler itself. 2 emit debug symbols and dump pseudo C code. 3 emit debug symbols and dump: pseudo C code, GCC intermediate passes and libgccjit log file." - :type 'integer + :type 'natnum :safe #'natnump :version "28.1") @@ -74,7 +74,7 @@ This is intended for debugging the compiler itself. 1 final LIMPLE is logged. 2 LAP, final LIMPLE, and some pass info are logged. 3 max verbosity." - :type 'integer + :type 'natnum :risky t :version "28.1") @@ -111,7 +111,7 @@ during bootstrap." "Default number of subprocesses used for async native compilation. Value of zero means to use half the number of the CPU's execution units, or one if there's just one execution unit." - :type 'integer + :type 'natnum :risky t :version "28.1") diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 2c43db9899..85a154a8e0 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -418,22 +418,22 @@ synchronously." (defcustom package-name-column-width 30 "Column width for the Package name in the package menu." - :type 'number + :type 'natnum :version "28.1") (defcustom package-version-column-width 14 "Column width for the Package version in the package menu." - :type 'number + :type 'natnum :version "28.1") (defcustom package-status-column-width 12 "Column width for the Package status in the package menu." - :type 'number + :type 'natnum :version "28.1") (defcustom package-archive-column-width 8 "Column width for the Package archive in the package menu." - :type 'number + :type 'natnum :version "28.1") diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el index db36909fb8..972d4f9df0 100644 --- a/lisp/eshell/esh-mode.el +++ b/lisp/eshell/esh-mode.el @@ -146,7 +146,7 @@ See variable `eshell-scroll-to-bottom-on-output' and function Eshell buffers are truncated from the top to be no greater than this number, if the function `eshell-truncate-buffer' is on `eshell-output-filter-functions'." - :type 'integer) + :type 'natnum) (defcustom eshell-output-filter-functions '(eshell-postoutput-scroll-to-bottom diff --git a/lisp/frame.el b/lisp/frame.el index 6996bb2e9c..9476cb0ec4 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2841,7 +2841,7 @@ Values smaller than 0.2 sec are treated as 0.2 sec." "How many times to blink before using a solid cursor on NS, X, and MS-Windows. Use 0 or negative value to blink forever." :version "24.4" - :type 'integer + :type 'natnum :group 'cursor) (defvar blink-cursor-blinks-done 1 diff --git a/lisp/info.el b/lisp/info.el index f9d63b0f32..906385fdc7 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -260,7 +260,7 @@ This only has an effect if `Info-hide-note-references' is non-nil." "Depth of breadcrumbs to display. 0 means do not display breadcrumbs." :version "23.1" - :type 'integer) + :type 'natnum) (defcustom Info-search-whitespace-regexp "\\s-+" "If non-nil, regular expression to match a sequence of whitespace chars. diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el index a3ada44370..be26ca55f0 100644 --- a/lisp/jit-lock.el +++ b/lisp/jit-lock.el @@ -51,7 +51,7 @@ This variable controls both `display-time' and stealth fontification. The optimum value is a little over the typical number of buffer characters which fit in a typical window." - :type 'integer) + :type 'natnum) (defcustom jit-lock-stealth-time nil diff --git a/lisp/kmacro.el b/lisp/kmacro.el index 14be909722..92118ad143 100644 --- a/lisp/kmacro.el +++ b/lisp/kmacro.el @@ -129,7 +129,7 @@ Set to nil if no mouse binding is desired." (defcustom kmacro-ring-max 8 "Maximum number of keyboard macros to save in macro ring." - :type 'integer) + :type 'natnum) (defcustom kmacro-execute-before-append t diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 92989fcfb2..a134654a02 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -2194,12 +2194,12 @@ otherwise it could decide to silently do nothing." (defcustom yank-menu-length 20 "Text of items in `yank-menu' longer than this will be truncated." - :type 'integer + :type 'natnum :group 'menu) (defcustom yank-menu-max-items 60 "Maximum number of entries to display in the `yank-menu'." - :type 'integer + :type 'natnum :group 'menu :version "29.1") diff --git a/lisp/midnight.el b/lisp/midnight.el index 3e309a5c88..60d9b565ef 100644 --- a/lisp/midnight.el +++ b/lisp/midnight.el @@ -67,14 +67,14 @@ The autokilling is done by `clean-buffer-list' when it is in `midnight-hook'. Currently displayed and/or modified (unsaved) buffers, as well as buffers matching `clean-buffer-list-kill-never-buffer-names' and `clean-buffer-list-kill-never-regexps' are excluded." - :type 'integer) + :type 'natnum) (defcustom clean-buffer-list-delay-special 3600 "The number of seconds before some buffers become eligible for autokilling. Buffers matched by `clean-buffer-list-kill-regexps' and `clean-buffer-list-kill-buffer-names' are killed if they were last displayed more than this many seconds ago." - :type 'integer) + :type 'natnum) (defcustom clean-buffer-list-kill-regexps '("\\`\\*Man ") "List of regexps saying which buffers will be killed at midnight. diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el index e0824f3971..eec405373d 100644 --- a/lisp/net/dictionary.el +++ b/lisp/net/dictionary.el @@ -89,7 +89,7 @@ You can specify here: This port is probably always 2628 so there should be no need to modify it." :group 'dictionary :set #'dictionary-set-server-var - :type 'number + :type 'natnum :version "28.1") (defcustom dictionary-identification @@ -206,7 +206,7 @@ where the current word was found." "The port of the proxy server, used only when `dictionary-use-http-proxy' is set." :group 'dictionary-proxy :set #'dictionary-set-server-var - :type 'number + :type 'natnum :version "28.1") (defcustom dictionary-use-single-buffer diff --git a/lisp/net/ldap.el b/lisp/net/ldap.el index da45457891..0f2943cbb0 100644 --- a/lisp/net/ldap.el +++ b/lisp/net/ldap.el @@ -54,7 +54,7 @@ a separator." Initialized from the LDAP library at build time. Default value is 389." :type '(choice (const :tag "Use library default" nil) - (integer :tag "Port number"))) + (natnum :tag "Port number"))) (defcustom ldap-default-base nil "Default base for LDAP searches. diff --git a/lisp/net/pop3.el b/lisp/net/pop3.el index 0f6dfb6ad4..de225d76dc 100644 --- a/lisp/net/pop3.el +++ b/lisp/net/pop3.el @@ -59,7 +59,7 @@ (defcustom pop3-port 110 "POP3 port." :version "22.1" ;; Oort Gnus - :type 'number + :type 'natnum :group 'pop3) (defcustom pop3-password-required t @@ -88,7 +88,7 @@ valid value is `apop'." The lower the number, the more latency-sensitive the fetching will be. If your pop3 server doesn't support streaming at all, set this to 1." - :type 'number + :type 'natnum :version "24.1" :group 'pop3) diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index 36352a4673..dc0946fb09 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -130,7 +130,7 @@ be displayed instead." (defcustom rcirc-default-port 6667 "The default port to connect to." - :type 'integer) + :type 'natnum) (defcustom rcirc-default-nick (user-login-name) "Your nick." diff --git a/lisp/net/sieve-manage.el b/lisp/net/sieve-manage.el index 50342b9105..a39e35a53a 100644 --- a/lisp/net/sieve-manage.el +++ b/lisp/net/sieve-manage.el @@ -131,7 +131,7 @@ for doing the actual authentication." (defcustom sieve-manage-default-port "sieve" "Default port number or service name for managesieve protocol." - :type '(choice integer string) + :type '(choice natnum string) :version "24.4") (defcustom sieve-manage-default-stream 'network diff --git a/lisp/play/spook.el b/lisp/play/spook.el index f2bdba1c2a..ccff2e75b0 100644 --- a/lisp/play/spook.el +++ b/lisp/play/spook.el @@ -49,7 +49,7 @@ (defcustom spook-phrase-default-count 15 "Default number of phrases to insert." - :type 'integer) + :type 'natnum) ;;;###autoload (defun spook () diff --git a/lisp/play/tetris.el b/lisp/play/tetris.el index d9bc0dd020..a6bfea81ee 100644 --- a/lisp/play/tetris.el +++ b/lisp/play/tetris.el @@ -95,27 +95,27 @@ If the return value is a number, it is used as the timer period." (defcustom tetris-buffer-width 30 "Width of used portion of buffer." - :type 'number) + :type 'natnum) (defcustom tetris-buffer-height 22 "Height of used portion of buffer." - :type 'number) + :type 'natnum) (defcustom tetris-width 10 "Width of playing area." - :type 'number) + :type 'natnum) (defcustom tetris-height 20 "Height of playing area." - :type 'number) + :type 'natnum) (defcustom tetris-top-left-x 3 "X position of top left of playing area." - :type 'number) + :type 'natnum) (defcustom tetris-top-left-y 1 "Y position of top left of playing area." - :type 'number) + :type 'natnum) (defcustom tetris-allow-repetitions t "If non-nil, use a random selection for each shape. diff --git a/lisp/profiler.el b/lisp/profiler.el index 94c24c62aa..8670e5786a 100644 --- a/lisp/profiler.el +++ b/lisp/profiler.el @@ -38,7 +38,7 @@ (defcustom profiler-sampling-interval 1000000 "Default sampling interval in nanoseconds." - :type 'integer + :type 'natnum :group 'profiler) diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el index ef8375e859..b950f93f2a 100644 --- a/lisp/progmodes/sql.el +++ b/lisp/progmodes/sql.el @@ -274,8 +274,8 @@ file. Since that is a plaintext file, this could be dangerous." (defcustom sql-port 0 "Default port for connecting to a MySQL or Postgres server." :version "24.1" - :type 'number - :safe 'numberp) + :type 'natnum + :safe 'natnump) (defcustom sql-default-directory nil "Default directory for SQL processes." diff --git a/lisp/recentf.el b/lisp/recentf.el index 601b2642f7..4bc1ab5c21 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -178,7 +178,7 @@ The default is to call `find-file' to edit the selected file." (defcustom recentf-max-menu-items 10 "Maximum number of items in the recentf menu." :group 'recentf - :type 'integer) + :type 'natnum) (defcustom recentf-menu-filter nil "Function used to filter files displayed in the recentf menu. diff --git a/lisp/savehist.el b/lisp/savehist.el index 172acaa4e8..8924c8dde2 100644 --- a/lisp/savehist.el +++ b/lisp/savehist.el @@ -97,7 +97,8 @@ This is decimal, not octal. The default is 384 (0600 in octal). Set to nil to use the default permissions that Emacs uses, typically mandated by umask. The default is a bit more restrictive to protect the user's privacy." - :type 'integer) + :type '(choice (natnum :tag "Specify") + (const :tag "Use default" :value nil))) (defcustom savehist-autosave-interval (* 5 60) "The interval between autosaves of minibuffer history. diff --git a/lisp/strokes.el b/lisp/strokes.el index 5402ebf1e1..376cbc0cfe 100644 --- a/lisp/strokes.el +++ b/lisp/strokes.el @@ -252,7 +252,7 @@ WARNING: Changing the value of this variable will gravely affect the figure out what it should be based on your needs and on how quick the particular platform(s) you're operating on, and only then start programming in your custom strokes." - :type 'integer) + :type 'natnum) (defcustom strokes-file (locate-user-emacs-file "strokes" ".strokes") "File containing saved strokes for Strokes mode." diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 4ca177f73b..fdfbe207b5 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -618,7 +618,7 @@ Also add the number of windows in the window configuration." "Maximum length of the tab name from the current buffer. Effective when `tab-bar-tab-name-function' is customized to `tab-bar-tab-name-truncated'." - :type 'integer + :type 'natnum :group 'tab-bar :version "27.1") diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index a7e257f41c..08e38c9a05 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el @@ -66,7 +66,7 @@ If you select a region larger than this size, it won't be copied to your system clipboard. Since clipboard data is base 64 encoded, the actual number of string bytes that can be copied is 3/4 of this value." :version "25.1" - :type 'integer) + :type 'natnum) (defcustom xterm-set-window-title nil "Whether Emacs should set window titles to an Emacs frame in an XTerm." diff --git a/lisp/time.el b/lisp/time.el index cd985bfb28..e7066cae7a 100644 --- a/lisp/time.el +++ b/lisp/time.el @@ -93,7 +93,7 @@ Non-nil means \\[display-time] should display day and date as well as time." (defcustom display-time-interval 60 "Seconds between updates of time in the mode line." - :type 'integer) + :type 'natnum) (defcustom display-time-24hr-format nil "Non-nil indicates time should be displayed as hh:mm, 0 <= hh <= 23. @@ -519,7 +519,7 @@ If the value is t instead of an alist, use the value of (defcustom world-clock-timer-second 60 "Interval in seconds for updating the `world-clock' buffer." - :type 'integer + :type 'natnum :version "28.1") (defface world-clock-label diff --git a/lisp/url/url-cache.el b/lisp/url/url-cache.el index 3e69227124..db8c121cf0 100644 --- a/lisp/url/url-cache.el +++ b/lisp/url/url-cache.el @@ -37,7 +37,7 @@ "Default maximum time in seconds before cache files expire. Used by the function `url-cache-expired'." :version "24.1" - :type 'integer + :type 'natnum :group 'url-cache) ;; Cache manager diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el index 15c78512c6..0709cdd3fa 100644 --- a/lisp/url/url-cookie.el +++ b/lisp/url/url-cookie.el @@ -360,7 +360,7 @@ to run the `url-cookie-setup-save-timer' function manually." (set-default var val) (if (bound-and-true-p url-setup-done) (url-cookie-setup-save-timer))) - :type 'integer + :type 'natnum :group 'url-cookie) (defun url-cookie-setup-save-timer () diff --git a/lisp/url/url-history.el b/lisp/url/url-history.el index cb4814afca..058e601301 100644 --- a/lisp/url/url-history.el +++ b/lisp/url/url-history.el @@ -63,7 +63,7 @@ to run the `url-history-setup-save-timer' function manually." (set-default var val) (if (bound-and-true-p url-setup-done) (url-history-setup-save-timer))) - :type 'integer + :type 'natnum :group 'url-history) (defvar url-history-timer nil) diff --git a/lisp/url/url-queue.el b/lisp/url/url-queue.el index b2e24607e1..cf45a7f681 100644 --- a/lisp/url/url-queue.el +++ b/lisp/url/url-queue.el @@ -36,13 +36,13 @@ (defcustom url-queue-parallel-processes 6 "The number of concurrent processes." :version "24.1" - :type 'integer + :type 'natnum :group 'url) (defcustom url-queue-timeout 5 "How long to let a job live once it's started (in seconds)." :version "24.1" - :type 'integer + :type 'natnum :group 'url) ;;; Internal variables. diff --git a/lisp/url/url-vars.el b/lisp/url/url-vars.el index 1012525568..de42599e0d 100644 --- a/lisp/url/url-vars.el +++ b/lisp/url/url-vars.el @@ -297,7 +297,7 @@ get the first available language (as opposed to the default)." (defcustom url-max-password-attempts 5 "Maximum number of times a password will be prompted for. Applies when a protected document is denied by the server." - :type 'integer + :type 'natnum :group 'url) (defcustom url-show-status t @@ -330,7 +330,7 @@ undefined." (defcustom url-max-redirections 30 "The maximum number of redirection requests to honor in a HTTP connection. A negative number means to honor an unlimited number of redirection requests." - :type 'integer + :type 'natnum :group 'url) (defcustom url-confirmation-func 'y-or-n-p diff --git a/lisp/vc/emerge.el b/lisp/vc/emerge.el index 6e94ea0715..422ed5c0a4 100644 --- a/lisp/vc/emerge.el +++ b/lisp/vc/emerge.el @@ -221,7 +221,7 @@ depend on the flags." (defcustom emerge-min-visible-lines 3 "Number of lines to show above and below the flags when displaying a difference." - :type 'integer) + :type 'natnum) (defcustom emerge-temp-file-prefix (expand-file-name "emerge" temporary-file-directory) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index d6f0f4a497..d3e53858c1 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -824,7 +824,7 @@ for the backend you use." "Limit the number of items shown by the VC log commands. Zero means unlimited. Not all VC backends are able to support this feature." - :type 'integer) + :type 'natnum) (defcustom vc-allow-async-revert nil "Specifies whether the diff during \\[vc-revert] may be asynchronous. diff --git a/lisp/window.el b/lisp/window.el index eba888a89d..a3ef2521bb 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -451,7 +451,7 @@ window to a height less than the one specified here, an application should instead call `window-resize' with a non-nil IGNORE argument. In order to have `split-window' make a window shorter, explicitly specify the SIZE argument of that function." - :type 'integer + :type 'natnum :version "24.1" :group 'windows) @@ -483,7 +483,7 @@ window to a width less than the one specified here, an application should instead call `window-resize' with a non-nil IGNORE argument. In order to have `split-window' make a window narrower, explicitly specify the SIZE argument of that function." - :type 'integer + :type 'natnum :version "24.1" :group 'windows) diff --git a/lisp/winner.el b/lisp/winner.el index 9b2433b492..38ab5f5101 100644 --- a/lisp/winner.el +++ b/lisp/winner.el @@ -50,7 +50,7 @@ (defcustom winner-ring-size 200 "Maximum number of stored window configurations per frame." - :type 'integer) + :type 'natnum) (defcustom winner-boring-buffers '("*Completions*") "List of buffer names whose windows `winner-undo' will not restore. commit 3868c3aa3e4f1be4863f2a382174347b8cfd3d6c Author: Lars Ingebrigtsen Date: Tue Jul 5 18:26:52 2022 +0200 Don't hard-code `M-c' in `read-regexp' * lisp/replace.el (read-regexp-map): New map. (read-regexp--case-fold, read-regexp-toggle-case-folding) (read-regexp): Factor out to avoid hard-coding `M-c'. diff --git a/lisp/replace.el b/lisp/replace.el index 163d582148..54ee64f64a 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -895,6 +895,23 @@ by this function to the end of values available via (regexp-quote (or (car search-ring) "")) (car (symbol-value query-replace-from-history-variable)))) +(defvar-keymap read-regexp-map + :parent minibuffer-local-map + "M-c" #'read-regexp-toggle-case-folding) + +(defvar read-regexp--case-fold nil) + +(defun read-regexp-toggle-case-folding () + (interactive) + (setq read-regexp--case-fold + (if (or (eq read-regexp--case-fold 'fold) + (and read-regexp--case-fold + (not (eq read-regexp--case-fold 'inhibit-fold)))) + 'inhibit-fold + 'fold)) + (minibuffer-message "Case folding is now %s" + (if (eq read-regexp--case-fold 'fold) "on" "off"))) + (defun read-regexp (prompt &optional defaults history) "Read and return a regular expression as a string. Prompt with the string PROMPT. If PROMPT ends in \":\" (followed by @@ -931,11 +948,14 @@ in \":\", followed by optional whitespace), DEFAULT is added to the prompt. The optional argument HISTORY is a symbol to use for the history list. If nil, use `regexp-history'. -If the user has used the \\`M-c' command to specify case +If the user has used the \\\\[read-regexp-toggle-case-folding] command to specify case sensitivity, the returned string will have a text property named `case-fold' that has a value of either `fold' or `inhibit-fold'. (It's up to the caller of `read-regexp' to -respect this or not; see `read-regexp-case-fold-search'.)" +respect this or not; see `read-regexp-case-fold-search'.) + +This command uses the `read-regexp-map' keymap while reading the +regexp from the user." (let* ((defaults (if (and defaults (symbolp defaults)) (cond @@ -951,29 +971,15 @@ respect this or not; see `read-regexp-case-fold-search'.)" (suggestions (delete-dups (delq nil (delete "" suggestions)))) ;; Do not automatically add default to the history for empty input. (history-add-new-input nil) - (case-fold case-fold-search) + ;; `read-regexp--case-fold' dynamically bound and may be + ;; altered by `M-c'. + (read-regexp--case-fold case-fold-search) (input (read-from-minibuffer (if (string-match-p ":[ \t]*\\'" prompt) prompt (format-prompt prompt (and (length> default 0) (query-replace-descr default)))) - nil - (define-keymap - :parent minibuffer-local-map - "M-c" (lambda () - (interactive) - (setq case-fold - (if (or (eq case-fold 'fold) - (and case-fold - (not (eq case-fold - 'inhibit-fold)))) - 'inhibit-fold - 'fold)) - (minibuffer-message - "Case folding is now %s" - (if (eq case-fold 'fold) - "on" - "off")))) + nil read-regexp-map nil (or history 'regexp-history) suggestions t)) (result (if (equal input "") ;; Return the default value when the user enters @@ -983,9 +989,9 @@ respect this or not; see `read-regexp-case-fold-search'.)" (when result (add-to-history (or history 'regexp-history) result)) (if (and result - (or (eq case-fold 'fold) - (eq case-fold 'inhibit-fold))) - (propertize result 'case-fold case-fold) + (or (eq read-regexp--case-fold 'fold) + (eq read-regexp--case-fold 'inhibit-fold))) + (propertize result 'case-fold read-regexp--case-fold) (or result input)))) (defun read-regexp-case-fold-search (regexp) commit 3bd889cba06b8511856559afa31511b8d67f4b49 Author: Lars Ingebrigtsen Date: Tue Jul 5 13:44:45 2022 +0200 Documnt left/right mwheel events * doc/lispref/commands.texi (Misc Events): Document left/right mwheel events (bug#41722). diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index ed32814329..1718978a39 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2212,6 +2212,17 @@ and @code{mouse-wheel-down-alternate-event} defined in @file{mwheel.el} to determine what event types to expect for the mouse wheel. +@vindex mouse-wheel-left-event +@vindex mouse-wheel-right-event +Similarly, some mice can generate @code{mouse-wheel-left-event} and +@code{mouse-wheel-right-event} and can be used to scroll if +@code{mouse-wheel-tilt-scroll} is non-@code{nil}. However, some mice +also generate other events at the same time as they're generating +these scroll events which may get in the way. The way to fix this is +generally to unbind these events (for instance, @code{mouse-6} or +@code{mouse-7}, but this is very hardware and operating system +dependent). + @cindex @code{pinch} event @item (pinch @var{position} @var{dx} @var{dy} @var{scale} @var{angle}) This kind of event is generated by the user performing a ``pinch'' commit 8681bf1e851dd4abda066ddab5199768f310db8a Author: Lars Ingebrigtsen Date: Tue Jul 5 13:07:56 2022 +0200 Mention byte order marks in string-limit doc string * lisp/emacs-lisp/subr-x.el (string-limit): Mention byte order marks (bug#48324). diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 56e8c2aa86..39697a8e72 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -169,7 +169,12 @@ limiting, and LENGTH is interpreted as the number of bytes to limit the string to. The result will be a unibyte string that is shorter than LENGTH, but will not contain \"partial\" characters (or glyphs), even if CODING-SYSTEM encodes characters -with several bytes per character. +with several bytes per character. If the coding system specifies +things like byte order marks (aka \"BOM\") or language tags, they +will normally be part of the calculation. This is the case, for +instance, with `utf-16'. If this isn't desired, use a coding +system that doesn't specify a BOM, like `utf-16le' or +`utf-16be'. When shortening strings for display purposes, `truncate-string-to-width' is almost always a better alternative commit 59276ff81d1ab391f4e3cd91f3070a12c51a3507 Author: Eli Zaretskii Date: Tue Jul 5 16:12:13 2022 +0300 ; * lisp/files.el (auto-save-visited-predicate): Doc fix. diff --git a/lisp/files.el b/lisp/files.el index 67b3ae9b68..9eeed836c9 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -446,9 +446,10 @@ idle for `auto-save-visited-interval' seconds." (defcustom auto-save-visited-predicate nil "Predicate function for `auto-save-visited-mode'. -This function is called (with no argument) once in each -file-visiting buffer. Only those buffers are saved, where -the predicate function returns a non-nil value. +If non-nil, the value should be a function of no arguments; it +will be called once in each file-visiting buffer when the time +comes to auto-save. A buffer will be saved only if the predicate +function returns a non-nil value. For example, you could add this to your Init file to only save files that are both in Org mode and in a particular directory: @@ -460,7 +461,7 @@ files that are both in Org mode and in a particular directory: If the value of this variable is not a function, it is ignored. This is the same as having a predicate that always returns -true." +non-nil." :group 'auto-save :type '(choice :tag "Function:" (const :tag "No extra predicate" :value nil) commit 207101e1690d55b71ba3c7f6d7cd76ae279796e0 Author: Eli Zaretskii Date: Tue Jul 5 16:07:03 2022 +0300 ; Fix documentation of 'auto-save-visited-remote-files' * etc/NEWS: * lisp/files.el (auto-save-visited-remote-files): Doc fix. diff --git a/etc/NEWS b/etc/NEWS index c5f6987dcf..1d12938c0f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2011,7 +2011,7 @@ example buffers using a particular mode or in some directory. --- *** New user option 'auto-save-visited-remote-files'. This user option controls whether or not 'auto-save-visited-mode' will -save remote buffers. The default is t. +auto-save remote buffers. The default is t. +++ *** New package vtable.el for formatting tabular data. diff --git a/lisp/files.el b/lisp/files.el index 794305520d..67b3ae9b68 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -469,7 +469,7 @@ true." :version "29.1") (defcustom auto-save-visited-remote-files t - "If non-nil, `auto-save-visited-mode' will save remote files." + "If non-nil, `auto-save-visited-mode' will auto-save remote files." :group 'auto-save :type 'boolean :version "29.1") commit 3631355dcb97ccbf24dd7f7ca6efb97d78e0c511 Author: Stefan Kangas Date: Tue Jul 5 14:16:08 2022 +0200 New user option auto-save-visited-remote-files * lisp/files.el (auto-save-visited-remote-files): New user option. (auto-save-visited-mode): Use above new variable to decide whether or not to save remote files. (Bug#41333) diff --git a/etc/NEWS b/etc/NEWS index 5926148648..c5f6987dcf 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2008,6 +2008,11 @@ This user option is a predicate function which is called by You can use it to automatically save only specific buffers, for example buffers using a particular mode or in some directory. +--- +*** New user option 'auto-save-visited-remote-files'. +This user option controls whether or not 'auto-save-visited-mode' will +save remote buffers. The default is t. + +++ *** New package vtable.el for formatting tabular data. This package allows formatting data using variable-pitch fonts. diff --git a/lisp/files.el b/lisp/files.el index 55c50c33b4..794305520d 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -468,6 +468,12 @@ true." :risky t :version "29.1") +(defcustom auto-save-visited-remote-files t + "If non-nil, `auto-save-visited-mode' will save remote files." + :group 'auto-save + :type 'boolean + :version "29.1") + (define-minor-mode auto-save-visited-mode "Toggle automatic saving to file-visiting buffers on or off. @@ -501,6 +507,8 @@ For more details, see Info node `(emacs) Auto Save Files'." auto-save-visited-mode (not (and buffer-auto-save-file-name auto-save-visited-file-name)) + (or (not (file-remote-p buffer-file-name)) + auto-save-visited-remote-files) (or (not (functionp auto-save-visited-predicate)) (funcall auto-save-visited-predicate)))))))) commit ac7f76528f2f2e2f6e77bc25e7040eb3b07e45c0 Author: Stefan Kangas Date: Tue Jul 5 13:34:24 2022 +0200 New user option auto-save-visited-mode-predicate * lisp/files.el (auto-save-visited-mode-predicate): New defcustom. (auto-save-visited-mode): Use above new variable as a predicate to decide whether or not to save a buffer. diff --git a/etc/NEWS b/etc/NEWS index 7967190c6e..5926148648 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2001,6 +2001,13 @@ Set it to nil to exclude line numbering from kills and copies. This option provides a mechanism to selectively disable font-lock keyword-driven fontifications. +--- +*** New user option 'auto-save-visited-predicate'. +This user option is a predicate function which is called by +'auto-save-visited-mode' to decide whether or not to save a buffer. +You can use it to automatically save only specific buffers, for +example buffers using a particular mode or in some directory. + +++ *** New package vtable.el for formatting tabular data. This package allows formatting data using variable-pitch fonts. diff --git a/lisp/files.el b/lisp/files.el index 8812175014..55c50c33b4 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -443,6 +443,31 @@ idle for `auto-save-visited-interval' seconds." (when auto-save--timer (timer-set-idle-time auto-save--timer value :repeat)))) +(defcustom auto-save-visited-predicate nil + "Predicate function for `auto-save-visited-mode'. + +This function is called (with no argument) once in each +file-visiting buffer. Only those buffers are saved, where +the predicate function returns a non-nil value. + +For example, you could add this to your Init file to only save +files that are both in Org mode and in a particular directory: + + (setq auto-save-visited-predicate + (lambda () (and (eq major-mode \\='org-mode) + (string-match \"^/home/skangas/org/\" + buffer-file-name)))) + +If the value of this variable is not a function, it is ignored. +This is the same as having a predicate that always returns +true." + :group 'auto-save + :type '(choice :tag "Function:" + (const :tag "No extra predicate" :value nil) + (function :tag "Predicate function" :value always)) + :risky t + :version "29.1") + (define-minor-mode auto-save-visited-mode "Toggle automatic saving to file-visiting buffers on or off. @@ -453,6 +478,9 @@ Unlike `auto-save-mode', this mode will auto-save buffer contents to the visited files directly and will also run all save-related hooks. See Info node `Saving' for details of the save process. +You can use `auto-save-visited-predicate' to control which +buffers are saved. + You can also set the buffer-local value of the variable `auto-save-visited-mode' to nil. A buffer where the buffer-local value of this variable is nil is ignored for the purpose of @@ -472,7 +500,9 @@ For more details, see Info node `(emacs) Auto Save Files'." (and buffer-file-name auto-save-visited-mode (not (and buffer-auto-save-file-name - auto-save-visited-file-name)))))))) + auto-save-visited-file-name)) + (or (not (functionp auto-save-visited-predicate)) + (funcall auto-save-visited-predicate)))))))) ;; The 'set' part is so we don't get a warning for using this variable ;; above, while still catching code that _sets_ the variable to get commit 74bca06469424f32f49399300c3e05233a0aaa72 Author: Stefan Kangas Date: Tue Jul 5 13:37:32 2022 +0200 Shorten name of recently added command to emacs-news-open-line * lisp/textmodes/emacs-news-mode.el (emacs-news-open-line): Rename from 'emacs-news-mode-open-line'. diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el index 4ca6ea86d8..be4bba06d2 100644 --- a/lisp/textmodes/emacs-news-mode.el +++ b/lisp/textmodes/emacs-news-mode.el @@ -55,7 +55,7 @@ "C-c C-g" #'emacs-news-goto-section "C-c C-j" #'emacs-news-find-heading "C-c C-e" #'emacs-news-count-untagged-entries - " " #'emacs-news-mode-open-line) + " " #'emacs-news-open-line) (defvar-keymap emacs-news-view-mode-map :parent emacs-news-common-map) @@ -233,7 +233,7 @@ untagged NEWS entry." (when (re-search-forward (concat "^*+ " (regexp-quote heading)) nil t) (beginning-of-line))) -(defun emacs-news-mode-open-line (n) +(defun emacs-news-open-line (n) "Open a new line in a NEWS file. This is like `open-line', but skips any temporary NEWS-style documentation marks on the previous line." commit 9298a571ebb15b3020c9e865d0a34cff4a07e77e Author: Po Lu Date: Tue Jul 5 19:17:03 2022 +0800 Fix manually disowning Emacs drag atoms * src/xterm.c (handle_one_xevent): Disown Motif drag atom if eventp->time is CurrentTime as well. This can happen with some synthetic events. diff --git a/src/xterm.c b/src/xterm.c index 771db4a05c..4a47fdfd45 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -16908,7 +16908,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, const XSelectionClearEvent *eventp = &event->xselectionclear; if (eventp->selection == dpyinfo->motif_drag_atom - && dpyinfo->motif_drag_atom_time <= eventp->time) + && (eventp->time == CurrentTime + || dpyinfo->motif_drag_atom_time <= eventp->time)) dpyinfo->motif_drag_atom = None; inev.sie.kind = SELECTION_CLEAR_EVENT; commit 678453ebc65cc075fbf777a9b41557c26de544f2 Author: Lars Ingebrigtsen Date: Tue Jul 5 13:03:36 2022 +0200 Remove the interactive prefix from emoji-insert * lisp/international/emoji.el (emoji-insert): Remove the prefix action from this command, since the same is already available on `C-x 8 e s', and we're considering using the prefix to copy to the kill ring. diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index 27b725b0aa..341b44cc11 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -73,18 +73,13 @@ representing names. For instance: (defvar emoji--insert-buffer) ;;;###autoload -(defun emoji-insert (&optional text) - "Choose and insert an emoji glyph. -If TEXT (interactively, the prefix argument), choose the emoji -by typing its Unicode Standard name (with completion), instead -of selecting from emoji display." - (interactive "*P") +(defun emoji-insert () + "Choose and insert an emoji glyph." + (interactive "*") (emoji--init) - (if text - (emoji--choose-emoji) - (unless (fboundp 'emoji--command-Emoji) - (emoji--define-transient)) - (funcall (intern "emoji--command-Emoji")))) + (unless (fboundp 'emoji--command-Emoji) + (emoji--define-transient)) + (funcall (intern "emoji--command-Emoji"))) ;;;###autoload (defun emoji-recent () commit 6dfe33297180765935858855ce4bd1934f533bb0 Author: Po Lu Date: Tue Jul 5 14:55:24 2022 +0800 Allow immediately saving XDS drops This fixes things with programs that have a very timeout, such as Chromium, within which it isn't practical for the user to confirm the default file name. * lisp/x-dnd.el (x-dnd-direct-save-function): Add new choices to defcustom. (x-dnd-init-frame): Use fast protocol requests. (x-dnd-save-direct-immediately): New function. (x-dnd-handle-xds-drop): Fix nil values of selected file name. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 3fd2d70cb6..9c1c98a1bf 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -135,7 +135,11 @@ It can also return nil, which means to cancel the drop. If the first argument is nil, the second is the name of the file that was dropped." :version "29.1" - :type 'function + :type '(choice (const :tag "Prompt for name before saving" + x-dnd-save-direct) + (const :tag "Save and open immediately without prompting" + x-dnd-save-direct-immediately) + (function :tag "Other function")) :group 'x) (defcustom x-dnd-copy-types '("chromium/x-renderer-taint") @@ -186,18 +190,21 @@ any protocol specific data.") (declare-function x-register-dnd-atom "xselect.c") +(defvar x-fast-protocol-requests) + (defun x-dnd-init-frame (&optional frame) "Setup drag and drop for FRAME (i.e. create appropriate properties)." (when (eq 'x (window-system frame)) - (x-register-dnd-atom "DndProtocol" frame) - (x-register-dnd-atom "_MOTIF_DRAG_AND_DROP_MESSAGE" frame) - (x-register-dnd-atom "XdndEnter" frame) - (x-register-dnd-atom "XdndPosition" frame) - (x-register-dnd-atom "XdndLeave" frame) - (x-register-dnd-atom "XdndDrop" frame) - (x-register-dnd-atom "_DND_PROTOCOL" frame) - (x-dnd-init-xdnd-for-frame frame) - (x-dnd-init-motif-for-frame frame))) + (let ((x-fast-protocol-requests (not x-dnd-debug-errors))) + (x-register-dnd-atom "DndProtocol" frame) + (x-register-dnd-atom "_MOTIF_DRAG_AND_DROP_MESSAGE" frame) + (x-register-dnd-atom "XdndEnter" frame) + (x-register-dnd-atom "XdndPosition" frame) + (x-register-dnd-atom "XdndLeave" frame) + (x-register-dnd-atom "XdndDrop" frame) + (x-register-dnd-atom "_DND_PROTOCOL" frame) + (x-dnd-init-xdnd-for-frame frame) + (x-dnd-init-motif-for-frame frame)))) (defun x-dnd-get-state-cons-for-frame (frame-or-window) "Return the entry in `x-dnd-current-state' for a frame or window." @@ -430,8 +437,6 @@ nil if not." (select-frame frame) (funcall handler window action data)))))) -(defvar x-fast-protocol-requests) - (defun x-dnd-handle-drag-n-drop-event (event) "Receive drag and drop events (X client messages). Currently XDND, Motif and old KDE 1.x protocols are recognized." @@ -1361,6 +1366,27 @@ Prompt the user for a file name, then open it." (revert-buffer) (find-file name)))) +(defun x-dnd-save-direct-immediately (need-name name) + "Save and open a dropped file, like `x-dnd-save-direct'. +NEED-NAME tells whether or not the file was not yet saved. NAME +is either the name of the file, or the name the drop source wants +us to save under. + +Unlike `x-dnd-save-direct', do not prompt for the name by which +to save the file. Simply save it in the current directory." + (if need-name + (let ((file-name (expand-file-name name))) + (when (file-exists-p file-name) + (unless (y-or-n-p (format-message + "File `%s' exists; overwrite? " file-name)) + (setq file-name nil))) + file-name) + ;; TODO: move this to dired.el once a platform-agonistic + ;; interface can be found. + (if (derived-mode-p 'dired-mode) + (revert-buffer) + (find-file name)))) + (defun x-dnd-handle-octet-stream-for-drop (save-to) "Save the contents of the XDS selection to SAVE-TO. Return non-nil if successful, nil otherwise." @@ -1402,15 +1428,14 @@ VERSION is the version of the XDND protocol understood by SOURCE." desired-name (or file-name-coding-system default-file-name-coding-system))) - (setq save-to (expand-file-name - (funcall x-dnd-direct-save-function - t desired-name)) - save-to-remote save-to) - (if (file-remote-p save-to) - (setq hostname (file-remote-p save-to 'host) - save-to (file-local-name save-to)) - (setq hostname (system-name))) + (let ((name (funcall x-dnd-direct-save-function + t desired-name))) + (setq save-to name save-to-remote name)) (when save-to + (if (file-remote-p save-to) + (setq hostname (file-remote-p save-to 'host) + save-to (file-local-name save-to)) + (setq hostname (system-name))) (with-selected-window window (let ((uri (format "file://%s%s" hostname save-to))) (x-change-window-property "XdndDirectSave0" commit 59206529a17a8ae976072d8306882c4ff37a2fbd Author: Paul Eggert Date: Mon Jul 4 23:12:45 2022 -0500 Quote configure.ac arguments more consistently This should help avoid further Autoconf portability gotchas such as the one recently fixed in 2022-06-27T04:26:01Z!meyering@fb.com. * autogen.sh (autoconf_min): Adjust pattern to match updated configure.ac. * configure.ac: Quote arguments more consistently, as per the Autoconf manual. diff --git a/autogen.sh b/autogen.sh index 03f647e576..041468edcd 100755 --- a/autogen.sh +++ b/autogen.sh @@ -35,7 +35,7 @@ progs="autoconf" ## Minimum versions we need: -autoconf_min=`sed -n 's/^ *AC_PREREQ(\([0-9\.]*\)).*/\1/p' configure.ac` +autoconf_min=`sed -n 's/^ *AC_PREREQ(\[\([0-9\.]*\)]).*/\1/p' configure.ac` ## $1 = program, eg "autoconf". diff --git a/configure.ac b/configure.ac index 3afe2e0114..45b62647e7 100644 --- a/configure.ac +++ b/configure.ac @@ -21,9 +21,10 @@ dnl dnl You should have received a copy of the GNU General Public License dnl along with GNU Emacs. If not, see . -AC_PREREQ(2.65) +AC_PREREQ([2.65]) dnl Note this is parsed by (at least) make-dist and lisp/cedet/ede/emacs.el. -AC_INIT(GNU Emacs, 29.0.50, bug-gnu-emacs@gnu.org, , https://www.gnu.org/software/emacs/) +AC_INIT([GNU Emacs], [29.0.50], [bug-gnu-emacs@gnu.org], [], + [https://www.gnu.org/software/emacs/]) dnl Set emacs_config_options to the options of 'configure', quoted for the shell, dnl and then quoted again for a C string. Separate options with spaces. @@ -64,13 +65,13 @@ for opt in "$@" CFLAGS CPPFLAGS LDFLAGS; do optsep=' ' done -AC_CONFIG_HEADERS(src/config.h:src/config.in) -AC_CONFIG_SRCDIR(src/lisp.h) -AC_CONFIG_AUX_DIR(build-aux) -AC_CONFIG_MACRO_DIR(m4) +AC_CONFIG_HEADERS([src/config.h:src/config.in]) +AC_CONFIG_SRCDIR([src/lisp.h]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([m4]) xcsdkdir= -AC_CHECK_PROGS(XCRUN, [xcrun]) +AC_CHECK_PROGS([XCRUN], [xcrun]) if test -n "$XCRUN"; then if test -z "$MAKE"; then dnl Call the variable MAKE_PROG, not MAKE, to avoid confusion with @@ -199,7 +200,7 @@ etcdocdir='${datadir}/emacs/${version}/etc' gamedir='${localstatedir}/games/emacs' dnl Special option to disable the most of other options. -AC_ARG_WITH(all, +AC_ARG_WITH([all], [AS_HELP_STRING([--without-all], [omit almost all features and build small executable with minimal dependencies])], @@ -278,41 +279,45 @@ AC_ARG_WITH([pop], *) with_pop=no-by-default;; esac]) if test "$with_pop" = yes; then - AC_DEFINE(MAIL_USE_POP) + AC_DEFINE([MAIL_USE_POP]) fi -AH_TEMPLATE(MAIL_USE_POP, [Define to support POP mail retrieval.])dnl +AH_TEMPLATE([MAIL_USE_POP], [Define to support POP mail retrieval.])dnl OPTION_DEFAULT_OFF([kerberos],[support Kerberos-authenticated POP]) if test "$with_kerberos" != no; then - AC_DEFINE(KERBEROS) + AC_DEFINE([KERBEROS]) fi -AH_TEMPLATE(KERBEROS, +AH_TEMPLATE([KERBEROS], [Define to support Kerberos-authenticated POP mail retrieval.])dnl OPTION_DEFAULT_OFF([kerberos5],[support Kerberos version 5 authenticated POP]) if test "${with_kerberos5}" != no; then if test "${with_kerberos}" = no; then with_kerberos=yes - AC_DEFINE(KERBEROS) + AC_DEFINE([KERBEROS]) fi - AC_DEFINE(KERBEROS5, 1, [Define to use Kerberos 5 instead of Kerberos 4.]) + AC_DEFINE([KERBEROS5], [1], + [Define to use Kerberos 5 instead of Kerberos 4.]) fi OPTION_DEFAULT_OFF([hesiod],[support Hesiod to get the POP server host]) dnl FIXME hesiod support may not be present, so it seems like an error dnl to define, or at least use, this unconditionally. if test "$with_hesiod" != no; then - AC_DEFINE(HESIOD, 1, [Define to support using a Hesiod database to find the POP server.]) + AC_DEFINE([HESIOD], [1], + [Define to support using a Hesiod database to find the POP server.]) fi OPTION_DEFAULT_OFF([mail-unlink],[unlink, rather than empty, mail spool after reading]) if test "$with_mail_unlink" != no; then - AC_DEFINE(MAIL_UNLINK_SPOOL, 1, [Define to unlink, rather than empty, mail spool after reading.]) + AC_DEFINE([MAIL_UNLINK_SPOOL], [1], + [Define to unlink, rather than empty, mail spool after reading.]) fi AC_ARG_WITH([mailhost],[AS_HELP_STRING([--with-mailhost=HOSTNAME], [string giving default POP mail host])], - AC_DEFINE_UNQUOTED(MAILHOST, ["$withval"], [String giving fallback POP mail host.])) + AC_DEFINE_UNQUOTED([MAILHOST], ["$withval"], + [String giving fallback POP mail host.])) AC_ARG_WITH([sound],[AS_HELP_STRING([--with-sound=VALUE], [compile with sound support (VALUE one of: yes, alsa, oss, bsd-ossaudio, no; @@ -395,7 +400,8 @@ if test "$with_dumping" = "unexec" && test "$with_unexec" = "no"; then fi if test "$with_pdumper" = "yes"; then - AC_DEFINE([HAVE_PDUMPER], 1, [Define to build with portable dumper support]) + AC_DEFINE([HAVE_PDUMPER], [1], + [Define to build with portable dumper support]) HAVE_PDUMPER=yes else HAVE_PDUMPER=no @@ -403,7 +409,7 @@ fi AC_SUBST([HAVE_PDUMPER]) DUMPING=$with_dumping -AC_SUBST(DUMPING) +AC_SUBST([DUMPING]) dnl FIXME currently it is not the last. dnl This should be the last --with option, because --with-x is @@ -436,7 +442,7 @@ OPTION_DEFAULT_OFF([wide-int], at the cost of 10% to 30% slowdown of Lisp interpreter and larger memory footprint]) if test "$with_wide_int" = yes; then - AC_DEFINE([WIDE_EMACS_INT], 1, [Use long long for EMACS_INT if available.]) + AC_DEFINE([WIDE_EMACS_INT], [1], [Use long long for EMACS_INT if available.]) fi dnl _ON results in a '--without' option in the --help output, so @@ -522,7 +528,7 @@ OPTION_DEFAULT_OFF([be-cairo], [enable use of cairo under Haiku's Application Kit]) ## Makefile.in needs the cache file name. -AC_SUBST(cache_file) +AC_SUBST([cache_file]) ## This is an option because I do not know if all info/man support ## compressed files, nor how to test if they do so. @@ -530,7 +536,7 @@ OPTION_DEFAULT_ON([compress-install], [don't compress some files (.el, .info, etc.) when installing. Equivalent to: make GZIP_PROG= install]) -AC_ARG_WITH(gameuser,dnl +AC_ARG_WITH([gameuser], [AS_HELP_STRING([--with-gameuser=USER_OR_GROUP], [user for shared game score files. An argument prefixed by ':' specifies a group instead.])]) @@ -543,7 +549,7 @@ case ${with_gameuser} in *) gameuser=${with_gameuser} ;; esac -AC_ARG_WITH([gnustep-conf],dnl +AC_ARG_WITH([gnustep-conf], [AS_HELP_STRING([--with-gnustep-conf=FILENAME], [name of GNUstep configuration file to use on systems where the command 'gnustep-config' does not work; default $GNUSTEP_CONFIG_FILE, or @@ -553,24 +559,24 @@ test "X${with_gnustep_conf}" != X && test "${with_gnustep_conf}" != yes && \ test "X$GNUSTEP_CONFIG_FILE" = "X" && \ GNUSTEP_CONFIG_FILE=/etc/GNUstep/GNUstep.conf -AC_ARG_ENABLE(ns-self-contained, +AC_ARG_ENABLE([ns-self-contained], [AS_HELP_STRING([--disable-ns-self-contained], [disable self contained build under NeXTstep])], - EN_NS_SELF_CONTAINED=$enableval, - EN_NS_SELF_CONTAINED=yes) + [EN_NS_SELF_CONTAINED=$enableval], + [EN_NS_SELF_CONTAINED=yes]) locallisppathset=no -AC_ARG_ENABLE(locallisppath, +AC_ARG_ENABLE([locallisppath], [AS_HELP_STRING([--enable-locallisppath=PATH], [directories Emacs should search for lisp files specific to this site])], -if test "${enableval}" = "no"; then +[if test "${enableval}" = "no"; then locallisppath= elif test "${enableval}" != "yes"; then locallisppath=${enableval} locallisppathset=yes -fi) +fi]) -AC_ARG_ENABLE(checking, +AC_ARG_ENABLE([checking], [AS_HELP_STRING([--enable-checking@<:@=LIST@:>@], [enable expensive checks. With LIST, enable only specific categories of checks. @@ -603,17 +609,17 @@ do stringfreelist) ac_gc_check_string_free_list=1 ;; structs) CHECK_STRUCTS=true ;; glyphs) ac_glyphs_debug=1 ;; - *) AC_MSG_ERROR(unknown check category $check) ;; + *) AC_MSG_ERROR([unknown check category $check]) ;; esac done IFS="$ac_save_IFS" if test x$ac_enable_checking != x ; then - AC_DEFINE(ENABLE_CHECKING, 1, + AC_DEFINE([ENABLE_CHECKING], [1], [Define to 1 if expensive run-time data type and consistency checks are enabled.]) fi if $CHECK_STRUCTS; then - AC_DEFINE([CHECK_STRUCTS], 1, + AC_DEFINE([CHECK_STRUCTS], [1], [Define this to check whether someone updated the portable dumper code after changing the layout of a structure that it uses. If you change one of these structures, check that the pdumper.c @@ -622,21 +628,21 @@ if $CHECK_STRUCTS; then fi AC_SUBST([CHECK_STRUCTS]) if test x$ac_gc_check_stringbytes != x ; then - AC_DEFINE(GC_CHECK_STRING_BYTES, 1, + AC_DEFINE([GC_CHECK_STRING_BYTES], [1], [Define this temporarily to hunt a bug. If defined, the size of strings is redundantly recorded in sdata structures so that it can be compared to the sizes recorded in Lisp strings.]) fi if test x$ac_gc_check_string_overrun != x ; then - AC_DEFINE(GC_CHECK_STRING_OVERRUN, 1, + AC_DEFINE([GC_CHECK_STRING_OVERRUN], [1], [Define this to check for short string overrun.]) fi if test x$ac_gc_check_string_free_list != x ; then - AC_DEFINE(GC_CHECK_STRING_FREE_LIST, 1, + AC_DEFINE([GC_CHECK_STRING_FREE_LIST], [1], [Define this to check the string free list.]) fi if test x$ac_glyphs_debug != x ; then - AC_DEFINE(GLYPH_DEBUG, 1, + AC_DEFINE([GLYPH_DEBUG], [1], [Define this to enable glyphs debugging code.]) fi @@ -644,7 +650,7 @@ dnl The name of this option is unfortunate. It predates, and has no dnl relation to, the "sampling-based elisp profiler" added in 24.3. dnl Actually, it stops it working. dnl https://lists.gnu.org/r/emacs-devel/2012-11/msg00393.html -AC_ARG_ENABLE(profiling, +AC_ARG_ENABLE([profiling], [AS_HELP_STRING([--enable-profiling], [build emacs with low-level, gprof profiling support. Mainly useful for debugging Emacs itself. May not work on @@ -655,15 +661,15 @@ if test x$ac_enable_profiling != x ; then else PROFILING_CFLAGS= fi -AC_SUBST(PROFILING_CFLAGS) +AC_SUBST([PROFILING_CFLAGS]) -AC_ARG_ENABLE(autodepend, +AC_ARG_ENABLE([autodepend], [AS_HELP_STRING([--enable-autodepend], [automatically generate dependencies to .h-files. Requires gcc, enabled if found.])], [ac_enable_autodepend="${enableval}"],[ac_enable_autodepend=yes]) -AC_ARG_ENABLE(gtk-deprecation-warnings, +AC_ARG_ENABLE([gtk-deprecation-warnings], [AS_HELP_STRING([--enable-gtk-deprecation-warnings], [Show Gtk+/Gdk deprecation warnings for Gtk+ >= 3.0])], [ac_enable_gtk_deprecation_warnings="${enableval}"],[]) @@ -866,7 +872,7 @@ AC_DEFUN([_AC_PROG_CC_C89], [$2]) dnl Sets GCC=yes if using gcc. AC_PROG_CC([gcc cc cl clang "$XCRUN gcc" "$XCRUN clang"]) if test -n "$XCRUN"; then - AC_CHECK_PROGS(AR, [ar "$XCRUN ar"]) + AC_CHECK_PROGS([AR], [ar "$XCRUN ar"]) test -n "$AR" && export AR fi @@ -1008,7 +1014,7 @@ AC_ARG_ENABLE([check-lisp-object-type], [Enable compile time checks for the Lisp_Object data type, which can catch some bugs during development.])]) if test "$enable_check_lisp_object_type" = yes; then - AC_DEFINE([CHECK_LISP_OBJECT_TYPE], 1, + AC_DEFINE([CHECK_LISP_OBJECT_TYPE], [1], [Define to enable compile-time checks for the Lisp_Object data type.]) fi @@ -1157,7 +1163,7 @@ edit_cflags=" s/^ // " -AC_ARG_ENABLE(link-time-optimization, +AC_ARG_ENABLE([link-time-optimization], [AS_HELP_STRING([--enable-link-time-optimization], [build with link-time optimization (experimental; see INSTALL)])], @@ -1267,7 +1273,7 @@ fi rm -f conf$$ conf$$.file]) LN_S_FILEONLY=$emacs_cv_ln_s_fileonly -AC_SUBST(LN_S_FILEONLY) +AC_SUBST([LN_S_FILEONLY]) dnl AC_PROG_LN_S sets LN_S to 'cp -pR' for MinGW, on the premise that 'ln' @@ -1286,13 +1292,13 @@ dnl if called via an absolute file name. dnl Use the entirely-identical-but-quieter ginstall-info instead if present. dnl Sadly some people may have an old ginstall-info installed on dnl non-Debian systems, so we can't use this. -dnl AC_PATH_PROGS(INSTALL_INFO, [ginstall-info install-info], :, -dnl $PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin) +dnl AC_PATH_PROGS([INSTALL_INFO], [ginstall-info install-info], [:], +dnl [$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin]) -AC_PATH_PROG(INSTALL_INFO, install-info, :, - $PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin) +AC_PATH_PROG([INSTALL_INFO], [install-info], [:], + [$PATH$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/sbin]) dnl Don't use GZIP, which is used by gzip for additional parameters. -AC_PATH_PROG(GZIP_PROG, gzip) +AC_PATH_PROG([GZIP_PROG], [gzip]) test $with_compress_install != yes && test -n "$GZIP_PROG" && \ GZIP_PROG=" # $GZIP_PROG # (disabled by configure --without-compress-install)" @@ -1361,7 +1367,7 @@ AC_SUBST([SETFATTR]) # Makeinfo on macOS is ancient, check whether there is a more recent # version installed by Homebrew. -AC_CHECK_PROGS(BREW, [brew]) +AC_CHECK_PROGS([BREW], [brew]) if test -n "$BREW"; then AC_PATH_PROG([MAKEINFO], [makeinfo], [], [`$BREW --prefix texinfo 2>/dev/null`/bin$PATH_SEPARATOR$PATH]) @@ -1369,7 +1375,7 @@ fi # Check MacPorts on macOS. if test $opsys = darwin; then - AC_PATH_PROG(HAVE_MACPORTS, port) + AC_PATH_PROG([HAVE_MACPORTS], [port]) fi ## Require makeinfo >= 4.13 (last of the 4.x series) to build the manuals. @@ -1409,7 +1415,7 @@ if test $opsys = mingw32; then else DOCMISC_W32= fi -AC_SUBST(DOCMISC_W32) +AC_SUBST([DOCMISC_W32]) dnl Add our options to ac_link now, after it is set up. @@ -1468,7 +1474,7 @@ AC_CACHE_CHECK([whether addresses are sanitized], [emacs_cv_sanitize_address=no])]) if test $with_unexec = yes; then - AC_DEFINE([HAVE_UNEXEC], 1, [Define if Emacs supports unexec.]) + AC_DEFINE([HAVE_UNEXEC], [1], [Define if Emacs supports unexec.]) if test "$emacs_cv_sanitize_address" = yes; then AC_MSG_WARN([[Addresses are sanitized; suggest --without-unexec]]) fi @@ -1505,7 +1511,7 @@ case "$opsys" in UNEXEC_OBJ=unexelf.o ;; esac -AC_SUBST(UNEXEC_OBJ) +AC_SUBST([UNEXEC_OBJ]) LD_SWITCH_SYSTEM= test "$with_unexec" = no || case "$opsys" in @@ -1535,7 +1541,7 @@ test "$with_unexec" = no || case "$opsys" in LD_SWITCH_SYSTEM="-Z" ;; esac -AC_SUBST(LD_SWITCH_SYSTEM) +AC_SUBST([LD_SWITCH_SYSTEM]) ac_link="$ac_link $LD_SWITCH_SYSTEM" @@ -1571,7 +1577,7 @@ case $canonical in fi ;; esac -AC_SUBST(C_SWITCH_MACHINE) +AC_SUBST([C_SWITCH_MACHINE]) C_SWITCH_SYSTEM= ## Some programs in src produce warnings saying certain subprograms @@ -1587,7 +1593,7 @@ if test "$opsys" = "mingw32"; then fi ## gnu-linux might need -D_BSD_SOURCE on old libc5 systems. ## It is redundant in glibc2, since we define _GNU_SOURCE. -AC_SUBST(C_SWITCH_SYSTEM) +AC_SUBST([C_SWITCH_SYSTEM]) LIBS_SYSTEM= @@ -1609,7 +1615,7 @@ case "$opsys" in haiku) LIBS_SYSTEM="-lnetwork" ;; esac -AC_SUBST(LIBS_SYSTEM) +AC_SUBST([LIBS_SYSTEM]) ### Make sure subsequent tests use flags consistent with the build flags. @@ -1717,8 +1723,8 @@ case $opsys in esac -AC_SUBST(LIB_MATH) -AC_DEFINE_UNQUOTED(SYSTEM_TYPE, "$SYSTEM_TYPE", +AC_SUBST([LIB_MATH]) +AC_DEFINE_UNQUOTED([SYSTEM_TYPE], ["$SYSTEM_TYPE"], [The type of system you are compiling for; sets 'system-type'.]) AC_SUBST([SYSTEM_TYPE]) @@ -1726,11 +1732,11 @@ AC_SUBST([SYSTEM_TYPE]) pre_PKG_CONFIG_CFLAGS=$CFLAGS pre_PKG_CONFIG_LIBS=$LIBS -PKG_PROG_PKG_CONFIG(0.9.0) +PKG_PROG_PKG_CONFIG([0.9.0]) -dnl EMACS_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4) -dnl acts like PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, -dnl HAVE_GSTUFF=yes, HAVE_GSTUFF=no) -- see pkg-config man page -- +dnl EMACS_CHECK_MODULES([GSTUFF], [gtk+-2.0 >= 1.3 glib = 1.3.4]) +dnl acts like PKG_CHECK_MODULES([GSTUFF], [gtk+-2.0 >= 1.3 glib = 1.3.4], +dnl [HAVE_GSTUFF=yes], [HAVE_GSTUFF=no]) -- see pkg-config man page -- dnl except that it postprocesses CFLAGS as needed for --enable-gcc-warnings. dnl EMACS_CHECK_MODULES accepts optional 3rd and 4th arguments that dnl can take the place of the default HAVE_GSTUFF=yes and HAVE_GSTUFF=no @@ -1745,7 +1751,7 @@ HAVE_SOUND=no if test "${with_sound}" != "no"; then # Sound support for GNU/Linux, the free BSDs, MinGW, and Cygwin. AC_CHECK_HEADERS([machine/soundcard.h sys/soundcard.h soundcard.h mmsystem.h], - have_sound_header=yes, [], [ + [have_sound_header=yes], [], [ #ifdef __MINGW32__ #define WIN32_LEAN_AND_MEAN #include @@ -1756,13 +1762,13 @@ if test "${with_sound}" != "no"; then if test "${with_sound}" = "bsd-ossaudio" || test "${with_sound}" = "yes"; then # Emulation library used on NetBSD. - AC_CHECK_LIB(ossaudio, _oss_ioctl, LIBSOUND=-lossaudio, LIBSOUND=) + AC_CHECK_LIB([ossaudio], [_oss_ioctl], [LIBSOUND=-lossaudio], [LIBSOUND=]) test "${with_sound}" = "bsd-ossaudio" && test -z "$LIBSOUND" && \ AC_MSG_ERROR([bsd-ossaudio sound support requested but not found.]) dnl FIXME? If we did find ossaudio, should we set with_sound=bsd-ossaudio? dnl Traditionally, we go on to check for alsa too. Does that make sense? fi - AC_SUBST(LIBSOUND) + AC_SUBST([LIBSOUND]) if test "${with_sound}" = "alsa" || test "${with_sound}" = "yes"; then ALSA_REQUIRED=1.0.0 @@ -1771,7 +1777,7 @@ if test "${with_sound}" != "no"; then if test $HAVE_ALSA = yes; then LIBSOUND="$LIBSOUND $ALSA_LIBS" CFLAGS_SOUND="$CFLAGS_SOUND $ALSA_CFLAGS" - AC_DEFINE(HAVE_ALSA, 1, [Define to 1 if ALSA is available.]) + AC_DEFINE([HAVE_ALSA], [1], [Define to 1 if ALSA is available.]) elif test "${with_sound}" = "alsa"; then AC_MSG_ERROR([ALSA sound support requested but not found.]) fi @@ -1787,25 +1793,25 @@ if test "${with_sound}" != "no"; then dnl defined __FreeBSD__ || defined __NetBSD__ || defined __linux__ dnl Adjust the --with-sound help text if you change this. gnu-linux|freebsd|netbsd|mingw32|cygwin) - AC_DEFINE(HAVE_SOUND, 1, [Define to 1 if you have sound support.]) + AC_DEFINE([HAVE_SOUND], [1], [Define to 1 if you have sound support.]) HAVE_SOUND=yes ;; esac fi - AC_SUBST(CFLAGS_SOUND) + AC_SUBST([CFLAGS_SOUND]) fi dnl checks for header files AC_CHECK_HEADERS_ONCE( - linux/fs.h + [linux/fs.h malloc.h sys/systeminfo.h sys/sysinfo.h coff.h pty.h sys/resource.h sys/utsname.h pwd.h utmp.h util.h - sanitizer/lsan_interface.h) + sanitizer/lsan_interface.h]) AC_CACHE_CHECK([for ADDR_NO_RANDOMIZE], [emacs_cv_personality_addr_no_randomize], @@ -1832,10 +1838,11 @@ if test "$ac_cv_header_sys_sysinfo_h" = yes; then emacs_cv_linux_sysinfo=yes, emacs_cv_linux_sysinfo=no)]) if test $emacs_cv_linux_sysinfo = yes; then - AC_DEFINE([HAVE_LINUX_SYSINFO], 1, [Define to 1 if you have Linux sysinfo function.]) + AC_DEFINE([HAVE_LINUX_SYSINFO], [1], + [Define to 1 if you have Linux sysinfo function.]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[struct sysinfo si; return si.mem_unit]])], - AC_DEFINE(LINUX_SYSINFO_UNIT, 1, + AC_DEFINE([LINUX_SYSINFO_UNIT], [1], [Define to 1 if Linux sysinfo sizes are in multiples of mem_unit bytes.])) fi fi @@ -1843,19 +1850,20 @@ fi dnl On Solaris 8 there's a compilation warning for term.h because dnl it doesn't define 'bool'. AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[#include ]],[[]])], - AC_DEFINE(HAVE_TERM_H, 1, [Define to 1 if you have the header file.])) + [AC_DEFINE([HAVE_TERM_H], [1], + [Define to 1 if you have the header file.])]) AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS_ONCE(sys/socket.h) -AC_CHECK_HEADERS(net/if.h, , , [AC_INCLUDES_DEFAULT +AC_CHECK_HEADERS_ONCE([sys/socket.h]) +AC_CHECK_HEADERS([net/if.h], [], [], [AC_INCLUDES_DEFAULT #if HAVE_SYS_SOCKET_H #include #endif]) -AC_CHECK_HEADERS(ifaddrs.h, , , [AC_INCLUDES_DEFAULT +AC_CHECK_HEADERS([ifaddrs.h], [], [], [AC_INCLUDES_DEFAULT #if HAVE_SYS_SOCKET_H #include #endif]) -AC_CHECK_HEADERS(net/if_dl.h, , , [AC_INCLUDES_DEFAULT +AC_CHECK_HEADERS([net/if_dl.h], [], [], [AC_INCLUDES_DEFAULT #if HAVE_SYS_SOCKET_H #include #endif]) @@ -1864,7 +1872,7 @@ dnl checks for structure members AC_CHECK_MEMBERS([struct ifreq.ifr_flags, struct ifreq.ifr_hwaddr, struct ifreq.ifr_netmask, struct ifreq.ifr_broadaddr, struct ifreq.ifr_addr, - struct ifreq.ifr_addr.sa_len], , , + struct ifreq.ifr_addr.sa_len], [], [], [AC_INCLUDES_DEFAULT #if HAVE_SYS_SOCKET_H #include @@ -1894,7 +1902,7 @@ if test "$GCC" = yes && test "$ac_enable_autodepend" = yes; then AUTO_DEPEND=yes fi fi -AC_SUBST(AUTO_DEPEND) +AC_SUBST([AUTO_DEPEND]) #### Choose a window system. @@ -1944,7 +1952,7 @@ ${x_library}/X11/%T/%N%S" fi done fi -AC_SUBST(LD_SWITCH_X_SITE_RPATH) +AC_SUBST([LD_SWITCH_X_SITE_RPATH]) if test "${x_includes}" != NONE && test -n "${x_includes}"; then C_SWITCH_X_SITE=$isystem`AS_ECHO(["$x_includes"]) | sed -e "s/:/ $isystem/g"` @@ -2028,17 +2036,20 @@ if test "${with_ns}" != no; then dnl GNUstep defines BASE_NATIVE_OBJC_EXCEPTIONS to 0 or 1. dnl If they had chosen to either define it or not, we could have dnl just used AC_CHECK_DECL here. - AC_CACHE_CHECK(if GNUstep defines BASE_NATIVE_OBJC_EXCEPTIONS, - emacs_cv_objc_exceptions, -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], + AC_CACHE_CHECK([if GNUstep defines BASE_NATIVE_OBJC_EXCEPTIONS], + [emacs_cv_objc_exceptions], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ]], [[#if defined BASE_NATIVE_OBJC_EXCEPTIONS && BASE_NATIVE_OBJC_EXCEPTIONS > 0 1; #else fail; -#endif]])], emacs_cv_objc_exceptions=yes, emacs_cv_objc_exceptions=no ) ) +#endif]])], + [emacs_cv_objc_exceptions=yes], + [emacs_cv_objc_exceptions=no])]) if test $emacs_cv_objc_exceptions = yes; then dnl _NATIVE_OBJC_EXCEPTIONS is used by the GNUstep headers. - AC_DEFINE(_NATIVE_OBJC_EXCEPTIONS, 1, + AC_DEFINE([_NATIVE_OBJC_EXCEPTIONS], [1], [Define if GNUstep uses ObjC exceptions.]) GNU_OBJC_CFLAGS="$GNU_OBJC_CFLAGS -fobjc-exceptions" fi @@ -2075,8 +2086,8 @@ Either fix this, or re-configure with the option '--without-ns'.])]) #endif #endif ])], - ns_osx_have_106=yes, - ns_osx_have_106=no) + [ns_osx_have_106=yes], + [ns_osx_have_106=no]) AC_MSG_RESULT([$ns_osx_have_106]) if test $ns_osx_have_106 = no; then @@ -2095,12 +2106,13 @@ Mac OS X 12.x or later. [emacs_cv_macosx_12_0=yes])) if test "${with_native_image_api}" = yes; then - AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use native OS APIs for images.]) + AC_DEFINE([HAVE_NATIVE_IMAGE_API], [1], + [Define to use native OS APIs for images.]) NATIVE_IMAGE_API="yes (ns)" fi fi -AC_SUBST(LIBS_GNUSTEP) +AC_SUBST([LIBS_GNUSTEP]) INSTALL_ARCH_INDEP_EXTRA=install-etc ns_self_contained=no @@ -2114,7 +2126,7 @@ if test "${HAVE_NS}" = yes; then window_system=nextstep # set up packaging dirs if test "${EN_NS_SELF_CONTAINED}" = yes; then - AC_DEFINE(NS_SELF_CONTAINED, 1, [Build an NS bundled app]) + AC_DEFINE([NS_SELF_CONTAINED], [1], [Build an NS bundled app]) ns_self_contained=yes prefix=${ns_appresdir} exec_prefix=${ns_appbindir} @@ -2137,10 +2149,10 @@ if test "${HAVE_NS}" = yes; then fi CFLAGS="$tmp_CFLAGS" CPPFLAGS="$tmp_CPPFLAGS" -AC_SUBST(INSTALL_ARCH_INDEP_EXTRA) -AC_SUBST(ns_self_contained) -AC_SUBST(NS_OBJ) -AC_SUBST(NS_OBJC_OBJ) +AC_SUBST([INSTALL_ARCH_INDEP_EXTRA]) +AC_SUBST([ns_self_contained]) +AC_SUBST([NS_OBJ]) +AC_SUBST([NS_OBJC_OBJ]) if test "${HAVE_NS}" = yes; then AC_CACHE_CHECK( @@ -2151,12 +2163,12 @@ if test "${HAVE_NS}" = yes; then [AC_LANG_SOURCE([[@interface Test + (instancetype)test; @end]])], - emacs_cv_objc_instancetype=yes, - emacs_cv_objc_instancetype=no) + [emacs_cv_objc_instancetype=yes], + [emacs_cv_objc_instancetype=no]) AC_LANG_POP([Objective C])]) if test x$emacs_cv_objc_instancetype = xyes ; then - AC_DEFINE(NATIVE_OBJC_INSTANCETYPE, 1, + AC_DEFINE([NATIVE_OBJC_INSTANCETYPE], [1], [Define if ObjC compiler supports instancetype natively.]) fi @@ -2166,8 +2178,8 @@ if test "${HAVE_NS}" = yes; then [AC_LANG_PUSH([Objective C]) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([], [[for (int i = 0;;);]])], - emacs_cv_objc_c99=yes, - emacs_cv_objc_c99=no) + [emacs_cv_objc_c99=yes], + [emacs_cv_objc_c99=no]) AC_LANG_POP([Objective C])]) if test x$emacs_cv_objc_c99 = xno ; then @@ -2189,7 +2201,7 @@ re-configure with the option '--without-be-app'.])]) AC_LANG_POP([C++]) fi -AC_SUBST(HAVE_BE_APP) +AC_SUBST([HAVE_BE_APP]) HAVE_W32=no W32_OBJ= @@ -2237,11 +2249,11 @@ NTLIB= CM_OBJ="cm.o" XARGS_LIMIT= if test "${HAVE_W32}" = "yes"; then - AC_DEFINE(HAVE_NTGUI, 1, [Define to use native MS Windows GUI.]) + AC_DEFINE([HAVE_NTGUI], [1], [Define to use native MS Windows GUI.]) if test "$with_toolkit_scroll_bars" = "no"; then AC_MSG_ERROR([Non-toolkit scroll bars are not implemented for w32 build.]) fi - AC_CHECK_TOOL(WINDRES, [windres], + AC_CHECK_TOOL([WINDRES], [windres], [AC_MSG_ERROR([No resource compiler found.])]) W32_OBJ="w32fns.o w32menu.o w32reg.o w32font.o w32term.o" W32_OBJ="$W32_OBJ w32xfns.o w32select.o w32uniscribe.o w32cygwinx.o" @@ -2254,8 +2266,8 @@ if test "${HAVE_W32}" = "yes"; then comma_version=`echo "${PACKAGE_VERSION}.0.0" | sed -e 's/\./,/g' -e 's/^\([[^,]]*,[[^,]]*,[[^,]]*,[[^,]]*\).*/\1/'` comma_space_version=`echo "$comma_version" | sed 's/,/, /g'` - AC_SUBST(comma_version) - AC_SUBST(comma_space_version) + AC_SUBST([comma_version]) + AC_SUBST([comma_space_version]) AC_CONFIG_FILES([nt/emacs.rc nt/emacsclient.rc]) if test "${opsys}" = "cygwin"; then W32_LIBS="$W32_LIBS -lkernel32 -luser32 -lusp10 -lgdi32" @@ -2268,7 +2280,8 @@ if test "${HAVE_W32}" = "yes"; then dnl FIXME: This should probably be supported for Cygwin/w32 as dnl well, but the Cygwin build needs to link against -lgdiplus if test "${with_native_image_api}" = yes; then - AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use native OS APIs for images.]) + AC_DEFINE([HAVE_NATIVE_IMAGE_API], [1], + [Define to use native OS APIs for images.]) NATIVE_IMAGE_API="yes (w32)" W32_OBJ="$W32_OBJ w32image.o" fi @@ -2292,20 +2305,20 @@ if test "${HAVE_W32}" = "no" && test "${opsys}" = "cygwin"; then W32_OBJ="w32cygwinx.o" fi -AC_SUBST(W32_OBJ) -AC_SUBST(W32_LIBS) -AC_SUBST(EMACSRES) -AC_SUBST(EMACS_MANIFEST) -AC_SUBST(CLIENTRES) -AC_SUBST(CLIENTW) -AC_SUBST(W32_RES_LINK) -AC_SUBST(FIRSTFILE_OBJ) -AC_SUBST(NTDIR) -AC_SUBST(CM_OBJ) -AC_SUBST(LIBS_ECLIENT) -AC_SUBST(LIB_WSOCK32) -AC_SUBST(NTLIB) -AC_SUBST(XARGS_LIMIT) +AC_SUBST([W32_OBJ]) +AC_SUBST([W32_LIBS]) +AC_SUBST([EMACSRES]) +AC_SUBST([EMACS_MANIFEST]) +AC_SUBST([CLIENTRES]) +AC_SUBST([CLIENTW]) +AC_SUBST([W32_RES_LINK]) +AC_SUBST([FIRSTFILE_OBJ]) +AC_SUBST([NTDIR]) +AC_SUBST([CM_OBJ]) +AC_SUBST([LIBS_ECLIENT]) +AC_SUBST([LIB_WSOCK32]) +AC_SUBST([NTLIB]) +AC_SUBST([XARGS_LIMIT]) if test "${HAVE_W32}" = "yes"; then window_system=w32 @@ -2322,7 +2335,7 @@ if test "$opsys" = "haiku"; then fi if test "${HAVE_BE_APP}" = "yes"; then - AC_DEFINE([HAVE_HAIKU], 1, + AC_DEFINE([HAVE_HAIKU], [1], [Define if Emacs will be built with Haiku windowing support]) fi @@ -2334,16 +2347,17 @@ if test "${HAVE_BE_APP}" = "yes"; then HAIKU_LIBS="-lbe -lgame -ltranslation -ltracker" # -lgame is needed for set_mouse_position. if test "${with_native_image_api}" = yes; then - AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use native OS APIs for images.]) + AC_DEFINE([HAVE_NATIVE_IMAGE_API], [1], + [Define to use native OS APIs for images.]) NATIVE_IMAGE_API="yes (haiku)" HAIKU_OBJ="$HAIKU_OBJ haikuimage.o" fi fi -AC_SUBST(HAIKU_LIBS) -AC_SUBST(HAIKU_OBJ) -AC_SUBST(HAIKU_CXX_OBJ) -AC_SUBST(HAIKU_CFLAGS) +AC_SUBST([HAIKU_LIBS]) +AC_SUBST([HAIKU_OBJ]) +AC_SUBST([HAIKU_CXX_OBJ]) +AC_SUBST([HAIKU_CFLAGS]) ## $window_system is now set to the window system we will ## ultimately use. @@ -2390,16 +2404,16 @@ dnl use the toolkit if we have gtk, or X11R5 or newer. with_gtk3=yes USE_X_TOOLKIT=none HAVE_PGTK=yes - AC_DEFINE([HAVE_PGTK], 1, [Define to 1 if you have pure Gtk+-3.]) + AC_DEFINE([HAVE_PGTK], [1], [Define to 1 if you have pure Gtk+-3.]) ;; haiku ) term_header=haikuterm.h ;; esac -AC_SUBST(HAVE_PGTK) +AC_SUBST([HAVE_PGTK]) if test "$window_system" = none && test "X$with_x" != "Xno"; then - AC_CHECK_PROG(HAVE_XSERVER, X, true, false) + AC_CHECK_PROG([HAVE_XSERVER], [X], [true], [false]) if test "$HAVE_XSERVER" = true || test -n "$DISPLAY" || { @@ -2463,7 +2477,7 @@ fi GMALLOC_OBJ= HYBRID_MALLOC= if test "${system_malloc}" = "yes"; then - AC_DEFINE([SYSTEM_MALLOC], 1, + AC_DEFINE([SYSTEM_MALLOC], [1], [Define to 1 to use the system memory allocator, even if it is not Doug Lea style.]) GNU_MALLOC=no @@ -2471,7 +2485,7 @@ if test "${system_malloc}" = "yes"; then (The GNU allocators don't work with this system configuration.)" VMLIMIT_OBJ= elif test "$hybrid_malloc" = yes; then - AC_DEFINE(HYBRID_MALLOC, 1, + AC_DEFINE([HYBRID_MALLOC], [1], [Define to use gmalloc before dumping and the system malloc after.]) HYBRID_MALLOC=1 GNU_MALLOC=no @@ -2491,21 +2505,21 @@ else [emacs_cv_data_start=yes], [emacs_cv_data_start=no])]) if test $emacs_cv_data_start = yes; then - AC_DEFINE([HAVE_DATA_START], 1, + AC_DEFINE([HAVE_DATA_START], [1], [Define to 1 if data_start is the address of the start of the main data segment.]) fi fi AC_SUBST([HYBRID_MALLOC]) -AC_SUBST(GMALLOC_OBJ) -AC_SUBST(VMLIMIT_OBJ) +AC_SUBST([GMALLOC_OBJ]) +AC_SUBST([VMLIMIT_OBJ]) if test "$doug_lea_malloc" = "yes" && test "$hybrid_malloc" != yes; then if test "$GNU_MALLOC" = yes ; then GNU_MALLOC_reason=" (Using Doug Lea's new malloc from the GNU C Library.)" fi - AC_DEFINE(DOUG_LEA_MALLOC, 1, + AC_DEFINE([DOUG_LEA_MALLOC], [1], [Define to 1 if the system memory allocator is Doug Lea style, with malloc hooks and malloc_set_state.]) @@ -2529,18 +2543,19 @@ esac AC_FUNC_MMAP if test $use_mmap_for_buffers = yes; then - AC_DEFINE(USE_MMAP_FOR_BUFFERS, 1, [Define to use mmap to allocate buffer text.]) + AC_DEFINE([USE_MMAP_FOR_BUFFERS], [1], + [Define to use mmap to allocate buffer text.]) REL_ALLOC=no fi LIBS="$LIBS_SYSTEM $LIBS" dnl FIXME replace main with a function we actually want from this library. -AC_CHECK_LIB(Xbsd, main, LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE -lXbsd") +AC_CHECK_LIB([Xbsd], [main], [LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE -lXbsd"]) dnl Check for the POSIX thread library. LIB_PTHREAD= -AC_CHECK_HEADERS_ONCE(pthread.h) +AC_CHECK_HEADERS_ONCE([pthread.h]) if test "$ac_cv_header_pthread_h" && test "$opsys" != "mingw32"; then AC_CACHE_CHECK([for pthread library], [emacs_cv_pthread_lib], @@ -2575,7 +2590,7 @@ if test "$ac_cv_header_pthread_h" && test "$opsys" != "mingw32"; then fi done]) if test "$emacs_cv_pthread_lib" != no; then - AC_DEFINE([HAVE_PTHREAD], 1, [Define to 1 if you have POSIX threads.]) + AC_DEFINE([HAVE_PTHREAD], [1], [Define to 1 if you have POSIX threads.]) case $emacs_cv_pthread_lib in -*) LIB_PTHREAD=$emacs_cv_pthread_lib;; esac @@ -2585,10 +2600,10 @@ if test "$ac_cv_header_pthread_h" && test "$opsys" != "mingw32"; then # definition of 'errno' in . case $opsys in hpux* | solaris) - AC_DEFINE([_REENTRANT], 1, + AC_DEFINE([_REENTRANT], [1], [Define to 1 if your system requires this in multithreaded code.]);; aix4-2) - AC_DEFINE([_THREAD_SAFE], 1, + AC_DEFINE([_THREAD_SAFE], [1], [Define to 1 if your system requires this in multithreaded code.]);; esac fi @@ -2599,12 +2614,12 @@ AC_MSG_CHECKING([for thread support]) threads_enabled=no if test "$with_threads" = yes; then if test "$emacs_cv_pthread_lib" != no; then - AC_DEFINE(THREADS_ENABLED, 1, + AC_DEFINE([THREADS_ENABLED], [1], [Define to 1 if you want elisp thread support.]) threads_enabled=yes elif test "${opsys}" = "mingw32"; then dnl MinGW can do native Windows threads even without pthreads - AC_DEFINE(THREADS_ENABLED, 1, + AC_DEFINE([THREADS_ENABLED], [1], [Define to 1 if you want elisp thread support.]) threads_enabled=yes fi @@ -2689,40 +2704,42 @@ if test "${HAVE_X11}" = "yes"; then [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[XkbDescPtr kb = XkbGetKeyboard (0, XkbAllComponentsMask, XkbUseCoreKbd);]])], - emacs_cv_xkb=yes, emacs_cv_xkb=no)]) + [emacs_cv_xkb=yes], + [emacs_cv_xkb=no])]) if test $emacs_cv_xkb = yes; then - AC_DEFINE(HAVE_XKB, 1, [Define to 1 if you have the Xkb extension.]) - AC_CHECK_FUNCS(XkbRefreshKeyboardMapping XkbFreeNames) + AC_DEFINE([HAVE_XKB], [1], [Define to 1 if you have the Xkb extension.]) + AC_CHECK_FUNCS([XkbRefreshKeyboardMapping XkbFreeNames]) fi - AC_CHECK_FUNCS(XrmSetDatabase XScreenResourceString XScreenNumberOfScreen) - AC_CHECK_FUNCS(XDisplayCells XDestroySubwindows) + AC_CHECK_FUNCS([XrmSetDatabase XScreenResourceString XScreenNumberOfScreen]) + AC_CHECK_FUNCS([XDisplayCells XDestroySubwindows]) fi if test "${window_system}" = "x11"; then - AC_MSG_CHECKING(X11 version 6) - AC_CACHE_VAL(emacs_cv_x11_version_6, + AC_MSG_CHECKING([X11 version 6]) + AC_CACHE_VAL([emacs_cv_x11_version_6], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[#if XlibSpecificationRelease < 6 fail; #endif -]])], emacs_cv_x11_version_6=yes, emacs_cv_x11_version_6=no)]) +]])], [emacs_cv_x11_version_6=yes], + [emacs_cv_x11_version_6=no])]) if test $emacs_cv_x11_version_6 = yes; then - AC_MSG_RESULT(6 or newer) - AC_DEFINE(HAVE_X11R6, 1, + AC_MSG_RESULT([6 or newer]) + AC_DEFINE([HAVE_X11R6], [1], [Define to 1 if you have the X11R6 or newer version of Xlib.]) - AC_DEFINE(HAVE_X_I18N, 1, [Define if you have usable i18n support.]) + AC_DEFINE([HAVE_X_I18N], [1], [Define if you have usable i18n support.]) AC_CHECK_MEMBERS([XICCallback.callback], [], [], [#include ]) ## inoue@ainet.or.jp says Solaris has a bug related to X11R6-style ## XIM support. case "$opsys" in solaris) : ;; - *) AC_DEFINE(HAVE_X11R6_XIM, 1, + *) AC_DEFINE([HAVE_X11R6_XIM], [1], [Define if you have usable X11R6-style XIM support.]) ;; esac else - AC_MSG_RESULT(before 6) + AC_MSG_RESULT([before 6]) fi fi @@ -2737,11 +2754,11 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" \ RSVG_MODULE="librsvg-2.0 >= $RSVG_REQUIRED" EMACS_CHECK_MODULES([RSVG], [$RSVG_MODULE]) - AC_SUBST(RSVG_CFLAGS) - AC_SUBST(RSVG_LIBS) + AC_SUBST([RSVG_CFLAGS]) + AC_SUBST([RSVG_LIBS]) if test $HAVE_RSVG = yes; then - AC_DEFINE(HAVE_RSVG, 1, [Define to 1 if using librsvg.]) + AC_DEFINE([HAVE_RSVG], [1], [Define to 1 if using librsvg.]) CFLAGS="$CFLAGS $RSVG_CFLAGS" # Windows loads librsvg dynamically if test "${opsys}" = "mingw32"; then @@ -2764,11 +2781,11 @@ if test "${with_webp}" != "no"; then if test "$HAVE_WEBP" = "yes"; then WEBP_LIBS="-lwebp -lwebpdemux" fi - AC_SUBST(WEBP_CFLAGS) - AC_SUBST(WEBP_LIBS) + AC_SUBST([WEBP_CFLAGS]) + AC_SUBST([WEBP_LIBS]) fi if test $HAVE_WEBP = yes; then - AC_DEFINE(HAVE_WEBP, 1, [Define to 1 if using libwebp.]) + AC_DEFINE([HAVE_WEBP], [1], [Define to 1 if using libwebp.]) CFLAGS="$CFLAGS $WEBP_CFLAGS" # Windows loads libwebp dynamically if test "${opsys}" = "mingw32"; then @@ -2780,20 +2797,25 @@ fi ### Use -lsqlite3 if available, unless '--with-sqlite3=no' HAVE_SQLITE3=no if test "${with_sqlite3}" != "no"; then - AC_CHECK_LIB(sqlite3, sqlite3_open_v2, HAVE_SQLITE3=yes, HAVE_SQLITE3=no) + AC_CHECK_LIB([sqlite3], [sqlite3_open_v2], + [HAVE_SQLITE3=yes], + [HAVE_SQLITE3=no]) if test "$HAVE_SQLITE3" = "yes"; then SQLITE3_LIBS=-lsqlite3 - AC_SUBST(SQLITE3_LIBS) + AC_SUBST([SQLITE3_LIBS]) LIBS="$SQLITE3_LIBS $LIBS" - AC_DEFINE(HAVE_SQLITE3, 1, [Define to 1 if you have the libsqlite3 library (-lsqlite).]) + AC_DEFINE([HAVE_SQLITE3], [1], + [Define to 1 if you have the libsqlite3 library (-lsqlite).]) # Windows loads libsqlite dynamically if test "${opsys}" = "mingw32"; then SQLITE3_LIBS= fi - AC_CHECK_LIB(sqlite3, sqlite3_load_extension, - HAVE_SQLITE3_LOAD_EXTENSION=yes, HAVE_SQLITE3_LOAD_EXTENSION=no) + AC_CHECK_LIB([sqlite3], [sqlite3_load_extension], + [HAVE_SQLITE3_LOAD_EXTENSION=yes], + [HAVE_SQLITE3_LOAD_EXTENSION=no]) if test "$HAVE_SQLITE3_LOAD_EXTENSION" = "yes"; then - AC_DEFINE(HAVE_SQLITE3_LOAD_EXTENSION, 1, [Define to 1 if sqlite3 supports loading extensions.]) + AC_DEFINE([HAVE_SQLITE3_LOAD_EXTENSION], [1], + [Define to 1 if sqlite3 supports loading extensions.]) fi fi fi @@ -2810,7 +2832,8 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" EMACS_CHECK_MODULES([IMAGEMAGICK], [MagickWand >= 7]) if test $HAVE_IMAGEMAGICK = yes; then - AC_DEFINE([HAVE_IMAGEMAGICK7], 1, [Define to 1 if using ImageMagick7.]) + AC_DEFINE([HAVE_IMAGEMAGICK7], [1], + [Define to 1 if using ImageMagick7.]) else ## 6.3.5 is the earliest version known to work; see Bug#17339. ## 6.8.2 makes Emacs crash; see Bug#13867. @@ -2834,7 +2857,7 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" fi fi if test $HAVE_IMAGEMAGICK = yes; then - AC_DEFINE([HAVE_IMAGEMAGICK], 1, [Define to 1 if using ImageMagick.]) + AC_DEFINE([HAVE_IMAGEMAGICK], [1], [Define to 1 if using ImageMagick.]) else if test "${with_imagemagick}" != "no"; then AC_MSG_ERROR([ImageMagick wanted, but it does not compile. Maybe some library files are missing?]); @@ -2847,12 +2870,12 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" fi fi -AC_CHECK_LIB(anl, getaddrinfo_a, HAVE_GETADDRINFO_A=yes) +AC_CHECK_LIB([anl], [getaddrinfo_a], [HAVE_GETADDRINFO_A=yes]) if test "${HAVE_GETADDRINFO_A}" = "yes"; then - AC_DEFINE(HAVE_GETADDRINFO_A, 1, + AC_DEFINE([HAVE_GETADDRINFO_A], [1], [Define to 1 if you have getaddrinfo_a for asynchronous DNS resolution.]) GETADDRINFO_A_LIBS="-lanl" - AC_SUBST(GETADDRINFO_A_LIBS) + AC_SUBST([GETADDRINFO_A_LIBS]) fi HAVE_GTK=no @@ -2874,10 +2897,10 @@ if test "${opsys}" != "mingw32"; then EMACS_CHECK_MODULES([GTK], [$GTK_MODULES], [pkg_check_gtk=yes], [pkg_check_gtk=no]) if test "$pkg_check_gtk" = "no" && test "$with_gtk3" = "yes"; then - AC_MSG_ERROR($GTK_PKG_ERRORS) + AC_MSG_ERROR([$GTK_PKG_ERRORS]) fi if test "$pkg_check_gtk" = "yes"; then - AC_DEFINE(HAVE_GTK3, 1, [Define to 1 if using GTK 3 or later.]) + AC_DEFINE([HAVE_GTK3], [1], [Define to 1 if using GTK 3 or later.]) GTK_OBJ=emacsgtkfixed.o gtk_term_header=gtkutil.h USE_GTK_TOOLKIT="GTK3" @@ -2904,7 +2927,7 @@ if test "${opsys}" != "mingw32"; then if test "$pkg_check_gtk" = "no" && { test "$with_gtk" = yes || test "$with_gtk2" = "yes"; } then - AC_MSG_ERROR($gtk3_pkg_errors$GTK_PKG_ERRORS) + AC_MSG_ERROR([$gtk3_pkg_errors$GTK_PKG_ERRORS]) fi test "$pkg_check_gtk" = "yes" && USE_GTK_TOOLKIT="GTK2" fi @@ -2915,7 +2938,7 @@ OLD_LIBS=$LIBS if test x"$pkg_check_gtk" = xyes; then - AC_SUBST(GTK_LIBS) + AC_SUBST([GTK_LIBS]) CFLAGS="$CFLAGS $GTK_CFLAGS" LIBS="$GTK_LIBS $LIBS" dnl Try to compile a simple GTK program. @@ -2947,7 +2970,7 @@ if test x"$pkg_check_gtk" = xyes; then else C_SWITCH_X_SITE="$C_SWITCH_X_SITE $GTK_CFLAGS" HAVE_GTK=yes - AC_DEFINE(USE_GTK, 1, [Define to 1 if using GTK.]) + AC_DEFINE([USE_GTK], [1], [Define to 1 if using GTK.]) GTK_OBJ="gtkutil.o $GTK_OBJ" term_header=$gtk_term_header USE_X_TOOLKIT=none @@ -2959,7 +2982,7 @@ if test x"$pkg_check_gtk" = xyes; then fi fi -AC_SUBST(GTK_OBJ) +AC_SUBST([GTK_OBJ]) if test "${HAVE_GTK}" = "yes"; then @@ -2979,15 +3002,17 @@ if test "${HAVE_GTK}" = "yes"; then dnl but not declared if deprecated featured has been selected out. dnl AC_CHECK_DECL checks for a macro, so check for GTK_TYPE_FILE_SELECTION. HAVE_GTK_FILE_SELECTION=no - AC_CHECK_DECL(GTK_TYPE_FILE_SELECTION, HAVE_GTK_FILE_SELECTION=yes, - HAVE_GTK_FILE_SELECTION=no, [AC_INCLUDES_DEFAULT + AC_CHECK_DECL([GTK_TYPE_FILE_SELECTION], + [HAVE_GTK_FILE_SELECTION=yes], + [HAVE_GTK_FILE_SELECTION=no], + [AC_INCLUDES_DEFAULT #include ]) if test "$HAVE_GTK_FILE_SELECTION" = yes; then - AC_CHECK_FUNCS(gtk_file_selection_new) + AC_CHECK_FUNCS([gtk_file_selection_new]) fi dnl This procedure causes a bug on certain Ubuntu GTK+2 builds - AC_CHECK_FUNCS(gtk_window_set_has_resize_grip) + AC_CHECK_FUNCS([gtk_window_set_has_resize_grip]) fi fi @@ -3000,10 +3025,10 @@ if test "$window_system" = "pgtk"; then PGTK_OBJ="pgtkfns.o pgtkterm.o pgtkselect.o pgtkmenu.o pgtkim.o xsettings.o" PGTK_LIBS="$GTK_LIBS" fi -AC_SUBST(PGTK_OBJ) -AC_SUBST(PGTK_LIBS) +AC_SUBST([PGTK_OBJ]) +AC_SUBST([PGTK_LIBS]) -AC_CHECK_FUNCS(malloc_trim) +AC_CHECK_FUNCS([malloc_trim]) dnl D-Bus has been tested under GNU/Linux only. Must be adapted for dnl other platforms. @@ -3012,25 +3037,25 @@ DBUS_OBJ= if test "${with_dbus}" = "yes"; then EMACS_CHECK_MODULES([DBUS], [dbus-1 >= 1.0]) if test "$HAVE_DBUS" = yes; then - AC_DEFINE(HAVE_DBUS, 1, [Define to 1 if using D-Bus.]) + AC_DEFINE([HAVE_DBUS], [1], [Define to 1 if using D-Bus.]) dnl dbus_watch_get_unix_fd has been introduced in D-Bus 1.1.1. dnl dbus_type_is_valid and dbus_validate_* have been introduced in dnl D-Bus 1.5.12. OLD_LIBS=$LIBS LIBS="$LIBS $DBUS_LIBS" - AC_CHECK_FUNCS(dbus_watch_get_unix_fd \ + AC_CHECK_FUNCS([dbus_watch_get_unix_fd \ dbus_type_is_valid \ dbus_validate_bus_name \ dbus_validate_path \ dbus_validate_interface \ - dbus_validate_member) + dbus_validate_member]) LIBS=$OLD_LIBS DBUS_OBJ=dbusbind.o fi fi -AC_SUBST(DBUS_CFLAGS) -AC_SUBST(DBUS_LIBS) -AC_SUBST(DBUS_OBJ) +AC_SUBST([DBUS_CFLAGS]) +AC_SUBST([DBUS_LIBS]) +AC_SUBST([DBUS_OBJ]) dnl GSettings has been tested under GNU/Linux only. HAVE_GSETTINGS=no @@ -3055,7 +3080,7 @@ if test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gse [emacs_cv_gsettings_in_gio=yes], [emacs_cv_gsettings_in_gio=no])]) if test "$emacs_cv_gsettings_in_gio" = "yes"; then - AC_DEFINE(HAVE_GSETTINGS, 1, [Define to 1 if using GSettings.]) + AC_DEFINE([HAVE_GSETTINGS], [1], [Define to 1 if using GSettings.]) SETTINGS_CFLAGS="$GSETTINGS_CFLAGS" SETTINGS_LIBS="$GSETTINGS_LIBS" test "$with_gconf" = "yes" || with_gconf=no @@ -3064,7 +3089,7 @@ if test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gse LIBS=$old_LIBS fi fi -AC_SUBST(HAVE_GSETTINGS) +AC_SUBST([HAVE_GSETTINGS]) dnl GConf has been tested under GNU/Linux only. dnl The version is really arbitrary, it is about the same age as Gtk+ 2.6. @@ -3072,7 +3097,7 @@ HAVE_GCONF=no if test "${HAVE_X11}" = "yes" -o "${window_system}" = "pgtk" && test "${with_gconf}" != "no"; then EMACS_CHECK_MODULES([GCONF], [gconf-2.0 >= 2.13]) if test "$HAVE_GCONF" = yes; then - AC_DEFINE(HAVE_GCONF, 1, [Define to 1 if using GConf.]) + AC_DEFINE([HAVE_GCONF], [1], [Define to 1 if using GConf.]) dnl Newer GConf doesn't link with g_objects, so this is not defined. SETTINGS_CFLAGS="$SETTINGS_CFLAGS $GCONF_CFLAGS" SETTINGS_LIBS="$SETTINGS_LIBS $GCONF_LIBS" @@ -3092,33 +3117,35 @@ if test "$HAVE_GSETTINGS" = "yes" || test "$HAVE_GCONF" = "yes"; then CFLAGS="$SAVE_CFLAGS" LIBS="$SAVE_LIBS" fi -AC_SUBST(SETTINGS_CFLAGS) -AC_SUBST(SETTINGS_LIBS) +AC_SUBST([SETTINGS_CFLAGS]) +AC_SUBST([SETTINGS_LIBS]) USE_STARTUP_NOTIFICATION=no if test "${HAVE_GTK}" = "yes"; then USE_STARTUP_NOTIFICATION=yes fi -AC_SUBST(USE_STARTUP_NOTIFICATION) +AC_SUBST([USE_STARTUP_NOTIFICATION]) dnl SELinux is available for GNU/Linux only. HAVE_LIBSELINUX=no LIBSELINUX_LIBS= if test "${with_selinux}" = "yes"; then - AC_CHECK_LIB([selinux], [lgetfilecon], HAVE_LIBSELINUX=yes, HAVE_LIBSELINUX=no) + AC_CHECK_LIB([selinux], [lgetfilecon], + [HAVE_LIBSELINUX=yes], + [HAVE_LIBSELINUX=no]) if test "$HAVE_LIBSELINUX" = yes; then - AC_DEFINE(HAVE_LIBSELINUX, 1, [Define to 1 if using SELinux.]) + AC_DEFINE([HAVE_LIBSELINUX], [1], [Define to 1 if using SELinux.]) LIBSELINUX_LIBS=-lselinux fi fi -AC_SUBST(LIBSELINUX_LIBS) +AC_SUBST([LIBSELINUX_LIBS]) HAVE_GNUTLS=no if test "${with_gnutls}" != "no" ; then EMACS_CHECK_MODULES([LIBGNUTLS], [gnutls >= 2.12.2], [HAVE_GNUTLS=yes], [HAVE_GNUTLS=no]) if test "${HAVE_GNUTLS}" = "yes"; then - AC_DEFINE(HAVE_GNUTLS, 1, [Define if using GnuTLS.]) + AC_DEFINE([HAVE_GNUTLS], [1], [Define if using GnuTLS.]) fi # Windows loads GnuTLS dynamically @@ -3127,8 +3154,8 @@ if test "${with_gnutls}" != "no" ; then fi fi -AC_SUBST(LIBGNUTLS_LIBS) -AC_SUBST(LIBGNUTLS_CFLAGS) +AC_SUBST([LIBGNUTLS_LIBS]) +AC_SUBST([LIBGNUTLS_CFLAGS]) HAVE_LIBSYSTEMD=no if test "${with_libsystemd}" = "yes" ; then @@ -3138,12 +3165,12 @@ if test "${with_libsystemd}" = "yes" ; then EMACS_CHECK_MODULES([LIBSYSTEMD], [libsystemd >= 222], [HAVE_LIBSYSTEMD=yes], [HAVE_LIBSYSTEMD=no]) if test "${HAVE_LIBSYSTEMD}" = "yes"; then - AC_DEFINE(HAVE_LIBSYSTEMD, 1, [Define if using libsystemd.]) + AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Define if using libsystemd.]) fi fi -AC_SUBST(LIBSYSTEMD_LIBS) -AC_SUBST(LIBSYSTEMD_CFLAGS) +AC_SUBST([LIBSYSTEMD_LIBS]) +AC_SUBST([LIBSYSTEMD_CFLAGS]) HAVE_JSON=no JSON_OBJ= @@ -3152,7 +3179,7 @@ if test "${with_json}" != no; then EMACS_CHECK_MODULES([JSON], [jansson >= 2.7], [HAVE_JSON=yes], [HAVE_JSON=no]) if test "${HAVE_JSON}" = yes; then - AC_DEFINE(HAVE_JSON, 1, [Define if using Jansson.]) + AC_DEFINE([HAVE_JSON], [1], [Define if using Jansson.]) JSON_OBJ=json.o fi @@ -3162,9 +3189,9 @@ if test "${with_json}" != no; then fi fi -AC_SUBST(JSON_LIBS) -AC_SUBST(JSON_CFLAGS) -AC_SUBST(JSON_OBJ) +AC_SUBST([JSON_LIBS]) +AC_SUBST([JSON_CFLAGS]) +AC_SUBST([JSON_OBJ]) NOTIFY_OBJ= NOTIFY_SUMMARY=no @@ -3177,9 +3204,9 @@ case $with_file_notification,$opsys in Consider using gfile instead.]) ;; w32,* | yes,mingw32) - AC_CHECK_HEADER(windows.h) + AC_CHECK_HEADER([windows.h]) if test "$ac_cv_header_windows_h" = yes ; then - AC_DEFINE(HAVE_W32NOTIFY, 1, [Define to 1 to use w32notify.]) + AC_DEFINE([HAVE_W32NOTIFY], [1], [Define to 1 to use w32notify.]) NOTIFY_OBJ=w32notify.o NOTIFY_SUMMARY="yes (w32)" fi ;; @@ -3188,11 +3215,11 @@ esac dnl inotify is available only on GNU/Linux. case $with_file_notification,$NOTIFY_OBJ in inotify, | yes,) - AC_CHECK_HEADER(sys/inotify.h) + AC_CHECK_HEADER([sys/inotify.h]) if test "$ac_cv_header_sys_inotify_h" = yes ; then - AC_CHECK_FUNC(inotify_init1) + AC_CHECK_FUNC([inotify_init1]) if test "$ac_cv_func_inotify_init1" = yes; then - AC_DEFINE(HAVE_INOTIFY, 1, [Define to 1 to use inotify.]) + AC_DEFINE([HAVE_INOTIFY], [1], [Define to 1 to use inotify.]) NOTIFY_OBJ=inotify.o NOTIFY_SUMMARY="yes -lglibc (inotify)" fi @@ -3204,16 +3231,16 @@ case $with_file_notification,$NOTIFY_OBJ in kqueue,* | yes,) EMACS_CHECK_MODULES([KQUEUE], [libkqueue]) if test "$HAVE_KQUEUE" = "yes"; then - AC_DEFINE(HAVE_KQUEUE, 1, [Define to 1 to use kqueue.]) + AC_DEFINE([HAVE_KQUEUE], [1], [Define to 1 to use kqueue.]) CPPFLAGS="$CPPFLAGS -I/usr/include/kqueue" NOTIFY_CFLAGS=$KQUEUE_CFLAGS NOTIFY_LIBS=$KQUEUE_LIBS NOTIFY_OBJ=kqueue.o NOTIFY_SUMMARY="yes -lkqueue" else - AC_SEARCH_LIBS(kqueue, []) + AC_SEARCH_LIBS([kqueue], []) if test "$ac_cv_search_kqueue" != no; then - AC_DEFINE(HAVE_KQUEUE, 1, [Define to 1 to use kqueue.]) + AC_DEFINE([HAVE_KQUEUE], [1], [Define to 1 to use kqueue.]) NOTIFY_OBJ=kqueue.o NOTIFY_SUMMARY="yes (kqueue)" fi @@ -3231,7 +3258,7 @@ Consider kqueue instead.]) else EMACS_CHECK_MODULES([GFILENOTIFY], [gio-2.0 >= 2.24]) if test "$HAVE_GFILENOTIFY" = "yes"; then - AC_DEFINE(HAVE_GFILENOTIFY, 1, [Define to 1 if using GFile.]) + AC_DEFINE([HAVE_GFILENOTIFY], [1], [Define to 1 if using GFile.]) NOTIFY_CFLAGS=$GFILENOTIFY_CFLAGS NOTIFY_LIBS=$GFILENOTIFY_LIBS NOTIFY_OBJ=gfilenotify.o @@ -3246,11 +3273,12 @@ case $with_file_notification,$NOTIFY_OBJ in esac if test -n "$NOTIFY_OBJ"; then - AC_DEFINE(USE_FILE_NOTIFY, 1, [Define to 1 if using file notifications.]) + AC_DEFINE([USE_FILE_NOTIFY], [1], + [Define to 1 if using file notifications.]) fi -AC_SUBST(NOTIFY_CFLAGS) -AC_SUBST(NOTIFY_LIBS) -AC_SUBST(NOTIFY_OBJ) +AC_SUBST([NOTIFY_CFLAGS]) +AC_SUBST([NOTIFY_LIBS]) +AC_SUBST([NOTIFY_OBJ]) dnl Do not put whitespace before the #include statements below. dnl Older compilers (eg sunos4 cc) choke on it. @@ -3258,36 +3286,37 @@ HAVE_XAW3D=no LUCID_LIBW= if test x"${USE_X_TOOLKIT}" = xmaybe || test x"${USE_X_TOOLKIT}" = xLUCID; then if test "$with_xaw3d" != no; then - AC_CACHE_VAL(emacs_cv_xaw3d, + AC_CACHE_VAL([emacs_cv_xaw3d], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[]])], - [AC_CHECK_LIB(Xaw3d, XawScrollbarSetThumb, - emacs_cv_xaw3d=yes, emacs_cv_xaw3d=no)], - emacs_cv_xaw3d=no)]) + [AC_CHECK_LIB([Xaw3d], [XawScrollbarSetThumb], + [emacs_cv_xaw3d=yes], + [emacs_cv_xaw3d=no])], + [emacs_cv_xaw3d=no])]) else emacs_cv_xaw3d=no fi if test $emacs_cv_xaw3d = yes; then - AC_MSG_CHECKING(for xaw3d) + AC_MSG_CHECKING([for xaw3d]) AC_MSG_RESULT([yes; using Lucid toolkit]) USE_X_TOOLKIT=LUCID HAVE_XAW3D=yes LUCID_LIBW=-lXaw3d - AC_DEFINE(HAVE_XAW3D, 1, + AC_DEFINE([HAVE_XAW3D], [1], [Define to 1 if you have the Xaw3d library (-lXaw3d).]) else - AC_MSG_CHECKING(for xaw3d) - AC_MSG_RESULT(no) - AC_MSG_CHECKING(for libXaw) - AC_CACHE_VAL(emacs_cv_xaw, + AC_MSG_CHECKING([for xaw3d]) + AC_MSG_RESULT([no]) + AC_MSG_CHECKING([for libXaw]) + AC_CACHE_VAL([emacs_cv_xaw], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include #include ]], [[]])], - emacs_cv_xaw=yes, - emacs_cv_xaw=no)]) + [emacs_cv_xaw=yes], + [emacs_cv_xaw=no])]) if test $emacs_cv_xaw = yes; then AC_MSG_RESULT([yes; using Lucid toolkit]) USE_X_TOOLKIT=LUCID @@ -3309,17 +3338,18 @@ X_TOOLKIT_TYPE=$USE_X_TOOLKIT LIBXTR6= LIBXMU= if test "${USE_X_TOOLKIT}" != "none"; then - AC_MSG_CHECKING(X11 toolkit version) - AC_CACHE_VAL(emacs_cv_x11_toolkit_version_6, + AC_MSG_CHECKING([X11 toolkit version]) + AC_CACHE_VAL([emacs_cv_x11_toolkit_version_6], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[#if XtSpecificationRelease < 6 fail; #endif -]])], emacs_cv_x11_toolkit_version_6=yes, emacs_cv_x11_toolkit_version_6=no)]) +]])], [emacs_cv_x11_toolkit_version_6=yes], + [emacs_cv_x11_toolkit_version_6=no])]) HAVE_X11XTR6=$emacs_cv_x11_toolkit_version_6 if test $emacs_cv_x11_toolkit_version_6 = yes; then - AC_MSG_RESULT(6 or newer) - AC_DEFINE(HAVE_X11XTR6, 1, + AC_MSG_RESULT([6 or newer]) + AC_DEFINE([HAVE_X11XTR6], [1], [Define to 1 if you have the X11R6 or newer version of Xt.]) LIBXTR6="-lSM -lICE" case "$opsys" in @@ -3327,7 +3357,7 @@ fail; unixware) LIBXTR6="$LIBXTR6 -lw" ;; esac else - AC_MSG_RESULT(before 6) + AC_MSG_RESULT([before 6]) fi dnl If using toolkit, check whether libXmu.a exists. @@ -3345,8 +3375,8 @@ dnl tranle@intellicorp.com says libXmu.a can need XtMalloc in libXt.a to link. LIBS=$OLDLIBS dnl ac_cv_search_XmuConvertStandardSelection is also referenced below. fi -AC_SUBST(LIBXTR6) -AC_SUBST(LIBXMU) +AC_SUBST([LIBXTR6]) +AC_SUBST([LIBXMU]) LIBXP= if test "${USE_X_TOOLKIT}" = "MOTIF"; then @@ -3364,16 +3394,17 @@ if test "${USE_X_TOOLKIT}" = "MOTIF"; then else emacs_cv_openmotif=no fi - AC_CACHE_CHECK(for (Open)Motif version 2.1, emacs_cv_motif_version_2_1, + AC_CACHE_CHECK([for (Open)Motif version 2.1], [emacs_cv_motif_version_2_1], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[#if XmVERSION > 2 || (XmVERSION == 2 && XmREVISION >= 1) int x = 5; #else Motif version prior to 2.1. #endif]])], - emacs_cv_motif_version_2_1=yes, emacs_cv_motif_version_2_1=no)]) + [emacs_cv_motif_version_2_1=yes], + [emacs_cv_motif_version_2_1=no])]) if test $emacs_cv_motif_version_2_1 = yes; then - AC_CHECK_LIB(Xp, XpCreateContext, LIBXP=-lXp) + AC_CHECK_LIB([Xp], [XpCreateContext], [LIBXP=-lXp]) if test x$emacs_cv_openmotif = xyes; then REAL_CPPFLAGS="-I/usr/include/openmotif $REAL_CPPFLAGS" fi @@ -3385,10 +3416,14 @@ Motif version prior to 2.1. OLD_CFLAGS=$CFLAGS CPPFLAGS="-I/usr/X11R6/LessTif/Motif1.2/include $CPPFLAGS" CFLAGS="-I/usr/X11R6/LessTif/Motif1.2/include $CFLAGS" - AC_CACHE_CHECK(for LessTif where some systems put it, emacs_cv_lesstif, - [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int x = 5;]])], - emacs_cv_lesstif=yes, emacs_cv_lesstif=no)]) + AC_CACHE_CHECK([for LessTif where some systems put it], [emacs_cv_lesstif], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + ]], + [[int x = 5;]])], + [emacs_cv_lesstif=yes], + [emacs_cv_lesstif=no])]) if test $emacs_cv_lesstif = yes; then # Make sure this -I option remains in CPPFLAGS after it is set # back to REAL_CPPFLAGS. @@ -3410,34 +3445,34 @@ dnl Use toolkit scroll bars if configured for GTK or X toolkit and either dnl using Motif or Xaw3d is available, and unless dnl --with-toolkit-scroll-bars=no was specified. -AH_TEMPLATE(USE_TOOLKIT_SCROLL_BARS, +AH_TEMPLATE([USE_TOOLKIT_SCROLL_BARS], [Define to 1 if we should use toolkit scroll bars.])dnl USE_TOOLKIT_SCROLL_BARS=no if test "${with_toolkit_scroll_bars}" != "no"; then if test "${USE_X_TOOLKIT}" != "none"; then if test "${USE_X_TOOLKIT}" = "MOTIF"; then - AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) + AC_DEFINE([USE_TOOLKIT_SCROLL_BARS]) HAVE_XAW3D=no USE_TOOLKIT_SCROLL_BARS=yes elif test "${HAVE_XAW3D}" = "yes" || test "${USE_X_TOOLKIT}" = "LUCID"; then - AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) + AC_DEFINE([USE_TOOLKIT_SCROLL_BARS]) USE_TOOLKIT_SCROLL_BARS=yes fi elif test "${HAVE_GTK}" = "yes"; then - AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) + AC_DEFINE([USE_TOOLKIT_SCROLL_BARS]) USE_TOOLKIT_SCROLL_BARS=yes elif test "${HAVE_NS}" = "yes"; then - AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) + AC_DEFINE([USE_TOOLKIT_SCROLL_BARS]) USE_TOOLKIT_SCROLL_BARS=yes elif test "${HAVE_W32}" = "yes"; then - AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) + AC_DEFINE([USE_TOOLKIT_SCROLL_BARS]) USE_TOOLKIT_SCROLL_BARS=yes elif test "${HAVE_BE_APP}" = "yes"; then - AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) + AC_DEFINE([USE_TOOLKIT_SCROLL_BARS]) USE_TOOLKIT_SCROLL_BARS=yes fi elif test "${window_system}" != "x11" && test "${window_system}" != "none"; then - AC_MSG_ERROR(Non-toolkit scroll bars are not implemented for your system) + AC_MSG_ERROR([Non-toolkit scroll bars are not implemented for your system]) fi dnl See if XIM is available. @@ -3446,14 +3481,14 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include ]], [[XIMProc callback;]])], [HAVE_XIM=yes - AC_DEFINE(HAVE_XIM, 1, [Define to 1 if XIM is available])], - HAVE_XIM=no) + AC_DEFINE([HAVE_XIM], [1], [Define to 1 if XIM is available])], + [HAVE_XIM=no]) dnl Note this is non-standard. --with-xim does not control whether dnl XIM support is compiled in, it only affects the runtime default of dnl use_xim in xterm.c. if test "${with_xim}" != "no"; then - AC_DEFINE(USE_XIM, 1, + AC_DEFINE([USE_XIM], [1], [Define to 1 to default runtime use of XIM to on.]) fi @@ -3469,8 +3504,8 @@ if test "${HAVE_X11}" = "yes"; then [AC_CHECK_LIB([Xrender], [XRenderQueryExtension], [HAVE_XRENDER=yes])]) if test $HAVE_XRENDER = yes; then XRENDER_LIBS="-lXrender" - AC_SUBST(XRENDER_LIBS) - AC_DEFINE([HAVE_XRENDER], 1, [Define to 1 if XRender is available.]) + AC_SUBST([XRENDER_LIBS]) + AC_DEFINE([HAVE_XRENDER], [1], [Define to 1 if XRender is available.]) fi fi @@ -3479,20 +3514,21 @@ if test "${HAVE_X11}" = "yes"; then if test "${with_cairo}" != "no"; then CAIRO_REQUIRED=1.8.0 CAIRO_MODULE="cairo >= $CAIRO_REQUIRED" - EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE) + EMACS_CHECK_MODULES([CAIRO], [$CAIRO_MODULE]) if test $HAVE_CAIRO = yes; then CAIRO_XCB_MODULE="cairo-xcb >= $CAIRO_REQUIRED" - EMACS_CHECK_MODULES(CAIRO_XCB, $CAIRO_XCB_MODULE) + EMACS_CHECK_MODULES([CAIRO_XCB], [$CAIRO_XCB_MODULE]) if test $HAVE_CAIRO_XCB = yes; then CAIRO_CFLAGS="$CAIRO_CFLAGS $CAIRO_XCB_CFLAGS" CAIRO_LIBS="$CAIRO_LIBS $CAIRO_XCB_LIBS" - AC_DEFINE(USE_CAIRO_XCB, 1, [Define to 1 if cairo XCB surfaces are available.]) + AC_DEFINE([USE_CAIRO_XCB], [1], + [Define to 1 if cairo XCB surfaces are available.]) fi - AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.]) + AC_DEFINE([USE_CAIRO], [1], [Define to 1 if using cairo.]) CFLAGS="$CFLAGS $CAIRO_CFLAGS" LIBS="$LIBS $CAIRO_LIBS" - AC_SUBST(CAIRO_CFLAGS) - AC_SUBST(CAIRO_LIBS) + AC_SUBST([CAIRO_CFLAGS]) + AC_SUBST([CAIRO_LIBS]) else AC_MSG_WARN([cairo requested but not found.]) fi @@ -3512,12 +3548,12 @@ if test "$with_xwidgets" != "no"; then XWIDGETS_OBJ="xwidget.o" if test "$HAVE_X_WINDOWS" = "yes" && test "${with_cairo}" = "no"; then CAIRO_XLIB_MODULES="cairo >= 1.8.0 cairo-xlib >= 1.8.0" - EMACS_CHECK_MODULES(CAIRO_XLIB, $CAIRO_XLIB_MODULES) + EMACS_CHECK_MODULES([CAIRO_XLIB], [$CAIRO_XLIB_MODULES]) if test $HAVE_CAIRO_XLIB = "yes"; then CAIRO_CFLAGS="$CAIRO_XLIB_CFLAGS" CAIRO_LIBS="$CAIRO_XLIB_LIBS" - AC_SUBST(CAIRO_CFLAGS) - AC_SUBST(CAIRO_LIBS) + AC_SUBST([CAIRO_CFLAGS]) + AC_SUBST([CAIRO_LIBS]) else AC_MSG_ERROR([xwidgets requested, but a suitable cairo installation wasn't found]) fi @@ -3532,7 +3568,7 @@ if test "$with_xwidgets" != "no"; then XWIDGETS_OBJ="xwidget.o" NS_OBJC_OBJ="$NS_OBJC_OBJ nsxwidget.o" dnl Update NS_OBJC_OBJ with added nsxwidget.o - AC_SUBST(NS_OBJC_OBJ) + AC_SUBST([NS_OBJC_OBJ]) else AC_MSG_ERROR([xwidgets requested, it requires GTK3 as X window toolkit or macOS Cocoa as window system.]) fi @@ -3540,37 +3576,37 @@ if test "$with_xwidgets" != "no"; then test $HAVE_XWIDGETS = yes || AC_MSG_ERROR([xwidgets requested but WebKitGTK+ or WebKit framework not found.]) - AC_DEFINE([HAVE_XWIDGETS], 1, [Define to 1 if you have xwidgets support.]) + AC_DEFINE([HAVE_XWIDGETS], [1], [Define to 1 if you have xwidgets support.]) fi -AC_SUBST(XWIDGETS_OBJ) +AC_SUBST([XWIDGETS_OBJ]) if test "$window_system" = "pgtk"; then CAIRO_REQUIRED=1.12.0 CAIRO_MODULE="cairo >= $CAIRO_REQUIRED" - EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE) + EMACS_CHECK_MODULES([CAIRO], [$CAIRO_MODULE]) if test $HAVE_CAIRO = yes; then - AC_DEFINE(USE_CAIRO, 1, [Define to 1 if using cairo.]) + AC_DEFINE([USE_CAIRO], [1], [Define to 1 if using cairo.]) else AC_MSG_ERROR([cairo required but not found.]) fi CFLAGS="$CFLAGS $CAIRO_CFLAGS" LIBS="$LIBS $CAIRO_LIBS" - AC_SUBST(CAIRO_CFLAGS) - AC_SUBST(CAIRO_LIBS) + AC_SUBST([CAIRO_CFLAGS]) + AC_SUBST([CAIRO_LIBS]) fi if test "${HAVE_BE_APP}" = "yes"; then if test "${with_be_cairo}" != "no"; then CAIRO_REQUIRED=1.8.0 CAIRO_MODULE="cairo >= $CAIRO_REQUIRED" - EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE) + EMACS_CHECK_MODULES([CAIRO], [$CAIRO_MODULE]) if test $HAVE_CAIRO = yes; then - AC_DEFINE(USE_BE_CAIRO, 1, [Define to 1 if using cairo on Haiku.]) + AC_DEFINE([USE_BE_CAIRO], [1], [Define to 1 if using cairo on Haiku.]) CFLAGS="$CFLAGS $CAIRO_CFLAGS" LIBS="$LIBS $CAIRO_LIBS" - AC_SUBST(CAIRO_CFLAGS) - AC_SUBST(CAIRO_LIBS) + AC_SUBST([CAIRO_CFLAGS]) + AC_SUBST([CAIRO_LIBS]) else AC_MSG_WARN([cairo requested but not found.]) fi @@ -3590,11 +3626,12 @@ if test "${HAVE_X11}" = "yes"; then dnl The following is needed to set FREETYPE_LIBS. EMACS_CHECK_MODULES([FREETYPE], [freetype2]) - test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR(cairo requires libfreetype) + test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR([cairo requires libfreetype]) EMACS_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.2.0]) - test "$HAVE_FONTCONFIG" = "no" && AC_MSG_ERROR(cairo requires libfontconfig) + test "$HAVE_FONTCONFIG" = "no" && + AC_MSG_ERROR([cairo requires libfontconfig]) dnl For the "Does Emacs use" message at the end. HAVE_XFT=no else @@ -3621,13 +3658,15 @@ if test "${HAVE_X11}" = "yes"; then CPPFLAGS="$CPPFLAGS $XFT_CFLAGS" CFLAGS="$CFLAGS $XFT_CFLAGS" LIBS="$XFT_LIBS $LIBS" - AC_CHECK_HEADER(X11/Xft/Xft.h, - [AC_CHECK_LIB(Xft, XftFontOpen, HAVE_XFT=yes, , $XFT_LIBS)] , , + AC_CHECK_HEADER([X11/Xft/Xft.h], + [AC_CHECK_LIB([Xft], [XftFontOpen], [HAVE_XFT=yes], + [], [$XFT_LIBS])], + [], [[#include ]]) if test "${HAVE_XFT}" = "yes"; then - AC_DEFINE(HAVE_XFT, 1, [Define to 1 if you have the Xft library.]) - AC_SUBST(XFT_LIBS) + AC_DEFINE([HAVE_XFT], [1], [Define to 1 if you have the Xft library.]) + AC_SUBST([XFT_LIBS]) C_SWITCH_X_SITE="$C_SWITCH_X_SITE $XFT_CFLAGS" fi # "${HAVE_XFT}" = "yes" CPPFLAGS=$OLD_CPPFLAGS @@ -3650,34 +3689,35 @@ if test "${HAVE_X11}" = "yes"; then dnl The following is needed to set FREETYPE_LIBS. EMACS_CHECK_MODULES([FREETYPE], [freetype2]) - test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR(libxft requires libfreetype) + test "$HAVE_FREETYPE" = "no" && + AC_MSG_ERROR([libxft requires libfreetype]) fi fi # $HAVE_CAIRO != yes HAVE_LIBOTF=no if test "${HAVE_FREETYPE}" = "yes"; then - AC_DEFINE(HAVE_FREETYPE, 1, + AC_DEFINE([HAVE_FREETYPE], [1], [Define to 1 if using the freetype and fontconfig libraries.]) OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS="$CFLAGS $FREETYPE_CFLAGS" LIBS="$FREETYPE_LIBS $LIBS" - AC_CHECK_FUNCS(FT_Face_GetCharVariantIndex) + AC_CHECK_FUNCS([FT_Face_GetCharVariantIndex]) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS if test "${with_libotf}" != "no"; then EMACS_CHECK_MODULES([LIBOTF], [libotf]) if test "$HAVE_LIBOTF" = "yes"; then - AC_DEFINE(HAVE_LIBOTF, 1, [Define to 1 if using libotf.]) - AC_CHECK_LIB(otf, OTF_get_variation_glyphs, - HAVE_OTF_GET_VARIATION_GLYPHS=yes, - HAVE_OTF_GET_VARIATION_GLYPHS=no) + AC_DEFINE([HAVE_LIBOTF], [1], [Define to 1 if using libotf.]) + AC_CHECK_LIB([otf], [OTF_get_variation_glyphs], + [HAVE_OTF_GET_VARIATION_GLYPHS=yes], + [HAVE_OTF_GET_VARIATION_GLYPHS=no]) if test "${HAVE_OTF_GET_VARIATION_GLYPHS}" = "yes"; then - AC_DEFINE(HAVE_OTF_GET_VARIATION_GLYPHS, 1, + AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1], [Define to 1 if libotf has OTF_get_variation_glyphs.]) fi if ! $PKG_CONFIG --atleast-version=0.9.16 libotf; then - AC_DEFINE(HAVE_OTF_KANNADA_BUG, 1, + AC_DEFINE([HAVE_OTF_KANNADA_BUG], [1], [Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.]) fi fi @@ -3691,7 +3731,7 @@ if test "${HAVE_X11}" = "yes"; then if test "${with_m17n_flt}" != "no"; then EMACS_CHECK_MODULES([M17N_FLT], [m17n-flt]) if test "$HAVE_M17N_FLT" = "yes"; then - AC_DEFINE(HAVE_M17N_FLT, 1, [Define to 1 if using libm17n-flt.]) + AC_DEFINE([HAVE_M17N_FLT], [1], [Define to 1 if using libm17n-flt.]) fi fi fi @@ -3700,20 +3740,20 @@ else # "${HAVE_X11}" != "yes" EMACS_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.2.0]) EMACS_CHECK_MODULES([FREETYPE], [freetype2]) if test "$HAVE_FONTCONFIG" != yes -o "$HAVE_FREETYPE" != yes; then - AC_MSG_ERROR(fontconfig and freetype is required.) + AC_MSG_ERROR([fontconfig and freetype is required.]) fi HAVE_LIBOTF=no - AC_DEFINE(HAVE_FREETYPE, 1, + AC_DEFINE([HAVE_FREETYPE], [1], [Define to 1 if using the freetype and fontconfig libraries.]) if test "${with_libotf}" != "no"; then EMACS_CHECK_MODULES([LIBOTF], [libotf]) if test "$HAVE_LIBOTF" = "yes"; then - AC_DEFINE(HAVE_LIBOTF, 1, [Define to 1 if using libotf.]) - AC_CHECK_LIB(otf, OTF_get_variation_glyphs, - HAVE_OTF_GET_VARIATION_GLYPHS=yes, - HAVE_OTF_GET_VARIATION_GLYPHS=no) + AC_DEFINE([HAVE_LIBOTF], [1], [Define to 1 if using libotf.]) + AC_CHECK_LIB([otf], [OTF_get_variation_glyphs], + [HAVE_OTF_GET_VARIATION_GLYPHS=yes], + [HAVE_OTF_GET_VARIATION_GLYPHS=no]) if test "${HAVE_OTF_GET_VARIATION_GLYPHS}" = "yes"; then - AC_DEFINE(HAVE_OTF_GET_VARIATION_GLYPHS, 1, + AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1], [Define to 1 if libotf has OTF_get_variation_glyphs.]) fi fi @@ -3740,7 +3780,7 @@ if test "${HAVE_X11}" = "yes" && test "${HAVE_FREETYPE}" = "yes" \ if test "${with_harfbuzz}" != "no"; then EMACS_CHECK_MODULES([HARFBUZZ], [harfbuzz >= $harfbuzz_required_ver]) if test "$HAVE_HARFBUZZ" = "yes"; then - AC_DEFINE(HAVE_HARFBUZZ, 1, [Define to 1 if using HarfBuzz.]) + AC_DEFINE([HAVE_HARFBUZZ], [1], [Define to 1 if using HarfBuzz.]) ### mingw32 and Cygwin-w32 don't use -lharfbuzz, since they load ### the library dynamically. if test "${HAVE_W32}" = "yes"; then @@ -3754,36 +3794,38 @@ fi if test "${HAVE_BE_APP}" = "yes"; then if test $HAVE_CAIRO = "yes"; then EMACS_CHECK_MODULES([FREETYPE], [freetype2 >= 2.5.0]) - test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR(cairo on Haiku requires libfreetype) + test "$HAVE_FREETYPE" = "no" && + AC_MSG_ERROR([cairo on Haiku requires libfreetype]) EMACS_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.2.0]) - test "$HAVE_FONTCONFIG" = "no" && AC_MSG_ERROR(cairo on Haiku requires libfontconfig) + test "$HAVE_FONTCONFIG" = "no" && + AC_MSG_ERROR([cairo on Haiku requires libfontconfig]) fi HAVE_LIBOTF=no if test "${HAVE_FREETYPE}" = "yes"; then - AC_DEFINE(HAVE_FREETYPE, 1, + AC_DEFINE([HAVE_FREETYPE], [1], [Define to 1 if using the freetype and fontconfig libraries.]) OLD_CFLAGS=$CFLAGS OLD_LIBS=$LIBS CFLAGS="$CFLAGS $FREETYPE_CFLAGS" LIBS="$FREETYPE_LIBS $LIBS" - AC_CHECK_FUNCS(FT_Face_GetCharVariantIndex) + AC_CHECK_FUNCS([FT_Face_GetCharVariantIndex]) CFLAGS=$OLD_CFLAGS LIBS=$OLD_LIBS if test "${with_libotf}" != "no"; then EMACS_CHECK_MODULES([LIBOTF], [libotf]) if test "$HAVE_LIBOTF" = "yes"; then - AC_DEFINE(HAVE_LIBOTF, 1, [Define to 1 if using libotf.]) - AC_CHECK_LIB(otf, OTF_get_variation_glyphs, - HAVE_OTF_GET_VARIATION_GLYPHS=yes, - HAVE_OTF_GET_VARIATION_GLYPHS=no) + AC_DEFINE([HAVE_LIBOTF], [1], [Define to 1 if using libotf.]) + AC_CHECK_LIB([otf], [OTF_get_variation_glyphs], + [HAVE_OTF_GET_VARIATION_GLYPHS=yes], + [HAVE_OTF_GET_VARIATION_GLYPHS=no]) if test "${HAVE_OTF_GET_VARIATION_GLYPHS}" = "yes"; then - AC_DEFINE(HAVE_OTF_GET_VARIATION_GLYPHS, 1, + AC_DEFINE([HAVE_OTF_GET_VARIATION_GLYPHS], [1], [Define to 1 if libotf has OTF_get_variation_glyphs.]) fi if ! $PKG_CONFIG --atleast-version=0.9.16 libotf; then - AC_DEFINE(HAVE_OTF_KANNADA_BUG, 1, + AC_DEFINE([HAVE_OTF_KANNADA_BUG], [1], [Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.]) fi fi @@ -3797,41 +3839,41 @@ if test "${HAVE_BE_APP}" = "yes" && test "${HAVE_FREETYPE}" = "yes"; then if test "${with_harfbuzz}" != "no"; then EMACS_CHECK_MODULES([HARFBUZZ], [harfbuzz >= $harfbuzz_required_ver]) if test "$HAVE_HARFBUZZ" = "yes"; then - AC_DEFINE(HAVE_HARFBUZZ, 1, [Define to 1 if using HarfBuzz.]) + AC_DEFINE([HAVE_HARFBUZZ], [1], [Define to 1 if using HarfBuzz.]) fi fi fi ### End of font-backend section. -AC_SUBST(FREETYPE_CFLAGS) -AC_SUBST(FREETYPE_LIBS) -AC_SUBST(FONTCONFIG_CFLAGS) -AC_SUBST(FONTCONFIG_LIBS) -AC_SUBST(HARFBUZZ_CFLAGS) -AC_SUBST(HARFBUZZ_LIBS) -AC_SUBST(LIBOTF_CFLAGS) -AC_SUBST(LIBOTF_LIBS) -AC_SUBST(M17N_FLT_CFLAGS) -AC_SUBST(M17N_FLT_LIBS) +AC_SUBST([FREETYPE_CFLAGS]) +AC_SUBST([FREETYPE_LIBS]) +AC_SUBST([FONTCONFIG_CFLAGS]) +AC_SUBST([FONTCONFIG_LIBS]) +AC_SUBST([HARFBUZZ_CFLAGS]) +AC_SUBST([HARFBUZZ_LIBS]) +AC_SUBST([LIBOTF_CFLAGS]) +AC_SUBST([LIBOTF_LIBS]) +AC_SUBST([M17N_FLT_CFLAGS]) +AC_SUBST([M17N_FLT_LIBS]) XCB_LIBS= if test "${HAVE_X11}" = "yes"; then - AC_CHECK_HEADER(X11/Xlib-xcb.h, - [AC_CHECK_LIB(xcb, xcb_translate_coordinates, HAVE_XCB=yes)]) + AC_CHECK_HEADER([X11/Xlib-xcb.h], + [AC_CHECK_LIB([xcb], [xcb_translate_coordinates], [HAVE_XCB=yes])]) if test "${HAVE_XCB}" = "yes"; then - AC_CHECK_LIB(X11-xcb, XGetXCBConnection, HAVE_X11_XCB=yes) + AC_CHECK_LIB([X11-xcb], [XGetXCBConnection], [HAVE_X11_XCB=yes]) if test "${HAVE_X11_XCB}" = "yes"; then - AC_CHECK_LIB(xcb-util, xcb_aux_sync, HAVE_XCB_UTIL=yes) + AC_CHECK_LIB([xcb-util], [xcb_aux_sync], [HAVE_XCB_UTIL=yes]) if test "${HAVE_XCB_UTIL}" = "yes"; then - AC_DEFINE(USE_XCB, 1, + AC_DEFINE([USE_XCB], [1], [Define to 1 if you have the XCB library and X11-XCB library for mixed X11/XCB programming.]) XCB_LIBS="-lX11-xcb -lxcb -lxcb-util" else - AC_CHECK_LIB(xcb-aux, xcb_aux_sync, HAVE_XCB_AUX=yes) + AC_CHECK_LIB([xcb-aux], [xcb_aux_sync], [HAVE_XCB_AUX=yes]) if test "${HAVE_XCB_AUX}" = "yes"; then - AC_DEFINE(USE_XCB, 1, + AC_DEFINE([USE_XCB], [1], [Define to 1 if you have the XCB library and X11-XCB library for mixed X11/XCB programming.]) XCB_LIBS="-lX11-xcb -lxcb -lxcb-aux" @@ -3840,7 +3882,7 @@ if test "${HAVE_X11}" = "yes"; then fi fi fi -AC_SUBST(XCB_LIBS) +AC_SUBST([XCB_LIBS]) ### Use -lXpm if available, unless '--with-xpm=no'. ### mingw32 doesn't use -lXpm, since it loads the library dynamically. @@ -3852,18 +3894,18 @@ if test "${HAVE_W32}" = "yes" && test "${opsys}" = "cygwin"; then if test "${with_xpm}" != "no"; then SAVE_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -L/usr/lib/noX" - AC_CHECK_HEADER(noX/xpm.h, - [AC_CHECK_LIB(Xpm, XpmReadFileToImage, HAVE_XPM=yes)]) + AC_CHECK_HEADER([noX/xpm.h], + [AC_CHECK_LIB([Xpm], [XpmReadFileToImage], [HAVE_XPM=yes])]) if test "${HAVE_XPM}" = "yes"; then AC_CACHE_CHECK([for XpmReturnAllocPixels preprocessor define], [emacs_cv_cpp_xpm_return_alloc_pixels], - [AC_EGREP_CPP(no_return_alloc_pixels, + [AC_EGREP_CPP([no_return_alloc_pixels], [#include "noX/xpm.h" #ifndef XpmReturnAllocPixels no_return_alloc_pixels #endif - ], emacs_cv_cpp_xpm_return_alloc_pixels=no, - emacs_cv_cpp_xpm_return_alloc_pixels=yes)]) + ], [emacs_cv_cpp_xpm_return_alloc_pixels=no], + [emacs_cv_cpp_xpm_return_alloc_pixels=yes])]) if test "$emacs_cv_cpp_xpm_return_alloc_pixels" = "no"; then HAVE_XPM=no @@ -3873,7 +3915,8 @@ no_return_alloc_pixels fi if test "${HAVE_XPM}" = "yes"; then - AC_DEFINE(HAVE_XPM, 1, [Define to 1 if you have the Xpm library (-lXpm).]) + AC_DEFINE([HAVE_XPM], [1], + [Define to 1 if you have the Xpm library (-lXpm).]) LIBXPM=-lXpm fi fi @@ -3886,18 +3929,19 @@ if test "${HAVE_X11}" = "yes"; then esac if test "${with_xpm}" != "no"; then - AC_CHECK_HEADER(X11/xpm.h, - [AC_CHECK_LIB(Xpm, XpmReadFileToPixmap, HAVE_XPM=yes, , -lX11)]) + AC_CHECK_HEADER([X11/xpm.h], + [AC_CHECK_LIB([Xpm], [XpmReadFileToPixmap], + [HAVE_XPM=yes], [], [-lX11])]) if test "${HAVE_XPM}" = "yes"; then AC_CACHE_CHECK([for XpmReturnAllocPixels preprocessor define], [emacs_cv_cpp_xpm_return_alloc_pixels], - [AC_EGREP_CPP(no_return_alloc_pixels, + [AC_EGREP_CPP([no_return_alloc_pixels], [#include "X11/xpm.h" #ifndef XpmReturnAllocPixels no_return_alloc_pixels #endif - ], emacs_cv_cpp_xpm_return_alloc_pixels=no, - emacs_cv_cpp_xpm_return_alloc_pixels=yes)]) + ], [emacs_cv_cpp_xpm_return_alloc_pixels=no], + [emacs_cv_cpp_xpm_return_alloc_pixels=yes])]) if test "$emacs_cv_cpp_xpm_return_alloc_pixels" = "no"; then HAVE_XPM=no @@ -3906,7 +3950,8 @@ no_return_alloc_pixels fi if test "${HAVE_XPM}" = "yes"; then - AC_DEFINE(HAVE_XPM, 1, [Define to 1 if you have the Xpm library (-lXpm).]) + AC_DEFINE([HAVE_XPM], [1], + [Define to 1 if you have the Xpm library (-lXpm).]) LIBXPM=-lXpm elif test "$opsys,$LUCID_LIBW" = aix4-2,-lXaw; then dnl AIX -lXaw needs -lXpm linked too; see Bug#17598 Message#152. @@ -3920,16 +3965,17 @@ fi ### run time). if test "${opsys}" = "mingw32"; then if test "${with_xpm}" != "no"; then - AC_CHECK_HEADER(X11/xpm.h, HAVE_XPM=yes, HAVE_XPM=no, [ + AC_CHECK_HEADER([X11/xpm.h], [HAVE_XPM=yes], [HAVE_XPM=no], [ #define FOR_MSW 1]) fi if test "${HAVE_XPM}" = "yes"; then - AC_DEFINE(HAVE_XPM, 1, [Define to 1 if you have the Xpm library (-lXpm).]) + AC_DEFINE([HAVE_XPM], [1], + [Define to 1 if you have the Xpm library (-lXpm).]) fi fi -AC_SUBST(LIBXPM) +AC_SUBST([LIBXPM]) ### Use -ljpeg if available, unless '--with-jpeg=no'. HAVE_JPEG=no @@ -3968,7 +4014,7 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \ done]) if test "$emacs_cv_jpeglib" != no; then HAVE_JPEG=yes - AC_DEFINE([HAVE_JPEG], 1, + AC_DEFINE([HAVE_JPEG], [1], [Define to 1 if you have the jpeg library (typically -ljpeg).]) ### mingw32 doesn't use -ljpeg, since it loads the library ### dynamically when needed, and doesn't want a run-time @@ -3978,7 +4024,7 @@ if test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \ fi fi fi -AC_SUBST(LIBJPEG) +AC_SUBST([LIBJPEG]) HAVE_LCMS2=no LCMS2_CFLAGS= @@ -3987,14 +4033,15 @@ if test "${with_lcms2}" != "no"; then EMACS_CHECK_MODULES([LCMS2], [lcms2]) fi if test "${HAVE_LCMS2}" = "yes"; then - AC_DEFINE([HAVE_LCMS2], 1, [Define to 1 if you have the lcms2 library (-llcms2).]) + AC_DEFINE([HAVE_LCMS2], [1], + [Define to 1 if you have the lcms2 library (-llcms2).]) ### mingw32 doesn't use -llcms2, since it loads the library dynamically. if test "${opsys}" = "mingw32"; then LCMS2_LIBS= fi fi -AC_SUBST(LCMS2_CFLAGS) -AC_SUBST(LCMS2_LIBS) +AC_SUBST([LCMS2_CFLAGS]) +AC_SUBST([LCMS2_LIBS]) HAVE_ZLIB=no LIBZ= @@ -4007,13 +4054,14 @@ if test "${with_zlib}" != "no"; then esac fi if test "${HAVE_ZLIB}" = "yes"; then - AC_DEFINE([HAVE_ZLIB], 1, [Define to 1 if you have the zlib library (-lz).]) + AC_DEFINE([HAVE_ZLIB], [1], + [Define to 1 if you have the zlib library (-lz).]) ### mingw32 doesn't use -lz, since it loads the library dynamically. if test "${opsys}" = "mingw32"; then LIBZ= fi fi -AC_SUBST(LIBZ) +AC_SUBST([LIBZ]) ### Dynamic modules support LIBMODULES= @@ -4067,19 +4115,20 @@ fi if test "${HAVE_MODULES}" = yes; then MODULES_OBJ="emacs-module.o" NEED_DYNLIB=yes - AC_DEFINE(HAVE_MODULES, 1, [Define to 1 if dynamic modules are enabled]) - AC_DEFINE_UNQUOTED(MODULES_SUFFIX, "$MODULES_SUFFIX", + AC_DEFINE([HAVE_MODULES], [1], [Define to 1 if dynamic modules are enabled]) + AC_DEFINE_UNQUOTED([MODULES_SUFFIX], ["$MODULES_SUFFIX"], [System extension for dynamic libraries]) if test -n "${MODULES_SECONDARY_SUFFIX}"; then - AC_DEFINE_UNQUOTED(MODULES_SECONDARY_SUFFIX, "$MODULES_SECONDARY_SUFFIX", + AC_DEFINE_UNQUOTED([MODULES_SECONDARY_SUFFIX], + ["$MODULES_SECONDARY_SUFFIX"], [Alternative system extension for dynamic libraries.]) fi fi -AC_SUBST(MODULES_OBJ) -AC_SUBST(LIBMODULES) -AC_SUBST(HAVE_MODULES) -AC_SUBST(MODULES_SUFFIX) -AC_SUBST(MODULES_SECONDARY_SUFFIX) +AC_SUBST([MODULES_OBJ]) +AC_SUBST([LIBMODULES]) +AC_SUBST([HAVE_MODULES]) +AC_SUBST([MODULES_SUFFIX]) +AC_SUBST([MODULES_SECONDARY_SUFFIX]) AC_CONFIG_FILES([src/emacs-module.h]) AC_SUBST_FILE([module_env_snippet_25]) @@ -4093,7 +4142,7 @@ module_env_snippet_27="$srcdir/src/module-env-27.h" module_env_snippet_28="$srcdir/src/module-env-28.h" module_env_snippet_29="$srcdir/src/module-env-29.h" emacs_major_version="${PACKAGE_VERSION%%.*}" -AC_SUBST(emacs_major_version) +AC_SUBST([emacs_major_version]) ### Emacs Lisp native compiler support @@ -4220,8 +4269,9 @@ if test "${with_native_compilation}" != "no"; then fi # Check if libgccjit is available. - AC_CHECK_LIB(gccjit, gcc_jit_context_acquire, [], [libgccjit_not_found]) - AC_CHECK_HEADERS(libgccjit.h, [], [libgccjit_dev_not_found]) + AC_CHECK_LIB([gccjit], [gcc_jit_context_acquire], + [], [libgccjit_not_found]) + AC_CHECK_HEADERS([libgccjit.h], [], [libgccjit_dev_not_found]) # Check if libgccjit really works. AC_RUN_IFELSE([libgccjit_smoke_test], [], [libgccjit_broken]) HAVE_NATIVE_COMP=yes @@ -4238,22 +4288,23 @@ if test "${with_native_compilation}" != "no"; then LIBGCCJIT_LIBS="-lgccjit -ldl" ;; esac NEED_DYNLIB=yes - AC_DEFINE(HAVE_NATIVE_COMP, 1, [Define to 1 if native compiler is available.]) + AC_DEFINE([HAVE_NATIVE_COMP], [1], + [Define to 1 if native compiler is available.]) CFLAGS=$SAVE_CFLAGS LIBS=$SAVE_LIBS fi -AC_DEFINE_UNQUOTED(NATIVE_ELISP_SUFFIX, ".eln", +AC_DEFINE_UNQUOTED([NATIVE_ELISP_SUFFIX], [".eln"], [System extension for native compiled elisp]) -AC_SUBST(HAVE_NATIVE_COMP) -AC_SUBST(LIBGCCJIT_CFLAGS) -AC_SUBST(LIBGCCJIT_LIBS) +AC_SUBST([HAVE_NATIVE_COMP]) +AC_SUBST([LIBGCCJIT_CFLAGS]) +AC_SUBST([LIBGCCJIT_LIBS]) DYNLIB_OBJ= if test "${NEED_DYNLIB}" = yes; then DYNLIB_OBJ="dynlib.o" fi -AC_SUBST(DYNLIB_OBJ) +AC_SUBST([DYNLIB_OBJ]) ### Use -lpng if available, unless '--with-png=no'. HAVE_PNG=no @@ -4325,8 +4376,8 @@ if test $HAVE_PNG = yes; then ]]) CFLAGS=$SAVE_CFLAGS fi -AC_SUBST(LIBPNG) -AC_SUBST(PNG_CFLAGS) +AC_SUBST([LIBPNG]) +AC_SUBST([PNG_CFLAGS]) ### Use -ltiff if available, unless '--with-tiff=no'. ### mingw32 doesn't use -ltiff, since it loads the library dynamically. @@ -4334,29 +4385,32 @@ HAVE_TIFF=no LIBTIFF= if test "${opsys}" = "mingw32"; then if test "${with_tiff}" != "no"; then - AC_CHECK_HEADER(tiffio.h, HAVE_TIFF=yes, HAVE_TIFF=no) + AC_CHECK_HEADER([tiffio.h], [HAVE_TIFF=yes], [HAVE_TIFF=no]) fi if test "${HAVE_TIFF}" = "yes"; then - AC_DEFINE(HAVE_TIFF, 1, [Define to 1 if you have the tiff library (-ltiff).]) + AC_DEFINE([HAVE_TIFF], [1], + [Define to 1 if you have the tiff library (-ltiff).]) fi elif test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \ || test "${HAVE_NS}" = "yes" || test "${HAVE_BE_APP}" = "yes" \ || test "$window_system" = "pgtk"; then if test "${with_tiff}" != "no"; then - AC_CHECK_HEADER(tiffio.h, + AC_CHECK_HEADER([tiffio.h], [tifflibs="-lz -lm" # At least one tiff package requires the jpeg library. if test "${HAVE_JPEG}" = yes; then tifflibs="-ljpeg $tifflibs"; fi - AC_CHECK_LIB(tiff, TIFFGetVersion, HAVE_TIFF=yes, , $tifflibs)]) + AC_CHECK_LIB([tiff], [TIFFGetVersion], [HAVE_TIFF=yes], [], + [$tifflibs])]) fi if test "${HAVE_TIFF}" = "yes"; then - AC_DEFINE(HAVE_TIFF, 1, [Define to 1 if you have the tiff library (-ltiff).]) + AC_DEFINE([HAVE_TIFF], [1], + [Define to 1 if you have the tiff library (-ltiff).]) dnl FIXME -lz -lm, as per libpng? LIBTIFF=-ltiff fi fi -AC_SUBST(LIBTIFF) +AC_SUBST([LIBTIFF]) ### Use -lgif or -lungif if available, unless '--with-gif=no'. ### mingw32 doesn't use -lgif/-lungif, since it loads the library dynamically. @@ -4364,34 +4418,40 @@ HAVE_GIF=no LIBGIF= if test "${opsys}" = "mingw32"; then if test "${with_gif}" != "no"; then - AC_CHECK_HEADER(gif_lib.h, HAVE_GIF=yes, HAVE_GIF=no) + AC_CHECK_HEADER([gif_lib.h], [HAVE_GIF=yes], [HAVE_GIF=no]) fi if test "${HAVE_GIF}" = "yes"; then - AC_DEFINE(HAVE_GIF, 1, [Define to 1 if you have a gif (or ungif) library.]) + AC_DEFINE([HAVE_GIF], [1], + [Define to 1 if you have a gif (or ungif) library.]) fi elif test "${HAVE_X11}" = "yes" && test "${with_gif}" != "no" \ || test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes" \ || test "${HAVE_BE_APP}" = "yes" || test "$window_system" = "pgtk" \ && test "${with_gif}" != "no"; then - AC_CHECK_HEADER(gif_lib.h, + AC_CHECK_HEADER([gif_lib.h], # EGifPutExtensionLast only exists from version libungif-4.1.0b1. # Earlier versions can crash Emacs, but version 5.0 removes EGifPutExtensionLast. - [AC_CHECK_LIB(gif, GifMakeMapObject, HAVE_GIF=yes, - [AC_CHECK_LIB(gif, EGifPutExtensionLast, HAVE_GIF=yes, HAVE_GIF=maybe)])]) + [AC_CHECK_LIB([gif], [GifMakeMapObject], [HAVE_GIF=yes], + [AC_CHECK_LIB([gif], [EGifPutExtensionLast], + [HAVE_GIF=yes], + [HAVE_GIF=maybe])])]) if test "$HAVE_GIF" = yes; then LIBGIF=-lgif elif test "$HAVE_GIF" = maybe; then # If gif_lib.h but no libgif, try libungif. - AC_CHECK_LIB(ungif, EGifPutExtensionLast, HAVE_GIF=yes, HAVE_GIF=no) + AC_CHECK_LIB([ungif], [EGifPutExtensionLast], + [HAVE_GIF=yes], + [HAVE_GIF=no]) test "$HAVE_GIF" = yes && LIBGIF=-lungif fi if test "${HAVE_GIF}" = "yes"; then - AC_DEFINE(HAVE_GIF, 1, [Define to 1 if you have a gif (or ungif) library.]) + AC_DEFINE([HAVE_GIF], [1], + [Define to 1 if you have a gif (or ungif) library.]) fi fi -AC_SUBST(LIBGIF) +AC_SUBST([LIBGIF]) dnl Check for required libraries. MISSING= @@ -4451,28 +4511,33 @@ fi HAVE_GPM=no LIBGPM= if test "${with_gpm}" != "no"; then - AC_CHECK_HEADER(gpm.h, - [AC_CHECK_LIB(gpm, Gpm_Open, HAVE_GPM=yes)]) + AC_CHECK_HEADER([gpm.h], + [AC_CHECK_LIB([gpm], [Gpm_Open], [HAVE_GPM=yes])]) if test "${HAVE_GPM}" = "yes"; then - AC_DEFINE(HAVE_GPM, 1, [Define to 1 if you have the gpm library (-lgpm).]) + AC_DEFINE([HAVE_GPM], [1], + [Define to 1 if you have the gpm library (-lgpm).]) LIBGPM=-lgpm fi fi -AC_SUBST(LIBGPM) +AC_SUBST([LIBGPM]) dnl Check for malloc/malloc.h on darwin -AC_CHECK_HEADERS_ONCE(malloc/malloc.h) +AC_CHECK_HEADERS_ONCE([malloc/malloc.h]) GNUSTEP_CFLAGS= ### Use NeXTstep API to implement GUI. if test "${HAVE_NS}" = "yes"; then - AC_DEFINE(HAVE_NS, 1, [Define to 1 if you are using the NeXTstep API, either GNUstep or Cocoa on macOS.]) + AC_DEFINE([HAVE_NS], [1], + [Define to 1 if you are using the NeXTstep API, + either GNUstep or Cocoa on macOS.]) if test "${NS_IMPL_COCOA}" = "yes"; then - AC_DEFINE(NS_IMPL_COCOA, 1, [Define to 1 if you are using NS windowing under macOS.]) + AC_DEFINE([NS_IMPL_COCOA], [1], + [Define to 1 if you are using NS windowing under macOS.]) fi if test "${NS_IMPL_GNUSTEP}" = "yes"; then - AC_DEFINE(NS_IMPL_GNUSTEP, 1, [Define to 1 if you are using NS windowing under GNUstep.]) + AC_DEFINE([NS_IMPL_GNUSTEP], [1], + [Define to 1 if you are using NS windowing under GNUstep.]) if test $NS_GNUSTEP_CONFIG != yes; then # See also .m.o rule in src/Makefile.in. */ # FIXME: are all these flags really needed? Document here why. */ @@ -4488,15 +4553,16 @@ fi HAVE_X_SM=no LIBXSM= if test "${HAVE_X11}" = "yes"; then - AC_CHECK_HEADER(X11/SM/SMlib.h, - [AC_CHECK_LIB(SM, SmcOpenConnection, HAVE_X_SM=yes, , -lICE)]) + AC_CHECK_HEADER([X11/SM/SMlib.h], + [AC_CHECK_LIB([SM], [SmcOpenConnection], [HAVE_X_SM=yes], [], [-lICE])]) if test "${HAVE_X_SM}" = "yes"; then - AC_DEFINE(HAVE_X_SM, 1, [Define to 1 if you have the SM library (-lSM).]) + AC_DEFINE([HAVE_X_SM], [1], + [Define to 1 if you have the SM library (-lSM).]) LIBXSM="-lSM -lICE" fi fi -AC_SUBST(LIBXSM) +AC_SUBST([LIBXSM]) ### Use XRandr (-lXrandr) if available HAVE_XRANDR=no @@ -4508,8 +4574,8 @@ if test "${HAVE_X11}" = "yes"; then # Test old way in case pkg-config doesn't have it (older machines). # Include Xrender.h by hand to work around bug in older Xrandr.h # (e.g. RHEL5) and silence (harmless) configure warning (bug#18465). - AC_CHECK_HEADER(X11/extensions/Xrandr.h, - [AC_CHECK_LIB(Xrandr, XRRGetScreenResources, HAVE_XRANDR=yes)], + AC_CHECK_HEADER([X11/extensions/Xrandr.h], + [AC_CHECK_LIB([Xrandr], [XRRGetScreenResources], [HAVE_XRANDR=yes])], [], [AC_INCLUDES_DEFAULT #include ]) if test $HAVE_XRANDR = yes; then @@ -4517,11 +4583,12 @@ if test "${HAVE_X11}" = "yes"; then fi fi if test $HAVE_XRANDR = yes; then - AC_DEFINE(HAVE_XRANDR, 1, [Define to 1 if you have the XRandr extension.]) + AC_DEFINE([HAVE_XRANDR], [1], + [Define to 1 if you have the XRandr extension.]) fi fi -AC_SUBST(XRANDR_CFLAGS) -AC_SUBST(XRANDR_LIBS) +AC_SUBST([XRANDR_CFLAGS]) +AC_SUBST([XRANDR_LIBS]) ### Use Xinerama (-lXinerama) if available HAVE_XINERAMA=no @@ -4531,18 +4598,20 @@ if test "${HAVE_X11}" = "yes"; then EMACS_CHECK_MODULES([XINERAMA], [$XINERAMA_MODULES]) if test $HAVE_XINERAMA = no; then # Test old way in case pkg-config doesn't have it (older machines). - AC_CHECK_HEADER(X11/extensions/Xinerama.h, - [AC_CHECK_LIB(Xinerama, XineramaQueryExtension, HAVE_XINERAMA=yes)]) + AC_CHECK_HEADER([X11/extensions/Xinerama.h], + [AC_CHECK_LIB([Xinerama], [XineramaQueryExtension], + [HAVE_XINERAMA=yes])]) if test $HAVE_XINERAMA = yes; then XINERAMA_LIBS=-lXinerama fi fi if test $HAVE_XINERAMA = yes; then - AC_DEFINE(HAVE_XINERAMA, 1, [Define to 1 if you have the Xinerama extension.]) + AC_DEFINE([HAVE_XINERAMA], [1], + [Define to 1 if you have the Xinerama extension.]) fi fi -AC_SUBST(XINERAMA_CFLAGS) -AC_SUBST(XINERAMA_LIBS) +AC_SUBST([XINERAMA_CFLAGS]) +AC_SUBST([XINERAMA_LIBS]) ### Use Xfixes (-lXfixes) if available HAVE_XFIXES=no @@ -4552,18 +4621,19 @@ if test "${HAVE_X11}" = "yes"; then EMACS_CHECK_MODULES([XFIXES], [$XFIXES_MODULES]) if test $HAVE_XFIXES = no; then # Test old way in case pkg-config doesn't have it (older machines). - AC_CHECK_HEADER(X11/extensions/Xfixes.h, - [AC_CHECK_LIB(Xfixes, XFixesHideCursor, HAVE_XFIXES=yes)]) + AC_CHECK_HEADER([X11/extensions/Xfixes.h], + [AC_CHECK_LIB([Xfixes], [XFixesHideCursor], [HAVE_XFIXES=yes])]) if test $HAVE_XFIXES = yes; then XFIXES_LIBS=-lXfixes fi fi if test $HAVE_XFIXES = yes; then - AC_DEFINE(HAVE_XFIXES, 1, [Define to 1 if you have the Xfixes extension.]) + AC_DEFINE([HAVE_XFIXES], [1], + [Define to 1 if you have the Xfixes extension.]) fi fi -AC_SUBST(XFIXES_CFLAGS) -AC_SUBST(XFIXES_LIBS) +AC_SUBST([XFIXES_CFLAGS]) +AC_SUBST([XFIXES_LIBS]) ## Use XInput 2.0 if available HAVE_XINPUT2=no @@ -4571,11 +4641,12 @@ if test "${HAVE_X11}" = "yes" && test "${with_xinput2}" != "no"; then EMACS_CHECK_MODULES([XINPUT], [xi]) if test $HAVE_XINPUT = yes; then # Now check for XInput2.h - AC_CHECK_HEADER(X11/extensions/XInput2.h, - [AC_CHECK_LIB(Xi, XIGrabButton, HAVE_XINPUT2=yes)]) + AC_CHECK_HEADER([X11/extensions/XInput2.h], + [AC_CHECK_LIB([Xi], [XIGrabButton], [HAVE_XINPUT2=yes])]) fi if test $HAVE_XINPUT2 = yes; then - AC_DEFINE(HAVE_XINPUT2, 1, [Define to 1 if the X Input Extension version 2.0 or later is present.]) + AC_DEFINE([HAVE_XINPUT2], [1], + [Define to 1 if the X Input Extension version 2.0 or later is present.]) if test "$USE_GTK_TOOLKIT" = "GTK2"; then AC_MSG_WARN([You are building Emacs with GTK+ 2 and the X Input Extension version 2. This might lead to problems if your version of GTK+ is not built with support for XInput 2.]) @@ -4589,31 +4660,32 @@ This might lead to problems if your version of GTK+ is not built with support fo [], [], [#include ]) fi fi -AC_SUBST(XINPUT_CFLAGS) -AC_SUBST(XINPUT_LIBS) +AC_SUBST([XINPUT_CFLAGS]) +AC_SUBST([XINPUT_LIBS]) XSYNC_LIBS= XSYNC_CFLAGS= HAVE_XSYNC=no if test "${HAVE_X11}" = "yes"; then - AC_CHECK_HEADER(X11/extensions/sync.h, - [AC_CHECK_LIB(Xext, XSyncQueryExtension, HAVE_XSYNC=yes)], + AC_CHECK_HEADER([X11/extensions/sync.h], + [AC_CHECK_LIB([Xext], [XSyncQueryExtension], [HAVE_XSYNC=yes])], [], [#include ]) if test "${HAVE_XSYNC}" = "yes"; then - AC_DEFINE(HAVE_XSYNC, 1, [Define to 1 if the X Synchronization Extension is available.]) + AC_DEFINE([HAVE_XSYNC], [1], + [Define to 1 if the X Synchronization Extension is available.]) XSYNC_LIBS="-lXext" fi fi -AC_SUBST(XSYNC_LIBS) -AC_SUBST(XSYNC_CFLAGS) +AC_SUBST([XSYNC_LIBS]) +AC_SUBST([XSYNC_CFLAGS]) ### Use Xdbe (-lXdbe) if available HAVE_XDBE=no if test "${HAVE_X11}" = "yes"; then if test "${with_xdbe}" != "no"; then - AC_CHECK_HEADER(X11/extensions/Xdbe.h, - [AC_CHECK_LIB(Xext, XdbeAllocateBackBufferName, HAVE_XDBE=yes)], + AC_CHECK_HEADER([X11/extensions/Xdbe.h], + [AC_CHECK_LIB([Xext], [XdbeAllocateBackBufferName], [HAVE_XDBE=yes])], [], [#include ]) @@ -4622,44 +4694,49 @@ if test "${HAVE_X11}" = "yes"; then XDBE_LIBS=-lXext fi if test $HAVE_XDBE = yes; then - AC_DEFINE(HAVE_XDBE, 1, [Define to 1 if you have the Xdbe extension.]) + AC_DEFINE([HAVE_XDBE], [1], [Define to 1 if you have the Xdbe extension.]) fi fi -AC_SUBST(XDBE_CFLAGS) -AC_SUBST(XDBE_LIBS) +AC_SUBST([XDBE_CFLAGS]) +AC_SUBST([XDBE_LIBS]) ### Use the Nonrectangular Window Shape extension if available. HAVE_XSHAPE=no HAVE_XCB_SHAPE=no if test "${HAVE_X11}" = "yes"; then - AC_CHECK_HEADER(X11/extensions/shape.h, - [AC_CHECK_LIB(Xext, XShapeQueryVersion, HAVE_XSHAPE=yes)], + AC_CHECK_HEADER([X11/extensions/shape.h], + [AC_CHECK_LIB([Xext], [XShapeQueryVersion], [HAVE_XSHAPE=yes])], [], [#include ]) if test $HAVE_XSHAPE = yes; then XSHAPE_LIBS=-lXext - AC_CHECK_HEADER(xcb/shape.h, - [AC_CHECK_LIB(xcb-shape, xcb_shape_combine, HAVE_XCB_SHAPE=yes)], [], + AC_CHECK_HEADER([xcb/shape.h], + [AC_CHECK_LIB([xcb-shape], [xcb_shape_combine], [HAVE_XCB_SHAPE=yes])], + [], [#include ]) if test $HAVE_XCB_SHAPE = yes && test "$XCB_LIBS" != ""; then XSHAPE_LIBS="$XSHAPE_LIBS -lxcb-shape" - AC_DEFINE(HAVE_XCB_SHAPE, 1, [Define to 1 if XCB supports the Nonrectangular Window Shape extension.]) + AC_DEFINE([HAVE_XCB_SHAPE], [1], + [Define to 1 if XCB supports the + Nonrectangular Window Shape extension.]) fi fi if test $HAVE_XSHAPE = yes; then - AC_DEFINE(HAVE_XSHAPE, 1, [Define to 1 if you have the Nonrectangular Window Shape extension.]) + AC_DEFINE([HAVE_XSHAPE], [1], + [Define to 1 if you have the Nonrectangular Window Shape extension.]) fi fi -AC_SUBST(XSHAPE_CFLAGS) -AC_SUBST(XSHAPE_LIBS) +AC_SUBST([XSHAPE_CFLAGS]) +AC_SUBST([XSHAPE_LIBS]) ### Use Xcomposite (-lXcomposite) if available HAVE_XCOMPOSITE=no if test "${HAVE_X11}" = "yes"; then - AC_CHECK_HEADER(X11/extensions/Xcomposite.h, - [AC_CHECK_LIB(Xcomposite, XCompositeRedirectWindow, HAVE_XCOMPOSITE=yes)], + AC_CHECK_HEADER([X11/extensions/Xcomposite.h], + [AC_CHECK_LIB([Xcomposite], [XCompositeRedirectWindow], + [HAVE_XCOMPOSITE=yes])], [], [#include ]) @@ -4667,11 +4744,12 @@ if test "${HAVE_X11}" = "yes"; then XCOMPOSITE_LIBS=-lXcomposite fi if test $HAVE_XCOMPOSITE = yes; then - AC_DEFINE(HAVE_XCOMPOSITE, 1, [Define to 1 if you have the XCOMPOSITE extension.]) + AC_DEFINE([HAVE_XCOMPOSITE], [1], + [Define to 1 if you have the XCOMPOSITE extension.]) fi fi -AC_SUBST(XCOMPOSITE_CFLAGS) -AC_SUBST(XCOMPOSITE_LIBS) +AC_SUBST([XCOMPOSITE_CFLAGS]) +AC_SUBST([XCOMPOSITE_LIBS]) ### Use libxml (-lxml2) if available ### mingw32 doesn't use -lxml2, since it loads the library dynamically. @@ -4691,8 +4769,8 @@ if test "${with_xml2}" != "no"; then esac fi CPPFLAGS="$CPPFLAGS -isystem${xcsdkdir}/usr/include/libxml2" - AC_CHECK_HEADER(libxml/HTMLparser.h, - [AC_CHECK_DECL(HTML_PARSE_RECOVER, HAVE_LIBXML2=yes, , + AC_CHECK_HEADER([libxml/HTMLparser.h], + [AC_CHECK_DECL([HTML_PARSE_RECOVER], [HAVE_LIBXML2=yes], [], [#include ])]) CPPFLAGS="$SAVE_CPPFLAGS" if test "${HAVE_LIBXML2}" = "yes"; then @@ -4702,21 +4780,24 @@ if test "${with_xml2}" != "no"; then fi if test "${HAVE_LIBXML2}" = "yes"; then if test "${opsys}" != "mingw32"; then - AC_CHECK_LIB(xml2, htmlReadMemory, HAVE_LIBXML2=yes, HAVE_LIBXML2=no, + AC_CHECK_LIB([xml2], [htmlReadMemory], + [HAVE_LIBXML2=yes], + [HAVE_LIBXML2=no], [$LIBXML2_LIBS]) else LIBXML2_LIBS="" fi if test "${HAVE_LIBXML2}" = "yes"; then - AC_DEFINE(HAVE_LIBXML2, 1, [Define to 1 if you have the libxml library (-lxml2).]) + AC_DEFINE([HAVE_LIBXML2], [1], + [Define to 1 if you have the libxml library (-lxml2).]) else LIBXML2_LIBS="" LIBXML2_CFLAGS="" fi fi fi -AC_SUBST(LIBXML2_LIBS) -AC_SUBST(LIBXML2_CFLAGS) +AC_SUBST([LIBXML2_LIBS]) +AC_SUBST([LIBXML2_CFLAGS]) BLESSMAIL_TARGET= LIBS_MAIL= @@ -4822,7 +4903,7 @@ AC_SUBST([LIBSECCOMP_CFLAGS]) OLD_LIBS=$LIBS LIBS="$LIB_PTHREAD $LIB_MATH $LIBS" -AC_CHECK_FUNCS(accept4 fchdir gethostname \ +AC_CHECK_FUNCS([accept4 fchdir gethostname \ getrusage get_current_dir_name \ lrand48 random rint trunc \ select getpagesize setlocale newlocale \ @@ -4832,7 +4913,7 @@ sendto recvfrom getsockname getifaddrs freeifaddrs \ gai_strerror sync \ getpwent endpwent getgrent endgrent \ cfmakeraw cfsetspeed __executable_start log2 pthread_setname_np \ -pthread_set_name_np) +pthread_set_name_np]) LIBS=$OLD_LIBS if test "$ac_cv_func_pthread_setname_np" = "yes"; then @@ -4847,7 +4928,7 @@ if test "$ac_cv_func_pthread_setname_np" = "yes"; then [emacs_cv_pthread_setname_np_1arg=no])]) if test "$emacs_cv_pthread_setname_np_1arg" = "yes"; then AC_DEFINE( - HAVE_PTHREAD_SETNAME_NP_1ARG, 1, + [HAVE_PTHREAD_SETNAME_NP_1ARG], [1], [Define to 1 if pthread_setname_np takes a single argument.]) else AC_CACHE_CHECK( @@ -4861,7 +4942,7 @@ if test "$ac_cv_func_pthread_setname_np" = "yes"; then [emacs_cv_pthread_setname_np_3arg=no])]) if test "$emacs_cv_pthread_setname_np_3arg" = "yes"; then AC_DEFINE( - HAVE_PTHREAD_SETNAME_NP_3ARG, 1, + [HAVE_PTHREAD_SETNAME_NP_3ARG], [1], [Define to 1 if pthread_setname_np takes three arguments.]) fi fi @@ -4894,28 +4975,28 @@ AC_CACHE_CHECK([for __builtin_frame_address], [emacs_cv_func___builtin_frame_address=yes], [emacs_cv_func___builtin_frame_address=no])]) if test $emacs_cv_func___builtin_frame_address = yes; then - AC_DEFINE([HAVE___BUILTIN_FRAME_ADDRESS], 1, + AC_DEFINE([HAVE___BUILTIN_FRAME_ADDRESS], [1], [Define to 1 if you have the '__builtin_frame_address' function.]) fi AC_CACHE_CHECK([for __builtin_unwind_init], - emacs_cv_func___builtin_unwind_init, + [emacs_cv_func___builtin_unwind_init], [AC_LINK_IFELSE([AC_LANG_PROGRAM([], [__builtin_unwind_init ();])], - emacs_cv_func___builtin_unwind_init=yes, - emacs_cv_func___builtin_unwind_init=no)]) + [emacs_cv_func___builtin_unwind_init=yes], + [emacs_cv_func___builtin_unwind_init=no])]) if test $emacs_cv_func___builtin_unwind_init = yes; then - AC_DEFINE(HAVE___BUILTIN_UNWIND_INIT, 1, + AC_DEFINE([HAVE___BUILTIN_UNWIND_INIT], [1], [Define to 1 if you have the '__builtin_unwind_init' function.]) fi -AC_CHECK_HEADERS_ONCE(sys/un.h) +AC_CHECK_HEADERS_ONCE([sys/un.h]) AC_FUNC_FSEEKO # UNIX98 PTYs. -AC_CHECK_FUNCS(grantpt) +AC_CHECK_FUNCS([grantpt]) # PTY-related GNU extensions. -AC_CHECK_FUNCS(getpt posix_openpt) +AC_CHECK_FUNCS([getpt posix_openpt]) dnl Run a test program that contains a call to tputs, a call that is dnl never executed. This tests whether a pre-'main' dynamic linker @@ -4987,14 +5068,15 @@ case "$opsys" in freebsd) AC_MSG_CHECKING([whether FreeBSD is new enough to use terminfo]) - AC_CACHE_VAL(emacs_cv_freebsd_terminfo, + AC_CACHE_VAL([emacs_cv_freebsd_terminfo], [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[#if __FreeBSD_version < 400000 fail; #endif -]])], emacs_cv_freebsd_terminfo=yes, emacs_cv_freebsd_terminfo=no)]) +]])], [emacs_cv_freebsd_terminfo=yes], + [emacs_cv_freebsd_terminfo=no])]) - AC_MSG_RESULT($emacs_cv_freebsd_terminfo) + AC_MSG_RESULT([$emacs_cv_freebsd_terminfo]) if test $emacs_cv_freebsd_terminfo = yes; then LIBS_TERMCAP="-lncurses" @@ -5029,7 +5111,8 @@ esac TERMCAP_OBJ=tparam.o if test $TERMINFO = yes; then - AC_DEFINE(TERMINFO, 1, [Define to 1 if you use terminfo instead of termcap.]) + AC_DEFINE([TERMINFO], [1], + [Define to 1 if you use terminfo instead of termcap.]) TERMCAP_OBJ=terminfo.o AC_CACHE_CHECK([whether $LIBS_TERMCAP library defines BC], [emacs_cv_terminfo_defines_BC], @@ -5040,15 +5123,15 @@ if test $TERMINFO = yes; then [emacs_cv_terminfo_defines_BC=no]) LIBS=$OLD_LIBS]) if test "$emacs_cv_terminfo_defines_BC" = yes; then - AC_DEFINE([TERMINFO_DEFINES_BC], 1, [Define to 1 if the + AC_DEFINE([TERMINFO_DEFINES_BC], [1], [Define to 1 if the terminfo library defines the variables BC, PC, and UP.]) fi fi if test "X$LIBS_TERMCAP" = "X-lncurses"; then - AC_DEFINE(USE_NCURSES, 1, [Define to 1 if you use ncurses.]) + AC_DEFINE([USE_NCURSES], [1], [Define to 1 if you use ncurses.]) fi -AC_SUBST(LIBS_TERMCAP) -AC_SUBST(TERMCAP_OBJ) +AC_SUBST([LIBS_TERMCAP]) +AC_SUBST([TERMCAP_OBJ]) # GNU/Linux-specific timer functions. AC_CACHE_CHECK([for timerfd interface], [emacs_cv_have_timerfd], @@ -5061,7 +5144,7 @@ AC_CACHE_CHECK([for timerfd interface], [emacs_cv_have_timerfd], [emacs_cv_have_timerfd=yes], [emacs_cv_have_timerfd=no])]) if test "$emacs_cv_have_timerfd" = yes; then - AC_DEFINE([HAVE_TIMERFD], 1, + AC_DEFINE([HAVE_TIMERFD], [1], [Define to 1 if timerfd functions are supported as in GNU/Linux.]) fi @@ -5088,25 +5171,26 @@ LIBRESOLV= if test "$with_hesiod" != no ; then # Don't set $LIBS here -- see comments above. FIXME which comments? resolv=no - AC_CHECK_FUNC(res_send, , [AC_CHECK_FUNC(__res_send, , - [AC_CHECK_LIB(resolv, res_send, resolv=yes, - [AC_CHECK_LIB(resolv, __res_send, resolv=yes)])])]) + AC_CHECK_FUNC([res_send], [], [AC_CHECK_FUNC([__res_send], [], + [AC_CHECK_LIB([resolv], [res_send], [resolv=yes], + [AC_CHECK_LIB([resolv], [__res_send], [resolv=yes])])])]) if test "$resolv" = yes ; then RESOLVLIB=-lresolv else RESOLVLIB= fi hesiod=no - AC_CHECK_FUNC(hes_getmailhost, , [AC_CHECK_LIB(hesiod, hes_getmailhost, - hesiod=yes, :, $RESOLVLIB)]) + AC_CHECK_FUNC([hes_getmailhost], [], + [AC_CHECK_LIB([hesiod], [hes_getmailhost], + [hesiod=yes], [:], [$RESOLVLIB])]) if test x"$hesiod" = xyes; then LIBHESIOD=-lhesiod LIBRESOLV=$RESOLVLIB fi fi -AC_SUBST(LIBHESIOD) -AC_SUBST(LIBRESOLV) +AC_SUBST([LIBHESIOD]) +AC_SUBST([LIBRESOLV]) # These tell us which Kerberos-related libraries to use. COM_ERRLIB= @@ -5117,45 +5201,51 @@ KRB4LIB= if test "${with_kerberos}" != no; then OLD_LIBS=$LIBS - AC_CHECK_LIB(com_err, com_err, have_com_err=yes, have_com_err=no) + AC_CHECK_LIB([com_err], [com_err], [have_com_err=yes], [have_com_err=no]) if test $have_com_err = yes; then COM_ERRLIB=-lcom_err LIBS="$COM_ERRLIB $LIBS" fi - AC_CHECK_LIB(crypto, mit_des_cbc_encrypt, have_crypto=yes, have_crypto=no) + AC_CHECK_LIB([crypto], [mit_des_cbc_encrypt], + [have_crypto=yes], + [have_crypto=no]) if test $have_crypto = yes; then CRYPTOLIB=-lcrypto LIBS="$CRYPTOLIB $LIBS" fi - AC_CHECK_LIB(k5crypto, mit_des_cbc_encrypt, have_k5crypto=yes, have_k5crypto=no) + AC_CHECK_LIB([k5crypto], [mit_des_cbc_encrypt], + [have_k5crypto=yes], + [have_k5crypto=no]) if test $have_k5crypto = yes; then CRYPTOLIB=-lk5crypto LIBS="$CRYPTOLIB $LIBS" fi - AC_CHECK_LIB(krb5, krb5_init_context, have_krb5=yes, have_krb5=no) + AC_CHECK_LIB([krb5], [krb5_init_context], [have_krb5=yes], [have_krb5=no]) if test $have_krb5=yes; then KRB5LIB=-lkrb5 LIBS="$KRB5LIB $LIBS" fi dnl FIXME Simplify. Does not match 22 logic, thanks to default_off? if test "${with_kerberos5}" = no; then - AC_CHECK_LIB(des425, des_cbc_encrypt, have_des425=yes, have_des425=no ) + AC_CHECK_LIB([des425], [des_cbc_encrypt], + [have_des425=yes], + [have_des425=no]) if test $have_des425 = yes; then DESLIB=-ldes425 LIBS="$DESLIB $LIBS" else - AC_CHECK_LIB(des, des_cbc_encrypt, have_des=yes, have_des=no) + AC_CHECK_LIB([des], [des_cbc_encrypt], [have_des=yes], [have_des=no]) if test $have_des = yes; then DESLIB=-ldes LIBS="$DESLIB $LIBS" fi fi - AC_CHECK_LIB(krb4, krb_get_cred, have_krb4=yes, have_krb4=no) + AC_CHECK_LIB([krb4], [krb_get_cred], [have_krb4=yes], [have_krb4=no]) if test $have_krb4 = yes; then KRB4LIB=-lkrb4 LIBS="$KRB4LIB $LIBS" else - AC_CHECK_LIB(krb, krb_get_cred, have_krb=yes, have_krb=no) + AC_CHECK_LIB([krb], [krb_get_cred], [have_krb=yes], [have_krb=no]) if test $have_krb = yes; then KRB4LIB=-lkrb LIBS="$KRB4LIB $LIBS" @@ -5164,25 +5254,25 @@ if test "${with_kerberos}" != no; then fi if test "${with_kerberos5}" != no; then - AC_CHECK_HEADERS(krb5.h, - [AC_CHECK_MEMBERS([krb5_error.text, krb5_error.e_text],,, + AC_CHECK_HEADERS([krb5.h], + [AC_CHECK_MEMBERS([krb5_error.text, krb5_error.e_text], [], [], [#include ])]) else - AC_CHECK_HEADERS(krb.h,, - [AC_CHECK_HEADERS(kerberosIV/krb.h,, - [AC_CHECK_HEADERS(kerberos/krb.h)])]) + AC_CHECK_HEADERS([krb.h], [], + [AC_CHECK_HEADERS([kerberosIV/krb.h], [], + [AC_CHECK_HEADERS([kerberos/krb.h])])]) fi - AC_CHECK_HEADERS(com_err.h) + AC_CHECK_HEADERS([com_err.h]) LIBS=$OLD_LIBS fi -AC_SUBST(COM_ERRLIB) -AC_SUBST(CRYPTOLIB) -AC_SUBST(KRB5LIB) -AC_SUBST(DESLIB) -AC_SUBST(KRB4LIB) +AC_SUBST([COM_ERRLIB]) +AC_SUBST([CRYPTOLIB]) +AC_SUBST([KRB5LIB]) +AC_SUBST([DESLIB]) +AC_SUBST([KRB4LIB]) -AC_CHECK_HEADERS(valgrind/valgrind.h) +AC_CHECK_HEADERS([valgrind/valgrind.h]) AC_CHECK_MEMBERS([struct unipair.unicode], [], [], [[#include ]]) @@ -5192,7 +5282,7 @@ AC_FUNC_FORK dnl AC_CHECK_FUNCS_ONCE wouldn’t be right for snprintf, which needs dnl the current CFLAGS etc. -AC_CHECK_FUNCS(snprintf) +AC_CHECK_FUNCS([snprintf]) dnl posix_spawn. The chdir and setsid functionality is relatively dnl recent, so we check for it specifically. @@ -5236,12 +5326,12 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM( CFLAGS="$OLDCFLAGS" LIBS="$OLDLIBS"]) if test "${emacs_cv_links_glib}" = "yes"; then - AC_DEFINE(HAVE_GLIB, 1, [Define to 1 if GLib is linked in.]) + AC_DEFINE([HAVE_GLIB], [1], [Define to 1 if GLib is linked in.]) if test "$HAVE_NS" = no ; then XGSELOBJ=xgselect.o fi fi -AC_SUBST(XGSELOBJ) +AC_SUBST([XGSELOBJ]) dnl Adapted from Haible's version. AC_CACHE_CHECK([for nl_langinfo and CODESET], [emacs_cv_langinfo_codeset], @@ -5251,7 +5341,7 @@ AC_CACHE_CHECK([for nl_langinfo and CODESET], [emacs_cv_langinfo_codeset], [emacs_cv_langinfo_codeset=no]) ]) if test "$emacs_cv_langinfo_codeset" = yes; then - AC_DEFINE([HAVE_LANGINFO_CODESET], 1, + AC_DEFINE([HAVE_LANGINFO_CODESET], [1], [Define if you have and nl_langinfo (CODESET).]) AC_CACHE_CHECK([for nl_langinfo and _NL_PAPER_WIDTH], @@ -5262,7 +5352,7 @@ if test "$emacs_cv_langinfo_codeset" = yes; then [emacs_cv_langinfo__nl_paper_width=no]) ]) if test "$emacs_cv_langinfo__nl_paper_width" = yes; then - AC_DEFINE([HAVE_LANGINFO__NL_PAPER_WIDTH], 1, + AC_DEFINE([HAVE_LANGINFO__NL_PAPER_WIDTH], [1], [Define if you have and nl_langinfo (_NL_PAPER_WIDTH).]) fi fi @@ -5275,15 +5365,17 @@ dnl The following looks like a useful start. dnl dnl AC_SYS_POSIX_TERMIOS dnl if test $ac_cv_sys_posix_termios = yes; then -dnl AC_DEFINE(HAVE_TERMIOS, 1, [Define to 1 if you have POSIX-style functions -dnl and macros for terminal control.]) -dnl AC_DEFINE(HAVE_TCATTR, 1, [Define to 1 if you have tcgetattr and tcsetattr.]) +dnl AC_DEFINE([HAVE_TERMIOS], [1], +dnl [Define to 1 if you have POSIX-style +dnl functions and macros for terminal control.]) +dnl AC_DEFINE([HAVE_TCATTR], [1], +dnl [Define to 1 if you have tcgetattr and tcsetattr.]) dnl fi dnl Turned on June 1996 supposing nobody will mind it. dnl MinGW emulates passwd database, so this feature doesn't make sense there. if test "${opsys}" != "mingw32"; then - AC_DEFINE(AMPERSAND_FULL_NAME, 1, [Define to use the convention that & + AC_DEFINE([AMPERSAND_FULL_NAME], [1], [Define to use the convention that & in the full name stands for the login id.]) fi @@ -5291,22 +5383,23 @@ dnl Everybody supports this, except MS. dnl Seems like the kind of thing we should be testing for, though. ## Note: PTYs are broken on darwin <6. Use at your own risk. if test "${opsys}" != "mingw32"; then - AC_DEFINE(HAVE_PTYS, 1, [Define if the system supports pty devices.]) + AC_DEFINE([HAVE_PTYS], [1], [Define if the system supports pty devices.]) fi dnl Everybody supports this, except MS-DOS. dnl Seems like the kind of thing we should be testing for, though. -AC_DEFINE(HAVE_SOCKETS, 1, [Define if the system supports +AC_DEFINE([HAVE_SOCKETS], [1], [Define if the system supports 4.2-compatible sockets.]) -AH_TEMPLATE(INTERNAL_TERMINAL, [This is substituted when $TERM is "internal".]) +AH_TEMPLATE([INTERNAL_TERMINAL], + [This is substituted when $TERM is "internal".]) -AH_TEMPLATE(NULL_DEVICE, [Name of the file to open to get +AH_TEMPLATE([NULL_DEVICE], [Name of the file to open to get a null file, or a data sink.]) if test "${opsys}" = "mingw32"; then - AC_DEFINE(NULL_DEVICE, ["NUL:"]) + AC_DEFINE([NULL_DEVICE], ["NUL:"]) else - AC_DEFINE(NULL_DEVICE, ["/dev/null"]) + AC_DEFINE([NULL_DEVICE], ["/dev/null"]) fi if test "${opsys}" = "mingw32"; then @@ -5314,7 +5407,8 @@ if test "${opsys}" = "mingw32"; then else SEPCHAR=':' fi -AC_DEFINE_UNQUOTED(SEPCHAR, ['$SEPCHAR'], [Character that separates PATH elements.]) +AC_DEFINE_UNQUOTED([SEPCHAR], ['$SEPCHAR'], + [Character that separates PATH elements.]) dnl This is for MinGW, and is used in test/Makefile.in. dnl The MSYS Bash has heuristics for replacing ':' with ';' when it dnl decides that a command-line argument to be passed to a MinGW program @@ -5324,34 +5418,35 @@ dnl sees a colon-separated list of file names; e.g. ":." is left alone, dnl which breaks in-tree builds. So we do this manually instead. dnl Note that we cannot rely on PATH_SEPARATOR, as that one will always dnl be computed as ':' in MSYS Bash. -AC_SUBST(SEPCHAR) +AC_SUBST([SEPCHAR]) dnl Everybody supports this, except MS-DOS. -AC_DEFINE(subprocesses, 1, [Define to enable asynchronous subprocesses.]) +AC_DEFINE([subprocesses], [1], [Define to enable asynchronous subprocesses.]) -AC_DEFINE(USER_FULL_NAME, [pw->pw_gecos], [How to get a user's full name.]) +AC_DEFINE([USER_FULL_NAME], [pw->pw_gecos], [How to get a user's full name.]) -AC_DEFINE(DIRECTORY_SEP, ['/'], +AC_DEFINE([DIRECTORY_SEP], ['/'], [Character that separates directories in a file name.]) if test "${opsys}" = "mingw32"; then - AC_DEFINE(IS_DEVICE_SEP(_c_), [((_c_) == ':')], + AC_DEFINE([IS_DEVICE_SEP(_c_)], [((_c_) == ':')], [Returns true if character is a device separator.]) - AC_DEFINE(IS_DIRECTORY_SEP(_c_), [((_c_) == '/' || (_c_) == '\\')], + AC_DEFINE([IS_DIRECTORY_SEP(_c_)], [((_c_) == '/' || (_c_) == '\\')], [Returns true if character is a directory separator.]) - AC_DEFINE(IS_ANY_SEP(_c_), [(IS_DIRECTORY_SEP (_c_) || IS_DEVICE_SEP(_c_))], + AC_DEFINE([IS_ANY_SEP(_c_)], + [(IS_DIRECTORY_SEP (_c_) || IS_DEVICE_SEP (_c_))], [Returns true if character is any form of separator.]) else - AC_DEFINE(IS_DEVICE_SEP(_c_), 0, + AC_DEFINE([IS_DEVICE_SEP(_c_)], 0, [Returns true if character is a device separator.]) - AC_DEFINE(IS_DIRECTORY_SEP(_c_), [((_c_) == DIRECTORY_SEP)], + AC_DEFINE([IS_DIRECTORY_SEP(_c_)], [((_c_) == DIRECTORY_SEP)], [Returns true if character is a directory separator.]) - AC_DEFINE(IS_ANY_SEP(_c_), [(IS_DIRECTORY_SEP (_c_))], + AC_DEFINE([IS_ANY_SEP(_c_)], [(IS_DIRECTORY_SEP (_c_))], [Returns true if character is any form of separator.]) fi @@ -5376,7 +5471,7 @@ if test "$USE_X_TOOLKIT" != "none"; then [[#include #include ]], [[_XEditResCheckMessages (0, 0, 0, 0);]])], - [AC_DEFINE([X_TOOLKIT_EDITRES], 1, + [AC_DEFINE([X_TOOLKIT_EDITRES], [1], [Define to 1 if we should use XEditRes.])]) LIBS=$OLDLIBS fi @@ -5388,7 +5483,7 @@ case $opsys in dnl instead, there's a system variable _sys_nsig. Unfortunately, we dnl need the constant to dimension an array. So wire in the appropriate dnl value here. - AC_DEFINE(NSIG_MINIMUM, 32, [Minimum value of NSIG.]) + AC_DEFINE([NSIG_MINIMUM], [32], [Minimum value of NSIG.]) ;; esac @@ -5421,7 +5516,7 @@ case $opsys in dnl of this file, so that we do not check for get_current_dir_name dnl on AIX. But that might be fragile if something else ends dnl up testing for get_current_dir_name as a dependency. - AC_DEFINE(BROKEN_GET_CURRENT_DIR_NAME, 1, [Define if + AC_DEFINE([BROKEN_GET_CURRENT_DIR_NAME], [1], [Define if get_current_dir_name should not be used.]) ;; @@ -5439,7 +5534,7 @@ case $opsys in dnl successfully after processing (for example with CRs added if the dnl terminal is set up that way which it is here). The same bytes will dnl be seen again in a later read(2), without the CRs. - AC_DEFINE(BROKEN_PTY_READ_AFTER_EAGAIN, 1, [Define on FreeBSD to + AC_DEFINE([BROKEN_PTY_READ_AFTER_EAGAIN], [1], [Define on FreeBSD to work around an issue when reading from a PTY.]) ;; esac @@ -5447,13 +5542,13 @@ esac case $opsys in gnu-* | solaris ) dnl FIXME Can't we test if this exists (eg /proc/$$)? - AC_DEFINE(HAVE_PROCFS, 1, [Define if you have the /proc filesystem.]) + AC_DEFINE([HAVE_PROCFS], [1], [Define if you have the /proc filesystem.]) ;; esac case $opsys in darwin | dragonfly | freebsd | netbsd | openbsd ) - AC_DEFINE(DONT_REOPEN_PTY, 1, [Define if process.c does not need to + AC_DEFINE([DONT_REOPEN_PTY], [1], [Define if process.c does not need to close a pty to make it a controlling terminal (it is already a controlling terminal of the subprocess, because we did ioctl TIOCSCTTY).]) ;; @@ -5466,7 +5561,7 @@ case $opsys in esac dnl Used in sound.c -AC_DEFINE_UNQUOTED(DEFAULT_SOUND_DEVICE, "$sound_device", +AC_DEFINE_UNQUOTED([DEFAULT_SOUND_DEVICE], ["$sound_device"], [Name of the default sound device.]) @@ -5493,7 +5588,7 @@ dnl to read the input and send it to the true Emacs process dnl through a pipe. case $opsys in darwin | gnu-linux | gnu-kfreebsd) - AC_DEFINE(INTERRUPT_INPUT, 1, [Define to read input using SIGIO.]) + AC_DEFINE([INTERRUPT_INPUT], [1], [Define to read input using SIGIO.]) ;; esac @@ -5505,73 +5600,78 @@ dnl NARROWPROTO, we will see the wrong function prototypes for X functions dnl taking float or double parameters. case $opsys in cygwin|gnu|gnu-linux|gnu-kfreebsd|freebsd|netbsd|openbsd) - AC_DEFINE(NARROWPROTO, 1, [Define if system's imake configuration + AC_DEFINE([NARROWPROTO], [1], [Define if system's imake configuration file defines 'NeedWidePrototypes' as 'NO'.]) ;; esac dnl Used in process.c, this must be a loop, even if it only runs once. -AH_TEMPLATE(PTY_ITERATION, [How to iterate over PTYs.]) +AH_TEMPLATE([PTY_ITERATION], [How to iterate over PTYs.]) dnl Only used if !PTY_ITERATION. Iterate from FIRST_PTY_LETTER to z, dnl trying suffixes 0-16. -AH_TEMPLATE(FIRST_PTY_LETTER, [Letter to use in finding device name of +AH_TEMPLATE([FIRST_PTY_LETTER], [Letter to use in finding device name of first PTY, if PTYs are supported.]) -AH_TEMPLATE(PTY_OPEN, [How to open a PTY, if non-standard.]) -AH_TEMPLATE(PTY_NAME_SPRINTF, [How to get the device name of the control +AH_TEMPLATE([PTY_OPEN], [How to open a PTY, if non-standard.]) +AH_TEMPLATE([PTY_NAME_SPRINTF], [How to get the device name of the control end of a PTY, if non-standard.]) -AH_TEMPLATE(PTY_TTY_NAME_SPRINTF, [How to get device name of the tty +AH_TEMPLATE([PTY_TTY_NAME_SPRINTF], [How to get device name of the tty end of a PTY, if non-standard.]) case $opsys in aix4-2 ) - AC_DEFINE(PTY_ITERATION, [int c; for (c = 0; !c ; c++)]) + AC_DEFINE([PTY_ITERATION], [int c; for (c = 0; !c ; c++)]) dnl You allocate a pty by opening /dev/ptc to get the master side. dnl To get the name of the slave side, you just ttyname() the master side. - AC_DEFINE(PTY_NAME_SPRINTF, [strcpy (pty_name, "/dev/ptc");]) - AC_DEFINE(PTY_TTY_NAME_SPRINTF, [strcpy (pty_name, ttyname (fd));]) + AC_DEFINE([PTY_NAME_SPRINTF], [strcpy (pty_name, "/dev/ptc");]) + AC_DEFINE([PTY_TTY_NAME_SPRINTF], [strcpy (pty_name, ttyname (fd));]) ;; cygwin ) - AC_DEFINE(PTY_ITERATION, [int i; for (i = 0; i < 1; i++)]) + AC_DEFINE([PTY_ITERATION], [int i; for (i = 0; i < 1; i++)]) dnl multi-line AC_DEFINEs are hard. :( - AC_DEFINE(PTY_OPEN, [ do { int dummy; sigset_t blocked, procmask; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); if (-1 == openpty (&fd, &dummy, pty_name, 0, 0)) fd = -1; pthread_sigmask (SIG_SETMASK, &procmask, 0); if (fd >= 0) emacs_close (dummy); } while (false)]) - AC_DEFINE(PTY_NAME_SPRINTF, []) - AC_DEFINE(PTY_TTY_NAME_SPRINTF, []) + AC_DEFINE([PTY_OPEN], + [ do { int dummy; sigset_t blocked, procmask; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, &procmask); if (-1 == openpty (&fd, &dummy, pty_name, 0, 0)) fd = -1; pthread_sigmask (SIG_SETMASK, &procmask, 0); if (fd >= 0) emacs_close (dummy); } while (false)]) + AC_DEFINE([PTY_NAME_SPRINTF], []) + AC_DEFINE([PTY_TTY_NAME_SPRINTF], []) ;; gnu | qnxnto ) - AC_DEFINE(FIRST_PTY_LETTER, ['p']) + AC_DEFINE([FIRST_PTY_LETTER], ['p']) ;; gnu-linux | gnu-kfreebsd | dragonfly | freebsd | openbsd | netbsd | darwin | nacl ) dnl if HAVE_GRANTPT if test "x$ac_cv_func_grantpt" = xyes; then - AC_DEFINE(UNIX98_PTYS, 1, [Define if the system has Unix98 PTYs.]) - AC_DEFINE(PTY_ITERATION, [int i; for (i = 0; i < 1; i++)]) + AC_DEFINE([UNIX98_PTYS], [1], [Define if the system has Unix98 PTYs.]) + AC_DEFINE([PTY_ITERATION], [int i; for (i = 0; i < 1; i++)]) dnl Note that grantpt and unlockpt may fork. We must block SIGCHLD dnl to prevent sigchld_handler from intercepting the child's death. - AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptyname = 0; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); if (grantpt (fd) != -1 && unlockpt (fd) != -1) ptyname = ptsname(fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (!ptyname) { emacs_close (fd); return -1; } snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }]) + AC_DEFINE([PTY_TTY_NAME_SPRINTF], + [{ char *ptyname = 0; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); if (grantpt (fd) != -1 && unlockpt (fd) != -1) ptyname = ptsname(fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (!ptyname) { emacs_close (fd); return -1; } snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }]) dnl if HAVE_POSIX_OPENPT if test "x$ac_cv_func_posix_openpt" = xyes; then - AC_DEFINE(PTY_OPEN, [do { fd = posix_openpt (O_RDWR | O_CLOEXEC | O_NOCTTY); if (fd < 0 && errno == EINVAL) fd = posix_openpt (O_RDWR | O_NOCTTY); } while (false)]) - AC_DEFINE(PTY_NAME_SPRINTF, []) + AC_DEFINE([PTY_OPEN], + [do { fd = posix_openpt (O_RDWR | O_CLOEXEC | O_NOCTTY); if (fd < 0 && errno == EINVAL) fd = posix_openpt (O_RDWR | O_NOCTTY); } while (false)]) + AC_DEFINE([PTY_NAME_SPRINTF], []) dnl if HAVE_GETPT elif test "x$ac_cv_func_getpt" = xyes; then - AC_DEFINE(PTY_OPEN, [fd = getpt ()]) - AC_DEFINE(PTY_NAME_SPRINTF, []) + AC_DEFINE([PTY_OPEN], [fd = getpt ()]) + AC_DEFINE([PTY_NAME_SPRINTF], []) else - AC_DEFINE(PTY_NAME_SPRINTF, [strcpy (pty_name, "/dev/ptmx");]) + AC_DEFINE([PTY_NAME_SPRINTF], [strcpy (pty_name, "/dev/ptmx");]) fi else - AC_DEFINE(FIRST_PTY_LETTER, ['p']) + AC_DEFINE([FIRST_PTY_LETTER], ['p']) fi ;; hpux*) - AC_DEFINE(FIRST_PTY_LETTER, ['p']) - AC_DEFINE(PTY_NAME_SPRINTF, [sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);]) - AC_DEFINE(PTY_TTY_NAME_SPRINTF, [sprintf (pty_name, "/dev/pty/tty%c%x", c, i);]) + AC_DEFINE([FIRST_PTY_LETTER], ['p']) + AC_DEFINE([PTY_NAME_SPRINTF], + [sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);]) + AC_DEFINE([PTY_TTY_NAME_SPRINTF], + [sprintf (pty_name, "/dev/pty/tty%c%x", c, i);]) ;; solaris ) @@ -5579,22 +5679,25 @@ case $opsys in dnl O_CLOEXEC when opening the pty, and keep the SIGCHLD handler dnl from intercepting that death. If any child but grantpt's should die dnl within, it should be caught after sigrelse(2). - AC_DEFINE(PTY_OPEN, [fd = open (pty_name, O_RDWR | O_NONBLOCK)]) - AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1 || unlockpt (fd) == -1 || !(ptyname = ptsname (fd))) { emacs_close (fd); return -1; } snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }]) + AC_DEFINE([PTY_OPEN], [fd = open (pty_name, O_RDWR | O_NONBLOCK)]) + AC_DEFINE([PTY_TTY_NAME_SPRINTF], + [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1 || unlockpt (fd) == -1 || !(ptyname = ptsname (fd))) { emacs_close (fd); return -1; } snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }]) ;; unixware ) dnl Comments are as per solaris. - AC_DEFINE(PTY_OPEN, [fd = open (pty_name, O_RDWR | O_NONBLOCK)]) - AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }]) + AC_DEFINE([PTY_OPEN], [fd = open (pty_name, O_RDWR | O_NONBLOCK)]) + AC_DEFINE([PTY_TTY_NAME_SPRINTF], + [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }]) ;; haiku*) - AC_DEFINE(FIRST_PTY_LETTER, ['s']) - AC_DEFINE(PTY_NAME_SPRINTF, []) + AC_DEFINE([FIRST_PTY_LETTER], ['s']) + AC_DEFINE([PTY_NAME_SPRINTF], []) dnl on Haiku pty names aren't distinctive, thus the use of posix_openpt - AC_DEFINE(PTY_OPEN, [fd = posix_openpt (O_RDWR | O_NONBLOCK)]) - AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }]) + AC_DEFINE([PTY_OPEN], [fd = posix_openpt (O_RDWR | O_NONBLOCK)]) + AC_DEFINE([PTY_TTY_NAME_SPRINTF], + [{ char *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }]) ;; esac @@ -5603,21 +5706,22 @@ case $opsys in solaris | unixware ) dnl This change means that we don't loop through allocate_pty too dnl many times in the (rare) event of a failure. - AC_DEFINE(FIRST_PTY_LETTER, ['z']) - AC_DEFINE(PTY_NAME_SPRINTF, [strcpy (pty_name, "/dev/ptmx");]) + AC_DEFINE([FIRST_PTY_LETTER], ['z']) + AC_DEFINE([PTY_NAME_SPRINTF], [strcpy (pty_name, "/dev/ptmx");]) dnl Push various streams modules onto a PTY channel. Used in process.c. - AC_DEFINE(SETUP_SLAVE_PTY, [if (ioctl (std_in, I_PUSH, "ptem") == -1) fatal ("ioctl I_PUSH ptem"); if (ioctl (std_in, I_PUSH, "ldterm") == -1) fatal ("ioctl I_PUSH ldterm"); if (ioctl (std_in, I_PUSH, "ttcompat") == -1) fatal ("ioctl I_PUSH ttcompat");], [How to set up a slave PTY, if needed.]) + AC_DEFINE([SETUP_SLAVE_PTY], + [if (ioctl (std_in, I_PUSH, "ptem") == -1) fatal ("ioctl I_PUSH ptem"); if (ioctl (std_in, I_PUSH, "ldterm") == -1) fatal ("ioctl I_PUSH ldterm"); if (ioctl (std_in, I_PUSH, "ttcompat") == -1) fatal ("ioctl I_PUSH ttcompat");], [How to set up a slave PTY, if needed.]) ;; esac -AH_TEMPLATE(SIGNALS_VIA_CHARACTERS, [Make process_send_signal work by +AH_TEMPLATE([SIGNALS_VIA_CHARACTERS], [Make process_send_signal work by "typing" a signal character on the pty.]) case $opsys in dnl Perry Smith says this is correct for AIX. aix4-2 | cygwin | gnu | dragonfly | freebsd | netbsd | openbsd | darwin ) - AC_DEFINE(SIGNALS_VIA_CHARACTERS, 1) + AC_DEFINE([SIGNALS_VIA_CHARACTERS], [1]) ;; dnl 21 Jun 06: Eric Hanchrow says this works. @@ -5630,35 +5734,41 @@ case $opsys in #if LINUX_VERSION_CODE < 0x20400 # error "Linux version too old" #endif - ]], [[]])], emacs_cv_signals_via_chars=yes, emacs_cv_signals_via_chars=no)]) + ]], [[]])], + [emacs_cv_signals_via_chars=yes], + [emacs_cv_signals_via_chars=no])]) - test "$emacs_cv_signals_via_chars" = yes && AC_DEFINE(SIGNALS_VIA_CHARACTERS, 1) + test "$emacs_cv_signals_via_chars" = yes && + AC_DEFINE([SIGNALS_VIA_CHARACTERS], [1]) ;; esac -AH_TEMPLATE(TAB3, [Undocumented.]) +AH_TEMPLATE([TAB3], [Undocumented.]) case $opsys in - darwin) AC_DEFINE(TAB3, OXTABS) ;; + darwin) AC_DEFINE([TAB3], [OXTABS]) ;; gnu | dragonfly | freebsd | netbsd | openbsd ) - AC_DEFINE(TABDLY, OXTABS, [Undocumented.]) - AC_DEFINE(TAB3, OXTABS) + AC_DEFINE([TABDLY], [OXTABS], [Undocumented.]) + AC_DEFINE([TAB3], [OXTABS]) ;; gnu-linux | gnu-kfreebsd ) - AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[ + AC_PREPROC_IFELSE( + [AC_LANG_PROGRAM( + [[ #ifndef __ia64__ # error "not ia64" #endif - ]], [[]])], AC_DEFINE(GC_MARK_SECONDARY_STACK(), + ]], [[]])], + [AC_DEFINE([GC_MARK_SECONDARY_STACK()], [do { extern void *__libc_ia64_register_backing_store_base; __builtin_ia64_flushrs (); mark_memory (__libc_ia64_register_backing_store_base, __builtin_ia64_bsp ());} while (false)], - [Mark a secondary stack, like the register stack on the ia64.]), []) + [Mark a secondary stack, like the register stack on the ia64.])], []) ;; hpux*) - AC_DEFINE(RUN_TIME_REMAP, 1, [Define if emacs.c needs to call + AC_DEFINE([RUN_TIME_REMAP], [1], [Define if emacs.c needs to call run_time_remap; for HPUX.]) ;; esac @@ -5666,7 +5776,7 @@ esac dnl This won't be used automatically yet. We also need to know, at least, dnl that the stack is continuous. -AH_TEMPLATE(GC_SETJMP_WORKS, [Define if setjmp is known to save all +AH_TEMPLATE([GC_SETJMP_WORKS], [Define if setjmp is known to save all registers relevant for conservative garbage collection in the jmp_buf.]) @@ -5686,18 +5796,18 @@ case $opsys in #else # error "setjmp not known to work on this arch" #endif - ]], [[]])], AC_DEFINE(GC_SETJMP_WORKS, 1)) + ]], [[]])], [AC_DEFINE([GC_SETJMP_WORKS], [1])]) ;; esac if test x$GCC = xyes; then dnl GC_SETJMP_WORKS is nearly always appropriate for GCC. - AC_DEFINE(GC_SETJMP_WORKS, 1) + AC_DEFINE([GC_SETJMP_WORKS], [1]) else case $opsys in aix* | dragonfly | freebsd | netbsd | openbsd | solaris ) - AC_DEFINE(GC_SETJMP_WORKS, 1) + AC_DEFINE([GC_SETJMP_WORKS], [1]) ;; esac fi dnl GCC? @@ -5717,7 +5827,7 @@ AC_CACHE_CHECK([for _setjmp], [emacs_cv_func__setjmp], [emacs_cv_func__setjmp=yes], [emacs_cv_func__setjmp=no])]) if test $emacs_cv_func__setjmp = yes; then - AC_DEFINE([HAVE__SETJMP], 1, [Define to 1 if _setjmp and _longjmp work.]) + AC_DEFINE([HAVE__SETJMP], [1], [Define to 1 if _setjmp and _longjmp work.]) fi # We need to preserve signal mask to handle C stack overflows. @@ -5732,13 +5842,13 @@ AC_CACHE_CHECK([for sigsetjmp], [emacs_cv_func_sigsetjmp], [emacs_cv_func_sigsetjmp=yes], [emacs_cv_func_sigsetjmp=no])]) if test $emacs_cv_func_sigsetjmp = yes; then - AC_DEFINE([HAVE_SIGSETJMP], 1, + AC_DEFINE([HAVE_SIGSETJMP], [1], [Define to 1 if sigsetjmp and siglongjmp work.]) fi case $emacs_cv_func_sigsetjmp,$emacs_cv_alternate_stack,$opsys in yes,yes,* | *,*,mingw32) - AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], 1, + AC_DEFINE([HAVE_STACK_OVERFLOW_HANDLING], [1], [Define to 1 if C stack overflow can be handled in some cases.]);; esac @@ -5747,7 +5857,7 @@ case $opsys in dnl TIOCGPGRP is broken in SysVr4, so we can't send signals to PTY dnl subprocesses the usual way. But TIOCSIGNAL does work for PTYs, dnl and this is all we need. - AC_DEFINE(TIOCSIGSEND, TIOCSIGNAL, [Some platforms redefine this.]) + AC_DEFINE([TIOCSIGSEND], [TIOCSIGNAL], [Some platforms redefine this.]) ;; esac @@ -5755,7 +5865,7 @@ esac case $opsys in hpux* | solaris ) dnl Used in xfaces.c. - AC_DEFINE(XOS_NEEDS_TIME_H, 1, [Compensate for a bug in Xos.h on + AC_DEFINE([XOS_NEEDS_TIME_H], [1], [Compensate for a bug in Xos.h on some systems, where it requires time.h.]) ;; esac @@ -5763,64 +5873,67 @@ esac dnl Define symbols to identify the version of Unix this is. dnl Define all the symbols that apply correctly. -AH_TEMPLATE(DOS_NT, [Define if the system is MS DOS or MS Windows.]) -AH_TEMPLATE(MSDOS, [Define if the system is MS DOS.]) -AH_TEMPLATE(USG, [Define if the system is compatible with System III.]) -AH_TEMPLATE(USG5_4, [Define if the system is compatible with System V Release 4.]) +AH_TEMPLATE([DOS_NT], [Define if the system is MS DOS or MS Windows.]) +AH_TEMPLATE([MSDOS], [Define if the system is MS DOS.]) +AH_TEMPLATE([USG], [Define if the system is compatible with System III.]) +AH_TEMPLATE([USG5_4], + [Define if the system is compatible with System V Release 4.]) case $opsys in aix4-2) - AC_DEFINE(USG, []) + AC_DEFINE([USG], []) dnl This symbol should be defined on AIX Version 3 ??????? AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[ #ifndef _AIX # error "_AIX not defined" #endif - ]], [[]])], [], AC_DEFINE(_AIX, [], [Define if the system is AIX.])) + ]], [[]])], [], [AC_DEFINE([_AIX], [], [Define if the system is AIX.])]) ;; cygwin) - AC_DEFINE(CYGWIN, 1, [Define if the system is Cygwin.]) + AC_DEFINE([CYGWIN], [1], [Define if the system is Cygwin.]) ;; darwin) dnl Not __APPLE__, as this may not be defined on non-macOS Darwin. dnl Not DARWIN, because Panther and lower CoreFoundation.h use DARWIN to dnl distinguish macOS from pure Darwin. - AC_DEFINE(DARWIN_OS, [], [Define if the system is Darwin.]) + AC_DEFINE([DARWIN_OS], [], [Define if the system is Darwin.]) ;; gnu-linux | gnu-kfreebsd ) - AC_DEFINE(USG, []) - AC_DEFINE(GNU_LINUX, [], [Define if ths system is compatible with GNU/Linux.]) + AC_DEFINE([USG], []) + AC_DEFINE([GNU_LINUX], [], + [Define if ths system is compatible with GNU/Linux.]) ;; hpux*) - AC_DEFINE(USG, []) - AC_DEFINE(HPUX, [], [Define if the system is HPUX.]) + AC_DEFINE([USG], []) + AC_DEFINE([HPUX], [], [Define if the system is HPUX.]) ;; mingw32) - AC_DEFINE(DOS_NT, []) - AC_DEFINE(WINDOWSNT, 1, [Define if compiling for native MS Windows.]) + AC_DEFINE([DOS_NT], []) + AC_DEFINE([WINDOWSNT], [1], [Define if compiling for native MS Windows.]) if test "x$ac_enable_checking" != "x" ; then - AC_DEFINE(EMACSDEBUG, 1, [Define to 1 to enable w32 debug facilities.]) + AC_DEFINE([EMACSDEBUG], [1], + [Define to 1 to enable w32 debug facilities.]) fi ;; solaris) - AC_DEFINE(USG, []) - AC_DEFINE(USG5_4, []) - AC_DEFINE(SOLARIS2, [], [Define if the system is Solaris.]) + AC_DEFINE([USG], []) + AC_DEFINE([USG5_4], []) + AC_DEFINE([SOLARIS2], [], [Define if the system is Solaris.]) ;; unixware) - AC_DEFINE(USG, []) - AC_DEFINE(USG5_4, []) + AC_DEFINE([USG], []) + AC_DEFINE([USG5_4], []) ;; haiku) - AC_DEFINE(HAIKU, [], [Define if the system is Haiku.]) + AC_DEFINE([HAIKU], [], [Define if the system is Haiku.]) ;; esac @@ -5901,13 +6014,13 @@ case $opsys in hpux11) dnl It works to open the pty's tty in the parent (Emacs), then dnl close and reopen it in the child. - AC_DEFINE(USG_SUBTTY_WORKS, 1, [Define for USG systems where it + AC_DEFINE([USG_SUBTTY_WORKS], [1], [Define for USG systems where it works to open a pty's tty in the parent process, then close and reopen it in the child.]) ;; solaris) - AC_DEFINE(_STRUCTURED_PROC, 1, [Needed for system_process_attributes + AC_DEFINE([_STRUCTURED_PROC], [1], [Needed for system_process_attributes on Solaris.]) ;; esac @@ -5930,72 +6043,72 @@ fi version=$PACKAGE_VERSION copyright="Copyright (C) 2022 Free Software Foundation, Inc." -AC_DEFINE_UNQUOTED(COPYRIGHT, ["$copyright"], +AC_DEFINE_UNQUOTED([COPYRIGHT], ["$copyright"], [Short copyright string for this version of Emacs.]) -AC_SUBST(copyright) +AC_SUBST([copyright]) ### Specify what sort of things we'll be editing into Makefile and config.h. ### Use configuration here uncanonicalized to avoid exceeding size limits. -AC_SUBST(version) -AC_SUBST(configuration) +AC_SUBST([version]) +AC_SUBST([configuration]) ## Unused? -AC_SUBST(canonical) -AC_SUBST(srcdir) -AC_SUBST(prefix) -AC_SUBST(exec_prefix) -AC_SUBST(bindir) -AC_SUBST(datadir) -AC_SUBST(gsettingsschemadir) -AC_SUBST(sharedstatedir) -AC_SUBST(libexecdir) -AC_SUBST(mandir) -AC_SUBST(infodir) -AC_SUBST(lispdirrel) -AC_SUBST(lispdir) -AC_SUBST(standardlisppath) -AC_SUBST(locallisppath) -AC_SUBST(lisppath) -AC_SUBST(x_default_search_path) -AC_SUBST(etcdir) -AC_SUBST(archlibdir) -AC_SUBST(etcdocdir) -AC_SUBST(bitmapdir) -AC_SUBST(gamedir) -AC_SUBST(gameuser) -AC_SUBST(gamegroup) +AC_SUBST([canonical]) +AC_SUBST([srcdir]) +AC_SUBST([prefix]) +AC_SUBST([exec_prefix]) +AC_SUBST([bindir]) +AC_SUBST([datadir]) +AC_SUBST([gsettingsschemadir]) +AC_SUBST([sharedstatedir]) +AC_SUBST([libexecdir]) +AC_SUBST([mandir]) +AC_SUBST([infodir]) +AC_SUBST([lispdirrel]) +AC_SUBST([lispdir]) +AC_SUBST([standardlisppath]) +AC_SUBST([locallisppath]) +AC_SUBST([lisppath]) +AC_SUBST([x_default_search_path]) +AC_SUBST([etcdir]) +AC_SUBST([archlibdir]) +AC_SUBST([etcdocdir]) +AC_SUBST([bitmapdir]) +AC_SUBST([gamedir]) +AC_SUBST([gameuser]) +AC_SUBST([gamegroup]) ## FIXME? Nothing uses @LD_SWITCH_X_SITE@. ## src/Makefile.in did add LD_SWITCH_X_SITE (as a cpp define) to the ## end of LIBX_BASE, but nothing ever set it. -AC_SUBST(LD_SWITCH_X_SITE) -AC_SUBST(C_SWITCH_X_SITE) -AC_SUBST(GNUSTEP_CFLAGS) -AC_SUBST(CFLAGS) +AC_SUBST([LD_SWITCH_X_SITE]) +AC_SUBST([C_SWITCH_X_SITE]) +AC_SUBST([GNUSTEP_CFLAGS]) +AC_SUBST([CFLAGS]) ## Used in lwlib/Makefile.in. -AC_SUBST(X_TOOLKIT_TYPE) -AC_SUBST(ns_appdir) -AC_SUBST(ns_appbindir) -AC_SUBST(ns_applibexecdir) -AC_SUBST(ns_applibdir) -AC_SUBST(ns_appresdir) -AC_SUBST(ns_appsrc) -AC_SUBST(GNU_OBJC_CFLAGS) -AC_SUBST(OTHER_FILES) +AC_SUBST([X_TOOLKIT_TYPE]) +AC_SUBST([ns_appdir]) +AC_SUBST([ns_appbindir]) +AC_SUBST([ns_applibexecdir]) +AC_SUBST([ns_applibdir]) +AC_SUBST([ns_appresdir]) +AC_SUBST([ns_appsrc]) +AC_SUBST([GNU_OBJC_CFLAGS]) +AC_SUBST([OTHER_FILES]) if test -n "${term_header}"; then - AC_DEFINE_UNQUOTED(TERM_HEADER, "${term_header}", + AC_DEFINE_UNQUOTED([TERM_HEADER], ["${term_header}"], [Define to the header for the built-in window system.]) fi -AC_DEFINE_UNQUOTED(EMACS_CONFIGURATION, "${canonical}", +AC_DEFINE_UNQUOTED([EMACS_CONFIGURATION], ["${canonical}"], [Define to the canonical Emacs configuration name.]) -AC_DEFINE_UNQUOTED(EMACS_CONFIG_OPTIONS, "${emacs_config_options}", +AC_DEFINE_UNQUOTED([EMACS_CONFIG_OPTIONS], "${emacs_config_options}", [Define to the options passed to configure.]) XMENU_OBJ= XOBJ= FONT_OBJ= if test "${HAVE_X_WINDOWS}" = "yes" ; then - AC_DEFINE(HAVE_X_WINDOWS, 1, + AC_DEFINE([HAVE_X_WINDOWS], [1], [Define to 1 if you want to use the X window system.]) XMENU_OBJ=xmenu.o XOBJ="xterm.o xfns.o xselect.o xrdb.o xsmfns.o xsettings.o" @@ -6022,20 +6135,20 @@ fi if test "${HAVE_HARFBUZZ}" = "yes" ; then FONT_OBJ="$FONT_OBJ hbfont.o" fi -AC_SUBST(FONT_OBJ) -AC_SUBST(XMENU_OBJ) -AC_SUBST(XOBJ) -AC_SUBST(FONT_OBJ) +AC_SUBST([FONT_OBJ]) +AC_SUBST([XMENU_OBJ]) +AC_SUBST([XOBJ]) +AC_SUBST([FONT_OBJ]) WIDGET_OBJ= MOTIF_LIBW= if test "${USE_X_TOOLKIT}" != "none" ; then WIDGET_OBJ=widget.o - AC_DEFINE(USE_X_TOOLKIT, 1, [Define to 1 if using an X toolkit.]) + AC_DEFINE([USE_X_TOOLKIT], [1], [Define to 1 if using an X toolkit.]) if test "${USE_X_TOOLKIT}" = "LUCID"; then - AC_DEFINE(USE_LUCID, 1, [Define to 1 if using the Lucid X toolkit.]) + AC_DEFINE([USE_LUCID], [1], [Define to 1 if using the Lucid X toolkit.]) elif test "${USE_X_TOOLKIT}" = "MOTIF"; then - AC_DEFINE(USE_MOTIF, 1, [Define to 1 if using the Motif X toolkit.]) + AC_DEFINE([USE_MOTIF], [1], [Define to 1 if using the Motif X toolkit.]) MOTIF_LIBW=-lXm case "$opsys" in gnu-linux) @@ -6057,7 +6170,7 @@ if test "${USE_X_TOOLKIT}" != "none" ; then MOTIF_LIBW="$MOTIF_LIBW $LIBXP" fi fi -AC_SUBST(WIDGET_OBJ) +AC_SUBST([WIDGET_OBJ]) TOOLKIT_LIBW= case "$USE_X_TOOLKIT" in @@ -6068,7 +6181,7 @@ esac if test "$HAVE_XWIDGETS" = "yes"; then TOOLKIT_LIBW="$TOOLKIT_LIBW -lXcomposite" fi -AC_SUBST(TOOLKIT_LIBW) +AC_SUBST([TOOLKIT_LIBW]) if test "${opsys}" != "mingw32"; then if test "$USE_X_TOOLKIT" = "none"; then @@ -6077,16 +6190,16 @@ if test "${opsys}" != "mingw32"; then LIBXT_OTHER="\$(LIBXMU) -lXt \$(LIBXTR6) -lXext" fi fi -AC_SUBST(LIBXT_OTHER) +AC_SUBST([LIBXT_OTHER]) if test "${HAVE_X11}" = "yes" ; then - AC_DEFINE(HAVE_X11, 1, + AC_DEFINE([HAVE_X11], [1], [Define to 1 if you want to use version 11 of X windows.]) LIBX_OTHER="\$(LIBXT) \$(LIBX_EXTRA)" else LIBX_OTHER= fi -AC_SUBST(LIBX_OTHER) +AC_SUBST([LIBX_OTHER]) HAVE_OLDXMENU=no if test "$HAVE_GTK" = yes || test "$HAVE_X11" != yes; then @@ -6099,7 +6212,7 @@ else LIBXMENU='$(lwlibdir)/liblw.a' AUTODEPEND_PARENTS="$AUTODEPEND_PARENTS lwlib" fi -AC_SUBST(LIBXMENU) +AC_SUBST([LIBXMENU]) AC_CACHE_CHECK([for struct alignment], [emacs_cv_struct_alignment], @@ -6112,7 +6225,7 @@ AC_CACHE_CHECK([for struct alignment], [emacs_cv_struct_alignment=yes], [emacs_cv_struct_alignment=no])]) if test "$emacs_cv_struct_alignment" = yes; then - AC_DEFINE([HAVE_STRUCT_ATTRIBUTE_ALIGNED], 1, + AC_DEFINE([HAVE_STRUCT_ATTRIBUTE_ALIGNED], [1], [Define to 1 if 'struct __attribute__ ((aligned (N)))' aligns the structure to an N-byte boundary.]) fi @@ -6126,24 +6239,24 @@ AC_CACHE_CHECK([for statement expressions], [emacs_cv_statement_expressions=yes], [emacs_cv_statement_expressions=no])]) if test "$emacs_cv_statement_expressions" = yes; then - AC_DEFINE([HAVE_STATEMENT_EXPRESSIONS], 1, + AC_DEFINE([HAVE_STATEMENT_EXPRESSIONS], [1], [Define to 1 if statement expressions work.]) fi if test "${GNU_MALLOC}" = "yes" ; then - AC_DEFINE(GNU_MALLOC, 1, + AC_DEFINE([GNU_MALLOC], [1], [Define to 1 if you want to use the GNU memory allocator.]) fi RALLOC_OBJ= if test "${REL_ALLOC}" = "yes" ; then - AC_DEFINE(REL_ALLOC, 1, + AC_DEFINE([REL_ALLOC], [1], [Define REL_ALLOC if you want to use the relocating allocator for buffer space.]) test "$system_malloc" != "yes" && RALLOC_OBJ=ralloc.o fi -AC_SUBST(RALLOC_OBJ) +AC_SUBST([RALLOC_OBJ]) if test "$opsys" = "cygwin"; then CYGWIN_OBJ="cygw32.o" @@ -6159,9 +6272,9 @@ else PRE_ALLOC_OBJ=lastfile.o POST_ALLOC_OBJ= fi -AC_SUBST(CYGWIN_OBJ) -AC_SUBST(PRE_ALLOC_OBJ) -AC_SUBST(POST_ALLOC_OBJ) +AC_SUBST([CYGWIN_OBJ]) +AC_SUBST([PRE_ALLOC_OBJ]) +AC_SUBST([POST_ALLOC_OBJ]) dnl Call this 'FORTIFY_SOUR' so that it sorts before the 'FORTIFY_SOURCE' dnl verbatim defined above. The tricky name is apropos, as this hack @@ -6209,7 +6322,7 @@ LIBS=$SAVE_LIBS # timer_getoverrun needs the same library as timer_settime OLD_LIBS=$LIBS LIBS="$LIB_TIMER_TIME $LIBS" -AC_CHECK_FUNCS(timer_getoverrun) +AC_CHECK_FUNCS([timer_getoverrun]) LIBS=$OLD_LIBS if test "${opsys}" = "mingw32"; then @@ -6323,16 +6436,17 @@ fi LD_SWITCH_SYSTEM_TEMACS="$LDFLAGS_NOCOMBRELOC $LD_SWITCH_SYSTEM_TEMACS" -AC_SUBST(LD_SWITCH_SYSTEM_TEMACS) +AC_SUBST([LD_SWITCH_SYSTEM_TEMACS]) ## Common for all window systems if test "$window_system" != "none"; then - AC_DEFINE(HAVE_WINDOW_SYSTEM, 1, [Define if you have a window system.]) - AC_DEFINE(POLL_FOR_INPUT, 1, [Define if you poll periodically to detect C-g.]) + AC_DEFINE([HAVE_WINDOW_SYSTEM], [1], [Define if you have a window system.]) + AC_DEFINE([POLL_FOR_INPUT], [1], + [Define if you poll periodically to detect C-g.]) WINDOW_SYSTEM_OBJ="fontset.o fringe.o image.o" fi -AC_SUBST(WINDOW_SYSTEM_OBJ) +AC_SUBST([WINDOW_SYSTEM_OBJ]) AH_TOP([/* GNU Emacs site configuration template file. @@ -6449,7 +6563,7 @@ for opt in ACL BE_APP CAIRO DBUS FREETYPE GCONF GIF GLIB GMP GNUTLS GPM GSETTING AS_VAR_APPEND([emacs_config_features], ["$optsep$opt"]) optsep=' ' done -AC_DEFINE_UNQUOTED(EMACS_CONFIG_FEATURES, "${emacs_config_features}", +AC_DEFINE_UNQUOTED([EMACS_CONFIG_FEATURES], ["${emacs_config_features}"], [Summary of some of the main features enabled by configure.]) AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D} @@ -6527,7 +6641,7 @@ case $opsys,$emacs_uname_r in echo ;; cygwin,3.0.[[0-7]]'('* | cygwin,3.1.[[0-2]]'('*) - AC_DEFINE([HAVE_CYGWIN_O_PATH_BUG], 1, + AC_DEFINE([HAVE_CYGWIN_O_PATH_BUG], [1], [Define to 1 if opening a FIFO, socket, or symlink with O_PATH is buggy.]);; esac @@ -6549,7 +6663,7 @@ if test "$HAVE_NS" = "yes"; then nextstep/Cocoa/Emacs.base/Contents/Resources/English.lproj/InfoPlist.strings:nextstep/templates/InfoPlist.strings.in]) ns_check_file=Contents/Info.plist fi - AC_SUBST(ns_check_file) + AC_SUBST([ns_check_file]) fi AC_CONFIG_FILES([Makefile lib/gnulib.mk]) @@ -6590,10 +6704,10 @@ fi dnl -d admin SUBDIR_MAKEFILES_IN=`echo " ${SUBDIR_MAKEFILES}" | sed -e 's| | $(srcdir)/|g' -e 's|Makefile|Makefile.in|g'` -AC_SUBST(SUBDIR_MAKEFILES_IN) +AC_SUBST([SUBDIR_MAKEFILES_IN]) SMALL_JA_DIC=$with_small_ja_dic -AC_SUBST(SMALL_JA_DIC) +AC_SUBST([SMALL_JA_DIC]) dnl You might wonder (I did) why epaths.h is generated by running make, dnl rather than just letting configure generate it from epaths.in. diff --git a/etc/compilation.txt b/etc/compilation.txt index e286b5a77d..111b2a37dc 100644 --- a/etc/compilation.txt +++ b/etc/compilation.txt @@ -542,7 +542,7 @@ cf90-113 f90comp: ERROR NSE, File = Hoved.f90, Line = 16, Column = 3 * ShellCheck In autogen.sh line 38: -autoconf_min=`sed -n 's/^ *AC_PREREQ(\([0-9\.]*\)).*/\1/p' configure.ac` +autoconf_min=`sed -n 's/^ *AC_PREREQ(\[\([0-9\.]*\)]).*/\1/p' configure.ac` ^----------^ SC2034: autoconf_min appears unused. Verify use (or export if used externally). ^-- SC2006: Use $(...) notation instead of legacy backticked `...`. commit e93d9e0f5da6e04aaa263dee8501e0ebe16f0a3e Author: Paul Eggert Date: Mon Jul 4 23:23:59 2022 -0500 Don’t mishandle preset emacs_cv_lesstif * configure.ac: Restore CFLAGS etc. correctly even when emacs_cv_lesstif is already set on the command line. diff --git a/configure.ac b/configure.ac index a016d464f3..3afe2e0114 100644 --- a/configure.ac +++ b/configure.ac @@ -3378,7 +3378,6 @@ Motif version prior to 2.1. REAL_CPPFLAGS="-I/usr/include/openmotif $REAL_CPPFLAGS" fi else - AC_CACHE_CHECK(for LessTif where some systems put it, emacs_cv_lesstif, # We put this in CFLAGS temporarily to precede other -I options # that might be in CFLAGS temporarily. # We put this in CPPFLAGS where it precedes the other -I options. @@ -3386,6 +3385,7 @@ Motif version prior to 2.1. OLD_CFLAGS=$CFLAGS CPPFLAGS="-I/usr/X11R6/LessTif/Motif1.2/include $CPPFLAGS" CFLAGS="-I/usr/X11R6/LessTif/Motif1.2/include $CFLAGS" + AC_CACHE_CHECK(for LessTif where some systems put it, emacs_cv_lesstif, [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int x = 5;]])], emacs_cv_lesstif=yes, emacs_cv_lesstif=no)]) commit 77d90ce79a1793bf2c398ee9ff2bf7da1f6a877d Merge: 8cf986702d d5e1424174 Author: Stefan Kangas Date: Tue Jul 5 06:30:40 2022 +0200 Merge from origin/emacs-28 d5e1424174 Expand docstrings related to auto-saving commit 8cf986702ddc51efe20c73e4a8f7e01cb24d1e56 Merge: b4d766fba5 28c5c27162 Author: Stefan Kangas Date: Tue Jul 5 06:30:40 2022 +0200 ; Merge from origin/emacs-28 The following commits were skipped: 28c5c27162 Don't bug out in manual-html-fix-index-2 on newer makeinfo... 724f712ef1 Preserve in the Emacs manuals commit b4d766fba5a9ccfe7262af9032e9e2b84a3370c4 Author: Po Lu <luangruo@yahoo.com> Date: Tue Jul 5 11:03:11 2022 +0800 Don't take XCB socket every time we want the no of the next request * src/xterm.c (x_ignore_errors_for_next_request, x_uncatch_errors) (x_check_errors, x_had_errors_p): Don't call XNextRequest redundantly. Use NextRequest if it was immediately preceded by XNextRequest, which updates dpy->request. diff --git a/src/xterm.c b/src/xterm.c index 7843a46ab2..771db4a05c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -23148,6 +23148,7 @@ static void x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) { struct x_failable_request *request, *max; + unsigned long next_request; #ifdef HAVE_GTK3 GdkDisplay *gdpy; @@ -23171,13 +23172,14 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) request = dpyinfo->next_failable_request; max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS; + next_request = XNextRequest (dpyinfo->display); if (request >= max) { /* There is no point in making this extra sync if all requests are known to have been fully processed. */ if ((LastKnownRequestProcessed (dpyinfo->display) - != XNextRequest (dpyinfo->display) - 1)) + != next_request - 1)) XSync (dpyinfo->display, False); x_clean_failable_requests (dpyinfo); @@ -23189,7 +23191,7 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) function. */ emacs_abort (); - request->start = XNextRequest (dpyinfo->display); + request->start = next_request; request->end = 0; dpyinfo->next_failable_request++; @@ -23271,7 +23273,7 @@ x_uncatch_errors (void) != XNextRequest (x_error_message->dpy) - 1) /* Likewise if no request was made since the trap was installed. */ - && (XNextRequest (x_error_message->dpy) + && (NextRequest (x_error_message->dpy) > x_error_message->first_request)) { XSync (x_error_message->dpy, False); @@ -23306,7 +23308,7 @@ x_check_errors (Display *dpy, const char *format) are known to have been fully processed. */ if ((LastKnownRequestProcessed (dpy) != XNextRequest (dpy) - 1) - && (XNextRequest (dpy) + && (NextRequest (dpy) > x_error_message->first_request)) XSync (dpy, False); @@ -23341,7 +23343,7 @@ x_had_errors_p (Display *dpy) /* Make sure to catch any errors incurred so far. */ if ((LastKnownRequestProcessed (dpy) != XNextRequest (dpy) - 1) - && (XNextRequest (dpy) + && (NextRequest (dpy) > x_error_message->first_request)) XSync (dpy, False); commit 3534426b28b9118e32cabe16810f16ef915f0dbd Author: Stefan Kangas <stefan@marxist.se> Date: Tue Jul 5 04:57:51 2022 +0200 New command emacs-news-mode-open-line * lisp/textmodes/emacs-news-mode.el (emacs-news-mode-open-line): New command. (emacs-news-mode-map): Remap 'open-line' to above new command. diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el index c5d7b6ea50..4ca6ea86d8 100644 --- a/lisp/textmodes/emacs-news-mode.el +++ b/lisp/textmodes/emacs-news-mode.el @@ -54,7 +54,8 @@ "C-c C-r" #'emacs-news-previous-untagged-entry "C-c C-g" #'emacs-news-goto-section "C-c C-j" #'emacs-news-find-heading - "C-c C-e" #'emacs-news-count-untagged-entries) + "C-c C-e" #'emacs-news-count-untagged-entries + "<remap> <open-line>" #'emacs-news-mode-open-line) (defvar-keymap emacs-news-view-mode-map :parent emacs-news-common-map) @@ -232,6 +233,16 @@ untagged NEWS entry." (when (re-search-forward (concat "^*+ " (regexp-quote heading)) nil t) (beginning-of-line))) +(defun emacs-news-mode-open-line (n) + "Open a new line in a NEWS file. +This is like `open-line', but skips any temporary NEWS-style +documentation marks on the previous line." + (interactive "*p" emacs-news-mode) + (when (save-excursion (forward-line -1) + (looking-at (rx bol (or "---" "+++") eol))) + (forward-line -1)) + (open-line n)) + (provide 'emacs-news-mode) ;;; emacs-news-mode.el ends here commit 83f059793af0d7191529582ce674f0af349cd1b7 Author: Po Lu <luangruo@yahoo.com> Date: Tue Jul 5 10:40:32 2022 +0800 Improve support for remote files in XDS * lisp/x-dnd.el (x-dnd-direct-save-function): Remove "local file name" from documentation. (x-dnd-save-direct): Handle remote file names normally. (x-dnd-handle-xds-drop): Handle remote file names in URI. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index f9e6b3198e..3fd2d70cb6 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -128,8 +128,7 @@ and the second is a string. If the first argument is t, the second argument is the name the dropped file should be saved under. The function should return a -complete local file name describing where the file should be -saved. +complete file name describing where the file should be saved. It can also return nil, which means to cancel the drop. @@ -1347,23 +1346,20 @@ is either the name of the file, or the name the drop source wants us to save under. Prompt the user for a file name, then open it." - (if (file-remote-p default-directory) - ;; TODO: figure out what to do with remote files. - nil - (if need-name - (let ((file-name (read-file-name "Write file: " - default-directory - nil nil name))) - (when (file-exists-p file-name) - (unless (y-or-n-p (format-message - "File `%s' exists; overwrite? " file-name)) - (setq file-name nil))) - file-name) - ;; TODO: move this to dired.el once a platform-agonistic - ;; interface can be found. - (if (derived-mode-p 'dired-mode) - (revert-buffer) - (find-file name))))) + (if need-name + (let ((file-name (read-file-name "Write file: " + default-directory + nil nil name))) + (when (file-exists-p file-name) + (unless (y-or-n-p (format-message + "File `%s' exists; overwrite? " file-name)) + (setq file-name nil))) + file-name) + ;; TODO: move this to dired.el once a platform-agonistic + ;; interface can be found. + (if (derived-mode-p 'dired-mode) + (revert-buffer) + (find-file name)))) (defun x-dnd-handle-octet-stream-for-drop (save-to) "Save the contents of the XDS selection to SAVE-TO. @@ -1399,7 +1395,7 @@ VERSION is the version of the XDND protocol understood by SOURCE." ;; encodings. "text/plain" source)) (frame (window-frame window)) - (success nil) save-to) + (success nil) save-to save-to-remote hostname) (unwind-protect (when (stringp desired-name) (setq desired-name (decode-coding-string @@ -1408,10 +1404,15 @@ VERSION is the version of the XDND protocol understood by SOURCE." default-file-name-coding-system))) (setq save-to (expand-file-name (funcall x-dnd-direct-save-function - t desired-name))) + t desired-name)) + save-to-remote save-to) + (if (file-remote-p save-to) + (setq hostname (file-remote-p save-to 'host) + save-to (file-local-name save-to)) + (setq hostname (system-name))) (when save-to (with-selected-window window - (let ((uri (format "file://%s%s" (system-name) save-to))) + (let ((uri (format "file://%s%s" hostname save-to))) (x-change-window-property "XdndDirectSave0" (encode-coding-string (url-encode-url uri) 'ascii) @@ -1419,7 +1420,8 @@ VERSION is the version of the XDND protocol understood by SOURCE." (let ((result (x-get-selection-internal 'XdndSelection 'XdndDirectSave0))) (cond ((equal result "F") - (setq success (x-dnd-handle-octet-stream-for-drop save-to)) + (setq success + (x-dnd-handle-octet-stream-for-drop save-to-remote)) (unless success (x-change-window-property "XdndDirectSave0" "" frame "text/plain" 8 @@ -1431,7 +1433,7 @@ VERSION is the version of the XDND protocol understood by SOURCE." (t (error "Broken implementation of XDS: got %s in reply" result))) (when success - (funcall x-dnd-direct-save-function nil save-to))))))) + (funcall x-dnd-direct-save-function nil save-to-remote))))))) ;; We assume XDS always comes from a client supporting version 2 ;; or later, since custom actions aren't present before. (x-send-client-message frame source frame commit 08df1631b4f0a71ef988d31c5792978fb3e587dc Author: Po Lu <luangruo@yahoo.com> Date: Tue Jul 5 10:12:19 2022 +0800 Don't overestimate supported input extension version on GTK 3 * src/xterm.c (x_term_init): If minor > original_minor (the maximum version supported by libXi), set it back to original_minor. diff --git a/src/xterm.c b/src/xterm.c index 82a20ad1a9..7843a46ab2 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -27099,6 +27099,13 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) } else x_uncatch_errors_after_check (); + + /* But don't delude ourselves into thinking that we can use + features provided by a version of the input extension that + libXi itself doesn't support. */ + + if (minor > original_minor) + minor = original_minor; #else if (x_had_errors_p (dpyinfo->display)) rc = BadRequest; commit f1ae277e0bbb5e03bb24ff79b4544e5b12f2d361 Author: Alexander Adolf <alexander.adolf@condition-alpha.com> Date: Sat Jul 2 17:27:55 2022 +0200 Add reverse mapping for EUDC attribute names * lisp/net/eudc.el (eudc-translate-query): new optional parameter to reverse the mapping direction (eudc-translate-attribute-list): new optional parameter to reverse the mapping direction diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el index ca4e4c9f37..eb1342e438 100644 --- a/lisp/net/eudc.el +++ b/lisp/net/eudc.el @@ -383,32 +383,51 @@ accordingly. Otherwise it is set to its EUDC default binding." (cons protocol eudc-known-protocols)))) -(defun eudc-translate-query (query) +(defun eudc-translate-query (query &optional reverse) "Translate attribute names of QUERY. The translation is done according to -`eudc-protocol-attributes-translation-alist'." +`eudc-protocol-attributes-translation-alist'. + +When REVERSE is nil or omitted, the attribute names are +translated from EUDC generic names to protocol-specific +names. When REVERSE is non-nil, the translation is from +protocol-specific names back to EUDC generic names." (if eudc-protocol-attributes-translation-alist (mapcar (lambda (attribute) - (let ((trans (assq (car attribute) - (symbol-value eudc-protocol-attributes-translation-alist)))) + (let ((trans + (if reverse + (rassq (car attribute) + (symbol-value eudc-protocol-attributes-translation-alist)) + (assq (car attribute) + (symbol-value eudc-protocol-attributes-translation-alist))))) (if trans - (cons (cdr trans) (cdr attribute)) + (cons (if reverse (car trans) (cdr trans)) + (cdr attribute)) attribute))) query) query)) -(defun eudc-translate-attribute-list (list) +(defun eudc-translate-attribute-list (list &optional reverse) "Translate a list of attribute names LIST. The translation is done according to -`eudc-protocol-attributes-translation-alist'." +`eudc-protocol-attributes-translation-alist'. + +When REVERSE is nil or omitted, the attribute names are +translated from EUDC generic names to protocol-specific +names. When REVERSE is non-nil, the translation is from +protocol-specific names back to EUDC generic names." (if eudc-protocol-attributes-translation-alist (let (trans) (mapcar (lambda (attribute) - (setq trans (assq attribute - (symbol-value eudc-protocol-attributes-translation-alist))) - (if trans - (cdr trans) - attribute)) + (setq trans + (if reverse + (rassq attribute + (symbol-value eudc-protocol-attributes-translation-alist)) + (assq attribute + (symbol-value eudc-protocol-attributes-translation-alist)))) + (if trans + (if reverse (car trans) (cdr trans)) + attribute)) list)) list)) commit edaa7780fd88ca6f184b2594a676af32eb4ade10 Author: Stefan Monnier <monnier@iro.umontreal.ca> Date: Mon Jul 4 18:44:03 2022 -0400 (gnus-inverse-list-range-intersection): Update alias * lisp/gnus/gnus-range.el (gnus-inverse-list-range-intersection): Don't alias to an obsolete alias. diff --git a/lisp/gnus/gnus-range.el b/lisp/gnus/gnus-range.el index 23a71bda20..2b9d7fac1d 100644 --- a/lisp/gnus/gnus-range.el +++ b/lisp/gnus/gnus-range.el @@ -36,10 +36,10 @@ (car list)) (make-obsolete 'gnus-last-element "use `car' of `last' instead." "27.1") -(define-obsolete-function-alias 'gnus-copy-sequence 'copy-tree "27.1") +(define-obsolete-function-alias 'gnus-copy-sequence #'copy-tree "27.1") -;;; We could be using `seq-difference' here, but it's much slower -;;; on these data sets. See bug#50877. +;; We could be using `seq-difference' here, but it's much slower +;; on these data sets. See bug#50877. (defun gnus-set-difference (list1 list2) "Return a list of elements of LIST1 that do not appear in LIST2." (let ((hash2 (make-hash-table :test 'eq)) @@ -163,7 +163,7 @@ LIST1 and LIST2 have to be sorted over <." #'range-intersection "29.1") ;;;###autoload -(defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection) +(defalias 'gnus-set-sorted-intersection #'gnus-sorted-nintersection) ;;;###autoload (defun gnus-sorted-nintersection (list1 list2) @@ -241,7 +241,7 @@ ranges." (range-compress-list numbers) (range-denormalize (range-compress-list numbers)))) -(defalias 'gnus-uncompress-sequence 'gnus-uncompress-range) +(defalias 'gnus-uncompress-sequence #'gnus-uncompress-range) (define-obsolete-function-alias 'gnus-uncompress-range #'range-uncompress "29.1") @@ -256,7 +256,7 @@ ranges." (define-obsolete-function-alias 'gnus-list-range-intersection #'range-list-intersection "29.1") -(defalias 'gnus-inverse-list-range-intersection 'gnus-list-range-difference) +(defalias 'gnus-inverse-list-range-intersection #'range-list-difference) (define-obsolete-function-alias 'gnus-list-range-difference #'range-list-difference "29.1") commit d5e14241744d2994102b5e66db48c9ebc406861d Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 23:54:07 2022 +0200 Expand docstrings related to auto-saving * lisp/files.el (auto-save-visited-mode): * lisp/simple.el (auto-save-mode): Expand docstring. diff --git a/lisp/files.el b/lisp/files.el index ea57f02ac0..752986b478 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -421,6 +421,9 @@ idle for `auto-save-visited-interval' seconds." (define-minor-mode auto-save-visited-mode "Toggle automatic saving to file-visiting buffers on or off. +When this mode is enabled, visited files are saved automatically. +The user option `auto-save-visited-interval' controls how often. + Unlike `auto-save-mode', this mode will auto-save buffer contents to the visited files directly and will also run all save-related hooks. See Info node `Saving' for details of the save process. @@ -429,7 +432,9 @@ You can also set the buffer-local value of the variable `auto-save-visited-mode' to nil. A buffer where the buffer-local value of this variable is nil is ignored for the purpose of `auto-save-visited-mode', even if `auto-save-visited-mode' is -enabled." +enabled. + +For more details, see Info node `(emacs) Auto Save Files'." :group 'auto-save :global t (when auto-save--timer (cancel-timer auto-save--timer)) diff --git a/lisp/simple.el b/lisp/simple.el index d235eb9745..dca8589be4 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8398,7 +8398,19 @@ presented." :global t :group 'mode-line) (define-minor-mode auto-save-mode - "Toggle auto-saving in the current buffer (Auto Save mode)." + "Toggle auto-saving in the current buffer (Auto Save mode). + +When this mode is enabled, Emacs periodically saves each visited +file in a separate file called the \"auto-save file\". This is a +safety measure to prevent you from losing more than a limited +amount of work if the system crashes. + +Auto-saving does not alter the file you actually use: the visited +file is changed only when you request saving it explicitly (such +as with \\[save-buffer]). If you want to save visited files +automatically, use \\[auto-save-visited-mode]). + +For more details, see Info node `(emacs) Auto Save'." :variable ((and buffer-auto-save-file-name ;; If auto-save is off because buffer has shrunk, ;; then toggling should turn it on. commit 6d415d5f0b616fc36f3e5c47a42b6af19eb3d82a Author: Paul Eggert <eggert@cs.ucla.edu> Date: Mon Jul 4 16:21:35 2022 -0500 Fix core dump with x-get-local-selection * src/xselect.c (Fx_get_local_selection): Check that VALUE has 4 elements, since x_get_local_selection can dump core otherwise. This pacifies gcc -Wanalyzer-null-dereference, which found the problem. diff --git a/src/xselect.c b/src/xselect.c index 2521dc171c..1fda300c43 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -2325,9 +2325,13 @@ run. */) Lisp_Object name, timestamp, frame, result; CHECK_SYMBOL (target); - name = Fnth (make_fixnum (0), value); - timestamp = Fnth (make_fixnum (2), value); - frame = Fnth (make_fixnum (3), value); + + /* Check that VALUE has 4 elements, for x_get_local_selection. */ + Lisp_Object v = value; CHECK_CONS (v); + name = XCAR (v); v = XCDR (v); CHECK_CONS (v); + v = XCDR (v); CHECK_CONS (v); + timestamp = XCAR (v); v = XCDR (v); CHECK_CONS (v); + frame = XCAR (v); CHECK_SYMBOL (name); CONS_TO_INTEGER (timestamp, Time, time); commit 7540f98c5ac57247066f017889b6cffe1dd690fc Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 18:44:24 2022 +0200 Add quit-window entry to list-timers menu * lisp/emacs-lisp/timer-list.el (timer-list-mode-map): Add quit-window entry to menu. diff --git a/lisp/emacs-lisp/timer-list.el b/lisp/emacs-lisp/timer-list.el index 8c56108dcb..d48698234f 100644 --- a/lisp/emacs-lisp/timer-list.el +++ b/lisp/emacs-lisp/timer-list.el @@ -85,7 +85,8 @@ "c" #'timer-list-cancel :menu '("Timers" - ["Cancel" timer-list-cancel t])) + ["Cancel" timer-list-cancel t] + ["Quit" quit-window])) (define-derived-mode timer-list-mode tabulated-list-mode "Timer-List" "Mode for listing and controlling timers." commit 162c6c12f97db9b4b3042dc8d122027e9fb01e71 Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 18:42:26 2022 +0200 Prefer defvar-keymap in emacs-lisp/*.el * lisp/emacs-lisp/backtrace.el (backtrace-mode-map): * lisp/emacs-lisp/bytecomp.el (emacs-lisp-compilation-mode-map): * lisp/emacs-lisp/checkdoc.el (checkdoc-minor-mode-map): * lisp/emacs-lisp/crm.el (crm-local-completion-map) (crm-local-must-match-map): * lisp/emacs-lisp/debug.el (debugger-mode-map): * lisp/emacs-lisp/edebug.el (edebug-mode-map, edebug-global-map) (edebug-eval-mode-map): * lisp/emacs-lisp/eieio-custom.el (eieio-custom-mode-map): * lisp/emacs-lisp/elp.el (elp-results-symname-map): * lisp/emacs-lisp/lisp-mode.el (lisp-mode-shared-map): * lisp/emacs-lisp/re-builder.el (reb-mode-map) (reb-lisp-mode-map, reb-subexp-mode-map): * lisp/emacs-lisp/tabulated-list.el (tabulated-list-mode-map) (tabulated-list-sort-button-map): * lisp/emacs-lisp/timer-list.el (timer-list-mode-map): diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el index 3231877a30..e305822af1 100644 --- a/lisp/emacs-lisp/backtrace.el +++ b/lisp/emacs-lisp/backtrace.el @@ -199,63 +199,63 @@ functions returns non-nil. When adding a function to this hook, you should also set the :source-available flag for the backtrace frames where the source code location is known.") -(defvar backtrace-mode-map - (let ((map (copy-keymap special-mode-map))) - (set-keymap-parent map button-buffer-map) - (define-key map "n" 'backtrace-forward-frame) - (define-key map "p" 'backtrace-backward-frame) - (define-key map "v" 'backtrace-toggle-locals) - (define-key map "#" 'backtrace-toggle-print-circle) - (define-key map ":" 'backtrace-toggle-print-gensym) - (define-key map "s" 'backtrace-goto-source) - (define-key map "\C-m" 'backtrace-help-follow-symbol) - (define-key map "+" 'backtrace-multi-line) - (define-key map "-" 'backtrace-single-line) - (define-key map "." 'backtrace-expand-ellipses) - (define-key map [follow-link] 'mouse-face) - (define-key map [mouse-2] 'mouse-select-window) - (easy-menu-define nil map "" - '("Backtrace" - ["Next Frame" backtrace-forward-frame - :help "Move cursor forwards to the start of a backtrace frame"] - ["Previous Frame" backtrace-backward-frame - :help "Move cursor backwards to the start of a backtrace frame"] - "--" - ["Show Variables" backtrace-toggle-locals - :style toggle - :active (backtrace-get-index) - :selected (plist-get (backtrace-get-view) :show-locals) - :help "Show or hide the local variables for the frame at point"] - ["Show Circular Structures" backtrace-toggle-print-circle - :style toggle - :active (backtrace-get-index) - :selected (plist-get (backtrace-get-view) :print-circle) - :help - "Condense or expand shared or circular structures in the frame at point"] - ["Show Uninterned Symbols" backtrace-toggle-print-gensym - :style toggle - :active (backtrace-get-index) - :selected (plist-get (backtrace-get-view) :print-gensym) - :help - "Toggle unique printing of uninterned symbols in the frame at point"] - ["Expand \"...\"s" backtrace-expand-ellipses - :help "Expand all the abbreviated forms in the current frame"] - ["Show on Multiple Lines" backtrace-multi-line - :help "Use line breaks and indentation to make a form more readable"] - ["Show on Single Line" backtrace-single-line] - "--" - ["Go to Source" backtrace-goto-source - :active (and (backtrace-get-index) - (plist-get (backtrace-frame-flags - (nth (backtrace-get-index) backtrace-frames)) - :source-available)) - :help "Show the source code for the current frame"] - ["Help for Symbol" backtrace-help-follow-symbol - :help "Show help for symbol at point"] - ["Describe Backtrace Mode" describe-mode - :help "Display documentation for backtrace-mode"])) - map) - "Local keymap for `backtrace-mode' buffers.") +(defvar-keymap backtrace-mode-map + :doc "Local keymap for `backtrace-mode' buffers." + :parent (make-composed-keymap special-mode-map + button-buffer-map) + "n" #'backtrace-forward-frame + "p" #'backtrace-backward-frame + "v" #'backtrace-toggle-locals + "#" #'backtrace-toggle-print-circle + ":" #'backtrace-toggle-print-gensym + "s" #'backtrace-goto-source + "RET" #'backtrace-help-follow-symbol + "+" #'backtrace-multi-line + "-" #'backtrace-single-line + "." #'backtrace-expand-ellipses + "<follow-link>" 'mouse-face + "<mouse-2>" #'mouse-select-window + + :menu + '("Backtrace" + ["Next Frame" backtrace-forward-frame + :help "Move cursor forwards to the start of a backtrace frame"] + ["Previous Frame" backtrace-backward-frame + :help "Move cursor backwards to the start of a backtrace frame"] + "--" + ["Show Variables" backtrace-toggle-locals + :style toggle + :active (backtrace-get-index) + :selected (plist-get (backtrace-get-view) :show-locals) + :help "Show or hide the local variables for the frame at point"] + ["Show Circular Structures" backtrace-toggle-print-circle + :style toggle + :active (backtrace-get-index) + :selected (plist-get (backtrace-get-view) :print-circle) + :help + "Condense or expand shared or circular structures in the frame at point"] + ["Show Uninterned Symbols" backtrace-toggle-print-gensym + :style toggle + :active (backtrace-get-index) + :selected (plist-get (backtrace-get-view) :print-gensym) + :help + "Toggle unique printing of uninterned symbols in the frame at point"] + ["Expand \"...\"s" backtrace-expand-ellipses + :help "Expand all the abbreviated forms in the current frame"] + ["Show on Multiple Lines" backtrace-multi-line + :help "Use line breaks and indentation to make a form more readable"] + ["Show on Single Line" backtrace-single-line] + "--" + ["Go to Source" backtrace-goto-source + :active (and (backtrace-get-index) + (plist-get (backtrace-frame-flags + (nth (backtrace-get-index) backtrace-frames)) + :source-available)) + :help "Show the source code for the current frame"] + ["Help for Symbol" backtrace-help-follow-symbol + :help "Show help for symbol at point"] + ["Describe Backtrace Mode" describe-mode + :help "Display documentation for backtrace-mode"])) (defconst backtrace--flags-width 2 "Width in characters of the flags for a backtrace frame.") diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index bd3db85c14..6545c8d961 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1123,10 +1123,8 @@ message buffer `default-directory'." :type '(repeat (choice (const :tag "Default" nil) (string :tag "Directory")))) -(defvar emacs-lisp-compilation-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "g" 'emacs-lisp-compilation-recompile) - map)) +(defvar-keymap emacs-lisp-compilation-mode-map + "g" #'emacs-lisp-compilation-recompile) (defvar emacs-lisp-compilation--current-file nil) diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index 2c9adfe2d2..611f32e23c 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -1279,38 +1279,30 @@ TEXT, START, END and UNFIXABLE conform to ;;; Minor Mode specification ;; -(defvar checkdoc-minor-mode-map - (let ((map (make-sparse-keymap)) - (pmap (make-sparse-keymap))) - ;; Override some bindings - (define-key map "\C-\M-x" #'checkdoc-eval-defun) - (define-key map "\C-x`" #'checkdoc-continue) - (define-key map [menu-bar emacs-lisp eval-buffer] - #'checkdoc-eval-current-buffer) - ;; Add some new bindings under C-c ? - (define-key pmap "x" #'checkdoc-defun) - (define-key pmap "X" #'checkdoc-ispell-defun) - (define-key pmap "`" #'checkdoc-continue) - (define-key pmap "~" #'checkdoc-ispell-continue) - (define-key pmap "s" #'checkdoc-start) - (define-key pmap "S" #'checkdoc-ispell-start) - (define-key pmap "d" #'checkdoc) - (define-key pmap "D" #'checkdoc-ispell) - (define-key pmap "b" #'checkdoc-current-buffer) - (define-key pmap "B" #'checkdoc-ispell-current-buffer) - (define-key pmap "e" #'checkdoc-eval-current-buffer) - (define-key pmap "m" #'checkdoc-message-text) - (define-key pmap "M" #'checkdoc-ispell-message-text) - (define-key pmap "c" #'checkdoc-comments) - (define-key pmap "C" #'checkdoc-ispell-comments) - (define-key pmap " " #'checkdoc-rogue-spaces) - - ;; bind our submap into map - (define-key map "\C-c?" pmap) - map) - "Keymap used to override evaluation key-bindings for documentation checking.") - -;; Add in a menubar with easy-menu +(defvar-keymap checkdoc-minor-mode-map + :doc "Keymap used to override evaluation key-bindings for documentation checking." + ;; Override some bindings + "C-M-x" #'checkdoc-eval-defun + "C-x `" #'checkdoc-continue + "<menu-bar> <emacs-lisp> <eval-buffer>" #'checkdoc-eval-current-buffer + + ;; Add some new bindings under C-c ? + "C-c ? x" #'checkdoc-defun + "C-c ? X" #'checkdoc-ispell-defun + "C-c ? `" #'checkdoc-continue + "C-c ? ~" #'checkdoc-ispell-continue + "C-c ? s" #'checkdoc-start + "C-c ? S" #'checkdoc-ispell-start + "C-c ? d" #'checkdoc + "C-c ? D" #'checkdoc-ispell + "C-c ? b" #'checkdoc-current-buffer + "C-c ? B" #'checkdoc-ispell-current-buffer + "C-c ? e" #'checkdoc-eval-current-buffer + "C-c ? m" #'checkdoc-message-text + "C-c ? M" #'checkdoc-ispell-message-text + "C-c ? c" #'checkdoc-comments + "C-c ? C" #'checkdoc-ispell-comments + "C-c ? SPC" #'checkdoc-rogue-spaces) (easy-menu-define nil checkdoc-minor-mode-map "Checkdoc Minor Mode Menu." diff --git a/lisp/emacs-lisp/crm.el b/lisp/emacs-lisp/crm.el index 8a5c3d3730..9d9c91e510 100644 --- a/lisp/emacs-lisp/crm.el +++ b/lisp/emacs-lisp/crm.el @@ -87,28 +87,23 @@ It should be a regexp that does not match the list of completion candidates. The default value is `crm-default-separator'.") -(defvar crm-local-completion-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map minibuffer-local-completion-map) - (define-key map [remap minibuffer-complete] #'crm-complete) - (define-key map [remap minibuffer-complete-word] #'crm-complete-word) - (define-key map [remap minibuffer-completion-help] #'crm-completion-help) - map) - "Local keymap for minibuffer multiple input with completion. -Analog of `minibuffer-local-completion-map'.") - -(defvar crm-local-must-match-map - (let ((map (make-sparse-keymap))) - ;; We'd want to have multiple inheritance here. - (set-keymap-parent map minibuffer-local-must-match-map) - (define-key map [remap minibuffer-complete] #'crm-complete) - (define-key map [remap minibuffer-complete-word] #'crm-complete-word) - (define-key map [remap minibuffer-completion-help] #'crm-completion-help) - (define-key map [remap minibuffer-complete-and-exit] - #'crm-complete-and-exit) - map) - "Local keymap for minibuffer multiple input with exact match completion. -Analog of `minibuffer-local-must-match-map' for crm.") +(defvar-keymap crm-local-completion-map + :doc "Local keymap for minibuffer multiple input with completion. +Analog of `minibuffer-local-completion-map'." + :parent minibuffer-local-completion-map + "<remap> <minibuffer-complete>" #'crm-complete + "<remap> <minibuffer-complete-word>" #'crm-complete-word + "<remap> <minibuffer-completion-help>" #'crm-completion-help) + +(defvar-keymap crm-local-must-match-map + :doc "Local keymap for minibuffer multiple input with exact match completion. +Analog of `minibuffer-local-must-match-map' for crm." + ;; We'd want to have multiple inheritance here. + :parent minibuffer-local-must-match-map + "<remap> <minibuffer-complete>" #'crm-complete + "<remap> <minibuffer-complete-word>" #'crm-complete-word + "<remap> <minibuffer-completion-help>" #'crm-completion-help + "<remap> <minibuffer-complete-and-exit>" #'crm-complete-and-exit) (defvar crm-completion-table nil "An alist whose elements' cars are strings, or an obarray. diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index c4929eb2b0..460057b3af 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el @@ -560,52 +560,53 @@ The environment used is the one when entering the activation frame at point." 'backtrace-toggle-locals "28.1") -(defvar debugger-mode-map - (let ((map (make-keymap))) - (set-keymap-parent map backtrace-mode-map) - (define-key map "b" 'debugger-frame) - (define-key map "c" 'debugger-continue) - (define-key map "j" 'debugger-jump) - (define-key map "r" 'debugger-return-value) - (define-key map "u" 'debugger-frame-clear) - (define-key map "d" 'debugger-step-through) - (define-key map "l" 'debugger-list-functions) - (define-key map "q" 'debugger-quit) - (define-key map "e" 'debugger-eval-expression) - (define-key map "R" 'debugger-record-expression) - (define-key map [mouse-2] 'push-button) - (easy-menu-define nil map "" - '("Debugger" - ["Step through" debugger-step-through - :help "Proceed, stepping through subexpressions of this expression"] - ["Continue" debugger-continue - :help "Continue, evaluating this expression without stopping"] - ["Jump" debugger-jump - :help "Continue to exit from this frame, with all debug-on-entry suspended"] - ["Eval Expression..." debugger-eval-expression - :help "Eval an expression, in an environment like that outside the debugger"] - ["Display and Record Expression" debugger-record-expression - :help "Display a variable's value and record it in `*Backtrace-record*' buffer"] - ["Return value..." debugger-return-value - :help "Continue, specifying value to return."] - "--" - ["Debug frame" debugger-frame - :help "Request entry to debugger when this frame exits"] - ["Cancel debug frame" debugger-frame-clear - :help "Do not enter debugger when this frame exits"] - ["List debug on entry functions" debugger-list-functions - :help "Display a list of all the functions now set to debug on entry"] - "--" - ["Next Line" next-line - :help "Move cursor down"] - ["Help for Symbol" backtrace-help-follow-symbol - :help "Show help for symbol at point"] - ["Describe Debugger Mode" describe-mode - :help "Display documentation for debugger-mode"] - "--" - ["Quit" debugger-quit - :help "Quit debugging and return to top level"])) - map)) +(defvar-keymap debugger-mode-map + :full t + :parent backtrace-mode-map + "b" #'debugger-frame + "c" #'debugger-continue + "j" #'debugger-jump + "r" #'debugger-return-value + "u" #'debugger-frame-clear + "d" #'debugger-step-through + "l" #'debugger-list-functions + "q" #'debugger-quit + "e" #'debugger-eval-expression + "R" #'debugger-record-expression + + "<mouse-2>" #'push-button + + :menu + '("Debugger" + ["Step through" debugger-step-through + :help "Proceed, stepping through subexpressions of this expression"] + ["Continue" debugger-continue + :help "Continue, evaluating this expression without stopping"] + ["Jump" debugger-jump + :help "Continue to exit from this frame, with all debug-on-entry suspended"] + ["Eval Expression..." debugger-eval-expression + :help "Eval an expression, in an environment like that outside the debugger"] + ["Display and Record Expression" debugger-record-expression + :help "Display a variable's value and record it in `*Backtrace-record*' buffer"] + ["Return value..." debugger-return-value + :help "Continue, specifying value to return."] + "--" + ["Debug frame" debugger-frame + :help "Request entry to debugger when this frame exits"] + ["Cancel debug frame" debugger-frame-clear + :help "Do not enter debugger when this frame exits"] + ["List debug on entry functions" debugger-list-functions + :help "Display a list of all the functions now set to debug on entry"] + "--" + ["Next Line" next-line + :help "Move cursor down"] + ["Help for Symbol" backtrace-help-follow-symbol + :help "Show help for symbol at point"] + ["Describe Debugger Mode" describe-mode + :help "Display documentation for debugger-mode"] + "--" + ["Quit" debugger-quit + :help "Quit debugging and return to top level"])) (put 'debugger-mode 'mode-class 'special) diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index b05ec3a768..1a1d58d6e3 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -3809,74 +3809,72 @@ be installed in `emacs-lisp-mode-map'.") ;; The following isn't a GUD binding. (define-key emacs-lisp-mode-map "\C-x\C-a\C-m" 'edebug-set-initial-mode)) -(defvar edebug-mode-map - (let ((map (copy-keymap emacs-lisp-mode-map))) - ;; control - (define-key map " " 'edebug-step-mode) - (define-key map "n" 'edebug-next-mode) - (define-key map "g" 'edebug-go-mode) - (define-key map "G" 'edebug-Go-nonstop-mode) - (define-key map "t" 'edebug-trace-mode) - (define-key map "T" 'edebug-Trace-fast-mode) - (define-key map "c" 'edebug-continue-mode) - (define-key map "C" 'edebug-Continue-fast-mode) - - ;;(define-key map "f" 'edebug-forward) not implemented - (define-key map "f" 'edebug-forward-sexp) - (define-key map "h" 'edebug-goto-here) - - (define-key map "I" 'edebug-instrument-callee) - (define-key map "i" 'edebug-step-in) - (define-key map "o" 'edebug-step-out) - - ;; quitting and stopping - (define-key map "q" 'top-level) - (define-key map "Q" 'edebug-top-level-nonstop) - (define-key map "a" 'abort-recursive-edit) - (define-key map "S" 'edebug-stop) - - ;; breakpoints - (define-key map "b" 'edebug-set-breakpoint) - (define-key map "u" 'edebug-unset-breakpoint) - (define-key map "U" 'edebug-unset-breakpoints) - (define-key map "B" 'edebug-next-breakpoint) - (define-key map "x" 'edebug-set-conditional-breakpoint) - (define-key map "X" 'edebug-set-global-break-condition) - (define-key map "D" 'edebug-toggle-disable-breakpoint) - - ;; evaluation - (define-key map "r" 'edebug-previous-result) - (define-key map "e" 'edebug-eval-expression) - (define-key map "\C-x\C-e" 'edebug-eval-last-sexp) - (define-key map "E" 'edebug-visit-eval-list) - - ;; views - (define-key map "w" 'edebug-where) - (define-key map "v" 'edebug-view-outside) ;; maybe obsolete?? - (define-key map "p" 'edebug-bounce-point) - (define-key map "P" 'edebug-view-outside) ;; same as v - (define-key map "W" 'edebug-toggle-save-windows) - - ;; misc - (define-key map "?" 'edebug-help) - (define-key map "d" 'edebug-pop-to-backtrace) - - (define-key map "-" 'negative-argument) - - ;; statistics - (define-key map "=" 'edebug-temp-display-freq-count) - - ;; GUD bindings - (define-key map "\C-c\C-s" 'edebug-step-mode) - (define-key map "\C-c\C-n" 'edebug-next-mode) - (define-key map "\C-c\C-c" 'edebug-go-mode) - - (define-key map "\C-x " 'edebug-set-breakpoint) - (define-key map "\C-c\C-d" 'edebug-unset-breakpoint) - (define-key map "\C-c\C-t" - (lambda () (interactive) (edebug-set-breakpoint t))) - (define-key map "\C-c\C-l" 'edebug-where) - map)) +(defvar-keymap edebug-mode-map + :parent emacs-lisp-mode-map + ;; control + "SPC" #'edebug-step-mode + "n" #'edebug-next-mode + "g" #'edebug-go-mode + "G" #'edebug-Go-nonstop-mode + "t" #'edebug-trace-mode + "T" #'edebug-Trace-fast-mode + "c" #'edebug-continue-mode + "C" #'edebug-Continue-fast-mode + + ;;"f" #'edebug-forward ; not implemented + "f" #'edebug-forward-sexp + "h" #'edebug-goto-here + + "I" #'edebug-instrument-callee + "i" #'edebug-step-in + "o" #'edebug-step-out + + ;; quitting and stopping + "q" #'top-level + "Q" #'edebug-top-level-nonstop + "a" #'abort-recursive-edit + "S" #'edebug-stop + + ;; breakpoints + "b" #'edebug-set-breakpoint + "u" #'edebug-unset-breakpoint + "U" #'edebug-unset-breakpoints + "B" #'edebug-next-breakpoint + "x" #'edebug-set-conditional-breakpoint + "X" #'edebug-set-global-break-condition + "D" #'edebug-toggle-disable-breakpoint + + ;; evaluation + "r" #'edebug-previous-result + "e" #'edebug-eval-expression + "C-x C-e" #'edebug-eval-last-sexp + "E" #'edebug-visit-eval-list + + ;; views + "w" #'edebug-where + "v" #'edebug-view-outside ; maybe obsolete?? + "p" #'edebug-bounce-point + "P" #'edebug-view-outside ; same as v + "W" #'edebug-toggle-save-windows + + ;; misc + "?" #'edebug-help + "d" #'edebug-pop-to-backtrace + + "-" #'negative-argument + + ;; statistics + "=" #'edebug-temp-display-freq-count + + ;; GUD bindings + "C-c C-s" #'edebug-step-mode + "C-c C-n" #'edebug-next-mode + "C-c C-c" #'edebug-go-mode + + "C-x SPC" #'edebug-set-breakpoint + "C-c C-d" #'edebug-unset-breakpoint + "C-c C-t" (lambda () (interactive) (edebug-set-breakpoint t)) + "C-c C-l" #'edebug-where) ;; Autoloading these global bindings doesn't make sense because ;; they cannot be used anyway unless Edebug is already loaded and active. @@ -3891,38 +3889,35 @@ be installed in `emacs-lisp-mode-map'.") (define-obsolete-variable-alias 'global-edebug-map 'edebug-global-map "28.1") -(defvar edebug-global-map - (let ((map (make-sparse-keymap))) - - (define-key map " " 'edebug-step-mode) - (define-key map "g" 'edebug-go-mode) - (define-key map "G" 'edebug-Go-nonstop-mode) - (define-key map "t" 'edebug-trace-mode) - (define-key map "T" 'edebug-Trace-fast-mode) - (define-key map "c" 'edebug-continue-mode) - (define-key map "C" 'edebug-Continue-fast-mode) - - ;; breakpoints - (define-key map "b" 'edebug-set-breakpoint) - (define-key map "u" 'edebug-unset-breakpoint) - (define-key map "U" 'edebug-unset-breakpoints) - (define-key map "x" 'edebug-set-conditional-breakpoint) - (define-key map "X" 'edebug-set-global-break-condition) - (define-key map "D" 'edebug-toggle-disable-breakpoint) - - ;; views - (define-key map "w" 'edebug-where) - (define-key map "W" 'edebug-toggle-save-windows) - - ;; quitting - (define-key map "q" 'top-level) - (define-key map "Q" 'edebug-top-level-nonstop) - (define-key map "a" 'abort-recursive-edit) - - ;; statistics - (define-key map "=" 'edebug-display-freq-count) - map) - "Global map of edebug commands, available from any buffer.") +(defvar-keymap edebug-global-map + :doc "Global map of edebug commands, available from any buffer." + "SPC" #'edebug-step-mode + "g" #'edebug-go-mode + "G" #'edebug-Go-nonstop-mode + "t" #'edebug-trace-mode + "T" #'edebug-Trace-fast-mode + "c" #'edebug-continue-mode + "C" #'edebug-Continue-fast-mode + + ;; breakpoints + "b" #'edebug-set-breakpoint + "u" #'edebug-unset-breakpoint + "U" #'edebug-unset-breakpoints + "x" #'edebug-set-conditional-breakpoint + "X" #'edebug-set-global-break-condition + "D" #'edebug-toggle-disable-breakpoint + + ;; views + "w" #'edebug-where + "W" #'edebug-toggle-save-windows + + ;; quitting + "q" #'top-level + "Q" #'edebug-top-level-nonstop + "a" #'abort-recursive-edit + + ;; statistics + "=" #'edebug-display-freq-count) (when edebug-global-prefix (global-unset-key edebug-global-prefix) @@ -4093,16 +4088,14 @@ May only be called from within `edebug--recursive-edit'." -(defvar edebug-eval-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map lisp-interaction-mode-map) - (define-key map "\C-c\C-w" 'edebug-where) - (define-key map "\C-c\C-d" 'edebug-delete-eval-item) - (define-key map "\C-c\C-u" 'edebug-update-eval-list) - (define-key map "\C-x\C-e" 'edebug-eval-last-sexp) - (define-key map "\C-j" 'edebug-eval-print-last-sexp) - map) - "Keymap for Edebug Eval mode. Superset of Lisp Interaction mode.") +(defvar-keymap edebug-eval-mode-map + :doc "Keymap for Edebug Eval mode. Superset of Lisp Interaction mode." + :parent lisp-interaction-mode-map + "C-c C-w" #'edebug-where + "C-c C-d" #'edebug-delete-eval-item + "C-c C-u" #'edebug-update-eval-list + "C-x C-e" #'edebug-eval-last-sexp + "C-j" #'edebug-eval-print-last-sexp) (put 'edebug-eval-mode 'mode-class 'special) diff --git a/lisp/emacs-lisp/eieio-custom.el b/lisp/emacs-lisp/eieio-custom.el index ebb6f2cd8c..4b8b4275f1 100644 --- a/lisp/emacs-lisp/eieio-custom.el +++ b/lisp/emacs-lisp/eieio-custom.el @@ -329,11 +329,9 @@ Argument OBJ is the object that has been customized." Optional argument GROUP is the sub-group of slots to display." (eieio-customize-object obj group)) -(defvar eieio-custom-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map widget-keymap) - map) - "Keymap for EIEIO Custom mode.") +(defvar-keymap eieio-custom-mode-map + :doc "Keymap for EIEIO Custom mode." + :parent widget-keymap) (define-derived-mode eieio-custom-mode fundamental-mode "EIEIO Custom" "Major mode for customizing EIEIO objects. diff --git a/lisp/emacs-lisp/elp.el b/lisp/emacs-lisp/elp.el index 385ddb3f41..03c5b94e3b 100644 --- a/lisp/emacs-lisp/elp.el +++ b/lisp/emacs-lisp/elp.el @@ -472,13 +472,11 @@ original definition, use \\[elp-restore-function] or \\[elp-restore-all]." (insert atstr)) (insert "\n")))) -(defvar elp-results-symname-map - (let ((map (make-sparse-keymap))) - (define-key map [mouse-2] 'elp-results-jump-to-definition) - (define-key map [follow-link] 'mouse-face) - (define-key map "\C-m" 'elp-results-jump-to-definition) - map) - "Keymap used on the function name column." ) +(defvar-keymap elp-results-symname-map + :doc "Keymap used on the function name column." + "<mouse-2>" #'elp-results-jump-to-definition + "<follow-link>" 'mouse-face + "RET" #'elp-results-jump-to-definition) (defun elp-results-jump-to-definition (&optional event) "Jump to the definition of the function at point." diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 65f76a4fa3..c559dd427c 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -753,17 +753,16 @@ font-lock keywords will not be case sensitive." (progn (forward-sexp 1) (point))))))) -(defvar lisp-mode-shared-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map prog-mode-map) - (define-key map "\e\C-q" 'indent-sexp) - (define-key map "\177" 'backward-delete-char-untabify) - ;; This gets in the way when viewing a Lisp file in view-mode. As - ;; long as [backspace] is mapped into DEL via the - ;; function-key-map, this should remain disabled!! - ;;;(define-key map [backspace] 'backward-delete-char-untabify) - map) - "Keymap for commands shared by all sorts of Lisp modes.") +(defvar-keymap lisp-mode-shared-map + :doc "Keymap for commands shared by all sorts of Lisp modes." + :parent prog-mode-map + "C-M-q" #'indent-sexp + "DEL" #'backward-delete-char-untabify + ;; This gets in the way when viewing a Lisp file in view-mode. As + ;; long as [backspace] is mapped into DEL via the + ;; function-key-map, this should remain disabled!! + ;;;"<backspace>" #'backward-delete-char-untabify + ) (defcustom lisp-mode-hook nil "Hook run when entering Lisp mode." @@ -779,14 +778,12 @@ font-lock keywords will not be case sensitive." ;;; Generic Lisp mode. -(defvar lisp-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map lisp-mode-shared-map) - (define-key map "\e\C-x" 'lisp-eval-defun) - (define-key map "\C-c\C-z" 'run-lisp) - map) - "Keymap for ordinary Lisp mode. -All commands in `lisp-mode-shared-map' are inherited by this map.") +(defvar-keymap lisp-mode-map + :doc "Keymap for ordinary Lisp mode. +All commands in `lisp-mode-shared-map' are inherited by this map." + :parent lisp-mode-shared-map + "C-M-x" #'lisp-eval-defun + "C-c C-z" #'run-lisp) (easy-menu-define lisp-mode-menu lisp-mode-map "Menu for ordinary Lisp mode." diff --git a/lisp/emacs-lisp/re-builder.el b/lisp/emacs-lisp/re-builder.el index 24770fac67..46b429ce6f 100644 --- a/lisp/emacs-lisp/re-builder.el +++ b/lisp/emacs-lisp/re-builder.el @@ -216,19 +216,17 @@ Except for Lisp syntax this is the same as `reb-regexp'.") "Buffer to use for the RE Builder.") ;; Define the local "\C-c" keymap -(defvar reb-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-c\C-c" 'reb-toggle-case) - (define-key map "\C-c\C-q" 'reb-quit) - (define-key map "\C-c\C-w" 'reb-copy) - (define-key map "\C-c\C-s" 'reb-next-match) - (define-key map "\C-c\C-r" 'reb-prev-match) - (define-key map "\C-c\C-i" 'reb-change-syntax) - (define-key map "\C-c\C-e" 'reb-enter-subexp-mode) - (define-key map "\C-c\C-b" 'reb-change-target-buffer) - (define-key map "\C-c\C-u" 'reb-force-update) - map) - "Keymap used by the RE Builder.") +(defvar-keymap reb-mode-map + :doc "Keymap used by the RE Builder." + "C-c C-c" #'reb-toggle-case + "C-c C-q" #'reb-quit + "C-c C-w" #'reb-copy + "C-c C-s" #'reb-next-match + "C-c C-r" #'reb-prev-match + "C-c C-i" #'reb-change-syntax + "C-c C-e" #'reb-enter-subexp-mode + "C-c C-b" #'reb-change-target-buffer + "C-c C-u" #'reb-force-update) (easy-menu-define reb-mode-menu reb-mode-map "Menu for the RE Builder." @@ -263,12 +261,10 @@ Except for Lisp syntax this is the same as `reb-regexp'.") (setq-local blink-matching-paren nil) (reb-mode-common)) -(defvar reb-lisp-mode-map - (let ((map (make-sparse-keymap))) - ;; Use the same "\C-c" keymap as `reb-mode' and use font-locking from - ;; `emacs-lisp-mode' - (define-key map "\C-c" (lookup-key reb-mode-map "\C-c")) - map)) +(defvar-keymap reb-lisp-mode-map + ;; Use the same "\C-c" keymap as `reb-mode' and use font-locking from + ;; `emacs-lisp-mode' + "C-c" (keymap-lookup reb-mode-map "C-c")) (define-derived-mode reb-lisp-mode emacs-lisp-mode "RE Builder Lisp" @@ -278,16 +274,22 @@ Except for Lisp syntax this is the same as `reb-regexp'.") (require 'rx)) ; require rx anyway (reb-mode-common)) -(defvar reb-subexp-mode-map - (let ((m (make-keymap))) - (suppress-keymap m) - ;; Again share the "\C-c" keymap for the commands - (define-key m "\C-c" (lookup-key reb-mode-map "\C-c")) - (define-key m "q" 'reb-quit-subexp-mode) - (dotimes (digit 10) - (define-key m (int-to-string digit) 'reb-display-subexp)) - m) - "Keymap used by the RE Builder for the subexpression mode.") +(defvar-keymap reb-subexp-mode-map + :doc "Keymap used by the RE Builder for the subexpression mode." + :full t :suppress t + ;; Again share the "\C-c" keymap for the commands + "C-c" (keymap-lookup reb-mode-map "C-c") + "q" #'reb-quit-subexp-mode + "0" #'reb-display-subexp + "1" #'reb-display-subexp + "2" #'reb-display-subexp + "3" #'reb-display-subexp + "4" #'reb-display-subexp + "5" #'reb-display-subexp + "6" #'reb-display-subexp + "7" #'reb-display-subexp + "8" #'reb-display-subexp + "9" #'reb-display-subexp) (defun reb-mode-common () "Setup functions common to functions `reb-mode' and `reb-lisp-mode'." diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el index 7d815a3ced..9868d8c4ec 100644 --- a/lisp/emacs-lisp/tabulated-list.el +++ b/lisp/emacs-lisp/tabulated-list.el @@ -216,33 +216,28 @@ If ADVANCE is non-nil, move forward by one line afterwards." (while (re-search-forward re nil 'noerror) (tabulated-list-put-tag empty))))) -(defvar tabulated-list-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map (make-composed-keymap - button-buffer-map - special-mode-map)) - (define-key map "n" 'next-line) - (define-key map "p" 'previous-line) - (define-key map (kbd "M-<left>") 'tabulated-list-previous-column) - (define-key map (kbd "M-<right>") 'tabulated-list-next-column) - (define-key map "S" 'tabulated-list-sort) - (define-key map "}" 'tabulated-list-widen-current-column) - (define-key map "{" 'tabulated-list-narrow-current-column) - (define-key map [follow-link] 'mouse-face) - (define-key map [mouse-2] 'mouse-select-window) - map) - "Local keymap for `tabulated-list-mode' buffers.") - -(defvar tabulated-list-sort-button-map - (let ((map (make-sparse-keymap))) - (define-key map [header-line mouse-1] 'tabulated-list-col-sort) - (define-key map [header-line mouse-2] 'tabulated-list-col-sort) - (define-key map [mouse-1] 'tabulated-list-col-sort) - (define-key map [mouse-2] 'tabulated-list-col-sort) - (define-key map "\C-m" 'tabulated-list-sort) - (define-key map [follow-link] 'mouse-face) - map) - "Local keymap for `tabulated-list-mode' sort buttons.") +(defvar-keymap tabulated-list-mode-map + :doc "Local keymap for `tabulated-list-mode' buffers." + :parent (make-composed-keymap button-buffer-map + special-mode-map) + "n" #'next-line + "p" #'previous-line + "M-<left>" #'tabulated-list-previous-column + "M-<right>" #'tabulated-list-next-column + "S" #'tabulated-list-sort + "}" #'tabulated-list-widen-current-column + "{" #'tabulated-list-narrow-current-column + "<follow-link>" 'mouse-face + "<mouse-2>" #'mouse-select-window) + +(defvar-keymap tabulated-list-sort-button-map + :doc "Local keymap for `tabulated-list-mode' sort buttons." + "<header-line> <mouse-1>" #'tabulated-list-col-sort + "<header-line> <mouse-2>" #'tabulated-list-col-sort + "<mouse-1>" #'tabulated-list-col-sort + "<mouse-2>" #'tabulated-list-col-sort + "RET" #'tabulated-list-sort + "<follow-link>" 'mouse-face) (defun tabulated-list-make-glyphless-char-display-table () "Make the `glyphless-char-display' table used for text-mode frames. diff --git a/lisp/emacs-lisp/timer-list.el b/lisp/emacs-lisp/timer-list.el index aef18d0ba2..8c56108dcb 100644 --- a/lisp/emacs-lisp/timer-list.el +++ b/lisp/emacs-lisp/timer-list.el @@ -81,13 +81,11 @@ ;; doing. Kids, don't try this at home! ;;;###autoload (put 'list-timers 'disabled "Beware: manually canceling timers can ruin your Emacs session.") -(defvar timer-list-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "c" 'timer-list-cancel) - (easy-menu-define nil map "" - '("Timers" - ["Cancel" timer-list-cancel t])) - map)) +(defvar-keymap timer-list-mode-map + "c" #'timer-list-cancel + :menu + '("Timers" + ["Cancel" timer-list-cancel t])) (define-derived-mode timer-list-mode tabulated-list-mode "Timer-List" "Mode for listing and controlling timers." commit 616d3c24e2b75c240065abeb524b3c6613b9bb84 Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 18:19:20 2022 +0200 Document using make-composed-keymap with defvar-keymap * doc/lispref/keymaps.texi (Inheritance and Keymaps): Document using 'make-composed-keymap' with 'defvar-keymap'. * lisp/help-mode.el (help-mode-map): Use defvar-keymap to make this code match the above documentation change. diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index a27b0ea366..9488c4d7b3 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -579,11 +579,10 @@ override any non-@code{nil} binding in any other of the @var{maps}. @code{button-buffer-map} and @code{special-mode-map}: @example -(defvar help-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map - (make-composed-keymap button-buffer-map special-mode-map)) - ... map) ... ) +(defvar-keymap help-mode-map + :parent (make-composed-keymap button-buffer-map + special-mode-map) + ...) @end example diff --git a/lisp/help-mode.el b/lisp/help-mode.el index 219e3c7b86..8b5e48edad 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -31,25 +31,23 @@ (require 'cl-lib) -(defvar help-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map (make-composed-keymap button-buffer-map - special-mode-map)) - (define-key map "n" 'help-goto-next-page) - (define-key map "p" 'help-goto-previous-page) - (define-key map "l" 'help-go-back) - (define-key map "r" 'help-go-forward) - (define-key map "\C-c\C-b" 'help-go-back) - (define-key map "\C-c\C-f" 'help-go-forward) - (define-key map [XF86Back] 'help-go-back) - (define-key map [XF86Forward] 'help-go-forward) - (define-key map "\C-c\C-c" 'help-follow-symbol) - (define-key map "s" 'help-view-source) - (define-key map "I" 'help-goto-lispref-info) - (define-key map "i" 'help-goto-info) - (define-key map "c" 'help-customize) - map) - "Keymap for Help mode.") +(defvar-keymap help-mode-map + :doc "Keymap for Help mode." + :parent (make-composed-keymap button-buffer-map + special-mode-map) + "n" #'help-goto-next-page + "p" #'help-goto-previous-page + "l" #'help-go-back + "r" #'help-go-forward + "C-c C-b" #'help-go-back + "C-c C-f" #'help-go-forward + "<XF86Back>" #'help-go-back + "<XF86Forward>" #'help-go-forward + "C-c C-c" #'help-follow-symbol + "s" #'help-view-source + "I" #'help-goto-lispref-info + "i" #'help-goto-info + "c" #'help-customize) (easy-menu-define help-mode-menu help-mode-map "Menu for Help mode." commit 6d3adedcf136e813daf2eb8ea24c61d27a52bd53 Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 16:58:53 2022 +0200 ; Fix warning in mwheel.el * lisp/mwheel.el (global-text-scale-adjust): Declare function. diff --git a/lisp/mwheel.el b/lisp/mwheel.el index e32f896916..ba5255fc07 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -441,6 +441,7 @@ See also `text-scale-adjust'." (text-scale-decrease 1))) (select-window selected-window)))) +(declare-function global-text-scale-adjust "face-remap.el" (increment)) (defun mouse-wheel-global-text-scale (event) "Increase or decrease the global font size according to the EVENT. This invokes `global-text-scale-adjust', which see." commit 7882c77a1eff9f65682f9425e935626e8f3e99cc Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 16:54:38 2022 +0200 Doc fix; quote keys in face-remap.el * lisp/face-remap.el (text-scale-adjust, global-text-scale-adjust): Doc fix; quote keys. diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 7037bc58cb..467ccbc299 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -372,9 +372,9 @@ INC may be passed as a numeric prefix argument. The actual adjustment made depends on the final component of the keybinding used to invoke the command, with all modifiers removed: - +, = Increase font size in current buffer by one step - - Decrease font size in current buffer by one step - 0 Reset the font size to the global default + \\`+', \\`=' Increase font size in current buffer by one step + \\`-' Decrease font size in current buffer by one step + \\`0' Reset the font size to the global default After adjusting, continue to read input events and further adjust the font size as long as the input event read @@ -479,9 +479,9 @@ Interactively, INCREMENT may be passed as a numeric prefix argument. The adjustment made depends on the final component of the key binding used to invoke the command, with all modifiers removed: - +, = Globally increase the height of the default face - - Globally decrease the height of the default face - 0 Globally reset the height of the default face + \\`+', \\`=' Globally increase the height of the default face + \\`-' Globally decrease the height of the default face + \\`0' Globally reset the height of the default face After adjusting, further adjust the font size as long as the key, with all modifiers removed, is one of the above characters. commit 0b5301fceb7a4a86551ca41e2271c5189e150d87 Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 16:18:54 2022 +0200 Inherit instead of copying keymap in bookmark.el * lisp/bookmark.el (bookmark-rename): Inherit instead of copying keymap. diff --git a/lisp/bookmark.el b/lisp/bookmark.el index 126c25966c..7138822447 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -216,10 +216,10 @@ A non-nil value may result in truncated bookmark names." ;; Set up these bindings dumping time *only*; ;; if the user alters them, don't override the user when loading bookmark.el. -;;;###autoload (define-key ctl-x-r-map "b" 'bookmark-jump) -;;;###autoload (define-key ctl-x-r-map "m" 'bookmark-set) -;;;###autoload (define-key ctl-x-r-map "M" 'bookmark-set-no-overwrite) -;;;###autoload (define-key ctl-x-r-map "l" 'bookmark-bmenu-list) +;;;###autoload (keymap-set ctl-x-r-map "b" #'bookmark-jump) +;;;###autoload (keymap-set ctl-x-r-map "m" #'bookmark-set) +;;;###autoload (keymap-set ctl-x-r-map "M" #'bookmark-set-no-overwrite) +;;;###autoload (keymap-set ctl-x-r-map "l" #'bookmark-bmenu-list) ;;;###autoload (defvar-keymap bookmark-map @@ -1436,9 +1436,9 @@ name." (read-from-minibuffer "New name: " nil - (let ((now-map (copy-keymap minibuffer-local-map))) - (define-key now-map "\C-w" 'bookmark-yank-word) - now-map) + (define-keymap + :parent minibuffer-local-map + "C-w" #'bookmark-yank-word) nil 'bookmark-history)))) (bookmark-set-name old-name final-new-name) commit 599aea301283327a00e57a95c47148d28e93f1fc Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 16:02:26 2022 +0200 * src/keymap.c (Fcopy_keymap): Document using defvar-keymap. diff --git a/src/keymap.c b/src/keymap.c index 2b77a7fc44..506b755e5d 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -1026,8 +1026,14 @@ DEFUN ("copy-keymap", Fcopy_keymap, Scopy_keymap, 1, 1, 0, doc: /* Return a copy of the keymap KEYMAP. Note that this is almost never needed. If you want a keymap that's like -another yet with a few changes, you should use map inheritance rather -than copying. I.e. something like: +another yet with a few changes, you should use keymap inheritance rather +than copying. That is, something like: + + (defvar-keymap foo-map + :parent <theirmap> + ...) + +Or, if you need to support Emacs versions older than 29: (let ((map (make-sparse-keymap))) (set-keymap-parent map <theirmap>) commit cfc754a67c049e9297c19eb5400f8ea38159a0d9 Author: Mattias Engdegård <mattiase@acm.org> Date: Mon Jul 4 15:54:14 2022 +0200 ; remove regexp ambiguity diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 888e339719..65f76a4fa3 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -478,10 +478,10 @@ This will generate compile-time constants from BINDINGS." ;; Words inside \\[], \\<>, \\{} or \\`' tend to be for ;; `substitute-command-keys'. (,(rx "\\\\" (or (seq "[" (group-n 1 lisp-mode-symbol) "]") - (seq "`" (group-n 1 (+ lisp-mode-symbol - ;; allow multiple words, e.g. "C-x a" - (? " "))) - "'"))) + (seq "`" (group-n 1 + ;; allow multiple words, e.g. "C-x a" + lisp-mode-symbol (* " " lisp-mode-symbol)) + "'"))) (1 font-lock-constant-face prepend)) (,(rx "\\\\" (or (seq "<" (group-n 1 lisp-mode-symbol) ">") (seq "{" (group-n 1 lisp-mode-symbol) "}"))) commit 0e5d790c6b8e38bbdffa146085771b7d10e6fc15 Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 15:45:18 2022 +0200 Use substitute-command-keys in Helper-help * lisp/emacs-lisp/helper.el (Helper-help-scroller) (Helper-help-options, Helper-help): Use substitute-command-keys. (Helper-help-map): Prefer defvar-keymap. diff --git a/lisp/emacs-lisp/helper.el b/lisp/emacs-lisp/helper.el index cbc0afc3a7..654dbbc5fe 100644 --- a/lisp/emacs-lisp/helper.el +++ b/lisp/emacs-lisp/helper.el @@ -1,6 +1,6 @@ ;;; helper.el --- utility help package supporting help in electric modes -*- lexical-binding: t; -*- -;; Copyright (C) 1985, 2001-2022 Free Software Foundation, Inc. +;; Copyright (C) 1985-2022 Free Software Foundation, Inc. ;; Author: K. Shane Hartman ;; Maintainer: emacs-devel@gnu.org @@ -39,19 +39,16 @@ ;; keymap either. -(defvar Helper-help-map - (let ((map (make-sparse-keymap))) - ;(fillarray map 'undefined) - (define-key map "m" 'Helper-describe-mode) - (define-key map "b" 'Helper-describe-bindings) - (define-key map "c" 'Helper-describe-key-briefly) - (define-key map "k" 'Helper-describe-key) - ;(define-key map "f" 'Helper-describe-function) - ;(define-key map "v" 'Helper-describe-variable) - (define-key map "?" 'Helper-help-options) - (define-key map (char-to-string help-char) 'Helper-help-options) - (fset 'Helper-help-map map) - map)) +(defvar-keymap Helper-help-map + "m" #'Helper-describe-mode + "b" #'Helper-describe-bindings + "c" #'Helper-describe-key-briefly + "k" #'Helper-describe-key + ;;"f" #'Helper-describe-function + ;;"v" #'Helper-describe-variable + "?" #'Helper-help-options + (key-description (char-to-string help-char)) #'Helper-help-options) +(fset 'Helper-help-map Helper-help-map) (defun Helper-help-scroller () (let ((blurb (or (and (boundp 'Helper-return-blurb) @@ -68,11 +65,13 @@ (setq state (+ (* 2 (if (pos-visible-in-window-p (point-max)) 1 0)) (if (pos-visible-in-window-p (point-min)) 1 0))) (message - (nth state - '("Space forward, Delete back. Other keys %s" - "Space scrolls forward. Other keys %s" - "Delete scrolls back. Other keys %s" - "Type anything to %s")) + (nth state + (mapcar + #'substitute-command-keys + '("\\`SPC' forward, \\`DEL' back. Other keys %s" + "\\`SPC' scrolls forward. Other keys %s" + "\\`DEL' scrolls back. Other keys %s" + "Type anything to %s"))) blurb) (setq continue (read-event)) (cond ((and (memq continue '(?\s ?\C-v)) (< state 2)) @@ -88,8 +87,8 @@ (defun Helper-help-options () "Describe help options." (interactive) - (message "c (key briefly), m (mode), k (key), b (bindings)") - ;(message "c (key briefly), m (mode), k (key), v (variable), f (function)") + (message (substitute-command-keys + "\\`c' (key briefly), \\`m' (mode), \\`k' (key), \\`b' (bindings)")) (sit-for 4)) (defun Helper-describe-key-briefly (key) @@ -142,7 +141,8 @@ (interactive) (let ((continue t) c) (while continue - (message "Help (Type ? for further options)") + (message (substitute-command-keys + "Help (Type \\`?' for further options)")) (setq c (read-key-sequence nil)) (setq c (lookup-key Helper-help-map c)) (cond ((eq c 'Helper-help-options) commit a218921172438a904168cae58142a42ab0d0dd0b Author: Po Lu <luangruo@yahoo.com> Date: Mon Jul 4 21:03:02 2022 +0800 Avoid code duplication converting XI event state in toolkit menu code * src/xmenu.c (x_menu_translate_generic_event): (popup_get_selection): Use `xi_convert_event_state' instead. * src/xterm.c (xi_convert_event_state): Export on non-GTK builds. * src/xterm.h: Update prototypes. diff --git a/src/xmenu.c b/src/xmenu.c index 7134bf22c8..c006d2bfe2 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -261,20 +261,10 @@ x_menu_translate_generic_event (XEvent *event) copy.xbutton.y = lrint (xev->event_y); copy.xbutton.x_root = lrint (xev->root_x); copy.xbutton.y_root = lrint (xev->root_y); - copy.xbutton.state = xev->mods.effective; + copy.xbutton.state = xi_convert_event_state (xev); copy.xbutton.button = xev->detail; copy.xbutton.same_screen = True; - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - copy.xbutton.state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - copy.xbutton.state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - copy.xbutton.state |= Button3Mask; - } - XPutBackEvent (dpyinfo->display, ©); break; @@ -397,7 +387,7 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, copy.xbutton.y = lrint (xev->event_y); copy.xbutton.x_root = lrint (xev->root_x); copy.xbutton.y_root = lrint (xev->root_y); - copy.xbutton.state = xev->mods.effective; + copy.xbutton.state = xi_convert_event_state (xev); copy.xbutton.button = xev->detail; copy.xbutton.same_screen = True; @@ -412,16 +402,6 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, copy.xbutton.state = 0; #endif - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - copy.xbutton.state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - copy.xbutton.state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - copy.xbutton.state |= Button3Mask; - } - break; } case XI_KeyPress: @@ -442,7 +422,7 @@ popup_get_selection (XEvent *initial_event, struct x_display_info *dpyinfo, copy.xkey.y = lrint (xev->event_y); copy.xkey.x_root = lrint (xev->root_x); copy.xkey.y_root = lrint (xev->root_y); - copy.xkey.state = xev->mods.effective; + copy.xkey.state = xi_convert_event_state (xev); copy.xkey.keycode = xev->detail; copy.xkey.same_screen = True; diff --git a/src/xterm.c b/src/xterm.c index e242768c95..82a20ad1a9 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5077,7 +5077,11 @@ xi_convert_button_state (XIButtonState *in, unsigned int *out) } /* Return the modifier state in XEV as a standard X modifier mask. */ -static unsigned int + +#ifdef USE_GTK +static +#endif +unsigned int xi_convert_event_state (XIDeviceEvent *xev) { unsigned int mods, buttons; diff --git a/src/xterm.h b/src/xterm.h index 26d6e4b3d0..b0f9200eea 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1689,6 +1689,9 @@ extern int x_error_message_count; #ifdef HAVE_XINPUT2 extern struct xi_device_t *xi_device_from_id (struct x_display_info *, int); extern bool xi_frame_selected_for (struct frame *, unsigned long); +#ifndef USE_GTK +extern unsigned int xi_convert_event_state (XIDeviceEvent *); +#endif #endif extern void mark_xterm (void); commit c933f988254168ae537301f37841e1f1ebeb42e9 Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 15:06:52 2022 +0200 Fix scrolling backwards in Helper-help * lisp/emacs-lisp/helper.el (Helper-help-scroller): Fix scrolling backwards. diff --git a/lisp/emacs-lisp/helper.el b/lisp/emacs-lisp/helper.el index 930dbfe6c4..cbc0afc3a7 100644 --- a/lisp/emacs-lisp/helper.el +++ b/lisp/emacs-lisp/helper.el @@ -77,9 +77,11 @@ (setq continue (read-event)) (cond ((and (memq continue '(?\s ?\C-v)) (< state 2)) (scroll-up)) - ((= continue ?\C-l) + ((eq continue ?\C-l) (recenter)) - ((and (= continue ?\177) (zerop (% state 2))) + ((and (or (eq continue 'backspace) + (eq continue ?\177)) + (zerop (% state 2))) (scroll-down)) (t (setq continue nil)))))))) commit 1268902db17501862e5efbd51a41108ffc5105f3 Author: Mattias Engdegård <mattiase@acm.org> Date: Mon Jul 4 14:52:50 2022 +0200 Remove some useless `eval-when-compile` * lisp/cedet/semantic/java.el (semantic-java-number-regexp): * lisp/cedet/semantic/lex.el (semantic-lex-number-expression): * lisp/emacs-lisp/cl-indent.el (common-lisp-indent-function-1): * lisp/emacs-lisp/lisp-mode.el (lisp-imenu-generic-expression) (lisp--el-match-keyword, lisp-string-in-doc-position-p): * lisp/emacs-lisp/shorthands.el (shorthands-font-lock-shorthands): * lisp/net/socks.el (socks-send-command): * lisp/progmodes/meta-mode.el (meta-font-lock-keywords): * lisp/shell.el (shell--parse-pcomplete-arguments): * lisp/textmodes/sgml-mode.el (sgml-mode): * lisp/textmodes/tex-mode.el (tex--guess-mode) (tex-common-initialization, tex-input-files-re): * lisp/textmodes/tildify.el (tildify-mode): * lisp/xdg.el (xdg-line-regexp): Eliminate `eval-when-compile` when the argument would be evaluated by the compiler anyway. diff --git a/lisp/cedet/semantic/java.el b/lisp/cedet/semantic/java.el index 9b70afd0a3..53fd4de297 100644 --- a/lisp/cedet/semantic/java.el +++ b/lisp/cedet/semantic/java.el @@ -37,25 +37,24 @@ ;;; Lexical analysis ;; (defconst semantic-java-number-regexp - (eval-when-compile - (concat "\\(" - "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>" - "\\|" - "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>" - "\\|" - "\\<[0-9]+[.][fFdD]\\>" - "\\|" - "\\<[0-9]+[.]" - "\\|" - "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>" - "\\|" - "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>" - "\\|" - "\\<0[xX][[:xdigit:]]+[lL]?\\>" - "\\|" - "\\<[0-9]+[lLfFdD]?\\>" - "\\)" - )) + (concat "\\(" + "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>" + "\\|" + "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>" + "\\|" + "\\<[0-9]+[.][fFdD]\\>" + "\\|" + "\\<[0-9]+[.]" + "\\|" + "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>" + "\\|" + "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>" + "\\|" + "\\<0[xX][[:xdigit:]]+[lL]?\\>" + "\\|" + "\\<[0-9]+[lLfFdD]?\\>" + "\\)" + ) "Lexer regexp to match Java number terminals. Following is the specification of Java number literals. diff --git a/lisp/cedet/semantic/lex.el b/lisp/cedet/semantic/lex.el index 885ffbf5a7..9c64cc9f7e 100644 --- a/lisp/cedet/semantic/lex.el +++ b/lisp/cedet/semantic/lex.el @@ -574,25 +574,24 @@ may need to be overridden for some special languages.") (defvar-local semantic-lex-number-expression ;; This expression was written by David Ponce for Java, and copied ;; here for C and any other similar language. - (eval-when-compile - (concat "\\(" - "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>" - "\\|" - "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>" - "\\|" - "\\<[0-9]+[.][fFdD]\\>" - "\\|" - "\\<[0-9]+[.]" - "\\|" - "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>" - "\\|" - "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>" - "\\|" - "\\<0[xX][[:xdigit:]]+[lL]?\\>" - "\\|" - "\\<[0-9]+[lLfFdD]?\\>" - "\\)" - )) + (concat "\\(" + "\\<[0-9]+[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>" + "\\|" + "\\<[0-9]+[.][eE][-+]?[0-9]+[fFdD]?\\>" + "\\|" + "\\<[0-9]+[.][fFdD]\\>" + "\\|" + "\\<[0-9]+[.]" + "\\|" + "[.][0-9]+\\([eE][-+]?[0-9]+\\)?[fFdD]?\\>" + "\\|" + "\\<[0-9]+[eE][-+]?[0-9]+[fFdD]?\\>" + "\\|" + "\\<0[xX][[:xdigit:]]+[lL]?\\>" + "\\|" + "\\<[0-9]+[lLfFdD]?\\>" + "\\)" + ) "Regular expression for matching a number. If this value is nil, no number extraction is done during lex. This expression tries to match C and Java like numbers. diff --git a/lisp/emacs-lisp/cl-indent.el b/lisp/emacs-lisp/cl-indent.el index 213eecf88d..fe7e4506d7 100644 --- a/lisp/emacs-lisp/cl-indent.el +++ b/lisp/emacs-lisp/cl-indent.el @@ -378,10 +378,9 @@ instead." function) (setq tentative-defun t)) ((string-match - (eval-when-compile - (concat "\\`\\(" - (regexp-opt '("with" "without" "do")) - "\\)-")) + (concat "\\`\\(" + (regexp-opt '("with" "without" "do")) + "\\)-") function) (setq method '(&lambda &body)))))) ;; backwards compatibility. Bletch. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index ab572d5795..888e339719 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -100,48 +100,45 @@ (list (list nil (purecopy (concat "^\\s-*(" - (eval-when-compile - (regexp-opt - '("defun" "defmacro" - ;; Elisp. - "defun*" "defsubst" "define-inline" - "define-advice" "defadvice" "define-skeleton" - "define-compilation-mode" "define-minor-mode" - "define-global-minor-mode" - "define-globalized-minor-mode" - "define-derived-mode" "define-generic-mode" - "ert-deftest" - "cl-defun" "cl-defsubst" "cl-defmacro" - "cl-define-compiler-macro" "cl-defgeneric" - "cl-defmethod" - ;; CL. - "define-compiler-macro" "define-modify-macro" - "defsetf" "define-setf-expander" - "define-method-combination" - ;; CLOS and EIEIO - "defgeneric" "defmethod") - t)) + (regexp-opt + '("defun" "defmacro" + ;; Elisp. + "defun*" "defsubst" "define-inline" + "define-advice" "defadvice" "define-skeleton" + "define-compilation-mode" "define-minor-mode" + "define-global-minor-mode" + "define-globalized-minor-mode" + "define-derived-mode" "define-generic-mode" + "ert-deftest" + "cl-defun" "cl-defsubst" "cl-defmacro" + "cl-define-compiler-macro" "cl-defgeneric" + "cl-defmethod" + ;; CL. + "define-compiler-macro" "define-modify-macro" + "defsetf" "define-setf-expander" + "define-method-combination" + ;; CLOS and EIEIO + "defgeneric" "defmethod") + t) "\\s-+\\(" (rx lisp-mode-symbol) "\\)")) 2) ;; Like the previous, but uses a quoted symbol as the name. (list nil (purecopy (concat "^\\s-*(" - (eval-when-compile - (regexp-opt - '("defalias" "define-obsolete-function-alias") - t)) + (regexp-opt + '("defalias" "define-obsolete-function-alias") + t) "\\s-+'\\(" (rx lisp-mode-symbol) "\\)")) 2) (list (purecopy "Variables") (purecopy (concat "^\\s-*(" - (eval-when-compile - (regexp-opt - '(;; Elisp - "defconst" "defcustom" - ;; CL - "defconstant" - "defparameter" "define-symbol-macro") - t)) + (regexp-opt + '(;; Elisp + "defconst" "defcustom" + ;; CL + "defconstant" + "defparameter" "define-symbol-macro") + t) "\\s-+\\(" (rx lisp-mode-symbol) "\\)")) 2) ;; For `defvar'/`defvar-local', we ignore (defvar FOO) constructs. @@ -152,18 +149,17 @@ 1) (list (purecopy "Types") (purecopy (concat "^\\s-*(" - (eval-when-compile - (regexp-opt - '(;; Elisp - "defgroup" "deftheme" - "define-widget" "define-error" - "defface" "cl-deftype" "cl-defstruct" - ;; CL - "deftype" "defstruct" - "define-condition" "defpackage" - ;; CLOS and EIEIO - "defclass") - t)) + (regexp-opt + '(;; Elisp + "defgroup" "deftheme" + "define-widget" "define-error" + "defface" "cl-deftype" "cl-defstruct" + ;; CL + "deftype" "defstruct" + "define-condition" "defpackage" + ;; CLOS and EIEIO + "defclass") + t) "\\s-+'?\\(" (rx lisp-mode-symbol) "\\)")) 2)) @@ -273,8 +269,7 @@ to a package-local <package>-loaddefs.el file.") ;; FIXME: Move to elisp-mode.el. (catch 'found (while (re-search-forward - (eval-when-compile - (concat "(\\(" (rx lisp-mode-symbol) "\\)\\_>")) + (concat "(\\(" (rx lisp-mode-symbol) "\\)\\_>") limit t) (let ((sym (intern-soft (match-string 1)))) (when (and (or (special-form-p sym) (macrop sym)) @@ -591,16 +586,15 @@ This will generate compile-time constants from BINDINGS." "Gaudy highlighting from Emacs Lisp mode used in Backtrace mode.") (defun lisp-string-in-doc-position-p (listbeg startpos) - "Return non-nil if a doc string may occur at STARTPOS inside a list. + "Return non-nil if a doc string may occur at STARTPOS inside a list. LISTBEG is the position of the start of the innermost list containing STARTPOS." (let* ((firstsym (and listbeg (save-excursion (goto-char listbeg) (and (looking-at - (eval-when-compile - (concat "([ \t\n]*\\(" - (rx lisp-mode-symbol) "\\)"))) + (concat "([ \t\n]*\\(" + (rx lisp-mode-symbol) "\\)")) (match-string 1))))) (docelt (and firstsym (function-get (intern-soft firstsym) diff --git a/lisp/emacs-lisp/shorthands.el b/lisp/emacs-lisp/shorthands.el index 75cbe5f192..ffd3856db6 100644 --- a/lisp/emacs-lisp/shorthands.el +++ b/lisp/emacs-lisp/shorthands.el @@ -61,8 +61,7 @@ (defun shorthands-font-lock-shorthands (limit) (when read-symbol-shorthands (while (re-search-forward - (eval-when-compile - (concat "\\_<\\(" (rx lisp-mode-symbol) "\\)\\_>")) + (concat "\\_<\\(" (rx lisp-mode-symbol) "\\)\\_>") limit t) (let* ((existing (get-text-property (match-beginning 1) 'face)) (probe (and (not (memq existing '(font-lock-comment-face diff --git a/lisp/net/socks.el b/lisp/net/socks.el index 8df0773e1d..2ba1c20566 100644 --- a/lisp/net/socks.el +++ b/lisp/net/socks.el @@ -407,11 +407,10 @@ When ATYPE indicates an IP, param ADDRESS must be given as raw bytes." (setq version (process-get proc 'socks-server-protocol)) (cond ((equal version 'http) - (setq request (format (eval-when-compile - (concat - "CONNECT %s:%d HTTP/1.0\r\n" - "User-Agent: Emacs/SOCKS v1.0\r\n" - "\r\n")) + (setq request (format (concat + "CONNECT %s:%d HTTP/1.0\r\n" + "User-Agent: Emacs/SOCKS v1.0\r\n" + "\r\n") (cond ((equal atype socks-address-type-name) address) (t diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el index 5aaa277431..34288e0e4f 100644 --- a/lisp/progmodes/meta-mode.el +++ b/lisp/progmodes/meta-mode.el @@ -108,30 +108,27 @@ (macro-keywords-2 "\\(primarydef\\|secondarydef\\|tertiarydef\\)") (args-keywords - (eval-when-compile - (regexp-opt - '("expr" "suffix" "text" "primary" "secondary" "tertiary") - t))) + (regexp-opt + '("expr" "suffix" "text" "primary" "secondary" "tertiary") + t)) (type-keywords - (eval-when-compile - (regexp-opt - '("boolean" "color" "numeric" "pair" "path" "pen" "picture" - "string" "transform" "newinternal") - t))) + (regexp-opt + '("boolean" "color" "numeric" "pair" "path" "pen" "picture" + "string" "transform" "newinternal") + t)) (syntactic-keywords - (eval-when-compile - (regexp-opt - '("for" "forever" "forsuffixes" "endfor" - "step" "until" "upto" "downto" "thru" "within" - "iff" "if" "elseif" "else" "fi" "exitif" "exitunless" - "let" "def" "vardef" "enddef" "mode_def" - "true" "false" "known" "unknown" "and" "or" "not" - "save" "interim" "inner" "outer" "relax" - "begingroup" "endgroup" "expandafter" "scantokens" - "generate" "input" "endinput" "end" "bye" - "message" "errmessage" "errhelp" "special" "numspecial" - "readstring" "readfrom" "write") - t))) + (regexp-opt + '("for" "forever" "forsuffixes" "endfor" + "step" "until" "upto" "downto" "thru" "within" + "iff" "if" "elseif" "else" "fi" "exitif" "exitunless" + "let" "def" "vardef" "enddef" "mode_def" + "true" "false" "known" "unknown" "and" "or" "not" + "save" "interim" "inner" "outer" "relax" + "begingroup" "endgroup" "expandafter" "scantokens" + "generate" "input" "endinput" "end" "bye" + "message" "errmessage" "errhelp" "special" "numspecial" + "readstring" "readfrom" "write") + t)) ) (list ;; embedded TeX code in btex ... etex diff --git a/lisp/shell.el b/lisp/shell.el index 8bcc578406..85225b128a 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -440,12 +440,11 @@ Useful for shells like zsh that has this feature." (push (point) begins) (let ((arg ())) (while (looking-at - (eval-when-compile - (concat - "\\(?:[^\s\t\n\\\"';]+" - "\\|'\\([^']*\\)'?" - "\\|\"\\(\\(?:[^\"\\]\\|\\\\.\\)*\\)\"?" - "\\|\\\\\\(\\(?:.\\|\n\\)?\\)\\)"))) + (concat + "\\(?:[^\s\t\n\\\"';]+" + "\\|'\\([^']*\\)'?" + "\\|\"\\(\\(?:[^\"\\]\\|\\\\.\\)*\\)\"?" + "\\|\\\\\\(\\(?:.\\|\n\\)?\\)\\)")) (goto-char (match-end 0)) (cond ((match-beginning 3) ;Backslash escape. diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index ff881377a7..13ff3dcab6 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el @@ -600,12 +600,11 @@ Do \\[describe-key] on the following bindings to discover what they do. (setq-local tildify-foreach-region-function (apply-partially 'tildify-foreach-ignore-environments - `((,(eval-when-compile - (concat - "<\\(" - (regexp-opt '("pre" "dfn" "code" "samp" "kbd" "var" - "PRE" "DFN" "CODE" "SAMP" "KBD" "VAR")) - "\\)\\>[^>]*>")) + `((,(concat + "<\\(" + (regexp-opt '("pre" "dfn" "code" "samp" "kbd" "var" + "PRE" "DFN" "CODE" "SAMP" "KBD" "VAR")) + "\\)\\>[^>]*>") . ("</" 1 ">")) ("<! *--" . "-- *>") ("<" . ">")))) diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el index 473643bb48..e90d214a12 100644 --- a/lisp/textmodes/tex-mode.el +++ b/lisp/textmodes/tex-mode.el @@ -983,14 +983,13 @@ Inherits `shell-mode-map' with a few additions.") (when (and slash (not comment)) (setq mode (if (looking-at - (eval-when-compile - (concat - (regexp-opt '("documentstyle" "documentclass" - "begin" "subsection" "section" - "part" "chapter" "newcommand" - "renewcommand" "RequirePackage") - 'words) - "\\|NeedsTeXFormat{LaTeX"))) + (concat + (regexp-opt '("documentstyle" "documentclass" + "begin" "subsection" "section" + "part" "chapter" "newcommand" + "renewcommand" "RequirePackage") + 'words) + "\\|NeedsTeXFormat{LaTeX")) (if (and (looking-at "document\\(style\\|class\\)\\(\\[.*\\]\\)?{slides}") ;; SliTeX is almost never used any more nowadays. @@ -1242,11 +1241,10 @@ Entering SliTeX mode runs the hook `text-mode-hook', then the hook (apply-partially #'tildify-foreach-ignore-environments `(("\\\\\\\\" . "") ; do not remove this - (,(eval-when-compile - (concat "\\\\begin{\\(" - (regexp-opt '("verbatim" "math" "displaymath" - "equation" "eqnarray" "eqnarray*")) - "\\)}")) + (,(concat "\\\\begin{\\(" + (regexp-opt '("verbatim" "math" "displaymath" + "equation" "eqnarray" "eqnarray*")) + "\\)}") . ("\\\\end{" 1 "}")) ("\\\\verb\\*?\\(.\\)" . (1)) ("\\$\\$?" . (0)) @@ -2126,11 +2124,10 @@ If NOT-ALL is non-nil, save the `.dvi' file." (defvar tex-compile-history nil) (defvar tex-input-files-re - (eval-when-compile - (concat "\\." (regexp-opt '("tex" "texi" "texinfo" - "bbl" "ind" "sty" "cls") t) - ;; Include files with no dots (for directories). - "\\'\\|\\`[^.]+\\'"))) + (concat "\\." (regexp-opt '("tex" "texi" "texinfo" + "bbl" "ind" "sty" "cls") t) + ;; Include files with no dots (for directories). + "\\'\\|\\`[^.]+\\'")) (defcustom tex-use-reftex t "If non-nil, use RefTeX's list of files to determine what command to use." diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el index 9dcfb10d6d..2a7ad295ab 100644 --- a/lisp/textmodes/tildify.el +++ b/lisp/textmodes/tildify.el @@ -494,9 +494,8 @@ variable will be set to the representation." (if (not (string-equal " " (or space tildify-space-string))) (when space (setq tildify-space-string space)) - (message (eval-when-compile - (concat "Hard space is a single space character, tildify-" - "mode won't have any effect, disabling."))) + (message (concat "Hard space is a single space character, tildify-" + "mode won't have any effect, disabling.")) (setq tildify-mode nil)))) (if tildify-mode (add-hook 'post-self-insert-hook #'tildify-space nil t) diff --git a/lisp/xdg.el b/lisp/xdg.el index 6a0b1dedd1..c7d9c0e785 100644 --- a/lisp/xdg.el +++ b/lisp/xdg.el @@ -171,13 +171,12 @@ file:///foo/bar.jpg" ;; https://www.freedesktop.org/wiki/Software/xdg-user-dirs/ (defconst xdg-line-regexp - (eval-when-compile - (rx "XDG_" - (group-n 1 (or "DESKTOP" "DOWNLOAD" "TEMPLATES" "PUBLICSHARE" - "DOCUMENTS" "MUSIC" "PICTURES" "VIDEOS")) - "_DIR=\"" - (group-n 2 (or "/" "$HOME/") (*? (or (not (any "\"")) "\\\""))) - "\"")) + (rx "XDG_" + (group-n 1 (or "DESKTOP" "DOWNLOAD" "TEMPLATES" "PUBLICSHARE" + "DOCUMENTS" "MUSIC" "PICTURES" "VIDEOS")) + "_DIR=\"" + (group-n 2 (or "/" "$HOME/") (*? (or (not (any "\"")) "\\\""))) + "\"") "Regexp matching non-comment lines in `xdg-user-dirs' config files.") (defvar xdg-user-dirs nil commit 544361d37f3877b2f10c362936a283f4a0b2fa71 Author: Mattias Engdegård <mattiase@acm.org> Date: Mon Jul 4 14:12:24 2022 +0200 Replace lisp-mode-symbol-regexp with (rx lisp-mode-symbol) This is shorter, simplifies use inside rx expressions, and removes need for eval-when-compile elsewhere (for later exploitation). * lisp/emacs-lisp/lisp-mode.el (lisp-mode-symbol): New rx-define. (lisp-mode-symbol-regexp): Redefine using lisp-mode-symbol. (lisp-imenu-generic-expression, lisp--el-match-keyword) (lisp-fdefs, lisp-string-in-doc-position-p): * lisp/emacs-lisp/checkdoc.el (checkdoc--error-bad-format-p): * lisp/emacs-lisp/shorthands.el (shorthands-font-lock-shorthands): Use lisp-mode-symbol instead of lisp-mode-symbol-regexp. diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index 2cb5fa120e..2c9adfe2d2 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -165,7 +165,7 @@ (require 'cl-lib) (require 'help-mode) ;; for help-xref-info-regexp (require 'thingatpt) ;; for handy thing-at-point-looking-at -(require 'lisp-mode) ;; for lisp-mode-symbol-regexp +(require 'lisp-mode) ;; for lisp-mode-symbol regexp (eval-when-compile (require 'dired)) ;; for dired-map-over-marks (require 'lisp-mnt) @@ -2604,13 +2604,13 @@ The correct format is \"Foo\" or \"some-symbol: Foo\". See also (unless (let ((case-fold-search nil)) (looking-at (rx (or upper-case "%s")))) ;; A defined Lisp symbol is always okay. - (unless (and (looking-at (rx (group (regexp lisp-mode-symbol-regexp)))) + (unless (and (looking-at (rx (group lisp-mode-symbol))) (or (fboundp (intern (match-string 1))) (boundp (intern (match-string 1))))) ;; Other Lisp symbols are sometimes okay. (rx-let ((c (? "\\\n"))) ; `c' is for a continued line (let ((case-fold-search nil) - (some-symbol (rx (regexp lisp-mode-symbol-regexp) + (some-symbol (rx lisp-mode-symbol c ":" c (+ (any " \t\n")))) (lowercase-str (rx c (group (any "a-z") (+ wordchar))))) (if (looking-at some-symbol) diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index d61432b7dd..ab572d5795 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -89,8 +89,12 @@ table) "Syntax table used in `lisp-mode'.") +(rx-define lisp-mode-symbol (+ (| (syntax word) + (syntax symbol) + (: "\\" nonl)))) + (eval-and-compile - (defconst lisp-mode-symbol-regexp "\\(?:\\sw\\|\\s_\\|\\\\.\\)+")) + (defconst lisp-mode-symbol-regexp (rx lisp-mode-symbol))) (defvar lisp-imenu-generic-expression (list @@ -117,7 +121,7 @@ ;; CLOS and EIEIO "defgeneric" "defmethod") t)) - "\\s-+\\(" lisp-mode-symbol-regexp "\\)")) + "\\s-+\\(" (rx lisp-mode-symbol) "\\)")) 2) ;; Like the previous, but uses a quoted symbol as the name. (list nil @@ -126,7 +130,7 @@ (regexp-opt '("defalias" "define-obsolete-function-alias") t)) - "\\s-+'\\(" lisp-mode-symbol-regexp "\\)")) + "\\s-+'\\(" (rx lisp-mode-symbol) "\\)")) 2) (list (purecopy "Variables") (purecopy (concat "^\\s-*(" @@ -138,12 +142,12 @@ "defconstant" "defparameter" "define-symbol-macro") t)) - "\\s-+\\(" lisp-mode-symbol-regexp "\\)")) + "\\s-+\\(" (rx lisp-mode-symbol) "\\)")) 2) ;; For `defvar'/`defvar-local', we ignore (defvar FOO) constructs. (list (purecopy "Variables") (purecopy (concat "^\\s-*(defvar\\(?:-local\\)?\\s-+\\(" - lisp-mode-symbol-regexp "\\)" + (rx lisp-mode-symbol) "\\)" "[[:space:]\n]+[^)]")) 1) (list (purecopy "Types") @@ -160,7 +164,7 @@ ;; CLOS and EIEIO "defclass") t)) - "\\s-+'?\\(" lisp-mode-symbol-regexp "\\)")) + "\\s-+'?\\(" (rx lisp-mode-symbol) "\\)")) 2)) "Imenu generic expression for Lisp mode. See `imenu-generic-expression'.") @@ -270,7 +274,7 @@ to a package-local <package>-loaddefs.el file.") (catch 'found (while (re-search-forward (eval-when-compile - (concat "(\\(" lisp-mode-symbol-regexp "\\)\\_>")) + (concat "(\\(" (rx lisp-mode-symbol) "\\)\\_>")) limit t) (let ((sym (intern-soft (match-string 1)))) (when (and (or (special-form-p sym) (macrop sym)) @@ -419,8 +423,8 @@ This will generate compile-time constants from BINDINGS." ;; Any whitespace and defined object. "[ \t']*" "\\(([ \t']*\\)?" ;; An opening paren. - "\\(\\(setf\\)[ \t]+" lisp-mode-symbol-regexp - "\\|" lisp-mode-symbol-regexp "\\)?") + "\\(\\(setf\\)[ \t]+" (rx lisp-mode-symbol) + "\\|" (rx lisp-mode-symbol) "\\)?") (1 font-lock-keyword-face) (3 (let ((type (get (intern-soft (match-string 1)) 'lisp-define-type))) (cond ((eq type 'var) font-lock-variable-name-face) @@ -446,8 +450,8 @@ This will generate compile-time constants from BINDINGS." ;; Any whitespace and defined object. "[ \t']*" "\\(([ \t']*\\)?" ;; An opening paren. - "\\(\\(setf\\)[ \t]+" lisp-mode-symbol-regexp - "\\|" lisp-mode-symbol-regexp "\\)?") + "\\(\\(setf\\)[ \t]+" (rx lisp-mode-symbol) + "\\|" (rx lisp-mode-symbol) "\\)?") (1 font-lock-keyword-face) (3 (let ((type (get (intern-soft (match-string 1)) 'lisp-define-type))) (cond ((eq type 'var) font-lock-variable-name-face) @@ -473,34 +477,34 @@ This will generate compile-time constants from BINDINGS." (lisp--el-match-keyword . 1) ;; Exit/Feature symbols as constants. (,(concat "(\\(catch\\|throw\\|featurep\\|provide\\|require\\)\\_>" - "[ \t']*\\(" lisp-mode-symbol-regexp "\\)?") + "[ \t']*\\(" (rx lisp-mode-symbol) "\\)?") (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) ;; Words inside \\[], \\<>, \\{} or \\`' tend to be for ;; `substitute-command-keys'. - (,(rx "\\\\" (or (seq "[" (group-n 1 (regexp lisp-mode-symbol-regexp)) "]") - (seq "`" (group-n 1 (+ (regexp lisp-mode-symbol-regexp) + (,(rx "\\\\" (or (seq "[" (group-n 1 lisp-mode-symbol) "]") + (seq "`" (group-n 1 (+ lisp-mode-symbol ;; allow multiple words, e.g. "C-x a" (? " "))) "'"))) (1 font-lock-constant-face prepend)) - (,(rx "\\\\" (or (seq "<" (group-n 1 (regexp lisp-mode-symbol-regexp)) ">") - (seq "{" (group-n 1 (regexp lisp-mode-symbol-regexp)) "}"))) + (,(rx "\\\\" (or (seq "<" (group-n 1 lisp-mode-symbol) ">") + (seq "{" (group-n 1 lisp-mode-symbol) "}"))) (1 font-lock-variable-name-face prepend)) ;; Ineffective backslashes (typically in need of doubling). ("\\(\\\\\\)\\([^\"\\]\\)" (1 (elisp--font-lock-backslash) prepend)) ;; Words inside ‘’, '' and `' tend to be symbol names. - (,(concat "[`‘']\\(" lisp-mode-symbol-regexp "\\)['’]") + (,(concat "[`‘']\\(" (rx lisp-mode-symbol) "\\)['’]") (1 font-lock-constant-face prepend)) ;; \\= tends to be an escape in doc strings. (,(rx "\\\\=") (0 font-lock-builtin-face prepend)) ;; Constant values. - (,(concat "\\_<:" lisp-mode-symbol-regexp "\\_>") + (,(concat "\\_<:" (rx lisp-mode-symbol) "\\_>") (0 font-lock-builtin-face)) ;; ELisp and CLisp `&' keywords as types. - (,(concat "\\_<&" lisp-mode-symbol-regexp "\\_>") + (,(concat "\\_<&" (rx lisp-mode-symbol) "\\_>") . font-lock-type-face) ;; ELisp regexp grouping constructs (,(lambda (bound) @@ -537,30 +541,30 @@ This will generate compile-time constants from BINDINGS." (,(concat "(" cl-kws-re "\\_>") . 1) ;; Exit/Feature symbols as constants. (,(concat "(\\(catch\\|throw\\|provide\\|require\\)\\_>" - "[ \t']*\\(" lisp-mode-symbol-regexp "\\)?") + "[ \t']*\\(" (rx lisp-mode-symbol) "\\)?") (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) ;; Erroneous structures. (,(concat "(" cl-errs-re "\\_>") (1 font-lock-warning-face)) ;; Words inside ‘’ and `' tend to be symbol names. - (,(concat "[`‘]\\(" lisp-mode-symbol-regexp "\\)['’]") + (,(concat "[`‘]\\(" (rx lisp-mode-symbol) "\\)['’]") (1 font-lock-constant-face prepend)) ;; Uninterned symbols, e.g., (defpackage #:my-package ...) ;; must come before keywords below to have effect - (,(concat "#:" lisp-mode-symbol-regexp "") 0 font-lock-builtin-face) + (,(concat "#:" (rx lisp-mode-symbol) "") 0 font-lock-builtin-face) ;; Constant values. - (,(concat "\\_<:" lisp-mode-symbol-regexp "\\_>") + (,(concat "\\_<:" (rx lisp-mode-symbol) "\\_>") (0 font-lock-builtin-face)) ;; ELisp and CLisp `&' keywords as types. - (,(concat "\\_<&" lisp-mode-symbol-regexp "\\_>") + (,(concat "\\_<&" (rx lisp-mode-symbol) "\\_>") . font-lock-type-face) ;; This is too general -- rms. ;; A user complained that he has functions whose names start with `do' ;; and that they get the wrong color. ;; That user has violated the https://www.cliki.net/Naming+conventions: ;; CL (but not EL!) `with-' (context) and `do-' (iteration) - (,(concat "(\\(\\(do-\\|with-\\)" lisp-mode-symbol-regexp "\\)") + (,(concat "(\\(\\(do-\\|with-\\)" (rx lisp-mode-symbol) "\\)") (1 font-lock-keyword-face)) (lisp--match-hidden-arg (0 '(face font-lock-warning-face @@ -596,7 +600,7 @@ containing STARTPOS." (and (looking-at (eval-when-compile (concat "([ \t\n]*\\(" - lisp-mode-symbol-regexp "\\)"))) + (rx lisp-mode-symbol) "\\)"))) (match-string 1))))) (docelt (and firstsym (function-get (intern-soft firstsym) diff --git a/lisp/emacs-lisp/shorthands.el b/lisp/emacs-lisp/shorthands.el index a9e4343715..75cbe5f192 100644 --- a/lisp/emacs-lisp/shorthands.el +++ b/lisp/emacs-lisp/shorthands.el @@ -62,7 +62,7 @@ (when read-symbol-shorthands (while (re-search-forward (eval-when-compile - (concat "\\_<\\(" lisp-mode-symbol-regexp "\\)\\_>")) + (concat "\\_<\\(" (rx lisp-mode-symbol) "\\)\\_>")) limit t) (let* ((existing (get-text-property (match-beginning 1) 'face)) (probe (and (not (memq existing '(font-lock-comment-face commit 65df97f361ace8b7f272d050b56389eeb1a08b03 Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 14:53:16 2022 +0200 * lisp/progmodes/ebrowse.el (ebrowse-tree-mode): Fix typo. diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el index 16069f75ae..16b2f3ff50 100644 --- a/lisp/progmodes/ebrowse.el +++ b/lisp/progmodes/ebrowse.el @@ -996,7 +996,7 @@ if for some reason a circle is in the inheritance graph." Each line corresponds to a class in a class tree. Letters do not insert themselves, they are commands. File operations in the tree buffer work on class tree data structures. -E.g.\\[save-buffer] writes the tree to the file it was loaded from. +E.g. \\[save-buffer] writes the tree to the file it was loaded from. Tree mode key bindings: \\{ebrowse-tree-mode-map}" commit a5f5f6c0ab5fd088f827eb53dac5dd3bcdace3f5 Author: Stefan Kangas <stefan@marxist.se> Date: Mon Jul 4 14:10:04 2022 +0200 Remove remaining Helper-help support from view-mode * lisp/view.el (view-old-Helper-return-blurb): Make obsolete. (view--enable, view--disable): Delete remaining Helper-help support code; view-mode stopped using it in 1995. diff --git a/lisp/view.el b/lisp/view.el index 3343136c1c..17bc46d4c4 100644 --- a/lisp/view.el +++ b/lisp/view.el @@ -1,7 +1,6 @@ ;;; view.el --- peruse file or buffer without editing -*- lexical-binding: t -*- -;; Copyright (C) 1985, 1989, 1994-1995, 1997, 2000-2022 Free Software -;; Foundation, Inc. +;; Copyright (C) 1985-2022 Free Software Foundation, Inc. ;; Author: K. Shane Hartman ;; Maintainer: emacs-devel@gnu.org @@ -26,9 +25,11 @@ ;; This package provides the `view' minor mode documented in the Emacs ;; user's manual. +;; ;; View mode entry and exit is done through the functions `view-mode-enter' ;; and `view-mode-exit'. Use these functions to enter or exit `view-mode' from ;; Emacs Lisp programs. +;; ;; We use both view- and View- as prefix for symbols. View- is used as ;; prefix for commands that have a key binding. view- is used for commands ;; without key binding. The purpose of this is to make it easier for a @@ -101,8 +102,6 @@ functions that enable or disable view mode.") (defvar-local view-old-buffer-read-only nil) -(defvar-local view-old-Helper-return-blurb nil) - (defvar-local view-page-size nil "Default number of lines to scroll by View page commands. If nil that means use the window size.") @@ -454,15 +453,7 @@ Entry to view-mode runs the normal hook `view-mode-hook'." (setq view-page-size nil view-half-page-size nil view-old-buffer-read-only buffer-read-only - buffer-read-only t) - (if (boundp 'Helper-return-blurb) - (setq view-old-Helper-return-blurb (and (boundp 'Helper-return-blurb) - Helper-return-blurb) - Helper-return-blurb - (format "continue viewing %s" - (if (buffer-file-name) - (file-name-nondirectory (buffer-file-name)) - (buffer-name)))))) + buffer-read-only t)) (define-obsolete-function-alias 'view-mode-enable 'view-mode "24.4") @@ -482,8 +473,6 @@ Entry to view-mode runs the normal hook `view-mode-hook'." ;; so that View mode stays off if read-only-mode is called. (if (local-variable-p 'view-read-only) (kill-local-variable 'view-read-only)) - (if (boundp 'Helper-return-blurb) - (setq Helper-return-blurb view-old-Helper-return-blurb)) (if buffer-read-only (setq buffer-read-only view-old-buffer-read-only))) @@ -988,6 +977,9 @@ If TIMES is negative, search backwards." (and (zerop times) (looking-at ".*"))) +(defvar-local view-old-Helper-return-blurb nil) +(make-obsolete 'view-old-Helper-return-blurb nil "29.1") + (provide 'view) ;;; view.el ends here commit a525c9f5c96c2798185bb52ab2894305fb32966f Author: Eli Zaretskii <eliz@gnu.org> Date: Mon Jul 4 15:13:12 2022 +0300 ; Fix doc strings in help-fns.el * lisp/help-fns.el (help-fns-edit-mode-done) (help-fns-edit-mode-cancel): Doc fixes. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index fc691e7642..17354783ca 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1402,7 +1402,7 @@ it is displayed along with the global value." :interactive nil) (defun help-fns-edit-mode-done (&optional kill) - "Update the value of the variable and kill the buffer. + "Update the value of the variable being edited and kill the edit buffer. If KILL (the prefix), don't update the value, but just kill the current buffer." (interactive "P" help-fns--edit-value-mode) @@ -1423,7 +1423,8 @@ current buffer." (revert-buffer))))) (defun help-fns-edit-mode-cancel () - "Kill the buffer without updating the value." + "Kill the edit buffer and cancel editing of the value. +This cancels value editing without updating the value." (interactive nil help-fns--edit-value-mode) (help-fns-edit-mode-done t)) commit 28c5c27162f227a1aae466de9ad52fb146ce63c2 Author: Lars Ingebrigtsen <larsi@gnus.org> Date: Mon Jul 4 12:37:17 2022 +0200 Don't bug out in manual-html-fix-index-2 on newer makeinfo versions Backport from master. * admin/admin.el (manual-html-fix-index-2): Don't bug out if the makeinfo version doesn't include <ul>. (cherry picked from commit e0e3f2b672bc42da52ac9c7596c7560a88684651) diff --git a/admin/admin.el b/admin/admin.el index 2a597e624b..67cbf85a32 100644 --- a/admin/admin.el +++ b/admin/admin.el @@ -607,7 +607,7 @@ style=\"text-align:left\">") ;; its original form. (when (or (search-forward "<ul class=\"menu\">" nil t) ;; FIXME? The following search seems dangerously lax. - (search-forward "<ul>")) + (search-forward "<ul>" nil t)) ;; Convert the list that Makeinfo made into a table. (replace-match "<table style=\"float:left\" width=\"100%\">") (forward-line 1) commit 724f712ef17d4a248048d97a8c9b72f95fcf0914 Author: Lars Ingebrigtsen <larsi@gnus.org> Date: Mon Jul 4 12:47:16 2022 +0200 Preserve <title> in the Emacs manuals Backport from master. * admin/admin.el (manual-html-fix-headers): Preserve the <title> element (bug#48334). (cherry picked from commit b778e71af7ca8c59917334b4bb1b34cdb52faca9) diff --git a/admin/admin.el b/admin/admin.el index 57d5afb23b..2a597e624b 100644 --- a/admin/admin.el +++ b/admin/admin.el @@ -477,10 +477,11 @@ the @import directive." (delete-region opoint (point)) (search-forward "<meta http-equiv=\"Content-Style") (setq opoint (match-beginning 0))) + (search-forward "<title>") + (delete-region opoint (match-beginning 0)) (search-forward "\n") - (delete-region opoint (point)) - (search-forward "") commit 603de9a38ef92bb6583973e6c874f551c185d3bd Author: Eli Zaretskii Date: Mon Jul 4 14:59:58 2022 +0300 ; Fix documentation of 'file-parent-directory' * doc/lispref/files.texi (Directory Names): * lisp/files.el (file-parent-directory): Improve wording of the documentation of 'file-parent-directory'. (Bug#56355) diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index ee4e1ec4d9..986fb22c75 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -2446,9 +2446,12 @@ because it recognizes abbreviations even as part of the name. @end defun @defun file-parent-directory filename -This function returns the parent directory of @var{filename}. If -@var{filename} is at the top level, return @code{nil}. @var{filename} -can be relative to @code{default-directory}. +This function returns the directory name of the parent directory of +@var{filename}. If @var{filename} is at the root directory of the +filesystem, it returns @code{nil}. A relative @var{filename} is +assumed to be relative to @code{default-directory}, and the return +value will also be relative in that case. If the return value is +non-@code{nil}, it ends in a slash. @end defun @node File Name Expansion diff --git a/lisp/files.el b/lisp/files.el index b952b08ff4..185aae164d 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -5146,9 +5146,10 @@ On most systems, this will be true: components)) (defun file-parent-directory (filename) - "Return the parent directory of FILENAME. -If FILENAME is at the top level, return nil. FILENAME can be -relative to `default-directory'." + "Return the directory name of the parent directory of FILENAME. +If FILENAME is at the root of the filesystem, return nil. +If FILENAME is relative, it is interpreted to be relative +to `default-directory', and the result will also be relative." (let* ((expanded-filename (expand-file-name filename)) (parent (file-name-directory (directory-file-name expanded-filename)))) (cond commit 1ac383bcb69578ac9e89ab00538d81ee8daee022 Author: Daanturo Date: Mon Jul 4 13:07:51 2022 +0200 Add file-parent-directory function * doc/lispref/files.texi: Document the function. * etc/NEWS: Add its entry. * lisp/emacs-lisp/shortdoc.el: Add it to 'file-name' group. * lisp/files.el: implementation (bug#56355). diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index ea8683a6d8..ee4e1ec4d9 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -2445,6 +2445,12 @@ You can use this function for directory names and for file names, because it recognizes abbreviations even as part of the name. @end defun +@defun file-parent-directory filename +This function returns the parent directory of @var{filename}. If +@var{filename} is at the top level, return @code{nil}. @var{filename} +can be relative to @code{default-directory}. +@end defun + @node File Name Expansion @subsection Functions that Expand Filenames @cindex expansion of file names diff --git a/etc/NEWS b/etc/NEWS index 3836efa692..7967190c6e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -339,6 +339,10 @@ increase and decrease the font size globally. Additionally, the variable 'global-text-scale-adjust-resizes-frames' controls whether the frames are resized when the font size is changed. ++++ +** New function 'file-parent-directory'. +Get the parent directory of a file. + ** New config variable 'syntax-wholeline-max' to reduce the cost of long lines. This variable is used by some operations (mostly syntax-propertization and font-locking) to treat lines longer than this variable as if they diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index f53e783111..68293931c3 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -353,6 +353,13 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), (abbreviate-file-name :no-eval (abbreviate-file-name "/home/some-user") :eg-result "~some-user") + (file-parent-directory + :eval (file-parent-directory "/foo/bar") + :eval (file-parent-directory "~") + :eval (file-parent-directory "/tmp/") + :eval (file-parent-directory "foo/bar") + :eval (file-parent-directory "foo") + :eval (file-parent-directory "/")) "Quoted File Names" (file-name-quote :args (name) diff --git a/lisp/files.el b/lisp/files.el index 1295c24c93..b952b08ff4 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -5145,6 +5145,23 @@ On most systems, this will be true: (setq filename nil)))) components)) +(defun file-parent-directory (filename) + "Return the parent directory of FILENAME. +If FILENAME is at the top level, return nil. FILENAME can be +relative to `default-directory'." + (let* ((expanded-filename (expand-file-name filename)) + (parent (file-name-directory (directory-file-name expanded-filename)))) + (cond + ;; filename is at top-level, therefore no parent + ((or (null parent) + (file-equal-p parent expanded-filename)) + nil) + ;; filename is relative, return relative parent + ((not (file-name-absolute-p filename)) + (file-relative-name parent)) + (t + parent)))) + (defcustom make-backup-file-name-function #'make-backup-file-name--default-function "A function that `make-backup-file-name' uses to create backup file names. commit 2a0740b95af87167c2954d7106dc0dc4143a31ca Author: Benjamin Riefenstahl Date: Mon Jul 4 12:57:34 2022 +0200 lisp/thumbs.el: Fix calling the "convert" command * lisp/thumbs.el (thumbs-call-convert): Pass 'action-prefix' and 'action' as a combined parameter. Do not pass 'arg' if it is nil. (thumbs-modify-image): Do not pass "" as 'arg' to 'thumbs-call-convert' (bug#56375). Some time in the past this was converted from using the shell to passing the parameters directly, but the fallout was not handled correctly. diff --git a/lisp/thumbs.el b/lisp/thumbs.el index 3bf08dd6a5..e622bcedc4 100644 --- a/lisp/thumbs.el +++ b/lisp/thumbs.el @@ -215,16 +215,17 @@ FILEIN is the input file, FILEOUT is the output file, ACTION is the command to send to convert. Optional arguments are: -ARG any arguments to the ACTION command, +ARG if non-nil, the argument of the ACTION command, OUTPUT-FORMAT is the file format to output (default is jpeg), ACTION-PREFIX is the symbol to place before the ACTION command (defaults to `-' but can sometimes be `+')." - (call-process thumbs-conversion-program nil nil nil - (or action-prefix "-") - action - (or arg "") - filein - (format "%s:%s" (or output-format "jpeg") fileout))) + (let ((action-param (concat (or action-prefix "-") action)) + (fileout-param (format "%s:%s" (or output-format "jpeg") fileout))) + (if arg + (call-process thumbs-conversion-program nil nil nil + action-param arg filein fileout-param) + (call-process thumbs-conversion-program nil nil nil + action-param filein fileout-param)))) (defun thumbs-new-image-size (s increment) "New image (a cons of width x height)." @@ -610,7 +611,7 @@ ACTION and ARG should be a valid convert command." (thumbs-call-convert (or old thumbs-current-image-filename) tmp action - (or arg "")) + arg) (save-excursion (thumbs-insert-image tmp 'jpeg 0)) (setq thumbs-current-tmp-filename tmp))) commit b778e71af7ca8c59917334b4bb1b34cdb52faca9 Author: Lars Ingebrigtsen Date: Mon Jul 4 12:47:16 2022 +0200 Preserve in the Emacs manuals * admin/admin.el (manual-html-fix-headers): Preserve the <title> element (bug#48334). diff --git a/admin/admin.el b/admin/admin.el index 2d809313ca..c84287a702 100644 --- a/admin/admin.el +++ b/admin/admin.el @@ -488,10 +488,11 @@ the @import directive." (delete-region opoint (point)) (search-forward "<meta http-equiv=\"Content-Style") (setq opoint (match-beginning 0))) + (search-forward "<title>") + (delete-region opoint (match-beginning 0)) (search-forward "\n") - (delete-region opoint (point)) - (search-forward "") commit e0e3f2b672bc42da52ac9c7596c7560a88684651 Author: Lars Ingebrigtsen Date: Mon Jul 4 12:37:17 2022 +0200 Don't bug out in manual-html-fix-index-2 on newer makeinfo versions * admin/admin.el (manual-html-fix-index-2): Don't bug out if the makeinfo version doesn't include
    . diff --git a/admin/admin.el b/admin/admin.el index 6be378b924..2d809313ca 100644 --- a/admin/admin.el +++ b/admin/admin.el @@ -617,7 +617,7 @@ style=\"text-align:left\">") ;; its original form. (when (or (search-forward "
      " nil t) ;; FIXME? The following search seems dangerously lax. - (search-forward "
        ")) + (search-forward "
          " nil t)) ;; Convert the list that Makeinfo made into a table. (replace-match "") (forward-line 1) commit f133336a1afc45f4329eb8ed8a1e0e319a4691d9 Author: Visuwesh Date: Sun Jul 3 15:29:44 2022 +0200 Exclude radio buttons when suggesting URI in eww * lisp/net/eww.el (eww-links-at-point): Exclude radio links. (bug#56366). diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 3c16942e7c..1671e062b2 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -932,9 +932,9 @@ The renaming scheme is performed in accordance with (defun eww-links-at-point () "Return list of URIs, if any, linked at point." - (remq nil - (list (get-text-property (point) 'shr-url) - (get-text-property (point) 'image-url)))) + (seq-filter #'stringp + (list (get-text-property (point) 'shr-url) + (get-text-property (point) 'image-url)))) (defun eww-view-source () "View the HTML source code of the current page." commit 906b97edb9a7dbc61af4386cb34d4bf89bd0ecfb Author: Stefan Kangas Date: Mon Jul 4 12:12:45 2022 +0200 New command help-fns-edit-mode-cancel * lisp/help-fns.el (help-fns-edit-mode-cancel): New command. (help-fns--edit-value-mode-map): Bind it to 'C-c C-k'. (help-fns-edit-variable): Advertise it in help text. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 705f92b37b..fc691e7642 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1390,11 +1390,13 @@ it is displayed along with the global value." (help-fns--edit-value-mode) (insert (format ";; Edit the `%s' variable.\n" (nth 0 var)) (substitute-command-keys - ";; \\[help-fns-edit-mode-done] to update the value and exit.\n\n")) + ";; `\\[help-fns-edit-mode-done]' to update the value and exit; \ +`\\[help-fns-edit-mode-cancel]' to cancel.\n\n")) (setq-local help-fns--edit-variable var))) (defvar-keymap help-fns--edit-value-mode-map - "C-c C-c" #'help-fns-edit-mode-done) + "C-c C-c" #'help-fns-edit-mode-done + "C-c C-k" #'help-fns-edit-mode-cancel) (define-derived-mode help-fns--edit-value-mode emacs-lisp-mode "Elisp" :interactive nil) @@ -1420,6 +1422,11 @@ current buffer." (with-current-buffer help-buffer (revert-buffer))))) +(defun help-fns-edit-mode-cancel () + "Kill the buffer without updating the value." + (interactive nil help-fns--edit-value-mode) + (help-fns-edit-mode-done t)) + (defun help-fns--run-describe-functions (functions &rest args) (with-current-buffer standard-output (unless (bolp) commit c4e93b67c456b2a7cfc57b13c5d8070eb2b6d167 Author: Po Lu Date: Mon Jul 4 14:02:42 2022 +0800 Handle errors caused by ignoring errors with GDK's trap installed * src/xterm.c (x_ignore_errors_for_next_request) (x_stop_ignoring_errors): Also tell GDK to ignore errors from the following requests. (bug#56372) diff --git a/src/xterm.c b/src/xterm.c index de8e973173..e242768c95 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -23144,6 +23144,19 @@ static void x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) { struct x_failable_request *request, *max; +#ifdef HAVE_GTK3 + GdkDisplay *gdpy; + + /* GTK 3 tends to override our own error handler inside certain + callbacks, which this can be called from. Instead of trying to + restore our own, add a trap for the following requests with + GDK as well. */ + + gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display); + + if (gdpy) + gdk_x11_display_error_trap_push (gdpy); +#endif if ((dpyinfo->next_failable_request != dpyinfo->failable_requests) @@ -23182,6 +23195,9 @@ static void x_stop_ignoring_errors (struct x_display_info *dpyinfo) { struct x_failable_request *range; +#ifdef HAVE_GTK3 + GdkDisplay *gdpy; +#endif range = dpyinfo->next_failable_request - 1; range->end = XNextRequest (dpyinfo->display) - 1; @@ -23192,6 +23208,13 @@ x_stop_ignoring_errors (struct x_display_info *dpyinfo) if (X_COMPARE_SERIALS (range->end, <, range->start)) emacs_abort (); + +#ifdef HAVE_GTK3 + gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display); + + if (gdpy) + gdk_x11_display_error_trap_pop_ignored (gdpy); +#endif } /* Undo the last x_catch_errors call. commit 1da6a6d3271be003b545e41ae21c3071faf22f86 Author: Po Lu Date: Mon Jul 4 13:41:20 2022 +0800 Always wait for XdndStatus before sending XdndDrop * src/xterm.c (x_dnd_do_drop): New function. (x_dnd_begin_drag_and_drop): Clear new flag. (handle_one_xevent): Use that function; send drops upon receipt of pending XdndStatus, to avoid race conditions where we don't yet know the selected action. diff --git a/src/xterm.c b/src/xterm.c index 6a357b473d..de8e973173 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1268,6 +1268,13 @@ static Window x_dnd_waiting_for_status_window; upon receiving an XdndStatus event from said window. */ static XEvent x_dnd_pending_send_position; +/* If true, send a drop from `x_dnd_finish_frame' to the pending + status window after receiving all pending XdndStatus events. */ +static bool x_dnd_need_send_drop; + +/* The protocol version of any such drop. */ +static int x_dnd_send_drop_proto; + /* The action the drop target actually chose to perform. Under XDND, this is set upon receiving the XdndFinished or @@ -4529,6 +4536,19 @@ x_dnd_send_drop (struct frame *f, Window target, Time timestamp, return true; } +static bool +x_dnd_do_drop (Window target, int supported) +{ + if (x_dnd_waiting_for_status_window != target) + return x_dnd_send_drop (x_dnd_frame, target, + x_dnd_selection_timestamp, supported); + + x_dnd_need_send_drop = true; + x_dnd_send_drop_proto = supported; + + return true; +} + static void x_set_dnd_targets (Atom *targets, int ntargets) { @@ -11398,6 +11418,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), QXdndSelection); + if (NILP (ltimestamp)) + error ("No local value for XdndSelection"); + if (BIGNUMP (ltimestamp)) x_dnd_selection_timestamp = bignum_to_intmax (ltimestamp); else @@ -11538,6 +11561,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_allow_current_frame = allow_current_frame; x_dnd_movement_frame = NULL; x_dnd_init_type_lists = false; + x_dnd_need_send_drop = false; #ifdef HAVE_XKB x_dnd_keyboard_state = 0; @@ -16426,8 +16450,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, { int rc; - if (x_dnd_in_progress - && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo + if (((x_dnd_in_progress + && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo) + || (x_dnd_waiting_for_finish + && FRAME_DISPLAY_INFO (x_dnd_finish_frame) == dpyinfo)) && event->xclient.message_type == dpyinfo->Xatom_XdndStatus) { Window target; @@ -16436,6 +16462,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, target = event->xclient.data.l[0]; if (x_dnd_last_protocol_version != -1 + && x_dnd_in_progress && target == x_dnd_last_seen_window && event->xclient.data.l[1] & 2) { @@ -16452,7 +16479,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_mouse_rect_target = None; if (x_dnd_last_protocol_version != -1 - && target == x_dnd_last_seen_window) + && (x_dnd_in_progress + && target == x_dnd_last_seen_window)) { if (event->xclient.data.l[1] & 1) { @@ -16484,6 +16512,26 @@ handle_one_xevent (struct x_display_info *dpyinfo, } else x_dnd_waiting_for_status_window = None; + + /* Send any pending drop if warranted. */ + if (x_dnd_waiting_for_finish && x_dnd_need_send_drop + && x_dnd_waiting_for_status_window == None) + { + if (event->xclient.data.l[1] & 1) + { + if (x_dnd_send_drop_proto >= 2) + x_dnd_action = event->xclient.data.l[4]; + else + x_dnd_action = dpyinfo->Xatom_XdndActionCopy; + } + else + x_dnd_action = None; + + x_dnd_waiting_for_finish + = x_dnd_send_drop (x_dnd_finish_frame, + target, x_dnd_selection_timestamp, + x_dnd_send_drop_proto); + } } goto done; @@ -18948,9 +18996,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; x_dnd_waiting_for_finish - = x_dnd_send_drop (x_dnd_frame, x_dnd_last_seen_window, - x_dnd_selection_timestamp, - x_dnd_last_protocol_version); + = x_dnd_do_drop (x_dnd_last_seen_window, + x_dnd_last_protocol_version); x_dnd_finish_display = dpyinfo->display; } else if (x_dnd_last_seen_window != None) @@ -20354,9 +20401,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; x_dnd_waiting_for_finish - = x_dnd_send_drop (x_dnd_frame, x_dnd_last_seen_window, - x_dnd_selection_timestamp, - x_dnd_last_protocol_version); + = x_dnd_do_drop (x_dnd_last_seen_window, + x_dnd_last_protocol_version); x_dnd_finish_display = dpyinfo->display; } else if (x_dnd_last_seen_window != None) commit bd034b342ccf15a1887614f19de1caa9ff2f2d22 Author: Po Lu Date: Mon Jul 4 12:56:24 2022 +0800 Fix accessing dpyinfo after it is deallocated * src/xterm.c (x_connection_closed): Print disconnect error for the last terminal before freeing it. diff --git a/src/xterm.c b/src/xterm.c index c5acb45083..6a357b473d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -23501,43 +23501,47 @@ For details, see etc/PROBLEMS.\n", /* We have just closed all frames on this display. */ emacs_abort (); - XSETTERMINAL (tmp, dpyinfo->terminal); - Fdelete_terminal (tmp, Qnoelisp); - } - - unblock_input (); + /* This was the last terminal remaining, so print the error + message and associated error handlers and kill Emacs. */ + if (dpyinfo->terminal == terminal_list + && !terminal_list->next_terminal) + { + fprintf (stderr, "%s\n", error_msg); - if (terminal_list == 0) - { - fprintf (stderr, "%s\n", error_msg); + if (!ioerror && dpyinfo) + { + /* Dump the list of error handlers for debugging + purposes. */ - if (!ioerror) - { - /* Dump the list of error handlers for debugging - purposes. */ + fprintf (stderr, "X error handlers currently installed:\n"); - fprintf (stderr, "X error handlers currently installed:\n"); + for (failable = dpyinfo->failable_requests; + failable < dpyinfo->next_failable_request; + ++failable) + { + if (failable->end) + fprintf (stderr, "Ignoring errors between %lu to %lu\n", + failable->start, failable->end); + else + fprintf (stderr, "Ignoring errors from %lu onwards\n", + failable->start); + } - for (failable = dpyinfo->failable_requests; - failable < dpyinfo->next_failable_request; - ++failable) - { - if (failable->end) - fprintf (stderr, "Ignoring errors between %lu to %lu\n", - failable->start, failable->end); - else - fprintf (stderr, "Ignoring errors from %lu onwards\n", - failable->start); + for (stack = x_error_message; stack; stack = stack->prev) + fprintf (stderr, "Trapping errors from %lu\n", + stack->first_request); } - - for (stack = x_error_message; stack; stack = stack->prev) - fprintf (stderr, "Trapping errors from %lu\n", - stack->first_request); } - Fkill_emacs (make_fixnum (70), Qnil); + XSETTERMINAL (tmp, dpyinfo->terminal); + Fdelete_terminal (tmp, Qnoelisp); } + unblock_input (); + + if (terminal_list == 0) + Fkill_emacs (make_fixnum (70), Qnil); + totally_unblock_input (); unbind_to (idx, Qnil); commit 3f2af38ef844e29ab31e5d30e3ccee91a33f6b99 Merge: c96cd5e2b7 41472f3b6c Author: Stefan Kangas Date: Mon Jul 4 06:30:34 2022 +0200 Merge from origin/emacs-28 41472f3b6c Document 'jit-lock-debug-mode' commit c96cd5e2b71f1de8c5b84c290ec8c9a01ec75bdd Author: Po Lu Date: Mon Jul 4 11:32:05 2022 +0800 Display list of traps and handlers when crashing due to an X error * src/xterm.c (x_connection_closed): Print list of installed error handlers if not crashing due to an IO error. (NO_INLINE): Include error serial in error message. diff --git a/src/xterm.c b/src/xterm.c index 02ea968031..c5acb45083 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -23342,6 +23342,8 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) xm_drop_start_message dmsg; struct frame *f; Lisp_Object minibuf_frame, tmp; + struct x_failable_request *failable; + struct x_error_message_stack *stack; dpyinfo = x_display_info_for_display (dpy); error_msg = alloca (strlen (error_message) + 1); @@ -23508,6 +23510,31 @@ For details, see etc/PROBLEMS.\n", if (terminal_list == 0) { fprintf (stderr, "%s\n", error_msg); + + if (!ioerror) + { + /* Dump the list of error handlers for debugging + purposes. */ + + fprintf (stderr, "X error handlers currently installed:\n"); + + for (failable = dpyinfo->failable_requests; + failable < dpyinfo->next_failable_request; + ++failable) + { + if (failable->end) + fprintf (stderr, "Ignoring errors between %lu to %lu\n", + failable->start, failable->end); + else + fprintf (stderr, "Ignoring errors from %lu onwards\n", + failable->start); + } + + for (stack = x_error_message; stack; stack = stack->prev) + fprintf (stderr, "Trapping errors from %lu\n", + stack->first_request); + } + Fkill_emacs (make_fixnum (70), Qnil); } @@ -23599,7 +23626,8 @@ x_error_handler (Display *display, XErrorEvent *event) static void NO_INLINE x_error_quitter (Display *display, XErrorEvent *event) { - char buf[256], buf1[356]; + char buf[256], buf1[400 + INT_STRLEN_BOUND (int) + + INT_STRLEN_BOUND (unsigned long)]; /* Ignore BadName errors. They can happen because of fonts or colors that are not defined. */ @@ -23611,8 +23639,9 @@ x_error_quitter (Display *display, XErrorEvent *event) original error handler. */ XGetErrorText (display, event->error_code, buf, sizeof (buf)); - sprintf (buf1, "X protocol error: %s on protocol request %d", - buf, event->request_code); + sprintf (buf1, "X protocol error: %s on protocol request %d\n" + "Serial no: %lu\n", buf, event->request_code, + event->serial); x_connection_closed (display, buf1, false); } commit bbca04fd9d10ec2a5e849c48eab42faad0de0a32 Author: Florian Rommel Date: Fri Jun 3 03:03:03 2022 +0200 Add support for fullscreen values fullheight and fullwidth on PGTK * src/pgtkterm.c (window_state_event): Support values fullheight and fullwidth for the fullscreen frame-parameter * doc/lispref/frames.texi (Size Parameters): Document inability to actively set hullheight/fullwidth for PGTK frames * configure.ac: Bump GTK version for PGTK * etc/NEWS: Change GTK version in PGTK announcement diff --git a/configure.ac b/configure.ac index ad3df5d731..a016d464f3 100644 --- a/configure.ac +++ b/configure.ac @@ -2866,7 +2866,7 @@ if test "${opsys}" != "mingw32"; then if test "${window_system}" = "x11"; then GTK_REQUIRED=3.10 else - GTK_REQUIRED=3.20 + GTK_REQUIRED=3.22.23 fi GTK_MODULES="gtk+-3.0 >= $GTK_REQUIRED glib-2.0 >= $GLIB_REQUIRED" diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index f655ccdfa7..ed56fa777d 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -1746,15 +1746,16 @@ fit will be clipped by the window manager. @item fullscreen This parameter specifies whether to maximize the frame's width, height or both. Its value can be @code{fullwidth}, @code{fullheight}, -@code{fullboth}, or @code{maximized}. A @dfn{fullwidth} frame is as -wide as possible, a @dfn{fullheight} frame is as tall as possible, and -a @dfn{fullboth} frame is both as wide and as tall as possible. A -@dfn{maximized} frame is like a ``fullboth'' frame, except that it -usually keeps its title bar and the buttons for resizing and closing -the frame. Also, maximized frames typically avoid hiding any task bar -or panels displayed on the desktop. A ``fullboth'' frame, on the -other hand, usually omits the title bar and occupies the entire -available screen space. +@code{fullboth}, or @code{maximized}.@footnote{On PGTK frames, setting +the values @code{fullheight} and @code{fullwidth} has no effect.} A +@dfn{fullwidth} frame is as wide as possible, a @dfn{fullheight} frame +is as tall as possible, and a @dfn{fullboth} frame is both as wide and +as tall as possible. A @dfn{maximized} frame is like a ``fullboth'' +frame, except that it usually keeps its title bar and the buttons for +resizing and closing the frame. Also, maximized frames typically +avoid hiding any task bar or panels displayed on the desktop. A +``fullboth'' frame, on the other hand, usually omits the title bar and +occupies the entire available screen space. Full-height and full-width frames are more similar to maximized frames in this regard. However, these typically display an external diff --git a/etc/NEWS b/etc/NEWS index 3d679fdec6..3836efa692 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -85,7 +85,7 @@ after deleting lisp/leim/ja-dic/ja-dic.el. +++ ** Emacs now supports being built with pure GTK. -To use this option, make sure the GTK 3 (version 3.20 or later) and +To use this option, make sure the GTK 3 (version 3.22.23 or later) and Cairo development files are installed, and configure Emacs with the option '--with-pgtk'. Unlike the default X and GTK build, the resulting Emacs binary will work on any underlying window system diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 1eb4d378ad..b283cef7cd 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5454,15 +5454,18 @@ window_state_event (GtkWidget *widget, gpointer *user_data) { struct frame *f = pgtk_any_window_to_frame (event->window_state.window); + GdkWindowState new_state; union buffered_input_event inev; + new_state = event->window_state.new_window_state; + EVENT_INIT (inev.ie); inev.ie.kind = NO_EVENT; inev.ie.arg = Qnil; if (f) { - if (event->window_state.new_window_state & GDK_WINDOW_STATE_FOCUSED) + if (new_state & GDK_WINDOW_STATE_FOCUSED) { if (FRAME_ICONIFIED_P (f)) { @@ -5478,17 +5481,24 @@ window_state_event (GtkWidget *widget, } } - if (event->window_state.new_window_state - & GDK_WINDOW_STATE_FULLSCREEN) + if (new_state & GDK_WINDOW_STATE_FULLSCREEN) store_frame_param (f, Qfullscreen, Qfullboth); - else if (event->window_state.new_window_state - & GDK_WINDOW_STATE_MAXIMIZED) + else if (new_state & GDK_WINDOW_STATE_MAXIMIZED) store_frame_param (f, Qfullscreen, Qmaximized); + else if ((new_state & GDK_WINDOW_STATE_TOP_TILED) + && (new_state & GDK_WINDOW_STATE_BOTTOM_TILED) + && !(new_state & GDK_WINDOW_STATE_TOP_RESIZABLE) + && !(new_state & GDK_WINDOW_STATE_BOTTOM_RESIZABLE)) + store_frame_param (f, Qfullscreen, Qfullheight); + else if ((new_state & GDK_WINDOW_STATE_LEFT_TILED) + && (new_state & GDK_WINDOW_STATE_RIGHT_TILED) + && !(new_state & GDK_WINDOW_STATE_LEFT_RESIZABLE) + && !(new_state & GDK_WINDOW_STATE_RIGHT_RESIZABLE)) + store_frame_param (f, Qfullscreen, Qfullwidth); else store_frame_param (f, Qfullscreen, Qnil); - if (event->window_state.new_window_state - & GDK_WINDOW_STATE_ICONIFIED) + if (new_state & GDK_WINDOW_STATE_ICONIFIED) SET_FRAME_ICONIFIED (f, true); else { @@ -5498,8 +5508,7 @@ window_state_event (GtkWidget *widget, SET_FRAME_ICONIFIED (f, false); } - if (event->window_state.new_window_state - & GDK_WINDOW_STATE_STICKY) + if (new_state & GDK_WINDOW_STATE_STICKY) store_frame_param (f, Qsticky, Qt); else store_frame_param (f, Qsticky, Qnil); commit 06afa7b4e096b14d03cc801235b27395a9857272 Author: Po Lu Date: Mon Jul 4 09:33:19 2022 +0800 Add some more error checking code to `x_stop_ignoring_errors' * src/xterm.c (x_stop_ignoring_errors): Abort if no request was actually made, making the state inconsistent. diff --git a/src/xterm.c b/src/xterm.c index dc7e3283a5..02ea968031 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -23139,6 +23139,13 @@ x_stop_ignoring_errors (struct x_display_info *dpyinfo) range = dpyinfo->next_failable_request - 1; range->end = XNextRequest (dpyinfo->display) - 1; + + /* Abort if no request was made since + `x_ignore_errors_for_next_request'. */ + + if (X_COMPARE_SERIALS (range->end, <, + range->start)) + emacs_abort (); } /* Undo the last x_catch_errors call. commit ae3416d69431fe80e767813bfe9837df599eca98 Author: Stefan Kangas Date: Sun Jul 3 23:05:50 2022 +0200 Simplify lisp-el-font-lock-keywords-2 definition slightly * lisp/emacs-lisp/lisp-mode.el (lisp-el-font-lock-keywords-2): Simplify slightly. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index ac56d42339..d61432b7dd 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -478,17 +478,15 @@ This will generate compile-time constants from BINDINGS." (2 font-lock-constant-face nil t)) ;; Words inside \\[], \\<>, \\{} or \\`' tend to be for ;; `substitute-command-keys'. - (,(rx "\\\\[" (group (regexp lisp-mode-symbol-regexp)) "]") + (,(rx "\\\\" (or (seq "[" (group-n 1 (regexp lisp-mode-symbol-regexp)) "]") + (seq "`" (group-n 1 (+ (regexp lisp-mode-symbol-regexp) + ;; allow multiple words, e.g. "C-x a" + (? " "))) + "'"))) (1 font-lock-constant-face prepend)) (,(rx "\\\\" (or (seq "<" (group-n 1 (regexp lisp-mode-symbol-regexp)) ">") (seq "{" (group-n 1 (regexp lisp-mode-symbol-regexp)) "}"))) (1 font-lock-variable-name-face prepend)) - (,(rx "\\\\`" (group - (+ (regexp lisp-mode-symbol-regexp) - ;; allow multiple words, e.g. "C-x a" - (? " "))) - "'") - (1 font-lock-constant-face prepend)) ;; Ineffective backslashes (typically in need of doubling). ("\\(\\\\\\)\\([^\"\\]\\)" (1 (elisp--font-lock-backslash) prepend)) @@ -496,7 +494,7 @@ This will generate compile-time constants from BINDINGS." (,(concat "[`‘']\\(" lisp-mode-symbol-regexp "\\)['’]") (1 font-lock-constant-face prepend)) ;; \\= tends to be an escape in doc strings. - ("\\\\\\\\=" + (,(rx "\\\\=") (0 font-lock-builtin-face prepend)) ;; Constant values. (,(concat "\\_<:" lisp-mode-symbol-regexp "\\_>") commit 05297e40c0ab3ffcf5b5db74e4aa2aaefe05f5cf Author: Stefan Kangas Date: Sun Jul 3 17:35:53 2022 +0200 Quote some literal keys to get help-key-binding face * lisp/align.el (align): * lisp/bindings.el (undo-repeat-map): * lisp/calc/calc-embed.el (calc-do-embedded): * lisp/calc/calc-prog.el (calc-user-define-invocation): * lisp/calc/calc-yank.el (calc--edit-mode): * lisp/comint.el (comint-history-isearch) * lisp/dired.el (dired-mode): * lisp/emulation/viper.el (viper-mode): * lisp/erc/erc-button.el (erc-button-face): * lisp/erc/erc-track.el (erc-track-enable-keybindings): * lisp/gnus/gnus-art.el (gnus-article-button-face): * lisp/gnus/gnus-eform.el (gnus-edit-form): * lisp/gnus/gnus-sum.el (gnus-summary-stop-at-end-of-message) (gnus-summary-goto-unread): * lisp/icomplete.el (icomplete-show-matches-on-no-input): * lisp/image-mode.el (image-scroll-up): * lisp/international/iso-transl.el (iso-transl-set-language): * lisp/isearch.el (isearch-forward-regexp): * lisp/misc.el (butterfly): * lisp/outline.el (outline-minor-mode-cycle-filter) (outline-minor-mode-cycle): * lisp/progmodes/grep.el (rgrep): * lisp/progmodes/gud.el (gud-gdb-repeat-map, gud-sdb-repeat-map) (gud-dbx-repeat-map, gud-xdb-repeat-map, gud-perldb-repeat-map) (gud-pdb-repeat-map, gud-guiler-repeat-map, gud-jdb-repeat-map): * lisp/progmodes/idlw-shell.el (idlwave-shell-graphics-window-size) (idlwave-shell-mode): * lisp/progmodes/idlwave.el (idlwave-shell-debug-modifiers) (idlwave-list-shell-load-path-shadows): * lisp/progmodes/python.el (python-shell-get-process-or-error): * lisp/repeat.el (repeat-check-key): * lisp/replace.el (query-replace, query-replace-regexp) (read-regexp): * lisp/simple.el (read-extended-command-predicate): * lisp/tab-bar.el (tab-bar-switch-repeat-map) (tab-bar-move-repeat-map): * lisp/term.el (ansi-term): * lisp/textmodes/reftex-index.el (reftex-index-phrases-set-macro-key): * lisp/vc/emerge.el (emerge-scroll-left, emerge-scroll-right): * lisp/windmove.el: * lisp/winner.el (winner-mode): Quote literal keys to get 'help-key-binding' face. * lisp/comint.el (comint-insert-previous-argument): Use regular quotes. diff --git a/lisp/align.el b/lisp/align.el index 9364d54665..1ee6bb0cac 100644 --- a/lisp/align.el +++ b/lisp/align.el @@ -841,8 +841,8 @@ Interactively, BEG and END are the mark/point of the current region. Many modes define specific alignment rules, and some of these rules in some modes react to the current prefix argument. For -instance, in `text-mode', `M-x align' will align into columns -based on space delimiters, while `C-u - M-x align' will align +instance, in `text-mode', \\`M-x align' will align into columns +based on space delimiters, while \\`C-u -' \\`M-x align' will align into columns based on the \"$\" character. See the `align-rules-list' variable definition for the specific rules. diff --git a/lisp/bindings.el b/lisp/bindings.el index c67a104b4c..0cf1834a4f 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -1013,7 +1013,7 @@ if `inhibit-field-text-motion' is non-nil." (let ((map (make-sparse-keymap))) (define-key map "u" 'undo) map) - "Keymap to repeat undo key sequences `C-x u u'. Used in `repeat-mode'.") + "Keymap to repeat undo key sequences \\`C-x u u'. Used in `repeat-mode'.") (put 'undo 'repeat-map 'undo-repeat-map) (define-key global-map '[(control ??)] 'undo-redo) diff --git a/lisp/calc/calc-embed.el b/lisp/calc/calc-embed.el index 9a580d9602..bb427ef86e 100644 --- a/lisp/calc/calc-embed.el +++ b/lisp/calc/calc-embed.el @@ -335,7 +335,8 @@ (message (concat "Embedded Calc mode enabled; " (if calc-embedded-quiet - "Type `C-x * x'" + (substitute-command-keys + "Type \\`C-x * x'") "Give this command again") " to return to normal"))))) (scroll-down 0))) ; fix a bug which occurs when truncate-lines is changed. diff --git a/lisp/calc/calc-prog.el b/lisp/calc/calc-prog.el index ec30ee7e0f..f11d9741ec 100644 --- a/lisp/calc/calc-prog.el +++ b/lisp/calc/calc-prog.el @@ -678,7 +678,7 @@ (or last-kbd-macro (error "No keyboard macro defined")) (setq calc-invocation-macro last-kbd-macro) - (message "Use `C-x * Z' to invoke this macro")) + (message (substitute-command-keys "Use \\`C-x * Z' to invoke this macro"))) (defun calc-user-define-edit () (interactive) ; but no calc-wrapper! diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el index c98505a0b1..71cc68b0c2 100644 --- a/lisp/calc/calc-yank.el +++ b/lisp/calc/calc-yank.el @@ -715,9 +715,9 @@ To cancel the edit, simply kill the *Calc Edit* buffer." (insert (propertize (concat (or title title "Calc Edit Mode. ") - (format-message "Press `C-c C-c'") + (substitute-command-keys "Press \\`C-c C-c'") (if allow-ret "" " or RET") - (format-message " to finish, `C-x k RET' to cancel.\n\n")) + (substitute-command-keys " to finish, \\`C-x k RET' to cancel.\n\n")) 'font-lock-face 'italic 'read-only t 'rear-nonsticky t 'front-sticky t)) (setq-local calc-edit-top (point)))) diff --git a/lisp/comint.el b/lisp/comint.el index 92262eab32..4fc1ffcf0c 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -1466,7 +1466,7 @@ A useful command to bind to SPC. See `comint-replace-by-expanded-history'." (defcustom comint-history-isearch nil "Non-nil to Isearch in input history only, not in comint buffer output. -If t, usual Isearch keys like `C-r' and `C-M-r' in comint mode search +If t, usual Isearch keys like \\`C-r' and \\`C-M-r' in comint mode search in the input history. If `dwim', Isearch keys search in the input history only when initial point position is at the comint command line. When starting Isearch @@ -2812,7 +2812,7 @@ Interactively, if no prefix argument is given, the last argument is inserted. Repeated interactive invocations will cycle through the same argument from progressively earlier commands (using the value of INDEX specified with the first command). Values of INDEX < 0 count from the end, so -INDEX = -1 is the last argument. This command is like `M-.' in +INDEX = -1 is the last argument. This command is like \"M-.\" in Bash and zsh." (interactive "P") (unless (null index) diff --git a/lisp/dired.el b/lisp/dired.el index 6b9bb35543..3eff218728 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -2469,7 +2469,7 @@ Type \\[dired-do-copy] to Copy files. Type \\[dired-sort-toggle-or-edit] to toggle Sorting by name/date or change the `ls' switches. Type \\[revert-buffer] to read all currently expanded directories aGain. This retains all marks and hides subdirs again that were hidden before. -Use `SPC' and `DEL' to move down and up by lines. +Use \\`SPC' and \\`DEL' to move down and up by lines. If Dired ever gets confused, you can either type \\[revert-buffer] \ to read the diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el index b1c361145c..be87d788e9 100644 --- a/lisp/emulation/viper.el +++ b/lisp/emulation/viper.el @@ -559,10 +559,10 @@ and improving upon much of it. 2. Vi exit functions (e.g., :wq, ZZ) work on INDIVIDUAL files -- they do not cause Emacs to quit, except at user level 1 (for a novice). 3. ^X^C EXITS EMACS. - 4. Viper supports multiple undo: `u' will undo. Typing `.' will repeat - undo. Another `u' changes direction. + 4. Viper supports multiple undo: \\`u' will undo. Typing \\`.' will repeat + undo. Another \\`u' changes direction. - 6. Emacs Meta key is `C-\\' (in all modes) or `\\ ESC' (in Vi command mode). + 6. Emacs Meta key is \\`C-\\' (in all modes) or \\`\\ ESC' (in Vi command mode). On a window system, the best way is to use the Meta-key on your keyboard. 7. Try \\[keyboard-quit] and \\[abort-recursive-edit] repeatedly,if something funny happens. This would abort the current editing command. @@ -573,12 +573,12 @@ For more information on Viper: b. Print Viper manual, found in ./etc/viper.dvi c. Print the Quick Reference, found in ./etc/viperCard.dvi -To submit a bug report or to contact the author, type :submitReport in Vi +To submit a bug report or to contact the author, type \\`:submitReport' in Vi command mode. To shoo Viper away and return to pure Emacs (horror!), type: \\[viper-go-away] -This startup message appears whenever you load Viper, unless you type `y' now." +This startup message appears whenever you load Viper, unless you type \\`y' now." )) (goto-char (point-min)) (if (y-or-n-p "Inhibit Viper startup message? ") diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el index aeada705c4..bccf0e6f1f 100644 --- a/lisp/erc/erc-button.el +++ b/lisp/erc/erc-button.el @@ -71,7 +71,7 @@ "Face used for highlighting buttons in ERC buffers. A button is a piece of text that you can activate by pressing -`RET' or `mouse-2' above it. See also `erc-button-keymap'." +\\`RET' or `mouse-2' above it. See also `erc-button-keymap'." :type 'face :group 'erc-faces) diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el index 59b79bcfd9..d02a8d13e5 100644 --- a/lisp/erc/erc-track.el +++ b/lisp/erc/erc-track.el @@ -46,7 +46,7 @@ (defcustom erc-track-enable-keybindings 'ask "Whether to enable the ERC track keybindings, namely: -`C-c C-SPC' and `C-c C-@', which both do the same thing. +\\`C-c C-SPC' and \\`C-c C-@', which both do the same thing. The default is to check to see whether these keys are used already: if not, then enable the ERC track minor mode, which diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 59c3bbc76e..2a56a12dbb 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -743,7 +743,7 @@ Each element is a regular expression." "Face used for highlighting buttons in the article buffer. An article button is a piece of text that you can activate by pressing -`RET' or `mouse-2' above it." +\\`RET' or `mouse-2' above it." :type 'face :group 'gnus-article-buttons) diff --git a/lisp/gnus/gnus-eform.el b/lisp/gnus/gnus-eform.el index 300532de28..96f515119d 100644 --- a/lisp/gnus/gnus-eform.el +++ b/lisp/gnus/gnus-eform.el @@ -92,7 +92,7 @@ The optional LAYOUT overrides the `edit-form' window layout." (insert ";;; ") (forward-line 1)) (insert (substitute-command-keys - ";; Type `C-c C-c' after you've finished editing.\n")) + ";; Type \\`C-c C-c' after you've finished editing.\n")) (insert "\n") (let ((p (point))) (gnus-pp form) diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index a4f98c9157..7f96e16c8a 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -97,7 +97,7 @@ See `gnus-group-goto-unread'." :type 'boolean) (defcustom gnus-summary-stop-at-end-of-message nil - "If non-nil, don't select the next message when using `SPC'." + "If non-nil, don't select the next message when using \\`SPC'." :link '(custom-manual "(gnus)Group Maneuvering") :group 'gnus-summary-maneuvering :version "24.1" @@ -264,8 +264,8 @@ This variable will only be used if the value of (defcustom gnus-summary-goto-unread nil "If t, many commands will go to the next unread article. This applies to marking commands as well as other commands that -\"naturally\" select the next article, like, for instance, `SPC' at -the end of an article. +\"naturally\" select the next article, like, for instance, \\`SPC' +at the end of an article. If nil, the marking commands do NOT go to the next unread article \(they go to the next article instead). If `never', commands that diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 0bc6330cc5..9640d98ca8 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -81,7 +81,7 @@ selection process starts again from the user's $HOME.") This means to show completions even when the current minibuffer contents is the same as was the initial input after minibuffer activation. This also means that if you traverse the list of completions with -commands like `C-.' and just hit RET without typing any +commands like \\`C-.' and just hit \\`RET' without typing any characters, the match under point will be chosen instead of the default." :type 'boolean diff --git a/lisp/image-mode.el b/lisp/image-mode.el index 684f2ff3fc..46c555df27 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el @@ -286,7 +286,7 @@ Stop if the bottom edge of the image is reached. Interactively, giving this command a numerical prefix will scroll up by that many lines (and down by that many lines if the number is negative). Without a prefix, scroll up by a full screen. -If given a `C-u -' prefix, scroll a full page down instead. +If given a \\`C-u -' prefix, scroll a full page down instead. If N is omitted or nil, scroll upward by a near full screen. A near full screen is `next-screen-context-lines' less than a full screen. @@ -314,7 +314,7 @@ Stop if the top edge of the image is reached. Interactively, giving this command a numerical prefix will scroll down by that many lines (and up by that many lines if the number is negative). Without a prefix, scroll down by a full screen. -If given a `C-u -' prefix, scroll a full page up instead. +If given a \\`C-u -' prefix, scroll a full page up instead. If N is omitted or nil, scroll downward by a near full screen. A near full screen is `next-screen-context-lines' less than a full screen. diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el index 912c4b72a0..90fdc06b1e 100644 --- a/lisp/international/iso-transl.el +++ b/lisp/international/iso-transl.el @@ -375,12 +375,12 @@ sequence VECTOR. (VECTOR is normally one character long.)") (defun iso-transl-set-language (lang) "Set shorter key bindings for some characters relevant for LANG. -This affects the `C-x 8' prefix. +This affects the \\`C-x 8' prefix. Note that only a few languages are supported, and for more rigorous support it is recommended to use an input method instead. Also note that many of these characters can be input -with the regular `C-x 8' map without having to specify a language +with the regular \\`C-x 8' map without having to specify a language here." (interactive (list (let ((completion-ignore-case t)) (completing-read "Set which language? " diff --git a/lisp/isearch.el b/lisp/isearch.el index 34c3665bd8..db7b53c014 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -1103,7 +1103,7 @@ In incremental searches, a space or spaces normally matches any whitespace defined by the variable `search-whitespace-regexp'. To search for a literal space and nothing else, enter C-q SPC. To toggle whitespace matching, use `isearch-toggle-lax-whitespace', -usually bound to `M-s SPC' during isearch. +usually bound to \\`M-s SPC' during isearch. This command does not support character folding." (interactive "P\np") (isearch-mode t (null not-regexp) nil (not no-recursive-edit))) diff --git a/lisp/misc.el b/lisp/misc.el index 8a01b51c6d..28c5d6e07f 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -151,7 +151,7 @@ ripples outward, changing the flow of the eddy currents in the upper atmosphere. These cause momentary pockets of higher-pressure air to form, which act as lenses that deflect incoming cosmic rays, focusing them to strike the drive platter and flip the desired bit. -You can type `M-x butterfly C-M-c' to run it. This is a permuted +You can type \\`M-x butterfly C-M-c' to run it. This is a permuted variation of `C-x M-c M-butterfly' from url `https://xkcd.com/378/'." (interactive) (if (yes-or-no-p "Do you really want to unleash the powers of the butterfly? ") diff --git a/lisp/outline.el b/lisp/outline.el index 7fd43195cc..38a37fb74d 100644 --- a/lisp/outline.el +++ b/lisp/outline.el @@ -1,7 +1,6 @@ ;;; outline.el --- outline mode commands for Emacs -*- lexical-binding: t; -*- -;; Copyright (C) 1986, 1993-1995, 1997, 2000-2022 Free Software -;; Foundation, Inc. +;; Copyright (C) 1986-2022 Free Software Foundation, Inc. ;; Maintainer: emacs-devel@gnu.org ;; Keywords: outlines @@ -182,7 +181,7 @@ in the file it applies to.") This option controls, in Outline minor mode, where on a heading typing the key sequences bound to visibility-cycling commands like `outline-cycle' and `outline-cycle-buffer' will invoke those commands. By default, you can -invoke these commands by typing `TAB' and `S-TAB' anywhere on a heading line, +invoke these commands by typing \\`TAB' and \\`S-TAB' anywhere on a heading line, but customizing this option can make those bindings be in effect only at specific positions on the heading, like only at the line's beginning or line's end. This allows these keys to be bound to their usual commands, @@ -381,9 +380,9 @@ After that, changing the prefix key requires manipulating keymaps." (defcustom outline-minor-mode-cycle nil "Enable visibility-cycling commands on headings in `outline-minor-mode'. -If enabled, typing `TAB' on a heading line cycles the visibility +If enabled, typing \\`TAB' on a heading line cycles the visibility state of that heading's body between `hide all', `headings only' -and `show all' (`outline-cycle'), and typing `S-TAB' on a heading +and `show all' (`outline-cycle'), and typing \\`S-TAB' on a heading line likewise cycles the visibility state of the whole buffer \(`outline-cycle-buffer'). Typing these keys anywhere outside heading lines invokes their default diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index 4f90a53444..423de7d581 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -1218,7 +1218,7 @@ to specify a command to run. If CONFIRM is non-nil, the user will be given an opportunity to edit the command before it's run. -Interactively, the user can use the `M-c' command while entering +Interactively, the user can use the \\`M-c' command while entering the regexp to indicate whether the grep should be case sensitive or not." (interactive diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index 26fecf9c9f..d277eef284 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -334,7 +334,7 @@ Used to gray out relevant toolbar icons.") (">" . gud-down))) (define-key map key cmd)) map) - "Keymap to repeat `gud-gdb' stepping instructions `C-x C-a C-n n n'. + "Keymap to repeat `gud-gdb' stepping instructions \\`C-x C-a C-n n n'. Used in `repeat-mode'.") (defun gud-set-repeat-map-property (keymap-symbol) @@ -1054,7 +1054,7 @@ SKIP is the number of chars to skip on each line, it defaults to 0." ("l" . gud-refresh))) (define-key map key cmd)) map) - "Keymap to repeat `sdb' stepping instructions `C-x C-a C-n n n'. + "Keymap to repeat `sdb' stepping instructions \\`C-x C-a C-n n n'. Used in `repeat-mode'.") (defun gud-sdb-marker-filter (string) @@ -1301,7 +1301,7 @@ whereby $stopformat=1 produces an output format compatible with gud-irix-p) (define-key map "f" 'gud-finish)) map) - "Keymap to repeat `dbx' stepping instructions `C-x C-a C-n n n'. + "Keymap to repeat `dbx' stepping instructions \\`C-x C-a C-n n n'. Used in `repeat-mode'.") ;; The process filter is also somewhat @@ -1476,7 +1476,7 @@ and source-file directory for your debugger." (">" . gud-down))) (define-key map key cmd)) map) - "Keymap to repeat `xdb' stepping instructions `C-x C-a C-n n n'. + "Keymap to repeat `xdb' stepping instructions \\`C-x C-a C-n n n'. Used in `repeat-mode'.") (defcustom gud-xdb-directories nil @@ -1564,7 +1564,7 @@ directories if your program contains sources from more than one directory." ("l" . gud-refresh))) (define-key map key cmd)) map) - "Keymap to repeat `perldb' stepping instructions `C-x C-a C-n n n'. + "Keymap to repeat `perldb' stepping instructions \\`C-x C-a C-n n n'. Used in `repeat-mode'.") (defun gud-perldb-massage-args (_file args) @@ -1754,7 +1754,7 @@ working directory and source-file directory for your debugger." (">" . gud-down))) (define-key map key cmd)) map) - "Keymap to repeat `pdb' stepping instructions `C-x C-a C-n n n'. + "Keymap to repeat `pdb' stepping instructions \\`C-x C-a C-n n n'. Used in `repeat-mode'.") ;; There's no guarantee that Emacs will hand the filter the entire @@ -1871,7 +1871,7 @@ directory and source-file directory for your debugger." (">" . gud-down))) (define-key map key cmd)) map) - "Keymap to repeat `guiler' stepping instructions `C-x C-a C-n n n'. + "Keymap to repeat `guiler' stepping instructions \\`C-x C-a C-n n n'. Used in `repeat-mode'.") (defun gud-guiler-marker-filter (string) @@ -2398,7 +2398,7 @@ extension EXTN. Normally EXTN is given as the regular expression ("l" . gud-refresh))) (define-key map key cmd)) map) - "Keymap to repeat `jdb' stepping instructions `C-x C-a C-n n n'. + "Keymap to repeat `jdb' stepping instructions \\`C-x C-a C-n n n'. Used in `repeat-mode'.") (defun gud-jdb-find-source-using-classpath (p) diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el index b606352136..d21a9faec9 100644 --- a/lisp/progmodes/idlw-shell.el +++ b/lisp/progmodes/idlw-shell.el @@ -231,7 +231,7 @@ because these are used as separators by IDL." (defcustom idlwave-shell-graphics-window-size '(500 400) "Size of IDL graphics windows popped up by special IDLWAVE command. -The command is `C-c C-d C-f' and accepts as a prefix the window nr. +The command is \\`C-c C-d C-f' and accepts as a prefix the window nr. A command like `WINDOW,N,xsize=XX,ysize=YY' is sent to IDL." :group 'idlwave-shell-general-setup :type '(list @@ -844,7 +844,7 @@ IDL has currently stepped.") --------- A complete set of commands for compiling and debugging IDL programs is available from the menu. Also keybindings starting with a - `C-c C-d' prefix are available for most commands in the *idl* buffer + \\`C-c C-d' prefix are available for most commands in the *idl* buffer and also in source buffers. The best place to learn about the keybindings is again the menu. diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el index f55e3449e4..a2061fde76 100644 --- a/lisp/progmodes/idlwave.el +++ b/lisp/progmodes/idlwave.el @@ -1001,9 +1001,9 @@ Obsolete, if the IDL Assistant is being used for help." "List of modifiers to be used for the debugging commands. Will be used to bind debugging commands in the shell buffer and in all source buffers. These are additional convenience bindings, the debugging -commands are always available with the `C-c C-d' prefix. +commands are always available with the \\`C-c C-d' prefix. If you set this to (control shift), this means setting a breakpoint will -be on `C-S-b', compiling a source file on `C-S-c' etc. Possible modifiers +be on \\`C-S-b', compiling a source file on \\`C-S-c' etc. Possible modifiers are `control', `meta', `super', `hyper', `alt', and `shift'." :group 'idlwave-shell-general-setup :type '(set :tag "Specify modifiers" @@ -8421,7 +8421,7 @@ was pressed." (defun idlwave-list-shell-load-path-shadows (&optional _arg) "List the load path shadows of all routines compiled under the shell. This is very useful for checking an IDL application. Just compile the -application, do RESOLVE_ALL, and `C-c C-i' to compile all referenced +application, do RESOLVE_ALL, and \\`C-c C-i' to compile all referenced routines and update IDLWAVE internal info. Then check for shadowing with this command." (interactive) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 7a626ae35e..f1191b8faa 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -3110,7 +3110,8 @@ of `error' with a user-friendly message." (or (python-shell-get-process) (if interactivep (user-error - "Start a Python process first with `M-x run-python' or `%s'" + (substitute-command-keys + "Start a Python process first with \\`M-x run-python' or `%s'") ;; Get the binding. (key-description (where-is-internal diff --git a/lisp/repeat.el b/lisp/repeat.el index 608f7aaf98..d69640a29c 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -368,8 +368,8 @@ When non-nil and the last typed key (with or without modifiers) doesn't exist in the keymap attached by the `repeat-map' property, then don't activate that keymap for the next command. So only the same keys among repeatable keys are allowed in the repeating sequence. -For example, with a non-nil value, only `C-x u u' repeats undo, -whereas `C-/ u' doesn't. +For example, with a non-nil value, only \\`C-x u u' repeats undo, +whereas \\`C-/ u' doesn't. You can also set the property `repeat-check-key' on the command symbol. This property can override the value of this variable. diff --git a/lisp/replace.el b/lisp/replace.el index 34c3d5299e..163d582148 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -415,7 +415,7 @@ word boundaries. A negative prefix arg means replace backward. Use \\\\[next-history-element] \ to pull the last incremental search string to the minibuffer that reads FROM-STRING, or invoke replacements from -incremental search with a key sequence like `C-s C-s M-%' +incremental search with a key sequence like \\`C-s C-s M-%' to use its current search string as the string to replace. Matching is independent of case if both `case-fold-search' @@ -472,8 +472,8 @@ To customize possible responses, change the bindings in `query-replace-map'." (defun query-replace-regexp (regexp to-string &optional delimited start end backward region-noncontiguous-p) "Replace some things after point matching REGEXP with TO-STRING. As each match is found, the user must type a character saying -what to do with it. Type SPC or `y' to replace the match, -DEL or `n' to skip and go to the next match. For more directions, +what to do with it. Type \\`SPC' or \\`y' to replace the match, +\\`DEL' or \\`n' to skip and go to the next match. For more directions, type \\[help-command] at that time. In Transient Mark mode, if the mark is active, operate on the contents @@ -481,12 +481,12 @@ of the region. Otherwise, operate from point to the end of the buffer's accessible portion. When invoked interactively, matching a newline with `\\n' will not work; -use `C-q C-j' instead. To match a tab character (`\\t'), just press `TAB'. +use \\`C-q C-j' instead. To match a tab character (`\\t'), just press \\`TAB'. Use \\\\[next-history-element] \ to pull the last incremental search regexp to the minibuffer that reads REGEXP, or invoke replacements from -incremental search with a key sequence like `C-M-s C-M-s C-M-%' +incremental search with a key sequence like \\`C-M-s C-M-s C-M-%' to use its current search regexp as the regexp to replace. Matching is independent of case if both `case-fold-search' @@ -931,7 +931,7 @@ in \":\", followed by optional whitespace), DEFAULT is added to the prompt. The optional argument HISTORY is a symbol to use for the history list. If nil, use `regexp-history'. -If the user has used the `M-c' command to specify case +If the user has used the \\`M-c' command to specify case sensitivity, the returned string will have a text property named `case-fold' that has a value of either `fold' or `inhibit-fold'. (It's up to the caller of `read-regexp' to diff --git a/lisp/simple.el b/lisp/simple.el index ea94727b3a..d02a32b944 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2211,7 +2211,7 @@ to get different commands to edit and resubmit." If it's nil, include all the commands. If it's a function, it will be called with two parameters: the symbol of the command and a buffer. The predicate should return -non-nil if the command should be present when doing `M-x TAB' +non-nil if the command should be present when doing \\`M-x TAB' in that buffer." :version "28.1" :group 'completion diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 705b072501..4ca177f73b 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -2425,7 +2425,7 @@ When `switch-to-buffer-obey-display-actions' is non-nil, (define-key map "o" 'tab-next) (define-key map "O" 'tab-previous) map) - "Keymap to repeat tab switch key sequences `C-x t o o O'. + "Keymap to repeat tab switch key sequences \\`C-x t o o O'. Used in `repeat-mode'.") (put 'tab-next 'repeat-map 'tab-bar-switch-repeat-map) (put 'tab-previous 'repeat-map 'tab-bar-switch-repeat-map) @@ -2435,7 +2435,7 @@ Used in `repeat-mode'.") (define-key map "m" 'tab-move) (define-key map "M" 'tab-bar-move-tab-backward) map) - "Keymap to repeat tab move key sequences `C-x t m m M'. + "Keymap to repeat tab move key sequences \\`C-x t m m M'. Used in `repeat-mode'.") (put 'tab-move 'repeat-map 'tab-bar-move-repeat-map) (put 'tab-bar-move-tab-backward 'repeat-map 'tab-bar-move-repeat-map) diff --git a/lisp/term.el b/lisp/term.el index 3bf1531fcd..c129ed976d 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -4373,7 +4373,7 @@ the process. Any more args are arguments to PROGRAM." (defun ansi-term (program &optional new-buffer-name) "Start a terminal-emulator in a new buffer. This is almost the same as `term' apart from always creating a new buffer, -and `C-x' being marked as a `term-escape-char'." +and \\`C-x' being marked as a `term-escape-char'." (interactive (list (read-from-minibuffer "Run program: " (or explicit-shell-file-name (getenv "ESHELL") diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el index 9adf0c819b..aeae389da6 100644 --- a/lisp/textmodes/reftex-index.el +++ b/lisp/textmodes/reftex-index.el @@ -1685,8 +1685,8 @@ this function repeatedly." (defun reftex-index-phrases-set-macro-key () "Change the macro key for the current line. Prompts for a macro key and insert is at the beginning of the line. -If you reply with SPACE, the macro keyn will be removed, so that the -default macro will be used. If you reply with `RET', just prints +If you reply with \\`SPC', the macro key will be removed, so that the +default macro will be used. If you reply with \\`RET', just prints information about the currently selected macro." (interactive) (reftex-index-phrases-parse-header) diff --git a/lisp/vc/emerge.el b/lisp/vc/emerge.el index b2fdb07d5f..6e94ea0715 100644 --- a/lisp/vc/emerge.el +++ b/lisp/vc/emerge.el @@ -1647,7 +1647,7 @@ the height of the merge window. (defun emerge-scroll-left (&optional arg) "Scroll left all three merge buffers, if they are in windows. If an argument is given, that is how many columns are scrolled, else nearly -the width of the A and B windows. `C-u -' alone as argument scrolls half the +the width of the A and B windows. \\`C-u -' alone as argument scrolls half the width of the A and B windows." (interactive "P") (emerge-operate-on-windows @@ -1675,7 +1675,7 @@ width of the A and B windows." (defun emerge-scroll-right (&optional arg) "Scroll right all three merge buffers, if they are in windows. If an argument is given, that is how many columns are scrolled, else nearly -the width of the A and B windows. `C-u -' alone as argument scrolls half the +the width of the A and B windows. \\`C-u -' alone as argument scrolls half the width of the A and B windows." (interactive "P") (emerge-operate-on-windows diff --git a/lisp/windmove.el b/lisp/windmove.el index c8ea4fd1e5..958a9585dc 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -644,7 +644,7 @@ Default value of MODIFIERS is `shift-meta'." (defun windmove-delete-in-direction (dir &optional arg) "Delete the window at direction DIR. If prefix ARG is `\\[universal-argument]', also kill the buffer in that window. -With `M-0' prefix, delete the selected window and +With \\`M-0' prefix, delete the selected window and select the window at direction DIR. When `windmove-wrap-around' is non-nil, takes the window from the opposite side of the frame." diff --git a/lisp/winner.el b/lisp/winner.el index e671b83880..9b2433b492 100644 --- a/lisp/winner.el +++ b/lisp/winner.el @@ -343,8 +343,8 @@ Winner mode is a global minor mode that records the changes in the window configuration (i.e. how the frames are partitioned into windows) so that the changes can be \"undone\" using the command `winner-undo'. By default this one is bound to the key -sequence `C-c '. If you change your mind (while undoing), -you can press `C-c ' (calling `winner-redo')." +sequence \\`C-c '. If you change your mind (while undoing), +you can press \\`C-c ' (calling `winner-redo')." :global t (if winner-mode (progn commit bda6e9a226f42d74176cba640dda7dfef25b764b Author: Stefan Kangas Date: Sun Jul 3 21:00:16 2022 +0200 Use command substitutions instead of literal keys in some places * lisp/emulation/viper-macs.el (ex-map, viper-set-register-macro): * lisp/minibuffer.el (minibuffer-beginning-of-buffer-movement): * lisp/speedbar.el (speedbar-frame-mode): * lisp/subr.el (kbd): * lisp/textmodes/page-ext.el (pages-directory) (pages-directory-for-addresses): * lisp/textmodes/reftex-toc.el: Use command substitutions instead of literal keys. diff --git a/lisp/emulation/viper-macs.el b/lisp/emulation/viper-macs.el index c4eb183ce4..06130afa7d 100644 --- a/lisp/emulation/viper-macs.el +++ b/lisp/emulation/viper-macs.el @@ -105,7 +105,8 @@ a key is a symbol, e.g., `a', `\\1', `f2', etc., or a list, e.g., #'viper-end-mapping-kbd-macro) (define-key viper-emacs-intercept-map "\C-x)" #'viper-end-mapping-kbd-macro) - (message "Mapping %S in %s state. Type macro definition followed by `C-x )'" + (message (substitute-command-keys "Mapping %S in %s state. \ +Type macro definition followed by \\[kmacro-end-macro]") (viper-display-macro macro-name) (if ins "Insert" "Vi"))) )) @@ -886,8 +887,9 @@ mistakes in macro names to be passed to this function is to use (if (get-register reg) (if (y-or-n-p "Register contains data. Overwrite? ") () - (error - "Macro not saved in register. Can still be invoked via `C-x e'"))) + (error + (substitute-command-keys + "Macro not saved in register. Can still be invoked via \\[kmacro-end-and-call-macro]")))) (set-register reg last-kbd-macro)) (defun viper-register-macro (count) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 8a7da41a3b..e029dfe414 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3091,7 +3091,8 @@ such as making the current buffer visit no file in the case of :type 'boolean) (defcustom minibuffer-beginning-of-buffer-movement nil - "Control how the `M-<' command in the minibuffer behaves. + "Control how the \\\\[minibuffer-beginning-of-buffer] \ +command in the minibuffer behaves. If non-nil, the command will go to the end of the prompt (if point is after the end of the prompt). If nil, it will behave like the `beginning-of-buffer' command." diff --git a/lisp/speedbar.el b/lisp/speedbar.el index b12cf3d9c2..da85d54863 100644 --- a/lisp/speedbar.el +++ b/lisp/speedbar.el @@ -934,7 +934,8 @@ supported at a time. ;; reset the selection variable (setq speedbar-last-selected-file nil) (unless (display-graphic-p) - (message "Use `M-x speedbar-get-focus' to see the speedbar window"))) + (message (substitute-command-keys + "Use \\[speedbar-get-focus] to see the speedbar window")))) (defun speedbar-frame-reposition-smartly () "Reposition the speedbar frame to be next to the attached frame." diff --git a/lisp/subr.el b/lisp/subr.el index 4e4eac32d9..2f9d37ffd6 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -964,7 +964,7 @@ side-effects, and the argument LIST is not modified." (defun kbd (keys) "Convert KEYS to the internal Emacs key representation. KEYS should be a string in the format returned by commands such -as `C-h k' (`describe-key'). +as \\[describe-key] (`describe-key'). This is the same format used for saving keyboard macros (see `edmacro-mode'). diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el index 24149f9afb..6b71f26e4f 100644 --- a/lisp/textmodes/page-ext.el +++ b/lisp/textmodes/page-ext.el @@ -515,13 +515,12 @@ resets the page-delimiter to the original value." (defvar pages-buffer-original-position) (defvar pages-buffer-original-page) -(defun pages-directory - (pages-list-all-headers-p count-lines-p &optional regexp) +(defun pages-directory (pages-list-all-headers-p count-lines-p &optional regexp) "Display a directory of the page headers in a temporary buffer. A header is the first non-blank line after the `page-delimiter'. -\\[pages-directory-mode] +\\ You may move point to one of the lines in the temporary buffer, -then use \\ to go to the same line in the pages buffer. +then use \\[pages-directory-goto] to go to the same line in the pages buffer. In interactive use: @@ -587,7 +586,9 @@ directory for only the accessible portion of the buffer." (pages-directory-mode) (setq buffer-read-only nil) (insert - "==== Pages Directory: use `C-c C-c' to go to page under cursor. ====" ?\n) + (substitute-command-keys + "==== Pages Directory: use \\\ +\\[pages-directory-goto] to go to page under cursor. ====") "\n") (setq pages-buffer pages-target-buffer) (setq pages-pos-list nil)) @@ -772,7 +773,9 @@ directory." (goto-char (point-min)) (delete-region (point) (line-end-position)) (insert - "=== Address List Directory: use `C-c C-c' to go to page under cursor. ===") + (substitute-command-keys + "=== Address List Directory: use \\\ +\\[pages-directory-goto] to go to page under cursor. ===")) (set-buffer-modified-p nil) )) (error "No addresses file found!"))) diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el index 9fdb104452..89c734a0d7 100644 --- a/lisp/textmodes/reftex-toc.el +++ b/lisp/textmodes/reftex-toc.el @@ -394,7 +394,9 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help (frame-parameter frame 'name)) "RefTeX TOC Frame"))) (if (and res error) - (error "This frame is view-only. Use `C-c =' to create TOC window for commands")) + (error (substitute-command-keys + "This frame is view-only. Use \\[reftex-toc] \ +to create TOC window for commands"))) res)) (defun reftex-toc-show-help () commit 5cb8303f6b207eade52ba8faee1ef364617077de Author: Stefan Kangas Date: Sun Jul 3 22:42:13 2022 +0200 Normalize definition of erc-track-minor-mode-map * lisp/erc/erc-track.el (erc-track-minor-mode-map): Normalize keymap definition. diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el index e8117f9a89..59b79bcfd9 100644 --- a/lisp/erc/erc-track.el +++ b/lisp/erc/erc-track.el @@ -453,13 +453,13 @@ START is the minimum length of the name used." ;; Play nice with other IRC clients (and Emacs development rules) by ;; making this a minor mode -(defvar erc-track-minor-mode-map (make-sparse-keymap) +(defvar erc-track-minor-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-c C-@") #'erc-track-switch-buffer) + (define-key map (kbd "C-c C-SPC") #'erc-track-switch-buffer) + map) "Keymap for rcirc track minor mode.") -(define-key erc-track-minor-mode-map (kbd "C-c C-@") #'erc-track-switch-buffer) -(define-key erc-track-minor-mode-map (kbd "C-c C-SPC") - #'erc-track-switch-buffer) - ;;;###autoload (define-minor-mode erc-track-minor-mode "Toggle mode line display of ERC activity (ERC Track minor mode). commit e688176b21f821d9265578f08e82ef953cfacd9b Author: Stefan Kangas Date: Sun Jul 3 22:32:47 2022 +0200 Use substitute-command-keys in reftex-toc-show-help * lisp/textmodes/reftex-toc.el (reftex-toc-help) (reftex-toc-show-help): Use substitute-command-keys. diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el index f6f72cec4f..9fdb104452 100644 --- a/lisp/textmodes/reftex-toc.el +++ b/lisp/textmodes/reftex-toc.el @@ -157,22 +157,22 @@ Here are all local bindings. (defconst reftex-toc-help " AVAILABLE KEYS IN TOC BUFFER ============================ -n / p next-line / previous-line -SPC Show the corresponding location of the LaTeX document. -TAB Goto the location and keep the TOC window. -RET Goto the location and hide the TOC window (also on mouse-2). -< / > Promote / Demote section, or all sections in region. -C-c > Display Index. With prefix arg, restrict index to current section. -q / k Hide/Kill *toc* buffer, return to position of reftex-toc command. -l i c F Toggle display of [l]abels, [i]ndex, [c]ontext, [F]ile borders. -t Change maximum toc depth (e.g. `3 t' hides levels greater than 3). -f / g Toggle follow mode / Refresh *toc* buffer. -a / d Toggle auto recenter / Toggle dedicated frame -r / C-u r Reparse the LaTeX document / Reparse entire LaTeX document. -. In other window, show position from where `reftex-toc' was called. -M-% Global search and replace to rename label at point. -x Switch to TOC of external document (with LaTeX package `xr'). -z Jump to a specific section (e.g. '3 z' goes to section 3).") +\\`n' / \\`p' `next-line' / `previous-line' +\\`SPC' Show the corresponding location of the LaTeX document. +\\`TAB' Goto the location and keep the TOC window. +\\`RET' Goto the location and hide the TOC window (also on `mouse-2'). +\\`<' / \\`>' Promote / Demote section, or all sections in region. +\\`C-c >' Display Index. With prefix arg, restrict index to current section. +\\`q' / \\`k' Hide/Kill *toc* buffer, return to position of reftex-toc command. +\\`l' \\`i' \\`c' \\`F' Toggle display of [l]abels, [i]ndex, [c]ontext, [F]ile borders. +\\`t' Change maximum toc depth (e.g. `3 t' hides levels greater than 3). +\\`f' / \\`g' Toggle follow mode / Refresh *toc* buffer. +\\`a' / \\`d' Toggle auto recenter / Toggle dedicated frame +\\`r' / \\`C-u r' Reparse the LaTeX document / Reparse entire LaTeX document. +\\`.' In other window, show position from where `reftex-toc' was called. +\\`M-%' Global search and replace to rename label at point. +\\`x' Switch to TOC of external document (with LaTeX package `xr'). +\\`z' Jump to a specific section (e.g. \\`3 z' goes to section 3).") (defvar reftex--rebuilding-toc nil) @@ -402,7 +402,9 @@ SPC=view TAB=goto RET=goto+hide [q]uit [r]escan [l]abels [f]ollow [x]r [?]Help (interactive) (reftex-toc-dframe-p nil 'error) (with-output-to-temp-buffer "*RefTeX Help*" - (princ reftex-toc-help)) + (let ((help (substitute-command-keys reftex-toc-help))) + (with-current-buffer standard-output + (insert help)))) (reftex-enlarge-to-fit "*RefTeX Help*" t) ;; If follow mode is active, arrange to delay it one command (if reftex-toc-follow-mode commit b000bd47a6efbd12cab6e6a1b19a59014931abd8 Author: Stefan Kangas Date: Sun Jul 3 20:59:00 2022 +0200 Font lock \\<> and \\{} command substitutions in docstrings * lisp/emacs-lisp/lisp-mode.el (lisp-el-font-lock-keywords-2): Support \\<> and \\{} command substitutions. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 3797217e1a..ac56d42339 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -476,9 +476,13 @@ This will generate compile-time constants from BINDINGS." "[ \t']*\\(" lisp-mode-symbol-regexp "\\)?") (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) - ;; Words inside \\[] or \\`' tend to be for `substitute-command-keys'. + ;; Words inside \\[], \\<>, \\{} or \\`' tend to be for + ;; `substitute-command-keys'. (,(rx "\\\\[" (group (regexp lisp-mode-symbol-regexp)) "]") (1 font-lock-constant-face prepend)) + (,(rx "\\\\" (or (seq "<" (group-n 1 (regexp lisp-mode-symbol-regexp)) ">") + (seq "{" (group-n 1 (regexp lisp-mode-symbol-regexp)) "}"))) + (1 font-lock-variable-name-face prepend)) (,(rx "\\\\`" (group (+ (regexp lisp-mode-symbol-regexp) ;; allow multiple words, e.g. "C-x a" commit 8bb770234db78c86e633c58e130ff7a977bf4607 Author: Stefan Kangas Date: Sun Jul 3 23:28:50 2022 +0200 Fix warning in last commit * lisp/calc/calc-misc.el (calc-dispatch-help): Fix warning. diff --git a/lisp/calc/calc-misc.el b/lisp/calc/calc-misc.el index 68a7d81637..7c75e79a26 100644 --- a/lisp/calc/calc-misc.el +++ b/lisp/calc/calc-misc.el @@ -64,42 +64,42 @@ "\\`C-x *' is a prefix key sequence; follow it with one of these letters: For turning Calc on and off: - \\`C' `calc'. Start the Calculator in a window at the bottom of the screen. - \\`O' `calc-other-window'. Start the Calculator but don't select its window. - \\`B' `calc-big-or-small'. Control whether to use the full Emacs screen for Calc. - \\`Q' `quick-calc'. Use the Calculator in the minibuffer. - \\`K' `calc-keypad'. Start the Calculator in keypad mode (X window system only). - \\`E' `calc-embedded'. Use the Calculator on a formula in this editing buffer. - \\`J' `calc-embedded-select'. Like E, but select appropriate half of => or :=. - \\`W' `calc-embedded-word'. Like E, but activate a single word, i.e., a number. - \\`Z' `calc-user-invocation'. Invoke Calc in the way you defined with `Z I' cmd. - \\`X' `calc-quit'. Turn Calc off. + \\`C' calc. Start the Calculator in a window at the bottom of the screen. + \\`O' calc-other-window. Start the Calculator but don't select its window. + \\`B' calc-big-or-small. Toggle using the full Emacs screen for Calc. + \\`Q' quick-calc. Use the Calculator in the minibuffer. + \\`K' calc-keypad. Start the Calculator in keypad mode (X window system only). + \\`E' calc-embedded. Use the Calculator on a formula in this editing buffer. + \\`J' calc-embedded-select. Like \\`E', but select appropriate half of => or :=. + \\`W' calc-embedded-word. Like \\`E', but activate a single word, i.e., a number. + \\`Z' calc-user-invocation. Invoke Calc in the way you defined with `Z I' cmd. + \\`X' calc-quit. Turn Calc off. For moving data into and out of Calc: - \\`G' `calc-grab-region'. Grab the region defined by mark and point into Calc. - \\`R' `calc-grab-rectangle'. Grab the rectangle defined by mark, point into Calc. - \\`:' `calc-grab-sum-down'. Grab a rectangle and sum the columns. - \\`_' `calc-grab-sum-across'. Grab a rectangle and sum the rows. - \\`Y' `calc-copy-to-buffer'. Copy a value from the stack into the editing buffer. + \\`G' calc-grab-region. Grab the region defined by mark and point into Calc. + \\`R' calc-grab-rectangle. Grab the rectangle defined by mark, point into Calc. + \\`:' calc-grab-sum-down. Grab a rectangle and sum the columns. + \\`_' calc-grab-sum-across. Grab a rectangle and sum the rows. + \\`Y' calc-copy-to-buffer. Copy a value from the stack into the editing buffer. For use with Embedded mode: - \\`A' `calc-embedded-activate'. Find and activate all :='s and =>'s in buffer. - \\`D' `calc-embedded-duplicate'. Make a copy of this formula and select it. - \\`F' `calc-embedded-new-formula'. Insert a new formula at current point. - \\`N' `calc-embedded-next'. Advance cursor to next known formula in buffer. - \\`P' `calc-embedded-previous'. Advance cursor to previous known formula. - \\`U' `calc-embedded-update-formula'. Re-evaluate formula at point. - \\``' `calc-embedded-edit'. Use calc-edit to edit formula at point. + \\`A' calc-embedded-activate. Find and activate all :='s and =>'s in buffer. + \\`D' calc-embedded-duplicate. Make a copy of this formula and select it. + \\`F' calc-embedded-new-formula. Insert a new formula at current point. + \\`N' calc-embedded-next. Advance cursor to next known formula in buffer. + \\`P' calc-embedded-previous. Advance cursor to previous known formula. + \\`U' calc-embedded-update-formula. Re-evaluate formula at point. + \\``' calc-embedded-edit. Use calc-edit to edit formula at point. Documentation: - \\`I' `calc-info'. Read the Calculator manual in the Emacs Info system. - \\`T' `calc-tutorial'. Run the Calculator Tutorial using the Emacs Info system. - \\`S' `calc-summary'. Read the Summary from the Calculator manual in Info. + \\`I' calc-info. Read the Calculator manual in the Emacs Info system. + \\`T' calc-tutorial. Run the Calculator Tutorial using the Emacs Info system. + \\`S' calc-summary. Read the Summary from the Calculator manual in Info. Miscellaneous: - \\`L' `calc-load-everything'. Load all parts of the Calculator into memory. - \\`M' `read-kbd-macro'. Read a region of keystroke names as a keyboard macro. - \\`0' (zero) `calc-reset'. Reset Calc stack and modes to default state. + \\`L' calc-load-everything. Load all parts of the Calculator into memory. + \\`M' read-kbd-macro. Read a region of keystroke names as a keyboard macro. + \\`0' (zero) calc-reset. Reset Calc stack and modes to default state. Press \\`*' twice (\\`C-x * *') to turn Calc on or off using the same Calc user interface as before (either \\`C-x * C' or \\`C-x * K'; initially \\`C-x * C')." commit e3f8dd9023eda75fef99b570c4af1ee68da7cf97 Author: Eli Zaretskii Date: Sun Jul 3 20:57:22 2022 +0300 ; * lisp/mwheel.el (mouse-wheel-scroll-amount): Doc fix. diff --git a/lisp/mwheel.el b/lisp/mwheel.el index 401922bd0b..e32f896916 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -134,9 +134,9 @@ the mouse wheel will scroll horizontally instead of vertically. If AMOUNT is the symbol `text-scale' or `global-text-scale', this means that with MODIFIER, the mouse wheel will change the font size -instead of scrolling (by adjusting the font height of the buffer or -global face). For more information, see `text-scale-adjust' and -`global-text-scale-adjust'." +instead of scrolling (by adjusting the font height of the default +face, either locally in the buffer or globally). For more +information, see `text-scale-adjust' and `global-text-scale-adjust'." :group 'mouse :type '(cons (choice :tag "Normal" commit ae31dd53069ad71772387f8abed3ebf2e1b54b5a Author: Juri Linkov Date: Sun Jul 3 20:02:02 2022 +0300 Use more help-key-binding faces in repeat-mode message * lisp/repeat.el (repeat-echo-message-string): Use substitute-command-keys for repeat-exit-key as well. diff --git a/lisp/repeat.el b/lisp/repeat.el index 6bbed95449..608f7aaf98 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -508,8 +508,9 @@ See `describe-repeat-maps' for a list of all repeatable commands." (key-description (vector key))))) keys ", ") (if repeat-exit-key - (format ", or exit with %s" - (key-description repeat-exit-key)) + (substitute-command-keys + (format ", or exit with \\`%s'" + (key-description repeat-exit-key))) "")))) (defun repeat-echo-message (keymap) commit 1c3c8b6d58c91ceaac90ebe800ec365983ae81a2 Author: Juri Linkov Date: Sun Jul 3 20:00:11 2022 +0300 * lisp/mwheel.el: More fixes for global-text-scale (bug#48307) (mouse-wheel-global-text-scale): Move down closer to mouse-wheel-text-scale. (mouse-wheel-scroll-amount): Add :value global-text-scale and mention it in the docstring. (mouse-wheel-global-text-scale, mouse-wheel--setup-bindings): Add mouse-wheel-down-alternate-event and mouse-wheel-up-alternate-event. Allow a list of modifiers for 'text-scale'. diff --git a/lisp/mwheel.el b/lisp/mwheel.el index 062c98b53e..401922bd0b 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -42,17 +42,6 @@ (defvar mouse-wheel-mode) -(defun mouse-wheel-global-text-scale (event) - "Increase or decrease the global font size according to the EVENT. -This invokes `global-text-scale-adjust', which see." - (interactive (list last-input-event)) - (let ((button (mwheel-event-button event))) - (unwind-protect - (cond ((eq button mouse-wheel-down-event) - (global-text-scale-adjust 1)) - ((eq button mouse-wheel-up-event) - (global-text-scale-adjust -1)))))) - (defvar mouse-wheel--installed-bindings-alist nil "Alist of all installed mouse wheel key bindings.") @@ -143,10 +132,11 @@ less than a full screen. If AMOUNT is the symbol `hscroll', this means that with MODIFIER, the mouse wheel will scroll horizontally instead of vertically. -If AMOUNT is the symbol `text-scale', this means that with -MODIFIER, the mouse wheel will change the font size instead of -scrolling (by adjusting the font height of the default face). -For more information, see `text-scale-adjust'." +If AMOUNT is the symbol `text-scale' or `global-text-scale', this +means that with MODIFIER, the mouse wheel will change the font size +instead of scrolling (by adjusting the font height of the buffer or +global face). For more information, see `text-scale-adjust' and +`global-text-scale-adjust'." :group 'mouse :type '(cons (choice :tag "Normal" @@ -171,7 +161,8 @@ For more information, see `text-scale-adjust'." (integer :tag "Scroll specific # of lines") (float :tag "Scroll fraction of window") (const :tag "Scroll horizontally" :value hscroll) - (const :tag "Change face size" :value text-scale))))) + (const :tag "Change buffer face size" :value text-scale) + (const :tag "Change global face size" :value global-text-scale))))) :set 'mouse-wheel-change-button :version "28.1") @@ -450,6 +441,19 @@ See also `text-scale-adjust'." (text-scale-decrease 1))) (select-window selected-window)))) +(defun mouse-wheel-global-text-scale (event) + "Increase or decrease the global font size according to the EVENT. +This invokes `global-text-scale-adjust', which see." + (interactive (list last-input-event)) + (let ((button (mwheel-event-button event))) + (unwind-protect + (cond ((memq button (list mouse-wheel-down-event + mouse-wheel-down-alternate-event)) + (global-text-scale-adjust 1)) + ((memq button (list mouse-wheel-up-event + mouse-wheel-up-alternate-event)) + (global-text-scale-adjust -1)))))) + (defun mouse-wheel--add-binding (key fun) "Bind mouse wheel button KEY to function FUN. Save it for later removal by `mouse-wheel--remove-bindings'." @@ -502,12 +506,15 @@ an event used for scrolling, such as `mouse-wheel-down-event'." mouse-wheel-down-alternate-event mouse-wheel-up-alternate-event)) (when event - (mouse-wheel--add-binding `[,(list (caar binding) event)] + (mouse-wheel--add-binding `[,(append (car binding) (list event))] 'mouse-wheel-text-scale)))) - ((and (consp binding) (eq (cdr binding) 'global-text-scale)) - (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event)) + ((and (consp binding) (eq (cdr binding) 'global-text-scale)) + (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event + mouse-wheel-down-alternate-event + mouse-wheel-up-alternate-event)) + (when event (mouse-wheel--add-binding `[,(append (car binding) (list event))] - 'mouse-wheel-global-text-scale))) + 'mouse-wheel-global-text-scale)))) ;; Bindings for scrolling. (t (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event commit 0835bc40d353ca2a8a96e0aa82a329f7083d8dd0 Author: Stefan Kangas Date: Sun Jul 3 17:31:45 2022 +0200 Improve calc-dispatch-help docstring * lisp/calc/calc-misc.el (calc-dispatch-help): Use command substitutions. diff --git a/lisp/calc/calc-misc.el b/lisp/calc/calc-misc.el index bd1635f2bf..68a7d81637 100644 --- a/lisp/calc/calc-misc.el +++ b/lisp/calc/calc-misc.el @@ -61,48 +61,48 @@ ;;;###autoload (defun calc-dispatch-help (arg) - "C-x* is a prefix key sequence; follow it with one of these letters: + "\\`C-x *' is a prefix key sequence; follow it with one of these letters: For turning Calc on and off: - C calc. Start the Calculator in a window at the bottom of the screen. - O calc-other-window. Start the Calculator but don't select its window. - B calc-big-or-small. Control whether to use the full Emacs screen for Calc. - Q quick-calc. Use the Calculator in the minibuffer. - K calc-keypad. Start the Calculator in keypad mode (X window system only). - E calc-embedded. Use the Calculator on a formula in this editing buffer. - J calc-embedded-select. Like E, but select appropriate half of => or :=. - W calc-embedded-word. Like E, but activate a single word, i.e., a number. - Z calc-user-invocation. Invoke Calc in the way you defined with `Z I' cmd. - X calc-quit. Turn Calc off. + \\`C' `calc'. Start the Calculator in a window at the bottom of the screen. + \\`O' `calc-other-window'. Start the Calculator but don't select its window. + \\`B' `calc-big-or-small'. Control whether to use the full Emacs screen for Calc. + \\`Q' `quick-calc'. Use the Calculator in the minibuffer. + \\`K' `calc-keypad'. Start the Calculator in keypad mode (X window system only). + \\`E' `calc-embedded'. Use the Calculator on a formula in this editing buffer. + \\`J' `calc-embedded-select'. Like E, but select appropriate half of => or :=. + \\`W' `calc-embedded-word'. Like E, but activate a single word, i.e., a number. + \\`Z' `calc-user-invocation'. Invoke Calc in the way you defined with `Z I' cmd. + \\`X' `calc-quit'. Turn Calc off. For moving data into and out of Calc: - G calc-grab-region. Grab the region defined by mark and point into Calc. - R calc-grab-rectangle. Grab the rectangle defined by mark, point into Calc. - : calc-grab-sum-down. Grab a rectangle and sum the columns. - _ calc-grab-sum-across. Grab a rectangle and sum the rows. - Y calc-copy-to-buffer. Copy a value from the stack into the editing buffer. + \\`G' `calc-grab-region'. Grab the region defined by mark and point into Calc. + \\`R' `calc-grab-rectangle'. Grab the rectangle defined by mark, point into Calc. + \\`:' `calc-grab-sum-down'. Grab a rectangle and sum the columns. + \\`_' `calc-grab-sum-across'. Grab a rectangle and sum the rows. + \\`Y' `calc-copy-to-buffer'. Copy a value from the stack into the editing buffer. For use with Embedded mode: - A calc-embedded-activate. Find and activate all :='s and =>'s in buffer. - D calc-embedded-duplicate. Make a copy of this formula and select it. - F calc-embedded-new-formula. Insert a new formula at current point. - N calc-embedded-next. Advance cursor to next known formula in buffer. - P calc-embedded-previous. Advance cursor to previous known formula. - U calc-embedded-update-formula. Re-evaluate formula at point. - \\=` calc-embedded-edit. Use calc-edit to edit formula at point. + \\`A' `calc-embedded-activate'. Find and activate all :='s and =>'s in buffer. + \\`D' `calc-embedded-duplicate'. Make a copy of this formula and select it. + \\`F' `calc-embedded-new-formula'. Insert a new formula at current point. + \\`N' `calc-embedded-next'. Advance cursor to next known formula in buffer. + \\`P' `calc-embedded-previous'. Advance cursor to previous known formula. + \\`U' `calc-embedded-update-formula'. Re-evaluate formula at point. + \\``' `calc-embedded-edit'. Use calc-edit to edit formula at point. Documentation: - I calc-info. Read the Calculator manual in the Emacs Info system. - T calc-tutorial. Run the Calculator Tutorial using the Emacs Info system. - S calc-summary. Read the Summary from the Calculator manual in Info. + \\`I' `calc-info'. Read the Calculator manual in the Emacs Info system. + \\`T' `calc-tutorial'. Run the Calculator Tutorial using the Emacs Info system. + \\`S' `calc-summary'. Read the Summary from the Calculator manual in Info. Miscellaneous: - L calc-load-everything. Load all parts of the Calculator into memory. - M read-kbd-macro. Read a region of keystroke names as a keyboard macro. - 0 (zero) calc-reset. Reset Calc stack and modes to default state. + \\`L' `calc-load-everything'. Load all parts of the Calculator into memory. + \\`M' `read-kbd-macro'. Read a region of keystroke names as a keyboard macro. + \\`0' (zero) `calc-reset'. Reset Calc stack and modes to default state. -Press `*' twice (`C-x * *') to turn Calc on or off using the same -Calc user interface as before (either C-x * C or C-x * K; initially C-x * C)." +Press \\`*' twice (\\`C-x * *') to turn Calc on or off using the same +Calc user interface as before (either \\`C-x * C' or \\`C-x * K'; initially \\`C-x * C')." (interactive "P") (calc-check-defines) (if calc-dispatch-help commit c8da2a991ee042742f4da65e99f751c14da8354a Author: Michael Albinus Date: Sun Jul 3 18:23:55 2022 +0200 Tramp code cleanup * lisp/net/tramp-cache.el (tramp-get-file-property) (tramp-get-connection-property): Make DEFAULT optional. Adapt callees. * lisp/net/tramp.el: * lisp/net/tramp-adb.el: * lisp/net/tramp-cmds.el: * lisp/net/tramp-compat.el: * lisp/net/tramp-crypt.el: * lisp/net/tramp-ftp.el: * lisp/net/tramp-fuse.el: * lisp/net/tramp-gvfs.el: * lisp/net/tramp-integration.el: * lisp/net/tramp-sh.el: * lisp/net/tramp-smb.el: * lisp/net/tramp-sshfs.el: * lisp/net/trampver.el: Code cleanup. * test/lisp/net/tramp-tests.el (tramp--test-sh-no-ls--dired-p) (tramp--test-with-proper-process-name-and-buffer): Code cleanup. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 9981cc3c13..b504ce600d 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -270,7 +270,7 @@ arguments to pass to the OPERATION." "Parse `file-attributes' for Tramp files using the ls(1) command." (with-current-buffer (tramp-get-buffer vec) (goto-char (point-min)) - (let ((file-properties nil)) + (let (file-properties) (while (re-search-forward tramp-adb-ls-toolbox-regexp nil t) (let* ((mod-string (match-string 1)) (is-dir (eq ?d (aref mod-string 0))) @@ -1289,8 +1289,7 @@ connection if a previous connection has died for some reason." "echo \\\"`getprop ro.product.model` " "`getprop ro.product.version` " "`getprop ro.build.version.release`\\\"")) - (let ((old-getprop - (tramp-get-connection-property vec "getprop" nil)) + (let ((old-getprop (tramp-get-connection-property vec "getprop")) (new-getprop (tramp-set-connection-property vec "getprop" diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index a0cbfed64e..dbebcad1a8 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -129,7 +129,7 @@ If KEY is `tramp-cache-undefined', don't create anything, and return nil." hash)))) ;;;###tramp-autoload -(defun tramp-get-file-property (key file property default) +(defun tramp-get-file-property (key file property &optional default) "Get the PROPERTY of FILE from the cache context of KEY. Return DEFAULT if not set." ;; Unify localname. Remove hop from `tramp-file-name' structure. @@ -240,7 +240,7 @@ Return VALUE." (defun tramp-flush-file-properties (key file) "Remove all properties of FILE in the cache context of KEY." (let* ((file (tramp-run-real-handler #'directory-file-name (list file))) - (truename (tramp-get-file-property key file "file-truename" nil))) + (truename (tramp-get-file-property key file "file-truename"))) ;; Unify localname. Remove hop from `tramp-file-name' structure. (setq file (tramp-compat-file-name-unquote file) key (copy-tramp-file-name key)) @@ -262,7 +262,7 @@ Remove also properties of all files in subdirectories." (setq directory (tramp-compat-file-name-unquote directory)) (let* ((directory (tramp-run-real-handler #'directory-file-name (list directory))) - (truename (tramp-get-file-property key directory "file-truename" nil))) + (truename (tramp-get-file-property key directory "file-truename"))) (tramp-message key 8 "%s" directory) (dolist (key (hash-table-keys tramp-cache-data)) (when (and (tramp-file-name-p key) @@ -311,7 +311,7 @@ This is suppressed for temporary buffers." ;;; -- Properties -- ;;;###tramp-autoload -(defun tramp-get-connection-property (key property default) +(defun tramp-get-connection-property (key property &optional default) "Get the named PROPERTY for the connection. KEY identifies the connection, it is either a process or a `tramp-file-name' structure. A special case is nil, which is diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 006683bdcc..bd2dbf4a1e 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -135,7 +135,7 @@ When called interactively, a Tramp connection has to be selected." (get-buffer (tramp-debug-buffer-name vec))) (unless keep-debug (get-buffer (tramp-trace-buffer-name vec))) - (tramp-get-connection-property vec "process-buffer" nil))) + (tramp-get-connection-property vec "process-buffer"))) (when (bufferp buf) (kill-buffer buf))) ;; Flush file cache. @@ -722,7 +722,7 @@ the debug buffer(s).") (when (y-or-n-p "Do you want to append the buffer(s)?") ;; OK, let's send. First we delete the buffer list. - (kill-buffer nil) + (kill-buffer) (switch-to-buffer curbuf) (goto-char (point-max)) (insert (propertize "\n" 'display "\n\ diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el index bd6d53afcb..a12e4859ac 100644 --- a/lisp/net/tramp-compat.el +++ b/lisp/net/tramp-compat.el @@ -31,7 +31,7 @@ (require 'auth-source) (require 'format-spec) -(require 'ls-lisp) ;; Due to `tramp-handle-insert-directory'. +(require 'ls-lisp) ;; Due to `tramp-handle-insert-directory'. (require 'parse-time) (require 'shell) (require 'subr-x) @@ -234,7 +234,7 @@ CONDITION can also be a list of error conditions." (if (fboundp 'string-replace) #'string-replace (lambda (from-string to-string in-string) - (let ((case-fold-search nil)) + (let (case-fold-search) (replace-regexp-in-string (regexp-quote from-string) to-string in-string t t))))) @@ -243,7 +243,7 @@ CONDITION can also be a list of error conditions." (if (fboundp 'string-search) #'string-search (lambda (needle haystack &optional start-pos) - (let ((case-fold-search nil)) + (let (case-fold-search) (string-match-p (regexp-quote needle) haystack start-pos))))) ;; Function `make-lock-file-name' is new in Emacs 28.1. diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el index ca7bcf35ce..6cb1237a0f 100644 --- a/lisp/net/tramp-crypt.el +++ b/lisp/net/tramp-crypt.el @@ -151,7 +151,7 @@ If NAME doesn't belong to a crypted remote directory, retun nil." (dolist (dir tramp-crypt-directories) (and (string-prefix-p dir (file-name-as-directory (expand-file-name name))) - (throw 'crypt-file-name-p dir)))))) + (throw 'crypt-file-name-p dir)))))) ;; New handlers should be added here. diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el index 7a13760ffc..dd7e0f9f34 100644 --- a/lisp/net/tramp-ftp.el +++ b/lisp/net/tramp-ftp.el @@ -125,7 +125,7 @@ pass to the OPERATION." ;; "ftp" method is used in the Tramp file name. So we unset ;; those values. (ange-ftp-ftp-name-arg "") - (ange-ftp-ftp-name-res nil)) + ange-ftp-ftp-name-res) (cond ;; If argument is a symlink, `file-directory-p' and ;; `file-exists-p' call the traversed file recursively. So we diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el index 20be74a79b..2ff106d602 100644 --- a/lisp/net/tramp-fuse.el +++ b/lisp/net/tramp-fuse.el @@ -153,7 +153,7 @@ (defun tramp-fuse-mount-point (vec) "Return local mount point of VEC." - (or (tramp-get-connection-property vec "mount-point" nil) + (or (tramp-get-connection-property vec "mount-point") (expand-file-name (concat tramp-temp-name-prefix @@ -177,7 +177,7 @@ It has the same meaning as `remote-file-name-inhibit-cache'.") ;; cannot use `with-tramp-file-property', because we don't want to ;; cache a nil result. (let ((remote-file-name-inhibit-cache tramp-fuse-mount-timeout)) - (or (tramp-get-file-property vec "/" "mounted" nil) + (or (tramp-get-file-property vec "/" "mounted") (let* ((default-directory tramp-compat-temporary-file-directory) (command (format "mount -t fuse.%s" (tramp-file-name-method vec))) (mount (shell-command-to-string command))) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 07e084768a..056237fd55 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1020,7 +1020,7 @@ file names." ;; We cannot copy or rename directly. ((or (and equal-remote - (tramp-get-connection-property v "direct-copy-failed" nil)) + (tramp-get-connection-property v "direct-copy-failed")) (and t1 (not (tramp-gvfs-file-name-p filename))) (and t2 (not (tramp-gvfs-file-name-p newname)))) (let ((tmpfile (tramp-compat-make-temp-file filename))) @@ -1057,7 +1057,7 @@ file names." (if (or (not equal-remote) (and equal-remote (tramp-get-connection-property - v "direct-copy-failed" nil))) + v "direct-copy-failed"))) ;; Propagate the error. (with-current-buffer (tramp-get-connection-buffer v) (goto-char (point-min)) @@ -1145,7 +1145,7 @@ file names." (setq name (tramp-compat-file-name-concat dir name))) ;; If NAME is not a Tramp file, run the real handler. (if (not (tramp-tramp-file-p name)) - (tramp-run-real-handler #'expand-file-name (list name nil)) + (tramp-run-real-handler #'expand-file-name (list name)) ;; Dissect NAME. (with-parsed-tramp-file-name name nil ;; If there is a default location, expand tilde. @@ -1336,32 +1336,29 @@ If FILE-SYSTEM is non-nil, return file system attributes." (or (cdr (assoc "standard::size" attributes)) "0"))) ;; ... file mode flags (setq res-filemodes - (let ((n (cdr (assoc "unix::mode" attributes)))) - (if n - (tramp-file-mode-from-int (string-to-number n)) - (format - "%s%s%s%s------" - (if dirp "d" (if res-symlink-target "l" "-")) - (if (equal (cdr (assoc "access::can-read" attributes)) - "FALSE") - "-" "r") - (if (equal (cdr (assoc "access::can-write" attributes)) - "FALSE") - "-" "w") - (if (equal (cdr (assoc "access::can-execute" attributes)) - "FALSE") - "-" "x"))))) + (if-let ((n (cdr (assoc "unix::mode" attributes)))) + (tramp-file-mode-from-int (string-to-number n)) + (format + "%s%s%s%s------" + (if dirp "d" (if res-symlink-target "l" "-")) + (if (equal (cdr (assoc "access::can-read" attributes)) + "FALSE") + "-" "r") + (if (equal (cdr (assoc "access::can-write" attributes)) + "FALSE") + "-" "w") + (if (equal (cdr (assoc "access::can-execute" attributes)) + "FALSE") + "-" "x")))) ;; ... inode and device (setq res-inode - (let ((n (cdr (assoc "unix::inode" attributes)))) - (if n - (string-to-number n) - (tramp-get-inode (tramp-dissect-file-name filename))))) + (if-let ((n (cdr (assoc "unix::inode" attributes)))) + (string-to-number n) + (tramp-get-inode (tramp-dissect-file-name filename)))) (setq res-device - (let ((n (cdr (assoc "unix::device" attributes)))) - (if n - (string-to-number n) - (tramp-get-device (tramp-dissect-file-name filename))))) + (if-let ((n (cdr (assoc "unix::device" attributes)))) + (string-to-number n) + (tramp-get-device (tramp-dissect-file-name filename)))) ;; Return data gathered. (list @@ -1582,8 +1579,7 @@ If FILE-SYSTEM is non-nil, return file system attributes." (with-current-buffer (tramp-get-connection-buffer vec) (goto-char (point-min)) (when (looking-at-p "gio: Operation not supported") - (tramp-set-connection-property vec key nil))) - nil)))) + (tramp-set-connection-property vec key nil))))))) (defun tramp-gvfs-handle-set-file-modes (filename mode &optional flag) "Like `set-file-modes' for Tramp files." @@ -1612,12 +1608,11 @@ If FILE-SYSTEM is non-nil, return file system attributes." If USER is a string, return its home directory instead of the user identified by VEC. If there is no user specified in either VEC or USER, or if there is no home directory, return nil." - (let ((localname - (tramp-get-connection-property vec "default-location" nil)) + (let ((localname (tramp-get-connection-property vec "default-location")) result) (cond ((zerop (length localname)) - (tramp-get-connection-property (tramp-get-process vec) "share" nil)) + (tramp-get-connection-property (tramp-get-process vec) "share")) ;; Google-drive. ((not (string-prefix-p "/" localname)) (dolist (item @@ -1634,8 +1629,7 @@ ID-FORMAT valid values are `string' and `integer'." (if (equal id-format 'string) (tramp-file-name-user vec) (when-let ((localname - (tramp-get-connection-property - (tramp-get-process vec) "share" nil))) + (tramp-get-connection-property (tramp-get-process vec) "share"))) (file-attribute-user-id (file-attributes (tramp-make-tramp-file-name vec localname) id-format))))) @@ -1643,8 +1637,7 @@ ID-FORMAT valid values are `string' and `integer'." "The gid of the remote connection VEC, in ID-FORMAT. ID-FORMAT valid values are `string' and `integer'." (when-let ((localname - (tramp-get-connection-property - (tramp-get-process vec) "share" nil))) + (tramp-get-connection-property (tramp-get-process vec) "share"))) (file-attribute-group-id (file-attributes (tramp-make-tramp-file-name vec localname) id-format)))) @@ -1682,7 +1675,7 @@ ID-FORMAT valid values are `string' and `integer'." (concat (tramp-gvfs-get-remote-prefix v) localname))) (when (string-equal "mtp" method) (when-let - ((media (tramp-get-connection-property v "media-device" nil))) + ((media (tramp-get-connection-property v "media-device"))) (setq method (tramp-media-device-method media) host (tramp-media-device-host media) port (tramp-media-device-port media)))) @@ -1757,7 +1750,7 @@ a downcased host name only." (setq domain (read-string "Domain name: "))) (tramp-message l 6 "%S %S %S %d" message user domain flags) - (unless (tramp-get-connection-property l "first-password-request" nil) + (unless (tramp-get-connection-property l "first-password-request") (tramp-clear-passwd l)) (setq password (tramp-read-passwd @@ -1879,14 +1872,13 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and (when (member method tramp-media-methods) ;; Ensure that media devices are cached. (tramp-get-media-devices nil) - (let ((v (tramp-get-connection-property - (make-tramp-media-device - :method method :host host :port port) - "vector" nil))) - (when v - (setq method (tramp-file-name-method v) - host (tramp-file-name-host v) - port (tramp-file-name-port v))))) + (when-let ((v (tramp-get-connection-property + (make-tramp-media-device + :method method :host host :port port) + "vector" nil))) + (setq method (tramp-file-name-method v) + host (tramp-file-name-host v) + port (tramp-file-name-port v)))) (when (member method tramp-gvfs-methods) (let ((v (make-tramp-file-name :method method :user user :domain domain @@ -1924,15 +1916,14 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and (defun tramp-gvfs-connection-mounted-p (vec) "Check, whether the location is already mounted." (or - (tramp-get-file-property vec "/" "fuse-mountpoint" nil) + (tramp-get-file-property vec "/" "fuse-mountpoint") (catch 'mounted (dolist (elt (with-tramp-file-property vec "/" "list-mounts" (with-tramp-dbus-call-method vec t :session tramp-gvfs-service-daemon tramp-gvfs-path-mounttracker - tramp-gvfs-interface-mounttracker tramp-gvfs-listmounts)) - nil) + tramp-gvfs-interface-mounttracker tramp-gvfs-listmounts))) ;; Jump over the first elements of the mount info. Since there ;; were changes in the entries, we cannot access dedicated ;; elements. @@ -1981,14 +1972,13 @@ Their full names are \"org.gtk.vfs.MountTracker.mounted\" and (when (member method tramp-media-methods) ;; Ensure that media devices are cached. (tramp-get-media-devices vec) - (let ((v (tramp-get-connection-property - (make-tramp-media-device - :method method :host host :port port) - "vector" nil))) - (when v - (setq method (tramp-file-name-method v) - host (tramp-file-name-host v) - port (tramp-file-name-port v))))) + (when-let ((v (tramp-get-connection-property + (make-tramp-media-device + :method method :host host :port port) + "vector"))) + (setq method (tramp-file-name-method v) + host (tramp-file-name-host v) + port (tramp-file-name-port v)))) (when (and (string-equal method (tramp-file-name-method vec)) (string-equal user (tramp-file-name-user vec)) @@ -2244,7 +2234,7 @@ connection if a previous connection has died for some reason." (tramp-error vec 'file-error "Timeout reached mounting %s@%s using %s" user host method))) - (while (not (tramp-get-file-property vec "/" "fuse-mountpoint" nil)) + (while (not (tramp-get-file-property vec "/" "fuse-mountpoint")) (read-event nil nil 0.1))) ;; If `tramp-gvfs-handler-askquestion' has returned "No", it @@ -2382,11 +2372,11 @@ It checks for registered GNOME Online Accounts." (defun tramp-get-media-device (vec) "Transform VEC into a `tramp-media-device' structure. Check, that respective cache values do exist." - (if-let ((media (tramp-get-connection-property vec "media-device" nil)) - (prop (tramp-get-connection-property media "vector" nil))) + (if-let ((media (tramp-get-connection-property vec "media-device")) + (prop (tramp-get-connection-property media "vector"))) media (tramp-get-media-devices vec) - (tramp-get-connection-property vec "media-device" nil))) + (tramp-get-connection-property vec "media-device"))) (defun tramp-get-media-devices (vec) "Retrieve media devices, and cache them. @@ -2431,9 +2421,9 @@ It checks for mounted media devices." (lambda (key) (and (tramp-media-device-p key) (string-equal service (tramp-media-device-method key)) - (tramp-get-connection-property key "vector" nil) + (tramp-get-connection-property key "vector") (list nil (tramp-file-name-host - (tramp-get-connection-property key "vector" nil))))) + (tramp-get-connection-property key "vector"))))) (hash-table-keys tramp-cache-data))) diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el index 5e51074c49..226113d880 100644 --- a/lisp/net/tramp-integration.el +++ b/lisp/net/tramp-integration.el @@ -108,7 +108,7 @@ been set up by `rfn-eshadow-setup-minibuffer'." end)) (point-max)) (let ((rfn-eshadow-overlay tramp-rfn-eshadow-overlay) - (rfn-eshadow-update-overlay-hook nil) + rfn-eshadow-update-overlay-hook file-name-handler-alist) (move-overlay rfn-eshadow-overlay (point-max) (point-max)) (rfn-eshadow-update-overlay)))))))) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index f2e91a1977..174fde720e 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -1146,8 +1146,8 @@ component is used as the target of the symlink." ;; Use Perl implementation. ((and (tramp-get-remote-perl v) - (tramp-get-connection-property v "perl-file-spec" nil) - (tramp-get-connection-property v "perl-cwd-realpath" nil)) + (tramp-get-connection-property v "perl-file-spec") + (tramp-get-connection-property v "perl-cwd-realpath")) (tramp-maybe-send-script v tramp-perl-file-truename "tramp_perl_file_truename") (setq result @@ -1185,9 +1185,9 @@ component is used as the target of the symlink." (with-parsed-tramp-file-name filename nil (with-tramp-file-property v localname "file-exists-p" (or (not (null (tramp-get-file-property - v localname "file-attributes-integer" nil))) + v localname "file-attributes-integer"))) (not (null (tramp-get-file-property - v localname "file-attributes-string" nil))) + v localname "file-attributes-string"))) (tramp-send-command-and-check v (format @@ -1463,7 +1463,7 @@ of." v (format "env TZ=UTC %s %s %s %s" (tramp-get-remote-touch v) - (if (tramp-get-connection-property v "touch-t" nil) + (if (tramp-get-connection-property v "touch-t") (format "-t %s" (format-time-string "%Y%m%d%H%M.%S" time t)) "") (if (eq flag 'nofollow) "-h" "") @@ -2350,7 +2350,7 @@ The method used must be an out-of-band method." ?h (or (tramp-file-name-host v) "") ?u (or (tramp-file-name-user v) ;; There might be an interactive setting. - (tramp-get-connection-property v "login-as" nil) + (tramp-get-connection-property v "login-as") "") ;; For direct remote copying, the port must be the ;; same for source and target. @@ -2771,7 +2771,7 @@ the result will be a local, non-Tramp, file name." (with-parsed-tramp-file-name name nil ;; If connection is not established yet, run the real handler. (if (not (tramp-connectable-p v)) - (tramp-run-real-handler #'expand-file-name (list name nil)) + (tramp-run-real-handler #'expand-file-name (list name)) (unless (tramp-run-real-handler #'file-name-absolute-p (list localname)) (setq localname (concat "~/" localname))) ;; Tilde expansion if necessary. This needs a shell which @@ -3976,7 +3976,7 @@ Only send the definition if it has not already been done." ;; We cannot let-bind (tramp-get-connection-process vec) because it ;; might be nil. (let ((scripts (tramp-get-connection-property - (tramp-get-connection-process vec) "scripts" nil))) + (tramp-get-connection-process vec) "scripts"))) (unless (member name scripts) (with-tramp-progress-reporter vec 5 (format-message "Sending script `%s'" name) @@ -4226,7 +4226,7 @@ file exists and nonzero exit status otherwise." (defun tramp-find-shell (vec) "Open a shell on the remote host which groks tilde expansion." ;; If we are in `make-process', we don't need another shell. - (unless (tramp-get-connection-property vec "process-name" nil) + (unless (tramp-get-connection-property vec "process-name") (with-current-buffer (tramp-get-buffer vec) (let ((default-shell (tramp-get-method-parameter vec 'tramp-remote-shell)) shell) @@ -4323,11 +4323,10 @@ process to set up. VEC specifies the connection." ;; connection properties. We start again with ;; `tramp-maybe-open-connection', it will be caught there. (tramp-message vec 5 "Checking system information") - (let* ((old-uname (tramp-get-connection-property vec "uname" nil)) + (let* ((old-uname (tramp-get-connection-property vec "uname")) (uname ;; If we are in `make-process', we don't need to recompute. - (if (and old-uname - (tramp-get-connection-property vec "process-name" nil)) + (if (and old-uname (tramp-get-connection-property vec "process-name")) old-uname (tramp-set-connection-property vec "uname" @@ -4935,7 +4934,7 @@ Goes through the list `tramp-inline-compress-commands'." "Close the connection VEC after a session timeout. If there is just some editing, retry it after 5 seconds." (if (and (tramp-get-connection-property - (tramp-get-connection-process vec) "locked" nil) + (tramp-get-connection-process vec) "locked") (tramp-file-name-equal-p vec (car tramp-current-connection))) (progn (tramp-message @@ -4954,7 +4953,7 @@ connection if a previous connection has died for some reason." (throw 'non-essential 'non-essential)) (let ((p (tramp-get-connection-process vec)) - (process-name (tramp-get-connection-property vec "process-name" nil)) + (process-name (tramp-get-connection-property vec "process-name")) (process-environment (copy-sequence process-environment)) (pos (with-current-buffer (tramp-get-connection-buffer vec) (point)))) @@ -5168,9 +5167,9 @@ connection if a previous connection has died for some reason." previous-hop hop))) ;; Activate session timeout. - (when (tramp-get-connection-property p "session-timeout" nil) + (when (tramp-get-connection-property p "session-timeout") (run-at-time - (tramp-get-connection-property p "session-timeout" nil) nil + (tramp-get-connection-property p "session-timeout") nil #'tramp-timeout-session vec)) ;; Make initial shell settings. @@ -5192,7 +5191,7 @@ is meant to be used from `tramp-maybe-open-connection' only. The function waits for output unless NOOUTPUT is set." (unless neveropen (tramp-maybe-open-connection vec)) (let ((p (tramp-get-connection-process vec))) - (when (tramp-get-connection-property p "remote-echo" nil) + (when (tramp-get-connection-property p "remote-echo") ;; We mark the command string that it can be erased in the output buffer. (tramp-set-connection-property p "check-remote-echo" t) ;; If we put `tramp-echo-mark' after a trailing newline (which @@ -5959,7 +5958,7 @@ If no corresponding command is found, nil is returned." (> size tramp-inline-compress-start-size)) (with-tramp-connection-property (tramp-get-process vec) prop (tramp-find-inline-compress vec) - (tramp-get-connection-property (tramp-get-process vec) prop nil)))) + (tramp-get-connection-property (tramp-get-process vec) prop)))) (defun tramp-get-inline-coding (vec prop size) "Return the coding command related to PROP. @@ -5979,7 +5978,7 @@ function cell is returned to be applied on a buffer." (let ((coding (with-tramp-connection-property (tramp-get-process vec) prop (tramp-find-inline-encoding vec) - (tramp-get-connection-property (tramp-get-process vec) prop nil))) + (tramp-get-connection-property (tramp-get-process vec) prop))) (prop1 (if (tramp-compat-string-search "encoding" prop) "inline-compress" "inline-decompress")) compress) diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 528463c5a7..b717c4dcc3 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -748,7 +748,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (setq name (tramp-compat-file-name-concat dir name))) ;; If NAME is not a Tramp file, run the real handler. (if (not (tramp-tramp-file-p name)) - (tramp-run-real-handler #'expand-file-name (list name nil)) + (tramp-run-real-handler #'expand-file-name (list name)) ;; Dissect NAME. (with-parsed-tramp-file-name name nil ;; Tilde expansion if necessary. @@ -1385,7 +1385,7 @@ component is used as the target of the symlink." (when tmpinput (delete-file tmpinput)) ;; FIXME: Does connection-property "process-buffer" still exist? (unless outbuf - (kill-buffer (tramp-get-connection-property v "process-buffer" nil))) + (kill-buffer (tramp-get-connection-property v "process-buffer"))) (when process-file-side-effects (tramp-flush-directory-properties v "")) @@ -1700,7 +1700,7 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)." (setq localname (or localname "/")) (with-tramp-file-property v localname "file-entries" (let* ((share (tramp-smb-get-share v)) - (cache (tramp-get-connection-property v "share-cache" nil)) + (cache (tramp-get-connection-property v "share-cache")) res entry) (if (and (not share) cache) @@ -2029,7 +2029,7 @@ If ARGUMENT is non-nil, use it as argument for (if (not (zerop (length user))) (concat user "@") "") host (or share "")) - (let* ((coding-system-for-read nil) + (let* (coding-system-for-read (process-connection-type tramp-process-connection-type) (p (let ((default-directory tramp-compat-temporary-file-directory) diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el index 61bf165f30..d7c918fbc8 100644 --- a/lisp/net/tramp-sshfs.el +++ b/lisp/net/tramp-sshfs.el @@ -449,7 +449,7 @@ connection if a previous connection has died for some reason." (funcall orig-fun))) (add-function - :around (symbol-function #'shell-mode) #'tramp-sshfs-tolerate-tilde) + :around (symbol-function #'shell-mode) #'tramp-sshfs-tolerate-tilde) (add-hook 'tramp-sshfs-unload-hook (lambda () (remove-function diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 9d5a02456e..b580987e91 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1384,7 +1384,8 @@ would require an immediate reread during filename completion, nil means to use always cached values for the directory contents." :type '(choice (const nil) (const t) integer)) (make-obsolete-variable - 'tramp-completion-reread-directory-timeout 'remote-file-name-inhibit-cache "27.2") + 'tramp-completion-reread-directory-timeout + 'remote-file-name-inhibit-cache "27.2") ;;; Internal Variables: @@ -1501,7 +1502,7 @@ entry does not exist, return nil." (replace-regexp-in-string "^tramp-" "" (symbol-name param)))) (if (tramp-connection-property-p vec hash-entry) ;; We use the cached property. - (tramp-get-connection-property vec hash-entry nil) + (tramp-get-connection-property vec hash-entry) ;; Use the static value from `tramp-methods'. (when-let ((methods-entry (assoc @@ -1837,7 +1838,7 @@ Unless DONT-CREATE, the buffer is created when it doesn't exist yet." ;; as indication, whether a connection is active. (tramp-set-connection-property vec "process-buffer" - (tramp-get-connection-property vec "process-buffer" nil)) + (tramp-get-connection-property vec "process-buffer")) (setq buffer-undo-list t default-directory (tramp-make-tramp-file-name vec 'noloc)) @@ -1848,14 +1849,14 @@ Unless DONT-CREATE, the buffer is created when it doesn't exist yet." Unless DONT-CREATE, the buffer is created when it doesn't exist yet. In case a second asynchronous communication has been started, it is different from `tramp-get-buffer'." - (or (tramp-get-connection-property vec "process-buffer" nil) + (or (tramp-get-connection-property vec "process-buffer") (tramp-get-buffer vec dont-create))) (defun tramp-get-connection-name (vec) "Get the connection name to be used for VEC. In case a second asynchronous communication has been started, it is different from the default one." - (or (tramp-get-connection-property vec "process-name" nil) + (or (tramp-get-connection-property vec "process-name") (tramp-buffer-name vec))) (defun tramp-get-process (vec-or-proc) @@ -2352,7 +2353,7 @@ without a visible progress reporter." ;; running, and when there is a minimum level. (when-let ((pr (and (null tramp-inhibit-progress-reporter) (<= ,level (min tramp-verbose 3)) - (make-progress-reporter ,message nil nil)))) + (make-progress-reporter ,message)))) (run-at-time 3 0.1 #'tramp-progress-reporter-update pr)))) (unwind-protect ;; Execute the body. @@ -3521,7 +3522,7 @@ Let-bind it when necessary.") ;; home directory. (tramp-get-home-directory vec) ;; Otherwise, just use the cached value. - (tramp-get-connection-property vec "~" nil)))) + (tramp-get-connection-property vec "~")))) (when home-dir (setq home-dir (tramp-compat-funcall @@ -3651,7 +3652,7 @@ Let-bind it when necessary.") (setq name (tramp-compat-file-name-concat dir name))) ;; If NAME is not a Tramp file, run the real handler. (if (not (tramp-tramp-file-p name)) - (tramp-run-real-handler #'expand-file-name (list name nil)) + (tramp-run-real-handler #'expand-file-name (list name)) ;; Dissect NAME. (with-parsed-tramp-file-name name nil (unless (tramp-run-real-handler #'file-name-absolute-p (list localname)) @@ -3881,7 +3882,7 @@ Let-bind it when necessary.") (let* ((o (tramp-dissect-file-name filename)) (p (tramp-get-connection-process o)) (c (and (process-live-p p) - (tramp-get-connection-property p "connected" nil)))) + (tramp-get-connection-property p "connected")))) ;; We expand the file name only, if there is already a connection. (with-parsed-tramp-file-name (if c (expand-file-name filename) filename) nil @@ -4567,7 +4568,7 @@ substitution. SPEC-LIST is a list of char/value pairs used for (and ;; The method supports it. (tramp-get-method-parameter v 'tramp-direct-async) ;; It has been indicated. - (tramp-get-connection-property v "direct-async-process" nil) + (tramp-get-connection-property v "direct-async-process") ;; There's no multi-hop. (or (not (tramp-multi-hop-p v)) (= (length (tramp-compute-multi-hops v)) 1)) @@ -4848,7 +4849,7 @@ support symbolic links." (prog1 ;; Run the process. - (process-file-shell-command command nil buffer nil) + (process-file-shell-command command nil buffer) ;; Insert error messages if they were separated. (when error-file (with-current-buffer error-buffer @@ -5073,8 +5074,7 @@ of." ;; Sometimes, the process returns a new password request ;; immediately after rejecting the previous (wrong) one. (unless (or tramp-password-prompt-not-unique - (tramp-get-connection-property - vec "first-password-request" nil)) + (tramp-get-connection-property vec "first-password-request")) (tramp-clear-passwd vec)) (goto-char (point-min)) (tramp-check-for-regexp proc tramp-process-action-regexp) @@ -5318,7 +5318,7 @@ performed successfully. Any other value means an error." "Lock PROC for other communication, and run BODY. Mostly useful to protect BODY from being interrupted by timers." (declare (indent 1) (debug t)) - `(if (tramp-get-connection-property ,proc "locked" nil) + `(if (tramp-get-connection-property ,proc "locked") ;; Be kind for older Emacsen. (if (member 'remote-file-error debug-ignored-errors) (throw 'non-essential 'non-essential) @@ -5371,7 +5371,7 @@ Erase echoed commands if exists." ;; Check whether we need to remove echo output. The max length of ;; the echo mark regexp is taken for search. We restrict the ;; search for the second echo mark to PIPE_BUF characters. - (when (and (tramp-get-connection-property proc "check-remote-echo" nil) + (when (and (tramp-get-connection-property proc "check-remote-echo") (re-search-forward tramp-echoed-echo-mark-regexp (+ (point) (* 5 tramp-echo-mark-marker-length)) t)) @@ -5387,7 +5387,7 @@ Erase echoed commands if exists." (delete-region begin (point)) (goto-char (point-min))))) - (when (or (not (tramp-get-connection-property proc "check-remote-echo" nil)) + (when (or (not (tramp-get-connection-property proc "check-remote-echo")) ;; Sometimes, the echo string is suppressed on the remote side. (not (string-equal (substring-no-properties @@ -5449,7 +5449,7 @@ The STRING is expected to use Unix line-endings, but the lines sent to the remote host use line-endings as defined in the variable `tramp-rsh-end-of-line'. The communication buffer is erased before sending." (let* ((p (tramp-get-connection-process vec)) - (chunksize (tramp-get-connection-property p "chunksize" nil))) + (chunksize (tramp-get-connection-property p "chunksize"))) (unless p (tramp-error vec 'file-error "Can't send string to remote host -- not logged in")) @@ -5487,7 +5487,7 @@ the remote host use line-endings as defined in the variable (unless (process-live-p proc) (let ((vec (process-get proc 'vector)) (buf (process-buffer proc)) - (prompt (tramp-get-connection-property proc "prompt" nil))) + (prompt (tramp-get-connection-property proc "prompt"))) (when vec (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event) (tramp-flush-connection-properties proc) @@ -5711,7 +5711,7 @@ VEC is used for tracing." "Check `file-attributes' caches for VEC. Return t if according to the cache access type ACCESS is known to be granted." - (let ((result nil) + (let (result (offset (cond ((eq ?r access) 1) ((eq ?w access) 2) @@ -6055,7 +6055,7 @@ Consults the auth-source package." (key (tramp-make-tramp-file-name vec 'noloc)) (method (tramp-file-name-method vec)) (user (or (tramp-file-name-user-domain vec) - (tramp-get-connection-property key "login-as" nil))) + (tramp-get-connection-property key "login-as"))) (host (tramp-file-name-host-port vec)) (pw-prompt (or prompt @@ -6078,8 +6078,7 @@ Consults the auth-source package." (setq tramp-password-save-function nil) ;; See if auth-sources contains something useful. (ignore-errors - (and (tramp-get-connection-property - vec "first-password-request" nil) + (and (tramp-get-connection-property vec "first-password-request") ;; Try with Tramp's current method. If there is no ;; user name, `:create' triggers to ask for. We ;; suppress it. diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el index 9a2f495eb8..68fd110ec0 100644 --- a/lisp/net/trampver.el +++ b/lisp/net/trampver.el @@ -52,9 +52,9 @@ ;; Suppress message from `emacs-repository-get-branch'. We must ;; also handle out-of-tree builds. (let ((inhibit-message t) - (debug-on-error nil) (dir (or (locate-dominating-file (locate-library "tramp") ".git") - source-directory))) + source-directory)) + debug-on-error) ;; `emacs-repository-get-branch' has been introduced with Emacs 27.1. (with-no-warnings (and (stringp dir) (file-directory-p dir) @@ -67,9 +67,9 @@ ;; Suppress message from `emacs-repository-get-version'. We must ;; also handle out-of-tree builds. (let ((inhibit-message t) - (debug-on-error nil) (dir (or (locate-dominating-file (locate-library "tramp") ".git") - source-directory))) + source-directory)) + debug-on-error) (and (stringp dir) (file-directory-p dir) (executable-find "git") (emacs-repository-get-version dir)))) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 63fd96cae8..a53fc7ec7a 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -6570,7 +6570,7 @@ Additionally, ls does not support \"--dired\"." ;; This fails for tramp-crypt.el, so we ignore that. (ignore-errors (insert-directory ert-remote-temporary-file-directory "-al")) - (not (tramp-get-connection-property tramp-test-vec "ls--dired" nil))))) + (not (tramp-get-connection-property tramp-test-vec "ls--dired"))))) (defun tramp--test-share-p () "Check, whether the method needs a share." @@ -7141,13 +7141,13 @@ The values are derived from PROC. Run BODY. This is needed in timer functions as well as process filters and sentinels." ;; FIXME: For tramp-sshfs.el, `processp' does not work. (declare (indent 1) (debug (processp body))) - `(let* ((v (tramp-get-connection-property ,proc "vector" nil)) - (pname (tramp-get-connection-property v "process-name" nil)) - (pbuffer (tramp-get-connection-property v "process-buffer" nil))) + `(let* ((v (tramp-get-connection-property ,proc "vector")) + (pname (tramp-get-connection-property v "process-name")) + (pbuffer (tramp-get-connection-property v "process-buffer"))) (tramp--test-message "tramp--test-with-proper-process-name-and-buffer before %s %s" - (tramp-get-connection-property v "process-name" nil) - (tramp-get-connection-property v "process-buffer" nil)) + (tramp-get-connection-property v "process-name") + (tramp-get-connection-property v "process-buffer")) (if (process-name ,proc) (tramp-set-connection-property v "process-name" (process-name ,proc)) (tramp-flush-connection-property v "process-name")) @@ -7157,8 +7157,8 @@ This is needed in timer functions as well as process filters and sentinels." (tramp-flush-connection-property v "process-buffer")) (tramp--test-message "tramp--test-with-proper-process-name-and-buffer changed %s %s" - (tramp-get-connection-property v "process-name" nil) - (tramp-get-connection-property v "process-buffer" nil)) + (tramp-get-connection-property v "process-name") + (tramp-get-connection-property v "process-buffer")) (unwind-protect (progn ,@body) (if pname commit 676d38cfc34a001d0eebbb512468bafb3ba292cf Author: Florian Rommel Date: Sun Jul 3 17:04:32 2022 +0200 abort-redisplay: Add missing unbind_to in 'recenter' * src/window.c (recenter): Add ubind_to before early return. (Bug#56369) diff --git a/src/window.c b/src/window.c index ad03a02758..af463b90ce 100644 --- a/src/window.c +++ b/src/window.c @@ -6667,6 +6667,7 @@ and redisplay normally--don't erase and redraw the frame. */) if (h <= 0) { bidi_unshelve_cache (itdata, false); + unbind_to (count, Qnil); return Qnil; } commit bfc9e7669688b3439cfdd2d5972065b95eae812f Author: Stefan Monnier Date: Sun Jul 3 11:12:45 2022 -0400 lisp/elec-pair.el: Simplify last change * lisp/elec-pair.el (electric-pair--with-syntax): Rename from `electric-pair--with-text-syntax`. Make `start` mandatory. Run `body` in the normal syntax if `start` is nil. (electric-pair--with-syntax-1): New function, extracted from `electric-pair--with-text-syntax`. (electric-pair-syntax-info, electric-pair--balance-info): Adjust calls accordingly. diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 247e9b93ec..4b901071cd 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el @@ -188,24 +188,29 @@ be considered.") ;; I also find it often preferable not to pair next to a word. (eq (char-syntax (following-char)) ?w))) -(cl-defmacro electric-pair--with-text-syntax ((&optional start) &rest body) - "Run BODY with `electric-pair-text-syntax-table' active. -This ensures that all syntax related values are set properly and the -`syntax-ppss' cache is cleared before and after. -In particular, this must be used when BODY contains code which may -update the `syntax-ppss' cache. This includes calling -`parse-partial-sexp' and any sexp-based movement functions when -`parse-sexp-lookup-properties' is non-nil. The cache is flushed from -position START, defaulting to point." - (declare (debug ((&optional form) body)) (indent 1)) - (let ((start-var (make-symbol "start"))) - `(let ((syntax-propertize-function nil) - (,start-var ,(or start '(point)))) - (syntax-ppss-flush-cache ,start-var) +(defmacro electric-pair--with-syntax (string-or-comment &rest body) + "Run BODY with appropriate syntax table active. +STRING-OR-COMMENT is the start position of the string/comment +in which we are, if applicable. +Uses the text-mode syntax table if within a string or a comment." + (declare (debug t) (indent 1)) + `(electric-pair--with-syntax-1 ,string-or-comment (lambda () ,@body))) + +(defun electric-pair--with-syntax-1 (string-or-comment body-fun) + (if (not string-or-comment) + (funcall body-fun) + ;; Here we assume that the `syntax-ppss' cache has already been filled + ;; past `string-or-comment' with data corresponding to the "normal" syntax + ;; (this should be the case because STRING-OR-COMMENT was returned + ;; in the `nth 8' of `syntax-ppss'). + ;; Maybe we should narrow-to-region so that `syntax-ppss' uses the narrow + ;; cache? + (syntax-ppss-flush-cache string-or-comment) + (let ((syntax-propertize-function nil)) (unwind-protect (with-syntax-table electric-pair-text-syntax-table - ,@body) - (syntax-ppss-flush-cache ,start-var))))) + (funcall body-fun)) + (syntax-ppss-flush-cache string-or-comment))))) (defun electric-pair-syntax-info (command-event) "Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START). @@ -222,13 +227,10 @@ inside a comment or string." (string-or-comment (and post-string-or-comment pre-string-or-comment)) (table-syntax-and-pair - (cl-flet ((f () - (list (char-syntax command-event) - (or (matching-paren command-event) - command-event)))) - (if string-or-comment - (electric-pair--with-text-syntax () (f)) - (f)))) + (electric-pair--with-syntax string-or-comment + (list (char-syntax command-event) + (or (matching-paren command-event) + command-event)))) (fallback (if string-or-comment (append electric-pair-text-pairs electric-pair-pairs) @@ -275,7 +277,7 @@ when to fallback to `parse-partial-sexp'." (skip-syntax-forward " >!") (point))))) (if s-or-c-start - (electric-pair--with-text-syntax (s-or-c-start) + (electric-pair--with-syntax s-or-c-start (parse-partial-sexp s-or-c-start pos)) ;; HACK! cc-mode apparently has some `syntax-ppss' bugs (if (memq major-mode '(c-mode c++ mode)) @@ -293,7 +295,8 @@ when to fallback to `parse-partial-sexp'." (defun electric-pair--balance-info (direction string-or-comment) "Examine lists forward or backward according to DIRECTION's sign. -STRING-OR-COMMENT is info suitable for running `parse-partial-sexp'. +STRING-OR-COMMENT is the position of the start of the comment/string +in which we are, if applicable. Return a cons of two descriptions (MATCHED-P . PAIR) for the innermost and outermost lists that enclose point. The outermost @@ -325,14 +328,11 @@ If point is not enclosed by any lists, return ((t) . (t))." (cond ((< direction 0) (condition-case nil (eq (char-after pos) - (cl-flet ((f () - (matching-paren - (char-before - (scan-sexps (point) 1))))) - (if string-or-comment - (electric-pair--with-text-syntax () - (f)) - (f)))) + (electric-pair--with-syntax + string-or-comment + (matching-paren + (char-before + (scan-sexps (point) 1))))) (scan-error nil))) (t ;; In this case, no need to use @@ -346,9 +346,8 @@ If point is not enclosed by any lists, return ((t) . (t))." (opener (char-after start))) (and start (eq (char-before pos) - (or (if string-or-comment - (electric-pair--with-text-syntax () - (matching-paren opener)) + (or (electric-pair--with-syntax + string-or-comment (matching-paren opener)) opener)))))))) (actual-pair (if (> direction 0) @@ -361,14 +360,11 @@ If point is not enclosed by any lists, return ((t) . (t))." (save-excursion (while (not outermost) (condition-case err - (cl-flet ((f () - (scan-sexps (point) (if (> direction 0) - (point-max) - (- (point-max)))) - (funcall at-top-level-or-equivalent-fn))) - (if string-or-comment - (electric-pair--with-text-syntax () (f)) - (f))) + (electric-pair--with-syntax string-or-comment + (scan-sexps (point) (if (> direction 0) + (point-max) + (- (point-max)))) + (funcall at-top-level-or-equivalent-fn)) (scan-error (cond ((or ;; some error happened and it is not of the "ended commit e41ba8ab89a125c91dee672845679f2dec19853a Author: Stefan Kangas Date: Sun Jul 3 15:16:23 2022 +0200 Fix dired-goto-subdir prompt * lisp/dired-aux.el (dired-goto-subdir): Fix prompt and improve docstring. Add interactive mode tag for dired-mode. diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index c403cc5cbd..5f2d1cfc9f 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -3023,18 +3023,20 @@ When called interactively and not on a subdir line, go to this subdir's line." ;;;###autoload (defun dired-goto-subdir (dir) - "Go to end of header line of DIR in this dired buffer. + "Go to end of header line of inserted directory DIR in this Dired buffer. +When called interactively, prompt for the inserted subdirectory +to go to. + Return value of point on success, otherwise return nil. The next char is \\n." (interactive (prog1 ; let push-mark display its message (list (expand-file-name - (completing-read "Goto in situ directory: " ; prompt - dired-subdir-alist ; table - nil ; predicate - t ; require-match - (dired-current-directory)))) - (push-mark))) + (completing-read "Goto inserted directory: " + dired-subdir-alist nil t + (dired-current-directory)))) + (push-mark)) + dired-mode) (setq dir (file-name-as-directory dir)) (let ((elt (assoc dir dired-subdir-alist))) (and elt commit d5c6f22193402509e315ea3d78daa5e0f69d0ef4 Author: Stefan Kangas Date: Sun Jul 3 14:47:53 2022 +0200 Fix warnings in my last commit * lisp/textmodes/emacs-news-mode.el (outline): Require. diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el index c6b352448c..c5d7b6ea50 100644 --- a/lisp/textmodes/emacs-news-mode.el +++ b/lisp/textmodes/emacs-news-mode.el @@ -24,6 +24,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(require 'outline) (defgroup emacs-news-mode nil "Major mode for editing and viewing the Emacs NEWS file." commit d68ecda05c4a634a1f0a606c73137d85bf261775 Author: Stefan Kangas Date: Sun Jul 3 14:40:21 2022 +0200 Improve navigation keybindings in emacs-news-mode * lisp/textmodes/emacs-news-mode.el (emacs-news-common-map): New defvar-keymap. Bind navigation commands as in 'org-mode' and 'outline-minor-mode'. (emacs-news-mode-map): Inherit from 'emacs-news-common-map'. (emacs-news-view-mode-map): New defvar-keymap; inherit from 'emacs-news-common-map'. diff --git a/lisp/textmodes/emacs-news-mode.el b/lisp/textmodes/emacs-news-mode.el index fdb3cb8628..c6b352448c 100644 --- a/lisp/textmodes/emacs-news-mode.el +++ b/lisp/textmodes/emacs-news-mode.el @@ -39,12 +39,24 @@ "Face used for displaying the \"does not need documentation\" tag." :version "29.1") +(defvar-keymap emacs-news-common-map + ;; Navigation like `org-mode'/`outline-minor-mode'. + "C-c C-f" #'outline-forward-same-level + "C-c C-b" #'outline-backward-same-level + "C-c C-n" #'outline-next-visible-heading + "C-c C-p" #'outline-previous-visible-heading + "C-c C-u" #'outline-up-heading) + (defvar-keymap emacs-news-mode-map + :parent emacs-news-common-map "C-c C-s" #'emacs-news-next-untagged-entry "C-c C-r" #'emacs-news-previous-untagged-entry "C-c C-g" #'emacs-news-goto-section - "C-c C-f" #'emacs-news-find-heading - "C-c C-n" #'emacs-news-count-untagged-entries) + "C-c C-j" #'emacs-news-find-heading + "C-c C-e" #'emacs-news-count-untagged-entries) + +(defvar-keymap emacs-news-view-mode-map + :parent emacs-news-common-map) (defvar emacs-news-mode-font-lock-keywords `(("^---$" 0 'emacs-news-does-not-need-documentation) commit 18a2bc7a6e9af85e58ba77fc48277cc2a92e00f3 Merge: e9bb92940e 93cec6cf68 Author: Eli Zaretskii Date: Sun Jul 3 15:39:05 2022 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit e9bb92940e895c73c802d8c4c79e45de20ebbf83 Author: Eli Zaretskii Date: Sun Jul 3 15:37:50 2022 +0300 Fix implementation of 'reset' face values * src/xfaces.c (Finternal_merge_in_global_face) (gui_supports_face_attributes_p): Only modify local copy of face attributes when replacing 'reset' pseudo-values with real values. (Bug#38771) diff --git a/src/xfaces.c b/src/xfaces.c index 6142fe1ab1..8ae922578e 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -4190,12 +4190,6 @@ Default face attributes override any local face attributes. */) the previously-cached vector. */ memcpy (attrs, oldface->lface, sizeof attrs); - /* Make explicit any attributes whose value is 'reset'. */ - int i; - for (i = 1; i < LFACE_VECTOR_SIZE; i++) - if (EQ (lvec[i], Qreset)) - lvec[i] = attrs[i]; - merge_face_vectors (NULL, f, lvec, attrs, 0); vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE); newface = realize_face (c, lvec, DEFAULT_FACE_ID); @@ -5193,55 +5187,60 @@ gui_supports_face_attributes_p (struct frame *f, struct face *def_face) { Lisp_Object *def_attrs = def_face->lface; + Lisp_Object lattrs[LFACE_VECTOR_SIZE]; /* Make explicit any attributes whose value is 'reset'. */ int i; for (i = 1; i < LFACE_VECTOR_SIZE; i++) - if (EQ (attrs[i], Qreset)) - attrs[i] = def_attrs[i]; + { + if (EQ (attrs[i], Qreset)) + lattrs[i] = def_attrs[i]; + else + lattrs[i] = attrs[i]; + } /* Check that other specified attributes are different from the default face. */ - if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) - && face_attr_equal_p (attrs[LFACE_UNDERLINE_INDEX], + if ((!UNSPECIFIEDP (lattrs[LFACE_UNDERLINE_INDEX]) + && face_attr_equal_p (lattrs[LFACE_UNDERLINE_INDEX], def_attrs[LFACE_UNDERLINE_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX]) - && face_attr_equal_p (attrs[LFACE_INVERSE_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_INVERSE_INDEX]) + && face_attr_equal_p (lattrs[LFACE_INVERSE_INDEX], def_attrs[LFACE_INVERSE_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_EXTEND_INDEX]) - && face_attr_equal_p (attrs[LFACE_EXTEND_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_EXTEND_INDEX]) + && face_attr_equal_p (lattrs[LFACE_EXTEND_INDEX], def_attrs[LFACE_EXTEND_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX]) - && face_attr_equal_p (attrs[LFACE_FOREGROUND_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_FOREGROUND_INDEX]) + && face_attr_equal_p (lattrs[LFACE_FOREGROUND_INDEX], def_attrs[LFACE_FOREGROUND_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_DISTANT_FOREGROUND_INDEX]) - && face_attr_equal_p (attrs[LFACE_DISTANT_FOREGROUND_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_DISTANT_FOREGROUND_INDEX]) + && face_attr_equal_p (lattrs[LFACE_DISTANT_FOREGROUND_INDEX], def_attrs[LFACE_DISTANT_FOREGROUND_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX]) - && face_attr_equal_p (attrs[LFACE_BACKGROUND_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_BACKGROUND_INDEX]) + && face_attr_equal_p (lattrs[LFACE_BACKGROUND_INDEX], def_attrs[LFACE_BACKGROUND_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX]) - && face_attr_equal_p (attrs[LFACE_STIPPLE_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_STIPPLE_INDEX]) + && face_attr_equal_p (lattrs[LFACE_STIPPLE_INDEX], def_attrs[LFACE_STIPPLE_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) - && face_attr_equal_p (attrs[LFACE_OVERLINE_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_OVERLINE_INDEX]) + && face_attr_equal_p (lattrs[LFACE_OVERLINE_INDEX], def_attrs[LFACE_OVERLINE_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX]) - && face_attr_equal_p (attrs[LFACE_STRIKE_THROUGH_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_STRIKE_THROUGH_INDEX]) + && face_attr_equal_p (lattrs[LFACE_STRIKE_THROUGH_INDEX], def_attrs[LFACE_STRIKE_THROUGH_INDEX])) - || (!UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]) - && face_attr_equal_p (attrs[LFACE_BOX_INDEX], + || (!UNSPECIFIEDP (lattrs[LFACE_BOX_INDEX]) + && face_attr_equal_p (lattrs[LFACE_BOX_INDEX], def_attrs[LFACE_BOX_INDEX]))) return false; /* Check font-related attributes, as those are the most commonly "unsupported" on a window-system (because of missing fonts). */ - if (!UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX]) - || !UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX]) - || !UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX]) - || !UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX]) - || !UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX]) - || !UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX])) + if (!UNSPECIFIEDP (lattrs[LFACE_FAMILY_INDEX]) + || !UNSPECIFIEDP (lattrs[LFACE_FOUNDRY_INDEX]) + || !UNSPECIFIEDP (lattrs[LFACE_HEIGHT_INDEX]) + || !UNSPECIFIEDP (lattrs[LFACE_WEIGHT_INDEX]) + || !UNSPECIFIEDP (lattrs[LFACE_SLANT_INDEX]) + || !UNSPECIFIEDP (lattrs[LFACE_SWIDTH_INDEX])) { int face_id; struct face *face; commit 93cec6cf68e66f265e10ccc9c11027931616fd3f Author: Stefan Kangas Date: Sun Jul 3 14:34:44 2022 +0200 ; * etc/NEWS: Tag two items. diff --git a/etc/NEWS b/etc/NEWS index a16549dcce..3d679fdec6 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1053,6 +1053,7 @@ customize the user option 'dired-clean-up-buffers-too' to nil. The related user option 'dired-clean-confirm-killing-deleted-buffers' (which see) has also been moved to 'dired'. ++++ *** 'dired-info' and 'dired-man' moved from dired-x to dired. The 'dired-info' and 'dired-man' commands have been moved from the 'dired-x' package to 'dired'. They have also been renamed to @@ -1070,6 +1071,7 @@ the following to your Init file: (keymap-set dired-mode-map "N" nil) (keymap-set dired-mode-map "I" nil)) +--- *** New command 'dired-do-eww'. This command visits the file on the current line with EWW. commit 831b5f3f14c482f482c0dc0dc6a4d602f2a19338 Author: Stefan Kangas Date: Sun Jul 3 14:32:44 2022 +0200 Move dired-clean-up-buffers-too to dired.el * lisp/dired-x.el (dired-clean-up-buffers-too) (dired-clean-confirm-killing-deleted-buffers): Move from here... * lisp/dired.el (dired-clean-up-buffers-too) (dired-clean-confirm-killing-deleted-buffers): ...to here. (Bug#21981) (dired-clean-up-after-deletion): Adjust documentation. * etc/NEWS: Announce the change. diff --git a/etc/NEWS b/etc/NEWS index e1cdbd5077..a16549dcce 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1044,6 +1044,15 @@ so automatically. ** Dired +--- +*** 'dired-clean-up-buffers-too' moved from dired-x to dired. +This means that Dired now offers to kill buffers visiting files and +dirs when they are deleted in Dired. Before, you had to require +'dired-x' to enable this behavior. To disable this behavior, +customize the user option 'dired-clean-up-buffers-too' to nil. The +related user option 'dired-clean-confirm-killing-deleted-buffers' +(which see) has also been moved to 'dired'. + *** 'dired-info' and 'dired-man' moved from dired-x to dired. The 'dired-info' and 'dired-man' commands have been moved from the 'dired-x' package to 'dired'. They have also been renamed to diff --git a/lisp/dired-x.el b/lisp/dired-x.el index c8cf1fd612..db5a93b60c 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -230,17 +230,6 @@ to nil: a pipe using `zcat' or `gunzip -c' will be used." (string :tag "Switches")) :group 'dired-x) -(defcustom dired-clean-up-buffers-too t - "Non-nil means offer to kill buffers visiting files and dirs deleted in Dired." - :type 'boolean - :group 'dired-x) - -(defcustom dired-clean-confirm-killing-deleted-buffers t - "If nil, don't ask whether to kill buffers visiting deleted files." - :version "26.1" - :type 'boolean - :group 'dired-x) - ;;; Key bindings diff --git a/lisp/dired.el b/lisp/dired.el index 2572bb79c0..6b9bb35543 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -3692,13 +3692,21 @@ See `dired-delete-file' in case you wish that." (dired-remove-entry file) (dired-clean-up-after-deletion file)) -(defvar dired-clean-up-buffers-too) -(defvar dired-clean-confirm-killing-deleted-buffers) +(defcustom dired-clean-up-buffers-too t + "Non-nil means offer to kill buffers visiting files and dirs deleted in Dired." + :type 'boolean + :group 'dired) + +(defcustom dired-clean-confirm-killing-deleted-buffers t + "If nil, don't ask whether to kill buffers visiting deleted files." + :type 'boolean + :group 'dired + :version "26.1") (defun dired-clean-up-after-deletion (fn) "Clean up after a deleted file or directory FN. -Removes any expanded subdirectory of deleted directory. If -`dired-x' is loaded and `dired-clean-up-buffers-too' is non-nil, +Removes any expanded subdirectory of deleted directory. +If `dired-clean-up-buffers-too' is non-nil, kill any buffers visiting those files, prompting for confirmation. To disable the confirmation, see `dired-clean-confirm-killing-deleted-buffers'." commit 6e2f9dd3dd8b3c65608366039ce69666905d80cb Author: kobarity Date: Sun Jul 3 14:22:13 2022 +0200 Fix `python-nav-beginning-of-defun' line continuation using backslash * lisp/progmodes/python.el (python-nav--beginning-of-defun): Allow line continuation using backslash in defuns (bug#55702). (python-info-looking-at-beginning-of-defun): Add CHECK-STATEMENT argument. diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 16cdf58611..7a626ae35e 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1472,15 +1472,17 @@ With positive ARG search backwards, else search forwards." 0)))) (found (progn - (when (and (python-info-looking-at-beginning-of-defun) + (when (and (python-info-looking-at-beginning-of-defun nil t) (or (< arg 0) ;; If looking at beginning of defun, and if ;; pos is > line-content-start, ensure a ;; backward re search match this defun by ;; going to end of line before calling ;; re-search-fn bug#40563 - (and (> arg 0) (> pos line-content-start)))) - (end-of-line 1)) + (and (> arg 0) + (or (python-info-continuation-line-p) + (> pos line-content-start))))) + (python-nav-end-of-statement)) (while (and (funcall re-search-fn python-nav-beginning-of-defun-regexp nil t) @@ -1490,14 +1492,18 @@ With positive ARG search backwards, else search forwards." (and (> arg 0) (not (= (current-indentation) 0)) (>= (current-indentation) body-indentation))))) - (and (python-info-looking-at-beginning-of-defun) + (and (python-info-looking-at-beginning-of-defun nil t) (or (not (= (line-number-at-pos pos) (line-number-at-pos))) (and (>= (point) line-beg-pos) (<= (point) line-content-start) (> pos line-content-start))))))) (if found - (or (beginning-of-line 1) t) + (progn + (when (< arg 0) + (python-nav-beginning-of-statement)) + (beginning-of-line 1) + t) (and (goto-char pos) nil)))) (defun python-nav-beginning-of-defun (&optional arg) @@ -5299,10 +5305,15 @@ operator." (forward-line -1) (python-info-assignment-statement-p t)))) -(defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss) - "Check if point is at `beginning-of-defun' using SYNTAX-PPSS." +(defun python-info-looking-at-beginning-of-defun (&optional syntax-ppss + check-statement) + "Check if point is at `beginning-of-defun' using SYNTAX-PPSS. +When CHECK-STATEMENT is non-nil, the current statement is checked +instead of the current physical line." (and (not (python-syntax-context-type (or syntax-ppss (syntax-ppss)))) (save-excursion + (when check-statement + (python-nav-beginning-of-statement)) (beginning-of-line 1) (looking-at python-nav-beginning-of-defun-regexp)))) diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index c59a2e7953..d7b3c102f2 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -1757,6 +1757,36 @@ def foo(x): (should (= (marker-position (mark-marker)) expected-mark-end-position))))) +(ert-deftest python-mark-defun-5 () + "Test `python-mark-defun' with point inside backslash escaped defun." + (python-tests-with-temp-buffer + " +def \\ + foo(x): + return x +" + (let ((transient-mark-mode t) + (expected-mark-beginning-position + (progn + (python-tests-look-at "def ") + (1- (line-beginning-position)))) + (expected-mark-end-position + (save-excursion + (python-tests-look-at "return x") + (forward-line) + (point)))) + (python-tests-look-at "def ") + (python-mark-defun 1) + (should (= (point) expected-mark-beginning-position)) + (should (= (marker-position (mark-marker)) + expected-mark-end-position)) + (deactivate-mark) + (python-tests-look-at "foo(x)") + (python-mark-defun 1) + (should (= (point) expected-mark-beginning-position)) + (should (= (marker-position (mark-marker)) + expected-mark-end-position))))) + ;;; Navigation @@ -1905,17 +1935,47 @@ class C(object): (ert-deftest python-nav-beginning-of-defun-4 () (python-tests-with-temp-buffer " +def a(): + pass + def \\ - a(): + b(): return 0 + +def c(): + pass " - (python-tests-look-at "return 0") + (python-tests-look-at "def c():") + (should (= (save-excursion + (python-nav-beginning-of-defun) + (point)) + (save-excursion + (python-tests-look-at "def \\" -1) + (beginning-of-line) + (point)))) + (python-tests-look-at "return 0" -1) (should (= (save-excursion (python-nav-beginning-of-defun) (point)) (save-excursion (python-tests-look-at "def \\" -1) (beginning-of-line) + (point)))) + (python-tests-look-at "b():" -1) + (should (= (save-excursion + (python-nav-beginning-of-defun) + (point)) + (save-excursion + (python-tests-look-at "def \\" -1) + (beginning-of-line) + (point)))) + (python-tests-look-at "def a():" -1) + (should (= (save-excursion + (python-nav-beginning-of-defun -1) + (point)) + (save-excursion + (python-tests-look-at "def \\") + (beginning-of-line) (point)))))) (ert-deftest python-nav-end-of-defun-1 () @@ -5242,6 +5302,23 @@ def decorat0r(deff): (python-tests-look-at "deff()") (should (not (python-info-looking-at-beginning-of-defun))))) +(ert-deftest python-info-looking-at-beginning-of-defun-2 () + (python-tests-with-temp-buffer + " +def \\ + foo(arg): + pass +" + (python-tests-look-at "def \\") + (should (python-info-looking-at-beginning-of-defun)) + (should (python-info-looking-at-beginning-of-defun nil t)) + (python-tests-look-at "foo(arg):") + (should (not (python-info-looking-at-beginning-of-defun))) + (should (python-info-looking-at-beginning-of-defun nil t)) + (python-tests-look-at "pass") + (should (not (python-info-looking-at-beginning-of-defun))) + (should (not (python-info-looking-at-beginning-of-defun nil t))))) + (ert-deftest python-info-current-line-comment-p-1 () (python-tests-with-temp-buffer " commit c61c647f7272faf625b5584035d455e81d1ebd0e Author: Stefan Kangas Date: Sun Jul 3 14:20:34 2022 +0200 * lisp/dired-x.el (dired-omit-size-limit): Increase value. diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 21de913287..c8cf1fd612 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -82,11 +82,12 @@ files not writable by you are visited read-only." (other :tag "non-writable only" if-file-read-only)) :group 'dired-x) -(defcustom dired-omit-size-limit 30000 +(defcustom dired-omit-size-limit 100000 "Maximum size for the \"omitting\" feature. If nil, there is no maximum size." :type '(choice (const :tag "no maximum" nil) integer) - :group 'dired-x) + :group 'dired-x + :version "29.1") (defcustom dired-omit-case-fold 'filesystem "Determine whether \"omitting\" patterns are case-sensitive. commit b72e4b149329797b8f2c947953251f92615ee73e Author: Lars Ingebrigtsen Date: Sun Jul 3 14:05:01 2022 +0200 Make string-limit with encoding return complete glyphs * lisp/emacs-lisp/subr-x.el (string-limit): Return more correct results in the CODING-SYSTEM case for coding systems with BOM and charset designations (bug#48324). Also amend the algorithm to return complete glyphs, not just complete code points. diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 390e505f00..56e8c2aa86 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -167,9 +167,9 @@ non-nil, return the last LENGTH characters instead. If CODING-SYSTEM is non-nil, STRING will be encoded before limiting, and LENGTH is interpreted as the number of bytes to limit the string to. The result will be a unibyte string that is -shorter than LENGTH, but will not contain \"partial\" characters, -even if CODING-SYSTEM encodes characters with several bytes per -character. +shorter than LENGTH, but will not contain \"partial\" +characters (or glyphs), even if CODING-SYSTEM encodes characters +with several bytes per character. When shortening strings for display purposes, `truncate-string-to-width' is almost always a better alternative @@ -177,34 +177,55 @@ than this function." (unless (natnump length) (signal 'wrong-type-argument (list 'natnump length))) (if coding-system - (let ((result nil) - (result-length 0) - (index (if end (1- (length string)) 0))) - ;; FIXME: This implementation, which uses encode-coding-char - ;; to encode the string one character at a time, is in general - ;; incorrect: coding-systems that produce prefix or suffix - ;; bytes, such as ISO-2022-based or UTF-8/16 with BOM, will - ;; produce those bytes for each character, instead of just - ;; once for the entire string. encode-coding-char attempts to - ;; remove those extra bytes at least in some situations, but - ;; it cannot do that in all cases. And in any case, producing - ;; what is supposed to be a UTF-16 or ISO-2022-CN encoded - ;; string which lacks the BOM bytes at the beginning and the - ;; charset designation sequences at the head and tail of the - ;; result will definitely surprise the callers in some cases. - (while (let ((encoded (encode-coding-char - (aref string index) coding-system))) - (and (<= (+ (length encoded) result-length) length) - (progn - (push encoded result) - (cl-incf result-length (length encoded)) - (setq index (if end (1- index) - (1+ index)))) - (if end (> index -1) - (< index (length string))))) - ;; No body. - ) - (apply #'concat (if end result (nreverse result)))) + ;; The previous implementation here tried to encode char by + ;; char, and then adding up the length of the encoded octets, + ;; but that's not reliably in the presence of BOM marks and + ;; ISO-2022-CN which may add charset designations at the + ;; start/end of each encoded char (which we don't want). So + ;; iterate (with a binary search) instead to find the desired + ;; length. + (let* ((glyphs (string-glyph-split string)) + (nglyphs (length glyphs)) + (too-long (1+ nglyphs)) + (stop (max (/ nglyphs 2) 1)) + (gap stop) + candidate encoded found candidate-stop) + ;; We're returning the end of the string. + (when end + (setq glyphs (nreverse glyphs))) + (while (and (not found) + (< stop too-long)) + (setq encoded + (encode-coding-string (string-join (seq-take glyphs stop)) + coding-system)) + (cond + ((= (length encoded) length) + (setq found encoded + candidate-stop stop)) + ;; Too long; try shortening. + ((> (length encoded) length) + (setq too-long stop + stop (max (- stop gap) 1))) + ;; Too short; try lengthening. + (t + (setq candidate encoded + candidate-stop stop) + (setq stop + (if (>= stop nglyphs) + too-long + (min (+ stop gap) nglyphs))))) + (setq gap (max (/ gap 2) 1))) + (cond + ((not (or found candidate)) + "") + ;; We're returning the end, so redo the encoding. + (end + (encode-coding-string + (string-join (nreverse (seq-take glyphs candidate-stop))) + coding-system)) + (t + (or found candidate)))) + ;; Char-based version. (cond ((<= (length string) length) string) (end (substring string (- (length string) length))) diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el index 0bec9db36e..99c0e82215 100644 --- a/test/lisp/emacs-lisp/subr-x-tests.el +++ b/test/lisp/emacs-lisp/subr-x-tests.el @@ -607,21 +607,36 @@ (should (equal (string-limit "foó" 4 nil 'utf-8) "fo\303\263")) (should (equal (string-limit "foóa" 4 nil 'utf-8) "fo\303\263")) (should (equal (string-limit "foóá" 4 nil 'utf-8) "fo\303\263")) + (should (equal (string-limit "foóá" 2 nil 'utf-8-with-signature) + "")) (should (equal (string-limit "foóá" 4 nil 'utf-8-with-signature) - "fo\303\263")) + "\357\273\277f")) (should (equal (string-limit "foóa" 4 nil 'iso-8859-1) "fo\363a")) (should (equal (string-limit "foóá" 4 nil 'iso-8859-1) "fo\363\341")) - (should (equal (string-limit "foóá" 4 nil 'utf-16) "\000f\000o")) + (should (equal (string-limit "foóá" 3 nil 'utf-16) "")) + (should (equal (string-limit "foóá" 6 nil 'utf-16) "\376\377\000f\000o")) (should (equal (string-limit "foó" 10 t 'utf-8) "fo\303\263")) (should (equal (string-limit "foó" 3 t 'utf-8) "o\303\263")) (should (equal (string-limit "foó" 4 t 'utf-8) "fo\303\263")) (should (equal (string-limit "foóa" 4 t 'utf-8) "o\303\263a")) (should (equal (string-limit "foóá" 4 t 'utf-8) "\303\263\303\241")) - (should (equal (string-limit "foóá" 2 t 'utf-8-with-signature) "\303\241")) + (should (equal (string-limit "foóá" 2 t 'utf-8-with-signature) + "")) (should (equal (string-limit "foóa" 4 t 'iso-8859-1) "fo\363a")) (should (equal (string-limit "foóá" 4 t 'iso-8859-1) "fo\363\341")) - (should (equal (string-limit "foóá" 4 t 'utf-16) "\000\363\000\341"))) + (should (equal (string-limit "foóá" 6 t 'utf-16) "\376\377\000\363\000\341"))) + +(ert-deftest subr-string-limit-glyphs () + (should (equal (encode-coding-string "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 'utf-8) + "Hello, \360\237\221\274\360\237\217\273\360\237\247\221\360\237\217\274\342\200\215\360\237\244\235\342\200\215\360\237\247\221\360\237\217\273")) + (should (= (length (encode-coding-string "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 'utf-8)) 41)) + (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 100 nil 'utf-8) + "Hello, \360\237\221\274\360\237\217\273\360\237\247\221\360\237\217\274\342\200\215\360\237\244\235\342\200\215\360\237\247\221\360\237\217\273")) + (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 15 nil 'utf-8) + "Hello, \360\237\221\274\360\237\217\273")) + (should (equal (string-limit "Hello, 👼🏻🧑🏼‍🤝‍🧑🏻" 10 nil 'utf-8) + "Hello, "))) (ert-deftest subr-string-lines () (should (equal (string-lines "foo") '("foo"))) commit cfee07d4dd6317bc235046b99542fa76dc676dde Author: Po Lu Date: Sun Jul 3 19:48:55 2022 +0800 Improve performance when rejecting XI touch event * src/xterm.c (handle_one_xevent): Avoid sync handling simple error. diff --git a/src/xterm.c b/src/xterm.c index 819f7fd7e4..dc7e3283a5 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -21676,11 +21676,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (!menu_bar_p && !tool_bar_p) { - x_catch_errors (dpyinfo->display); - if (f && device->direct_p) { *finish = X_EVENT_DROP; + + x_catch_errors (dpyinfo->display); + if (x_input_grab_touch_events) XIAllowTouchEvents (dpyinfo->display, xev->deviceid, xev->detail, xev->event, XIAcceptTouch); @@ -21700,13 +21701,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (source) inev.ie.device = source->name; } + + x_uncatch_errors (); } #ifndef HAVE_GTK3 else if (x_input_grab_touch_events) - XIAllowTouchEvents (dpyinfo->display, xev->deviceid, - xev->detail, xev->event, XIRejectTouch); + { + x_ignore_errors_for_next_request (dpyinfo); + XIAllowTouchEvents (dpyinfo->display, xev->deviceid, + xev->detail, xev->event, XIRejectTouch); + x_stop_ignoring_errors (dpyinfo); + } #endif - x_uncatch_errors (); } else { commit 5a094d16e358de13d6a8caa26ec91fea85125cf8 Author: Lars Ingebrigtsen Date: Sun Jul 3 12:57:29 2022 +0200 Fix streaming problems in nnimap-retrieve-headers * lisp/gnus/nnimap.el (nnimap-retrieve-headers): Don't stream the UID FETCH commands, since the server may return the results out-of-order (bug#56332). diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index 22edc3c72c..c629cb85d9 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -241,22 +241,20 @@ during splitting, which may be slow." (when (nnimap-change-group group server) (with-current-buffer (nnimap-buffer) (erase-buffer) - (let ((ranges (gnus-compress-sequence articles t)) - sequence) - ;; If we have a lot of ranges, split them up to avoid - ;; generating too-long lines. (The limit is 8192 octects, - ;; and this should guarantee that it's (much) shorter than - ;; that.) - (while ranges - (setq sequence - (nnimap-send-command - "UID FETCH %s %s" - (nnimap-article-ranges - (seq-take ranges nnimap--max-retrieve-headers)) - (nnimap-header-parameters))) - (setq ranges (nthcdr nnimap--max-retrieve-headers ranges))) - ;; Wait for the final one. - (nnimap-wait-for-response sequence t)) + ;; If we have a lot of ranges, split them up to avoid + ;; generating too-long lines. (The limit is 8192 octects, + ;; and this should guarantee that it's (much) shorter than + ;; that.) We don't stream the requests, since the server + ;; may respond to the requests out-of-order: + ;; https://datatracker.ietf.org/doc/html/rfc3501#section-5.5 + (dolist (ranges (seq-split (gnus-compress-sequence articles t) + nnimap--max-retrieve-headers)) + (nnimap-wait-for-response + (nnimap-send-command + "UID FETCH %s %s" + (nnimap-article-ranges ranges) + (nnimap-header-parameters)) + t)) (unless (process-live-p (get-buffer-process (current-buffer))) (error "IMAP server %S closed connection" nnimap-address)) (nnimap-transform-headers) commit b31680ef040d4a232619e8d070794a43d2cdca2c Author: Lars Ingebrigtsen Date: Sun Jul 3 12:55:00 2022 +0200 Add new function `seq-split' * doc/lispref/sequences.texi (Sequence Functions): Document it. * lisp/emacs-lisp/seq.el (seq-split): New function. * lisp/emacs-lisp/shortdoc.el (sequence): Mention it. diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi index c3f4cff301..39230d0adc 100644 --- a/doc/lispref/sequences.texi +++ b/doc/lispref/sequences.texi @@ -577,6 +577,20 @@ starting from the first one for which @var{predicate} returns @code{nil}. @end example @end defun +@defun seq-split sequence length + This function returns a list consisting of sub-sequences of +@var{sequence} of (at most) length @var{length}. (The final element +may be shorter than @var{length} if the length of @var{sequence} isn't +a multiple of @var{length}. + +@example +@group +(seq-split [0 1 2 3 4] 2) +@result{} ([0 1] [2 3] [4]) +@end group +@end example +@end defun + @defun seq-do function sequence This function applies @var{function} to each element of @var{sequence} in turn (presumably for side effects), and returns diff --git a/etc/NEWS b/etc/NEWS index af3240e504..e1cdbd5077 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2250,6 +2250,10 @@ patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el. * Lisp Changes in Emacs 29.1 ++++ +** New function 'seq-split'. +This returns a list of sub-sequences of the specified sequence. + +++ ** 'plist-get', 'plist-put' and 'plist-member' are no longer limited to 'eq'. These function now take an optional comparison predicate argument. diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 947b64e868..36c17f4cd5 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -632,5 +632,20 @@ Signal an error if SEQUENCE is empty." ;; we automatically highlight macros. (add-hook 'emacs-lisp-mode-hook #'seq--activate-font-lock-keywords)) +(defun seq-split (sequence length) + "Split SEQUENCE into a list of sub-sequences of at most LENGTH. +All the sub-sequences will be of LENGTH, except the last one, +which may be shorter." + (when (< length 1) + (error "Sub-sequence length must be larger than zero")) + (let ((result nil) + (seq-length (length sequence)) + (start 0)) + (while (< start seq-length) + (push (seq-subseq sequence start + (setq start (min seq-length (+ start length)))) + result)) + (nreverse result))) + (provide 'seq) ;;; seq.el ends here diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index c82aa3365c..f53e783111 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -889,6 +889,8 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), :eval (seq-subseq '(a b c d e) 2 4)) (seq-take :eval (seq-take '(a b c d e) 3)) + (seq-split + :eval (seq-split [0 1 2 3 5] 2)) (seq-take-while :eval (seq-take-while #'cl-evenp [2 4 9 6 5])) (seq-uniq diff --git a/test/lisp/emacs-lisp/seq-tests.el b/test/lisp/emacs-lisp/seq-tests.el index 9e5d59163f..d979604910 100644 --- a/test/lisp/emacs-lisp/seq-tests.el +++ b/test/lisp/emacs-lisp/seq-tests.el @@ -511,5 +511,26 @@ Evaluate BODY for each created sequence. (should (equal (seq-difference '(1 nil) '(2 nil)) '(1))))) +(ert-deftest test-seq-split () + (let ((seq [0 1 2 3 4 5 6 7 8 9 10])) + (should (equal seq (car (seq-split seq 20)))) + (should (equal seq (car (seq-split seq 11)))) + (should (equal (seq-split seq 10) + '([0 1 2 3 4 5 6 7 8 9] [10]))) + (should (equal (seq-split seq 5) + '([0 1 2 3 4] [5 6 7 8 9] [10]))) + (should (equal (seq-split seq 1) + '([0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]))) + (should-error (seq-split seq 0)) + (should-error (seq-split seq -10))) + (let ((seq '(0 1 2 3 4 5 6 7 8 9))) + (should (equal (seq-split seq 5) + '((0 1 2 3 4) (5 6 7 8 9))))) + (let ((seq "0123456789")) + (should (equal (seq-split seq 2) + '("01" "23" "45" "67" "89"))) + (should (equal (seq-split seq 3) + '("012" "345" "678" "9"))))) + (provide 'seq-tests) ;;; seq-tests.el ends here commit a2f956a1d6fad6a2bc7c5d79eb3aa76cbb63cc40 Author: Allen Li Date: Sun Jul 3 12:31:15 2022 +0200 elec-pair: Fix bug incorrectly hiding syntax-propertize-function * lisp/elec-pair.el (electric-pair--with-text-syntax): New macro. (electric-pair-syntax-info): (electric-pair--balance-info): (electric-pair--syntax-ppss, electric-pair--balance-info): Use it. (electric-pair--with-uncached-syntax): Remove (bug#49629). The main bug that this is fixing is `syntax-propertize-function' being hidden in `electric-pair--balance-info' when the original syntax table is to be used, not `electric-pair-text-syntax-table'. Notably, this causes `electric-pair-mode' to often misbehave in HTML files when pairing angle brackets. This commit also flushes the cache before installing `electric-pair-text-syntax-table', to prevent cached syntax for the original table from affecting things. diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 720f608368..247e9b93ec 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el @@ -188,6 +188,25 @@ be considered.") ;; I also find it often preferable not to pair next to a word. (eq (char-syntax (following-char)) ?w))) +(cl-defmacro electric-pair--with-text-syntax ((&optional start) &rest body) + "Run BODY with `electric-pair-text-syntax-table' active. +This ensures that all syntax related values are set properly and the +`syntax-ppss' cache is cleared before and after. +In particular, this must be used when BODY contains code which may +update the `syntax-ppss' cache. This includes calling +`parse-partial-sexp' and any sexp-based movement functions when +`parse-sexp-lookup-properties' is non-nil. The cache is flushed from +position START, defaulting to point." + (declare (debug ((&optional form) body)) (indent 1)) + (let ((start-var (make-symbol "start"))) + `(let ((syntax-propertize-function nil) + (,start-var ,(or start '(point)))) + (syntax-ppss-flush-cache ,start-var) + (unwind-protect + (with-syntax-table electric-pair-text-syntax-table + ,@body) + (syntax-ppss-flush-cache ,start-var))))) + (defun electric-pair-syntax-info (command-event) "Calculate a list (SYNTAX PAIR UNCONDITIONAL STRING-OR-COMMENT-START). @@ -202,13 +221,14 @@ inside a comment or string." (post-string-or-comment (nth 8 (syntax-ppss (point)))) (string-or-comment (and post-string-or-comment pre-string-or-comment)) - (table (if string-or-comment - electric-pair-text-syntax-table - (syntax-table))) - (table-syntax-and-pair (with-syntax-table table - (list (char-syntax command-event) - (or (matching-paren command-event) - command-event)))) + (table-syntax-and-pair + (cl-flet ((f () + (list (char-syntax command-event) + (or (matching-paren command-event) + command-event)))) + (if string-or-comment + (electric-pair--with-text-syntax () (f)) + (f)))) (fallback (if string-or-comment (append electric-pair-text-pairs electric-pair-pairs) @@ -237,22 +257,6 @@ inside a comment or string." (electric-layout-allow-duplicate-newlines t)) (self-insert-command 1))) -(cl-defmacro electric-pair--with-uncached-syntax ((table &optional start) &rest body) - "Like `with-syntax-table', but flush the `syntax-ppss' cache afterwards. -Use this instead of (with-syntax-table TABLE BODY) when BODY -contains code which may update the `syntax-ppss' cache. This -includes calling `parse-partial-sexp' and any sexp-based movement -functions when `parse-sexp-lookup-properties' is non-nil. The -cache is flushed from position START, defaulting to point." - (declare (debug ((form &optional form) body)) (indent 1)) - (let ((start-var (make-symbol "start"))) - `(let ((syntax-propertize-function #'ignore) - (,start-var ,(or start '(point)))) - (unwind-protect - (with-syntax-table ,table - ,@body) - (syntax-ppss-flush-cache ,start-var))))) - (defun electric-pair--syntax-ppss (&optional pos where) "Like `syntax-ppss', but sometimes fallback to `parse-partial-sexp'. @@ -271,8 +275,7 @@ when to fallback to `parse-partial-sexp'." (skip-syntax-forward " >!") (point))))) (if s-or-c-start - (electric-pair--with-uncached-syntax (electric-pair-text-syntax-table - s-or-c-start) + (electric-pair--with-text-syntax (s-or-c-start) (parse-partial-sexp s-or-c-start pos)) ;; HACK! cc-mode apparently has some `syntax-ppss' bugs (if (memq major-mode '(c-mode c++ mode)) @@ -301,9 +304,6 @@ If the outermost list is matched, don't rely on its PAIR. If point is not enclosed by any lists, return ((t) . (t))." (let* (innermost outermost - (table (if string-or-comment - electric-pair-text-syntax-table - (syntax-table))) (at-top-level-or-equivalent-fn ;; called when `scan-sexps' ran perfectly, when it found ;; a parenthesis pointing in the direction of travel. @@ -325,11 +325,14 @@ If point is not enclosed by any lists, return ((t) . (t))." (cond ((< direction 0) (condition-case nil (eq (char-after pos) - (electric-pair--with-uncached-syntax - (table) - (matching-paren - (char-before - (scan-sexps (point) 1))))) + (cl-flet ((f () + (matching-paren + (char-before + (scan-sexps (point) 1))))) + (if string-or-comment + (electric-pair--with-text-syntax () + (f)) + (f)))) (scan-error nil))) (t ;; In this case, no need to use @@ -343,7 +346,9 @@ If point is not enclosed by any lists, return ((t) . (t))." (opener (char-after start))) (and start (eq (char-before pos) - (or (with-syntax-table table + (or (if string-or-comment + (electric-pair--with-text-syntax () + (matching-paren opener)) (matching-paren opener)) opener)))))))) (actual-pair (if (> direction 0) @@ -356,11 +361,14 @@ If point is not enclosed by any lists, return ((t) . (t))." (save-excursion (while (not outermost) (condition-case err - (electric-pair--with-uncached-syntax (table) - (scan-sexps (point) (if (> direction 0) - (point-max) - (- (point-max)))) - (funcall at-top-level-or-equivalent-fn)) + (cl-flet ((f () + (scan-sexps (point) (if (> direction 0) + (point-max) + (- (point-max)))) + (funcall at-top-level-or-equivalent-fn))) + (if string-or-comment + (electric-pair--with-text-syntax () (f)) + (f))) (scan-error (cond ((or ;; some error happened and it is not of the "ended commit f5a11369ea1480d0b99fd538c759b53c88fd6acc Author: Eli Zaretskii Date: Sun Jul 3 13:22:42 2022 +0300 ; * src/xfaces.c (Finternal_set_lisp_face_attribute): Fix last change. diff --git a/src/xfaces.c b/src/xfaces.c index 57c888ad9c..6142fe1ab1 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -3536,7 +3536,7 @@ FRAME 0 means change the face on all frames, and change the default #ifdef HAVE_WINDOW_SYSTEM if (EQ (frame, Qt) || FRAME_WINDOW_P (f)) { - Lisp_Object tmp; + Lisp_Object tmp = value; old_value = LFACE_FONTSET (lface); if (!RESET_P (value)) commit 2c4922d76b7231dd704d34870c6e75099343a48d Author: Po Lu Date: Sun Jul 3 17:51:55 2022 +0800 Improve efficiency of `x_frame_highlight' and `x_frame_unhighlight' * src/xterm.c (x_frame_highlight, x_frame_unhighlight): Don't sync catching errors. diff --git a/src/xterm.c b/src/xterm.c index 0aca949dbc..819f7fd7e4 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10633,6 +10633,10 @@ x_scroll_run (struct window *w, struct run *run) static void x_frame_highlight (struct frame *f) { + struct x_display_info *dpyinfo; + + dpyinfo = FRAME_DISPLAY_INFO (f); + /* We used to only do this if Vx_no_window_manager was non-nil, but the ICCCM (section 4.1.6) says that the window's border pixmap and border pixel are window attributes which are "private to the @@ -10642,10 +10646,10 @@ x_frame_highlight (struct frame *f) the window-manager in use, tho something more is at play since I've been using that same window-manager binary for ever. Let's not crash just because of this (bug#9310). */ - x_catch_errors (FRAME_X_DISPLAY (f)); + x_ignore_errors_for_next_request (dpyinfo); XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), f->output_data.x->border_pixel); - x_uncatch_errors (); + x_stop_ignoring_errors (dpyinfo); unblock_input (); gui_update_cursor (f, true); x_set_frame_alpha (f); @@ -10654,17 +10658,23 @@ x_frame_highlight (struct frame *f) static void x_frame_unhighlight (struct frame *f) { + struct x_display_info *dpyinfo; + + dpyinfo = FRAME_DISPLAY_INFO (f); + /* We used to only do this if Vx_no_window_manager was non-nil, but the ICCCM (section 4.1.6) says that the window's border pixmap and border pixel are window attributes which are "private to the client", so we can always change it to whatever we want. */ + block_input (); /* Same as above for XSetWindowBorder (bug#9310). */ - x_catch_errors (FRAME_X_DISPLAY (f)); + x_ignore_errors_for_next_request (dpyinfo); XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), f->output_data.x->border_tile); - x_uncatch_errors (); + x_stop_ignoring_errors (dpyinfo); unblock_input (); + gui_update_cursor (f, true); x_set_frame_alpha (f); } commit e7da53a1169ff1796d71fb80b3a51c82821c4bbe Author: Stefan Kangas Date: Sun Jul 3 11:44:04 2022 +0200 * lisp/dired.el (dired-do-eww): New command. diff --git a/etc/NEWS b/etc/NEWS index 7403750677..af3240e504 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1061,6 +1061,9 @@ the following to your Init file: (keymap-set dired-mode-map "N" nil) (keymap-set dired-mode-map "I" nil)) +*** New command 'dired-do-eww'. +This command visits the file on the current line with EWW. + ** Elisp *** New command 'elisp-eval-buffer' (bound to 'C-c C-e'). diff --git a/lisp/dired.el b/lisp/dired.el index 6fe0ba0be6..2572bb79c0 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -4827,6 +4827,11 @@ Interactively with prefix argument, read FILE-NAME." (interactive nil dired-mode) (info (dired-get-file-for-visit))) +(defun dired-do-eww () + "In Dired, visit file in EWW." + (interactive nil dired-mode) + (eww-open-file (dired-get-file-for-visit))) + (provide 'dired) (run-hooks 'dired-load-hook) ; for your customizations commit 60f77c58f1139e0196d859844d74cdfea5f264cf Author: Stefan Kangas Date: Sat Jul 2 22:17:06 2022 +0200 Improve dired-do-{info,man} error handling * lisp/dired.el (dired-do-man, dired-do-info): Use 'dired-get-file-for-visit' to get better error handling. Interactive mode tagging. diff --git a/lisp/dired.el b/lisp/dired.el index d7bf631688..6fe0ba0be6 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -4810,22 +4810,22 @@ Interactively with prefix argument, read FILE-NAME." (defvar manual-program) ; from man.el (defun dired-do-man () - "Run `man' on this file." - (interactive) + "In Dired, run `man' on this file." + (interactive nil dired-mode) (require 'man) ;; FIXME: Move `dired-guess-shell-command' to dired.el to remove the ;; need for requiring `dired-x'. (require 'dired-x) - (let* ((file (dired-get-filename)) + (let* ((file (dired-get-file-for-visit)) (manual-program (string-replace "*" "%s" (dired-guess-shell-command "Man command: " (list file))))) (Man-getpage-in-background file))) (defun dired-do-info () - "Run `info' on this file." - (interactive) - (info (dired-get-filename))) + "In Dired, run `info' on this file." + (interactive nil dired-mode) + (info (dired-get-file-for-visit))) (provide 'dired) commit 45badeceecab5e5975d2e1700fce819acd34a964 Author: Eli Zaretskii Date: Sun Jul 3 12:30:24 2022 +0300 Implement pseudo-value 'reset' of face attrributes * doc/lispref/display.texi (Face Attributes): * etc/NEWS: Document the new pseudo-value 'reset'. * src/xfaces.c (realize_named_face, lookup_derived_face) (gui_supports_face_attributes_p, lookup_named_face) (Finternal_merge_in_global_face, merge_named_face, merge_faces): Handle the 'reset' pseudo-value of a face's attribute. (syms_of_xfaces): New symbol 'reset'. (RESET_P): New macro. (check_lface_attrs, Finternal_set_lisp_face_attribute): Allow 'reset' as a value of any attribute except ':inherit'. (Bug#38771) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 81799a2a57..08bf7441df 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -2474,6 +2474,7 @@ Otherwise, it returns @code{nil}. The following table lists all the face attributes, their possible values, and their effects. +@cindex unspecified, face attribute value Apart from the values given below, each face attribute can have the value @code{unspecified}. This special value means that the face doesn't specify that attribute directly. An @code{unspecified} @@ -2482,7 +2483,13 @@ description @code{:inherit} attribute below); or, failing that, to an underlying face (@pxref{Displaying Faces}). (However, @code{unspecified} is not a valid value in @code{defface}.) - The @code{default} face must specify all attributes. +@cindex reset, face attribute value + A face attribute can also have the value @code{reset}. This special +value stands for the value of the corresponding attribute of the +@code{default} face. + + The @code{default} face must explicitly specify all attributes, and +cannot use the special value @code{reset}. Some of these attributes are meaningful only on certain kinds of displays. If your display cannot handle a certain attribute, the diff --git a/etc/NEWS b/etc/NEWS index 47ca9c4b6e..7403750677 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -515,6 +515,12 @@ mixed. This inherits from the 'mode-line' face, but is the face actually used on the mode lines (along with 'mode-line-inactive'). ++++ +** New face attribute pseudo-value 'reset'. +This value stands for the value of the corresponding attribute of the +'default' face. It can be used to reset attribute values produced by +inheriting from other faces. + +++ ** New function 'buffer-text-pixel-size'. This is similar to 'window-text-pixel-size', but can be used when the diff --git a/src/xfaces.c b/src/xfaces.c index f70fe87c95..57c888ad9c 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -295,6 +295,10 @@ along with GNU Emacs. If not, see . */ #define IGNORE_DEFFACE_P(ATTR) EQ ((ATTR), QCignore_defface) +/* True if face attribute ATTR is `reset'. */ + +#define RESET_P(ATTR) EQ ((ATTR), Qreset) + /* Size of hash table of realized faces in face caches (should be a prime number). */ @@ -1757,57 +1761,72 @@ check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE]) { eassert (UNSPECIFIEDP (attrs[LFACE_FAMILY_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_FAMILY_INDEX]) + || RESET_P (attrs[LFACE_FAMILY_INDEX]) || STRINGP (attrs[LFACE_FAMILY_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_FOUNDRY_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_FOUNDRY_INDEX]) + || RESET_P (attrs[LFACE_FOUNDRY_INDEX]) || STRINGP (attrs[LFACE_FOUNDRY_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_SWIDTH_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_SWIDTH_INDEX]) + || RESET_P (attrs[LFACE_SWIDTH_INDEX]) || SYMBOLP (attrs[LFACE_SWIDTH_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_HEIGHT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_HEIGHT_INDEX]) + || RESET_P (attrs[LFACE_HEIGHT_INDEX]) || NUMBERP (attrs[LFACE_HEIGHT_INDEX]) || FUNCTIONP (attrs[LFACE_HEIGHT_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_WEIGHT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_WEIGHT_INDEX]) + || RESET_P (attrs[LFACE_WEIGHT_INDEX]) || SYMBOLP (attrs[LFACE_WEIGHT_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_SLANT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_SLANT_INDEX]) + || RESET_P (attrs[LFACE_SLANT_INDEX]) || SYMBOLP (attrs[LFACE_SLANT_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX]) + || RESET_P (attrs[LFACE_UNDERLINE_INDEX]) || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX]) || STRINGP (attrs[LFACE_UNDERLINE_INDEX]) || CONSP (attrs[LFACE_UNDERLINE_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_EXTEND_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_EXTEND_INDEX]) + || RESET_P (attrs[LFACE_EXTEND_INDEX]) || SYMBOLP (attrs[LFACE_EXTEND_INDEX]) || STRINGP (attrs[LFACE_EXTEND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX]) + || RESET_P (attrs[LFACE_OVERLINE_INDEX]) || SYMBOLP (attrs[LFACE_OVERLINE_INDEX]) || STRINGP (attrs[LFACE_OVERLINE_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_STRIKE_THROUGH_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_STRIKE_THROUGH_INDEX]) + || RESET_P (attrs[LFACE_STRIKE_THROUGH_INDEX]) || SYMBOLP (attrs[LFACE_STRIKE_THROUGH_INDEX]) || STRINGP (attrs[LFACE_STRIKE_THROUGH_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_BOX_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_BOX_INDEX]) + || RESET_P (attrs[LFACE_BOX_INDEX]) || SYMBOLP (attrs[LFACE_BOX_INDEX]) || STRINGP (attrs[LFACE_BOX_INDEX]) || FIXNUMP (attrs[LFACE_BOX_INDEX]) || CONSP (attrs[LFACE_BOX_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_INVERSE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_INVERSE_INDEX]) + || RESET_P (attrs[LFACE_INVERSE_INDEX]) || SYMBOLP (attrs[LFACE_INVERSE_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_FOREGROUND_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_FOREGROUND_INDEX]) + || RESET_P (attrs[LFACE_FOREGROUND_INDEX]) || STRINGP (attrs[LFACE_FOREGROUND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_DISTANT_FOREGROUND_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_DISTANT_FOREGROUND_INDEX]) + || RESET_P (attrs[LFACE_DISTANT_FOREGROUND_INDEX]) || STRINGP (attrs[LFACE_DISTANT_FOREGROUND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_BACKGROUND_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_BACKGROUND_INDEX]) + || RESET_P (attrs[LFACE_BACKGROUND_INDEX]) || STRINGP (attrs[LFACE_BACKGROUND_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_INHERIT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_INHERIT_INDEX]) @@ -1817,13 +1836,16 @@ check_lface_attrs (Lisp_Object attrs[LFACE_VECTOR_SIZE]) #ifdef HAVE_WINDOW_SYSTEM eassert (UNSPECIFIEDP (attrs[LFACE_STIPPLE_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_STIPPLE_INDEX]) + || RESET_P (attrs[LFACE_STIPPLE_INDEX]) || SYMBOLP (attrs[LFACE_STIPPLE_INDEX]) || !NILP (Fbitmap_spec_p (attrs[LFACE_STIPPLE_INDEX]))); eassert (UNSPECIFIEDP (attrs[LFACE_FONT_INDEX]) || IGNORE_DEFFACE_P (attrs[LFACE_FONT_INDEX]) + || RESET_P (attrs[LFACE_FONT_INDEX]) || FONTP (attrs[LFACE_FONT_INDEX])); eassert (UNSPECIFIEDP (attrs[LFACE_FONTSET_INDEX]) || STRINGP (attrs[LFACE_FONTSET_INDEX]) + || RESET_P (attrs[LFACE_FONTSET_INDEX]) || NILP (attrs[LFACE_FONTSET_INDEX])); #endif } @@ -2083,7 +2105,7 @@ lface_fully_specified_p (Lisp_Object attrs[LFACE_VECTOR_SIZE]) #ifdef HAVE_WINDOW_SYSTEM /* Set font-related attributes of Lisp face LFACE from FONT-OBJECT. - If FORCE_P, set only unspecified attributes of LFACE. The + If FORCE_P is zero, set only unspecified attributes of LFACE. The exception is `font' attribute. It is set to FONT_OBJECT regardless of FORCE_P. */ @@ -2339,6 +2361,14 @@ merge_named_face (struct window *w, Lisp_Object from[LFACE_VECTOR_SIZE], val; bool ok = get_lface_attributes (w, f, face_name, from, false, named_merge_points); + if (ok && !EQ (face_name, Qdefault)) + { + struct face *deflt = FACE_FROM_ID (f, DEFAULT_FACE_ID); + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (from[i], Qreset)) + from[i] = deflt->lface[i]; + } if (ok && (attr_filter == 0 /* No filter. */ || (!NILP (from[attr_filter]) /* Filter, but specified. */ @@ -3087,7 +3117,9 @@ FRAME 0 means change the face on all frames, and change the default if (EQ (attr, QCfamily)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_STRING (value); if (SCHARS (value) == 0) @@ -3099,7 +3131,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCfoundry)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_STRING (value); if (SCHARS (value) == 0) @@ -3111,7 +3145,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCheight)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { if (EQ (face, Qdefault)) { @@ -3139,7 +3175,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCweight)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (FONT_WEIGHT_NAME_NUMERIC (value) < 0) @@ -3151,7 +3189,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCslant)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (FONT_SLANT_NAME_NUMERIC (value) < 0) @@ -3165,7 +3205,7 @@ FRAME 0 means change the face on all frames, and change the default { bool valid_p = false; - if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value)) + if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value) || RESET_P (value)) valid_p = true; else if (NILP (value) || EQ (value, Qt)) valid_p = true; @@ -3223,7 +3263,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCoverline)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) if ((SYMBOLP (value) && !EQ (value, Qt) && !NILP (value)) @@ -3237,7 +3279,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCstrike_through)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) if ((SYMBOLP (value) && !EQ (value, Qt) && !NILP (value)) @@ -3258,7 +3302,7 @@ FRAME 0 means change the face on all frames, and change the default if (EQ (value, Qt)) value = make_fixnum (1); - if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value)) + if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value) || RESET_P (value)) valid_p = true; else if (NILP (value)) valid_p = true; @@ -3320,7 +3364,9 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCinverse_video) || EQ (attr, QCreverse_video)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (!EQ (value, Qt) && !NILP (value)) @@ -3331,7 +3377,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCextend)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (!EQ (value, Qt) && !NILP (value)) @@ -3345,7 +3393,9 @@ FRAME 0 means change the face on all frames, and change the default /* Compatibility with 20.x. */ if (NILP (value)) value = Qunspecified; - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { /* Don't check for valid color names here because it depends on the frame (display) whether the color will be valid @@ -3362,7 +3412,9 @@ FRAME 0 means change the face on all frames, and change the default /* Compatibility with 20.x. */ if (NILP (value)) value = Qunspecified; - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { /* Don't check for valid color names here because it depends on the frame (display) whether the color will be valid @@ -3379,7 +3431,9 @@ FRAME 0 means change the face on all frames, and change the default /* Compatibility with 20.x. */ if (NILP (value)) value = Qunspecified; - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { /* Don't check for valid color names here because it depends on the frame (display) whether the color will be valid @@ -3394,7 +3448,9 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCstipple)) { #if defined (HAVE_WINDOW_SYSTEM) - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value) && !NILP (value) && NILP (Fbitmap_spec_p (value))) signal_error ("Invalid stipple attribute", value); @@ -3404,7 +3460,9 @@ FRAME 0 means change the face on all frames, and change the default } else if (EQ (attr, QCwidth)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { CHECK_SYMBOL (value); if (FONT_WIDTH_NAME_NUMERIC (value) < 0) @@ -3419,7 +3477,9 @@ FRAME 0 means change the face on all frames, and change the default #ifdef HAVE_WINDOW_SYSTEM if (EQ (frame, Qt) || FRAME_WINDOW_P (f)) { - if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)) + if (!UNSPECIFIEDP (value) + && !IGNORE_DEFFACE_P (value) + && !RESET_P (value)) { struct frame *f1; @@ -3479,9 +3539,12 @@ FRAME 0 means change the face on all frames, and change the default Lisp_Object tmp; old_value = LFACE_FONTSET (lface); - tmp = Fquery_fontset (value, Qnil); - if (NILP (tmp)) - signal_error ("Invalid fontset name", value); + if (!RESET_P (value)) + { + tmp = Fquery_fontset (value, Qnil); + if (NILP (tmp)) + signal_error ("Invalid fontset name", value); + } ASET (lface, LFACE_FONTSET_INDEX, value = tmp); } #endif /* HAVE_WINDOW_SYSTEM */ @@ -3503,14 +3566,20 @@ FRAME 0 means change the face on all frames, and change the default else if (EQ (attr, QCbold)) { old_value = LFACE_WEIGHT (lface); - ASET (lface, LFACE_WEIGHT_INDEX, NILP (value) ? Qnormal : Qbold); + if (RESET_P (value)) + ASET (lface, LFACE_WEIGHT_INDEX, value); + else + ASET (lface, LFACE_WEIGHT_INDEX, NILP (value) ? Qnormal : Qbold); prop_index = FONT_WEIGHT_INDEX; } else if (EQ (attr, QCitalic)) { attr = QCslant; old_value = LFACE_SLANT (lface); - ASET (lface, LFACE_SLANT_INDEX, NILP (value) ? Qnormal : Qitalic); + if (RESET_P (value)) + ASET (lface, LFACE_SLANT_INDEX, value); + else + ASET (lface, LFACE_SLANT_INDEX, NILP (value) ? Qnormal : Qitalic); prop_index = FONT_SLANT_INDEX; } else @@ -4120,6 +4189,13 @@ Default face attributes override any local face attributes. */) /* Ensure that the face vector is fully specified by merging the previously-cached vector. */ memcpy (attrs, oldface->lface, sizeof attrs); + + /* Make explicit any attributes whose value is 'reset'. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (lvec[i], Qreset)) + lvec[i] = attrs[i]; + merge_face_vectors (NULL, f, lvec, attrs, 0); vcopy (local_lface, 0, attrs, LFACE_VECTOR_SIZE); newface = realize_face (c, lvec, DEFAULT_FACE_ID); @@ -4886,6 +4962,13 @@ lookup_named_face (struct window *w, struct frame *f, return -1; memcpy (attrs, default_face->lface, sizeof attrs); + + /* Make explicit any attributes whose value is 'reset'. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (symbol_attrs[i], Qreset)) + symbol_attrs[i] = attrs[i]; + merge_face_vectors (w, f, symbol_attrs, attrs, 0); return lookup_face (f, attrs); @@ -5056,6 +5139,13 @@ lookup_derived_face (struct window *w, default_face = FACE_FROM_ID (f, face_id); memcpy (attrs, default_face->lface, sizeof attrs); + + /* Make explicit any attributes whose value is 'reset'. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (symbol_attrs[i], Qreset)) + symbol_attrs[i] = attrs[i]; + merge_face_vectors (w, f, symbol_attrs, attrs, 0); return lookup_face (f, attrs); } @@ -5104,6 +5194,12 @@ gui_supports_face_attributes_p (struct frame *f, { Lisp_Object *def_attrs = def_face->lface; + /* Make explicit any attributes whose value is 'reset'. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (attrs[i], Qreset)) + attrs[i] = def_attrs[i]; + /* Check that other specified attributes are different from the default face. */ if ((!UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX]) @@ -5811,8 +5907,16 @@ realize_named_face (struct frame *f, Lisp_Object symbol, int id) lface = Finternal_make_lisp_face (symbol, frame); } - /* Merge SYMBOL's face with the default face. */ + get_lface_attributes_no_remap (f, symbol, symbol_attrs, true); + + /* Handle the 'reset' pseudo-value of any attribute by replacing it + with the corresponding value of the default face. */ + int i; + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (symbol_attrs[i], Qreset)) + symbol_attrs[i] = attrs[i]; + /* Merge SYMBOL's face with the default face. */ merge_face_vectors (NULL, f, symbol_attrs, attrs, 0); /* Realize the face. */ @@ -6750,7 +6854,21 @@ merge_faces (struct window *w, Lisp_Object face_name, int face_id, if (!face) return base_face_id; - merge_face_vectors (w, f, face->lface, attrs, 0); + if (face_id != DEFAULT_FACE_ID) + { + struct face *deflt = FACE_FROM_ID (f, DEFAULT_FACE_ID); + Lisp_Object lface_attrs[LFACE_VECTOR_SIZE]; + int i; + + memcpy (lface_attrs, face->lface, LFACE_VECTOR_SIZE); + /* Make explicit any attributes whose value is 'reset'. */ + for (i = 1; i < LFACE_VECTOR_SIZE; i++) + if (EQ (lface_attrs[i], Qreset)) + lface_attrs[i] = deflt->lface[i]; + merge_face_vectors (w, f, lface_attrs, attrs, 0); + } + else + merge_face_vectors (w, f, face->lface, attrs, 0); } /* Look up a realized face with the given face attributes, @@ -7019,6 +7137,7 @@ syms_of_xfaces (void) DEFSYM (Qblack, "black"); DEFSYM (Qoblique, "oblique"); DEFSYM (Qitalic, "italic"); + DEFSYM (Qreset, "reset"); /* The symbols `foreground-color' and `background-color' which can be used as part of a `face' property. This is for compatibility with commit 94d43f4942feff16a85786bcee67f551ccbbbe40 Author: James Thomas Date: Sat Jul 2 14:53:54 2022 +0530 * lisp/leim/quail/indian.el ("malayalam-mozhi"): Set DETERMINISTIC. diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el index 8fffcc3511..04e95b0737 100644 --- a/lisp/leim/quail/indian.el +++ b/lisp/leim/quail/indian.el @@ -681,7 +681,7 @@ Full key sequences are listed below:") (quail-define-package "malayalam-mozhi" "Malayalam" "MlmMI" t "Malayalam transliteration by Mozhi method." nil nil t nil nil nil t nil - #'indian-mlm-mozhi-update-translation) + #'indian-mlm-mozhi-update-translation nil t) (maphash (lambda (key val) commit fcdaaf241ea1511d3ff3879b8ed1ae0a62887861 Author: Po Lu Date: Sun Jul 3 14:33:02 2022 +0800 Fix deadlocks with very old versions of libXi * src/xfns.c (setup_xi_event_mask, Fx_create_frame): Set `xi_mask' ourselves if the version of libXi is too old to have working XIGetSelectedEvents. * src/xterm.c (x_destroy_window): Free `xi_mask' with xfree in that case. diff --git a/src/xfns.c b/src/xfns.c index ea2b1c0b3d..331f22763e 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3712,6 +3712,16 @@ setup_xi_event_mask (struct frame *f) XIEventMask mask; ptrdiff_t l = XIMaskLen (XI_LASTEVENT); unsigned char *m; +#ifndef HAVE_XINPUT2_1 + /* Set up fallback values, since XIGetSelectedEvents doesn't work + with this version of libXi. */ + XIEventMask *selected; + + selected = xzalloc (sizeof *selected + l); + selected->mask = ((unsigned char *) selected) + sizeof *selected; + selected->mask_len = l; + selected->deviceid = XIAllMasterDevices; +#endif mask.mask = m = alloca (l); memset (m, 0, l); @@ -3736,6 +3746,12 @@ setup_xi_event_mask (struct frame *f) FRAME_X_WINDOW (f), &mask, 1); + /* Fortunately `xi_masks' isn't used on GTK 3, where we really have + to get the event mask from the X server. */ +#ifndef HAVE_XINPUT2_1 + memcpy (selected->mask, m, l); +#endif + memset (m, 0, l); #endif /* !HAVE_GTK3 */ @@ -3775,6 +3791,12 @@ setup_xi_event_mask (struct frame *f) XISelectEvents (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &mask, 1); + +#ifndef HAVE_XINPUT2_1 + FRAME_X_OUTPUT (f)->xi_masks = selected; + FRAME_X_OUTPUT (f)->num_xi_masks = 1; +#endif + unblock_input (); } #endif @@ -4935,7 +4957,10 @@ This function is an internal primitive--use `make-frame' instead. */) x_icon (f, parms); x_make_gc (f); -#ifdef HAVE_XINPUT2 + /* While this function is present in versions of libXi that only + support 2.0, it does not release the display lock after + finishing, leading to a deadlock. */ +#if defined HAVE_XINPUT2 && defined HAVE_XINPUT2_1 if (dpyinfo->supports_xi2) FRAME_X_OUTPUT (f)->xi_masks = XIGetSelectedEvents (dpyinfo->display, FRAME_X_WINDOW (f), diff --git a/src/xterm.c b/src/xterm.c index 4353b173ca..0aca949dbc 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -25728,8 +25728,15 @@ x_destroy_window (struct frame *f) #endif #ifdef HAVE_XINPUT2 +#ifdef HAVE_XINPUT2_1 if (f->output_data.x->xi_masks) XFree (f->output_data.x->xi_masks); +#else + /* This is allocated by us under very old versions of libXi; see + `setup_xi_event_mask'. */ + if (f->output_data.x->xi_masks) + xfree (f->output_data.x->xi_masks); +#endif #endif xfree (f->output_data.x); commit 41472f3b6c028db18228fb569457ab1c1313f36b Author: Eli Zaretskii Date: Sun Jul 3 08:40:54 2022 +0300 Document 'jit-lock-debug-mode' * doc/lispref/modes.texi (Other Font Lock Variables): Document 'jit-lock-debug-mode'. diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index bc078d60e1..cb748606ed 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -3321,7 +3321,8 @@ fontification functions, and gives it two arguments, @var{start} and @var{end}, which specify the region to be fontified or refontified. If @var{function} performs fontifications, it can return a list of the form @w{@code{(jit-lock-bounds @var{beg} . @var{end})}}, to indicate -the bounds of the region it actually fontified; JIT font-lock will use +the bounds of the region it actually fontified; Just-In-Time (a.k.a.@: +@acronym{``JIT''}) font-lock will use this information to optimize subsequent redisplay cycles and regions of buffer text it will pass to future calls to @var{function}. @@ -3341,6 +3342,19 @@ If @var{function} was previously registered as a fontification function using @code{jit-lock-register}, this function unregisters it. @end defun +@cindex debugging font-lock +@cindex jit-lock functions, debugging +@deffn Command jit-lock-debug-mode &optional arg +This is a minor mode whose purpose is to help in debugging code that +is run by JIT font-lock. When this mode is enabled, most of the code +that JIT font-lock normally runs during redisplay cycles, where Lisp +errors are suppressed, is instead run by a timer. Thus, this mode +allows using debugging aids such as @code{debug-on-error} +(@pxref{Error Debugging}) and Edebug (@pxref{Edebug}) for finding and +fixing problems in font-lock code and any other code run by JIT +font-lock. +@end deffn + @node Levels of Font Lock @subsection Levels of Font Lock commit 04e4a902d3c6f0c73e9f7604c779cd8405c29bf0 Merge: 740d7e54e1 d927181b1a Author: Stefan Kangas Date: Sun Jul 3 06:30:39 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: d927181b1a * lisp/progmodes/cc-mode.el (c-common-init): Bind case-fol... commit 740d7e54e14633a0c3628b1ab339e7fb967d7c06 Merge: 4ef1e4daf5 dc3d01a5af Author: Stefan Kangas Date: Sun Jul 3 06:30:38 2022 +0200 Merge from origin/emacs-28 dc3d01a5af CC Mode: Fix a c-backward-token-2 call wrongly jumping bac... e390396e68 Doc fixes; don't use obsolete names c85f7c2e8a Don't refer to obsolete alias for insert-char 60ad45c5d2 Don't use obsolete face name in manoj-dark-theme commit 4ef1e4daf5e3569fed748f4487058d68a4c20ae6 Author: Po Lu Date: Sun Jul 3 09:41:32 2022 +0800 Speed up receiving drops over slow connections * lisp/x-dnd.el (x-dnd-debug-errors): New variable. (x-dnd-handle-drag-n-drop-event): Bind `x-fast-protocol-requests' to t if that is off. * src/xfns.c (Fx_change_window_property): (Fx_delete_window_property): * src/xselect.c (Fx_send_client_message, x_send_client_event): Don't sync to check for errors if fast protocol requests are enabled. * src/xterm.c (x_catch_errors_for_lisp, x_check_errors_for_lisp) (x_uncatch_errors_for_lisp): New functions. (syms_of_xterm): New variable `x-fast-protocol-requests'. * src/xterm.h: Update prototypes. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 8bea333012..f9e6b3198e 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -151,6 +151,12 @@ data types in this list." ;; Internal variables +(defvar x-dnd-debug-errors nil + "Whether or not to signal protocol errors during drag-and-drop. +This is useful for debugging errors in the DND code, but makes +drag-and-drop much slower over network connections with high +latency.") + (defvar x-dnd-current-state nil "The current state for a drop. This is an alist with one entry for each display. The value for each display @@ -425,11 +431,14 @@ nil if not." (select-frame frame) (funcall handler window action data)))))) +(defvar x-fast-protocol-requests) + (defun x-dnd-handle-drag-n-drop-event (event) "Receive drag and drop events (X client messages). Currently XDND, Motif and old KDE 1.x protocols are recognized." (interactive "e") (let* ((client-message (car (cdr (cdr event)))) + (x-fast-protocol-requests (not x-dnd-debug-errors)) (window (posn-window (event-start event)))) (if (eq (and (consp client-message) (car client-message)) diff --git a/src/xfns.c b/src/xfns.c index adb4fb58bc..ea2b1c0b3d 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -7339,18 +7339,23 @@ If VALUE is a string and FORMAT is 32, then the format of VALUE is system-specific. VALUE must contain unsigned integer data in native endian-ness in multiples of the size of the C type 'long': the low 32 bits of each such number are used as the value of each element of the -property. */) +property. + +Wait for the request to complete and signal any error, unless +`x-fast-protocol-requests' is non-nil, in which case errors will be +silently ignored. */) (Lisp_Object prop, Lisp_Object value, Lisp_Object frame, Lisp_Object type, Lisp_Object format, Lisp_Object outer_p, Lisp_Object window_id) { - struct frame *f = decode_window_system_frame (frame); + struct frame *f; Atom prop_atom; Atom target_type = XA_STRING; int element_format = 8; unsigned char *data; int nelements; Window target_window; + struct x_display_info *dpyinfo; #ifdef USE_XCB bool intern_prop; bool intern_target; @@ -7361,6 +7366,9 @@ property. */) bool rc; #endif + f = decode_window_system_frame (frame); + dpyinfo = FRAME_DISPLAY_INFO (f); + CHECK_STRING (prop); if (! NILP (format)) @@ -7412,7 +7420,7 @@ property. */) { CONS_TO_INTEGER (window_id, Window, target_window); if (! target_window) - target_window = FRAME_DISPLAY_INFO (f)->root_window; + target_window = dpyinfo->root_window; } else { @@ -7424,47 +7432,47 @@ property. */) block_input (); #ifndef USE_XCB - prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), - SSDATA (prop), false); + prop_atom = x_intern_cached_atom (dpyinfo, SSDATA (prop), + false); if (! NILP (type)) { CHECK_STRING (type); - target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), - SSDATA (type), false); + target_type = x_intern_cached_atom (dpyinfo, SSDATA (type), + false); } #else rc = true; intern_target = true; intern_prop = true; - prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), - SSDATA (prop), true); + prop_atom = x_intern_cached_atom (dpyinfo, SSDATA (prop), + true); if (prop_atom != None) intern_prop = false; else prop_atom_cookie - = xcb_intern_atom (FRAME_DISPLAY_INFO (f)->xcb_connection, + = xcb_intern_atom (dpyinfo->xcb_connection, 0, SBYTES (prop), SSDATA (prop)); if (!NILP (type)) { CHECK_STRING (type); - target_type = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), - SSDATA (type), true); + target_type = x_intern_cached_atom (dpyinfo, SSDATA (type), + true); if (target_type) intern_target = false; else target_type_cookie - = xcb_intern_atom (FRAME_DISPLAY_INFO (f)->xcb_connection, + = xcb_intern_atom (dpyinfo->xcb_connection, 0, SBYTES (type), SSDATA (type)); } if (intern_prop) { - reply = xcb_intern_atom_reply (FRAME_DISPLAY_INFO (f)->xcb_connection, + reply = xcb_intern_atom_reply (dpyinfo->xcb_connection, prop_atom_cookie, &generic_error); if (reply) @@ -7481,7 +7489,7 @@ property. */) if (!NILP (type) && intern_target) { - reply = xcb_intern_atom_reply (FRAME_DISPLAY_INFO (f)->xcb_connection, + reply = xcb_intern_atom_reply (dpyinfo->xcb_connection, target_type_cookie, &generic_error); if (reply) @@ -7500,15 +7508,18 @@ property. */) error ("Failed to intern type or property atom"); #endif - x_catch_errors (FRAME_X_DISPLAY (f)); - XChangeProperty (FRAME_X_DISPLAY (f), target_window, - prop_atom, target_type, element_format, PropModeReplace, - data, nelements); + x_catch_errors_for_lisp (dpyinfo); - if (CONSP (value)) xfree (data); - x_check_errors (FRAME_X_DISPLAY (f), - "Couldn't change window property: %s"); - x_uncatch_errors_after_check (); + XChangeProperty (dpyinfo->display, target_window, + prop_atom, target_type, element_format, + PropModeReplace, data, nelements); + + if (CONSP (value)) + xfree (data); + + x_check_errors_for_lisp (dpyinfo, + "Couldn't change window property: %s"); + x_uncatch_errors_for_lisp (dpyinfo); unblock_input (); return value; @@ -7525,7 +7536,11 @@ If WINDOW-ID is non-nil, remove property from that window instead across X displays or screens on the same display, so FRAME provides context for the window ID. -Value is PROP. */) +Value is PROP. + +Wait for the request to complete and signal any error, unless +`x-fast-protocol-requests' is non-nil, in which case errors will be +silently ignored. */) (Lisp_Object prop, Lisp_Object frame, Lisp_Object window_id) { struct frame *f = decode_window_system_frame (frame); @@ -7545,11 +7560,11 @@ Value is PROP. */) prop_atom = x_intern_cached_atom (FRAME_DISPLAY_INFO (f), SSDATA (prop), false); - x_catch_errors (FRAME_X_DISPLAY (f)); + x_catch_errors_for_lisp (FRAME_DISPLAY_INFO (f)); XDeleteProperty (FRAME_X_DISPLAY (f), target_window, prop_atom); - x_check_errors (FRAME_X_DISPLAY (f), - "Couldn't delete window property: %s"); - x_uncatch_errors_after_check (); + x_check_errors_for_lisp (FRAME_DISPLAY_INFO (f), + "Couldn't delete window property: %s"); + x_uncatch_errors_for_lisp (FRAME_DISPLAY_INFO (f)); unblock_input (); return prop; diff --git a/src/xselect.c b/src/xselect.c index 41fa837c5a..2521dc171c 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -2749,7 +2749,11 @@ to send. If a value is a string, it is converted to an Atom and the value of the Atom is sent. If a value is a cons, it is converted to a 32 bit number with the high 16 bits from the car and the lower 16 bit from the cdr. If more values than fits into the event is given, the excessive values -are ignored. */) +are ignored. + +Wait for the event to be sent and signal any error, unless +`x-fast-protocol-requests' is non-nil, in which case errors will be +silently ignored. */) (Lisp_Object display, Lisp_Object dest, Lisp_Object from, Lisp_Object message_type, Lisp_Object format, Lisp_Object values) { @@ -2830,7 +2834,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, the destination window. But if we are sending to the root window, there is no such client. Then we set the event mask to 0xffffff. The event then goes to clients selecting for events on the root window. */ - x_catch_errors (dpyinfo->display); + x_catch_errors_for_lisp (dpyinfo); { bool propagate = !to_root; long mask = to_root ? 0xffffff : 0; @@ -2838,7 +2842,8 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from, XSendEvent (dpyinfo->display, wdest, propagate, mask, &event); XFlush (dpyinfo->display); } - x_uncatch_errors (); + x_check_errors_for_lisp (dpyinfo, "Failed to send client event: %s"); + x_uncatch_errors_for_lisp (dpyinfo); unblock_input (); } diff --git a/src/xterm.c b/src/xterm.c index 7ab22f256f..4353b173ca 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -27836,6 +27836,36 @@ mark_xterm (void) #endif } +/* Error handling functions for Lisp functions that expose X protocol + requests. They are mostly like `x_catch_errors' and friends, but + respect `x-fast-protocol-requests'. */ + +void +x_catch_errors_for_lisp (struct x_display_info *dpyinfo) +{ + if (!x_fast_protocol_requests) + x_catch_errors (dpyinfo->display); + else + x_ignore_errors_for_next_request (dpyinfo); +} + +void +x_check_errors_for_lisp (struct x_display_info *dpyinfo, + const char *format) +{ + if (!x_fast_protocol_requests) + x_check_errors (dpyinfo->display, format); +} + +void +x_uncatch_errors_for_lisp (struct x_display_info *dpyinfo) +{ + if (!x_fast_protocol_requests) + x_uncatch_errors (); + else + x_stop_ignoring_errors (dpyinfo); +} + void syms_of_xterm (void) { @@ -28141,4 +28171,13 @@ When nil, do not use the primary selection and synthetic mouse clicks to emulate the drag-and-drop of `STRING', `UTF8_STRING', `COMPOUND_TEXT' or `TEXT'. */); x_dnd_use_unsupported_drop = true; + + DEFVAR_BOOL ("x-fast-protocol-requests", x_fast_protocol_requests, + doc: /* Whether or not X protocol-related functions should wait for errors. +When this is nil, functions such as `x-delete-window-property', +`x-change-window-property' and `x-send-client-message' will wait for a +reply from the X server, and signal any errors that occurred while +executing the protocol request. Otherwise, errors will be silently +ignored without waiting, which is generally faster. */); + x_fast_protocol_requests = false; } diff --git a/src/xterm.h b/src/xterm.h index 7c09073d76..26d6e4b3d0 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1445,6 +1445,11 @@ extern bool x_text_icon (struct frame *, const char *); extern void x_catch_errors (Display *); extern void x_catch_errors_with_handler (Display *, x_special_error_handler, void *); +extern void x_catch_errors_for_lisp (struct x_display_info *); +extern void x_uncatch_errors_for_lisp (struct x_display_info *); +extern void x_check_errors_for_lisp (struct x_display_info *, + const char *) + ATTRIBUTE_FORMAT_PRINTF (2, 0); extern void x_check_errors (Display *, const char *) ATTRIBUTE_FORMAT_PRINTF (2, 0); extern bool x_had_errors_p (Display *); commit 782e48b3dbae3d30d4fd8f2be90e9d9a0114210a Author: Lars Ingebrigtsen Date: Sat Jul 2 22:03:06 2022 +0200 REQUIRE-MATCH doc string clarification * src/minibuf.c (Fcompleting_read): * lisp/minibuffer.el (read-file-name): Clarify what the return value is in the REQUIRE-MATCH function case. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 69a10ce4e2..8a7da41a3b 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3160,8 +3160,9 @@ Fourth arg MUSTMATCH can take the following values: input, but she needs to confirm her choice if she called `minibuffer-complete' right before `minibuffer-complete-and-exit' and the input is not an existing file. -- a function, which will be called with the input as the argument. - If it returns a non-nil value, the minibuffer is exited with that value. +- a function, which will be called with the input as the + argument. If the function returns a non-nil value, the + minibuffer is exited with that argument as the value. - anything else behaves like t except that typing RET does not exit if it does non-null completion. diff --git a/src/minibuf.c b/src/minibuf.c index 85d6ec4434..c2e270a450 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -2011,8 +2011,9 @@ REQUIRE-MATCH can take the following values: input, but she needs to confirm her choice if she called `minibuffer-complete' right before `minibuffer-complete-and-exit' and the input is not an element of COLLECTION. -- a function, which will be called with the input as the parameter. - If it returns a non-nil value, the minibuffer is exited with that value. +- a function, which will be called with the input as the + argument. If the function returns a non-nil value, the + minibuffer is exited with that argument as the value. - anything else behaves like t except that typing RET does not exit if it does non-null completion. commit 6b2a9171b81e24c53b388697b99de1ee63a9426e Author: Lars Ingebrigtsen Date: Sat Jul 2 19:45:27 2022 +0200 Fix some typos in NEWS diff --git a/etc/NEWS b/etc/NEWS index 6d99a55d56..47ca9c4b6e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -328,7 +328,7 @@ startup. Previously, these functions ignored ** 'longlines-mode' is no longer obsolete. +++ -** New command to change the fond sized globally. +** New command to change the font size globally. To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to decrease it, type 'C-x C-M--'; to restore the font size, type 'C-x C-M-0'. The final key in these commands may be repeated without the commit 3c125290d208e4c962635aa5af4951249af17804 Author: Lars Ingebrigtsen Date: Sat Jul 2 18:42:11 2022 +0200 Add sanity check for Emacsen distributed without .el files * src/lread.c (maybe_swap_for_eln): Add sanity check for Emacsen distributed without .el files (bug#48342). diff --git a/src/lread.c b/src/lread.c index ef2bb036e3..759cc08946 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1735,13 +1735,24 @@ maybe_swap_for_eln (bool no_native, Lisp_Object *filename, int *fd, { if (!NILP (find_symbol_value ( Qnative_comp_warning_on_missing_source))) - call2 (intern_c_string ("display-warning"), - Qcomp, - CALLN (Fformat, - build_string ("Cannot look-up eln file as no source " - "file was found for %s"), - *filename)); - return; + { + /* If we have an installation without any .el files, + there's really no point in giving a warning here, + because that will trigger a cascade of warnings. So + just do a sanity check and refuse to do anything if we + can't find even central .el files. */ + if (NILP (Flocate_file_internal (build_string ("simple.el"), + Vload_path, + Qnil, Qnil))) + return; + call2 (intern_c_string ("display-warning"), + Qcomp, + CALLN (Fformat, + build_string ("Cannot look up eln file as " + "no source file was found for %s"), + *filename)); + return; + } } } Lisp_Object eln_rel_name = Fcomp_el_to_eln_rel_filename (src_name); commit d927181b1a4d62a289a702faa12a9e9e6d6dcae4 Author: Alan Mackenzie Date: Mon Jan 31 17:44:59 2022 +0000 * lisp/progmodes/cc-mode.el (c-common-init): Bind case-fold-search to nil Backport: This fixes bug #53605. diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 0aef94a4f2..22ab277781 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -787,43 +787,44 @@ MODE is the symbol for the mode to initialize, like `c-mode'. See `c-basic-common-init' for details. It's only optional to be compatible with old code; callers should always specify it." - (unless mode - ;; Called from an old third party package. The fallback is to - ;; initialize for C. - (c-init-language-vars-for 'c-mode)) - - (c-basic-common-init mode c-default-style) - (when mode - ;; Only initialize font locking if we aren't called from an old package. - (c-font-lock-init)) - - ;; Starting a mode is a sort of "change". So call the change functions... - (save-restriction - (widen) - (setq c-new-BEG (point-min)) - (setq c-new-END (point-max)) - (save-excursion - (let (before-change-functions after-change-functions) - (mapc (lambda (fn) - (funcall fn (point-min) (point-max))) - c-get-state-before-change-functions) - (mapc (lambda (fn) - (funcall fn (point-min) (point-max) - (- (point-max) (point-min)))) - c-before-font-lock-functions)))) - - (set (make-local-variable 'outline-regexp) "[^#\n\^M]") - (set (make-local-variable 'outline-level) 'c-outline-level) - (set (make-local-variable 'add-log-current-defun-function) - (lambda () - (or (c-cpp-define-name) (car (c-defun-name-and-limits nil))))) - (let ((rfn (assq mode c-require-final-newline))) - (when rfn - (if (boundp 'mode-require-final-newline) - (and (cdr rfn) - (set (make-local-variable 'require-final-newline) - mode-require-final-newline)) - (set (make-local-variable 'require-final-newline) (cdr rfn)))))) + (let (case-fold-search) + (unless mode + ;; Called from an old third party package. The fallback is to + ;; initialize for C. + (c-init-language-vars-for 'c-mode)) + + (c-basic-common-init mode c-default-style) + (when mode + ;; Only initialize font locking if we aren't called from an old package. + (c-font-lock-init)) + + ;; Starting a mode is a sort of "change". So call the change functions... + (save-restriction + (widen) + (setq c-new-BEG (point-min)) + (setq c-new-END (point-max)) + (save-excursion + (let (before-change-functions after-change-functions) + (mapc (lambda (fn) + (funcall fn (point-min) (point-max))) + c-get-state-before-change-functions) + (mapc (lambda (fn) + (funcall fn (point-min) (point-max) + (- (point-max) (point-min)))) + c-before-font-lock-functions)))) + + (set (make-local-variable 'outline-regexp) "[^#\n\^M]") + (set (make-local-variable 'outline-level) 'c-outline-level) + (set (make-local-variable 'add-log-current-defun-function) + (lambda () + (or (c-cpp-define-name) (car (c-defun-name-and-limits nil))))) + (let ((rfn (assq mode c-require-final-newline))) + (when rfn + (if (boundp 'mode-require-final-newline) + (and (cdr rfn) + (set (make-local-variable 'require-final-newline) + mode-require-final-newline)) + (set (make-local-variable 'require-final-newline) (cdr rfn))))))) (defun c-count-cfss (lv-alist) ;; LV-ALIST is an alist like `file-local-variables-alist'. Count how many commit dc3d01a5aff4017ac071bf7f72ab4df493d2b2f6 Author: Alan Mackenzie Date: Sat Jul 2 16:12:59 2022 +0000 CC Mode: Fix a c-backward-token-2 call wrongly jumping back over macros. This fixes bug #56256. * lisp/progmodes/cc-fonts.el (c-font-lock-c++-lambda-captures): Replace a c-backward-token-2, which could jump back too far leading to an infinite loop, with a save-excursion to remember the point we've got to go back to. diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 63df267b43..49e8763a28 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1826,7 +1826,7 @@ casts and declarations are fontified. Used on level 2 and higher." ;; font-lock-keyword-face. It always returns NIL to inhibit this and ;; prevent a repeat invocation. See elisp/lispref page "Search-based ;; Fontification". - (let (mode capture-default id-start id-end declaration sub-begin sub-end) + (let (mode capture-default id-start id-end declaration sub-begin sub-end tem) (while (and (< (point) limit) (search-forward "[" limit t)) (when (progn (backward-char) @@ -1838,15 +1838,18 @@ casts and declarations are fontified. Used on level 2 and higher." (char-after))) ;; Is the first element of the list a bare "=" or "&"? (when mode - (forward-char) - (c-forward-syntactic-ws) - (if (memq (char-after) '(?, ?\])) - (progn - (setq capture-default mode) - (when (eq (char-after) ?,) - (forward-char) - (c-forward-syntactic-ws))) - (c-backward-token-2))) + (setq tem nil) + (save-excursion + (forward-char) + (c-forward-syntactic-ws) + (if (memq (char-after) '(?, ?\])) + (progn + (setq capture-default mode) + (when (eq (char-after) ?,) + (forward-char) + (c-forward-syntactic-ws)) + (setq tem (point))))) + (if tem (goto-char tem))) ;; Go round the following loop once per captured item. We use "\\s)" ;; rather than "\\]" here to avoid infinite looping in this situation: commit b79cfaaf14a7aa7e8bb56fc4063bd007e0edc69a Author: Lars Ingebrigtsen Date: Sat Jul 2 17:58:56 2022 +0200 Filter out nul bytes when killing from a *grep* buffer * lisp/progmodes/grep.el (grep-mode): Filter out the nul bytes (bug#48321). diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index a3ef90f397..4f90a53444 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -885,6 +885,14 @@ The value depends on `grep-command', `grep-template', (setq-local compilation-disable-input t) (setq-local compilation-error-screen-columns grep-error-screen-columns) + ;; We normally use a nul byte to separate the file name from the + ;; contents, but display it as ":". That's fine, but when yanking + ;; to other buffers, it's annoying to have the nul byte there. + (unless kill-transform-function + (setq-local kill-transform-function #'identity)) + (add-function :filter-return (local 'kill-transform-function) + (lambda (string) + (string-replace "\0" ":" string))) (add-hook 'compilation-filter-hook #'grep-filter nil t)) (defun grep--save-buffers () commit a06fc4be132b8dcf7a5dab9d68be3f280e14f436 Author: Manuel Giraud Date: Sat Jul 2 17:38:36 2022 +0200 Add more separators to longlines-mode * lisp/obsolete/longlines.el (longlines-breakpoint-chars): New custom to have multiple breakpoint chars. (longlines-set-breakpoint): Add a target-column parameter and use `longlines-breakpoint-chars'. (longlines-find-break-backward, longlines-find-break-foreward): Use `longlines-breakpoint-chars'. (longlines-wrap-line): Do not insert space upon merging, just remove the soft newline. Fix "space before tab" in indent. (longlines-merge-lines-p): Use the new target-column parameter to find out if the next line could be merged with the current one. (longlines-encode-region): Do not replace a soft newline with a space, just remove it. * etc/NEWS: New user option 'longlines-breakpoint-chars' diff --git a/etc/NEWS b/etc/NEWS index 9b80adb7da..6d99a55d56 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -458,6 +458,11 @@ including those typed in response to passwords prompt (this was the previous behavior). The default is nil, which inhibits recording of passwords. ++++ +** New user option 'longlines-breakpoint-chars'. +This is a string containing chars that could be used as breakpoint in +longlines mode. + +++ ** New function 'command-query'. This function makes its argument command prompt the user for diff --git a/lisp/longlines.el b/lisp/longlines.el index 7cea68ef18..a6cf93a039 100644 --- a/lisp/longlines.el +++ b/lisp/longlines.el @@ -72,6 +72,10 @@ You can also enable the display temporarily, using the command This is used when `longlines-show-hard-newlines' is on." :type 'string) +(defcustom longlines-breakpoint-chars " ;,|" + "A bag of separator chars for longlines." + :type 'string) + ;;; Internal variables (defvar longlines-wrap-beg nil) @@ -272,11 +276,8 @@ end of the buffer." "If the current line needs to be wrapped, wrap it and return nil. If wrapping is performed, point remains on the line. If the line does not need to be wrapped, move point to the next line and return t." - (if (longlines-set-breakpoint) + (if (longlines-set-breakpoint fill-column) (progn (insert-before-markers-and-inherit ?\n) - (backward-char 1) - (delete-char -1) - (forward-char 1) nil) (if (longlines-merge-lines-p) (progn (end-of-line) @@ -285,58 +286,60 @@ not need to be wrapped, move point to the next line and return t." ;; replace these two newlines by a single space. Unfortunately, ;; this breaks the conservation of (spaces + newlines), so we ;; have to fiddle with longlines-wrap-point. - (if (or (prog1 (bolp) (forward-char 1)) (eolp)) - (progn - (delete-char -1) - (if (> longlines-wrap-point (point)) - (setq longlines-wrap-point - (1- longlines-wrap-point)))) - (insert-before-markers-and-inherit ?\s) - (backward-char 1) - (delete-char -1) - (forward-char 1)) + (if (or (prog1 (bolp) (forward-char 1)) (eolp)) + (progn + (delete-char -1) + (if (> longlines-wrap-point (point)) + (setq longlines-wrap-point + (1- longlines-wrap-point)))) + (delete-char -1)) nil) (forward-line 1) t))) -(defun longlines-set-breakpoint () +(defun longlines-set-breakpoint (target-column) "Place point where we should break the current line, and return t. If the line should not be broken, return nil; point remains on the line." - (move-to-column fill-column) - (if (and (re-search-forward "[^ ]" (line-end-position) 1) - (> (current-column) fill-column)) - ;; This line is too long. Can we break it? - (or (longlines-find-break-backward) - (progn (move-to-column fill-column) - (longlines-find-break-forward))))) + (move-to-column target-column) + (let ((non-breakpoint-re (format "[^%s]" longlines-breakpoint-chars))) + (if (and (re-search-forward non-breakpoint-re (line-end-position) t 1) + (> (current-column) target-column)) + ;; This line is too long. Can we break it? + (or (longlines-find-break-backward) + (progn (move-to-column target-column) + (longlines-find-break-forward)))))) (defun longlines-find-break-backward () "Move point backward to the first available breakpoint and return t. If no breakpoint is found, return nil." - (and (search-backward " " (line-beginning-position) 1) - (save-excursion - (skip-chars-backward " " (line-beginning-position)) - (null (bolp))) - (progn (forward-char 1) - (if (and fill-nobreak-predicate - (run-hook-with-args-until-success - 'fill-nobreak-predicate)) - (progn (skip-chars-backward " " (line-beginning-position)) - (longlines-find-break-backward)) - t)))) + (let ((breakpoint-re (format "[%s]" longlines-breakpoint-chars))) + (when (and (re-search-backward breakpoint-re (line-beginning-position) t 1) + (save-excursion + (skip-chars-backward longlines-breakpoint-chars + (line-beginning-position)) + (null (bolp)))) + (forward-char 1) + (if (and fill-nobreak-predicate + (run-hook-with-args-until-success 'fill-nobreak-predicate)) + (progn + (skip-chars-backward longlines-breakpoint-chars + (line-beginning-position)) + (longlines-find-break-backward)) + t)))) (defun longlines-find-break-forward () "Move point forward to the first available breakpoint and return t. If no break point is found, return nil." - (and (search-forward " " (line-end-position) 1) - (progn (skip-chars-forward " " (line-end-position)) - (null (eolp))) - (if (and fill-nobreak-predicate - (run-hook-with-args-until-success - 'fill-nobreak-predicate)) - (longlines-find-break-forward) - t))) + (let ((breakpoint-re (format "[%s]" longlines-breakpoint-chars))) + (and (re-search-forward breakpoint-re (line-end-position) t 1) + (progn + (skip-chars-forward longlines-breakpoint-chars (line-end-position)) + (null (eolp))) + (if (and fill-nobreak-predicate + (run-hook-with-args-until-success 'fill-nobreak-predicate)) + (longlines-find-break-forward) + t)))) (defun longlines-merge-lines-p () "Return t if part of the next line can fit onto the current line. @@ -347,12 +350,7 @@ Otherwise, return nil. Text cannot be moved across hard newlines." (null (get-text-property (point) 'hard)) (let ((space (- fill-column (current-column)))) (forward-line 1) - (if (eq (char-after) ? ) - t ; We can always merge some spaces - (<= (if (search-forward " " (line-end-position) 1) - (current-column) - (1+ (current-column))) - space)))))) + (longlines-set-breakpoint (max 0 (1- space))))))) (defun longlines-decode-region (&optional beg end) "Turn all newlines between BEG and END into hard newlines. @@ -371,7 +369,7 @@ If BEG and END are nil, the point and mark are used." (longlines-decode-region (point-min) (point-max))) (defun longlines-encode-region (beg end &optional _buffer) - "Replace each soft newline between BEG and END with exactly one space. + "Remove each soft newline between BEG and END. Hard newlines are left intact. The optional argument BUFFER exists for compatibility with `format-alist', and is ignored." (save-excursion @@ -381,10 +379,8 @@ compatibility with `format-alist', and is ignored." (while (search-forward "\n" reg-max t) (let ((pos (match-beginning 0))) (unless (get-text-property pos 'hard) - (goto-char (1+ pos)) - (insert-and-inherit " ") - (delete-region pos (1+ pos)) - (remove-text-properties pos (1+ pos) '(hard nil))))) + (remove-text-properties pos (1+ pos) '(hard nil)) + (delete-region pos (1+ pos))))) (set-buffer-modified-p mod) end))) commit 3ace37a387cf87aec11ace23e6b4d9a3058db667 Author: Lars Ingebrigtsen Date: Sat Jul 2 17:33:33 2022 +0200 Unobsolete longlines-mode (bug#18589) diff --git a/etc/NEWS b/etc/NEWS index 7eb0ebbc28..9b80adb7da 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -324,6 +324,9 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 +--- +** 'longlines-mode' is no longer obsolete. + +++ ** New command to change the fond sized globally. To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to diff --git a/lisp/obsolete/longlines.el b/lisp/longlines.el similarity index 99% rename from lisp/obsolete/longlines.el rename to lisp/longlines.el index 731f47794c..7cea68ef18 100644 --- a/lisp/obsolete/longlines.el +++ b/lisp/longlines.el @@ -6,7 +6,6 @@ ;; Alex Schroeder ;; Chong Yidong ;; Maintainer: emacs-devel@gnu.org -;; Obsolete-since: 24.4 ;; Keywords: convenience, wp ;; This file is part of GNU Emacs. commit feac92fe1da10d75aa9319a43458bca55086cd6f Author: Stefan Kangas Date: Sat Jul 2 17:32:14 2022 +0200 Use help-key-binding face in text scale adjust messages * lisp/face-remap.el (text-scale-adjust) (global-text-scale-adjust): Use substitute-command-keys. diff --git a/lisp/face-remap.el b/lisp/face-remap.el index ade650c629..7037bc58cb 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -409,7 +409,8 @@ See also the related command `global-text-scale-adjust'." (_ inc)))) (text-scale-increase step) ;; (unless (zerop step) - (message "Use +,-,0 for further adjustment") + (message (substitute-command-keys + "Use \\`+',\\`-',\\`0' for further adjustment")) (set-transient-map (let ((map (make-sparse-keymap))) (dolist (mods '(() (control))) @@ -514,7 +515,8 @@ See also the related command `text-scale-adjust'." (not global-text-scale-adjust-resizes-frames))) (set-face-attribute 'default nil :height new))) (when (characterp key) - (message "Use +,-,0 for further adjustment") + (message (substitute-command-keys + "Use \\`+',\\`-',\\`0' for further adjustment")) (set-transient-map (let ((map (make-sparse-keymap))) (dolist (mod '(() (control meta))) commit 4b9b1ea6a091f41f3c0315762661b4dcc350564a Author: Stefan Kangas Date: Sat Jul 2 16:59:14 2022 +0200 Use help-key-binding face in repeat-mode message * lisp/repeat.el (repeat-echo-message-string): Use substitute-command-keys. diff --git a/lisp/repeat.el b/lisp/repeat.el index fa65057a73..6bbed95449 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -503,7 +503,9 @@ See `describe-repeat-maps' for a list of all repeatable commands." (map-keymap (lambda (key cmd) (and cmd (push key keys))) keymap) (format-message "Repeat with %s%s" (mapconcat (lambda (key) - (key-description (vector key))) + (substitute-command-keys + (format "\\`%s'" + (key-description (vector key))))) keys ", ") (if repeat-exit-key (format ", or exit with %s" commit ad73b588d48367dbef35c7561f79473317bd81f9 Author: Stefan Kangas Date: Sat Jul 2 16:56:39 2022 +0200 Make dired-jump repeatable in repeat-mode * lisp/dired.el (dired-jump-map): New variable. (dired-jump): Put 'repeat-map' property with 'dired-jump-map'. diff --git a/lisp/dired.el b/lisp/dired.el index dc7400d46e..d7bf631688 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -4797,6 +4797,11 @@ Interactively with prefix argument, read FILE-NAME." (read-file-name "Jump to Dired file: ")))) (dired-jump t file-name)) +(defvar-keymap dired-jump-map + :doc "Keymap to repeat `dired-jump'. Used in `repeat-mode'." + "C-j" #'dired-jump) +(put 'dired-jump 'repeat-map 'dired-jump-map) + ;;; Miscellaneous commands commit 1ee1d21c752c8a3eeb3d65a8d246c2c9979a2b40 Author: Eli Zaretskii Date: Sat Jul 2 17:56:05 2022 +0300 ; * etc/NEWS: Fix typo in recently-added entry. diff --git a/etc/NEWS b/etc/NEWS index d5f3459630..7eb0ebbc28 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1036,7 +1036,7 @@ The 'dired-info' and 'dired-man' commands have been moved from the 'dired-do-info' and 'dired-do-man'; the old command names are obsolete aliases. -They keys 'I' ('dired-do-info') and 'N' ('dired-do-man') are now bound +The keys 'I' ('dired-do-info') and 'N' ('dired-do-man') are now bound in Dired mode by default. The user options 'dired-bind-man' and 'dired-bind-info' no longer have any effect and are obsolete. commit d06bc48716e53b77b39026db813bb0386ae53209 Author: Eli Zaretskii Date: Sat Jul 2 17:52:23 2022 +0300 ; Minor fixes for 'global-text-scale-adjust' * doc/emacs/display.texi (Text Scale): Improve indexing. * lisp/mwheel.el (mouse-wheel-global-text-scale): Doc fix. * lisp/face-remap.el (global-text-scale-adjust-resizes-frames): Fix a typo. (global-text-scale-adjust-limits): Doc fix. (Bug#48307) diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 5e4728c8da..cadac7e453 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -895,6 +895,7 @@ the same as typing @kbd{C-x C-0}. @cindex ajust global font size @findex global-text-scale-adjust +@vindex global-text-scale-adjust-resizes-frames @kindex C-x C-M-+ @kindex C-x C-M-= @kindex C-x C-M-- diff --git a/lisp/face-remap.el b/lisp/face-remap.el index bfc138b043..ade650c629 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -452,12 +452,12 @@ See also the related command `global-text-scale-adjust'." :type '(choice (const :tag "Off" nil) (const :tag "On" t)) :group 'display - :version "28.1") + :version "29.1") (defcustom global-text-scale-adjust-limits '(10 . 500) "Min/max values for `global-text-scale-adjust'. This is a cons cell where the `car' has the minimum font size and -the `cdr' has the max font size." +the `cdr' has the maximum font size, in units of 1/10 pt." :version "29.1" :group 'display :type '(cons (integer :tag "Min") diff --git a/lisp/mwheel.el b/lisp/mwheel.el index 7963eaf4a4..062c98b53e 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -43,7 +43,8 @@ (defvar mouse-wheel-mode) (defun mouse-wheel-global-text-scale (event) - "Increase or decrease the global font size according to the EVENT." + "Increase or decrease the global font size according to the EVENT. +This invokes `global-text-scale-adjust', which see." (interactive (list last-input-event)) (let ((button (mwheel-event-button event))) (unwind-protect commit 0bb6b2dd1eee72788bed6d16bc6e4502e52b4e1c Author: Stefan Kangas Date: Sat Jul 2 15:41:43 2022 +0200 Move dired-info and dired-man from dired-x to dired * lisp/dired-x.el (dired-bind-man, dired-bind-info): Change into defvars and make obsolete. (dired-extra-startup): Doc fix. (dired-info, dired-man): Move from here... * lisp/dired.el (dired-do-info, dired-do-man): ...to here and rename. (Bug#21981) * lisp/dired.el (dired-mode-map): Bind 'I' and 'N' to 'dired-do-info' and 'dired-do-man'. * doc/misc/dired-x.texi (Miscellaneous Commands): Remove documentation of 'dired-info' and 'dired-man'. * doc/emacs/dired.texi (Dired Enter): Document 'dired-do-info' and 'dired-do-man'. * etc/NEWS: Announce the above changes. diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index 9e14e0f9a9..c7ef097bfb 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -963,6 +963,18 @@ Byte compile the specified Emacs Lisp files (@code{dired-do-byte-compile}). @xref{Byte Compilation,, Byte Compilation, elisp, The Emacs Lisp Reference Manual}. +@findex dired-do-info +@kindex I @r{(Dired)} +@cindex running info on files (in Dired) +@item I +Run Info on this file (assumed to be a file in Info format). + +@findex dired-do-man +@kindex N @r{(Dired)} +@cindex running man on files (in Dired) +@item N +Run man on this file (assumed to be a file in @code{nroff} format). + @kindex A @r{(Dired)} @findex dired-do-find-regexp @cindex search multiple files (in Dired) diff --git a/doc/misc/dired-x.texi b/doc/misc/dired-x.texi index 754ccf4065..504060f41f 100644 --- a/doc/misc/dired-x.texi +++ b/doc/misc/dired-x.texi @@ -921,28 +921,6 @@ to @kbd{V}. Otherwise, @code{dired-bind-rmail} will be bound. Bound to @kbd{V} if @code{dired-bind-vm} is @code{nil}. Run Rmail on this file (assumed to be mail folder in Rmail format). -@item dired-info -@kindex I -@cindex running info. -@findex dired-info -Bound to @kbd{I}. Run Info on this file (assumed to be a file in Info -format). - -@vindex dired-bind-info -If the variable @code{dired-bind-info} is @code{nil}, @code{dired-info} will -not be bound to @kbd{I}. - -@item dired-man -@cindex running man. -@kindex N -@findex dired-man -Bound to @kbd{N}. Run man on this file (assumed to be a file in @code{nroff} -format). - -@vindex dired-bind-man -If the variable @code{dired-bind-man} is @code{nil}, @code{dired-man} will not -be bound to @kbd{N}. - @item dired-do-relsymlink @cindex relative symbolic links. @kindex Y diff --git a/etc/NEWS b/etc/NEWS index 773e0849c2..d5f3459630 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1028,6 +1028,25 @@ so automatically. * Changes in Specialized Modes and Packages in Emacs 29.1 +** Dired + +*** 'dired-info' and 'dired-man' moved from dired-x to dired. +The 'dired-info' and 'dired-man' commands have been moved from the +'dired-x' package to 'dired'. They have also been renamed to +'dired-do-info' and 'dired-do-man'; the old command names are obsolete +aliases. + +They keys 'I' ('dired-do-info') and 'N' ('dired-do-man') are now bound +in Dired mode by default. The user options 'dired-bind-man' and +'dired-bind-info' no longer have any effect and are obsolete. + +To get the old behavior back and unbind these keys in Dired mode, add +the following to your Init file: + +(with-eval-after-load 'dired + (keymap-set dired-mode-map "N" nil) + (keymap-set dired-mode-map "I" nil)) + ** Elisp *** New command 'elisp-eval-buffer' (bound to 'C-c C-e'). diff --git a/lisp/dired-x.el b/lisp/dired-x.el index ed7f71e006..21de913287 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -1,7 +1,6 @@ ;;; dired-x.el --- extra Dired functionality -*- lexical-binding:t -*- -;; Copyright (C) 1993-1994, 1997, 2001-2022 Free Software Foundation, -;; Inc. +;; Copyright (C) 1993-2022 Free Software Foundation, Inc. ;; Author: Sebastian Kremer ;; Lawrence R. Dodd @@ -68,29 +67,11 @@ mbox format, and so cannot be distinguished in this way." (defvar dired-bind-jump t) (make-obsolete-variable 'dired-bind-jump "not used." "28.1") -(defcustom dired-bind-man t - "Non-nil means bind `dired-man' to \"N\" in Dired, otherwise do not. -Setting this variable directly after dired-x is loaded has no effect - -use \\[customize]." - :type 'boolean - :set (lambda (sym val) - (if (set sym val) - (define-key dired-mode-map "N" 'dired-man) - (if (eq 'dired-man (lookup-key dired-mode-map "N")) - (define-key dired-mode-map "N" nil)))) - :group 'dired-keys) +(defvar dired-bind-man t) +(make-obsolete-variable 'dired-bind-man "not used." "29.1") -(defcustom dired-bind-info t - "Non-nil means bind `dired-info' to \"I\" in Dired, otherwise do not. -Setting this variable directly after dired-x is loaded has no effect - -use \\[customize]." - :type 'boolean - :set (lambda (sym val) - (if (set sym val) - (define-key dired-mode-map "I" 'dired-info) - (if (eq 'dired-info (lookup-key dired-mode-map "I")) - (define-key dired-mode-map "I" nil)))) - :group 'dired-keys) +(defvar dired-bind-info t) +(make-obsolete-variable 'dired-bind-info "not used." "29.1") (defcustom dired-vm-read-only-folders nil "If non-nil, \\[dired-vm] will visit all folders read-only. @@ -328,8 +309,6 @@ files"] "Automatically put on `dired-mode-hook' to get extra Dired features: \\ \\[dired-do-run-mail]\t-- run mail on folder (see `dired-bind-vm') - \\[dired-info]\t-- run info on file - \\[dired-man]\t-- run man on file \\[dired-do-find-marked-files]\t-- visit all marked files simultaneously \\[dired-omit-mode]\t-- toggle omitting of files \\[dired-mark-sexp]\t-- mark by Lisp expression @@ -338,10 +317,8 @@ To see the options you can set, use \\[customize-group] RET dired-x RET. See also the functions: `dired-flag-extension' `dired-virtual' - `dired-man' `dired-vm' `dired-rmail' - `dired-info' `dired-do-find-marked-files'" (interactive) ;; These must be done in each new dired buffer. @@ -1238,31 +1215,6 @@ NOSELECT the files are merely found but not selected." ;;; Miscellaneous commands -;; Run man on files. - -(declare-function Man-getpage-in-background "man" (topic)) - -(defvar manual-program) ; from man.el - -(defun dired-man () - "Run `man' on this file." - ;; Used also to say: "Display old buffer if buffer name matches filename." - ;; but I have no idea what that means. - (interactive) - (require 'man) - (let* ((file (dired-get-filename)) - (manual-program (string-replace "*" "%s" - (dired-guess-shell-command - "Man command: " (list file))))) - (Man-getpage-in-background file))) - -;; Run Info on files. - -(defun dired-info () - "Run `info' on this file." - (interactive) - (info (dired-get-filename))) - ;; Run mail on mail folders. (declare-function vm-visit-folder "ext:vm" (folder &optional read-only)) @@ -1596,6 +1548,8 @@ If `current-prefix-arg' is non-nil, uses name at point as guess." ;;; Epilog (define-obsolete-function-alias 'dired-x-submit-report 'report-emacs-bug "24.1") +(define-obsolete-function-alias 'dired-man #'dired-do-man "29.1") +(define-obsolete-function-alias 'dired-info #'dired-do-info "29.1") ;; As Barry Warsaw would say: "This might be useful..." diff --git a/lisp/dired.el b/lisp/dired.el index 55e150e9e0..dc7400d46e 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -2079,8 +2079,10 @@ Do so according to the former subdir alist OLD-SUBDIR-ALIST." "D" #'dired-do-delete "G" #'dired-do-chgrp "H" #'dired-do-hardlink + "I" #'dired-do-info "L" #'dired-do-load "M" #'dired-do-chmod + "N" #'dired-do-man "O" #'dired-do-chown "P" #'dired-do-print "Q" #'dired-do-find-regexp-and-replace @@ -4795,6 +4797,31 @@ Interactively with prefix argument, read FILE-NAME." (read-file-name "Jump to Dired file: ")))) (dired-jump t file-name)) + +;;; Miscellaneous commands + +(declare-function Man-getpage-in-background "man" (topic)) +(declare-function dired-guess-shell-command "dired-x" (prompt files)) +(defvar manual-program) ; from man.el + +(defun dired-do-man () + "Run `man' on this file." + (interactive) + (require 'man) + ;; FIXME: Move `dired-guess-shell-command' to dired.el to remove the + ;; need for requiring `dired-x'. + (require 'dired-x) + (let* ((file (dired-get-filename)) + (manual-program (string-replace "*" "%s" + (dired-guess-shell-command + "Man command: " (list file))))) + (Man-getpage-in-background file))) + +(defun dired-do-info () + "Run `info' on this file." + (interactive) + (info (dired-get-filename))) + (provide 'dired) (run-hooks 'dired-load-hook) ; for your customizations commit 25d80e4f8115bc297ebe99bc698e8257bb0d29b3 Author: Stefan Kangas Date: Sat Jul 2 12:25:03 2022 +0200 Prefer defvar-keymap in nxml/*.el * lisp/nxml/nxml-mode.el (nxml-mode-map): * lisp/nxml/nxml-outln.el (nxml-outline-prefix-map) (nxml-outline-show-map, nxml-outline-hiding-tag-map) (nxml-outline-showing-tag-map): Prefer defvar-keymap. diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el index 171b7088c1..dfe5c369e2 100644 --- a/lisp/nxml/nxml-mode.el +++ b/lisp/nxml/nxml-mode.el @@ -369,31 +369,29 @@ and, if `nxml-char-ref-display-glyph-flag' is non-nil, a glyph corresponding to the referenced character following the character reference.") -(defvar nxml-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\M-\C-u" 'nxml-backward-up-element) - (define-key map "\M-\C-d" 'nxml-down-element) - (define-key map "\M-\C-n" 'nxml-forward-element) - (define-key map "\M-\C-p" 'nxml-backward-element) - (define-key map "\M-{" 'nxml-backward-paragraph) - (define-key map "\M-}" 'nxml-forward-paragraph) - (define-key map "\M-h" 'nxml-mark-paragraph) - (define-key map "\C-c\C-f" 'nxml-finish-element) - (define-key map "\C-c]" 'nxml-finish-element) - (define-key map "\C-c/" 'nxml-finish-element) - (define-key map "\C-c\C-m" 'nxml-split-element) - (define-key map "\C-c\C-b" 'nxml-balanced-close-start-tag-block) - (define-key map "\C-c\C-i" 'nxml-balanced-close-start-tag-inline) - (define-key map "\C-c\C-x" 'nxml-insert-xml-declaration) - (define-key map "\C-c\C-d" 'nxml-dynamic-markup-word) - ;; u is for Unicode - (define-key map "\C-c\C-u" 'nxml-insert-named-char) - (define-key map "\C-c\C-o" nxml-outline-prefix-map) - (define-key map [S-mouse-2] 'nxml-mouse-hide-direct-text-content) - (define-key map "/" 'nxml-electric-slash) - (define-key map "\M-\t" 'completion-at-point) - map) - "Keymap for `nxml-mode'.") +(defvar-keymap nxml-mode-map + :doc "Keymap for `nxml-mode'." + "C-M-u" #'nxml-backward-up-element + "C-M-d" #'nxml-down-element + "C-M-n" #'nxml-forward-element + "C-M-p" #'nxml-backward-element + "M-{" #'nxml-backward-paragraph + "M-}" #'nxml-forward-paragraph + "M-h" #'nxml-mark-paragraph + "C-c C-f" #'nxml-finish-element + "C-c ]" #'nxml-finish-element + "C-c /" #'nxml-finish-element + "C-c C-m" #'nxml-split-element + "C-c C-b" #'nxml-balanced-close-start-tag-block + "C-c C-i" #'nxml-balanced-close-start-tag-inline + "C-c C-x" #'nxml-insert-xml-declaration + "C-c C-d" #'nxml-dynamic-markup-word + ;; u is for Unicode + "C-c C-u" #'nxml-insert-named-char + "C-c C-o" nxml-outline-prefix-map + "/" #'nxml-electric-slash + "M-TAB" #'completion-at-point + "S-" #'nxml-mouse-hide-direct-text-content) (defvar nxml-font-lock-keywords '(nxml-fontify-matcher) diff --git a/lisp/nxml/nxml-outln.el b/lisp/nxml/nxml-outln.el index 928338a6af..1518122a79 100644 --- a/lisp/nxml/nxml-outln.el +++ b/lisp/nxml/nxml-outln.el @@ -129,20 +129,18 @@ See the variable `nxml-section-element-name-regexp' for more details." (defvar nxml-heading-scan-distance 1000 "Maximum distance from section to scan for heading.") -(defvar nxml-outline-prefix-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-a" 'nxml-show-all) - (define-key map "\C-t" 'nxml-hide-all-text-content) - (define-key map "\C-r" 'nxml-refresh-outline) - (define-key map "\C-c" 'nxml-hide-direct-text-content) - (define-key map "\C-e" 'nxml-show-direct-text-content) - (define-key map "\C-d" 'nxml-hide-subheadings) - (define-key map "\C-s" 'nxml-show) - (define-key map "\C-k" 'nxml-show-subheadings) - (define-key map "\C-l" 'nxml-hide-text-content) - (define-key map "\C-i" 'nxml-show-direct-subheadings) - (define-key map "\C-o" 'nxml-hide-other) - map)) +(defvar-keymap nxml-outline-prefix-map + "C-a" #'nxml-show-all + "C-t" #'nxml-hide-all-text-content + "C-r" #'nxml-refresh-outline + "C-c" #'nxml-hide-direct-text-content + "C-e" #'nxml-show-direct-text-content + "C-d" #'nxml-hide-subheadings + "C-s" #'nxml-show + "C-k" #'nxml-show-subheadings + "C-l" #'nxml-hide-text-content + "C-i" #'nxml-show-direct-subheadings + "C-o" #'nxml-hide-other) ;;; Commands for changing visibility @@ -693,11 +691,9 @@ non-transparent child section." (nxml-highlighted-qname (xmltok-end-tag-qname)) nxml-highlighted-greater-than)))) -(defvar nxml-outline-show-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-m" 'nxml-show-direct-text-content) - (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content) - map)) +(defvar-keymap nxml-outline-show-map + "RET" #'nxml-show-direct-text-content + "" #'nxml-mouse-show-direct-text-content) (defvar nxml-outline-show-help "mouse-2: show") @@ -724,12 +720,10 @@ non-transparent child section." (put 'nxml-outline-display-heading 'evaporate t) (put 'nxml-outline-display-heading 'face 'nxml-heading) -(defvar nxml-outline-hiding-tag-map - (let ((map (make-sparse-keymap))) - (define-key map [mouse-1] 'nxml-mouse-show-direct-subheadings) - (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content) - (define-key map "\C-m" 'nxml-show-direct-text-content) - map)) +(defvar-keymap nxml-outline-hiding-tag-map + "" #'nxml-mouse-show-direct-subheadings + "" #'nxml-mouse-show-direct-text-content + "RET" #'nxml-show-direct-text-content) (defvar nxml-outline-hiding-tag-help "mouse-1: show subheadings, mouse-2: show text content") @@ -739,12 +733,10 @@ non-transparent child section." (put 'nxml-outline-display-hiding-tag 'keymap nxml-outline-hiding-tag-map) (put 'nxml-outline-display-hiding-tag 'help-echo nxml-outline-hiding-tag-help) -(defvar nxml-outline-showing-tag-map - (let ((map (make-sparse-keymap))) - (define-key map [mouse-1] 'nxml-mouse-hide-subheadings) - (define-key map [mouse-2] 'nxml-mouse-show-direct-text-content) - (define-key map "\C-m" 'nxml-show-direct-text-content) - map)) +(defvar-keymap nxml-outline-showing-tag-map + "" #'nxml-mouse-hide-subheadings + "" #'nxml-mouse-show-direct-text-content + "RET" #'nxml-show-direct-text-content) (defvar nxml-outline-showing-tag-help "mouse-1: hide subheadings, mouse-2: show text content") commit b25ca542983dc885d69d263cb9719f7f3db416fa Author: Po Lu Date: Sat Jul 2 21:55:22 2022 +0800 Fix error handling for XCB Xlib * src/xterm.c (xm_send_drop_message) (xm_send_top_level_enter_message, xm_send_drag_motion_message) (xm_send_top_level_leave_message, x_dnd_compute_toplevels) (x_dnd_send_enter, x_dnd_send_position, x_dnd_send_leave) (x_dnd_send_drop, handle_one_xevent, x_catch_errors_with_handler) (x_request_can_fail, x_clean_failable_requests) (x_ignore_errors_for_next_request, x_stop_ignoring_errors) (x_uncatch_errors, x_check_errors, x_had_errors_p, x_error_handler) (frame_set_mouse_pixel_position, x_focus_frame): Record serial sequences instead of simply the next request when ignoring a single request. Use XNextRequest instead of NextRequest, since the latter is unreliable when using Xlib built with XCB. * src/xterm.h (struct x_failable_request): New struct.. (struct x_display_info): Make failable request variables the right type. diff --git a/src/xterm.c b/src/xterm.c index 0c695324f3..7ab22f256f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1117,6 +1117,7 @@ static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar static int x_filter_event (struct x_display_info *, XEvent *); #endif static void x_ignore_errors_for_next_request (struct x_display_info *); +static void x_stop_ignoring_errors (struct x_display_info *); static void x_clean_failable_requests (struct x_display_info *); static struct frame *x_tooltip_window_to_frame (struct x_display_info *, @@ -2444,6 +2445,7 @@ xm_send_drop_message (struct x_display_info *dpyinfo, Window source, x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); + x_stop_ignoring_errors (dpyinfo); } static void @@ -2470,6 +2472,7 @@ xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source, x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); + x_stop_ignoring_errors (dpyinfo); } static void @@ -2500,6 +2503,7 @@ xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source, x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); + x_stop_ignoring_errors (dpyinfo); } static void @@ -2558,6 +2562,7 @@ xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source, x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); + x_stop_ignoring_errors (dpyinfo); } static int @@ -3211,6 +3216,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) XShapeSelectInput (dpyinfo->display, toplevels[i], ShapeNotifyMask); + x_stop_ignoring_errors (dpyinfo); #ifndef HAVE_XCB_SHAPE x_catch_errors (dpyinfo->display); @@ -4397,6 +4403,7 @@ x_dnd_send_enter (struct frame *f, Window target, int supported) x_ignore_errors_for_next_request (dpyinfo); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); + x_stop_ignoring_errors (dpyinfo); } static void @@ -4459,6 +4466,7 @@ x_dnd_send_position (struct frame *f, Window target, int supported, { x_ignore_errors_for_next_request (dpyinfo); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); + x_stop_ignoring_errors (dpyinfo); x_dnd_waiting_for_status_window = target; } @@ -4484,6 +4492,7 @@ x_dnd_send_leave (struct frame *f, Window target) x_ignore_errors_for_next_request (dpyinfo); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); + x_stop_ignoring_errors (dpyinfo); } static bool @@ -4516,6 +4525,7 @@ x_dnd_send_drop (struct frame *f, Window target, Time timestamp, x_ignore_errors_for_next_request (dpyinfo); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); + x_stop_ignoring_errors (dpyinfo); return true; } @@ -16454,6 +16464,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XSendEvent (dpyinfo->display, target, False, NoEventMask, &x_dnd_pending_send_position); + x_stop_ignoring_errors (dpyinfo); x_dnd_pending_send_position.type = 0; /* Since we sent another XdndPosition message, we @@ -22991,7 +23002,8 @@ x_error_catcher (Display *display, XErrorEvent *event, There is no need to use this mechanism for ignoring errors from single asynchronous requests, such as sending a ClientMessage to a window that might no longer exist. Use - x_ignore_errors_for_next_request instead. */ + x_ignore_errors_for_next_request (paired with + x_stop_ignoring_errors) instead. */ void x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler, @@ -23004,7 +23016,7 @@ x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler, data->handler = handler; data->handler_data = handler_data; data->prev = x_error_message; - data->first_request = NextRequest (dpy); + data->first_request = XNextRequest (dpy); x_error_message = data; ++x_error_message_count; @@ -23018,17 +23030,21 @@ x_catch_errors (Display *dpy) /* Return if errors for REQUEST should be ignored even if there is no error handler applied. */ -static unsigned long * +static struct x_failable_request * x_request_can_fail (struct x_display_info *dpyinfo, unsigned long request) { - unsigned long *failable_requests; + struct x_failable_request *failable_requests; for (failable_requests = dpyinfo->failable_requests; failable_requests < dpyinfo->next_failable_request; failable_requests++) { - if (*failable_requests == request) + if (X_COMPARE_SERIALS (request, >=, + failable_requests->start) + && (!failable_requests->end + || X_COMPARE_SERIALS (request, <=, + failable_requests->end))) return failable_requests; } @@ -23040,13 +23056,17 @@ x_request_can_fail (struct x_display_info *dpyinfo, static void x_clean_failable_requests (struct x_display_info *dpyinfo) { - unsigned long *first, *last; + struct x_failable_request *first, *last; last = dpyinfo->next_failable_request; for (first = dpyinfo->failable_requests; first < last; first++) { - if (*first > LastKnownRequestProcessed (dpyinfo->display)) + if (X_COMPARE_SERIALS (first->start, >, + LastKnownRequestProcessed (dpyinfo->display)) + || !first->end + || X_COMPARE_SERIALS (first->end, >, + LastKnownRequestProcessed (dpyinfo->display))) break; } @@ -23061,7 +23081,14 @@ x_clean_failable_requests (struct x_display_info *dpyinfo) static void x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) { - unsigned long *request, *max; + struct x_failable_request *request, *max; + + if ((dpyinfo->next_failable_request + != dpyinfo->failable_requests) + && (dpyinfo->next_failable_request - 1)->end == 0) + /* A new sequence should never be started before an old one + finishes. Use `x_catch_errors' to nest error handlers. */ + emacs_abort (); request = dpyinfo->next_failable_request; max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS; @@ -23071,7 +23098,7 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) /* There is no point in making this extra sync if all requests are known to have been fully processed. */ if ((LastKnownRequestProcessed (dpyinfo->display) - != NextRequest (dpyinfo->display) - 1)) + != XNextRequest (dpyinfo->display) - 1)) XSync (dpyinfo->display, False); x_clean_failable_requests (dpyinfo); @@ -23083,10 +23110,21 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) function. */ emacs_abort (); - *request = NextRequest (dpyinfo->display); + request->start = XNextRequest (dpyinfo->display); + request->end = 0; + dpyinfo->next_failable_request++; } +static void +x_stop_ignoring_errors (struct x_display_info *dpyinfo) +{ + struct x_failable_request *range; + + range = dpyinfo->next_failable_request - 1; + range->end = XNextRequest (dpyinfo->display) - 1; +} + /* Undo the last x_catch_errors call. DPY should be the display that was passed to x_catch_errors. @@ -23134,10 +23172,10 @@ x_uncatch_errors (void) /* There is no point in making this extra sync if all requests are known to have been fully processed. */ && (LastKnownRequestProcessed (x_error_message->dpy) - != NextRequest (x_error_message->dpy) - 1) + != XNextRequest (x_error_message->dpy) - 1) /* Likewise if no request was made since the trap was installed. */ - && (NextRequest (x_error_message->dpy) + && (XNextRequest (x_error_message->dpy) > x_error_message->first_request)) { XSync (x_error_message->dpy, False); @@ -23171,8 +23209,8 @@ x_check_errors (Display *dpy, const char *format) /* There is no point in making this extra sync if all requests are known to have been fully processed. */ if ((LastKnownRequestProcessed (dpy) - != NextRequest (dpy) - 1) - && (NextRequest (dpy) + != XNextRequest (dpy) - 1) + && (XNextRequest (dpy) > x_error_message->first_request)) XSync (dpy, False); @@ -23206,8 +23244,8 @@ x_had_errors_p (Display *dpy) /* Make sure to catch any errors incurred so far. */ if ((LastKnownRequestProcessed (dpy) - != NextRequest (dpy) - 1) - && (NextRequest (dpy) + != XNextRequest (dpy) - 1) + && (XNextRequest (dpy) > x_error_message->first_request)) XSync (dpy, False); @@ -23471,7 +23509,7 @@ x_error_handler (Display *display, XErrorEvent *event) { struct x_error_message_stack *stack; struct x_display_info *dpyinfo; - unsigned long *fail, *last; + struct x_failable_request *fail, *last; #if defined USE_GTK && defined HAVE_GTK3 if ((event->error_code == BadMatch @@ -23488,13 +23526,17 @@ x_error_handler (Display *display, XErrorEvent *event) if (fail) { - /* Now that this request has been handled, remove it from - the list of requests that can fail. */ - last = dpyinfo->next_failable_request; - memmove (&dpyinfo->failable_requests, fail, - sizeof *fail * (last - fail)); - dpyinfo->next_failable_request = (dpyinfo->failable_requests - + (last - fail)); + /* Now that this request sequence has been fully handled, + remove it from the list of requests that can fail. */ + + if (event->serial == fail->end) + { + last = dpyinfo->next_failable_request; + memmove (&dpyinfo->failable_requests, fail, + sizeof *fail * (last - fail)); + dpyinfo->next_failable_request = (dpyinfo->failable_requests + + (last - fail)); + } return 0; } @@ -24882,11 +24924,9 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) &deviceid)) { x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f)); - - XIWarpPointer (FRAME_X_DISPLAY (f), - deviceid, None, - FRAME_X_WINDOW (f), - 0, 0, 0, 0, pix_x, pix_y); + XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None, + FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y); + x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f)); } } else @@ -25025,6 +25065,7 @@ x_focus_frame (struct frame *f, bool noactivate) x_ignore_errors_for_next_request (dpyinfo); XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), RevertToParent, CurrentTime); + x_stop_ignoring_errors (dpyinfo); if (!noactivate) x_ewmh_activate_frame (f); diff --git a/src/xterm.h b/src/xterm.h index eee7672426..7c09073d76 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -261,6 +261,16 @@ struct xi_device_t Status x_parse_color (struct frame *f, const char *color_name, XColor *color); +struct x_failable_request +{ + /* The first request making up this sequence. */ + unsigned long start; + + /* If this is zero, then the request has not yet been made. + Otherwise, this is the request that ends this sequence. */ + unsigned long end; +}; + /* For each X display, we have a structure that records information about it. */ @@ -746,12 +756,12 @@ struct x_display_info int screen_mm_width; int screen_mm_height; - /* Circular buffer of request serials to ignore inside an error - handler in increasing order. */ - unsigned long failable_requests[N_FAILABLE_REQUESTS]; + /* Circular buffer of request serial ranges to ignore inside an + error handler in increasing order. */ + struct x_failable_request failable_requests[N_FAILABLE_REQUESTS]; /* Pointer to the next request in `failable_requests'. */ - unsigned long *next_failable_request; + struct x_failable_request *next_failable_request; }; #ifdef HAVE_X_I18N commit 59d109b73c48ca41d240f1fbe10f7349e9df4e31 Author: Po Lu Date: Sat Jul 2 21:21:33 2022 +0800 Fix display disconnect when tooltip frame is alive * src/xterm.c (x_connection_closed): Don't dereference nil when loop finds a tooltip frame. diff --git a/src/xterm.c b/src/xterm.c index 2629997f2a..0c695324f3 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -23280,6 +23280,7 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) Emacs_XIOErrorHandler io_error_handler; xm_drop_start_message dmsg; struct frame *f; + Lisp_Object minibuf_frame, tmp; dpyinfo = x_display_info_for_display (dpy); error_msg = alloca (strlen (error_message) + 1); @@ -23379,9 +23380,14 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) that are on the dead display. */ FOR_EACH_FRAME (tail, frame) { - Lisp_Object minibuf_frame; + /* Tooltip frames don't have these, so avoid crashing. */ + + if (FRAME_TOOLTIP_P (XFRAME (frame))) + continue; + minibuf_frame = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame)))); + if (FRAME_X_P (XFRAME (frame)) && FRAME_X_P (XFRAME (minibuf_frame)) && ! EQ (frame, minibuf_frame) @@ -23432,11 +23438,8 @@ For details, see etc/PROBLEMS.\n", /* We have just closed all frames on this display. */ emacs_abort (); - { - Lisp_Object tmp; - XSETTERMINAL (tmp, dpyinfo->terminal); - Fdelete_terminal (tmp, Qnoelisp); - } + XSETTERMINAL (tmp, dpyinfo->terminal); + Fdelete_terminal (tmp, Qnoelisp); } unblock_input (); commit e0488f89d1712ce905f9040e6b26fdf0a4a0666d Author: Gregory Heytings Date: Sat Jul 2 15:40:45 2022 +0200 Command for global adjustments to the default face * lisp/face-remap.el (global-text-scale-adjust): New command. (text-scale-adjust): Refer to the new related command. (global-text-scale-adjust-resizes-frames): New user option. * lisp/mwheel.el (mouse-wheel-scroll-amount): Add the new command to the mouse wheel scrolling events. (mouse-wheel-global-text-scale): New function. (mouse-wheel-mode): Use the new function with mouse-wheel-mode. * doc/emacs/display.texi (Text Scale): Document the new command and the new user option. * etc/NEWS: Mention the new command and its bindings, and the new user option. diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index fbff1d4eb6..5e4728c8da 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -893,6 +893,22 @@ of 1.2; to change this factor, customize the variable to the @code{text-scale-adjust} command restores the default height, the same as typing @kbd{C-x C-0}. +@cindex ajust global font size +@findex global-text-scale-adjust +@kindex C-x C-M-+ +@kindex C-x C-M-= +@kindex C-x C-M-- +@kindex C-x C-M-0 +@kindex C-M-wheel-down +@kindex C-M-wheel-up + Similarly, to change the sizes of the fonts globally, type @kbd{C-x +C-M-+}, @kbd{C-x C-M-=}, @kbd{C-x C-M--} or @kbd{C-x C-M-0}, or scroll +the mouse wheel with both the @kbd{Ctrl} and @kbd{Meta} modifiers +pressed. To enable frame resizing when the font size is changed +globally, customize the variable +@code{global-text-scale-adjust-resizes-frames} (@pxref{Easy +Customization}). + @cindex increase buffer font size @findex text-scale-increase @cindex decrease buffer font size diff --git a/etc/NEWS b/etc/NEWS index 4b3a02b2e0..773e0849c2 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -324,6 +324,18 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 ++++ +** New command to change the fond sized globally. +To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to +decrease it, type 'C-x C-M--'; to restore the font size, type 'C-x +C-M-0'. The final key in these commands may be repeated without the +leading 'C-x' and without the modifiers, e.g. 'C-x C-M-+ C-M-+ C-M-+' +and 'C-x C-M-+ + +' increase the font size by three steps. When +mouse-wheel-mode is enabled, 'C-M-wheel-up' and 'C-M-wheel-down' also +increase and decrease the font size globally. Additionally, the +variable 'global-text-scale-adjust-resizes-frames' controls whether +the frames are resized when the font size is changed. + ** New config variable 'syntax-wholeline-max' to reduce the cost of long lines. This variable is used by some operations (mostly syntax-propertization and font-locking) to treat lines longer than this variable as if they diff --git a/lisp/face-remap.el b/lisp/face-remap.el index d611671408..bfc138b043 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -394,7 +394,9 @@ a top-level keymap, `text-scale-increase' or Most faces are affected by these font size changes, but not faces that have an explicit `:height' setting. The two exceptions to this are the `default' and `header-line' faces: they will both be -scaled even if they have an explicit `:height' setting." +scaled even if they have an explicit `:height' setting. + +See also the related command `global-text-scale-adjust'." (interactive "p") (let ((ev last-command-event) (echo-keystrokes nil)) @@ -445,6 +447,82 @@ scaled even if they have an explicit `:height' setting." (+ text-scale--pinch-start-scale (round (log scale text-scale-mode-step))))))) +(defcustom global-text-scale-adjust-resizes-frames nil + "Whether `global-text-scale-adjust' resizes the frames." + :type '(choice (const :tag "Off" nil) + (const :tag "On" t)) + :group 'display + :version "28.1") + +(defcustom global-text-scale-adjust-limits '(10 . 500) + "Min/max values for `global-text-scale-adjust'. +This is a cons cell where the `car' has the minimum font size and +the `cdr' has the max font size." + :version "29.1" + :group 'display + :type '(cons (integer :tag "Min") + (integer :tag "Max"))) + +(defvar global-text-scale-adjust--default-height nil) + +;;;###autoload (define-key ctl-x-map [(control meta ?+)] 'global-text-scale-adjust) +;;;###autoload (define-key ctl-x-map [(control meta ?=)] 'global-text-scale-adjust) +;;;###autoload (define-key ctl-x-map [(control meta ?-)] 'global-text-scale-adjust) +;;;###autoload (define-key ctl-x-map [(control meta ?0)] 'global-text-scale-adjust) +;;;###autoload +(defun global-text-scale-adjust (increment) + "Globally adjust the font size by INCREMENT. + +Interactively, INCREMENT may be passed as a numeric prefix argument. + +The adjustment made depends on the final component of the key binding +used to invoke the command, with all modifiers removed: + + +, = Globally increase the height of the default face + - Globally decrease the height of the default face + 0 Globally reset the height of the default face + +After adjusting, further adjust the font size as long as the key, +with all modifiers removed, is one of the above characters. + +Buffer-local face adjustements have higher priority than global +face adjustments. + +The variable `global-text-scale-adjust-resizes-frames' controls +whether the frames are resized to keep the same number of lines +and characters per line when the font size is adjusted. + +See also the related command `text-scale-adjust'." + (interactive "p") + (when (display-graphic-p) + (unless global-text-scale-adjust--default-height + (setq global-text-scale-adjust--default-height + (face-attribute 'default :height))) + (let* ((key (event-basic-type last-command-event)) + (echo-keystrokes nil) + (cur (face-attribute 'default :height)) + (inc + (pcase key + (?- (* (- increment) 5)) + (?0 (- global-text-scale-adjust--default-height cur)) + (_ (* increment 5)))) + (new (+ cur inc))) + (when (< (car global-text-scale-adjust-limits) + new + (cdr global-text-scale-adjust-limits)) + (let ((frame-inhibit-implied-resize + (not global-text-scale-adjust-resizes-frames))) + (set-face-attribute 'default nil :height new))) + (when (characterp key) + (message "Use +,-,0 for further adjustment") + (set-transient-map + (let ((map (make-sparse-keymap))) + (dolist (mod '(() (control meta))) + (dolist (key '(?+ ?= ?- ?0)) + (define-key map (vector (append mod (list key))) + 'global-text-scale-adjust))) + map)))))) + ;; ---------------------------------------------------------------- ;; buffer-face-mode diff --git a/lisp/mwheel.el b/lisp/mwheel.el index 9a92d42cc0..7963eaf4a4 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -41,6 +41,17 @@ (require 'timer) (defvar mouse-wheel-mode) + +(defun mouse-wheel-global-text-scale (event) + "Increase or decrease the global font size according to the EVENT." + (interactive (list last-input-event)) + (let ((button (mwheel-event-button event))) + (unwind-protect + (cond ((eq button mouse-wheel-down-event) + (global-text-scale-adjust 1)) + ((eq button mouse-wheel-up-event) + (global-text-scale-adjust -1)))))) + (defvar mouse-wheel--installed-bindings-alist nil "Alist of all installed mouse wheel key bindings.") @@ -113,7 +124,10 @@ set to the event sent when clicking on the mouse wheel button." :type 'number) (defcustom mouse-wheel-scroll-amount - '(1 ((shift) . hscroll) ((meta) . nil) ((control) . text-scale)) + '(1 ((shift) . hscroll) + ((meta) . nil) + ((control meta) . global-text-scale) + ((control) . text-scale)) "Amount to scroll windows by when spinning the mouse wheel. This is an alist mapping the modifier key to the amount to scroll when the wheel is moved with the modifier key depressed. @@ -489,6 +503,10 @@ an event used for scrolling, such as `mouse-wheel-down-event'." (when event (mouse-wheel--add-binding `[,(list (caar binding) event)] 'mouse-wheel-text-scale)))) + ((and (consp binding) (eq (cdr binding) 'global-text-scale)) + (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event)) + (mouse-wheel--add-binding `[,(append (car binding) (list event))] + 'mouse-wheel-global-text-scale))) ;; Bindings for scrolling. (t (dolist (event (list mouse-wheel-down-event mouse-wheel-up-event commit b2670bfe42b8eb4f7aa811ddbb67e0e3995acc90 Author: Lars Ingebrigtsen Date: Sat Jul 2 15:22:13 2022 +0200 Add a comment about buffer_local_value/find_symbol_value * src/data.c: Note that buffer_local_value is very similar (bug#48281). diff --git a/src/data.c b/src/data.c index 1dbec4687b..568349ba83 100644 --- a/src/data.c +++ b/src/data.c @@ -1546,8 +1546,13 @@ swap_in_symval_forwarding (struct Lisp_Symbol *symbol, struct Lisp_Buffer_Local_ /* Find the value of a symbol, returning Qunbound if it's not bound. This is helpful for code which just wants to get a variable's value if it has one, without signaling an error. - Note that it must not be possible to quit - within this function. Great care is required for this. */ + + This function is very similar to buffer_local_value, but we have + two separate code paths here since find_symbol_value has to be very + efficient, while buffer_local_value doesn't have to be. + + Note that it must not be possible to quit within this function. + Great care is required for this. */ Lisp_Object find_symbol_value (Lisp_Object symbol) commit 8b52d9f5f177ce76b9ebecadd70c6dbbf07a20c6 Author: Lars Ingebrigtsen Date: Sat Jul 2 15:06:24 2022 +0200 Allow NUL characters in JSON input * src/json.c (Fjson_parse_string, Fjson_parse_buffer): Allow NUL characters in JSON (bug#48274). diff --git a/src/json.c b/src/json.c index 763f463aa4..9a455f507b 100644 --- a/src/json.c +++ b/src/json.c @@ -975,7 +975,7 @@ usage: (json-parse-string STRING &rest ARGS) */) json_error_t error; json_t *object - = json_loads (SSDATA (encoded), JSON_DECODE_ANY, &error); + = json_loads (SSDATA (encoded), JSON_DECODE_ANY | JSON_ALLOW_NUL, &error); if (object == NULL) json_parse_error (&error); @@ -1071,7 +1071,9 @@ usage: (json-parse-buffer &rest args) */) json_error_t error; json_t *object = json_load_callback (json_read_buffer_callback, &data, - JSON_DECODE_ANY | JSON_DISABLE_EOF_CHECK, + JSON_DECODE_ANY + | JSON_DISABLE_EOF_CHECK + | JSON_ALLOW_NUL, &error); if (object == NULL) diff --git a/test/src/json-tests.el b/test/src/json-tests.el index f3dfeea30b..3560e1abc9 100644 --- a/test/src/json-tests.el +++ b/test/src/json-tests.el @@ -187,8 +187,11 @@ (ert-deftest json-parse-string/null () (skip-unless (fboundp 'json-parse-string)) (should-error (json-parse-string "\x00") :type 'wrong-type-argument) - ;; FIXME: Reconsider whether this is the right behavior. - (should-error (json-parse-string "[\"a\\u0000b\"]") :type 'json-parse-error)) + (should (json-parse-string "[\"a\\u0000b\"]")) + (let* ((string "{\"foo\":\"this is a string including a literal \\u0000\"}") + (data (json-parse-string string))) + (should (hash-table-p data)) + (should (equal string (json-serialize data))))) (ert-deftest json-parse-string/invalid-unicode () "Some examples from commit 5b112482fbdb0351487a7af592ae901e20ec45c1 Author: Lars Ingebrigtsen Date: Sat Jul 2 14:21:00 2022 +0200 Make comint-watch-for-password-prompt more resilient * lisp/comint.el (comint-watch-for-password-prompt): Don't try to send commands to the process after it's exited (bug#56336). (This commonly happens when invoked via `M-&'.) diff --git a/lisp/comint.el b/lisp/comint.el index 3da61fb992..92262eab32 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -2515,8 +2515,9 @@ This function could be in the list `comint-output-filter-functions'." (1+ comint--prompt-recursion-depth))) (if (> comint--prompt-recursion-depth 10) (message "Password prompt recursion too deep") - (comint-send-invisible - (string-trim string "[ \n\r\t\v\f\b\a]+" "\n+")))))) + (when (get-buffer-process (current-buffer)) + (comint-send-invisible + (string-trim string "[ \n\r\t\v\f\b\a]+" "\n+"))))))) (current-buffer)))) ;; Low-level process communication commit 8d68760ddee3690b4312fdb5d85210cb21b4eb7d Author: Mattias Engdegård Date: Sat Jul 2 12:01:18 2022 +0200 ; Fix typos. diff --git a/admin/nt/dist-build/README-scripts b/admin/nt/dist-build/README-scripts index 6b1adbe03e..e99fbe0706 100644 --- a/admin/nt/dist-build/README-scripts +++ b/admin/nt/dist-build/README-scripts @@ -131,7 +131,7 @@ The process is the same as for building from the master branch, except that the release branch should already exist as a worktree, and the version number must be added to the command line with `build-zips.sh -V 27 -s`. The final zips will be named after the branch rather than -the version (e.g emacs-27-2019-12-26.zip) rather than than the Emacs +the version (e.g emacs-27-2019-12-26.zip) rather than the Emacs version (e.g emacs-27.0.50.zip). diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index e85d492bbb..81799a2a57 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -8551,7 +8551,7 @@ displayed in the echo area. @vindex use-system-tooltips When Emacs is built with the GTK+ toolkit or Haiku windowing support, it by default displays tooltips using toolkit functions, and the -appearance of the tooltips is then controlled by by the toolkit's +appearance of the tooltips is then controlled by the toolkit's settings. Toolkit-provided tooltips can be disabled by changing the value of the variable @code{use-system-tooltips} to @code{nil}. The rest of this subsection describes how to control non-toolkit tooltips, diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index 00a1fe05fd..54fc16ec9f 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -728,7 +728,7 @@ variables to control this: The value of this constant is a regexp that matches autoload cookies. @code{loaddefs-generate} copies the Lisp form that follows the cookie into the autoload file it generates. This will match comments -like like @samp{;;;###autoload} and @samp{;;;###calc-autoload}. +like @samp{;;;###autoload} and @samp{;;;###calc-autoload}. @end defvar @defvar generated-autoload-file diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 14856b9e05..80c371e1c6 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3547,7 +3547,7 @@ and @code{#x1c} @code{#x28} to @w{@code{(3 5 10 11 12)}}. @item fill @var{len} @var{len} bytes used as a mere filler. In packing, these bytes are -are left unchanged, which normally means they remain zero. +left unchanged, which normally means they remain zero. When unpacking, this just returns nil. @item align @var{len} diff --git a/etc/tutorials/TUTORIAL.nl b/etc/tutorials/TUTORIAL.nl index 2ec3fac11b..7aaed218ff 100644 --- a/etc/tutorials/TUTORIAL.nl +++ b/etc/tutorials/TUTORIAL.nl @@ -1158,7 +1158,7 @@ overeenkomende commandonaam zoals find-file. -------------------- Je kunt meer over Emacs leren door haar handleiding te lezen. Deze is -zowel als boek als in in Emacs beschikbaar (gebruik het Help menu of +zowel als boek als in Emacs beschikbaar (gebruik het Help menu of tik C-h r). Kijk bijvoorbeeld eens naar "completion", wat minder tikwerk oplevert, of "dired" wat het omgaan met bestanden vereenvoudigt. diff --git a/lisp/allout.el b/lisp/allout.el index 4624c236f5..de8ee85b39 100644 --- a/lisp/allout.el +++ b/lisp/allout.el @@ -26,7 +26,7 @@ ;;; Commentary: ;; Allout outline minor mode provides extensive outline formatting and -;; and manipulation beyond standard Emacs outline mode. Some features: +;; manipulation beyond standard Emacs outline mode. Some features: ;; ;; - Classic outline-mode topic-oriented navigation and exposure adjustment ;; - Topic-oriented editing including coherent topic and subtopic diff --git a/lisp/calc/calc-prog.el b/lisp/calc/calc-prog.el index dc2a086bbd..ec30ee7e0f 100644 --- a/lisp/calc/calc-prog.el +++ b/lisp/calc/calc-prog.el @@ -1949,7 +1949,7 @@ Redefine the corresponding command." ;; The variable math-exp-env is local to math-define-body, but is ;; used by math-define-exp, which is called (indirectly) by -;; by math-define-body. +;; math-define-body. (defvar math-exp-env) (defun math-define-body (body exp-env) diff --git a/lisp/cedet/semantic/edit.el b/lisp/cedet/semantic/edit.el index 76230d438a..4679500ed9 100644 --- a/lisp/cedet/semantic/edit.el +++ b/lisp/cedet/semantic/edit.el @@ -610,7 +610,7 @@ This function is for internal use by `semantic-edits-incremental-parser'." (setq last-cond "Beginning of buffer") (setq parse-start ;; Don't worry about parents since - ;; there there would be an exact + ;; there would be an exact ;; match in the tag list otherwise ;; and the routine would fail. (point-min) diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el index 57e59f4e9f..4bdaaf77ac 100644 --- a/lisp/cedet/semantic/lex-spp.el +++ b/lisp/cedet/semantic/lex-spp.el @@ -1074,7 +1074,7 @@ and variable state from the current buffer." )) ;; Second Cheat: copy key variables regarding macro state from the - ;; the originating buffer we are parsing. We need to do this every time + ;; originating buffer we are parsing. We need to do this every time ;; since the state changes. (dolist (V important-vars) (set V (buffer-local-value V origbuff))) diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index f35362b371..c3a4e9fc7a 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -408,7 +408,7 @@ or call the function `%s'.")))) No problems result if this variable is not bound. `add-hook' automatically binds it. (This is true for all hook variables.)" modefun))) - ;; Allow using using `M-x customize-variable' on the hook. + ;; Allow using `M-x customize-variable' on the hook. (put ',hook 'custom-type 'hook) (put ',hook 'standard-value (list nil)) diff --git a/lisp/env.el b/lisp/env.el index a630bf120f..a35383a13b 100644 --- a/lisp/env.el +++ b/lisp/env.el @@ -225,7 +225,7 @@ VARIABLES is a list of variable settings of the form (VAR VALUE), where VAR is the name of the variable (a string) and VALUE is its value (also a string). -The previous values will be be restored upon exit." +The previous values will be restored upon exit." (declare (indent 1) (debug (sexp body))) (unless (consp variables) (error "Invalid VARIABLES: %s" variables)) diff --git a/lisp/font-lock.el b/lisp/font-lock.el index 7eeaf2f547..206879b169 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -2361,7 +2361,7 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item." ;; e.g. assembler code and GNU linker script in Linux kernel. ;; `cpp-font-lock-keywords' is handy for modes for the files. ;; -;; Here we cannot use `regexp-opt' because because regex-opt is not preloaded +;; Here we cannot use `regexp-opt' because regex-opt is not preloaded ;; while font-lock.el is preloaded to emacs. So values pre-calculated with ;; regexp-opt are used here. diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index b108788571..27b725b0aa 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -711,7 +711,7 @@ FACTOR is the multiplication factor for the size." (interactive) (message (substitute-command-keys - "Zoom with with \\\\[emoji-zoom-increase] and \\[emoji-zoom-decrease]")) + "Zoom with \\\\[emoji-zoom-increase] and \\[emoji-zoom-decrease]")) (set-transient-map emoji-zoom-map t) (let* ((factor (or factor 1.1)) (old (get-text-property (point) 'face)) diff --git a/lisp/mail/unrmail.el b/lisp/mail/unrmail.el index 8ce5afa962..9e7194e4a0 100644 --- a/lisp/mail/unrmail.el +++ b/lisp/mail/unrmail.el @@ -208,7 +208,7 @@ The variable `unrmail-mbox-format' controls which mbox format to use." (setq mail-from (or (let ((from (mail-fetch-field "Mail-From"))) ;; mail-mbox-from (below) returns a ;; string that ends in a newline, but - ;; but mail-fetch-field does not, so + ;; mail-fetch-field does not, so ;; we append a newline here. (if from (format "%s\n" from))) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 9ffaff7c8e..69a10ce4e2 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2135,7 +2135,7 @@ and with BASE-SIZE appended as the last element." (lambda (elem) (let ((str ;; Don't modify the string itself, but a copy, since the - ;; the string may be read-only or used for other purposes. + ;; string may be read-only or used for other purposes. ;; Furthermore, since `completions' may come from ;; display-completion-list, `elem' may be a list. (if (consp elem) diff --git a/lisp/mouse.el b/lisp/mouse.el index 98e49c3598..ddcb51aecf 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -1200,7 +1200,7 @@ frame with the mouse." (<= (- right parent-right) snap-width) snap-x (<= (- last-x snap-x) snap-width)) ;; Stay snapped when the mouse moved rightward but - ;; not more more than `snap-width' pixels from the + ;; not more than `snap-width' pixels from the ;; time FRAME snapped. (setq left (- parent-right native-width))) (t @@ -1222,7 +1222,7 @@ frame with the mouse." (<= (- parent-top top) snap-width) snap-y (<= (- snap-y last-y) snap-width)) ;; Stay snapped when the mouse moved upward but - ;; not more more than `snap-width' pixels from the + ;; not more than `snap-width' pixels from the ;; time FRAME snapped. (setq top parent-top)) (t @@ -1244,7 +1244,7 @@ frame with the mouse." (<= (- bottom parent-bottom) snap-width) snap-y (<= (- last-y snap-y) snap-width)) ;; Stay snapped when the mouse moved downward but - ;; not more more than `snap-width' pixels from the + ;; not more than `snap-width' pixels from the ;; time FRAME snapped. (setq top (- parent-bottom native-height))) (t diff --git a/lisp/nxml/nxml-parse.el b/lisp/nxml/nxml-parse.el index ff9eda3fd2..56ba4480bf 100644 --- a/lisp/nxml/nxml-parse.el +++ b/lisp/nxml/nxml-parse.el @@ -246,7 +246,7 @@ same way as well-formedness error." parsed-attributes))) (setq atts (cdr atts))) ;; We want to end up with the attributes followed by the - ;; the namespace attributes in the same order as + ;; namespace attributes in the same order as ;; xmltok-attributes and xmltok-namespace-attributes respectively. (when parsed-namespace-attributes (setq parsed-attributes diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index e571cee83c..f51d2fcb11 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -1322,7 +1322,7 @@ name, and one for the discovery of a following BLOCK.") ,cperl--ws+-rx (group-n 2 ,cperl--normal-identifier-rx)) "A regular expression to detect a subroutine start. -Contains three groups: One one to distinguish lexical from +Contains three groups: One to distinguish lexical from \"normal\" subroutines, for the keyword \"sub\", and one for the subroutine name.") diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el index edb53793e6..f55e3449e4 100644 --- a/lisp/progmodes/idlwave.el +++ b/lisp/progmodes/idlwave.el @@ -3247,7 +3247,7 @@ ignored." ;; In the following while statements, after one iteration ;; point will be at the beginning of a line in which case ;; the while will not be executed for the - ;; the first paragraph line and thus will not affect the + ;; first paragraph line and thus will not affect the ;; indentation. ;; ;; First check to see if indentation is based on hanging indent. diff --git a/lisp/ps-print.el b/lisp/ps-print.el index 8df5204fa1..069d116907 100644 --- a/lisp/ps-print.el +++ b/lisp/ps-print.el @@ -6415,7 +6415,7 @@ If FACE is not a valid face name, use default face." (ps-end-job needs-begin-file) ;; Setting this variable tells the unwind form that the - ;; the PostScript was generated without error. + ;; PostScript was generated without error. (setq completed-safely t)) ;; Unwind form: If some bad mojo occurred while generating diff --git a/lisp/textmodes/texnfo-upd.el b/lisp/textmodes/texnfo-upd.el index 5b468dc808..e44aa06e3d 100644 --- a/lisp/textmodes/texnfo-upd.el +++ b/lisp/textmodes/texnfo-upd.el @@ -1367,7 +1367,7 @@ left at the end of the node line." ;; There may be an @chapter or other such command between ;; the top node line and the next node line, as a title ;; for an `ifinfo' section. This @chapter command must - ;; must be skipped. So the procedure is to search for + ;; be skipped. So the procedure is to search for ;; the next `@node' line, and then copy its name. (if (re-search-forward "^@node" nil t) (progn diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 98f21ce9a5..240f99effc 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -1697,7 +1697,7 @@ cleaning up these problems." (rstart (min start end)) (rend (max start end)) ;; Fall back to whitespace-style so we can run before - ;; before the mode is active. + ;; the mode is active. (style (copy-sequence (or whitespace-active-style whitespace-style))) (bogus-list diff --git a/src/lread.c b/src/lread.c index 66b1391646..ef2bb036e3 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4877,7 +4877,7 @@ oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff /* Like 'oblookup', but considers 'Vread_symbol_shorthands', potentially recognizing that IN is shorthand for some other - longhand name, which is then then placed in OUT. In that case, + longhand name, which is then placed in OUT. In that case, memory is malloc'ed for OUT (which the caller must free) while SIZE_OUT and SIZE_BYTE_OUT respectively hold the character and byte sizes of the transformed symbol name. If IN is not recognized diff --git a/src/print.c b/src/print.c index d562500b61..4d7e42df1e 100644 --- a/src/print.c +++ b/src/print.c @@ -727,7 +727,7 @@ Optional argument OVERRIDES should be a list of settings for print-related variables. An element in this list can be the symbol t, which means "reset all the values to their defaults". Otherwise, an element should be a pair, where the `car' or the pair is the setting symbol, and the `cdr' is the -value of of the setting to use for this `prin1' call. +value of the setting to use for this `prin1' call. For instance: commit c5aec9b10d709b91a0188b705b653bd2a59fff2d Author: Michael Albinus Date: Sat Jul 2 13:19:04 2022 +0200 Preserve connection-local settings in dired * lisp/dired-aux.el (dired-shell-command): Preserve connection-local settings. (Bug#56333) diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 095f800170..c403cc5cbd 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -1056,18 +1056,19 @@ Return the result of `process-file' - zero for success." (dir default-directory)) (with-current-buffer (get-buffer-create out-buffer) (erase-buffer) - (let* ((default-directory dir) - (res (process-file - shell-file-name - nil - t - nil - shell-command-switch - cmd))) - (dired-uncache dir) - (unless (zerop res) - (pop-to-buffer out-buffer)) - res)))) + (let ((default-directory dir) res) + (with-connection-local-variables + (setq res (process-file + shell-file-name + nil + t + nil + shell-command-switch + cmd)) + (dired-uncache dir) + (unless (zerop res) + (pop-to-buffer out-buffer)) + res))))) ;;; Commands that delete or redisplay part of the dired buffer commit 05d240997aeb6ffe3db21e7f4c8e2f181edc37b6 Author: Lars Ingebrigtsen Date: Sat Jul 2 12:59:41 2022 +0200 Add native-compile-prune-cache command * lisp/emacs-lisp/comp.el (native-compile-prune-cache): New command (bug#48108). diff --git a/etc/NEWS b/etc/NEWS index 30404cc13c..4b3a02b2e0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -148,8 +148,15 @@ This is run at the end of the Emacs startup process, and is meant to be used to reinitialize structures that would normally be done at load time. +** Native Compilation + +--- +*** New command 'native-compile-prune-cache'. +This command deletes older .eln cache entries (but not the ones for +the current Emacs version). + --- -** New function 'startup-redirect-eln-cache'. +*** New function 'startup-redirect-eln-cache'. This function can be called in your init files to change the user-specific directory where Emacs stores the "*.eln" files produced by native compilation of Lisp packages Emacs loads. The default diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 4ce2ce75e1..2109aa9923 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -4288,6 +4288,30 @@ of (commands) to run simultaneously." (let ((load (not (not load)))) (native--compile-async files recursively load selector))) +(defun native-compile-prune-cache () + "Remove .eln files that aren't applicable to the current Emacs invocation." + (interactive) + (dolist (dir native-comp-eln-load-path) + ;; If a directory is non absolute it is assumed to be relative to + ;; `invocation-directory'. + (setq dir (expand-file-name dir invocation-directory)) + (when (file-exists-p dir) + (dolist (subdir (directory-files dir t)) + (when (and (file-directory-p subdir) + (file-writable-p subdir) + (not (equal (file-name-nondirectory + (directory-file-name subdir)) + comp-native-version-dir))) + (message "Deleting %s..." subdir) + ;; We're being overly cautious here -- there shouldn't be + ;; anything but .eln files in these directories. + (dolist (eln (directory-files subdir t "\\.eln\\(\\.tmp\\)?\\'")) + (when (file-writable-p eln) + (delete-file eln))) + (when (directory-empty-p subdir) + (delete-directory subdir)))))) + (message "Cache cleared")) + (provide 'comp) ;; LocalWords: limplified limplified limplification limplify Limple LIMPLE libgccjit elc eln commit 14d4d63c8c18df9a4333fe19eeb4764030df71a4 Author: Lars Ingebrigtsen Date: Sat Jul 2 12:54:14 2022 +0200 native-comp-eln-load-path doc string fix * src/comp.c (syms_of_comp): Fix grammar in doc string. diff --git a/src/comp.c b/src/comp.c index 0c78e60fc4..81d27299fa 100644 --- a/src/comp.c +++ b/src/comp.c @@ -5781,7 +5781,7 @@ For internal use. */); DEFVAR_LISP ("native-comp-eln-load-path", Vnative_comp_eln_load_path, doc: /* List of eln cache directories. -If a directory is non absolute is assumed to be relative to +If a directory is non absolute it is assumed to be relative to `invocation-directory'. `comp-native-version-dir' value is used as a sub-folder name inside each eln cache directory. commit e390396e684c99b4b0b27aa2e0bc1822d8854550 Author: Stefan Kangas Date: Sat Jul 2 10:38:57 2022 +0200 Doc fixes; don't use obsolete names * etc/compilation.txt: * lisp/mh-e/mh-funcs.el (mh-kill-folder): Don't use obsolete names. diff --git a/etc/compilation.txt b/etc/compilation.txt index b74a275043..0007e1f8bc 100644 --- a/etc/compilation.txt +++ b/etc/compilation.txt @@ -421,7 +421,7 @@ symbol: oracle This stupid precompiler wraps lines at column 80 in the middle of a file name. There is no obvious way of detecting this or turning it off. But if you -delete the newline (probably needs M-x toggle-read-only), the file name will +delete the newline (probably needs M-x read-only-mode), the file name will automatically be reparsed, so that you can then go there. Semantic error at line 528, column 5, file erosacqdb.pc: diff --git a/lisp/mh-e/mh-funcs.el b/lisp/mh-e/mh-funcs.el index 8a8922b77c..ccb1688510 100644 --- a/lisp/mh-e/mh-funcs.el +++ b/lisp/mh-e/mh-funcs.el @@ -95,9 +95,9 @@ RANGE is read in interactive use." Remove all of the messages (files) within the current folder, and then remove the folder (directory) itself. -Run the abnormal hook `mh-kill-folder-suppress-prompt-hooks'. The -hook functions are called with no arguments and should return a -non-nil value to suppress the normal prompt when you remove a +Run the abnormal hook `mh-kill-folder-suppress-prompt-functions'. +The hook functions are called with no arguments and should return +a non-nil value to suppress the normal prompt when you remove a folder. This is useful for folders that are easily regenerated." (interactive) (if (or (run-hook-with-args-until-success commit c85f7c2e8ae6a0c3661f4483cc795a08ebca7c1e Author: Stefan Kangas Date: Sat Jul 2 11:36:50 2022 +0200 Don't refer to obsolete alias for insert-char * lisp/leim/quail/persian.el: Don't refer to obsolete alias for insert-char. diff --git a/lisp/leim/quail/persian.el b/lisp/leim/quail/persian.el index 61428c94f0..07d006c2a4 100644 --- a/lisp/leim/quail/persian.el +++ b/lisp/leim/quail/persian.el @@ -23,7 +23,7 @@ ;; along with GNU Emacs. If not, see . ;;; Commentary: -;; + ;; This file contains a collection of input methods for ;; Persian languages (Farsi, Urdu, Pashto/Afghanic, ...) ;; @@ -402,7 +402,7 @@ ;;;;;;;;;;; isiri-6219 Table 6 -- جدول ۶ - حروِفِ عربی ("F" ?إ) - ("D" ?\u0671) ;; (ucs-insert #x0671)ٱ named: حرفِ الفِ وصل + ("D" ?\u0671) ;; (insert-char #x0671)ٱ named: حرفِ الفِ وصل ("K" ?ك) ;; Arabic kaf ("Th" ?ة) ;; ta marbuteh ("Y" ?ي) @@ -421,40 +421,40 @@ ("8" ?۸) ("9" ?۹) - ("\\/" ?\u066B) ;; (ucs-insert #x066B)٫ named: ممیزِ فارسی - ("\\," ?\u066C) ;; (ucs-insert #x066C)٬ named: جداکننده‌ی هزارهای فارسی - ("%" ?\u066A) ;; (ucs-insert #x066A)٪ named: درصدِ فارسی - ("+" ?\u002B) ;; (ucs-insert #x002B)+ named: علامتِ به‌اضافه - ("-" ?\u2212) ;; (ucs-insert #x2212)− named: علامتِ منها - ("\\*" ?\u00D7) ;; (ucs-insert #x00D7)× named: علامتِ ضرب - ("\\-" ?\u00F7) ;; (ucs-insert #x00F7)÷ named: علامتِ تقسیم - ("<" ?\u003C) ;; (ucs-insert #x003C)< named: علامتِ کوچکتر - ("=" ?\u003D) ;; (ucs-insert #x003D)= named: علامتِ مساوی - (">" ?\u003E) ;; (ucs-insert #x003E)> named: علامتِ بزرگتر + ("\\/" ?\u066B) ;; (insert-char #x066B)٫ named: ممیزِ فارسی + ("\\," ?\u066C) ;; (insert-char #x066C)٬ named: جداکننده‌ی هزارهای فارسی + ("%" ?\u066A) ;; (insert-char #x066A)٪ named: درصدِ فارسی + ("+" ?\u002B) ;; (insert-char #x002B)+ named: علامتِ به‌اضافه + ("-" ?\u2212) ;; (insert-char #x2212)− named: علامتِ منها + ("\\*" ?\u00D7) ;; (insert-char #x00D7)× named: علامتِ ضرب + ("\\-" ?\u00F7) ;; (insert-char #x00F7)÷ named: علامتِ تقسیم + ("<" ?\u003C) ;; (insert-char #x003C)< named: علامتِ کوچکتر + ("=" ?\u003D) ;; (insert-char #x003D)= named: علامتِ مساوی + (">" ?\u003E) ;; (insert-char #x003E)> named: علامتِ بزرگتر ;;;;;;;;;;; isiri-6219 Table 2 -- جدول ۲ - علائم نقطه گذاریِ مشترک ;;; Space ("." ?.) ;; - (":" ?\u003A) ;; (ucs-insert #x003A): named: - ("!" ?\u0021) ;; (ucs-insert #x0021)! named: - ("\\." ?\u2026) ;; (ucs-insert #x2026)… named: - ("\\-" ?\u2010) ;; (ucs-insert #x2010)‐ named: - ("-" ?\u002D) ;; (ucs-insert #x002D)- named: + (":" ?\u003A) ;; (insert-char #x003A): named: + ("!" ?\u0021) ;; (insert-char #x0021)! named: + ("\\." ?\u2026) ;; (insert-char #x2026)… named: + ("\\-" ?\u2010) ;; (insert-char #x2010)‐ named: + ("-" ?\u002D) ;; (insert-char #x002D)- named: ("|" ?|) ;;("\\\\" ?\) ("//" ?/) - ("*" ?\u002A) ;; (ucs-insert #x002A)* named: - ("(" ?\u0028) ;; (ucs-insert #x0028)( named: - (")" ?\u0029) ;; (ucs-insert #x0029)) named: - ("[" ?\u005B) ;; (ucs-insert #x005B)[ named: - ("[" ?\u005D) ;; (ucs-insert #x005D)] named: - ("{" ?\u007B) ;; (ucs-insert #x007B){ named: - ("}" ?\u007D) ;; (ucs-insert #x007D)} named: - ("\\<" ?\u00AB) ;; (ucs-insert #x00AB)« named: - ("\\>" ?\u00BB) ;; (ucs-insert #x00BB)» named: - ("N" ?\u00AB) ;; (ucs-insert #x00AB)« named: - ("M" ?\u00BB) ;; (ucs-insert #x00BB)» named: + ("*" ?\u002A) ;; (insert-char #x002A)* named: + ("(" ?\u0028) ;; (insert-char #x0028)( named: + (")" ?\u0029) ;; (insert-char #x0029)) named: + ("[" ?\u005B) ;; (insert-char #x005B)[ named: + ("[" ?\u005D) ;; (insert-char #x005D)] named: + ("{" ?\u007B) ;; (insert-char #x007B){ named: + ("}" ?\u007D) ;; (insert-char #x007D)} named: + ("\\<" ?\u00AB) ;; (insert-char #x00AB)« named: + ("\\>" ?\u00BB) ;; (insert-char #x00BB)» named: + ("N" ?\u00AB) ;; (insert-char #x00AB)« named: + ("M" ?\u00BB) ;; (insert-char #x00BB)» named: ;;;;;;;;;;; isiri-6219 Table 3 -- جدول ۳ - علائم نقطه گذاریِ فارسی ("," ?،) ;; farsi @@ -466,20 +466,20 @@ ;;;;;;;;;;; isiri-6219 Table 1 -- جدول ۱ - نویسه‌های کنترلی ;; LF ;; CR - ("‌" ?\u200C) ;; (ucs-insert #x200C)‌ named: فاصله‌ی مجازی + ("‌" ?\u200C) ;; (insert-char #x200C)‌ named: فاصله‌ی مجازی ("/" ?\u200C) ;; - ("‍" ?\u200D) ;; (ucs-insert #x200D)‍ named: اتصالِ مجازی + ("‍" ?\u200D) ;; (insert-char #x200D)‍ named: اتصالِ مجازی ("J" ?\u200D) ;; - ("‎" ?\u200E) ;; (ucs-insert #x200E)‎ named: نشانه‌ی چپ‌به‌راست - ("‏" ?\u200F) ;; (ucs-insert #x200F)‏ named: نشانه‌ی راست‌به‌چپ - ("&ls;" ?\u2028) ;; (ucs-insert #x2028)
 named: جداکننده‌ی سطرها - ("&ps;" ?\u2028) ;; (ucs-insert #x2029)
 named: جداکننده‌ی بندها - ("&lre;" ?\u202A) ;; (ucs-insert #x202A)‪ named: زیرمتنِ چپ‌به‌راست - ("&rle;" ?\u202B) ;; (ucs-insert #x202B) named: زیرمتنِ راست‌به‌چپ - ("&pdf;" ?\u202C) ;; (ucs-insert #x202C) named: پایانِ زیرمتن - ("&lro;" ?\u202D) ;; (ucs-insert #x202D) named: زیرمتنِ اکیداً چپ‌به‌راست - ("&rlo;" ?\u202D) ;; (ucs-insert #x202E) named: زیرمتنِ اکیداً راست‌به‌چپ - ("&bom;" ?\uFEFF) ;; (ucs-insert #xFEFF) named: نشانه‌ی ترتیبِ بایت‌ها + ("‎" ?\u200E) ;; (insert-char #x200E)‎ named: نشانه‌ی چپ‌به‌راست + ("‏" ?\u200F) ;; (insert-char #x200F)‏ named: نشانه‌ی راست‌به‌چپ + ("&ls;" ?\u2028) ;; (insert-char #x2028)
 named: جداکننده‌ی سطرها + ("&ps;" ?\u2028) ;; (insert-char #x2029)
 named: جداکننده‌ی بندها + ("&lre;" ?\u202A) ;; (insert-char #x202A)‪ named: زیرمتنِ چپ‌به‌راست + ("&rle;" ?\u202B) ;; (insert-char #x202B) named: زیرمتنِ راست‌به‌چپ + ("&pdf;" ?\u202C) ;; (insert-char #x202C) named: پایانِ زیرمتن + ("&lro;" ?\u202D) ;; (insert-char #x202D) named: زیرمتنِ اکیداً چپ‌به‌راست + ("&rlo;" ?\u202D) ;; (insert-char #x202E) named: زیرمتنِ اکیداً راست‌به‌چپ + ("&bom;" ?\uFEFF) ;; (insert-char #xFEFF) named: نشانه‌ی ترتیبِ بایت‌ها ;;;;;;;;;;; isiri-6219 Table 7 -- جدول ۷ - نشانه‌هایِ فارسی @@ -491,14 +491,14 @@ ("O" ?ٌ) ;; دو پيش فارسى -- تنوين رفع ("~" ?ّ) ;; tashdid ;; تشديد فارسى ("@" ?ْ) ;; ساکن فارسى - ("U" ?\u0653) ;; (ucs-insert #x0653)ٓ named: مدِ فارسی + ("U" ?\u0653) ;; (insert-char #x0653)ٓ named: مدِ فارسی ("`" ?ٔ) ;; همزه فارسى بالا - ("C" ?\u0655) ;; (ucs-insert #x0655)ٕ named: همزه فارسى پایین - ("$" ?\u0670) ;; (ucs-insert #x0670)ٰ named: الفِ مقصوره‌ی فارسی + ("C" ?\u0655) ;; (insert-char #x0655)ٕ named: همزه فارسى پایین + ("$" ?\u0670) ;; (insert-char #x0670)ٰ named: الفِ مقصوره‌ی فارسی ;;;;;;;;;;; isiri-6219 Table 8 - Forbidden Characters -- جدول ۸ - نویسه‌هایِ ممنوع -;; ;; he ye (ucs-insert 1728) (ucs-insert #x06c0) kills emacs-24.0.90 +;; ;; he ye (insert-char 1728) (insert-char #x06c0) kills emacs-24.0.90 ;; arabic digits 0-9 @@ -508,7 +508,7 @@ ("\\~" ?~) ("\\@" ?@) ("\\#" ?#) - ("\\$" ?\uFDFC) ;; (ucs-insert #xFDFC)﷼ named: + ("\\$" ?\uFDFC) ;; (insert-char #xFDFC)﷼ named: ("\\^" ?^) ("\\1" ?1) ("\\2" ?2) commit 60ad45c5d27f78ee58c6b39871b6b04d6bc4e5ed Author: Stefan Kangas Date: Sat Jul 2 10:58:45 2022 +0200 Don't use obsolete face name in manoj-dark-theme * etc/themes/manoj-dark-theme.el (change-log-acknowledgment): Don't use obsolete/non-existent face name. diff --git a/etc/themes/manoj-dark-theme.el b/etc/themes/manoj-dark-theme.el index 4c9e436749..5a53ffbfec 100644 --- a/etc/themes/manoj-dark-theme.el +++ b/etc/themes/manoj-dark-theme.el @@ -377,7 +377,7 @@ jarring angry fruit salad look to reduce eye fatigue.") :foreground "black" :background "grey" :weight bold )))) '(calendar-today-face ((t (:underline t :bold t :foreground "cornsilk")))) - '(change-log-acknowledgement-face ((t (:italic t :slant oblique :foreground "AntiqueWhite3")))) + '(change-log-acknowledgment ((t (:italic t :slant oblique :foreground "AntiqueWhite3")))) '(change-log-conditionals-face ((t (:foreground "Aquamarine")))) '(change-log-date-face ((t (:italic t :slant oblique :foreground "BurlyWood")))) '(change-log-email-face ((t (:foreground "Aquamarine")))) commit 631b3fbde76040fd3545cc9f18e1b7d13b62ad62 Author: Eli Zaretskii Date: Sat Jul 2 12:16:33 2022 +0300 * src/sheap.h (STATIC_HEAP_SIZE): Double the size of static heap. diff --git a/src/sheap.h b/src/sheap.h index 297b7cf317..9133f0b292 100644 --- a/src/sheap.h +++ b/src/sheap.h @@ -23,7 +23,7 @@ along with GNU Emacs. If not, see . */ /* Size of the static heap. Guess a value that is probably too large, by up to a factor of four or so. Typically the unused part is not paged in and so does not cost much. */ -enum { STATIC_HEAP_SIZE = sizeof (Lisp_Object) << 22 }; +enum { STATIC_HEAP_SIZE = sizeof (Lisp_Object) << 23 }; extern char bss_sbrk_buffer[STATIC_HEAP_SIZE]; extern char *max_bss_sbrk_ptr; commit 50b3e9d23dbdcd8809aaa8a95f62c2df33868d25 Author: Po Lu Date: Sat Jul 2 16:41:45 2022 +0800 Completely get rid of races during Motif drag window creation * src/xterm.c (x_special_window_exists_p): New function. (xm_get_drag_window_1): Rework workflow and display grabbing. diff --git a/src/xterm.c b/src/xterm.c index 245ffedb80..2629997f2a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1838,10 +1838,47 @@ xm_drag_window_io_error_handler (Display *dpy) siglongjmp (x_dnd_disconnect_handler, 1); } +/* Determine whether or not WINDOW exists on DPYINFO by selecting for + input from it. */ +static bool +x_special_window_exists_p (struct x_display_info *dpyinfo, + Window window) +{ + bool rc; + + x_catch_errors (dpyinfo->display); + XSelectInput (dpyinfo->display, window, + StructureNotifyMask); + rc = !x_had_errors_p (dpyinfo->display); + x_uncatch_errors_after_check (); + + return rc; +} + +/* Drag window creation strategy (very tricky, but race-free): + + First look for _MOTIF_DRAG_WINDOW. If it is already present, + return it immediately to avoid the overhead of new display + connections. + + Otherwise, create a new connection to the display. In that + connection, create a window, which will be the new drag window. Set + the client disconnect mode of the new connection to + RetainPermanent, and close it. + + Grab the current display. Look up _MOTIF_DRAG_WINDOW, the current + drag window. If it exists (which means _MOTIF_DRAG_WINDOW was + created between the first step and now), kill the client that + created the new drag window to free the client slot on the X + server. Otherwise, set _MOTIF_DRAG_WINDOW to the new drag window. + + Ungrab the display and return whichever window is currently in + _MOTIF_DRAG_WINDOW. */ + static Window xm_get_drag_window_1 (struct x_display_info *dpyinfo) { - Atom actual_type, _MOTIF_DRAG_WINDOW; + Atom actual_type; int rc, actual_format; unsigned long nitems, bytes_remaining; unsigned char *tmp_data = NULL; @@ -1851,9 +1888,9 @@ xm_get_drag_window_1 (struct x_display_info *dpyinfo) Emacs_XErrorHandler old_handler; Emacs_XIOErrorHandler old_io_handler; - /* These are volatile because GCC mistakenly warns about them being + /* This is volatile because GCC mistakenly warns about them being clobbered by longjmp. */ - volatile bool error, created; + volatile bool error; drag_window = None; rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, @@ -1862,26 +1899,20 @@ xm_get_drag_window_1 (struct x_display_info *dpyinfo) &actual_format, &nitems, &bytes_remaining, &tmp_data) == Success; - if (rc) + if (rc && actual_type == XA_WINDOW + && actual_format == 32 && nitems == 1 + && tmp_data) { - if (actual_type == XA_WINDOW - && actual_format == 32 && nitems == 1) - { - drag_window = *(Window *) tmp_data; - x_catch_errors (dpyinfo->display); - XSelectInput (dpyinfo->display, drag_window, - StructureNotifyMask); - rc = !x_had_errors_p (dpyinfo->display); - x_uncatch_errors_after_check (); + drag_window = *(Window *) tmp_data; + rc = x_special_window_exists_p (dpyinfo, drag_window); - if (!rc) - drag_window = None; - } - - if (tmp_data) - XFree (tmp_data); + if (!rc) + drag_window = None; } + if (tmp_data) + XFree (tmp_data); + if (drag_window == None) { block_input (); @@ -1910,74 +1941,22 @@ xm_get_drag_window_1 (struct x_display_info *dpyinfo) error = false; xm_drag_window_error = &error; - XGrabServer (temp_display); XSetCloseDownMode (temp_display, RetainPermanent); - old_handler = XSetErrorHandler (xm_drag_window_error_handler); - _MOTIF_DRAG_WINDOW = XInternAtom (temp_display, - "_MOTIF_DRAG_WINDOW", False); - - if (error) - goto give_up; - - /* Some other program might've created a drag window between now - and when we first looked. Use that if it exists. */ - - tmp_data = NULL; - rc = XGetWindowProperty (temp_display, DefaultRootWindow (temp_display), - _MOTIF_DRAG_WINDOW, 0, 1, False, XA_WINDOW, - &actual_type, &actual_format, &nitems, - &bytes_remaining, &tmp_data) == Success; - - if (rc && actual_type == XA_WINDOW - && actual_format == 32 && nitems == 1 - && tmp_data) - drag_window = *(Window *) tmp_data; - - if (tmp_data) - XFree (tmp_data); - - error = false; - - if (drag_window == None) - { - created = true; - - attrs.override_redirect = True; - drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), - -1, -1, 1, 1, 0, CopyFromParent, InputOnly, - CopyFromParent, CWOverrideRedirect, &attrs); - XChangeProperty (temp_display, DefaultRootWindow (temp_display), - _MOTIF_DRAG_WINDOW, XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &drag_window, 1); - } - else - created = false; + attrs.override_redirect = True; + drag_window = XCreateWindow (temp_display, DefaultRootWindow (temp_display), + -1, -1, 1, 1, 0, CopyFromParent, InputOnly, + CopyFromParent, CWOverrideRedirect, &attrs); /* Handle all errors now. */ XSync (temp_display, False); - give_up: - /* Some part of the drag window creation process failed, so - punt. */ + punt. Release all resources too. */ if (error) { XSetCloseDownMode (temp_display, DestroyAll); - - /* If the drag window was actually created, delete it now. - Probably, a BadAlloc happened during the XChangeProperty - request. */ - if (created) - { - if (drag_window != None) - XDestroyWindow (temp_display, drag_window); - - XDeleteProperty (temp_display, DefaultRootWindow (temp_display), - _MOTIF_DRAG_WINDOW); - } - drag_window = None; } @@ -1995,15 +1974,49 @@ xm_get_drag_window_1 (struct x_display_info *dpyinfo) /* Make sure the drag window created is actually valid for the current display, and the XOpenDisplay above didn't accidentally connect to some other display. */ - x_catch_errors (dpyinfo->display); - XSelectInput (dpyinfo->display, drag_window, StructureNotifyMask); - rc = !x_had_errors_p (dpyinfo->display); - x_uncatch_errors_after_check (); + if (!x_special_window_exists_p (dpyinfo, drag_window)) + drag_window = None; unblock_input (); - /* We connected to the wrong display, so just give up. */ - if (!rc) - drag_window = None; + if (drag_window != None) + { + XGrabServer (dpyinfo->display); + + x_catch_errors (dpyinfo->display); + tmp_data = NULL; + + rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, + dpyinfo->Xatom_MOTIF_DRAG_WINDOW, + 0, 1, False, XA_WINDOW, &actual_type, + &actual_format, &nitems, &bytes_remaining, + &tmp_data) == Success; + + if (rc && actual_type == XA_WINDOW + && actual_format == 32 && nitems == 1 + && tmp_data + && x_special_window_exists_p (dpyinfo, + *(Window *) tmp_data)) + { + /* Kill the client now to avoid leaking a client slot, + which is a limited resource. */ + XKillClient (dpyinfo->display, drag_window); + drag_window = *(Window *) tmp_data; + } + else + XChangeProperty (dpyinfo->display, dpyinfo->root_window, + dpyinfo->Xatom_MOTIF_DRAG_WINDOW, + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &drag_window, 1); + + if (tmp_data) + XFree (tmp_data); + + if (x_had_errors_p (dpyinfo->display)) + drag_window = None; + x_uncatch_errors (); + + XUngrabServer (dpyinfo->display); + } } return drag_window; commit 9230953f23c432699347bb3eeadebd82e4cbbfaa Author: Stefan Kangas Date: Sat Jul 2 10:20:23 2022 +0200 ; Fix typos. diff --git a/ChangeLog.3 b/ChangeLog.3 index d0ff14117b..907eb2ce6f 100644 --- a/ChangeLog.3 +++ b/ChangeLog.3 @@ -2276,7 +2276,7 @@ 2021-12-27 Eli Zaretskii - Fix typos in in 'reset-language-environment' + Fix typos in 'reset-language-environment' * lisp/international/mule-cmds.el (reset-language-environment): Fix a typo in 'windows-nt'. (Bug#52816) @@ -15459,7 +15459,7 @@ Fix automatic hscrolling when line numbers are displayed * src/xdisp.c (hscroll_window_tree): When line numbers are - displayed, account for the the line-number space when calculating + displayed, account for the line-number space when calculating the desired X coordinate on the left. (Bug#49891) 2021-08-06 Eli Zaretskii @@ -27169,7 +27169,7 @@ * lisp/minibuffer.el (minibuffer--sort-by-length-alpha): New function. (minibuffer--sort-by-position): New function extracted from `completion-all-sorted-completions`. - (completion-all-sorted-completions): Use use them. + (completion-all-sorted-completions): Use them. 2021-04-19 Daniel Mendler @@ -42218,7 +42218,7 @@ string in the byte-code (so the two branches return `eq` strings). So, I think using `iso-2022-jp` is a bad idea here: it gives the - illusion that the the `charset` info exists, even it will be lost. + illusion that the `charset` info exists, even it will be lost. Eli discussed it with Handa-san a year ago, and they arrived at the conclusion that the charset information is indeed no longer important. @@ -67358,7 +67358,7 @@ wdired-do-renames: Speed up for long Emacs sessions `dired-rename-file' calls unconditionally `dired-rename-subdir'. - The second function performs performs a loop on all the Emacs + The second function performs a loop on all the Emacs buffers; this step is only needed if FILE is a directory (bug#32899). In a long lived Emacs session, this can make a difference @@ -74306,7 +74306,7 @@ (Bug#42563) - For some time, Eldoc has has some Elisp-specific code that shouldn't + For some time, Eldoc has some Elisp-specific code that shouldn't live there, but in elisp-mode.el. This can be fixed in Emacs master, but since ElDoc is distributed in GNU Elpa and is meant to work with Emacs 26 and 27, this means that that elisp-specific code must still @@ -74558,7 +74558,7 @@ Do this conservatively for now: if the ElDoc helper buffer (as returned by eldoc--doc-buffer) is visible and showing documentation - for the very same "situation" (as computed by the the new + for the very same "situation" (as computed by the new eldoc--request-state helper), don't request that documentation from sources again. @@ -77976,7 +77976,7 @@ * lisp/emacs-lisp/comp.el (comp-symbol-values-optimizable): New defconst. - (comp-function-call-maybe-remove): New logic to to remove + (comp-function-call-maybe-remove): New logic to remove unnecessary `symbol-value' calls. 2020-06-07 Juri Linkov @@ -85368,7 +85368,7 @@ 2020-03-10 AndreaCorallo - * Fix store_function_docstring for for native functions + * Fix store_function_docstring for native functions Do not Nil native_doc fields. This will be naturally dumped by pdumper. This was affecting dumped functions. @@ -114426,7 +114426,7 @@ 2019-08-21 Nicolas Petton - * etc/HISTORY: Add Emacs 26.3 release release date. + * etc/HISTORY: Add Emacs 26.3 release date. 2019-08-21 Nicolas Petton @@ -117408,7 +117408,7 @@ 2019-07-30 Lars Ingebrigtsen - Use decoded time accessors in in em-ls + Use decoded time accessors in em-ls * lisp/eshell/em-ls.el (eshell-ls-file): Use decoded time accessors. @@ -118983,7 +118983,7 @@ * doc/lispref/hash.texi (Creating Hash, Defining Hash): * src/fns.c (Fsxhash_eq, Fsxhash_eql, Fsxhash_equal): Say that hashes are fixnums. - (Fmake_hash_table): Say that that an integer rehash-size + (Fmake_hash_table): Say that an integer rehash-size should be a fixnum. * doc/lispref/hash.texi (Defining Hash): Say that hash and comparison functions should be consistent and pure, and should @@ -128629,7 +128629,7 @@ * lisp/emacs-lisp/package.el (package-install-from-archive): Fix last change - Don't place the unibyte content of of the downloaded file into + Don't place the unibyte content of the downloaded file into a multibyte buffer. 2019-05-24 Michael Albinus @@ -149671,7 +149671,7 @@ * lisp/textmodes/bibtex.el (bibtex-next-entry) (bibtex-previous-entry): New commands. - (bibtex-mode-map): Bind to to forward-paragraph and + (bibtex-mode-map): Bind to forward-paragraph and backward-paragraph. Add to menu under "Moving inside an Entry". 2018-08-27 Noam Postavsky @@ -186529,7 +186529,7 @@ Lay some groundwork for a more flexible approach that allows for different classes of diagnostics, not necessarily line-based. Importantly, one overlay per diagnostic is created, whereas the - original implementation had one per line, and on it it concatenated + original implementation had one per line, and on it concatenated the results of errors and warnings. This means that currently, an error and warning on the same line are diff --git a/doc/emacs/ChangeLog.1 b/doc/emacs/ChangeLog.1 index c1c5f5407d..048b7bd99a 100644 --- a/doc/emacs/ChangeLog.1 +++ b/doc/emacs/ChangeLog.1 @@ -8529,7 +8529,7 @@ * text.texi (Cell Justification): * trouble.texi (After a Crash): * xresources.texi (GTK styles): - Delete duplicate duplicate words. + Delete duplicate words. 2005-07-17 Richard M. Stallman diff --git a/doc/misc/ert.texi b/doc/misc/ert.texi index 91288db45a..4dccd8edcf 100644 --- a/doc/misc/ert.texi +++ b/doc/misc/ert.texi @@ -321,7 +321,7 @@ Show the list of @code{should} forms executed in the test @kindex m@r{, in ert results buffer} @findex ert-results-pop-to-messages-for-test-at-point Show any messages that were generated (with the Lisp function -@code{message}) in in a test or any of the code that it invoked +@code{message}) in a test or any of the code that it invoked (@code{ert-results-pop-to-messages-for-test-at-point}). @item L diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index fa4d6d9849..720f608368 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el @@ -503,8 +503,8 @@ The decision is taken by order of preference: * According to C's syntax and the syntactic state of the buffer (both as defined by the major mode's syntax table). This is - done by looking up up the variables - `electric-pair-inhibit-predicate', `electric-pair-skip-self' + done by looking up the variables + `electric-pair-inhibit-predicate', `electric-pair-skip-self' and `electric-pair-skip-whitespace' (which see)." (let* ((pos (and electric-pair-mode (electric--after-char-pos))) (skip-whitespace-info)) diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el index ec9fd86a55..94f9654b23 100644 --- a/lisp/emacs-lisp/cl-preloaded.el +++ b/lisp/emacs-lisp/cl-preloaded.el @@ -146,7 +146,7 @@ supertypes from the most specific to least specific.") (while (recordp parent) (add-to-list (cl--struct-class-children-sym parent) tag) ;; Only register ourselves as a child of the leftmost parent since structs - ;; can only only have one parent. + ;; can only have one parent. (setq parent (car (cl--struct-class-parents parent))))) ;;;###autoload diff --git a/lisp/org/ob-comint.el b/lisp/org/ob-comint.el index 427aba3415..c99d6a8ba7 100644 --- a/lisp/org/ob-comint.el +++ b/lisp/org/ob-comint.el @@ -166,7 +166,7 @@ source block, and the name of the temp file.") (defvar-local org-babel-comint-async-chunk-callback nil "Callback function to clean Babel async output results before insertion. Its single argument is a string consisting of output from the -comint process. It should return a string that will be be passed +comint process. It should return a string that will be passed to `org-babel-insert-result'.") (defvar-local org-babel-comint-async-dangling nil diff --git a/lisp/org/ol-doi.el b/lisp/org/ol-doi.el index 94585e4c3e..56239f65d4 100644 --- a/lisp/org/ol-doi.el +++ b/lisp/org/ol-doi.el @@ -44,7 +44,7 @@ PATH is a the path to search for, as a string." "Export a \"doi\" type link. PATH is the DOI name. DESC is the description of the link, or nil. BACKEND is a symbol representing the backend used for -export. INFO is a a plist containing the export parameters." +export. INFO is a plist containing the export parameters." (let ((uri (concat org-link-doi-server-url path))) (pcase backend (`html diff --git a/lisp/org/org-feed.el b/lisp/org/org-feed.el index a5fea08882..c7b4bde0d2 100644 --- a/lisp/org/org-feed.el +++ b/lisp/org/org-feed.el @@ -406,7 +406,7 @@ it can be a list structured like an entry in `org-feed-alist'." ;; Write the new status ;; We do this only now, in case something goes wrong above, so - ;; that would would end up with a status that does not reflect + ;; that would end up with a status that does not reflect ;; which items truly have been handled (org-feed-write-status inbox-pos drawer status) diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 79ef6101e9..03beb06569 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -2112,7 +2112,7 @@ is running." (not (null gdb-running-threads-count)) (> gdb-running-threads-count 0)))) -;; GUD displays the selected GDB frame. This might might not be the current +;; GUD displays the selected GDB frame. This might not be the current ;; GDB frame (after up, down etc). If no GDB frame is visible but the last ;; visited breakpoint is, use that window. (defun gdb-display-source-buffer (buffer) diff --git a/lisp/transient.el b/lisp/transient.el index 06e4106192..41b69b1aba 100644 --- a/lisp/transient.el +++ b/lisp/transient.el @@ -246,7 +246,7 @@ for infix argument are highlighted when only a long argument In the rare case that a short-hand is specified but does not match the key binding, then it is highlighed differently. -The highlighting is done using using `transient-mismatched-key' +The highlighting is done using `transient-mismatched-key' and `transient-nonstandard-key'." :package-version '(transient . "0.1.0") :group 'transient diff --git a/src/lisp.h b/src/lisp.h index 7a7d2e7997..e4a49b8ef9 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3451,7 +3451,7 @@ union specbinding #define WRAP_SPECPDL_REF 1 #endif -/* Abstract reference to to a specpdl entry. +/* Abstract reference to a specpdl entry. The number is always a multiple of sizeof (union specbinding). */ #ifdef WRAP_SPECPDL_REF /* Use a proper type for specpdl_ref if it does not make the code slower, diff --git a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp index e7d85101a1..f5b6d64184 100644 --- a/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp +++ b/test/lisp/cedet/semantic-utest-ia-resources/teststruct.cpp @@ -20,7 +20,7 @@ // along with GNU Emacs. If not, see . -// Note: initially provided by by Alex Ott. +// Note: initially provided by Alex Ott. template struct grammar { commit 3112d5a2f1cff376f7aeba97479ed38e494959ee Author: Stefan Kangas Date: Sat Jul 2 09:48:20 2022 +0200 * src/xfns.c (Fx_server_input_extension_version): Fix typo. diff --git a/src/xfns.c b/src/xfns.c index 9dcf73da1c..adb4fb58bc 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -5387,9 +5387,9 @@ DEFUN ("x-server-input-extension-version", Fx_server_input_extension_version, doc: /* Return the version of the X Input Extension supported by TERMINAL. The value is nil if TERMINAL's X server doesn't support the X Input Extension extension, or if Emacs doesn't support the version present -on that server. Otherwise, the return value is a list of the the -major and minor versions of the X Input Extension extension running on -that server. */) +on that server. Otherwise, the return value is a list of the major +and minor versions of the X Input Extension extension running on that +server. */) (Lisp_Object terminal) { #ifdef HAVE_XINPUT2 commit 52c91122eecb0f679de46d539fc85b8e28599fe1 Merge: 9dc0fdfdc1 1c3d107cb5 Author: Stefan Kangas Date: Sat Jul 2 09:33:51 2022 +0200 Merge from origin/emacs-28 1c3d107cb5 Fix "C-u C-x =" for SPC 7e33618bbc ; * src/fns.c (Frequire): Fix a typo in the doc string. (... 6908309827 Doc fixes: don't refer to some obsolete items dc3cb749f3 Remove obsolete cust-print from elisp index 9ffbbddf8e * admin/make-tarball.txt: Minor clarifications. f5421104e9 Fix external image conversion on MS-Windows 6f22631a63 * doc/emacs/buffers.texi (Indirect Buffers): Mention modif... # Conflicts: # doc/emacs/buffers.texi # lisp/emacs-lisp/nadvice.el # lisp/image/image-converter.el commit 9dc0fdfdc14beb5d19b705b25bf01020df27541b Author: Lele Gaifax Date: Fri Jul 1 18:03:57 2022 +0200 Fix repeated "the" * configure.ac (EMACS_CONFIG_FEATURES): * etc/NEWS: * lisp/dnd.el (dnd-begin-text-drag): * src/pgtkfns.c (Fx_display_mm_height, Fx_display_mm_width): (Fx_display_backing_store, Fx_display_visual_class): * src/xterm.c: Fix repeated "the". (Bug#56341) Copyright-paperwork-exempt: yes diff --git a/configure.ac b/configure.ac index 17f86627a7..ad3df5d731 100644 --- a/configure.ac +++ b/configure.ac @@ -6492,7 +6492,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D Does Emacs support legacy unexec dumping? ${with_unexec} Which dumping strategy does Emacs use? ${with_dumping} Does Emacs have native lisp compiler? ${HAVE_NATIVE_COMP} - Does Emacs use version 2 of the the X Input Extension? ${HAVE_XINPUT2} + Does Emacs use version 2 of the X Input Extension? ${HAVE_XINPUT2} Does Emacs generate a smaller-size Japanese dictionary? ${with_small_ja_dic} "]) diff --git a/etc/NEWS b/etc/NEWS index 3127e73426..30404cc13c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1012,7 +1012,7 @@ so automatically. ** Elisp *** New command 'elisp-eval-buffer' (bound to 'C-c C-e'). -This command evals the forms in the the current buffer. +This command evals the forms in the current buffer. *** New commands 'elisp-byte-compile-file' and 'elisp-byte-compile-buffer'. These commands (bound to 'C-c C-f' and 'C-c C-b', respectively) diff --git a/lisp/dnd.el b/lisp/dnd.el index 29f4ca98ec..ade61917e9 100644 --- a/lisp/dnd.el +++ b/lisp/dnd.el @@ -348,7 +348,7 @@ program where the drop happened. FRAME is the frame where the 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 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, ignore any drops on FRAME itself. diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 4f15ec6ff6..5c43e5f360 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -2043,7 +2043,7 @@ use `(length \(display-monitor-attributes-list TERMINAL))' instead. */) DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0, - doc: /* Return the height in millimeters of the the display TERMINAL. + doc: /* Return the height in millimeters of the display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. @@ -2084,7 +2084,7 @@ for each physical monitor, use `display-monitor-attributes-list'. */) DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, - doc: /* Return the width in millimeters of the the display TERMINAL. + doc: /* Return the width in millimeters of the display TERMINAL. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. @@ -2125,7 +2125,7 @@ for each physical monitor, use `display-monitor-attributes-list'. */) DEFUN ("x-display-backing-store", Fx_display_backing_store, Sx_display_backing_store, 0, 1, 0, - doc: /* Return an indication of whether the the display TERMINAL does backing store. + doc: /* Return an indication of whether the display TERMINAL does backing store. The value may be `buffered', `retained', or `non-retained'. The optional argument TERMINAL specifies which display to ask about. TERMINAL should be a terminal object, a frame or a display name (a string). @@ -2138,7 +2138,7 @@ If omitted or nil, that stands for the selected frame's display. */) DEFUN ("x-display-visual-class", Fx_display_visual_class, Sx_display_visual_class, 0, 1, 0, - doc: /* Return the visual class of the the display TERMINAL. + doc: /* Return the visual class of the display TERMINAL. The value is one of the symbols `static-gray', `gray-scale', `static-color', `pseudo-color', `true-color', or `direct-color'. diff --git a/src/xterm.c b/src/xterm.c index 061bca0684..245ffedb80 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -497,7 +497,7 @@ along with GNU Emacs. If not, see . */ data.l[1] = timestamp data.l[2] = low 32 bits of a provided frame counter value data.l[3] = high 32 bits of a provided frame counter value - data.l[4] = 1 if the the extended frame counter should be updated, + data.l[4] = 1 if the extended frame counter should be updated, otherwise 0 Upon receiving such an event, Emacs constructs and saves a counter commit 9d14e0bf1e913fbb223241d246438e53bbc81431 Author: Visuwesh Date: Thu Jun 30 19:36:41 2022 +0530 Fix fallout from bug#50143 * lisp/language/ind-util.el (indian-tml-base-table) (indian-tml-base-digits-table): Add TAMIL OM sign and more Sanskrit consonants to the table (bug#50143) (bug#56323). diff --git a/lisp/language/ind-util.el b/lisp/language/ind-util.el index 60ada03fa2..fa380dbde7 100644 --- a/lisp/language/ind-util.el +++ b/lisp/language/ind-util.el @@ -267,11 +267,11 @@ ?த nil nil nil ?ந ?ன ;; DENTALS ?ப nil nil nil ?ம ;; LABIALS ?ய ?ர ?ற ?ல ?ள ?ழ ?வ ;; SEMIVOWELS - nil ?ஷ ?ஸ ?ஹ ;; SIBILANTS + ?ஶ ?ஷ ?ஸ ?ஹ ;; SIBILANTS nil nil nil nil nil nil nil nil ;; NUKTAS - "ஜ்ஞ" "க்ஷ") + "ஜ்ஞ" "க்ஷ" "க்‌ஷ்") (;; Misc Symbols - nil ?ஂ ?ஃ nil ?் nil nil) + nil ?ஂ ?ஃ nil ?் ?ௐ nil) (;; Digits nil nil nil nil nil nil nil nil nil nil) (;; Inscript-extra (4) (#, $, ^, *, ]) @@ -290,11 +290,11 @@ ?த nil nil nil ?ந ?ன ;; DENTALS ?ப nil nil nil ?ம ;; LABIALS ?ய ?ர ?ற ?ல ?ள ?ழ ?வ ;; SEMIVOWELS - nil ?ஷ ?ஸ ?ஹ ;; SIBILANTS + ?ஶ ?ஷ ?ஸ ?ஹ ;; SIBILANTS nil nil nil nil nil nil nil nil ;; NUKTAS - "ஜ்ஞ" "க்ஷ") + "ஜ்ஞ" "க்ஷ" "க்‌ஷ்") (;; Misc Symbols - nil ?ஂ ?ஃ nil ?் nil nil) + nil ?ஂ ?ஃ nil ?் ?ௐ nil) (;; Digits ?௦ ?௧ ?௨ ?௩ ?௪ ?௫ ?௬ ?௭ ?௮ ?௯) (;; Inscript-extra (4) (#, $, ^, *, ]) commit 09444b5fc4d9703eddd227df192603fd03b45577 Author: Omar Polo Date: Fri Jul 1 10:50:19 2022 +0200 Improve rcirc's CertFP documentation * doc/misc/rcirc.texi: Clarify meaning of key and password * lisp/net/rcirc.el (rcirc-authinfo): Add example diff --git a/doc/misc/rcirc.texi b/doc/misc/rcirc.texi index 8253e40408..8c798d6c33 100644 --- a/doc/misc/rcirc.texi +++ b/doc/misc/rcirc.texi @@ -639,9 +639,9 @@ password to use. @item certfp @cindex certfp authentication Use this symbol if you want to use CertFP authentication. The -necessary arguments are the path to the client certificate key and -password. The CertFP authentication requires a @acronym{TLS} -connection. +necessary arguments are the path to the key and to the client +certificate associated with the account. The CertFP authentication +requires a @acronym{TLS} connection. @end table diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index eca7b2046c..36352a4673 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -267,6 +267,7 @@ The ARGUMENTS for each METHOD symbol are: Examples: ((\"Libera.Chat\" nickserv \"bob\" \"p455w0rd\") (\"Libera.Chat\" chanserv \"bob\" \"#bobland\" \"passwd99\") + (\"Libera.Chat\" certfp \"/path/to/key\" \"/path/to/cert\") (\"bitlbee\" bitlbee \"robert\" \"sekrit\") (\"dal.net\" nickserv \"bob\" \"sekrit\" \"NickServ@services.dal.net\") (\"quakenet.org\" quakenet \"bobby\" \"sekrit\") commit 2b1cf5aff41f946b64abeb2ec4eea9d243880501 Author: Po Lu Date: Sat Jul 2 14:06:28 2022 +0800 Fix drag-and-drop from Chromium family browsers * lisp/x-dnd.el (x-dnd-copy-types): New defcustom. (x-dnd-default-test-function): Check if data type warrants using `copy'. (x-dnd-do-direct-save): Offer application/octet-stream as well. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 8a7f3e2436..8bea333012 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -139,6 +139,16 @@ that was dropped." :type 'function :group 'x) +(defcustom x-dnd-copy-types '("chromium/x-renderer-taint") + "List of data types offered by programs that don't support `private'. +Some programs (such as Chromium) do not support +`XdndActionPrivate'. The default `x-dnd-test-function' will +always return `copy' instead, for programs offering one of the +data types in this list." + :version "29.1" + :type '(repeat string) + :group 'x) + ;; Internal variables (defvar x-dnd-current-state nil @@ -200,13 +210,22 @@ any protocol specific data.") (defun x-dnd-default-test-function (_window _action types) "The default test function for drag and drop. -WINDOW is where the mouse is when this function is called. It may be -a frame if the mouse is over the menu bar, scroll bar or tool bar. -ACTION is the suggested action from the source, and TYPES are the -types the drop data can have. This function only accepts drops with -types in `x-dnd-known-types'. It always returns the action private." +WINDOW is where the mouse is when this function is called. It +may be a frame if the mouse is over the menu bar, scroll bar or +tool bar. ACTION is the suggested action from the source, and +TYPES are the types the drop data can have. This function only +accepts drops with types in `x-dnd-known-types'. It always +returns the action `private', unless `types' contains a value +inside `x-dnd-copy-types'." (let ((type (x-dnd-choose-type types))) - (when type (cons 'private type)))) + (when type (let ((list x-dnd-copy-types)) + (catch 'out + (while t + (if (not list) + (throw 'out (cons 'private type)) + (if (x-dnd-find-type (car list) types) + (throw 'out (cons 'copy type)) + (setq list (cdr list)))))))))) (defun x-dnd-current-type (frame-or-window) "Return the type we want the DND data to be in for the current drop. @@ -1292,7 +1311,8 @@ was taken, or the direct save failed." ;; FIXME: this does not work with GTK file managers, since ;; they always reach for `text/uri-list' first, contrary to ;; the spec. - (let ((action (x-begin-drag '("XdndDirectSave0" "text/uri-list") + (let ((action (x-begin-drag '("XdndDirectSave0" "text/uri-list" + "application/octet-stream") 'XdndActionDirectSave frame nil allow-same-frame))) (if (not x-dnd-xds-performed) commit 6c9c8b09b974e6cd356038a4308c61195b547e35 Author: Stefan Kangas Date: Sat Jul 2 06:25:01 2022 +0200 * lisp/ruler-mode.el (ruler-mode-map): Use defvar-keymap. diff --git a/lisp/ruler-mode.el b/lisp/ruler-mode.el index f0efc20f03..0b18697cea 100644 --- a/lisp/ruler-mode.el +++ b/lisp/ruler-mode.el @@ -509,36 +509,21 @@ START-EVENT is the mouse click event." (setq ruler-mode-show-tab-stops (not ruler-mode-show-tab-stops)) (force-mode-line-update)) -(defvar ruler-mode-map - (let ((km (make-sparse-keymap))) - (define-key km [header-line down-mouse-1] - #'ignore) - (define-key km [header-line down-mouse-3] - #'ignore) - (define-key km [header-line down-mouse-2] - #'ruler-mode-mouse-grab-any-column) - (define-key km [header-line (shift down-mouse-1)] - #'ruler-mode-mouse-set-left-margin) - (define-key km [header-line (shift down-mouse-3)] - #'ruler-mode-mouse-set-right-margin) - (define-key km [header-line (control down-mouse-1)] - #'ruler-mode-mouse-add-tab-stop) - (define-key km [header-line (control down-mouse-3)] - #'ruler-mode-mouse-del-tab-stop) - (define-key km [header-line (control down-mouse-2)] - #'ruler-mode-toggle-show-tab-stops) - (define-key km [header-line (shift mouse-1)] - #'ignore) - (define-key km [header-line (shift mouse-3)] - #'ignore) - (define-key km [header-line (control mouse-1)] - #'ignore) - (define-key km [header-line (control mouse-3)] - #'ignore) - (define-key km [header-line (control mouse-2)] - #'ignore) - km) - "Keymap for ruler minor mode.") +(defvar-keymap ruler-mode-map + :doc "Keymap for `ruler-mode'." + " " #'ignore + " " #'ignore + " " #'ruler-mode-mouse-grab-any-column + " S-" #'ruler-mode-mouse-set-left-margin + " S-" #'ruler-mode-mouse-set-right-margin + " C-" #'ruler-mode-mouse-add-tab-stop + " C-" #'ruler-mode-mouse-del-tab-stop + " C-" #'ruler-mode-toggle-show-tab-stops + " S-" #'ignore + " S-" #'ignore + " C-" #'ignore + " C-" #'ignore + " C-" #'ignore) (defvar ruler-mode-header-line-format-old nil "Hold previous value of `header-line-format'.") commit 8b6c9169f498e6f0bd147e4f6e7d339c3b1132de Author: Stefan Kangas Date: Sat Jul 2 06:04:55 2022 +0200 * lisp/epa-mail.el (epa-mail-mode-map): Use defvar-keymap. diff --git a/lisp/epa-mail.el b/lisp/epa-mail.el index 6170dcb611..bb34ca72d6 100644 --- a/lisp/epa-mail.el +++ b/lisp/epa-mail.el @@ -30,21 +30,19 @@ ;;; Local Mode -(defvar epa-mail-mode-map - (let ((keymap (make-sparse-keymap))) - (define-key keymap "\C-c\C-ed" 'epa-mail-decrypt) - (define-key keymap "\C-c\C-ev" 'epa-mail-verify) - (define-key keymap "\C-c\C-es" 'epa-mail-sign) - (define-key keymap "\C-c\C-ee" 'epa-mail-encrypt) - (define-key keymap "\C-c\C-ei" 'epa-mail-import-keys) - (define-key keymap "\C-c\C-eo" 'epa-insert-keys) - (define-key keymap "\C-c\C-e\C-d" 'epa-mail-decrypt) - (define-key keymap "\C-c\C-e\C-v" 'epa-mail-verify) - (define-key keymap "\C-c\C-e\C-s" 'epa-mail-sign) - (define-key keymap "\C-c\C-e\C-e" 'epa-mail-encrypt) - (define-key keymap "\C-c\C-e\C-i" 'epa-mail-import-keys) - (define-key keymap "\C-c\C-e\C-o" 'epa-insert-keys) - keymap)) +(defvar-keymap epa-mail-mode-map + "C-c C-e d" #'epa-mail-decrypt + "C-c C-e v" #'epa-mail-verify + "C-c C-e s" #'epa-mail-sign + "C-c C-e e" #'epa-mail-encrypt + "C-c C-e i" #'epa-mail-import-keys + "C-c C-e o" #'epa-insert-keys + "C-c C-e C-d" #'epa-mail-decrypt + "C-c C-e C-v" #'epa-mail-verify + "C-c C-e C-s" #'epa-mail-sign + "C-c C-e C-e" #'epa-mail-encrypt + "C-c C-e C-i" #'epa-mail-import-keys + "C-c C-e C-o" #'epa-insert-keys) (defvar epa-mail-mode-hook nil) (defvar epa-mail-mode-on-hook nil) commit 3b66c23325909fef077831c5f289221583e75bd7 Author: Stefan Kangas Date: Sat Jul 2 05:35:15 2022 +0200 Font lock \\`' command substitutions in docstrings * lisp/emacs-lisp/lisp-mode.el (lisp-el-font-lock-keywords-2): Support \\`' command substitutions. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 6d5391d1e9..3797217e1a 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -476,8 +476,14 @@ This will generate compile-time constants from BINDINGS." "[ \t']*\\(" lisp-mode-symbol-regexp "\\)?") (1 font-lock-keyword-face) (2 font-lock-constant-face nil t)) - ;; Words inside \\[] tend to be for `substitute-command-keys'. - (,(concat "\\\\\\\\\\[\\(" lisp-mode-symbol-regexp "\\)\\]") + ;; Words inside \\[] or \\`' tend to be for `substitute-command-keys'. + (,(rx "\\\\[" (group (regexp lisp-mode-symbol-regexp)) "]") + (1 font-lock-constant-face prepend)) + (,(rx "\\\\`" (group + (+ (regexp lisp-mode-symbol-regexp) + ;; allow multiple words, e.g. "C-x a" + (? " "))) + "'") (1 font-lock-constant-face prepend)) ;; Ineffective backslashes (typically in need of doubling). ("\\(\\\\\\)\\([^\"\\]\\)" commit e3a3d6bf2324cf300d0d07bf655cf8f99ca030af Author: Po Lu Date: Sat Jul 2 10:17:57 2022 +0800 Add interactive XDS test * test/lisp/dnd-tests.el (dnd-tests-direct-save): New test. diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index b6edbc3a2e..88f6e69457 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -411,5 +411,31 @@ This function only tries to handle strings." (inhibit-message t)) (should (prog1 t (dnd-open-remote-url url 'private))))) +(ert-deftest dnd-tests-direct-save () + ;; This test just verifies that a direct save works; the window + ;; system specific test is in x-dnd-tests.el. When running this + ;; interactively, keep in mind that there are only two file managers + ;; which are known to implement XDS correctly: System G (see + ;; http://nps-systemg.sourceforge.net), and Emacs itself. GTK file + ;; managers such as Nautilus will not work, since they prefer the + ;; `text/uri-list' selection target to `XdndDirectSave0', contrary + ;; to the XDS specification. + (let ((window-system window-system) + (normal-temp-file (expand-file-name (make-temp-name "dnd-test") + temporary-file-directory))) + (unwind-protect + (progn + (unless (file-exists-p normal-temp-file) + (write-region "" 0 normal-temp-file)) + (unless (eq window-system 'x) + ;; Use a window system that isn't X, since we only want to test + ;; the fallback code when run non-interactively. + (setq window-system 'haiku)) + (should (eq (dnd-direct-save normal-temp-file + (make-temp-name "target-file-name")) + 'copy))) + (ignore-errors + (delete-file normal-temp-file))))) + (provide 'dnd-tests) ;;; dnd-tests.el ends here commit a2d0a9ee5c78b12b10bb8666c87c4697c386757c Author: Stefan Monnier Date: Fri Jul 1 21:29:45 2022 -0400 * editfns.c (Fbyte_to_string): Use `make_unibyte_string` diff --git a/src/editfns.c b/src/editfns.c index 84947af508..4587b1132b 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -161,7 +161,7 @@ DEFUN ("byte-to-string", Fbyte_to_string, Sbyte_to_string, 1, 1, 0, if (XFIXNUM (byte) < 0 || XFIXNUM (byte) > 255) error ("Invalid byte"); b = XFIXNUM (byte); - return make_string_from_bytes ((char *) &b, 1, 1); + return make_unibyte_string ((char *) &b, 1); } DEFUN ("string-to-char", Fstring_to_char, Sstring_to_char, 1, 1, 0, commit eb6d74a26c64e6aa444f21b12a7ab9951a00bfa5 Author: Po Lu Date: Sat Jul 2 09:06:36 2022 +0800 Return the correct action from the Lisp side of drag-and-drop * lisp/x-dnd.el (x-dnd-handle-drag-n-drop-event): Select `window' when handling internal DND events. (x-dnd-handle-unsupported-drop): Return an appropriate action. * src/keyboard.c (kbd_buffer_get_event): * src/termhooks.h (enum event_kind): Delete `UNSUPPORTED_DROP_EVENT'. * src/xterm.c (x_dnd_send_unsupported_drop): Set flags instead of recording input event. (x_clear_dnd_monitors): Rename to `x_clear_dnd_variables'. Also clear unsupported drop data. (x_dnd_begin_drag_and_drop): Run unsupported drop function inline (and safely), and use its return value if it returned a symbol. (syms_of_xterm): Update doc string of `x-dnd-unsupported-drop-function'. * src/xterm.h: Update declarations. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index d78f926ee7..8a7f3e2436 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -422,6 +422,8 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." x-dnd-xdnd-to-action))) (targets (cddr client-message)) (local-value (nth 2 client-message))) + (when (windowp window) + (select-window window)) (x-dnd-save-state window nil nil (apply #'vector targets)) (x-dnd-maybe-call-test-function window action) @@ -1154,19 +1156,25 @@ X and Y are the root window coordinates of the drop. FRAME is the frame the drop originated on. WINDOW-ID is the X window the drop should happen to. LOCAL-SELECTION-DATA is the local selection data of the drop." - (not (and (or (eq action 'XdndActionCopy) - (eq action 'XdndActionMove)) - (not (and x-dnd-use-offix-drop local-selection-data - (or (not (eq x-dnd-use-offix-drop 'files)) - (member "FILE_NAME" targets)) - (x-dnd-do-offix-drop targets x - y frame window-id - local-selection-data))) - (or - (member "STRING" targets) - (member "UTF8_STRING" targets) - (member "COMPOUND_TEXT" targets) - (member "TEXT" targets))))) + (let ((chosen-action nil)) + (not (and (or (eq action 'XdndActionCopy) + (eq action 'XdndActionMove)) + (not (and x-dnd-use-offix-drop local-selection-data + (or (not (eq x-dnd-use-offix-drop 'files)) + (member "FILE_NAME" targets)) + (when (x-dnd-do-offix-drop targets x + y frame window-id + local-selection-data) + (setq chosen-action 'XdndActionCopy)))) + (let ((delegate-p (or (member "STRING" targets) + (member "UTF8_STRING" targets) + (member "COMPOUND_TEXT" targets) + (member "TEXT" targets)))) + (prog1 delegate-p + ;; A string will avoid the drop emulation done in C + ;; code, but won't be returned from `x-begin-drag'. + (setq chosen-action (unless delegate-p "")))))) + chosen-action)) (defvar x-dnd-targets-list) (defvar x-dnd-native-test-function) diff --git a/src/keyboard.c b/src/keyboard.c index 4cac20eb4b..bed8307b6f 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4036,56 +4036,6 @@ kbd_buffer_get_event (KBOARD **kbp, } break; -#ifdef HAVE_X_WINDOWS - case UNSUPPORTED_DROP_EVENT: - { - struct frame *f; - - kbd_fetch_ptr = next_kbd_event (event); - input_pending = readable_events (0); - - /* This means this event was already handled in - `x_dnd_begin_drag_and_drop'. */ - if (event->ie.modifiers < x_dnd_unsupported_event_level) - break; - - f = XFRAME (event->ie.frame_or_window); - - if (!FRAME_LIVE_P (f)) - break; - - if (!NILP (Vx_dnd_unsupported_drop_function)) - { - if (!NILP (call8 (Vx_dnd_unsupported_drop_function, - XCAR (XCDR (event->ie.arg)), event->ie.x, - event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))), - make_uint (event->ie.code), - event->ie.frame_or_window, - make_int (event->ie.timestamp), - Fcopy_sequence (XCAR (event->ie.arg))))) - break; - } - - /* `x-dnd-unsupported-drop-function' could have deleted the - event frame. */ - if (!FRAME_LIVE_P (f) - /* This means `x-dnd-use-unsupported-drop' was nil when the - event was generated. */ - || NILP (XCAR (XCDR (XCDR (XCDR (event->ie.arg)))))) - break; - - x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f), - event->ie.frame_or_window, - XCAR (event->ie.arg), - XCAR (XCDR (event->ie.arg)), - (Window) event->ie.code, - XFIXNUM (event->ie.x), - XFIXNUM (event->ie.y), - event->ie.timestamp); - break; - } -#endif - case MONITORS_CHANGED_EVENT: { kbd_fetch_ptr = next_kbd_event (event); diff --git a/src/termhooks.h b/src/termhooks.h index a1e3e2cde9..c5f1e286e9 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -209,30 +209,6 @@ enum event_kind representation of the dropped items. .timestamp gives a timestamp (in milliseconds) for the click. */ -#ifdef HAVE_X_WINDOWS - UNSUPPORTED_DROP_EVENT, /* Event sent when the regular C - drag-and-drop machinery could not - handle a drop to a window. - - .code is the XID of the window that - could not be dropped to. - - .arg is a list of the local value of - XdndSelection, a list of selection - targets, and the intended action to - be taken upon drop, and .timestamp - gives the timestamp where the drop - happened. - - .modifiers gives a number that - determines if an event was already - handled by - `x_dnd_begin_drag_and_drop'. - - .x and .y give the coordinates of - the drop originating from the root - window. */ -#endif USER_SIGNAL_EVENT, /* A user signal. code is a number identifying it, index into lispy_user_signals. */ diff --git a/src/xterm.c b/src/xterm.c index c83ddc6b9e..061bca0684 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1128,10 +1128,6 @@ static Window x_get_window_below (Display *, Window, int, int, int *, int *); /* Flag that indicates if a drag-and-drop operation is in progress. */ bool x_dnd_in_progress; -/* Number that indicates the last "generation" of - UNSUPPORTED_DROP_EVENTs handled. */ -unsigned x_dnd_unsupported_event_level; - /* The frame where the drag-and-drop operation originated. */ struct frame *x_dnd_frame; @@ -1146,6 +1142,20 @@ struct frame *x_dnd_finish_frame; important information. */ bool x_dnd_waiting_for_finish; +/* Flag that means (when set in addition to + `x_dnd_waiting_for_finish') to run the unsupported drop function + with the given arguments. */ +static bool x_dnd_run_unsupported_drop_function; + +/* The "before"-time of the unsupported drop. */ +static Time x_dnd_unsupported_drop_time; + +/* The target window of the unsupported drop. */ +static Window x_dnd_unsupported_drop_window; + +/* The Lisp data associated with the unsupported drop function. */ +static Lisp_Object x_dnd_unsupported_drop_data; + /* Whether or not to move the tooltip along with the mouse pointer during drag-and-drop. */ static bool x_dnd_update_tooltip; @@ -3881,12 +3891,10 @@ static void x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_window, int root_x, int root_y, Time before) { - struct input_event ie; Lisp_Object targets, arg; int i; char **atom_names, *name; - EVENT_INIT (ie); targets = Qnil; atom_names = alloca (sizeof *atom_names * x_dnd_n_targets); @@ -3894,8 +3902,6 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo x_dnd_n_targets, atom_names)) return; - x_dnd_action = dpyinfo->Xatom_XdndActionPrivate; - for (i = x_dnd_n_targets; i > 0; --i) { targets = Fcons (build_string (atom_names[i - 1]), @@ -3914,20 +3920,17 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo else arg = Qnil; - ie.kind = UNSUPPORTED_DROP_EVENT; - ie.code = (unsigned) target_window; - ie.modifiers = x_dnd_unsupported_event_level; - ie.arg = list4 (assq_no_quit (QXdndSelection, - dpyinfo->terminal->Vselection_alist), - targets, arg, (x_dnd_use_unsupported_drop - ? Qt : Qnil)); - ie.timestamp = before; - - XSETINT (ie.x, root_x); - XSETINT (ie.y, root_y); - XSETFRAME (ie.frame_or_window, x_dnd_frame); + x_dnd_run_unsupported_drop_function = true; + x_dnd_unsupported_drop_time = before; + x_dnd_unsupported_drop_window = target_window; + x_dnd_unsupported_drop_data + = listn (5, assq_no_quit (QXdndSelection, + dpyinfo->terminal->Vselection_alist), + targets, arg, make_fixnum (root_x), + make_fixnum (root_y)); - kbd_buffer_store_event (&ie); + x_dnd_waiting_for_finish = true; + x_dnd_finish_display = dpyinfo->display; } static Window @@ -4529,10 +4532,14 @@ x_free_dnd_targets (void) x_dnd_n_targets = 0; } +/* Clear some Lisp variables after the drop finishes, so they are + freed by the GC. */ + static void -x_clear_dnd_monitors (void) +x_clear_dnd_variables (void) { x_dnd_monitors = Qnil; + x_dnd_unsupported_drop_data = Qnil; } static void @@ -11311,7 +11318,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, XWindowAttributes root_window_attrs; struct input_event hold_quit; char *atom_name, *ask_actions; - Lisp_Object action, ltimestamp; + Lisp_Object action, ltimestamp, val; specpdl_ref ref, count, base; ptrdiff_t i, end, fill; XTextProperty prop; @@ -11324,9 +11331,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #ifndef USE_GTK struct x_display_info *event_display; #endif - union buffered_input_event *events, *event; - int n_events; - struct frame *event_frame; base = SPECPDL_INDEX (); @@ -11334,70 +11338,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, Fx_begin_drag. */ specbind (Qx_dnd_targets_list, selection_target_list); - /* Before starting drag-and-drop, walk through the keyboard buffer - to see if there are any UNSUPPORTED_DROP_EVENTs, and run them now - if they exist, to prevent race conditions from happening due to - multiple unsupported drops running at once. */ - - block_input (); - events = alloca (sizeof *events * KBD_BUFFER_SIZE); - n_events = 0; - event = kbd_fetch_ptr; - - while (event != kbd_store_ptr) - { - if (event->ie.kind == UNSUPPORTED_DROP_EVENT - && event->ie.modifiers < x_dnd_unsupported_event_level) - events[n_events++] = *event; - - event = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 - ? kbd_buffer : event + 1); - } - - x_dnd_unsupported_event_level += 1; - unblock_input (); - - for (i = 0; i < n_events; ++i) - { - maybe_quit (); - - event = &events[i]; - event_frame = XFRAME (event->ie.frame_or_window); - - if (!FRAME_LIVE_P (event_frame)) - continue; - - if (!NILP (Vx_dnd_unsupported_drop_function)) - { - if (!NILP (call8 (Vx_dnd_unsupported_drop_function, - XCAR (XCDR (event->ie.arg)), event->ie.x, - event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))), - make_uint (event->ie.code), - event->ie.frame_or_window, - make_int (event->ie.timestamp), - Fcopy_sequence (XCAR (event->ie.arg))))) - continue; - } - - /* `x-dnd-unsupported-drop-function' could have deleted the - event frame. */ - if (!FRAME_LIVE_P (event_frame) - /* This means `x-dnd-use-unsupported-drop' was nil when the - event was generated. */ - || NILP (XCAR (XCDR (XCDR (XCDR (event->ie.arg)))))) - continue; - - x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (event_frame), - event->ie.frame_or_window, - XCAR (event->ie.arg), - XCAR (XCDR (event->ie.arg)), - (Window) event->ie.code, - XFIXNUM (event->ie.x), - XFIXNUM (event->ie.y), - event->ie.timestamp); - break; - } - if (!FRAME_VISIBLE_P (f)) error ("Frame must be visible"); @@ -11500,6 +11440,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, unbind_to (count, Qnil); } + record_unwind_protect_void (x_clear_dnd_variables); + if (follow_tooltip) { #if defined HAVE_XRANDR || defined USE_GTK @@ -11510,8 +11452,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #endif x_dnd_monitors = Fx_display_monitor_attributes_list (frame); - - record_unwind_protect_void (x_clear_dnd_monitors); } x_dnd_update_tooltip = follow_tooltip; @@ -11558,6 +11498,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_xm_use_help = false; x_dnd_motif_setup_p = false; x_dnd_end_window = None; + x_dnd_run_unsupported_drop_function = false; x_dnd_use_toplevels = x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_client_list_stacking); x_dnd_toplevels = NULL; @@ -11812,6 +11753,50 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, unbind_to (ref, Qnil); } + if (x_dnd_run_unsupported_drop_function + && x_dnd_waiting_for_finish) + { + x_dnd_run_unsupported_drop_function = false; + x_dnd_waiting_for_finish = false; + x_dnd_unwind_flag = true; + + ref = SPECPDL_INDEX (); + record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f); + + if (!NILP (Vx_dnd_unsupported_drop_function)) + val = call8 (Vx_dnd_unsupported_drop_function, + XCAR (XCDR (x_dnd_unsupported_drop_data)), + Fnth (make_fixnum (3), x_dnd_unsupported_drop_data), + Fnth (make_fixnum (4), x_dnd_unsupported_drop_data), + Fnth (make_fixnum (2), x_dnd_unsupported_drop_data), + make_uint (x_dnd_unsupported_drop_window), + frame, make_uint (x_dnd_unsupported_drop_time), + Fcopy_sequence (XCAR (x_dnd_unsupported_drop_data))); + else + val = Qnil; + + if (NILP (val)) + x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f), + frame, XCAR (x_dnd_unsupported_drop_data), + XCAR (XCDR (x_dnd_unsupported_drop_data)), + x_dnd_unsupported_drop_window, + XFIXNUM (Fnth (make_fixnum (3), + x_dnd_unsupported_drop_data)), + XFIXNUM (Fnth (make_fixnum (4), + x_dnd_unsupported_drop_data)), + x_dnd_unsupported_drop_time); + + if (SYMBOLP (val)) + x_dnd_action_symbol = val; + + x_dnd_unwind_flag = false; + unbind_to (ref, Qnil); + + /* Break out of the loop now, since DND has + completed. */ + break; + } + #ifdef USE_GTK if (xg_pending_quit_event.kind != NO_EVENT) { @@ -27809,6 +27794,9 @@ syms_of_xterm (void) x_dnd_selection_alias_cell = Fcons (Qnil, Qnil); staticpro (&x_dnd_selection_alias_cell); + x_dnd_unsupported_drop_data = Qnil; + staticpro (&x_dnd_unsupported_drop_data); + DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); DEFSYM (Qlatin_1, "latin-1"); DEFSYM (Qnow, "now"); @@ -28033,7 +28021,6 @@ mouse position list. */); DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function, doc: /* Function called when trying to drop on an unsupported window. - This function is called whenever the user tries to drop something on a window that does not support either the XDND or Motif protocols for drag-and-drop. It should return a non-nil value if the drop was @@ -28046,8 +28033,11 @@ where the drop happened, ACTION is the action that was passed to `x-begin-drag', FRAME is the frame which initiated the drag-and-drop operation, TIME is the X server time when the drop happened, and LOCAL-SELECTION is the contents of the `XdndSelection' when -`x-begin-drag' was run, which can be passed to -`x-get-local-selection'. */); +`x-begin-drag' was run; its contents can be retrieved by calling the +function `x-get-local-selection'. + +If a symbol is returned, then it will be used as the return value of +`x-begin-drag'. */); Vx_dnd_unsupported_drop_function = Qnil; DEFVAR_INT ("x-color-cache-bucket-size", x_color_cache_bucket_size, diff --git a/src/xterm.h b/src/xterm.h index 76d35aaf34..eee7672426 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1669,7 +1669,6 @@ extern bool x_dnd_in_progress; extern bool x_dnd_waiting_for_finish; extern struct frame *x_dnd_frame; extern struct frame *x_dnd_finish_frame; -extern unsigned x_dnd_unsupported_event_level; extern int x_error_message_count; #ifdef HAVE_XINPUT2 commit 154634dcf0efb3e304b077ba532ae11ab8ed724d Author: Stefan Kangas Date: Fri Jul 1 20:18:31 2022 +0200 Use command substitution in kmacro.el * lisp/kmacro.el (kmacro-bind-to-key, kmacro-view-macro-repeat): Use command substitution. diff --git a/lisp/kmacro.el b/lisp/kmacro.el index ea60bc35f2..14be909722 100644 --- a/lisp/kmacro.el +++ b/lisp/kmacro.el @@ -875,8 +875,8 @@ KEYS should be a vector or a string that obeys `key-valid-p'." (defun kmacro-bind-to-key (_arg) "When not defining or executing a macro, offer to bind last macro to a key. -The key sequences `C-x C-k 0' through `C-x C-k 9' and `C-x C-k A' -through `C-x C-k Z' are reserved for user bindings, and to bind to +The key sequences \\`C-x C-k 0' through \\`C-x C-k 9' and \\`C-x C-k A' +through \\`C-x C-k Z' are reserved for user bindings, and to bind to one of these sequences, just enter the digit or letter, rather than the whole sequence. @@ -1002,7 +1002,7 @@ The ARG parameter is unused." "Display the last keyboard macro. If repeated, it shows previous elements in the macro ring. To execute the displayed macro ring item without changing the macro ring, -just enter C-k. +just enter \\`C-k'. This is like `kmacro-view-macro', but allows repeating macro commands without repeating the prefix." (interactive) commit 1dc70544d866bf92167777045149ff86900b6e33 Author: Stefan Kangas Date: Fri Jul 1 08:50:47 2022 +0200 * doc/misc/erc.texi (Connecting): Fix typo. diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index 3f81c2cece..3db83197f9 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -813,7 +813,7 @@ machine irc.libera.chat login MyNick password sEcReT @noindent Remember that field labels vary per backend, so @samp{machine} (in netrc's case) maps to auth-source's generalized notion of a host, -hence the @samp{:host} keyword property. Also, be sure and mind the +hence the @samp{:host} keyword property. Also, be sure to mind the syntax of your chosen backend medium. For example, always quote channel names in a netrc file. commit 1c3d107cb5367098d592b69d02beedd7aa9ded16 Author: Eli Zaretskii Date: Fri Jul 1 17:17:36 2022 +0300 Fix "C-u C-x =" for SPC * lisp/descr-text.el (describe-char): Don't report 'nobreak-space' face for SPC. (Bug#56337) diff --git a/lisp/descr-text.el b/lisp/descr-text.el index 4234deb73a..7427817a8e 100644 --- a/lisp/descr-text.el +++ b/lisp/descr-text.el @@ -690,6 +690,7 @@ The character information includes: (looking-at-p "[ \t]+$"))) 'trailing-whitespace) ((and nobreak-char-display char + (> char 127) (eq (get-char-code-property char 'general-category) 'Zs)) 'nobreak-space) ((and nobreak-char-display char commit 405d4723d96711151228cd1d0c9c3100dd0d6a96 Author: F. Jason Park Date: Fri Jul 1 05:54:03 2022 -0700 ; * doc/misc/erc.texi: Fix typo diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index cf19f1e32a..3f81c2cece 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -789,7 +789,7 @@ If ERC can't find a suitable server password, it will just skip the IRC CertFP or engaging NickServ via ERC's ``services'' module. If that is what you'd like to do, you can also customize the option @code{erc-auth-source-server-function} to @code{nil} to skip -server-passwork lookup for all servers. Note that some networks and +server-password lookup for all servers. Note that some networks and IRCds may accept account-services authentication via server password using the nonstandard @samp{mynick:sEcReT} convention. commit 0a0ec8958a3026d04101a0501d117a0195df8097 Author: F. Jason Park Date: Fri Jul 1 05:47:31 2022 -0700 ; Fix regexp in ERC test-server utility * test/lisp/erc/resources/erc-d/erc-d-i.el (erc-d-i--tag-unescaped-regexp): Thanks to Mattias and relint for catching this. diff --git a/test/lisp/erc/resources/erc-d/erc-d-i.el b/test/lisp/erc/resources/erc-d/erc-d-i.el index 27b1bf6083..db113335a8 100644 --- a/test/lisp/erc/resources/erc-d/erc-d-i.el +++ b/test/lisp/erc/resources/erc-d/erc-d-i.el @@ -39,14 +39,14 @@ UTF-8 text before parsing, which is nonstandard." (defconst erc-d-i--tag-escapes '((";" . "\\:") (" " . "\\s") ("\\" . "\\\\") ("\r" . "\\r") ("\n" . "\\n"))) -;; XXX these are not mirror inverses; unescaping may degenerate -;; original by dropping stranded/misplaced backslashes. +;; These are not mirror inverses; unescaping may drop stranded or +;; misplaced backslashes. (defconst erc-d-i--tag-escaped-regexp (rx (or ?\; ?\ ?\\ ?\r ?\n))) (defconst erc-d-i--tag-unescaped-regexp (rx (or "\\:" "\\s" "\\\\" "\\r" "\\n" - (seq "\\" (or string-end (not (or ":" "n" "r" "\\"))))))) + (seq "\\" (or string-end (not (or ":" "s" "n" "r" "\\"))))))) (defun erc-d-i--unescape-tag-value (str) "Undo substitution of char placeholders in raw tag value STR." @@ -65,8 +65,6 @@ UTF-8 text before parsing, which is nonstandard." (defconst erc-d-i--invalid-tag-regexp (rx (any "\0\7\r\n; "))) -;; This is `erc-v3-message-tags' with fatal errors. - (defun erc-d-i--validate-tags (raw) "Validate tags portion of some RAW incoming message. RAW must not have a leading \"@\" or a trailing space. The spec says commit 8a098f6517157ebe2364f08008b44ab49c2d1115 Author: Eli Zaretskii Date: Fri Jul 1 16:17:40 2022 +0300 Fix quoting of file names in 'ctags' * lib-src/etags.c (main) [WINDOWSNT || MSDOS]: Quote file names according to the rules of the system shells. diff --git a/lib-src/etags.c b/lib-src/etags.c index 9a60714eca..ef11257926 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -1431,6 +1431,16 @@ main (int argc, char **argv) setenv ("LC_COLLATE", "C", 1); setenv ("LC_ALL", "C", 1); */ char *cmd = xmalloc (8 * strlen (tagfile) + sizeof "sort -u -o '' ''"); +#if defined WINDOWSNT || defined MSDOS + /* Quote "like this". No need to escape the quotes in the file name, + since it is not allowed in file names on these systems. */ + char *z = stpcpy (cmd, "sort -u -o \""); + z = stpcpy (z, tagfile); + z = stpcpy (z, "\" \""); + z = stpcpy (z, tagfile); + stpcpy (z, "\""); +#else + /* Quote 'like this', and escape the apostrophe in the file name. */ char *z = stpcpy (cmd, "sort -u -o '"); char *escaped_tagfile = z; for (; *tagfile; *z++ = *tagfile++) @@ -1440,6 +1450,7 @@ main (int argc, char **argv) z = stpcpy (z, "' '"); z = mempcpy (z, escaped_tagfile, escaped_tagfile_len); strcpy (z, "'"); +#endif return system (cmd); } return EXIT_SUCCESS; commit 474f5b21b43efd4c2f60bfdfa385c8b522bf12c8 Author: Lars Ingebrigtsen Date: Fri Jul 1 13:45:52 2022 +0200 Add support for in shr * lisp/net/shr.el (shr-mark): New face (bug#48211). (shr-tag-mark): New function diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 0645f4721a..63f313bbf4 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -232,6 +232,11 @@ temporarily blinks with this face." "Face used for rendering blocks." :version "29.1") +(defface shr-mark + '((t :background "yellow" :foreground "black")) + "Face used for elements." + :version "29.1") + (defcustom shr-inhibit-images nil "If non-nil, inhibit loading images." :version "28.1" @@ -1422,6 +1427,14 @@ ones, in case fg and bg are nil." ;; The `tt' tag is deprecated in favor of `code'. (shr-tag-code dom)) +(defun shr-tag-mark (dom) + (when (and (not (bobp)) + (not (= (char-after (1- (point))) ?\s))) + (insert " ")) + (let ((start (point))) + (shr-generic dom) + (shr-add-font start (point) 'shr-mark))) + (defun shr-tag-ins (cont) (let* ((start (point)) (color "green") commit 3a4c408a7b6f3df5ca0eb4a406efbdb4899e9742 Author: Lars Ingebrigtsen Date: Fri Jul 1 13:19:31 2022 +0200 Fix elisp-byte-compile-buffer requirements * lisp/progmodes/elisp-mode.el (elisp-byte-compile-buffer): Require bytecomp so that byte-compile-dest-file-function is defined. (The byte compiler didn't catch this, because it's defined in bytecomp.) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index fb114ec990..0c4a9bfdbe 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -2223,6 +2223,7 @@ interactively, this is the prefix argument." (interactive "P") (let ((bfn buffer-file-name) file elc) + (require 'bytecomp) (unwind-protect (progn (setq file (make-temp-file "compile" nil ".el") commit 467a02d69efa462da5459c94d6110900b7929e73 Author: dick r. chiang Date: Fri Jul 1 12:49:36 2022 +0200 Fix typo in Property Search manual entry * doc/lispref/text.texi (Property Search): Fix typo (bug#56329). diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index 622f03d2a8..0c04d01261 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -3485,7 +3485,7 @@ This will give you a list of all those URLs. @end defun @defun text-property-search-backward prop &optional value predicate not-current -This is just like @code{text-property-search-backward}, but searches +This is just like @code{text-property-search-forward}, but searches backward instead. Point is placed at the beginning of the matched region instead of the end, though. @end defun commit 83e45596643c4586ecaecd024212b8c6cef11d2c Author: Lars Ingebrigtsen Date: Fri Jul 1 12:12:49 2022 +0200 Make time-stamp-tests.el work in a Norwegian language enviroment The short version of names for days/month is not necessary the same as limiting the string with a #n operator. For instance: (format-time-string "%^A" time) => "FREDAG" (format-time-string "%^a" time) => "FR." (time-stamp-string "%#3a" time) => "FRE" diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el index d52a19ef5d..8361d58b55 100644 --- a/test/lisp/time-stamp-tests.el +++ b/test/lisp/time-stamp-tests.el @@ -271,7 +271,8 @@ (should (equal (time-stamp-string "%3a" ref-time1) Mon)) (should (equal (time-stamp-string "%#A" ref-time1) MONDAY)) ;; documented 1997-2019 - (should (equal (time-stamp-string "%3A" ref-time1) MON)) + (should (equal (time-stamp-string "%3A" ref-time1) + (substring MONDAY 0 3))) (should (equal (time-stamp-string "%:a" ref-time1) Monday)) ;; implemented since 2001, documented since 2019 (should (equal (time-stamp-string "%#a" ref-time1) MON)) @@ -291,10 +292,12 @@ (January (format-time-string "%B" ref-time1 t)) (JANUARY (format-time-string "%^B" ref-time1 t))) ;; implemented and documented since 1997 - (should (equal (time-stamp-string "%3b" ref-time1) Jan)) + (should (equal (time-stamp-string "%3b" ref-time1) + (substring January 0 3))) (should (equal (time-stamp-string "%#B" ref-time1) JANUARY)) ;; documented 1997-2019 - (should (equal (time-stamp-string "%3B" ref-time1) JAN)) + (should (equal (time-stamp-string "%3B" ref-time1) + (substring JANUARY 0 3))) (should (equal (time-stamp-string "%:b" ref-time1) January)) ;; implemented since 2001, documented since 2019 (should (equal (time-stamp-string "%#b" ref-time1) JAN)) @@ -652,15 +655,17 @@ (should (equal (time-stamp-string "%0b" ref-time3) "")) (should (equal (time-stamp-string "%1b" ref-time3) (substring May 0 1))) (should (equal (time-stamp-string "%2b" ref-time3) (substring May 0 2))) - (should (equal (time-stamp-string "%3b" ref-time3) May)) + (should (equal (time-stamp-string "%3b" ref-time3) (substring May 0 3))) (should (equal (time-stamp-string "%4b" ref-time3) (concat " " May))) (should (equal (time-stamp-string "%0%" ref-time3) "")) (should (equal (time-stamp-string "%1%" ref-time3) "%")) (should (equal (time-stamp-string "%2%" ref-time3) " %")) (should (equal (time-stamp-string "%9%" ref-time3) " %")) (should (equal (time-stamp-string "%10%" ref-time3) " %")) - (should (equal (time-stamp-string "%#3a" ref-time3) SUN)) - (should (equal (time-stamp-string "%#3b" ref-time2) NOV))))) + (should (equal (time-stamp-string "%#3a" ref-time3) + (substring SUN 0 3))) + (should (equal (time-stamp-string "%#3b" ref-time2) + (substring NOV 0 3)))))) ;;; Tests of helper functions commit 12e5171882afb2bb31e3505cb077953b342920af Author: Po Lu Date: Fri Jul 1 18:10:39 2022 +0800 Document XDS stuff * doc/emacs/frames.texi (Drag and Drop): * doc/lispref/frames.texi (Drag and Drop): Add documentation about XDS features. * etc/NEWS: Tag entry. diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index d90a6ac672..d78cbffaa7 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -1249,6 +1249,13 @@ To drag text from Emacs to other programs, set the option @code{mouse-drag-and-drop-region-cross-program} to a non-@code{nil} value. + On the X window system, some programs can drop files on Emacs, +expecting Emacs to save them. Normally, Emacs will prompt for a file +name under which the file will be saved, and then open the file, but +that behavior can be changed by changing the variable +@code{x-dnd-direct-save-function}. @xref{Drag and Drop,,, elisp, The +Emacs Lisp Reference Manual}. + @node Menu Bars @section Menu Bars @cindex menu bar mode diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index f7491502f4..f655ccdfa7 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4090,6 +4090,20 @@ They can either be the same data types that are typically accepted by specific drag-n-drop protocol being used. Plain text may be @code{"STRING"} or @code{"text/plain"}, for example. +@vindex x-dnd-direct-save-function + However, @code{x-dnd-types-alist} does not handle a special kind of +drop sent by a program which wants Emacs to save a file in a location +Emacs must determine by itself. These drops are handled via the +variable @code{x-dnd-direct-save-function}, which should be a function +that accepts two arguments. If the first argument is non-@code{nil}, +then the second argument is a string describing the name (with no +leading directory) that the other program recommends the file be saved +under, and the function should return the complete file name under +which it will be saved. Otherwise, the file has already been saved, +and the second argument is the complete name of the file. The +function should then perform whatever action is appropriate (i.e., +open the file or refresh the directory listing.) + @cindex initiating drag-and-drop On capable window systems, Emacs also supports dragging contents from its frames to windows of other applications. diff --git a/etc/NEWS b/etc/NEWS index b0a5cd4f1d..3127e73426 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -423,6 +423,7 @@ This inhibits putting empty strings onto the kill ring. These options allow adjusting point and scrolling a window when dragging items from another program. ++++ ** The X Direct Save (XDS) protocol is now supported. This means dropping an image or file link from programs such as Firefox will no longer create a temporary file in a random directory, commit 45ba6a3104f9eb8a68e248a998e5f7cb4c99f8b7 Author: Lars Ingebrigtsen Date: Fri Jul 1 11:49:29 2022 +0200 Make it easier to debug nnimap-retrieve-headers * lisp/gnus/nnimap.el (nnimap--max-retrieve-headers): New variable to ease debugging. (nnimap-retrieve-headers): Use it. diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index a69b5c7727..22edc3c72c 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -233,6 +233,8 @@ during splitting, which may be slow." params) (format "%s" (nreverse params)))) +(defvar nnimap--max-retrieve-headers 200) + (deffoo nnimap-retrieve-headers (articles &optional group server _fetch-old) (with-current-buffer nntp-server-buffer (erase-buffer) @@ -249,9 +251,10 @@ during splitting, which may be slow." (setq sequence (nnimap-send-command "UID FETCH %s %s" - (nnimap-article-ranges (seq-take ranges 200)) + (nnimap-article-ranges + (seq-take ranges nnimap--max-retrieve-headers)) (nnimap-header-parameters))) - (setq ranges (nthcdr 200 ranges))) + (setq ranges (nthcdr nnimap--max-retrieve-headers ranges))) ;; Wait for the final one. (nnimap-wait-for-response sequence t)) (unless (process-live-p (get-buffer-process (current-buffer))) commit d0e15c3814665b57c005b4e05000e712841463f1 Author: Lars Ingebrigtsen Date: Fri Jul 1 11:11:47 2022 +0200 Make the emoji-zoom commands use a transient map for repetition * lisp/international/emoji.el (emoji-zoom-increase) (emoji-zoom-decrease): Use a transient map for convenience. diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index 6a65bc43dc..b108788571 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -707,10 +707,12 @@ We prefer the earliest unique letter." ;;;###autoload (defun emoji-zoom-increase (&optional factor) "Increase the size of the character under point. -FACTOR is the multiplication factor for the size. - -This command will be repeatable if `repeat-mode' is switched on." +FACTOR is the multiplication factor for the size." (interactive) + (message + (substitute-command-keys + "Zoom with with \\\\[emoji-zoom-increase] and \\[emoji-zoom-decrease]")) + (set-transient-map emoji-zoom-map t) (let* ((factor (or factor 1.1)) (old (get-text-property (point) 'face)) (height (or (and (consp old) @@ -728,18 +730,12 @@ This command will be repeatable if `repeat-mode' is switched on." (put-text-property (point) (1+ (point)) 'rear-nonsticky t))))) -(put 'emoji-zoom-increase 'repeat-map 'emoji-zoom-map) - ;;;###autoload (defun emoji-zoom-decrease () - "Decrease the size of the character under point. - -This command will be repeatable if `repeat-mode' is switched on." + "Decrease the size of the character under point." (interactive) (emoji-zoom-increase 0.9)) -(put 'emoji-zoom-decrease 'repeat-map 'emoji-zoom-map) - (provide 'emoji) ;;; emoji.el ends here commit bffca6070f4614a5075100082ce5a3c8bba6df77 Author: Mattias Engdegård Date: Fri Jul 1 11:00:41 2022 +0200 ; * test/lisp/erc/erc-networks-tests.el: escape `*`s in regexp diff --git a/test/lisp/erc/erc-networks-tests.el b/test/lisp/erc/erc-networks-tests.el index 417ee94cf0..66a334b709 100644 --- a/test/lisp/erc/erc-networks-tests.el +++ b/test/lisp/erc/erc-networks-tests.el @@ -1187,7 +1187,7 @@ nil (make-erc-response))))) (should (string-match-p "failed" (cadr err))) (should (eq (car err) 'error))) - (should (string-match-p "*** Failed" (car (pop calls))))))) + (should (string-match-p (rx "*** Failed") (car (pop calls))))))) (erc-networks-tests--clean-bufs))) commit 06cd24698e0b04b9d1f3292af4517f33c5f3767b Author: Po Lu Date: Fri Jul 1 16:32:37 2022 +0800 Expand file names read from XDS functions * lisp/x-dnd.el (x-dnd-handle-xds-drop): Expand file names before use. Some GUI dialogs read un-expanded file names. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index efd774f4e9..d78f926ee7 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -1369,8 +1369,9 @@ VERSION is the version of the XDND protocol understood by SOURCE." desired-name (or file-name-coding-system default-file-name-coding-system))) - (setq save-to (funcall x-dnd-direct-save-function - t desired-name)) + (setq save-to (expand-file-name + (funcall x-dnd-direct-save-function + t desired-name))) (when save-to (with-selected-window window (let ((uri (format "file://%s%s" (system-name) save-to))) commit b55059bbeb8577a371f54d1750a31786f5ab5b7f Author: Po Lu Date: Fri Jul 1 16:17:11 2022 +0800 Prevent XdndPosition messages from rarely being sent out of band * src/xterm.c (handle_one_xevent): Don't clear `x_dnd_waiting_for_status_window' if a pending position message was sent in reply to an XdndStatus event. diff --git a/src/xterm.c b/src/xterm.c index fa43371f05..c83ddc6b9e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -16456,10 +16456,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, XSendEvent (dpyinfo->display, target, False, NoEventMask, &x_dnd_pending_send_position); - } + x_dnd_pending_send_position.type = 0; - x_dnd_pending_send_position.type = 0; - x_dnd_waiting_for_status_window = None; + /* Since we sent another XdndPosition message, we + have to wait for another one in reply, so don't + reset `x_dnd_waiting_for_status_window' + here. */ + } + else + x_dnd_waiting_for_status_window = None; } goto done; commit ea5f5f81dd172ce40f10cd5e276d23839c24cbc1 Author: Po Lu Date: Fri Jul 1 16:12:45 2022 +0800 Support receiving XDS drops correctly * etc/NEWS: Announce new feature. It is not yet documented. * lisp/x-dnd.el (x-dnd-known-types): Add XdndDirectSave0. (x-dnd-direct-save-function): New defcustom. (x-dnd-xdnd-to-action): Add `direct-save'. (x-dnd-maybe-call-test-function): If XDS is present, use `direct-save'. (x-dnd-find-type): New function. (x-dnd-handle-xdnd): Handle XDS position and drop messages. (x-dnd-handle-direct-save): Don't use local-file-uri if nil. (x-dnd-save-direct): New function. (x-dnd-handle-octet-stream-for-drop): (x-dnd-handle-xds-drop): New functions. diff --git a/etc/NEWS b/etc/NEWS index d3dd896526..b0a5cd4f1d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -423,6 +423,11 @@ This inhibits putting empty strings onto the kill ring. These options allow adjusting point and scrolling a window when dragging items from another program. +** The X Direct Save (XDS) protocol is now supported. +This means dropping an image or file link from programs such as +Firefox will no longer create a temporary file in a random directory, +instead asking you where to save the file first. + +++ ** New user option 'record-all-keys'. If non-nil, this option will force recording of all input keys, diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 43905e1bb0..efd774f4e9 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -84,7 +84,8 @@ if drop is successful, nil if not." (defcustom x-dnd-known-types (mapcar 'purecopy - '("text/uri-list" + '("XdndDirectSave0" + "text/uri-list" "text/x-moz-url" "_NETSCAPE_URL" "FILE_NAME" @@ -120,6 +121,24 @@ like xterm) for text." (const :tag "Use the OffiX protocol for both files and text" t)) :group 'x) +(defcustom x-dnd-direct-save-function #'x-dnd-save-direct + "Function called when a file is dropped that Emacs must save. +It is called with two arguments: the first is either nil or t, +and the second is a string. + +If the first argument is t, the second argument is the name the +dropped file should be saved under. The function should return a +complete local file name describing where the file should be +saved. + +It can also return nil, which means to cancel the drop. + +If the first argument is nil, the second is the name of the file +that was dropped." + :version "29.1" + :type 'function + :group 'x) + ;; Internal variables (defvar x-dnd-current-state nil @@ -144,7 +163,8 @@ any protocol specific data.") ("XdndActionCopy" . copy) ("XdndActionMove" . move) ("XdndActionLink" . link) - ("XdndActionAsk" . ask)) + ("XdndActionAsk" . ask) + ("XdndActionDirectSave" . direct-save)) "Mapping from XDND action types to Lisp symbols.") (defvar x-dnd-empty-state [nil nil nil nil nil nil nil]) @@ -199,29 +219,49 @@ FRAME-OR-WINDOW is the frame or window that the mouse is over." (setcdr (x-dnd-get-state-cons-for-frame frame-or-window) (copy-sequence x-dnd-empty-state))) -(defun x-dnd-maybe-call-test-function (window action) +(defun x-dnd-find-type (target types) + "Find the type TARGET in an array of types TYPES. +TARGET must be a string, but TYPES can contain either symbols or +strings." + (catch 'done + (dotimes (i (length types)) + (let* ((type (aref types i)) + (typename (if (symbolp type) + (symbol-name type) type))) + (when (equal target typename) + (throw 'done t)))) + nil)) + +(defun x-dnd-maybe-call-test-function (window action &optional xdnd) "Call `x-dnd-test-function' if something has changed. WINDOW is the window the mouse is over. ACTION is the suggested action from the source. If nothing has changed, return the last -action and type we got from `x-dnd-test-function'." +action and type we got from `x-dnd-test-function'. + +XDND means the XDND protocol is being used." (let ((buffer (when (window-live-p window) (window-buffer window))) (current-state (x-dnd-get-state-for-frame window))) - (unless (and (equal buffer (aref current-state 0)) - (equal window (aref current-state 1)) - (equal action (aref current-state 3))) - (save-current-buffer - (when buffer (set-buffer buffer)) - (let* ((action-type (funcall x-dnd-test-function - window - action - (aref current-state 2))) - (handler (cdr (assoc (cdr action-type) x-dnd-types-alist)))) - ;; Ignore action-type if we have no handler. - (setq current-state - (x-dnd-save-state window - action - (when handler action-type))))))) + (if (and xdnd (x-dnd-find-type "XdndDirectSave0" + (aref current-state 2))) + (setq current-state + (x-dnd-save-state window 'direct-save + '(direct-save . "XdndDirectSave0"))) + (unless (and (equal buffer (aref current-state 0)) + (equal window (aref current-state 1)) + (equal action (aref current-state 3))) + (save-current-buffer + (when buffer (set-buffer buffer)) + (let* ((action-type (funcall x-dnd-test-function + window + action + (aref current-state 2))) + (handler (cdr (assoc (cdr action-type) x-dnd-types-alist)))) + ;; Ignore action-type if we have no handler. + (setq current-state + (x-dnd-save-state window + action + (when handler action-type)))))))) (let ((current-state (x-dnd-get-state-for-frame window))) (cons (aref current-state 5) (aref current-state 4)))) @@ -597,9 +637,21 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (dnd-source (aref data 0)) (action-type (x-dnd-maybe-call-test-function window - (cdr (assoc action x-dnd-xdnd-to-action)))) - (reply-action (car (rassoc (car action-type) - x-dnd-xdnd-to-action))) + (cdr (assoc action x-dnd-xdnd-to-action)) t)) + (reply-action (car (rassoc + ;; Mozilla and some other programs + ;; support XDS, but only if we + ;; reply with `copy'. We can + ;; recognize these broken programs + ;; by checking to see if + ;; `XdndActionDirectSave' was + ;; originally specified. + (if (and (eq (car action-type) + 'direct-save) + (not (eq action 'direct-save))) + 'copy + (car action-type)) + x-dnd-xdnd-to-action))) (accept ;; 1 = accept, 0 = reject (if (and reply-action action-type ;; Only allow drops on the text area of a @@ -637,34 +689,39 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (version (aref state 6)) (dnd-source (aref data 0)) (timestamp (aref data 2)) - (value (and (x-dnd-current-type window) - (x-get-selection-internal - 'XdndSelection - (intern (x-dnd-current-type window)) - timestamp))) - success action) + (current-action (aref state 5)) + (current-type (aref state 4)) + success action value) (x-display-set-last-user-time timestamp) - (unwind-protect - (setq action (if value - (condition-case info - (x-dnd-drop-data - event frame window value - (x-dnd-current-type window)) - (error - (message "Error: %s" info) - nil)))) - (setq success (if action 1 0)) - (when (>= version 2) - (x-send-client-message - frame dnd-source frame "XdndFinished" 32 - (list (string-to-number - (frame-parameter frame 'outer-window-id)) - (if (>= version 5) success 0) ;; 1 = Success, 0 = Error - (if (or (not success) (< version 5)) 0 - (or (car (rassoc action - x-dnd-xdnd-to-action)) - 0)))))) - (x-dnd-forget-drop window))) + (if (and (eq current-action 'direct-save) + (equal current-type "XdndDirectSave0")) + (x-dnd-handle-xds-drop event window dnd-source version) + (setq value (and (x-dnd-current-type window) + (x-get-selection-internal + 'XdndSelection + (intern (x-dnd-current-type window)) + timestamp))) + (unwind-protect + (setq action (if value + (condition-case info + (x-dnd-drop-data + event frame window value + (x-dnd-current-type window)) + (error + (message "Error: %s" info) + nil)))) + (setq success (if action 1 0)) + (when (>= version 2) + (x-send-client-message + frame dnd-source frame "XdndFinished" 32 + (list (string-to-number + (frame-parameter frame 'outer-window-id)) + (if (>= version 5) success 0) ;; 1 = Success, 0 = Error + (if (or (not action) (< version 5)) 0 + (or (car (rassoc action + x-dnd-xdnd-to-action)) + 0))))) + (x-dnd-forget-drop window))))) (t (error "Unknown XDND message %s %s" message data)))) @@ -1156,7 +1213,8 @@ ACTION is the action given to `x-begin-drag'." (not (equal (match-string 1 uri) ""))) (dnd-get-local-file-uri uri) uri)) - (local-name (dnd-get-local-file-name local-file-uri))) + (local-name (and local-file-uri + (dnd-get-local-file-name local-file-uri)))) (if (not local-name) '(STRING . "F") (condition-case nil @@ -1239,14 +1297,118 @@ was taken, or the direct save failed." (and (stringp property) (not (equal property "")))) action))))) - ;; TODO: check for failure and implement selection-based file - ;; transfer. (unless prop-deleted (x-delete-window-property "XdndDirectSave0" frame)) ;; Delete any remote copy that was made. (when (not (equal file-name original-file-name)) (delete-file file-name))))) +(defun x-dnd-save-direct (need-name name) + "Handle dropping a file that should be saved immediately. +NEED-NAME tells whether or not the file was not yet saved. NAME +is either the name of the file, or the name the drop source wants +us to save under. + +Prompt the user for a file name, then open it." + (if (file-remote-p default-directory) + ;; TODO: figure out what to do with remote files. + nil + (if need-name + (let ((file-name (read-file-name "Write file: " + default-directory + nil nil name))) + (when (file-exists-p file-name) + (unless (y-or-n-p (format-message + "File `%s' exists; overwrite? " file-name)) + (setq file-name nil))) + file-name) + ;; TODO: move this to dired.el once a platform-agonistic + ;; interface can be found. + (if (derived-mode-p 'dired-mode) + (revert-buffer) + (find-file name))))) + +(defun x-dnd-handle-octet-stream-for-drop (save-to) + "Save the contents of the XDS selection to SAVE-TO. +Return non-nil if successful, nil otherwise." + (ignore-errors + (let ((coding-system-for-write 'raw-text) + (data (x-get-selection-internal 'XdndSelection + 'application/octet-stream))) + (when data + (write-region data nil save-to) + t)))) + +(defun x-dnd-handle-xds-drop (event window source version) + "Handle an XDS (X Direct Save) protocol drop. +EVENT is the drag-n-drop event containing the drop. +WINDOW is the window on top of which the drop is supposed to happen. +SOURCE is the X window that sent the drop. +VERSION is the version of the XDND protocol understood by SOURCE." + (if (not (windowp window)) + ;; We can't perform an XDS drop if there's no window from which + ;; to determine the current directory. + (let* ((start (event-start event)) + (frame (posn-window start))) + (x-send-client-message frame source frame + "XdndFinished" 32 + (list (string-to-number + (frame-parameter frame + 'outer-window-id))))) + (let ((desired-name (x-window-property "XdndDirectSave0" + (window-frame window) + ;; We currently don't handle + ;; any alternative character + ;; encodings. + "text/plain" source)) + (frame (window-frame window)) + (success nil) save-to) + (unwind-protect + (when (stringp desired-name) + (setq desired-name (decode-coding-string + desired-name + (or file-name-coding-system + default-file-name-coding-system))) + (setq save-to (funcall x-dnd-direct-save-function + t desired-name)) + (when save-to + (with-selected-window window + (let ((uri (format "file://%s%s" (system-name) save-to))) + (x-change-window-property "XdndDirectSave0" + (encode-coding-string + (url-encode-url uri) 'ascii) + frame "text/plain" 8 nil source) + (let ((result (x-get-selection-internal 'XdndSelection + 'XdndDirectSave0))) + (cond ((equal result "F") + (setq success (x-dnd-handle-octet-stream-for-drop save-to)) + (unless success + (x-change-window-property "XdndDirectSave0" "" + frame "text/plain" 8 + nil source))) + ((equal result "S") + (setq success t)) + ((equal result "E") + (setq success nil)) + (t (error "Broken implementation of XDS: got %s in reply" + result))) + (when success + (funcall x-dnd-direct-save-function nil save-to))))))) + ;; We assume XDS always comes from a client supporting version 2 + ;; or later, since custom actions aren't present before. + (x-send-client-message frame source frame + "XdndFinished" 32 + (list (string-to-number + (frame-parameter frame + 'outer-window-id)) + (if (>= version 5) + (if success 1 0) + 0) + (if (or (not success) + (< version 5)) + 0 + "XdndDirectSave0"))))))) + (provide 'x-dnd) ;;; x-dnd.el ends here commit a08bb27517e840e14c8bb83dc96307a8771ab990 Author: Eli Zaretskii Date: Fri Jul 1 10:13:07 2022 +0300 ; Fix documentation of recent ERC changes * lisp/erc/erc.el (erc-inhibit-multiline-input) (erc-ask-about-multiline-input): Doc fixes. * doc/misc/erc.texi (Connecting): Fix typos, grammar, wording, punctuation, markup, and indexing. diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index 6daa54d956..cf19f1e32a 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -557,6 +557,7 @@ For example, calling the command like so (erc :server "irc.libera.chat" :full-name "J. Random Hacker") @end example +@noindent sets @var{server} and @var{full-name} directly while leaving the rest up to functions like @code{erc-compute-port}. Note that some arguments can't be specified interactively. @var{id}, in particular, @@ -589,6 +590,7 @@ That is, if called in the following manner (erc-tls :server "irc.libera.chat" :full-name "J. Random Hacker") @end example +@noindent the command will set @var{server} and @var{full-name} accordingly, while helpers, like @code{erc-compute-nick}, will determine other parameters, and some, like @code{client-certificate}, will just be @@ -730,14 +732,17 @@ You can manually set another nickname with the /NICK command. @subheading User @defun erc-compute-user &optional user -Determine a suitable value to send for the first argument to the +Determine a suitable value to send as the first argument of the opening @samp{USER} IRC command by consulting the following sources: @itemize -@item @var{user}, the argument passed to this function -@item The option @code{erc-email-userid}, assuming @code{erc-anonymous-login} +@item +@var{user}, the argument passed to this function +@item +The option @code{erc-email-userid}, assuming @code{erc-anonymous-login} is non-@code{nil} -@item The result of calling the function @code{user-login-name} +@item +The result of calling the function @code{user-login-name} @end itemize @end defun @@ -751,9 +756,9 @@ a string abiding by the rules of the network. @cindex password @defopt erc-prompt-for-password -If non-@code{nil} (the default), @kbd{M-x erc} prompts for a server -password. This only affects interactive invocations of @code{erc} and -@code{erc-tls}. +If non-@code{nil} (the default), @kbd{M-x erc} and @kbd{M-x erc-tls} +prompt for a server password. This only affects interactive +invocations of @code{erc} and @code{erc-tls}. @end defopt @noindent @@ -768,32 +773,33 @@ machine irc.example.net login mynick password sEcReT @noindent For server passwords, that is, passwords sent for the IRC @samp{PASS} -command, the @samp{host} field, here @code{machine irc.example.net}, +command, the @samp{host} field (@w{@code{machine irc.example.net}} in +the above example) corresponds to the @var{server} parameter used by @code{erc} and @code{erc-tls}. Unfortunately, specifying a network, like @samp{Libera.Chat}, or a specific network server, like -@samp{platinum.libera.chat}, won't work OOTB for looking up a server +@samp{platinum.libera.chat}, won't normally work for looking up a server password because such information isn't available during opening -introductions. Actually, ERC @emph{can} find entries with arbitrary +introductions. (Actually, ERC @emph{can} find entries with arbitrary @samp{host} values for any context, including server passwords, but -that requires messing with the more advanced options below. +that requires customizing the more advanced options below.) -If ERC can't find a suitable server password, it'll just skip the IRC +If ERC can't find a suitable server password, it will just skip the IRC @samp{PASS} command altogether, something users may want when using -CertFP or engaging NickServ via ERC's ``services'' module. If that -sounds like you, you can also set the option +CertFP or engaging NickServ via ERC's ``services'' module. If that is +what you'd like to do, you can also customize the option @code{erc-auth-source-server-function} to @code{nil} to skip server-passwork lookup for all servers. Note that some networks and IRCds may accept account-services authentication via server password -using the nonstandard ``mynick:sEcReT'' convention. +using the nonstandard @samp{mynick:sEcReT} convention. As just mentioned, you can also use @code{auth-source} to authenticate to account services the traditional way, through a bot called -``NickServ''. To tell ERC to do that, set +@samp{NickServ}. To tell ERC to do that, set @code{erc-use-auth-source-for-nickserv-password} to @code{t}. For these and most other queries, entries featuring custom identifiers and networks are matched first, followed by network-specific servers and -dialed endpoints (typically, the @var{SERVER} passed to +dialed endpoints (typically, the @var{server} argument passed to @code{erc}). The following netrc-style entries appear in order of precedence: @@ -812,7 +818,7 @@ syntax of your chosen backend medium. For example, always quote channel names in a netrc file. If this all seems overly nuanced or just plain doesn't appeal to you, -see options @code{erc-auth-source-services-function} and friends just +see options @code{erc-auth-source-services-function} and friends, described below. These let you query auth-source your way. Most users can simply ignore the passed-in arguments and get by with something like the following: @@ -830,7 +836,7 @@ Lastly, ERC also consults @code{auth-source} to find ``keys'' that may be required by certain channels you join. When modifying a traditional @code{auth-source} entry for this purpose, put the channel name in the @samp{user} field (for example, @samp{login "#fsf"}, in -netrc's case). The actual key goes in the @samp{password} (or +netrc's case). The actual key goes in the @samp{password} (or @samp{secret}) field. @noindent @@ -850,9 +856,10 @@ Generalized names, like @code{:user} and @code{:host}, are always used over back-end specific ones, like @code{:login} or @code{:machine}. ERC expects a string to use as the secret or nil, if the search fails. +@findex erc-auth-source-search The default value for all three options is the function @code{erc-auth-source-search}. It tries to merge relevant contextual -params with those provided or discovered from the logical connection +parameters with those provided or discovered from the logical connection or the underlying transport. Some auth-source back ends may not be compatible; netrc, plstore, json, and secrets are currently supported. @end defopt @@ -866,10 +873,14 @@ This tries a number of increasingly more default methods until a non-@code{nil} value is found. @itemize @bullet -@item @var{full-name} (the argument passed to this function) -@item The @code{erc-user-full-name} option -@item The value of the IRCNAME environment variable -@item The result from the @code{user-full-name} function +@item +@var{full-name} (the argument passed to this function) +@item +The @code{erc-user-full-name} option +@item +The value of the IRCNAME environment variable +@item +The result from the @code{user-full-name} function @end itemize @end defun @@ -884,20 +895,20 @@ This can be either a string or a function to call. @subheading ID @anchor{Network Identifier} -ERC uses an abstract designation called a @dfn{network context -identifier} for referring to a connection internally. While normally +ERC uses an abstract designation, called @dfn{network context +identifier}, for referring to a connection internally. While normally derived from a combination of logical and physical connection parameters, an ID can also be explicitly provided via an entry-point -command (like @code{erc-tls}). Use this in rare situations where ERC +command (like @code{erc-tls}). Use this in rare situations where ERC would otherwise have trouble discerning between connections. One such situation might arise when using multiple connections to the -same network with the same nick but different (nonstandard) "device" +same network with the same nick but different (nonstandard) @samp{device} identifiers, which some bouncers may support. Another might be when mimicking the experience offered by popular standalone clients, which normally offer ``named'' persistent configurations with server buffers reflecting those names. Yet another use case might involve -third-party code needing to identify a connection unequivocally but in +third-party code needing to identify a connection unequivocally, but in a human-friendly way suitable for UI components. When providing an ID as an entry-point argument, strings and symbols diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 6f17e4ee7b..239d8ebdcb 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -261,15 +261,16 @@ node `(auth) Top' and info node `(erc) Connecting'.") :type 'boolean) (defcustom erc-inhibit-multiline-input nil - "Conditionally disallow input consisting of multiple lines. + "When non-nil, conditionally disallow input consisting of multiple lines. Issue an error when the number of input lines submitted for -sending exceeds this value." +sending exceeds this value. The value t means disallow more +than 1 line of input." :package-version '(ERC . "5.4.1") ; FIXME match to next release :group 'erc :type '(choice integer boolean)) (defcustom erc-ask-about-multiline-input nil - "Ask to ignore `erc-inhibit-multiline-input' when tripped." + "Whether to ask to ignore `erc-inhibit-multiline-input' when tripped." :package-version '(ERC . "5.4.1") ; FIXME match to next release :group 'erc :type 'boolean) commit efc2a878de6368eebb1ba73f5131eec563ca9b56 Author: F. Jason Park Date: Thu Jun 30 22:43:41 2022 -0700 ; Tag ERC channel-buffers test as unstable * test/lisp/erc/erc-networks-tests.el (erc-networks--id, erc-networks--id-create): Attempt to fix arity of mocked `float-time'. * test/lisp/erc/erc-scenarios-base-reuse-buffers.el (erc-scenarios-base-reuse-buffers-channel-buffers--disabled): Tag as being unstable. diff --git a/test/lisp/erc/erc-networks-tests.el b/test/lisp/erc/erc-networks-tests.el index dcda04692e..417ee94cf0 100644 --- a/test/lisp/erc/erc-networks-tests.el +++ b/test/lisp/erc/erc-networks-tests.el @@ -48,7 +48,7 @@ (ert-deftest erc-networks--id () (cl-letf (((symbol-function 'float-time) - (lambda () 0.0))) + (lambda (&optional _) 0.0))) ;; Fixed (should (equal (erc-networks--id-fixed-create 'foo) @@ -81,7 +81,7 @@ (ert-deftest erc-networks--id-create () (cl-letf (((symbol-function 'float-time) - (lambda () 0.0))) + (lambda (&optional _) 0.0))) (should (equal (erc-networks--id-create 'foo) (make-erc-networks--id-fixed :ts (float-time) diff --git a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el index 5af9589b74..f134f3ffb6 100644 --- a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el +++ b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el @@ -226,7 +226,7 @@ Adapted from scenario clash-of-chans/uniquify described in Bug#48598: (should chan-buffer-foo)))) (ert-deftest erc-scenarios-base-reuse-buffers-channel-buffers--disabled () - :tags '(:expensive-test) + :tags '(:expensive-test :unstable) (with-suppressed-warnings ((obsolete erc-reuse-buffers)) (should erc-reuse-buffers) (let ((erc-scenarios-common-dialog "base/reuse-buffers/channel") commit 7e33618bbc07b65c36744db8e7ef219d2d942456 Author: Brennan Vincent Date: Thu Jun 30 14:24:48 2022 -0400 ; * src/fns.c (Frequire): Fix a typo in the doc string. (Bug#56328) Copyright-paperwork-exempt: yes diff --git a/src/fns.c b/src/fns.c index 65dc3b61f2..b2b209e1e8 100644 --- a/src/fns.c +++ b/src/fns.c @@ -3112,7 +3112,7 @@ dynamic module files, in that order; but the function will not try to load the file without any suffix. See `get-load-suffixes' for the complete list of suffixes. -To find the file, this function searches that directories in `load-path'. +To find the file, this function searches the directories in `load-path'. If the optional third argument NOERROR is non-nil, then, if the file is not found, the function returns nil instead of signaling commit ef3f8a25655e2a44a46f9c86c300a0b9cb120567 Author: Stefan Kangas Date: Fri Jul 1 06:01:14 2022 +0200 Update publicsuffix.txt from upstream * etc/publicsuffix.txt: Update from https://publicsuffix.org/list/public_suffix_list.dat dated 2022-06-29 19:13:08 UTC. diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt index f52169116e..18cb313a32 100644 --- a/etc/publicsuffix.txt +++ b/etc/publicsuffix.txt @@ -1340,7 +1340,7 @@ tt.im tv.im // in : https://en.wikipedia.org/wiki/.in -// see also: https://registry.in/Policies +// see also: https://registry.in/policies // Please note, that nic.in is not an official eTLD, but used by most // government institutions. in @@ -7130,7 +7130,7 @@ org.zw // newGTLDs -// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-05-18T15:16:02Z +// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-06-14T15:15:19Z // This list is auto-generated, don't edit it manually. // aaa : 2015-02-26 American Automobile Association, Inc. aaa @@ -7687,7 +7687,7 @@ chanel // channel : 2014-05-08 Charleston Road Registry Inc. channel -// charity : 2018-04-11 Binky Moon, LLC +// charity : 2018-04-11 Public Interest Registry charity // chase : 2015-04-30 JPMorgan Chase Bank, National Association @@ -7834,7 +7834,7 @@ coupon // coupons : 2015-03-26 Binky Moon, LLC coupons -// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD +// courses : 2014-12-04 Registry Services, LLC courses // cpa : 2019-06-10 American Institute of Certified Public Accountants @@ -8227,7 +8227,7 @@ forsale // forum : 2015-04-02 Fegistry, LLC forum -// foundation : 2013-12-05 Binky Moon, LLC +// foundation : 2013-12-05 Public Interest Registry foundation // fox : 2015-09-11 FOX Registry, LLC @@ -8326,7 +8326,7 @@ gift // gifts : 2014-07-03 Binky Moon, LLC gifts -// gives : 2014-03-06 Dog Beach, LLC +// gives : 2014-03-06 Public Interest Registry gives // giving : 2014-11-13 Giving Limited @@ -8452,7 +8452,7 @@ health // healthcare : 2014-06-12 Binky Moon, LLC healthcare -// help : 2014-06-26 UNR Corp. +// help : 2014-06-26 Innovation service Limited help // helsinki : 2015-02-05 City of Helsinki @@ -8866,7 +8866,7 @@ living // llc : 2017-12-14 Afilias Limited llc -// llp : 2019-08-26 UNR Corp. +// llp : 2019-08-26 Intercap Registry Inc. llp // loan : 2014-11-20 dot Loan Limited @@ -9841,7 +9841,7 @@ stream // studio : 2015-02-11 Dog Beach, LLC studio -// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD +// study : 2014-12-11 Registry Services, LLC study // style : 2014-12-04 Binky Moon, LLC @@ -12111,6 +12111,7 @@ kill.jp kilo.jp kuron.jp littlestar.jp +lolipopmc.jp lolitapunk.jp lomo.jp lovepop.jp @@ -12378,6 +12379,11 @@ moonscale.net // Submitted by Hannu Aronsson iki.fi +// iliad italia: https://www.iliad.it +// Submitted by Marios Makassikis +ibxos.it +iliadboxos.it + // Impertrix Solutions : // Submitted by Zhixiang Zhao impertrixcdn.com @@ -12458,9 +12464,11 @@ iopsys.se // Submitted by Matthew Hardeman ipifony.net -// IServ GmbH : https://iserv.eu -// Submitted by Kim-Alexander Brodowski +// IServ GmbH : https://iserv.de +// Submitted by Mario Hoberg +iservschule.de mein-iserv.de +schulplattform.de schulserver.de test-iserv.de iserv.dev @@ -12782,6 +12790,10 @@ hra.health miniserver.com memset.net +// Messerli Informatik AG : https://www.messerli.ch/ +// Submitted by Ruben Schmidmeister +messerli.app + // MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/ // Submitted by Zdeněk Šustr *.cloud.metacentrum.cz @@ -13394,9 +13406,9 @@ rocky.page // Salesforce.com, Inc. https://salesforce.com/ // Submitted by Michael Biven -builder.code.com -dev-builder.code.com -stg-builder.code.com +*.builder.code.com +*.dev-builder.code.com +*.stg-builder.code.com // Sandstorm Development Group, Inc. : https://sandcats.io/ // Submitted by Asheesh Laroia commit 23df6df775c7cb88534ea310287ff9b057cc98f9 Author: Po Lu Date: Fri Jul 1 11:31:25 2022 +0800 Add tests for XDS protocol support * test/lisp/x-dnd-tests.el (x-dnd-tests-xds-property-value): New variable. (x-window-property): Handle new kind of window property. (x-dnd-tests-xds-target-dir, x-dnd-tests-xds-name) (x-dnd-tests-xds-include-hostname): New variables. (x-dnd-tests-call-xds-converter): New function. (x-begin-drag, x-change-window-property): (x-delete-window-property): New replacement functions. (x-dnd-tests-do-direct-save-internal): New function. (x-dnd-tests-do-direct-save): New test. diff --git a/test/lisp/x-dnd-tests.el b/test/lisp/x-dnd-tests.el index 35cda3b10a..8856be79eb 100644 --- a/test/lisp/x-dnd-tests.el +++ b/test/lisp/x-dnd-tests.el @@ -24,6 +24,7 @@ ;;; Code: (require 'x-dnd) +(require 'cl-lib) (when (display-graphic-p) (error "This test cannot be run under X")) @@ -33,6 +34,9 @@ (defconst x-dnd-tests-drag-window-xid 3948573 "XID of the drag window returned during the test.") +(defvar x-dnd-tests-xds-property-value nil + "The value of the `XdndDirectSave0' window property.") + (defconst x-dnd-tests-targets-table (base64-decode-string "bAArAKIBAAAGAB8AAABqAQAANgIAAJMCAAAFAwAABgMAAAEAkMJbAAEAINNbAAUAHwAAAGoBAAA2 @@ -62,7 +66,7 @@ AgAABQMAAAYDAAATGwAAGhsAAA==") "The expected result of parsing that targets table.") (defalias 'x-window-property - (lambda (prop &optional _frame type window-id _delete-p _vector-ret-p) + (lambda (prop &optional _frame type window-id delete-p _vector-ret-p) (cond ((and (equal prop "_MOTIF_DRAG_WINDOW") (zerop window-id) (equal type "WINDOW")) @@ -70,7 +74,13 @@ AgAABQMAAAYDAAATGwAAGhsAAA==") ((and (equal prop "_MOTIF_DRAG_TARGETS") (equal type "_MOTIF_DRAG_TARGETS") (equal window-id x-dnd-tests-drag-window-xid)) - x-dnd-tests-targets-table)))) + x-dnd-tests-targets-table) + ((and (equal prop "XdndDirectSave0") + (or (equal type "text/plain") + (equal type "AnyPropertyType"))) + (prog1 x-dnd-tests-xds-property-value + (when delete-p + (setq x-dnd-tests-xds-property-value nil))))))) ;; This test also serves to exercise most of the Motif value ;; extraction code. @@ -78,5 +88,116 @@ AgAABQMAAAYDAAATGwAAGhsAAA==") (should (equal (x-dnd-xm-read-targets-table nil) x-dnd-tests-lispy-targets-table))) +;;; XDS tests. + +(defvar x-dnd-tests-xds-target-dir nil + "The name of the target directory where the file will be saved.") + +(defvar x-dnd-tests-xds-name nil + "The name that the dragged file should be saved under.") + +(defvar x-dnd-tests-xds-include-hostname nil + "Whether or not to include the hostname inside the XDS URI.") + +(defun x-dnd-tests-call-xds-converter () + "Look up the XDS selection converter and call it. +Return the result of the selection." + (let ((conv (cdr (assq 'XdndDirectSave0 + selection-converter-alist)))) + (should (functionp conv)) + (funcall conv 'XdndDirectSave0 'XdndDirectSave0 nil))) + +(defalias 'x-begin-drag + (lambda (_targets &optional action frame &rest _) + ;; Verify that frame is either nil or a valid frame. + (when (and frame (not (frame-live-p frame))) + (signal 'wrong-type-argument frame)) + (prog1 'XdndActionDirectSave + ;; Verify that the action is `XdndActionDirectSave'. + (should (eq action 'XdndActionDirectSave)) + ;; Set the property value to the URI of the new file. + (should (and (stringp x-dnd-tests-xds-property-value) + (not (multibyte-string-p x-dnd-tests-xds-property-value)))) + (let ((uri (if x-dnd-tests-xds-include-hostname + (format "file://%s%s" (system-name) + (expand-file-name x-dnd-tests-xds-property-value + x-dnd-tests-xds-target-dir)) + (concat "file:///" (expand-file-name x-dnd-tests-xds-property-value + x-dnd-tests-xds-target-dir))))) + (setq x-dnd-tests-xds-property-value + (encode-coding-string (url-encode-url uri) + 'raw-text))) + ;; Convert the selection and verify its success. + (should (equal (x-dnd-tests-call-xds-converter) + '(STRING . "S")))))) + +(defalias 'x-change-window-property + (lambda (prop value &optional _frame type format outer-p _window-id) + ;; Check that the properties are the right type. + (should (equal prop "XdndDirectSave0")) + (should (equal value (encode-coding-string + x-dnd-tests-xds-name + (or file-name-coding-system + default-file-name-coding-system)))) + (should (equal type "text/plain")) + (should (equal format 8)) + (should (not outer-p)) + (setq x-dnd-tests-xds-property-value value))) + +(defalias 'x-delete-window-property + (lambda (&rest _args) + ;; This function shouldn't ever be reached during XDS. + (setq x-dnd-tests-xds-property-value nil))) + +(defun x-dnd-tests-do-direct-save-internal (include-hostname) + "Test the behavior of `x-dnd-do-direct-save'. +Make it perform a direct save to a randomly generated directory, +and check that the file exists. If INCLUDE-HOSTNAME, include the +hostname in the target URI." + (let ((x-dnd-tests-xds-include-hostname include-hostname) + (x-dnd-tests-xds-target-dir + (file-name-as-directory (expand-file-name + (make-temp-name "x-dnd-test") + temporary-file-directory))) + (original-file (expand-file-name + (make-temp-name "x-dnd-test") + temporary-file-directory)) + (x-dnd-tests-xds-name (make-temp-name "x-dnd-test-target"))) + ;; The call to `gui-set-selection' is only used for providing the + ;; conventional `text/uri-list' target and can be ignored. + (cl-flet ((gui-set-selection #'ignore)) + (unwind-protect + (progn + ;; Touch `original-file' if it doesn't exist. + (unless (file-exists-p original-file) + (write-region "" 0 original-file)) + ;; Create `x-dnd-tests-xds-target-dir'. + (make-directory x-dnd-tests-xds-target-dir) + ;; Start the direct save and verify it returns the correct action. + (should (eq (x-dnd-do-direct-save original-file + x-dnd-tests-xds-name + nil nil) + 'XdndActionDirectSave)) + ;; Now verify that the new file exists. + (should (file-exists-p + (expand-file-name x-dnd-tests-xds-name + x-dnd-tests-xds-target-dir))) + ;; The XDS protocol makes very clear that the window + ;; property must be deleted after the drag-and-drop + ;; operation completes. + (should (not x-dnd-tests-xds-property-value))) + ;; Clean up after ourselves. + (ignore-errors + (delete-file original-file)) + (ignore-errors + (delete-directory x-dnd-tests-xds-target-dir t)))))) + +(ert-deftest x-dnd-tests-do-direct-save () + ;; TODO: add tests for application/octet-stream transfer. + (x-dnd-tests-do-direct-save-internal nil) + ;; Test with both kinds of file: URIs, since different programs + ;; generate different kinds. + (x-dnd-tests-do-direct-save-internal t)) + (provide 'x-dnd-tests) ;;; x-dnd-tests.el ends here commit 2289fafeaf4dc21c0c9751a3a195d855bf5e91f8 Author: Po Lu Date: Fri Jul 1 10:23:13 2022 +0800 Fix `clipboard-yank' inserting off the kill ring instead of CLIPBOARD * lisp/select.el (gui-last-cut-in-clipboard) (gui-last-cut-in-primary): New variables. (gui-select-text): Set those variables. (gui--selection-value-internal, gui-selection-value): Don't return nil if the last cut did not own the chosen selection. (bug#56325) diff --git a/lisp/select.el b/lisp/select.el index 8ffe16e7b3..d977a8714b 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -112,20 +112,28 @@ E.g. it doesn't exist under MS-Windows." ;; We keep track of the last selection here, so we can check the ;; current selection against it, and avoid passing back with ;; gui-selection-value the same text we previously killed or -;; yanked. We track both -;; separately in case another X application only sets one of them -;; we aren't fooled by the PRIMARY or CLIPBOARD selection staying the same. +;; yanked. We track both separately in case another X application only +;; sets one of them we aren't fooled by the PRIMARY or CLIPBOARD +;; selection staying the same. (defvar gui--last-selected-text-clipboard nil "The value of the CLIPBOARD selection last seen.") + (defvar gui--last-selected-text-primary nil "The value of the PRIMARY selection last seen.") (defvar gui--last-selection-timestamp-clipboard nil "The timestamp of the CLIPBOARD selection last seen.") + (defvar gui--last-selection-timestamp-primary nil "The timestamp of the PRIMARY selection last seen.") +(defvar gui-last-cut-in-clipboard nil + "Whether or not the last call to `interprogram-cut-function' owned CLIPBOARD.") + +(defvar gui-last-cut-in-primary nil + "Whether or not the last call to `interprogram-cut-function' owned PRIMARY.") + (defun gui--set-last-clipboard-selection (text) "Save last clipboard selection. Save the selected text, passed as argument, and for window @@ -182,7 +190,10 @@ MS-Windows does not have a \"primary\" selection." ;; should not be reset by cut (Bug#16382). (setq saved-region-selection text) (gui-set-selection 'CLIPBOARD text) - (gui--set-last-clipboard-selection text))) + (gui--set-last-clipboard-selection text)) + ;; Record which selections we now have ownership over. + (setq gui-last-cut-in-clipboard select-enable-clipboard + gui-last-cut-in-primary select-enable-primary)) (define-obsolete-function-alias 'x-select-text 'gui-select-text "25.1") (defcustom x-select-request-type nil @@ -218,13 +229,13 @@ decided by `x-select-request-type'. The return value is already decoded. If `gui-get-selection' signals an error, return nil." ;; The doc string of `interprogram-paste-function' says to return ;; nil if no other program has provided text to paste. - (unless (and - ;; `gui-backend-selection-owner-p' might be unreliable on - ;; some other window systems. - (memq window-system '(x haiku)) - (eq type 'CLIPBOARD) - ;; Should we unify this with gui--clipboard-selection-unchanged-p? - (gui-backend-selection-owner-p type)) + (unless (and gui-last-cut-in-clipboard + ;; `gui-backend-selection-owner-p' might be unreliable on + ;; some other window systems. + (memq window-system '(x haiku)) + (eq type 'CLIPBOARD) + ;; Should we unify this with gui--clipboard-selection-unchanged-p? + (gui-backend-selection-owner-p type)) (let ((request-type (if (memq window-system '(x pgtk haiku)) (or x-select-request-type '(UTF8_STRING COMPOUND_TEXT STRING text/plain\;charset=utf-8)) @@ -254,7 +265,15 @@ decoded. If `gui-get-selection' signals an error, return nil." ;; (bug#53894) for further discussion about this DWIM ;; action, and possible ways to make this check less ;; fragile, if so desired. - (unless (gui--clipboard-selection-unchanged-p text) + + ;; Don't check the "newness" of CLIPBOARD if the last + ;; call to `gui-select-text' didn't cause us to become + ;; its owner. This lets the user yank text killed by + ;; `clipboard-kill-region' with `clipboard-yank' without + ;; interference from text killed by other means when + ;; `select-enable-clipboard' is nil. + (unless (and gui-last-cut-in-clipboard + (gui--clipboard-selection-unchanged-p text)) (gui--set-last-clipboard-selection text) text)))) (primary-text @@ -264,7 +283,8 @@ decoded. If `gui-get-selection' signals an error, return nil." ;; Check the PRIMARY selection for 'newness', is it different ;; from what we remembered them to be last time we did a ;; cut/paste operation. - (unless (gui--primary-selection-unchanged-p text) + (unless (and gui-last-cut-in-primary + (gui--primary-selection-unchanged-p text)) (gui--set-last-primary-selection text) text))))) commit 833767e53fcb55e3000b54de1cb3803900c363e9 Author: Po Lu Date: Fri Jul 1 09:10:34 2022 +0800 Disable middle click selection emulation during XDS * doc/lispref/frames.texi (Drag and Drop): Document new variable. * lisp/x-dnd.el (x-dnd-do-direct-save): Disable drop emulation during XDS drag-and-drop. * src/keyboard.c (kbd_buffer_get_event): Handle recorded value. * src/xterm.c (x_dnd_do_unsupported_drop): Return if new variable is nil. (x_dnd_send_unsupported_drop): Record value of new variable in events. (x_dnd_begin_drag_and_drop): Handle recorded value. (syms_of_xterm): New variable `x-dnd-use-unsupported-drop'. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 720753edad..f7491502f4 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4280,6 +4280,18 @@ will only be used if @code{"FILE_NAME"} is one of the targets given to to drop all supported content. @end defvar +@defvar x-dnd-use-unsupported-drop +When one of the @code{"STRING"}, @code{"UTF8_STRING"}, +@code{"COMPOUND_TEXT"} or @code{"TEXT"} targets is present in the list +given to @code{x-begin-drag}, Emacs will try to use synthesized mouse +events and the primary selection to insert the text if the drop target +doesn't support any drag-and-drop protocol at all. + +A side effect is that Emacs will become the owner of the primary +selection upon such a drop. If that is not desired, then the drop +emulation can be disabled by setting this variable to @code{nil}. +@end defvar + @node Color Names @section Color Names diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index c3d56f327d..43905e1bb0 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -1144,6 +1144,7 @@ ACTION is the action given to `x-begin-drag'." "Whether or not the drop target made a request for `XdndDirectSave0'.") (defvar x-dnd-disable-motif-protocol) +(defvar x-dnd-use-unsupported-drop) (defun x-dnd-handle-direct-save (_selection _type _value) "Handle a selection request for `XdndDirectSave'." @@ -1204,6 +1205,7 @@ was taken, or the direct save failed." ;; possibly work with Motif or OffiX programs. (x-dnd-disable-motif-protocol t) (x-dnd-use-offix-drop nil) + (x-dnd-use-unsupported-drop nil) (prop-deleted nil) encoded-name) (unwind-protect diff --git a/src/keyboard.c b/src/keyboard.c index 8b8d348c41..4cac20eb4b 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4068,7 +4068,10 @@ kbd_buffer_get_event (KBOARD **kbp, /* `x-dnd-unsupported-drop-function' could have deleted the event frame. */ - if (!FRAME_LIVE_P (f)) + if (!FRAME_LIVE_P (f) + /* This means `x-dnd-use-unsupported-drop' was nil when the + event was generated. */ + || NILP (XCAR (XCDR (XCDR (XCDR (event->ie.arg)))))) break; x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f), diff --git a/src/xterm.c b/src/xterm.c index 500443ebaa..fa43371f05 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3810,6 +3810,9 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, if (NILP (value)) return; + if (!x_dnd_use_unsupported_drop) + return; + event.xbutton.serial = 0; event.xbutton.send_event = True; event.xbutton.display = dpyinfo->display; @@ -3914,9 +3917,10 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo ie.kind = UNSUPPORTED_DROP_EVENT; ie.code = (unsigned) target_window; ie.modifiers = x_dnd_unsupported_event_level; - ie.arg = list3 (assq_no_quit (QXdndSelection, + ie.arg = list4 (assq_no_quit (QXdndSelection, dpyinfo->terminal->Vselection_alist), - targets, arg); + targets, arg, (x_dnd_use_unsupported_drop + ? Qt : Qnil)); ie.timestamp = before; XSETINT (ie.x, root_x); @@ -11377,7 +11381,10 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* `x-dnd-unsupported-drop-function' could have deleted the event frame. */ - if (!FRAME_LIVE_P (event_frame)) + if (!FRAME_LIVE_P (event_frame) + /* This means `x-dnd-use-unsupported-drop' was nil when the + event was generated. */ + || NILP (XCAR (XCDR (XCDR (XCDR (event->ie.arg)))))) continue; x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (event_frame), @@ -28075,4 +28082,11 @@ drag-and-drop code. */); When non-nil, `x-begin-drag' will not drop onto any window that only supports the Motif drag-and-drop protocols. */); x_dnd_disable_motif_protocol = false; + + DEFVAR_BOOL ("x-dnd-use-unsupported-drop", x_dnd_use_unsupported_drop, + doc: /* Enable the emulation of drag-and-drop based on the primary selection. +When nil, do not use the primary selection and synthetic mouse clicks +to emulate the drag-and-drop of `STRING', `UTF8_STRING', +`COMPOUND_TEXT' or `TEXT'. */); + x_dnd_use_unsupported_drop = true; } commit ce00057cb91ba78596f06b674006b452666485a9 Author: F. Jason Park Date: Thu Jun 30 17:15:25 2022 -0700 ; Help ERC test fixture better withstand reordering * test/lisp/erc/erc-tests.el (erc-tests--with-process-input-spy): Shadow hook to prevent the erc-button module from interfering with tests using this helper. diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 62bea8fb3f..4971d0e194 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -664,6 +664,7 @@ (erc-server-current-nick "tester") (erc-last-input-time 0) erc-accidental-paste-threshold-seconds + erc-send-modify-hook ;; calls) (cl-letf (((symbol-function 'erc-process-input-line) commit 85c2f3bc3efd9cdd092a6d4fadca5cc04642a2a5 Author: F. Jason Park Date: Fri Jun 18 04:25:44 2021 -0700 Update ERC's Info doc with network-ID related changes * doc/misc/erc.texi: Update the `erc' and `erc-tls' entry-point sections with the new :id keyword parameter. Expand the auth-info related information in the passwords section. Remove all mention of the variable `erc-rename-buffers', whose "on" behavior has been made permanent. * etc/ERC-NEWS: Add new section for future 5.5 release. diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index b9297738ea..6daa54d956 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -545,20 +545,26 @@ Non-interactively, it takes the following keyword arguments. @item @var{server} @item @var{port} @item @var{nick} +@item @var{user} @item @var{password} @item @var{full-name} +@item @var{id} @end itemize -That is, if called with the following arguments, @var{server} and -@var{full-name} will be set to those values, whereas -@code{erc-compute-port} and @code{erc-compute-nick} will be invoked -for the values of the other parameters. +For example, calling the command like so -@example +@example lisp (erc :server "irc.libera.chat" :full-name "J. Random Hacker") @end example + +sets @var{server} and @var{full-name} directly while leaving the rest +up to functions like @code{erc-compute-port}. Note that some +arguments can't be specified interactively. @var{id}, in particular, +is rarely needed (@pxref{Network Identifier}). + @end defun +@noindent To connect securely over an encrypted TLS connection, use @kbd{M-x erc-tls}. @@ -570,21 +576,24 @@ Non-interactively, it takes the following keyword arguments. @item @var{server} @item @var{port} @item @var{nick} +@item @var{user} @item @var{password} @item @var{full-name} +@item @var{id} @item @var{client-certificate} @end itemize -That is, if called with the following arguments, @var{server} and -@var{full-name} will be set to those values, whereas -@code{erc-compute-port} and @code{erc-compute-nick} will be invoked -for the values of the other parameters, and @code{client-certificate} -will be @code{nil}. +That is, if called in the following manner -@example +@example lisp (erc-tls :server "irc.libera.chat" :full-name "J. Random Hacker") @end example +the command will set @var{server} and @var{full-name} accordingly, +while helpers, like @code{erc-compute-nick}, will determine other +parameters, and some, like @code{client-certificate}, will just be +@code{nil}. + To use a certificate with @code{erc-tls}, specify the optional @var{client-certificate} keyword argument, whose value should be as described in the documentation of @code{open-network-stream}: if @@ -719,29 +728,134 @@ ERC should automatically attempt to connect with another nickname. You can manually set another nickname with the /NICK command. @end defopt +@subheading User +@defun erc-compute-user &optional user +Determine a suitable value to send for the first argument to the +opening @samp{USER} IRC command by consulting the following sources: + +@itemize +@item @var{user}, the argument passed to this function +@item The option @code{erc-email-userid}, assuming @code{erc-anonymous-login} +is non-@code{nil} +@item The result of calling the function @code{user-login-name} +@end itemize + +@end defun + +@defopt erc-email-userid +A permanent username value to send for all connections. It should be +a string abiding by the rules of the network. +@end defopt + @subheading Password @cindex password @defopt erc-prompt-for-password -If non-@code{nil} (the default), @kbd{M-x erc} prompts for a password. +If non-@code{nil} (the default), @kbd{M-x erc} prompts for a server +password. This only affects interactive invocations of @code{erc} and +@code{erc-tls}. @end defopt +@noindent If you prefer, you can set this option to @code{nil} and use the @code{auth-source} mechanism to store your password. For instance, if -you use @file{~/.authinfo} as your auth-source backend, then put +the option @code{auth-sources} contains @file{~/.authinfo}, put something like the following in that file: @example -machine irc.example.net login "#fsf" password sEcReT +machine irc.example.net login mynick password sEcReT +@end example + +@noindent +For server passwords, that is, passwords sent for the IRC @samp{PASS} +command, the @samp{host} field, here @code{machine irc.example.net}, +corresponds to the @var{server} parameter used by @code{erc} and +@code{erc-tls}. Unfortunately, specifying a network, like +@samp{Libera.Chat}, or a specific network server, like +@samp{platinum.libera.chat}, won't work OOTB for looking up a server +password because such information isn't available during opening +introductions. Actually, ERC @emph{can} find entries with arbitrary +@samp{host} values for any context, including server passwords, but +that requires messing with the more advanced options below. + +If ERC can't find a suitable server password, it'll just skip the IRC +@samp{PASS} command altogether, something users may want when using +CertFP or engaging NickServ via ERC's ``services'' module. If that +sounds like you, you can also set the option +@code{erc-auth-source-server-function} to @code{nil} to skip +server-passwork lookup for all servers. Note that some networks and +IRCds may accept account-services authentication via server password +using the nonstandard ``mynick:sEcReT'' convention. + +As just mentioned, you can also use @code{auth-source} to authenticate +to account services the traditional way, through a bot called +``NickServ''. To tell ERC to do that, set +@code{erc-use-auth-source-for-nickserv-password} to @code{t}. For +these and most other queries, entries featuring custom identifiers and +networks are matched first, followed by network-specific servers and +dialed endpoints (typically, the @var{SERVER} passed to +@code{erc}). The following netrc-style entries appear in order of +precedence: + +@example +machine Libera/cellphone login MyNick password sEcReT +machine Libera.Chat login MyNick password sEcReT +machine zirconium.libera.chat login MyNick password sEcReT +machine irc.libera.chat login MyNick password sEcReT @end example @noindent -ERC also consults @code{auth-source} to find any channel keys required -for the channels that you wish to autojoin, as specified by the -variable @code{erc-autojoin-channels-alist}. +Remember that field labels vary per backend, so @samp{machine} (in +netrc's case) maps to auth-source's generalized notion of a host, +hence the @samp{:host} keyword property. Also, be sure and mind the +syntax of your chosen backend medium. For example, always quote +channel names in a netrc file. + +If this all seems overly nuanced or just plain doesn't appeal to you, +see options @code{erc-auth-source-services-function} and friends just +below. These let you query auth-source your way. Most users can +simply ignore the passed-in arguments and get by with something like +the following: -For more details, @pxref{Top,,auth-source, auth, Emacs auth-source Library}. +@lisp +(defun my-fancy-auth-source-func (&rest _) + (let* ((host (read-string "host: " nil nil "default")) + (pass (auth-source-pick-first-password :host host))) + (if (and pass (string-search "libera" host)) + (concat "MyNick:" pass) + pass))) +@end lisp + +Lastly, ERC also consults @code{auth-source} to find ``keys'' that may +be required by certain channels you join. When modifying a +traditional @code{auth-source} entry for this purpose, put the channel +name in the @samp{user} field (for example, @samp{login "#fsf"}, in +netrc's case). The actual key goes in the @samp{password} (or +@samp{secret}) field. + +@noindent +For details, @pxref{Top,,auth-source, auth, Emacs auth-source Library}. +@defopt erc-auth-source-server-function +@end defopt +@defopt erc-auth-source-services-function +@end defopt +@defopt erc-auth-source-join-function + +ERC calls these functions with keyword arguments recognized by +@code{auth-source-search}, namely, those deemed most relevant to the +current context, if any. For example, with NickServ queries, +@code{:user} is the ``desired'' nickname rather than the current one. +Generalized names, like @code{:user} and @code{:host}, are always used +over back-end specific ones, like @code{:login} or @code{:machine}. +ERC expects a string to use as the secret or nil, if the search fails. + +The default value for all three options is the function +@code{erc-auth-source-search}. It tries to merge relevant contextual +params with those provided or discovered from the logical connection +or the underlying transport. Some auth-source back ends may not be +compatible; netrc, plstore, json, and secrets are currently supported. +@end defopt @subheading Full name @@ -766,6 +880,31 @@ User full name. This can be either a string or a function to call. @end defopt + +@subheading ID +@anchor{Network Identifier} + +ERC uses an abstract designation called a @dfn{network context +identifier} for referring to a connection internally. While normally +derived from a combination of logical and physical connection +parameters, an ID can also be explicitly provided via an entry-point +command (like @code{erc-tls}). Use this in rare situations where ERC +would otherwise have trouble discerning between connections. + +One such situation might arise when using multiple connections to the +same network with the same nick but different (nonstandard) "device" +identifiers, which some bouncers may support. Another might be when +mimicking the experience offered by popular standalone clients, which +normally offer ``named'' persistent configurations with server buffers +reflecting those names. Yet another use case might involve +third-party code needing to identify a connection unequivocally but in +a human-friendly way suitable for UI components. + +When providing an ID as an entry-point argument, strings and symbols +make the most sense, but any reasonably printable object is +acceptable. + + @node Sample Configuration @section Sample Configuration @cindex configuration, sample @@ -827,12 +966,6 @@ stuff, to the current ERC buffer." (setq erc-autojoin-channels-alist '(("Libera.Chat" "#emacs" "#erc"))) -;; Rename server buffers to reflect the current network name instead -;; of SERVER:PORT (e.g., "Libera.Chat" instead of -;; "irc.libera.chat:6667"). This is useful when using a bouncer like -;; ZNC where you have multiple connections to the same server. -(setq erc-rename-buffers t) - ;; Interpret mIRC-style color commands in IRC chats (setq erc-interpret-mirc-color t) @@ -891,15 +1024,6 @@ lurkers. The function @code{erc-lurker-p} determines whether a given nickname is considered a lurker. @end defopt -@defopt erc-rename-buffers -If non, @code{nil}, this will rename server buffers to reflect the -current network name instead of IP:PORT - -@example -(setq erc-rename-buffers t) -@end example -@end defopt - @node Getting Help and Reporting Bugs @chapter Getting Help and Reporting Bugs @cindex help, getting @@ -924,7 +1048,7 @@ contributors are frequently around and willing to answer your questions. @item -To report a bug in ERC, use @kbd{M-x report-emacs-bug}. +To report a bug in ERC, use @kbd{M-x erc-bug}. @end itemize diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index bdcd943c37..7f95cdd39a 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -11,6 +11,96 @@ This file is about changes in ERC, the powerful, modular, and extensible IRC (Internet Relay Chat) client distributed with GNU Emacs since Emacs version 22.1. + +* Changes in ERC 5.5 + +** Smarter buffer naming for withstanding collisions. +ERC buffers now remain tied to their logical network contexts, even +while offline. These associations can survive regional server changes +and the intercession of proxies. As has long been practiced in other +areas of Emacs, "uniquified" buffer renaming prevents collisions +between buffers of different contexts. ERC's approach prioritizes +predictability over economy, favoring fully qualified suffixes without +elided or omitted components. Potential avenues for confusion remain +but will die out with the adoption of emerging protocol extensions. + +** Option 'erc-rename-buffers' deprecated. +The promises made by its old "on" state are now fully realized and +enabled permanently by default. Its old behavior when disabled has +been preserved and will remain available (with warnings) for years to +come. + +** Option 'erc-reuse-buffers' deprecated. +This ancient option has been a constant source of confusion, as +exhibited most recently when its "disabled" meaning was partially +inverted. Introduced in ERC 5.4 (Emacs 28.1), this regression saw +existing channel buffers transparently reassociated instead of created +anew. The pre-5.4 "disabled" behavior has been restored and will +remain accessible for the foreseeable future, warts and all (e.g., +with its often superfluous "/DIALED-HOST" suffixing always present). + +** Tighter auth-source integration with bigger changes on the horizon. +The days of hit-and-miss auth-source queries are hopefully behind us. +With the overhaul of the services module temporarily shelved and the +transition to SASL-based authentication still underway, users may feel +left in the lurch to endure yet another release cycle of backtick +hell. For some, auth-source may provide a workaround in the form of +nonstandard server passwords. See the "Connection" node in the manual +under the subheading "Password". + +If you require SASL immediately, please participate in ERC development +by volunteering to try (and give feedback on) edge features, one of +which is SASL. All known external offerings, past and present, are +valiant efforts whose use is nevertheless discouraged. + +** Username argument for entry-point commands. +Commands 'erc' and 'erc-tls' now accept a ':user' keyword argument, +which, when present, becomes the first argument passed to the "USER" +IRC command. The traditional way of setting this globally, via +'erc-email-userid', is still honored. + +** Additional display options for updated buffers. +Additional flexibility is now available for controlling the behavior +of newly created target buffers, especially during reconnection. + +** Improved handling of multiline prompt input. +This means better detection and handling of intervening and trailing +blanks when 'erc-send-whitespace-lines' is active. New options have +also been added for warning when input spans multiple lines. Although +off by default, new users are encouraged to enable them. + +** Miscellaneous behavioral changes impacting the user experience. +A bug has been fixed that saw prompts being mangled, doubled, or +erased in server buffers upon disconnection. Instead, input prompts +now collapse into an alternate form designated by the option +'erc-prompt-hidden'. Behavior differs for query and channel buffers +but can be fine-tuned via the repurposed, formerly abandoned option +'erc-hide-prompt'. + +A bug has been fixed affecting users of the Soju bouncer: outgoing +messages during periods of heavy traffic no longer disappear. + +Although rare, server passwords containing white space are now handled +correctly. + +** Miscellaneous behavioral changes in the library API. +The function 'erc-network' always returns non-nil in server and target +buffers belonging to a successfully established IRC connection, even +after that connection has been closed. + +In 5.4, support for network symbols as keys was added for +'erc-autojoin-channels-alist'. This has been extended to include +explicit symbols passed to 'erc-tls' and 'erc' as so-called +network-context identifiers via a new ':id' keyword. The latter +carries wider significance beyond autojoin and can be used for +unequivocally identifying a connection in a human-readable way. + +The function 'erc-auto-query', unused internally, and basically +inscrutable when read, has been deprecated with no public replacement. +This raises a related issue: if you use ERC as a library and need +something only offered internally, please lobby to have it exported by +writing to emacs-erc@gnu.org. + * Changes in ERC 5.4.1 commit 10237840d03c4ba647fd3045ee500af950a5df6e Author: F. Jason Park Date: Wed Apr 27 02:27:32 2022 -0700 Optionally prevent sending multiline input in ERC * lisp/erc/erc.el (erc-inhibit-multiline-input): Add option to cap the number of lines to be sent before admonishing the user. (erc-ask-about-multiline-input): Add option to ask instead of warning user when `erc-inhibit-multiline-input' is reached. (erc--check-prompt-input-for-excess-lines): Add validator to possibly warn when too many lines are submitted for transmission. * test/lisp/erc/erc-tests.el (erc--check-prompt-input-for-excess-lines): Add test. (Bug#54536) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 89ce713fe0..6f17e4ee7b 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -260,6 +260,20 @@ node `(auth) Top' and info node `(erc) Connecting'.") :group 'erc :type 'boolean) +(defcustom erc-inhibit-multiline-input nil + "Conditionally disallow input consisting of multiple lines. +Issue an error when the number of input lines submitted for +sending exceeds this value." + :package-version '(ERC . "5.4.1") ; FIXME match to next release + :group 'erc + :type '(choice integer boolean)) + +(defcustom erc-ask-about-multiline-input nil + "Ask to ignore `erc-inhibit-multiline-input' when tripped." + :package-version '(ERC . "5.4.1") ; FIXME match to next release + :group 'erc + :type 'boolean) + (defcustom erc-prompt-hidden ">" "Text to show in lieu of the prompt when hidden." :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release @@ -5890,6 +5904,23 @@ is empty or consists of one or more spaces, tabs, or form-feeds." (string-match (rx bot (* (in " \t\f")) eot) line)) (throw 'return t)))))) +(defun erc--check-prompt-input-for-excess-lines (_ lines) + "Return non-nil when trying to send too many LINES." + (when erc-inhibit-multiline-input + ;; Assume `erc--discard-trailing-multiline-nulls' is set to run + (let ((reversed (seq-drop-while #'string-empty-p (reverse lines))) + (max (if (eq erc-inhibit-multiline-input t) + 2 + erc-inhibit-multiline-input)) + (seen 0) + msg) + (while (and (pop reversed) (< (cl-incf seen) max))) + (when (= seen max) + (setq msg (format "(exceeded by %d)" (1+ (length reversed)))) + (unless (and erc-ask-about-multiline-input + (y-or-n-p (concat "Send input " msg "?"))) + (concat "Too many lines " msg)))))) + (defun erc--check-prompt-input-for-multiline-blanks (_ lines) "Return non-nil when multiline prompt input has blank LINES." (when (erc--blank-in-multiline-input-p lines) @@ -5911,7 +5942,8 @@ is empty or consists of one or more spaces, tabs, or form-feeds." (defvar erc--check-prompt-input-functions '(erc--check-prompt-input-for-point-in-bounds erc--check-prompt-input-for-multiline-blanks - erc--check-prompt-input-for-running-process) + erc--check-prompt-input-for-running-process + erc--check-prompt-input-for-excess-lines) "Validators for user input typed at prompt. Called with latest input string submitted by user and the list of lines produced by splitting it. If any member function returns diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 986988a335..62bea8fb3f 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -797,6 +797,31 @@ (should (equal (funcall next) '("there\n" nil t))) (should-not (funcall next)))))) +(ert-deftest erc--check-prompt-input-for-excess-lines () + (ert-info ("Without `erc-inhibit-multiline-input'") + (should-not erc-inhibit-multiline-input) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))) + + (ert-info ("With `erc-inhibit-multiline-input' as t (2)") + (let ((erc-inhibit-multiline-input t)) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" ""))) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))) + + (ert-info ("With `erc-inhibit-multiline-input' as 3") + (let ((erc-inhibit-multiline-input 3)) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b" ""))) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b" "c"))))) + + (ert-info ("With `erc-ask-about-multiline-input'") + (let ((erc-inhibit-multiline-input t) + (erc-ask-about-multiline-input t)) + (ert-simulate-keys '(?n ?\r ?y ?\r) + (should (erc--check-prompt-input-for-excess-lines "" '("a" "b"))) + (should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b"))))) + (should-not erc-ask-about-multiline-input))) + ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. commit f46547294d2684d80bb473bd4c85f273ff661a7d Author: F. Jason Park Date: Mon Mar 21 05:40:16 2022 -0700 Improve ERC's handling of multiline prompt input * lisp/erc/erc.el (erc--pre-send-split-functions): Add new internal hook allowing members to revise individual lines before sending. This was created with an eye toward possibly exporting it publicly as a customizable option. (erc-last-input-time): Tweak meaning of variable to match likely original intent, which is that it's only updated on successful calls to `erc-send-current-line'. (erc--discard-trailing-multiline-nulls): Conditionally truncate list of lines to be sent, skipping trailing blanks. This constitutes a behavioral change. But, considering the nature of the bug being fixed, it is thought to be justified. (erc--input-split): Add new internal struct containing split input lines and flag for command detection. (erc--input-line-delim-regexp): Add regex var for splitting multiline prompt input. (erc--blank-in-multiline-p): Add helper for detecting blank lines. (erc--check-prompt-input-for-multiline-blanks, erc--check-prompt-input-for-point-in-bounds, erc--check-prompt-input-for-running-process): New functions to encapsulate logic for various pre-flight idiot checks. (erc--check-prompt-input-functions): Add new hook for validating prompt input prior to clearing it, internal for now. (erc-send-current-line): Pre-screen for blank lines and bail out if necessary. (erc-send-input): Add optional param to skip checking for blank lines. Call hook `erc--pre-send-split-functions'. * test/lisp/erc/erc-tests.el (erc-ring-previous-command): Use new test helper. (erc--input-line-delim-regexp, erc--blank-in-multiline-input-p): Add tests. (erc-tests--send-prep, erc-tests--set-fake-server-process, erc-tests--with-process-input-spy): Add test helpers. (erc--check-prompt-input-functions, erc-send-current-line, erc-send-whitespace-lines): Add tests. (Bug#54536) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 971d3f426f..89ce713fe0 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1123,6 +1123,29 @@ The struct has three slots: :type 'hook :version "27.1") +;; This is being auditioned for possible exporting (as a custom hook +;; option). Likewise for (public versions of) `erc--input-split' and +;; `erc--discard-trailing-multiline-nulls'. If unneeded, we'll just +;; run the latter on the input after `erc-pre-send-functions', and +;; remove this hook and the struct completely. IOW, if you need this, +;; please say so. + +(defvar erc--pre-send-split-functions '(erc--discard-trailing-multiline-nulls) + "Special hook for modifying individual lines in multiline prompt input. +The functions are called with one argument, an `erc--input-split' +struct, which they can optionally modify. + +The struct has five slots: + + `string': the input string delivered by `erc-pre-send-functions' + `insertp': whether to insert the lines into the buffer + `sendp': whether the lines should be sent to the IRC server + `lines': a list of lines to be sent, each one a `string' + `cmdp': whether to interpret input as a command, like /ignore + +The `string' field is effectively read-only. When `cmdp' is +non-nil, all but the first line will be discarded.") + (defvar erc-insert-this t "Insert the text into the target buffer or not. Functions on `erc-insert-pre-hook' can set this variable to nil @@ -5835,7 +5858,7 @@ Specifically, return the position of `erc-insert-marker'." (point-max)) (defvar erc-last-input-time 0 - "Time of last call to `erc-send-current-line'. + "Time of last successful call to `erc-send-current-line'. If that function has never been called, the value is 0.") (defcustom erc-accidental-paste-threshold-seconds 0.2 @@ -5851,6 +5874,50 @@ submitted line to be intentional." :version "26.1" :type '(choice number (other :tag "disabled" nil))) +(defvar erc--input-line-delim-regexp (rx (| (: (? ?\r) ?\n) ?\r))) + +(defun erc--blank-in-multiline-input-p (lines) + "Detect whether LINES contains a blank line. +When `erc-send-whitespace-lines' is in effect, return nil if +LINES is multiline or the first line is non-empty. When +`erc-send-whitespace-lines' is nil, return non-nil when any line +is empty or consists of one or more spaces, tabs, or form-feeds." + (catch 'return + (let ((multilinep (cdr lines))) + (dolist (line lines) + (when (if erc-send-whitespace-lines + (and (string-empty-p line) (not multilinep)) + (string-match (rx bot (* (in " \t\f")) eot) line)) + (throw 'return t)))))) + +(defun erc--check-prompt-input-for-multiline-blanks (_ lines) + "Return non-nil when multiline prompt input has blank LINES." + (when (erc--blank-in-multiline-input-p lines) + (if erc-warn-about-blank-lines + "Blank line - ignoring..." + 'invalid))) + +(defun erc--check-prompt-input-for-point-in-bounds (_ _) + "Return non-nil when point is before prompt." + (when (< (point) (erc-beg-of-input-line)) + "Point is not in the input area")) + +(defun erc--check-prompt-input-for-running-process (string _) + "Return non-nil unless in an active ERC server buffer." + (unless (or (erc-server-buffer-live-p) + (erc-command-no-process-p string)) + "ERC: No process running")) + +(defvar erc--check-prompt-input-functions + '(erc--check-prompt-input-for-point-in-bounds + erc--check-prompt-input-for-multiline-blanks + erc--check-prompt-input-for-running-process) + "Validators for user input typed at prompt. +Called with latest input string submitted by user and the list of +lines produced by splitting it. If any member function returns +non-nil, processing is abandoned and input is left untouched. +When the returned value is a string, pass it to `erc-error'.") + (defun erc-send-current-line () "Parse current line and send it to IRC." (interactive) @@ -5864,20 +5931,21 @@ submitted line to be intentional." (eolp)) (expand-abbrev)) (widen) - (if (< (point) (erc-beg-of-input-line)) - (erc-error "Point is not in the input area") + (if-let* ((str (erc-user-input)) + (msg (run-hook-with-args-until-success + 'erc--check-prompt-input-functions str + (split-string str erc--input-line-delim-regexp)))) + (when (stringp msg) + (erc-error msg)) (let ((inhibit-read-only t) - (str (erc-user-input)) (old-buf (current-buffer))) - (if (and (not (erc-server-buffer-live-p)) - (not (erc-command-no-process-p str))) - (erc-error "ERC: No process running") + (progn ; unprogn this during next major surgery (erc-set-active-buffer (current-buffer)) ;; Kill the input and the prompt (delete-region (erc-beg-of-input-line) (erc-end-of-input-line)) (unwind-protect - (erc-send-input str) + (erc-send-input str 'skip-ws-chk) ;; Fix the buffer if the command didn't kill it (when (buffer-live-p old-buf) (with-current-buffer old-buf @@ -5892,8 +5960,8 @@ submitted line to be intentional." (set-buffer-modified-p buffer-modified)))))) ;; Only when last hook has been run... - (run-hook-with-args 'erc-send-completed-hook str)))) - (setq erc-last-input-time now)) + (run-hook-with-args 'erc-send-completed-hook str))) + (setq erc-last-input-time now))) (switch-to-buffer "*ERC Accidental Paste Overflow*") (lwarn 'erc :warning "You seem to have accidentally pasted some text!")))) @@ -5910,21 +5978,31 @@ submitted line to be intentional." (cl-defstruct erc-input string insertp sendp) -(defun erc-send-input (input) +(cl-defstruct (erc--input-split (:include erc-input)) + lines cmdp) + +(defun erc--discard-trailing-multiline-nulls (state) + "Ensure last line of STATE's string is non-null. +But only when `erc-send-whitespace-lines' is non-nil. STATE is +an `erc--input-split' object." + (when (and erc-send-whitespace-lines (erc--input-split-lines state)) + (let ((reversed (nreverse (erc--input-split-lines state)))) + (when (string-empty-p (car reversed)) + (pop reversed) + (setf (erc--input-split-cmdp state) nil)) + (nreverse (seq-drop-while #'string-empty-p reversed))))) + +(defun erc-send-input (input &optional skip-ws-chk) "Treat INPUT as typed in by the user. It is assumed that the input and the prompt is already deleted. Return non-nil only if we actually send anything." ;; Handle different kinds of inputs - (cond - ;; Ignore empty input - ((if erc-send-whitespace-lines - (string= input "") - (string-match "\\`[ \t\r\f\n]*\\'" input)) - (when erc-warn-about-blank-lines - (message "Blank line - ignoring...") - (beep)) - nil) - (t + (if (and (not skip-ws-chk) + (erc--check-prompt-input-for-multiline-blanks + input (split-string input erc--input-line-delim-regexp))) + (when erc-warn-about-blank-lines + (message "Blank line - ignoring...") ; compat + (beep)) ;; This dynamic variable is used by `erc-send-pre-hook'. It's ;; obsolete, and when it's finally removed, this binding should ;; also be removed. @@ -5944,27 +6022,28 @@ Return non-nil only if we actually send anything." :insertp erc-insert-this :sendp erc-send-this)) (run-hook-with-args 'erc-pre-send-functions state) + (setq state (make-erc--input-split + :string (erc-input-string state) + :insertp (erc-input-insertp state) + :sendp (erc-input-sendp state) + :lines (split-string (erc-input-string state) + erc--input-line-delim-regexp) + :cmdp (string-match erc-command-regexp + (erc-input-string state)))) + (run-hook-with-args 'erc--pre-send-split-functions state) (when (and (erc-input-sendp state) - erc-send-this) - (let ((string (erc-input-string state))) - (if (or (if (>= emacs-major-version 28) - (string-search "\n" string) - (string-match "\n" string)) - (not (string-match erc-command-regexp string))) - (mapc - (lambda (line) - (mapc - (lambda (line) - ;; Insert what has to be inserted for this. - (when (erc-input-insertp state) - (erc-display-msg line)) - (erc-process-input-line (concat line "\n") - (null erc-flood-protect) t)) - (or (and erc-flood-protect (erc-split-line line)) - (list line)))) - (split-string string "\n")) - (erc-process-input-line (concat string "\n") t nil)) - t)))))) + erc-send-this) + (let ((lines (erc--input-split-lines state))) + (if (and (erc--input-split-cmdp state) (not (cdr lines))) + (erc-process-input-line (concat (car lines) "\n") t nil) + (dolist (line lines) + (dolist (line (or (and erc-flood-protect (erc-split-line line)) + (list line))) + (when (erc-input-insertp state) + (erc-display-msg line)) + (erc-process-input-line (concat line "\n") + (null erc-flood-protect) t)))) + t))))) (defun erc-display-msg (line) "Display LINE as a message of the user to the current target at point." diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index afe9cc7b8c..986988a335 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -588,6 +588,214 @@ (kill-buffer "*erc-protocol*") (should-not erc-debug-irc-protocol))) +(ert-deftest erc--input-line-delim-regexp () + (let ((p erc--input-line-delim-regexp)) + ;; none + (should (equal '("a" "b") (split-string "a\r\nb" p))) + (should (equal '("a" "b") (split-string "a\nb" p))) + (should (equal '("a" "b") (split-string "a\rb" p))) + + ;; one + (should (equal '("") (split-string "" p))) + (should (equal '("a" "" "b") (split-string "a\r\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\rb" p))) + (should (equal '("a" "" "b") (split-string "a\n\nb" p))) + (should (equal '("a" "" "b") (split-string "a\r\r\nb" p))) + (should (equal '("a" "" "b") (split-string "a\n\r\nb" p))) + (should (equal '("a" "") (split-string "a\n" p))) + (should (equal '("a" "") (split-string "a\r" p))) + (should (equal '("a" "") (split-string "a\r\n" p))) + (should (equal '("" "b") (split-string "\nb" p))) + (should (equal '("" "b") (split-string "\rb" p))) + (should (equal '("" "b") (split-string "\r\nb" p))) + + ;; two + (should (equal '("" "") (split-string "\r" p))) + (should (equal '("" "") (split-string "\n" p))) + (should (equal '("" "") (split-string "\r\n" p))) + + ;; three + (should (equal '("" "" "") (split-string "\r\r" p))) + (should (equal '("" "" "") (split-string "\n\n" p))) + (should (equal '("" "" "") (split-string "\n\r" p))))) + +(ert-deftest erc--blank-in-multiline-input-p () + (let ((check (lambda (s) + (erc--blank-in-multiline-input-p + (split-string s erc--input-line-delim-regexp))))) + + (ert-info ("With `erc-send-whitespace-lines'") + (let ((erc-send-whitespace-lines t)) + (should (funcall check "")) + (should-not (funcall check "\na")) + (should-not (funcall check "/msg a\n")) ; real /cmd + (should-not (funcall check "a\n\nb")) ; "" allowed + (should-not (funcall check "/msg a\n\nb")) ; non-/cmd + (should-not (funcall check " ")) + (should-not (funcall check "\t")) + (should-not (funcall check "a\nb")) + (should-not (funcall check "a\n ")) + (should-not (funcall check "a\n \t")) + (should-not (funcall check "a\n \f")) + (should-not (funcall check "a\n \nb")) + (should-not (funcall check "a\n \t\nb")) + (should-not (funcall check "a\n \f\nb")))) + + (should (funcall check "")) + (should (funcall check " ")) + (should (funcall check "\t")) + (should (funcall check "a\n\nb")) + (should (funcall check "a\n\nb")) + (should (funcall check "a\n ")) + (should (funcall check "a\n \t")) + (should (funcall check "a\n \f")) + (should (funcall check "a\n \nb")) + (should (funcall check "a\n \t\nb")) + + (should-not (funcall check "a\rb")) + (should-not (funcall check "a\nb")) + (should-not (funcall check "a\r\nb")))) + +(defun erc-tests--with-process-input-spy (test) + (with-current-buffer (get-buffer-create "FakeNet") + (let* ((erc-pre-send-functions + (remove #'erc-add-to-input-ring erc-pre-send-functions)) ; for now + (inhibit-message noninteractive) + (erc-server-current-nick "tester") + (erc-last-input-time 0) + erc-accidental-paste-threshold-seconds + ;; + calls) + (cl-letf (((symbol-function 'erc-process-input-line) + (lambda (&rest r) (push r calls))) + ((symbol-function 'erc-server-buffer) + (lambda () (current-buffer)))) + (erc-tests--send-prep) + (funcall test (lambda () (pop calls))))) + (when noninteractive (kill-buffer)))) + +(ert-deftest erc--check-prompt-input-functions () + (erc-tests--with-process-input-spy + (lambda (next) + + (ert-info ("Errors when point not in prompt area") ; actually just dings + (insert "/msg #chan hi") + (forward-line -1) + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Point is not in the input area" (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when no process running") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "ERC: No process running" (cadr e)))) + (ert-info ("Input remains untouched") + (should (save-excursion (erc-bol) (looking-at "/msg #chan hi"))))) + + (ert-info ("Errors when line contains empty newline") + (erc-bol) + (delete-region (point) (point-max)) + (insert "one\n") + (let ((e (should-error (erc-send-current-line)))) + (should (equal "Blank line - ignoring..." (cadr e)))) + (goto-char (point-max)) + (ert-info ("Input remains untouched") + (should (save-excursion (goto-char erc-input-marker) + (looking-at "one\n"))))) + + (should (= 0 erc-last-input-time)) + (should-not (funcall next))))) + +;; These also indirectly tests `erc-send-input' + +(ert-deftest erc-send-current-line () + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (should (= 0 erc-last-input-time)) + + (ert-info ("Simple command") + (insert "/msg #chan hi") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + ;; Commands are forced (no flood protection) + (should (equal (funcall next) '("/msg #chan hi\n" t nil)))) + + (ert-info ("Simple non-command") + (insert "hi") + (erc-send-current-line) + (should (eq (point) (point-max))) + (should (save-excursion (forward-line -1) + (search-forward " hi"))) + ;; Non-ommands are forced only when `erc-flood-protect' is nil + (should (equal (funcall next) '("hi\n" nil t)))) + + (should (consp erc-last-input-time))))) + +(ert-deftest erc-send-whitespace-lines () + (erc-tests--with-process-input-spy + (lambda (next) + (erc-tests--set-fake-server-process "sleep" "1") + (setq-local erc-send-whitespace-lines t) + + (ert-info ("Multiline hunk with blank line correctly split") + (insert "one\n\ntwo") + (erc-send-current-line) + (ert-info ("Prompt restored") + (forward-line 0) + (should (looking-at-p erc-prompt))) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("two\n" nil t))) + (should (equal (funcall next) '("\n" nil t))) + (should (equal (funcall next) '("one\n" nil t)))) + + (ert-info ("Multiline hunk with trailing newline filtered") + (insert "hi\n") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline hunk with trailing carriage filtered") + (insert "hi\r") + (erc-send-current-line) + (ert-info ("Input cleared") + (erc-bol) + (should (eq (point) (point-max)))) + (should (equal (funcall next) '("hi\n" nil t))) + (should-not (funcall next))) + + (ert-info ("Multiline command with trailing blank filtered") + (pcase-dolist (`(,p . ,q) + '(("/a b\r" "/a b\n") ("/a b\n" "/a b\n") + ("/a b\n\n" "/a b\n") ("/a b\r\n" "/a b\n") + ("a b\nc\n\n" "c\n" "a b\n") + ("/a b\nc\n\n" "c\n" "/a b\n") + ("/a b\n\nc\n\n" "c\n" "\n" "/a b\n"))) + (insert p) + (erc-send-current-line) + (erc-bol) + (should (eq (point) (point-max))) + (while q + (should (equal (funcall next) (list (pop q) nil t)))) + (should-not (funcall next)))) + + (ert-info ("Multiline hunk with trailing whitespace not filtered") + (insert "there\n ") + (erc-send-current-line) + (should (equal (funcall next) '(" \n" nil t))) + (should (equal (funcall next) '("there\n" nil t))) + (should-not (funcall next)))))) ;; The point of this test is to ensure output is handled identically ;; regardless of whether a command handler is summoned. commit a9d89d083ac5bf0b9fd5568d42e565aba0b6e13f Author: F. Jason Park Date: Mon Mar 21 19:21:57 2022 -0700 Fix regression in erc-send-input-line * lisp/erc/erc.el (erc-send-input-line): Restore remedial single-space padding to ensure empty messages typed at the prompt without an explicit /msg aren't rejected by the server. This behavior is only noticeable when `erc-send-whitespace-lines' is active. * test/lisp/erc/erc-tests.el (erc-process-input-line): Add trailing newline to more correctly simulate how it's actually called by `erc-send-input'. (Bug#50008) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 1c221a9cb1..971d3f426f 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2992,6 +2992,8 @@ for special purposes (see erc-dcc.el).") (defun erc-send-input-line (target line &optional force) "Send LINE to TARGET." + (when (string= line "\n") + (setq line " \n")) (erc-message "PRIVMSG" (concat target " " line) force)) (defun erc-get-arglist (fun) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 618d7eeea0..afe9cc7b8c 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -643,19 +643,19 @@ (ert-info ("Implicit cmd via `erc-send-input-line-function'") (ert-info ("Baseline") - (erc-process-input-line "hi") + (erc-process-input-line "hi\n") (should (equal (pop erc-server-flood-queue) '("PRIVMSG #chan :hi\r\n" . utf-8)))) (ert-info ("Spaces preserved") - (erc-process-input-line "hi you") + (erc-process-input-line "hi you\n") (should (equal (pop erc-server-flood-queue) '("PRIVMSG #chan :hi you\r\n" . utf-8)))) - (ert-info ("Empty line transmitted without injected-space kludge") - (erc-process-input-line "") + (ert-info ("Empty line transmitted with injected-space kludge") + (erc-process-input-line "\n") (should (equal (pop erc-server-flood-queue) - '("PRIVMSG #chan :\r\n" . utf-8)))) + '("PRIVMSG #chan : \r\n" . utf-8)))) (should-not calls)))))) commit 05902243431c877011a0bf6ce38c9230d0ef0721 Author: F. Jason Park Date: Mon Aug 16 04:38:18 2021 -0700 Standardize auth-source queries in ERC * lisp/erc/erc.el (erc-password): Deprecate variable only used by `erc-select-read-args'. Server passwords are primarily used as surrogates for other forms of authentication. Such use is common but nonstandard and often discouraged in favor of the de facto standard, SASL. Folks in the habit of invoking `erc(-tls)' interactively should be encouraged to use auth-source instead. (erc-select-read-args): Before this change, `erc-select-read-args' offered to use the value of a non-nil `erc-password' as the :password argument for `erc' and `erc-tls', referring to it as the "default" password. And when `erc-prompt-for-password' was nil and `erc-password' wasn't, the latter was passed along unconditionally. This only further complicated an already confusing situation for new users, who in most cases shouldn't be worried about sending a PASS command at all. Until SASL arrives, they should provide server passwords manually or learn to use auth-source. (erc-auth-source-server-function, erc-auth-source-join-function): New user options for retrieving a password externally, ostensibly by calling `auth-source-search'. (erc--auth-source-determine-params-defaults): New helper for `erc--auth-source-search' with potential for exporting publicly in the future. Favors :host and :port fields above others. Prioritizes network IDs over announced servers and dialed endpoints. (erc--auth-source-determine-params-merge): Add new function for merging contextual and default parameters. This is another contender for possible exporting. (erc--auth-source-search): New function for consulting auth-source and sorting the result as filtered and prioritized by the previously mentioned helpers. (erc-auth-source-search): New function to serve as default value for auth-source query-function options. (erc-server-join-channel): Use user option for consulting auth-source facility. Also accept nil for first argument (instead of server). (erc-cmd-JOIN): Use above-mentioned facilities when joining new channel. Omit server when calling `erc-server-join-channel'. Don't filter target buffers twice. Don't call `switch-to-buffer', which would create phantom buffers with names like target/server that were never used. IOW, only switch to existing target buffers. (erc--compute-server-password): Add new helper function for determining password. (erc-open, erc-determine-parameters): Move password figuring from the first to the latter. * lisp/erc/erc-services.el (erc-auth-source-services-function): Add new option for consulting auth-source in a NickServ context. (erc-nickserv-get-password): Pass network-context ID, when looking up password in `erc-nickserv-passwords' and when formatting prompt for user input. (erc-nickserv-passwords): Add comment to custom option definition type tag. * test/lisp/erc/erc-services-tests.el: Add new test file for above changes. For now, stash auth-source-related tests here until a suitable home can be found. * lisp/erc/erc-join.el (erc-autojoin--join): Don't pass session-like entity from `erc-autojoin-channels-alist' match to `erc-server-join-channel'. Allow that function to decide for itself which host to look up if necessary. * test/lisp/erc/resources/base/auth-source/foonet.eld: New file. * test/lisp/erc/resources/base/auth-source/nopass.eld: New file. * test/lisp/erc/resources/erc-scenarios-common.el: New file. * test/lisp/erc/resources/services/auth-source/libera.eld: New file. * test/lisp/erc/erc-scenarios-auth-source.el: New file. * test/lisp/erc/erc-scenarios-base-reuse-buffers.el: New file. * test/lisp/erc/erc-scenarios-join-auth-source.el: New file. * test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld: New file. * test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld: New file. * test/lisp/erc/resources/join/auth-source/foonet.eld: New file. (Bug#48598) diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el index d4edca236d..b4044548e8 100644 --- a/lisp/erc/erc-join.el +++ b/lisp/erc/erc-join.el @@ -145,7 +145,7 @@ network or a network ID). Return nil on failure." (let ((buf (erc-get-buffer chan erc-server-process))) (unless (and buf (with-current-buffer buf (erc--current-buffer-joined-p))) - (erc-server-join-channel match chan))))))) + (erc-server-join-channel nil chan))))))) (defun erc-autojoin-after-ident (_network _nick) "Autojoin channels in `erc-autojoin-channels-alist'. diff --git a/lisp/erc/erc-services.el b/lisp/erc/erc-services.el index cc5d5701e4..fe9cb5b5f1 100644 --- a/lisp/erc/erc-services.el +++ b/lisp/erc/erc-services.el @@ -174,6 +174,18 @@ function `erc-nickserv-get-password'." :version "28.1" :type 'boolean) +(defcustom erc-auth-source-services-function #'erc-auth-source-search + "Function to retrieve NickServ password from auth-source. +Called with a subset of keyword parameters known to +`auth-source-search' and relevant to authenticating to nickname +services. In return, ERC expects a string to send as the +password, or nil, to fall through to the next method, such as +prompting. See info node `(erc) Connecting' for details." + :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA + :type '(choice (const erc-auth-source-search) + (const nil) + function)) + (defcustom erc-nickserv-passwords nil "Passwords used when identifying to NickServ automatically. `erc-prompt-for-nickserv-password' must be nil for these @@ -202,7 +214,7 @@ Example of use: (const QuakeNet) (const Rizon) (const SlashNET) - (symbol :tag "Network name")) + (symbol :tag "Network name or session ID")) (repeat :tag "Nickname and password" (cons :tag "Identity" (string :tag "Nick") @@ -431,31 +443,20 @@ As soon as some source returns a password, the sequence of lookups stops and this function returns it (or returns nil if it is empty). Otherwise, no corresponding password was found, and it returns nil." - (let (network server port) - ;; Fill in local vars, switching to the server buffer once only - (erc-with-server-buffer - (setq network erc-network - server erc-session-server - port erc-session-port)) - (let ((ret - (or - (when erc-nickserv-passwords - (cdr (assoc nick - (cl-second (assoc network - erc-nickserv-passwords))))) - (when erc-use-auth-source-for-nickserv-password - (auth-source-pick-first-password - :require '(:secret) - :host server - ;; Ensure a string for :port - :port (format "%s" port) - :user nick)) - (when erc-prompt-for-nickserv-password - (read-passwd - (format "NickServ password for %s on %s (RET to cancel): " - nick network)))))) - (when (and ret (not (string= ret ""))) - ret)))) + (when-let* + ((nid (erc-networks--id-symbol erc-networks--id)) + (ret (or (when erc-nickserv-passwords + (assoc-default nick + (cadr (assq nid erc-nickserv-passwords)))) + (when (and erc-use-auth-source-for-nickserv-password + erc-auth-source-services-function) + (funcall erc-auth-source-services-function :user nick)) + (when erc-prompt-for-nickserv-password + (read-passwd + (format "NickServ password for %s on %s (RET to cancel): " + nick nid))))) + ((not (string-empty-p ret)))) + ret)) (defvar erc-auto-discard-away) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 4b24f953dd..1c221a9cb1 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -228,9 +228,14 @@ parameters and authentication." "old behavior when t now permanent" "29.1") (defvar erc-password nil - "Password to use when authenticating to an IRC server. -It is not strictly necessary to provide this, since ERC will -prompt you for it.") + "Password to use when authenticating to an IRC server interactively. + +This variable only exists for legacy reasons. It's not customizable and +is limited to a single server password. Users looking for similar +functionality should consider auth-source instead. See info +node `(auth) Top' and info node `(erc) Connecting'.") + +(make-obsolete-variable 'erc-password "use auth-source instead" "29.1") (defcustom erc-user-mode "+i" ;; +i "Invisible". Hides user from global /who and /names. @@ -241,7 +246,7 @@ prompt you for it.") (defcustom erc-prompt-for-password t - "Asks before using the default password, or whether to enter a new one." + "Ask for a server password when invoking `erc-tls' interactively." :group 'erc :type 'boolean) @@ -2210,15 +2215,6 @@ Returns the buffer for the given server or channel." (setq erc-logged-in nil) ;; The local copy of `erc-nick' - the list of nicks to choose (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick))) - ;; password stuff - (setq erc-session-password - (or passwd - (auth-source-pick-first-password - :host server - :user nick - ;; secrets.el wouldn’t accept a number - :port (if (numberp port) (number-to-string port) port) - :require '(:secret)))) ;; client certificate (only useful if connecting over TLS) (setq erc-session-client-certificate client-certificate) (setq erc-networks--id (if connect @@ -2240,7 +2236,7 @@ Returns the buffer for the given server or channel." (erc-display-prompt) (goto-char (point-max))) - (erc-determine-parameters server port nick full-name user) + (erc-determine-parameters server port nick full-name user passwd) ;; Saving log file on exit (run-hook-with-args 'erc-connect-pre-hook buffer) @@ -2338,11 +2334,9 @@ parameters SERVER and NICK." (setq server user-input) (setq passwd (if erc-prompt-for-password - (if (and erc-password - (y-or-n-p "Use the default password? ")) - erc-password - (read-passwd "Password: ")) - erc-password)) + (read-passwd "Server password: ") + (with-suppressed-warnings ((obsolete erc-password)) + erc-password))) (when (and passwd (string= "" passwd)) (setq passwd nil)) @@ -3355,18 +3349,131 @@ For a list of user commands (/join /part, ...): (defalias 'erc-cmd-H #'erc-cmd-HELP) (put 'erc-cmd-HELP 'process-not-needed t) +(defcustom erc-auth-source-server-function #'erc-auth-source-search + "Function to query auth-source for a server password. +Called with a subset of keyword parameters known to +`auth-source-search' and relevant to an opening \"PASS\" command, +if any. In return, ERC expects a string to send as the server +password, or nil, to skip the \"PASS\" command completely. An +explicit `:password' argument to entry-point commands `erc' and +`erc-tls' also inhibits lookup, as does setting this option to +nil. See info node `(erc) Connecting' for details." + :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA + :group 'erc + :type '(choice (const erc-auth-source-search) + (const nil) + function)) + +(defcustom erc-auth-source-join-function #'erc-auth-source-search + "Function to query auth-source on joining a channel. +Called with a subset of keyword arguments known to +`auth-source-search' and relevant to joining a password-protected +channel. In return, ERC expects a string to use as the channel +\"key\", or nil to just join the channel normally. Setting the +option itself to nil tells ERC to always forgo consulting +auth-source for channel keys. For more information, see info +node `(erc) Connecting'." + :package-version '(ERC . "5.4.1") ; FIXME update when publishing to ELPA + :group 'erc + :type '(choice (const erc-auth-source-search) + (const nil) + function)) + +(defun erc--auth-source-determine-params-defaults () + (let* ((net (and-let* ((esid (erc-networks--id-symbol erc-networks--id)) + ((symbol-name esid))))) + (localp (and erc--target (erc--target-channel-local-p erc--target))) + (hosts (if localp + (list erc-server-announced-name erc-session-server net) + (list net erc-server-announced-name erc-session-server))) + (ports (list (cl-typecase erc-session-port + (integer (number-to-string erc-session-port)) + (string (and (string= erc-session-port "irc") + erc-session-port)) ; or nil + (t erc-session-port)) + "irc"))) + (list (cons :host (delq nil hosts)) + (cons :port (delq nil ports)) + (cons :require '(:secret))))) + +(defun erc--auth-source-determine-params-merge (&rest plist) + "Return a plist of merged keyword args to pass to `auth-source-search'. +Combine items in PLIST with others derived from the current connection +context, but prioritize the former. For keys not present in PLIST, +favor a network ID over an announced server unless `erc--target' is a +local channel. And treat the dialed server address as a fallback for +the announced name in both cases." + (let ((defaults (erc--auth-source-determine-params-defaults))) + `(,@(cl-loop for (key value) on plist by #'cddr + for default = (assq key defaults) + do (when default (setq defaults (delq default defaults))) + append `(,key ,(delete-dups + `(,@(if (consp value) value (list value)) + ,@(cdr default))))) + ,@(cl-loop for (k . v) in defaults append (list k v))))) + +(defun erc--auth-source-search (&rest defaults) + "Ask auth-source for a secret and return it if found. +Use DEFAULTS as keyword arguments for querying auth-source and as a +guide for narrowing results. Return a string if found or nil otherwise. +The ordering of DEFAULTS influences how results are filtered, as does +the ordering of the members of any individual composite values. If +necessary, the former takes priority. For example, if DEFAULTS were to +contain + + :host (\"foo\" \"bar\") :port (\"123\" \"456\") + +the secret from an auth-source entry of host foo and port 456 would be +chosen over another of host bar and port 123. However, if DEFAULTS +looked like + + :port (\"123\" \"456\") :host (\"foo\" \"bar\") + +the opposite would be true. In both cases, two entries with the same +host but different ports would result in the one with port 123 getting +the nod. Much the same would happen for entries sharing only a port: +the one with host foo would win." + (when-let* + ((priority (map-keys defaults)) + (test (lambda (a b) + (catch 'done + (dolist (key priority) + (let* ((d (plist-get defaults key)) + (defval (if (listp d) d (list d))) + ;; featurep 'seq via auth-source > json > map + (p (seq-position defval (plist-get a key))) + (q (seq-position defval (plist-get b key)))) + (unless (eql p q) + (throw 'done (when p (or (not q) (< p q)))))))))) + (plist (copy-sequence defaults))) + (unless (plist-get plist :max) + (setq plist (plist-put plist :max 5000))) ; `auth-source-netrc-parse' + (unless (plist-get defaults :require) + (setq plist (plist-put plist :require '(:secret)))) + (when-let* ((sorted (sort (apply #'auth-source-search plist) test)) + (secret (plist-get (car sorted) :secret))) + (if (functionp secret) (funcall secret) secret)))) + +(defun erc-auth-source-search (&rest plist) + "Call `auth-source-search', possibly with keyword params in PLIST." + ;; These exist as separate helpers in case folks should find them + ;; useful. If that's you, please request that they be exported. + (apply #'erc--auth-source-search + (apply #'erc--auth-source-determine-params-merge plist))) + (defun erc-server-join-channel (server channel &optional secret) - (let ((password - (or secret - (auth-source-pick-first-password - :host server - :port "irc" - :user channel)))) - (erc-log (format "cmd: JOIN: %s" channel)) - (erc-server-send (concat "JOIN " channel - (if password - (concat " " password) - ""))))) + "Join CHANNEL, optionally with SECRET. +Without SECRET, consult auth-source, possibly passing SERVER as the +`:host' query parameter." + (unless (or secret (not erc-auth-source-join-function)) + (unless server + (when (and erc-server-announced-name + (erc--valid-local-channel-p channel)) + (setq server erc-server-announced-name))) + (setq secret (apply erc-auth-source-join-function + `(,@(and server (list :host server)) :user ,channel)))) + (erc-log (format "cmd: JOIN: %s" channel)) + (erc-server-send (concat "JOIN " channel (and secret (concat " " secret))))) (defun erc--valid-local-channel-p (channel) "Non-nil when channel is server-local on a network that allows them." @@ -3388,19 +3495,12 @@ were most recently invited. See also `invitation'." (setq chnl (erc-ensure-channel-name channel))) (when chnl ;; Prevent double joining of same channel on same server. - (let* ((joined-channels - (mapcar (lambda (chanbuf) - (with-current-buffer chanbuf (erc-default-target))) - (erc-channel-list erc-server-process))) - (server (with-current-buffer (process-buffer erc-server-process) - (or erc-session-server erc-server-announced-name))) - (chnl-name (car (erc-member-ignore-case chnl joined-channels)))) - (if chnl-name - (switch-to-buffer (if (get-buffer chnl-name) - chnl-name - (concat chnl-name "/" server))) - (setq erc--server-last-reconnect-count 0) - (erc-server-join-channel server chnl key))))) + (if-let* ((existing (erc-get-buffer chnl erc-server-process)) + ((with-current-buffer existing + (erc-get-channel-user (erc-current-nick))))) + (switch-to-buffer existing) + (setq erc--server-last-reconnect-count 0) + (erc-server-join-channel nil chnl key)))) t) (defalias 'erc-cmd-CHANNEL #'erc-cmd-JOIN) @@ -6356,7 +6456,7 @@ user input." ;; connection properties' heuristics -(defun erc-determine-parameters (&optional server port nick name user) +(defun erc-determine-parameters (&optional server port nick name user passwd) "Determine the connection and authentication parameters. Sets the buffer local variables: @@ -6365,12 +6465,14 @@ Sets the buffer local variables: - `erc-session-port' - `erc-session-user-full-name' - `erc-session-username' +- `erc-session-password' - `erc-server-current-nick'" (setq erc-session-connector erc-server-connect-function erc-session-server (erc-compute-server server) erc-session-port (or port erc-default-port) erc-session-user-full-name (erc-compute-full-name name) - erc-session-username (erc-compute-user user)) + erc-session-username (erc-compute-user user) + erc-session-password (erc--compute-server-password passwd nick)) (erc-set-current-nick (erc-compute-nick nick))) (defun erc-compute-server (&optional server) @@ -6407,6 +6509,12 @@ non-nil value is found. (getenv "IRCNICK") (user-login-name))) +(defun erc--compute-server-password (password nick) + "Maybe provide a PASSWORD argument for the IRC \"PASS\" command. +When `erc-auth-source-server-function' is non-nil, call it with NICK for +the user field and use whatever it returns as the server password." + (or password (and erc-auth-source-server-function + (funcall erc-auth-source-server-function :user nick)))) (defun erc-compute-full-name (&optional full-name) "Return user's full name. diff --git a/test/lisp/erc/erc-scenarios-auth-source.el b/test/lisp/erc/erc-scenarios-auth-source.el new file mode 100644 index 0000000000..3d399a1815 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-auth-source.el @@ -0,0 +1,178 @@ +;;; erc-scenarios-auth-source.el --- auth-source scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;; Commentary: +;; +;; For practical reasons (mainly lack of imagination), this file +;; contains tests for both server-password and NickServ contexts. + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join) + (require 'erc-services)) + +(defun erc-scenarios-common--auth-source (id dialog &rest rest) + (push "machine GNU.chat port %d user \"#chan\" password spam" rest) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/auth-source") + (dumb-server (erc-d-run "localhost" t dialog)) + (port (process-contact dumb-server :service)) + (ents `(,@(mapcar (lambda (fmt) (format fmt port)) rest) + "machine MyHost port irc password 123")) + (netrc-file (make-temp-file "auth-source-test" nil nil + (string-join ents "\n"))) + (auth-sources (list netrc-file)) + (auth-source-do-cache nil) + (erc-scenarios-common-extra-teardown (lambda () + (delete-file netrc-file)))) + + (ert-info ("Connect") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :full-name "tester" + :id id) + (should (string= (buffer-name) (if id + (symbol-name id) + (format "127.0.0.1:%d" port)))) + (erc-d-t-wait-for 5 (eq erc-network 'FooNet)))))) + +(ert-deftest erc-scenarios-base-auth-source-server--dialed () + :tags '(:expensive-test) + (erc-scenarios-common--auth-source + nil 'foonet + "machine GNU.chat port %d user tester password fake" + "machine FooNet port %d user tester password fake" + "machine 127.0.0.1 port %d user tester password changeme" + "machine 127.0.0.1 port %d user imposter password fake")) + +(ert-deftest erc-scenarios-base-auth-source-server--netid () + :tags '(:expensive-test) + (erc-scenarios-common--auth-source + 'MySession 'foonet + "machine MySession port %d user tester password changeme" + "machine 127.0.0.1 port %d user tester password fake" + "machine FooNet port %d user tester password fake")) + +(ert-deftest erc-scenarios-base-auth-source-server--netid-custom () + :tags '(:expensive-test) + (let ((erc-auth-source-server-function + (lambda (&rest _) (erc-auth-source-search :host "MyHost")))) + (erc-scenarios-common--auth-source + 'MySession 'foonet + "machine 127.0.0.1 port %d user tester password fake" + "machine MyHost port %d user tester password changeme" + "machine MySession port %d user tester password fake"))) + +(ert-deftest erc-scenarios-base-auth-source-server--nopass () + :tags '(:expensive-test) + (let (erc-auth-source-server-function) + (erc-scenarios-common--auth-source nil 'nopass))) + +(ert-deftest erc-scenarios-base-auth-source-server--nopass-netid () + :tags '(:expensive-test) + (let (erc-auth-source-server-function) + (erc-scenarios-common--auth-source 'MySession 'nopass))) + +;; Identify via auth source with no initial password + +(defun erc-scenarios-common--services-auth-source (&rest rest) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "services/auth-source") + (erc-server-flood-penalty 0.1) + (dumb-server (erc-d-run "localhost" t 'libera)) + (port (process-contact dumb-server :service)) + (ents `(,@(mapcar (lambda (fmt) (format fmt port)) rest) + "machine MyHost port irc password 123")) + (netrc-file (make-temp-file "auth-source-test" nil nil + (string-join ents "\n"))) + (auth-sources (list netrc-file)) + (auth-source-do-cache nil) + (erc-modules (cons 'services erc-modules)) + (erc-use-auth-source-for-nickserv-password t) ; do consult for NickServ + (expect (erc-d-t-make-expecter)) + (erc-scenarios-common-extra-teardown (lambda () + (delete-file netrc-file)))) + + (cl-letf (((symbol-function 'read-passwd) + (lambda (&rest _) (error "Unexpected read-passwd call")))) + (ert-info ("Connect without password") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :full-name "tester") + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (erc-d-t-wait-for 8 (eq erc-network 'Libera.Chat)) + (funcall expect 3 "This nickname is registered.") + (funcall expect 3 "You are now identified") + (funcall expect 3 "Last login from") + (erc-cmd-QUIT "")))) + + (erc-services-mode -1) + + (should-not (memq 'services erc-modules)))) + +;; These tests are about authenticating to nick services + +(ert-deftest erc-scenarios-services-auth-source--network () + :tags '(:expensive-test) + ;; Skip consulting auth-source for the server password (PASS). + (let (erc-auth-source-server-function) + (erc-scenarios-common--services-auth-source + "machine 127.0.0.1 port %d user tester password spam" + "machine zirconium.libera.chat port %d user tester password fake" + "machine Libera.Chat port %d user tester password changeme"))) + +(ert-deftest erc-scenarios-services-auth-source--network-connect-lookup () + :tags '(:expensive-test) + ;; Do consult auth-source for the server password (and find nothing) + (erc-scenarios-common--services-auth-source + "machine zirconium.libera.chat port %d user tester password fake" + "machine Libera.Chat port %d user tester password changeme")) + +(ert-deftest erc-scenarios-services-auth-source--announced () + :tags '(:expensive-test) + (let (erc-auth-source-server-function) + (erc-scenarios-common--services-auth-source + "machine 127.0.0.1 port %d user tester password spam" + "machine zirconium.libera.chat port %d user tester password changeme"))) + +(ert-deftest erc-scenarios-services-auth-source--dialed () + :tags '(:expensive-test) + ;; Support legacy host -> domain name + ;; (likely most common in real configs) + (let (erc-auth-source-server-function) + (erc-scenarios-common--services-auth-source + "machine 127.0.0.1 port %d user tester password changeme"))) + +(ert-deftest erc-scenarios-services-auth-source--custom () + :tags '(:expensive-test) + (let (erc-auth-source-server-function + (erc-auth-source-services-function + (lambda (&rest _) (erc-auth-source-search :host "MyAccount")))) + (erc-scenarios-common--services-auth-source + "machine zirconium.libera.chat port %d user tester password spam" + "machine MyAccount port %d user tester password changeme" + "machine 127.0.0.1 port %d user tester password fake"))) + +;;; erc-scenarios-auth-source.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el index 2e3ed9969f..5af9589b74 100644 --- a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el +++ b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el @@ -107,4 +107,132 @@ collisions involving bouncers in ERC. Run EXTRA." erc-reuse-buffers) (erc-scenarios-common--base-reuse-buffers-server-buffers nil)))) +;; This also asserts that `erc-cmd-JOIN' is no longer susceptible to a +;; regression introduced in 28.1 (ERC 5.4) that caused phantom target +;; buffers of the form target/server to be created via +;; `switch-to-buffer' ("phantom" because they would go unused"). This +;; would happen (in place of a JOIN being sent out) when a previously +;; used (parted) target buffer existed and `erc-reuse-buffers' was +;; nil. +;; +;; Note: All the `erc-get-channel-user' calls have to do with the fact +;; that `erc-default-target' relies on the ambiguously defined +;; `erc-default-recipients' (meaning it's overloaded in the sense of +;; being used both for retrieving a target name and checking if a +;; channel has been PARTed). While not ideal, `erc-get-channel-user' +;; can (also) be used to detect the latter. + +(defun erc-scenarios-common--base-reuse-buffers-channel-buffers (port) + "The option `erc-reuse-buffers' is still respected when nil. +Adapted from scenario clash-of-chans/uniquify described in Bug#48598: +28.0.50; buffer-naming collisions involving bouncers in ERC." + (let* ((expect (erc-d-t-make-expecter)) + (server-buffer-foo + (get-buffer (format "127.0.0.1:%d/127.0.0.1" port))) + (server-buffer-bar + (get-buffer (format "127.0.0.1:%d/127.0.0.1<2>" port))) + (chan-buffer-foo (get-buffer "#chan/127.0.0.1")) + (chan-buffer-bar (get-buffer "#chan/127.0.0.1<2>")) + (server-process-foo (with-current-buffer server-buffer-foo + erc-server-process)) + (server-process-bar (with-current-buffer server-buffer-bar + erc-server-process))) + + (ert-info ("Unique #chan buffers exist") + (let ((chan-bufs (erc-scenarios-common-buflist "#chan")) + (known (list chan-buffer-bar chan-buffer-foo))) + (should (memq (pop chan-bufs) known)) + (should (memq (pop chan-bufs) known)) + (should-not chan-bufs))) + + (ert-info ("#chan@foonet is exclusive and not contaminated") + (with-current-buffer chan-buffer-foo + (funcall expect 1 "") + (erc-d-t-absent-for 0.1 "") + (funcall expect 1 "strength to climb") + (should (eq erc-server-process server-process-foo)))) + + (ert-info ("#chan@barnet is exclusive and not contaminated") + (with-current-buffer chan-buffer-bar + (funcall expect 1 "") + (erc-d-t-absent-for 0.1 "") + (funcall expect 1 "the loudest noise") + (should (eq erc-server-process server-process-bar)))) + + (ert-info ("Part #chan@foonet") + (with-current-buffer chan-buffer-foo + (erc-d-t-search-for 1 "shake my sword") + (erc-cmd-PART "#chan") + (funcall expect 3 "You have left channel #chan") + (erc-cmd-JOIN "#chan"))) + + (ert-info ("Part #chan@barnet") + (with-current-buffer chan-buffer-bar + (funcall expect 10 "Arm it in rags") + (should (erc-get-channel-user (erc-current-nick))) + (erc-cmd-PART "#chan") + (funcall expect 3 "You have left channel #chan") + (should-not (erc-get-channel-user (erc-current-nick))) + (erc-cmd-JOIN "#chan"))) + + (erc-d-t-wait-for 3 "New unique target buffer for #chan@foonet created" + (get-buffer "#chan/127.0.0.1<3>")) + + (ert-info ("Activity continues in new, -suffixed #chan@foonet buffer") + (with-current-buffer chan-buffer-foo + (should-not (erc-get-channel-user (erc-current-nick)))) + (with-current-buffer "#chan/127.0.0.1<3>" + (should (erc-get-channel-user (erc-current-nick))) + (funcall expect 2 "You have joined channel #chan") + (funcall expect 2 "#chan was created on") + (funcall expect 2 "") + (should (eq erc-server-process server-process-foo)) + (erc-d-t-absent-for 0.2 ""))) + + (sit-for 3) + (erc-d-t-wait-for 5 "New unique target buffer for #chan@barnet created" + (get-buffer "#chan/127.0.0.1<4>")) + + (ert-info ("Activity continues in new, -suffixed #chan@barnet buffer") + (with-current-buffer chan-buffer-bar + (should-not (erc-get-channel-user (erc-current-nick)))) + (with-current-buffer "#chan/127.0.0.1<4>" + (funcall expect 2 "You have joined channel #chan") + (funcall expect 1 "Users on #chan: @mike joe tester") + (funcall expect 2 "") + (should (eq erc-server-process server-process-bar)) + (erc-d-t-absent-for 0.2 ""))) + + (ert-info ("Two new chans created for a total of four") + (let* ((bufs (erc-scenarios-common-buflist "#chan")) + (names (sort (mapcar #'buffer-name bufs) #'string<))) + (should + (equal names (mapcar (lambda (f) (concat "#chan/127.0.0.1" f)) + '("" "<2>" "<3>" "<4>")))))) + + (ert-info ("All output sent") + (with-current-buffer "#chan/127.0.0.1<3>" + (funcall expect 10 "most lively")) + (with-current-buffer "#chan/127.0.0.1<4>" + (funcall expect 10 "soul black"))) + + ;; TODO ensure the exact 's aren't reassigned during killing as + ;; they are when the option is on. + (ert-info ("Buffers are exempt from shortening") + (kill-buffer "#chan/127.0.0.1<4>") + (kill-buffer "#chan/127.0.0.1<3>") + (kill-buffer chan-buffer-bar) + (should-not (get-buffer "#chan")) + (should chan-buffer-foo)))) + +(ert-deftest erc-scenarios-base-reuse-buffers-channel-buffers--disabled () + :tags '(:expensive-test) + (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + (should erc-reuse-buffers) + (let ((erc-scenarios-common-dialog "base/reuse-buffers/channel") + (erc-server-flood-penalty 0.1) + erc-reuse-buffers) + (erc-scenarios-common--base-reuse-buffers-server-buffers + #'erc-scenarios-common--base-reuse-buffers-channel-buffers)))) + ;;; erc-scenarios-base-reuse-buffers.el ends here diff --git a/test/lisp/erc/erc-scenarios-join-auth-source.el b/test/lisp/erc/erc-scenarios-join-auth-source.el new file mode 100644 index 0000000000..94336db07c --- /dev/null +++ b/test/lisp/erc/erc-scenarios-join-auth-source.el @@ -0,0 +1,67 @@ +;;; erc-scenarios-join-auth-source.el --- join-auth-source scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;;; Commentary: + +;; TODO add another test with autojoin and channel keys + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-join-auth-source--network () + :tags '(:expensive-test) + (should erc-auth-source-join-function) + (erc-scenarios-common-with-cleanup + ((entries + '("machine 127.0.0.1 port %d login \"#foo\" password spam" + "machine irc.foonet.org port %d login tester password fake" + "machine irc.foonet.org login \"#spam\" password secret" + "machine foonet port %d login dummy password fake" + "machine 127.0.0.1 port %d login dummy password changeme")) + (erc-scenarios-common-dialog "join/auth-source") + (erc-server-flood-penalty 0.1) + (dumb-server (erc-d-run "localhost" t 'foonet)) + (port (process-contact dumb-server :service)) + (ents (mapcar (lambda (fmt) (format fmt port)) entries)) + (netrc-file (make-temp-file "auth-source-test" nil nil + (string-join ents "\n"))) + (auth-sources (list netrc-file)) + (auth-source-do-cache nil) + (expect (erc-d-t-make-expecter)) + (erc-scenarios-common-extra-teardown (lambda () + (delete-file netrc-file)))) + + (ert-info ("Connect without password") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "dummy" + :full-name "dummy") + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (erc-d-t-wait-for 8 (eq erc-network 'foonet)) + (funcall expect 10 "user modes") + (erc-scenarios-common-say "/JOIN #spam"))) + + (ert-info ("Join #spam") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam")) + (funcall expect 10 "#spam was created on"))))) + +;;; erc-scenarios-join-auth-source.el ends here diff --git a/test/lisp/erc/erc-services-tests.el b/test/lisp/erc/erc-services-tests.el new file mode 100644 index 0000000000..8e2b8d2927 --- /dev/null +++ b/test/lisp/erc/erc-services-tests.el @@ -0,0 +1,574 @@ +;;; erc-services-tests.el --- Tests for erc-services. -*- lexical-binding:t -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published +;; by the Free Software Foundation, either version 3 of the License, +;; or (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; TODO: move the auth-source tests somewhere else. They've been +;; stashed here for pragmatic reasons. + +;;; Code: + +(require 'ert-x) +(require 'erc-services) +(require 'erc-compat) +(require 'secrets) + +;;;; Core auth-source + +(ert-deftest erc--auth-source-determine-params-merge () + (let ((erc-session-server "irc.gnu.org") + (erc-server-announced-name "my.gnu.org") + (erc-session-port 6697) + (erc-network 'fake) + (erc-server-current-nick "tester") + (erc-networks--id (erc-networks--id-create 'GNU.chat))) + + (should (equal (erc--auth-source-determine-params-merge) + '(:host ("GNU.chat" "my.gnu.org" "irc.gnu.org") + :port ("6697" "irc") + :require (:secret)))) + + (should (equal (erc--auth-source-determine-params-merge :host "fake") + '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org") + :port ("6697" "irc") + :require (:secret)))) + + (should (equal (erc--auth-source-determine-params-merge + :host '("fake") :require :host) + '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org") + :require (:host :secret) + :port ("6697" "irc")))) + + (should (equal (erc--auth-source-determine-params-merge + :host '("fake" "GNU.chat") :port "1234" :x "x") + '(:host ("fake" "GNU.chat" "my.gnu.org" "irc.gnu.org") + :port ("1234" "6697" "irc") + :x ("x") + :require (:secret)))))) + +;; Some of the following may be related to bug#23438. + +(defun erc-services-tests--auth-source-standard (search) + + (ert-info ("Session wins") + (let ((erc-session-server "irc.gnu.org") + (erc-server-announced-name "my.gnu.org") + (erc-session-port 6697) + (erc-network 'fake) + (erc-server-current-nick "tester") + (erc-networks--id (erc-networks--id-create 'GNU.chat))) + (should (string= (funcall search :user "#chan") "foo")))) + + (ert-info ("Network wins") + (let* ((erc-session-server "irc.gnu.org") + (erc-server-announced-name "my.gnu.org") + (erc-session-port 6697) + (erc-network 'GNU.chat) + (erc-server-current-nick "tester") + (erc-networks--id (erc-networks--id-create nil))) + (should (string= (funcall search :user "#chan") "foo")))) + + (ert-info ("Announced wins") + (let ((erc-session-server "irc.gnu.org") + (erc-server-announced-name "my.gnu.org") + (erc-session-port 6697) + erc-network + (erc-networks--id (erc-networks--id-create nil))) + (should (string= (funcall search :user "#chan") "baz"))))) + +(defun erc-services-tests--auth-source-announced (search) + (let* ((erc--isupport-params (make-hash-table)) + (erc-server-parameters '(("CHANTYPES" . "&#"))) + (erc--target (erc--target-from-string "&chan"))) + + (ert-info ("Announced prioritized") + + (ert-info ("Announced wins") + (let* ((erc-session-server "irc.gnu.org") + (erc-server-announced-name "my.gnu.org") + (erc-session-port 6697) + (erc-network 'GNU.chat) + (erc-server-current-nick "tester") + (erc-networks--id (erc-networks--id-create nil))) + (should (string= (funcall search :user "#chan") "baz")))) + + (ert-info ("Peer next") + (let* ((erc-server-announced-name "irc.gnu.org") + (erc-session-port 6697) + (erc-network 'GNU.chat) + (erc-server-current-nick "tester") + (erc-networks--id (erc-networks--id-create nil))) + (should (string= (funcall search :user "#chan") "bar")))) + + (ert-info ("Network used as fallback") + (let* ((erc-session-port 6697) + (erc-network 'GNU.chat) + (erc-server-current-nick "tester") + (erc-networks--id (erc-networks--id-create nil))) + (should (string= (funcall search :user "#chan") "foo"))))))) + +(defun erc-services-tests--auth-source-overrides (search) + (let* ((erc-session-server "irc.gnu.org") + (erc-server-announced-name "my.gnu.org") + (erc-network 'GNU.chat) + (erc-server-current-nick "tester") + (erc-networks--id (erc-networks--id-create nil)) + (erc-session-port 6667)) + + (ert-info ("Specificity and overrides") + + (ert-info ("More specific port") + (let ((erc-session-port 6697)) + (should (string= (funcall search :user "#chan") "spam")))) + + (ert-info ("More specific user (network loses)") + (should (string= (funcall search :user '("#fsf")) "42"))) + + (ert-info ("Actual override") + (should (string= (funcall search :port "6667") "sesame"))) + + (ert-info ("Overrides don't interfere with post-processing") + (should (string= (funcall search :host "MyHost") "123")))))) + +;; auth-source netrc backend + +(defvar erc-services-tests--auth-source-entries + '("machine irc.gnu.org port irc user \"#chan\" password bar" + "machine my.gnu.org port irc user \"#chan\" password baz" + "machine GNU.chat port irc user \"#chan\" password foo")) + +;; FIXME explain what this is for +(defun erc-services-tests--auth-source-shuffle (&rest extra) + (string-join `(,@(sort (append erc-services-tests--auth-source-entries extra) + (lambda (&rest _) (zerop (random 2)))) + "") + "\n")) + +(ert-deftest erc--auth-source-search--netrc-standard () + (ert-with-temp-file netrc-file + :prefix "erc--auth-source-search--standard" + :text (erc-services-tests--auth-source-shuffle) + + (let ((auth-sources (list netrc-file)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-standard #'erc-auth-source-search)))) + +(ert-deftest erc--auth-source-search--netrc-announced () + (ert-with-temp-file netrc-file + :prefix "erc--auth-source-search--announced" + :text (erc-services-tests--auth-source-shuffle) + + (let ((auth-sources (list netrc-file)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-announced #'erc-auth-source-search)))) + +(ert-deftest erc--auth-source-search--netrc-overrides () + (ert-with-temp-file netrc-file + :prefix "erc--auth-source-search--overrides" + :text (erc-services-tests--auth-source-shuffle + "machine GNU.chat port 6697 user \"#chan\" password spam" + "machine my.gnu.org port irc user \"#fsf\" password 42" + "machine irc.gnu.org port 6667 password sesame" + "machine MyHost port irc password 456" + "machine MyHost port 6667 password 123") + + (let ((auth-sources (list netrc-file)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-overrides #'erc-auth-source-search)))) + +;; auth-source plstore backend + +(defun erc-services-test--call-with-plstore (&rest args) + (advice-add 'epg-decrypt-string :override + (lambda (&rest r) (prin1-to-string (cadr r))) + '((name . erc--auth-source-plstore))) + (advice-add 'epg-find-configuration :override + (lambda (&rest _) "" '((program . "/bin/true"))) + '((name . erc--auth-source-plstore))) + (unwind-protect + (apply #'erc-auth-source-search args) + (advice-remove 'epg-decrypt-string 'erc--auth-source-plstore) + (advice-remove 'epg-find-configuration 'erc--auth-source-plstore))) + +(defvar erc-services-tests--auth-source-plstore-standard-entries + '(("ba950d38118a76d71f9f0591bb373d6cb366a512" + :secret-secret t + :host "irc.gnu.org" + :user "#chan" + :port "irc") + ("7f17ca445d11158065e911a6d0f4cbf52ca250e3" + :secret-secret t + :host "my.gnu.org" + :user "#chan" + :port "irc") + ("fcd3c8bd6daf4509de0ad6ee98e744ce0fca9377" + :secret-secret t + :host "GNU.chat" + :user "#chan" + :port "irc"))) + +(defvar erc-services-tests--auth-source-plstore-standard-secrets + '(("ba950d38118a76d71f9f0591bb373d6cb366a512" :secret "bar") + ("7f17ca445d11158065e911a6d0f4cbf52ca250e3" :secret "baz") + ("fcd3c8bd6daf4509de0ad6ee98e744ce0fca9377" :secret "foo"))) + +(ert-deftest erc--auth-source-search--plstore-standard () + (ert-with-temp-file plstore-file + :suffix ".plist" + :text (concat ";;; public entries -*- mode: plstore -*- \n" + (prin1-to-string + erc-services-tests--auth-source-plstore-standard-entries) + "\n;;; secret entries\n" + (prin1-to-string + erc-services-tests--auth-source-plstore-standard-secrets) + "\n") + + (let ((auth-sources (list plstore-file)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-standard + #'erc-services-test--call-with-plstore)))) + +(ert-deftest erc--auth-source-search--plstore-announced () + (ert-with-temp-file plstore-file + :suffix ".plist" + :text (concat ";;; public entries -*- mode: plstore -*- \n" + (prin1-to-string + erc-services-tests--auth-source-plstore-standard-entries) + "\n;;; secret entries\n" + (prin1-to-string + erc-services-tests--auth-source-plstore-standard-secrets) + "\n") + + (let ((auth-sources (list plstore-file)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-announced + #'erc-services-test--call-with-plstore)))) + +(ert-deftest erc--auth-source-search--plstore-overrides () + (ert-with-temp-file plstore-file + :suffix ".plist" + :text (concat + ";;; public entries -*- mode: plstore -*- \n" + (prin1-to-string + `(,@erc-services-tests--auth-source-plstore-standard-entries + ("1b3fab249a8dff77a4d8fe7eb4b0171b25cc711a" + :secret-secret t :host "GNU.chat" :user "#chan" :port "6697") + ("6cbcdc39476b8cfcca6f3e9a7876f41ec3f708cc" + :secret-secret t :host "my.gnu.org" :user "#fsf" :port "irc") + ("a33e2b3bd2d6f33995a4b88710a594a100c5e41d" + :secret-secret t :host "irc.gnu.org" :port "6667") + ("ab2fd349b2b7d6a9215bb35a92d054261b0b1537" + :secret-secret t :host "MyHost" :port "irc") + ("61a6bd552059494f479ff720e8de33e22574650a" + :secret-secret t :host "MyHost" :port "6667"))) + "\n;;; secret entries\n" + (prin1-to-string + `(,@erc-services-tests--auth-source-plstore-standard-secrets + ("1b3fab249a8dff77a4d8fe7eb4b0171b25cc711a" :secret "spam") + ("6cbcdc39476b8cfcca6f3e9a7876f41ec3f708cc" :secret "42") + ("a33e2b3bd2d6f33995a4b88710a594a100c5e41d" :secret "sesame") + ("ab2fd349b2b7d6a9215bb35a92d054261b0b1537" :secret "456") + ("61a6bd552059494f479ff720e8de33e22574650a" :secret "123"))) + "\n") + + (let ((auth-sources (list plstore-file)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-overrides + #'erc-services-test--call-with-plstore)))) + +;; auth-source JSON backend + +(defvar erc-services-tests--auth-source-json-standard-entries + [(:host "irc.gnu.org" :port "irc" :user "#chan" :secret "bar") + (:host "my.gnu.org" :port "irc" :user "#chan" :secret "baz") + (:host "GNU.chat" :port "irc" :user "#chan" :secret "foo")]) + +(ert-deftest erc--auth-source-search--json-standard () + (ert-with-temp-file json-store + :suffix ".json" + :text (let ((json-object-type 'plist)) + (json-encode + erc-services-tests--auth-source-json-standard-entries)) + (let ((auth-sources (list json-store)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-standard #'erc-auth-source-search)))) + +(ert-deftest erc--auth-source-search--json-announced () + (ert-with-temp-file plstore-file + :suffix ".json" + :text (let ((json-object-type 'plist)) + (json-encode + erc-services-tests--auth-source-json-standard-entries)) + + (let ((auth-sources (list plstore-file)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-announced #'erc-auth-source-search)))) + +(ert-deftest erc--auth-source-search--json-overrides () + (ert-with-temp-file json-file + :suffix ".json" + :text (let ((json-object-type 'plist)) + (json-encode + (vconcat + erc-services-tests--auth-source-json-standard-entries + [(:secret "spam" :host "GNU.chat" :user "#chan" :port "6697") + (:secret "42" :host "my.gnu.org" :user "#fsf" :port "irc") + (:secret "sesame" :host "irc.gnu.org" :port "6667") + (:secret "456" :host "MyHost" :port "irc") + (:secret "123" :host "MyHost" :port "6667")]))) + + (let ((auth-sources (list json-file)) + (auth-source-do-cache nil)) + (erc-services-tests--auth-source-overrides #'erc-auth-source-search)))) + +;; auth-source-secrets backend + +(defvar erc-services-tests--auth-source-secrets-standard-entries + '(("#chan@irc.gnu.org:irc" ; label + (:host . "irc.gnu.org") + (:user . "#chan") + (:port . "irc") + (:xdg:schema . "org.freedesktop.Secret.Generic")) + ("#chan@my.gnu.org:irc" + (:host . "my.gnu.org") + (:user . "#chan") + (:port . "irc") + (:xdg:schema . "org.freedesktop.Secret.Generic")) + ("#chan@GNU.chat:irc" + (:host . "GNU.chat") + (:user . "#chan") + (:port . "irc") + (:xdg:schema . "org.freedesktop.Secret.Generic")))) + +(defvar erc-services-tests--auth-source-secrets-standard-secrets + '(("#chan@irc.gnu.org:irc" . "bar") + ("#chan@my.gnu.org:irc" . "baz") + ("#chan@GNU.chat:irc" . "foo"))) + +(ert-deftest erc--auth-source-search--secrets-standard () + (skip-unless (bound-and-true-p secrets-enabled)) + (let ((auth-sources '("secrets:Test")) + (auth-source-do-cache nil) + (entries erc-services-tests--auth-source-secrets-standard-entries) + (secrets erc-services-tests--auth-source-secrets-standard-secrets)) + + (cl-letf (((symbol-function 'secrets-search-items) + (lambda (col &rest r) + (should (equal col "Test")) + (should (plist-get r :user)) + (map-keys entries))) + ((symbol-function 'secrets-get-secret) + (lambda (col label) + (should (equal col "Test")) + (assoc-default label secrets))) + ((symbol-function 'secrets-get-attributes) + (lambda (col label) + (should (equal col "Test")) + (assoc-default label entries)))) + + (erc-services-tests--auth-source-standard #'erc-auth-source-search)))) + +(ert-deftest erc--auth-source-search--secrets-announced () + (skip-unless (bound-and-true-p secrets-enabled)) + (let ((auth-sources '("secrets:Test")) + (auth-source-do-cache nil) + (entries erc-services-tests--auth-source-secrets-standard-entries) + (secrets erc-services-tests--auth-source-secrets-standard-secrets)) + + (cl-letf (((symbol-function 'secrets-search-items) + (lambda (col &rest r) + (should (equal col "Test")) + (should (plist-get r :user)) + (map-keys entries))) + ((symbol-function 'secrets-get-secret) + (lambda (col label) + (should (equal col "Test")) + (assoc-default label secrets))) + ((symbol-function 'secrets-get-attributes) + (lambda (col label) + (should (equal col "Test")) + (assoc-default label entries)))) + + (erc-services-tests--auth-source-announced #'erc-auth-source-search)))) + +(ert-deftest erc--auth-source-search--secrets-overrides () + (skip-unless (bound-and-true-p secrets-enabled)) + (let ((auth-sources '("secrets:Test")) + (auth-source-do-cache nil) + (entries `(,@erc-services-tests--auth-source-secrets-standard-entries + ("#chan@GNU.chat:6697" + (:host . "GNU.chat") (:user . "#chan") (:port . "6697") + (:xdg:schema . "org.freedesktop.Secret.Generic")) + ("#fsf@my.gnu.org:irc" + (:host . "my.gnu.org") (:user . "#fsf") (:port . "irc") + (:xdg:schema . "org.freedesktop.Secret.Generic")) + ("irc.gnu.org:6667" + (:host . "irc.gnu.org") (:port . "6667") + (:xdg:schema . "org.freedesktop.Secret.Generic")) + ("MyHost:irc" + (:host . "MyHost") (:port . "irc") + (:xdg:schema . "org.freedesktop.Secret.Generic")) + ("MyHost:6667" + (:host . "MyHost") (:port . "6667") + (:xdg:schema . "org.freedesktop.Secret.Generic")))) + (secrets `(,@erc-services-tests--auth-source-secrets-standard-secrets + ("#chan@GNU.chat:6697" . "spam") + ("#fsf@my.gnu.org:irc" . "42" ) + ("irc.gnu.org:6667" . "sesame") + ("MyHost:irc" . "456") + ("MyHost:6667" . "123")))) + + (cl-letf (((symbol-function 'secrets-search-items) + (lambda (col &rest _) + (should (equal col "Test")) + (map-keys entries))) + ((symbol-function 'secrets-get-secret) + (lambda (col label) + (should (equal col "Test")) + (assoc-default label secrets))) + ((symbol-function 'secrets-get-attributes) + (lambda (col label) + (should (equal col "Test")) + (assoc-default label entries)))) + + (erc-services-tests--auth-source-overrides #'erc-auth-source-search)))) + +;; auth-source-pass backend + +(require 'auth-source-pass) + +;; `auth-source-pass--find-match-unambiguous' returns something like: +;; +;; (list :host "irc.gnu.org" +;; :port "6697" +;; :user "rms" +;; :secret +;; #[0 "\301\302\300\"\207" +;; [((secret . "freedom")) auth-source-pass--get-attr secret] 3]) +;; +;; This function gives ^ (faked here to avoid gpg and file IO). See +;; `auth-source-pass--with-store' in ../auth-source-pass-tests.el +(defun erc-services-tests--asp-parse-entry (store entry) + (when-let ((found (cl-find entry store :key #'car :test #'string=))) + (list (assoc 'secret (cdr found))))) + +(defvar erc-join-tests--auth-source-pass-entries + '(("irc.gnu.org:irc/#chan" + ("port" . "irc") ("user" . "#chan") (secret . "bar")) + ("my.gnu.org:irc/#chan" + ("port" . "irc") ("user" . "#chan") (secret . "baz")) + ("GNU.chat:irc/#chan" + ("port" . "irc") ("user" . "#chan") (secret . "foo")))) + +(ert-deftest erc--auth-source-search--pass-standard () + (ert-skip "Pass backend not yet supported") + (let ((store erc-join-tests--auth-source-pass-entries) + (auth-sources '(password-store)) + (auth-source-do-cache nil)) + + (cl-letf (((symbol-function 'auth-source-pass-parse-entry) + (apply-partially #'erc-services-tests--asp-parse-entry store)) + ((symbol-function 'auth-source-pass-entries) + (lambda () (mapcar #'car store)))) + + (erc-services-tests--auth-source-standard #'erc-auth-source-search)))) + +(ert-deftest erc--auth-source-search--pass-announced () + (ert-skip "Pass backend not yet supported") + (let ((store erc-join-tests--auth-source-pass-entries) + (auth-sources '(password-store)) + (auth-source-do-cache nil)) + + (cl-letf (((symbol-function 'auth-source-pass-parse-entry) + (apply-partially #'erc-services-tests--asp-parse-entry store)) + ((symbol-function 'auth-source-pass-entries) + (lambda () (mapcar #'car store)))) + + (erc-services-tests--auth-source-announced #'erc-auth-source-search)))) + +(ert-deftest erc--auth-source-search--pass-overrides () + (ert-skip "Pass backend not yet supported") + (let ((store + `(,@erc-join-tests--auth-source-pass-entries + ("GNU.chat:6697/#chan" + ("port" . "6697") ("user" . "#chan") (secret . "spam")) + ("my.gnu.org:irc/#fsf" + ("port" . "irc") ("user" . "#fsf") (secret . "42")) + ("irc.gnu.org:6667" + ("port" . "6667") (secret . "sesame")) + ("MyHost:irc" + ("port" . "irc") (secret . "456")) + ("MyHost:6667" + ("port" . "6667") (secret . "123")))) + (auth-sources '(password-store)) + (auth-source-do-cache nil)) + + (cl-letf (((symbol-function 'auth-source-pass-parse-entry) + (apply-partially #'erc-services-tests--asp-parse-entry store)) + ((symbol-function 'auth-source-pass-entries) + (lambda () (mapcar #'car store)))) + + (erc-services-tests--auth-source-overrides #'erc-auth-source-search)))) + +;;;; The services module + +(ert-deftest erc-nickserv-get-password () + (should erc-prompt-for-nickserv-password) + (ert-with-temp-file netrc-file + :prefix "erc-nickserv-get-password" + :text (mapconcat 'identity + '("machine GNU/chat port 6697 user bob password spam" + "machine FSF.chat port 6697 user bob password sesame" + "machine MyHost port irc password 123") + "\n") + + (let* ((auth-sources (list netrc-file)) + (auth-source-do-cache nil) + (erc-nickserv-passwords '((FSF.chat (("alice" . "foo") + ("joe" . "bar"))))) + (erc-use-auth-source-for-nickserv-password t) + (erc-session-server "irc.gnu.org") + (erc-server-announced-name "my.gnu.org") + (erc-network 'FSF.chat) + (erc-server-current-nick "tester") + (erc-networks--id (erc-networks--id-create nil)) + (erc-session-port 6697)) + + (ert-info ("Lookup custom option") + (should (string= (erc-nickserv-get-password "alice") "foo"))) + + (ert-info ("Auth source") + (ert-info ("Network") + (should (string= (erc-nickserv-get-password "bob") "sesame"))) + + (ert-info ("Network ID") + (let ((erc-networks--id (erc-networks--id-create 'GNU/chat))) + (should (string= (erc-nickserv-get-password "bob") "spam"))))) + + (ert-info ("Read input") + (should (string= + (ert-simulate-keys "baz\r" (erc-nickserv-get-password "mike")) + "baz"))) + + (ert-info ("Failed") + (should-not (ert-simulate-keys "\r" + (erc-nickserv-get-password "fake"))))))) + + +;;; erc-services-tests.el ends here diff --git a/test/lisp/erc/resources/base/auth-source/foonet.eld b/test/lisp/erc/resources/base/auth-source/foonet.eld new file mode 100644 index 0000000000..1fe772c7e2 --- /dev/null +++ b/test/lisp/erc/resources/base/auth-source/foonet.eld @@ -0,0 +1,23 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) diff --git a/test/lisp/erc/resources/base/auth-source/nopass.eld b/test/lisp/erc/resources/base/auth-source/nopass.eld new file mode 100644 index 0000000000..3fdb4ecf7b --- /dev/null +++ b/test/lisp/erc/resources/base/auth-source/nopass.eld @@ -0,0 +1,22 @@ +;; -*- mode: lisp-data; -*- +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) diff --git a/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld b/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld new file mode 100644 index 0000000000..82700c5912 --- /dev/null +++ b/test/lisp/erc/resources/base/reuse-buffers/channel/barnet.eld @@ -0,0 +1,68 @@ +;; -*- mode: lisp-data; -*- +((pass 3 "PASS :barnet:changeme")) +((nick 3 "NICK tester")) +((user 3 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Wed, 05 May 2021 09:05:33 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@wvys46tx8tpmk.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester") + (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:16] joe: Tush! none but minstrels like of sonneting.") + (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:19] mike: Prithee, nuncle, be contented; 'tis a naughty night to swim in. Now a little fire in a wide field were like an old lecher's heart; a small spark, all the rest on's body cold. Look! here comes a walking fire.") + (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:22] joe: My name is Edgar, and thy father's son.") + (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:26] mike: Good my lord, be good to me; your honour is accounted a merciful man; good my lord.") + (0 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:31] joe: Thy child shall live, and I will see it nourish'd.") + (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :[09:09:33] mike: Quick, quick; fear nothing; I'll be at thy elbow.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0 ":irc.barnet.org NOTICE tester :[09:05:35] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.barnet.org 305 tester :You are no longer marked as being away")) + +((mode 3 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1620205534") + (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: That will be given to the loudest noise we make.") + (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: If it please your honour, I am the poor duke's constable, and my name is Elbow: I do lean upon justice, sir; and do bring in here before your good honour two notorious benefactors.") + (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Following the signs, woo'd but the sign of she.") + (0.5 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: That, sir, which I will not report after her.") + (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Boyet, prepare: I will away to-night.") + (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: If the man be a bachelor, sir, I can; but if he be a married man, he is his wife's head, and I can never cut off a woman's head.") + (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Thyself upon thy virtues, they on thee.") + (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: Arm it in rags, a pigmy's straw doth pierce it.")) + +((part 5.1 "PART #chan :" quit) + (0 ":tester!~u@wvys46tx8tpmk.irc PART #chan :" quit)) + +((join 10.1 "JOIN #chan") + (0 ":tester!~u@wvys46tx8tpmk.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :@mike joe tester") + (0 ":irc.barnet.org 366 tester #chan :End of NAMES list") + (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :tester, welcome!") + (0 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :tester, welcome!")) + +((mode 1 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1620205534") + (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Chi non te vede, non te pretia.") + (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: Well, if ever thou dost fall from this faith, thou wilt prove a notable argument.") + (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Of heavenly oaths, vow'd with integrity.") + (0.1 ":joe!~u@wvys46tx8tpmk.irc PRIVMSG #chan :mike: These herblets shall, which we upon you strew.") + (0.1 ":mike!~u@wvys46tx8tpmk.irc PRIVMSG #chan :joe: Aaron will have his soul black like his face.")) + +((linger 0.5 LINGER)) diff --git a/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld b/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld new file mode 100644 index 0000000000..a11cfac2e7 --- /dev/null +++ b/test/lisp/erc/resources/base/reuse-buffers/channel/foonet.eld @@ -0,0 +1,66 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Wed, 05 May 2021 09:05:34 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 12 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@247eaxkrufj44.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester") + (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:19] bob: Is this; she hath bought the name of whore thus dearly.") + (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:24] alice: He sent to me, sir,Here he comes.") + (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:26] bob: Till I torment thee for this injury.") + (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:07:29] alice: There's an Italian come; and 'tis thought, one of Leonatus' friends.") + (0 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:09:33] bob: Ay, and the particular confirmations, point from point, to the full arming of the verity.") + (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :[09:09:35] alice: Kneel in the streets and beg for grace in vain.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0 ":irc.foonet.org NOTICE tester :[09:06:05] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((mode 10 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620205534") + (0.5 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Nor I no strength to climb without thy help.") + (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: Nothing, but let him have thanks. Demand of him my condition, and what credit I have with the duke.") + (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Show me this piece. I am joyful of your sights.") + (0.2 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: Whilst I can shake my sword or hear the drum.")) + +((part 5 "PART #chan :" quit) + (0 ":tester!~u@247eaxkrufj44.irc PART #chan :" quit)) + +((join 10 "JOIN #chan") + (0 ":tester!~u@247eaxkrufj44.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :@bob alice tester") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list") + (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :tester, welcome!") + (0 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :tester, welcome!")) + +((mode 1 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620205534") + (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Thou desirest me to stop in my tale against the hair.") + (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: And dar'st not stand, nor look me in the face.") + (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: It should not be, by the persuasion of his new feasting.") + (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: It was not given me, nor I did not buy it.") + (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: He that would vouch it in any place but here.") + (0.1 ":alice!~u@yppdd5tt4admc.irc PRIVMSG #chan :bob: In everything I wait upon his will.") + (0.1 ":bob!~u@yppdd5tt4admc.irc PRIVMSG #chan :alice: Thou counterfeit'st most lively.")) + +((linger 8 LINGER)) diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el index 4c57624c33..cbabfcd26b 100644 --- a/test/lisp/erc/resources/erc-scenarios-common.el +++ b/test/lisp/erc/resources/erc-scenarios-common.el @@ -122,6 +122,7 @@ (erc-modules (copy-sequence erc-modules)) (inhibit-interaction t) (auth-source-do-cache nil) + (erc-auth-source-parameters-join-function nil) (erc-autojoin-channels-alist nil) (erc-server-auto-reconnect nil) (erc-d-linger-secs 10) diff --git a/test/lisp/erc/resources/join/auth-source/foonet.eld b/test/lisp/erc/resources/join/auth-source/foonet.eld new file mode 100644 index 0000000000..32b9e3fa0b --- /dev/null +++ b/test/lisp/erc/resources/join/auth-source/foonet.eld @@ -0,0 +1,33 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK dummy")) +((user 1 "USER user 0 * :dummy") + (0.00 ":irc.foonet.org 001 dummy :Welcome to the foonet IRC Network dummy") + (0.01 ":irc.foonet.org 002 dummy :Your host is irc.foonet.org, running version ergo-v2.8.0") + (0.00 ":irc.foonet.org 003 dummy :This server was created Tue, 24 May 2022 05:28:42 UTC") + (0.00 ":irc.foonet.org 004 dummy irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.00 ":irc.foonet.org 005 dummy AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.01 ":irc.foonet.org 005 dummy MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.01 ":irc.foonet.org 005 dummy draft/CHATHISTORY=100 :are supported by this server") + (0.00 ":irc.foonet.org 251 dummy :There are 0 users and 4 invisible on 1 server(s)") + (0.00 ":irc.foonet.org 252 dummy 0 :IRC Operators online") + (0.00 ":irc.foonet.org 253 dummy 0 :unregistered connections") + (0.00 ":irc.foonet.org 254 dummy 2 :channels formed") + (0.00 ":irc.foonet.org 255 dummy :I have 4 clients and 0 servers") + (0.00 ":irc.foonet.org 265 dummy 4 4 :Current local users 4, max 4") + (0.00 ":irc.foonet.org 266 dummy 4 4 :Current global users 4, max 4") + (0.00 ":irc.foonet.org 422 dummy :MOTD File is missing")) + +((mode 6 "MODE dummy +i") + (0.00 ":irc.foonet.org 221 dummy +i") + (0.00 ":irc.foonet.org NOTICE dummy :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0.02 ":irc.foonet.org 221 dummy +i")) + +((join 6.47 "JOIN #spam secret") + (0.03 ":dummy!~u@w9rfqveugz722.irc JOIN #spam")) + +((mode 1 "MODE #spam") + (0.01 ":irc.foonet.org 353 dummy = #spam :~tester dummy") + (0.00 ":irc.foonet.org 366 dummy #spam :End of NAMES list") + (0.01 ":irc.foonet.org 324 dummy #spam +knt secret") + (0.03 ":irc.foonet.org 329 dummy #spam 1653370308")) diff --git a/test/lisp/erc/resources/services/auth-source/libera.eld b/test/lisp/erc/resources/services/auth-source/libera.eld new file mode 100644 index 0000000000..c8dbc9d425 --- /dev/null +++ b/test/lisp/erc/resources/services/auth-source/libera.eld @@ -0,0 +1,49 @@ +;; -*- mode: lisp-data; -*- +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.26 ":zirconium.libera.chat NOTICE * :*** Checking Ident") + (0.01 ":zirconium.libera.chat NOTICE * :*** Looking up your hostname...") + (0.01 ":zirconium.libera.chat NOTICE * :*** No Ident response") + (0.02 ":zirconium.libera.chat NOTICE * :*** Found your hostname: static-198-54-131-100.cust.tzulo.com") + (0.02 ":zirconium.libera.chat 001 tester :Welcome to the Libera.Chat Internet Relay Chat Network tester") + (0.01 ":zirconium.libera.chat 002 tester :Your host is zirconium.libera.chat[46.16.175.175/6697], running version solanum-1.0-dev") + (0.03 ":zirconium.libera.chat 003 tester :This server was created Wed Jun 9 2021 at 01:38:28 UTC") + (0.02 ":zirconium.libera.chat 004 tester zirconium.libera.chat solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI") + (0.00 ":zirconium.libera.chat 005 tester ETRACE WHOX FNC MONITOR=100 SAFELIST ELIST=CTU CALLERID=g KNOCK CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server") + (0.03 ":zirconium.libera.chat 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server") + (0.02 ":zirconium.libera.chat 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server") + (0.02 ":zirconium.libera.chat 251 tester :There are 68 users and 37640 invisible on 25 servers") + (0.00 ":zirconium.libera.chat 252 tester 36 :IRC Operators online") + (0.01 ":zirconium.libera.chat 253 tester 5 :unknown connection(s)") + (0.00 ":zirconium.libera.chat 254 tester 19341 :channels formed") + (0.01 ":zirconium.libera.chat 255 tester :I have 3321 clients and 1 servers") + (0.01 ":zirconium.libera.chat 265 tester 3321 4289 :Current local users 3321, max 4289") + (0.00 ":zirconium.libera.chat 266 tester 37708 38929 :Current global users 37708, max 38929") + (0.01 ":zirconium.libera.chat 250 tester :Highest connection count: 4290 (4289 clients) (38580 connections received)") + (0.21 ":zirconium.libera.chat 375 tester :- zirconium.libera.chat Message of the Day - ") + (0.00 ":zirconium.libera.chat 372 tester :- This server provided by Seeweb ") + (0.01 ":zirconium.libera.chat 372 tester :- Welcome to Libera Chat, the IRC network for") + (0.01 ":zirconium.libera.chat 372 tester :- free & open-source software and peer directed projects.") + (0.00 ":zirconium.libera.chat 372 tester :- ") + (0.00 ":zirconium.libera.chat 372 tester :- Use of Libera Chat is governed by our network policies.") + (0.00 ":zirconium.libera.chat 372 tester :- ") + (0.01 ":zirconium.libera.chat 372 tester :- Please visit us in #libera for questions and support.") + (0.01 ":zirconium.libera.chat 372 tester :- ") + (0.01 ":zirconium.libera.chat 372 tester :- Website and documentation: https://libera.chat") + (0.01 ":zirconium.libera.chat 372 tester :- Webchat: https://web.libera.chat") + (0.01 ":zirconium.libera.chat 372 tester :- Network policies: https://libera.chat/policies") + (0.01 ":zirconium.libera.chat 372 tester :- Email: support@libera.chat") + (0.00 ":zirconium.libera.chat 376 tester :End of /MOTD command.")) + +((mode-user 1.2 "MODE tester +i") + (0.02 ":tester MODE tester :+Zi") + (0.02 ":NickServ!NickServ@services.libera.chat NOTICE tester :This nickname is registered. Please choose a different nickname, or identify via \2/msg NickServ IDENTIFY tester \2")) + +((privmsg 2 "PRIVMSG NickServ :IDENTIFY changeme") + (0.96 ":NickServ!NickServ@services.libera.chat NOTICE tester :You are now identified for \2tester\2.") + (0.25 ":NickServ!NickServ@services.libera.chat NOTICE tester :Last login from: \2~tester@school.edu/tester\2 on Jun 18 01:15:56 2021 +0000.")) + +((quit 5 "QUIT :\2ERC\2") + (0.19 ":tester!~user@static-198-54-131-100.cust.tzulo.com QUIT :Client Quit")) + +((linger 1 LINGER)) commit 959fbcf34b5dd04e1b4bf87c0b73afd784a41f7f Author: F. Jason Park Date: Sun May 30 00:50:50 2021 -0700 Favor network identities in erc-join * lisp/erc/erc-join.el (erc-autojoin-server-match): Favor network identities, falling back on old definition. (erc-autojoin--join): Add new helper containing common code from hookees `erc-autojoin-after-ident' and `erc-autojoin-channels'. (erc-autojoin-after-ident, erc-autojoin-channels): No longer make a point of returning nil because the hooks they're registered on, `erc-nickserv-identified-hook' and `erc-after-connect', don't stop on success. (erc-autojoin--mutate): Add helper for `erc-autojoin-add' and `erc-autojoin-remove'. (erc-autojoin-add, erc-autojoin-remove): Favor given network identities, over networks, when matching keys for `erc-autojoin-channels-alist'. * test/lisp/erc/erc-scenarios-base-reconnect.el: New file. * test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el: New file. * test/lisp/erc/erc-scenarios-join-netid-newcmd.el: New file. * test/lisp/erc/erc-scenarios-join-netid-recon-id.el: New file. * test/lisp/erc/erc-scenarios-join-netid-recon.el: New file. * test/lisp/erc/resources/erc-scenarios-common.el: New file. * test/lisp/erc/resources/join/legacy/foonet.eld: New file. * test/lisp/erc/resources/join/network-id/barnet.eld: New file. * test/lisp/erc/resources/join/network-id/foonet-again.eld: New file. * test/lisp/erc/resources/join/network-id/foonet.eld: New file. * test/lisp/erc/resources/join/reconnect/foonet-again.eld: New file. * test/lisp/erc/resources/join/reconnect/foonet.eld: New file. diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el index 425de4dc56..d4edca236d 100644 --- a/lisp/erc/erc-join.el +++ b/lisp/erc/erc-join.el @@ -33,8 +33,6 @@ ;;; Code: (require 'erc) -(require 'auth-source) -(require 'erc-networks) (defgroup erc-autojoin nil "Enable autojoining." @@ -57,11 +55,16 @@ Every element in the alist has the form (SERVER . CHANNELS). SERVER is a regexp matching the server, and channels is the list of channels to join. SERVER can also be a symbol, in which case -it is matched against the value of `erc-network' instead of +it's matched against a non-nil `:id' passed to `erc' or `erc-tls' +when connecting or the value of the current `erc-network' instead of `erc-server-announced-name' or `erc-session-server' (this can be useful when connecting to an IRC proxy that relays several networks under the same server). +Note that for historical reasons, this option is mutated at runtime, +which is regrettable but here to stay. Please double check the value +before saving it to a `custom-file'. + If the channel(s) require channel keys for joining, the passwords are found via auth-source. For instance, if you use ~/.authinfo as your auth-source backend, then put something like the @@ -123,33 +126,32 @@ This is called from a timer set up by `erc-autojoin-channels'." (erc-autojoin-channels server nick)))) (defun erc-autojoin-server-match (candidate) - "Match the current network or server against CANDIDATE. -This should be a key from `erc-autojoin-channels-alist'." - (or (eq candidate (erc-network)) - (and (stringp candidate) - (string-match-p candidate - (or erc-server-announced-name - erc-session-server))))) + "Match the current network ID or server against CANDIDATE. +CANDIDATE is a key from `erc-autojoin-channels-alist'. Return the +matching entity, either a string or a non-nil symbol (in the case of a +network or a network ID). Return nil on failure." + (if (symbolp candidate) + (eq (or (erc-networks--id-given erc-networks--id) (erc-network)) + candidate) + (when (stringp candidate) + (string-match-p candidate (or erc-server-announced-name + erc-session-server))))) + +(defun erc-autojoin--join () + ;; This is called in the server buffer + (pcase-dolist (`(,name . ,channels) erc-autojoin-channels-alist) + (when-let ((match (erc-autojoin-server-match name))) + (dolist (chan channels) + (let ((buf (erc-get-buffer chan erc-server-process))) + (unless (and buf (with-current-buffer buf + (erc--current-buffer-joined-p))) + (erc-server-join-channel match chan))))))) (defun erc-autojoin-after-ident (_network _nick) "Autojoin channels in `erc-autojoin-channels-alist'. This function is run from `erc-nickserv-identified-hook'." - (if erc--autojoin-timer - (setq erc--autojoin-timer - (cancel-timer erc--autojoin-timer))) (when (eq erc-autojoin-timing 'ident) - (let ((server (or erc-session-server erc-server-announced-name)) - (joined (mapcar (lambda (buf) - (with-current-buffer buf (erc-default-target))) - (erc-channel-list erc-server-process)))) - ;; We may already be in these channels, e.g. because the - ;; autojoin timer went off. - (dolist (l erc-autojoin-channels-alist) - (when (erc-autojoin-server-match (car l)) - (dolist (chan (cdr l)) - (unless (erc-member-ignore-case chan joined) - (erc-server-join-channel server chan))))))) - nil) + (erc-autojoin--join))) (defun erc-autojoin-channels (server nick) "Autojoin channels in `erc-autojoin-channels-alist'." @@ -162,24 +164,7 @@ This function is run from `erc-nickserv-identified-hook'." #'erc-autojoin-channels-delayed server nick (current-buffer)))) ;; `erc-autojoin-timing' is `connect': - (let ((server (or erc-session-server erc-server-announced-name))) - (dolist (l erc-autojoin-channels-alist) - (when (erc-autojoin-server-match (car l)) - (dolist (chan (cdr l)) - (let ((buffer - (car (erc-buffer-filter - (lambda () - (let ((current (erc-default-target))) - (and (stringp current) - (erc-autojoin-server-match (car l)) - (string-equal (erc-downcase chan) - (erc-downcase current))))))))) - (when (or (not buffer) - (not (with-current-buffer buffer - (erc--current-buffer-joined-p)))) - (erc-server-join-channel server chan)))))))) - ;; Return nil to avoid stomping on any other hook funcs. - nil) + (erc-autojoin--join))) (defun erc-autojoin-current-server () "Compute the current server for lookup in `erc-autojoin-channels-alist'. @@ -190,24 +175,29 @@ Respects `erc-autojoin-domain-only'." (match-string 1 server) server))) +(defun erc-autojoin--mutate (proc parsed remove) + (when-let* ((nick (car (erc-parse-user (erc-response.sender parsed)))) + ((erc-current-nick-p nick)) + (chnl (car (erc-response.command-args parsed))) + (elem (or (and (erc--valid-local-channel-p chnl) + (regexp-quote erc-server-announced-name)) + (erc-networks--id-given erc-networks--id) + (erc-network) + (with-current-buffer (process-buffer proc) + (erc-autojoin-current-server)))) + (test (if (symbolp elem) #'eq #'equal))) + (if remove + (let ((cs (delete chnl (assoc-default elem erc-autojoin-channels-alist + test)))) + (setf (alist-get elem erc-autojoin-channels-alist nil (null cs) test) + cs)) + (cl-pushnew chnl + (alist-get elem erc-autojoin-channels-alist nil nil test) + :test #'equal)))) + (defun erc-autojoin-add (proc parsed) "Add the channel being joined to `erc-autojoin-channels-alist'." - (let* ((chnl (erc-response.contents parsed)) - (nick (car (erc-parse-user (erc-response.sender parsed)))) - (server (with-current-buffer (process-buffer proc) - (erc-autojoin-current-server)))) - (when (erc-current-nick-p nick) - (let ((elem (or (assoc (erc-network) erc-autojoin-channels-alist) - (assoc server erc-autojoin-channels-alist)))) - (if elem - (unless (member chnl (cdr elem)) - (setcdr elem (cons chnl (cdr elem)))) - ;; This always keys on server, not network -- user can - ;; override by simply adding a network to - ;; `erc-autojoin-channels-alist' - (setq erc-autojoin-channels-alist - (cons (list server chnl) - erc-autojoin-channels-alist)))))) + (erc-autojoin--mutate proc parsed nil) ;; We must return nil to tell ERC to continue running the other ;; functions. nil) @@ -216,18 +206,7 @@ Respects `erc-autojoin-domain-only'." (defun erc-autojoin-remove (proc parsed) "Remove the channel being left from `erc-autojoin-channels-alist'." - (let* ((chnl (car (erc-response.command-args parsed))) - (nick (car (erc-parse-user (erc-response.sender parsed)))) - (server (with-current-buffer (process-buffer proc) - (erc-autojoin-current-server)))) - (when (erc-current-nick-p nick) - (let ((elem (or (assoc (erc-network) erc-autojoin-channels-alist) - (assoc server erc-autojoin-channels-alist)))) - (when elem - (setcdr elem (delete chnl (cdr elem))) - (unless (cdr elem) - (setq erc-autojoin-channels-alist - (delete elem erc-autojoin-channels-alist))))))) + (erc-autojoin--mutate proc parsed 'remove) ;; We must return nil to tell ERC to continue running the other ;; functions. nil) diff --git a/test/lisp/erc/erc-join-tests.el b/test/lisp/erc/erc-join-tests.el new file mode 100644 index 0000000000..8210defbfb --- /dev/null +++ b/test/lisp/erc/erc-join-tests.el @@ -0,0 +1,361 @@ +;;; erc-join-tests.el --- Tests for erc-join. -*- lexical-binding:t -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published +;; by the Free Software Foundation, either version 3 of the License, +;; or (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + +(require 'ert-x) +(require 'erc-join) +(require 'erc-networks) + +(ert-deftest erc-autojoin-channels--connect () + (should (eq erc-autojoin-timing 'connect)) + (should (= erc-autojoin-delay 30)) + (should-not erc--autojoin-timer) + + (let (calls + common + erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook) + + (cl-letf (((symbol-function 'erc-server-send) + (lambda (line) (push line calls)))) + + (setq common + (lambda () + (ert-with-test-buffer (:name "foonet") + (erc-mode) + (setq erc-server-process + (start-process "true" (current-buffer) "true") + erc-network 'FooNet + erc-session-server "irc.gnu.chat" + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-announced-name "foo.gnu.chat") + (set-process-query-on-exit-flag erc-server-process nil) + (erc-autojoin-channels erc-server-announced-name + "tester") + (should-not erc--autojoin-timer)))) + + (ert-info ("Join immediately on connect; server") + (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan")))) + (funcall common)) + (should (equal (pop calls) "JOIN #chan"))) + + (ert-info ("Join immediately on connect; network") + (let ((erc-autojoin-channels-alist '((FooNet "#chan")))) + (funcall common)) + (should (equal (pop calls) "JOIN #chan"))) + + (ert-info ("Do nothing; server") + (let ((erc-autojoin-channels-alist '(("bar\\.gnu\\.chat" "#chan")))) + (funcall common)) + (should-not calls)) + + (ert-info ("Do nothing; network") + (let ((erc-autojoin-channels-alist '((BarNet "#chan")))) + (funcall common)) + (should-not calls))))) + +(ert-deftest erc-autojoin-channels--delay () + (should (eq erc-autojoin-timing 'connect)) + (should (= erc-autojoin-delay 30)) + (should-not erc--autojoin-timer) + + (let (calls + common + erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook + (erc-autojoin-timing 'ident) + (erc-autojoin-delay 0.05)) + + (cl-letf (((symbol-function 'erc-server-send) + (lambda (line) (push line calls))) + ((symbol-function 'erc-autojoin-after-ident) + (lambda (&rest _r) (error "I ran but shouldn't have")))) + + (setq common + (lambda () + (ert-with-test-buffer (:name "foonet") + (erc-mode) + (setq erc-server-process + (start-process "true" (current-buffer) "true") + erc-network 'FooNet + erc-session-server "irc.gnu.chat" + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-announced-name "foo.gnu.chat") + (set-process-query-on-exit-flag erc-server-process nil) + (should-not erc--autojoin-timer) + (erc-autojoin-channels erc-server-announced-name "tester") + (should erc--autojoin-timer) + (should-not calls) + (sleep-for 0.1)))) + + (ert-info ("Deferred on connect; server") + (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan")))) + (funcall common)) + (should (equal (pop calls) "JOIN #chan"))) + + (ert-info ("Deferred on connect; network") + (let ((erc-autojoin-channels-alist '((FooNet "#chan")))) + (funcall common)) + (should (equal (pop calls) "JOIN #chan"))) + + (ert-info ("Do nothing; server") + (let ((erc-autojoin-channels-alist '(("bar\\.gnu\\.chat" "#chan")))) + (funcall common)) + (should-not calls))))) + +(ert-deftest erc-autojoin-channels--ident () + (should (eq erc-autojoin-timing 'connect)) + (should (= erc-autojoin-delay 30)) + (should-not erc--autojoin-timer) + + (let (calls + common + erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook + (erc-autojoin-timing 'ident)) + + (cl-letf (((symbol-function 'erc-server-send) + (lambda (line) (push line calls)))) + + (setq common + (lambda () + (ert-with-test-buffer (:name "foonet") + (erc-mode) + (setq erc-server-process + (start-process "true" (current-buffer) "true") + erc-network 'FooNet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-announced-name "foo.gnu.chat") + (set-process-query-on-exit-flag erc-server-process nil) + (erc-autojoin-after-ident 'FooNet "tester") + (should-not erc--autojoin-timer)))) + + (ert-info ("Join on NickServ hook; server") + (let ((erc-autojoin-channels-alist '(("\\.gnu\\.chat\\'" "#chan")))) + (funcall common)) + (should (equal (pop calls) "JOIN #chan"))) + + (ert-info ("Join on NickServ hook; network") + (let ((erc-autojoin-channels-alist '((FooNet "#chan")))) + (funcall common)) + (should (equal (pop calls) "JOIN #chan")))))) + +(defun erc-join-tests--autojoin-add--common (setup &optional fwd) + (let (calls + erc-autojoin-channels-alist + erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook) + + (cl-letf (((symbol-function 'erc-handle-parsed-server-response) + (lambda (_p m) (push m calls)))) + + (ert-with-test-buffer (:name "foonet") + (erc-mode) + (setq erc-server-process + (start-process "true" (current-buffer) "true") + erc-server-current-nick "tester" + erc--isupport-params (make-hash-table) + erc-server-announced-name "foo.gnu.chat") + (puthash 'CHANTYPES '("&#") erc--isupport-params) + (funcall setup) + (set-process-query-on-exit-flag erc-server-process nil) + (should-not calls) + + (ert-info ("Add #chan") + (erc-parse-server-response erc-server-process + (concat ":tester!~i@c.u JOIN #chan" + (and fwd " * :Tes Ter"))) + (should calls) + (erc-autojoin-add erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist '((FooNet "#chan"))))) + + (ert-info ("More recently joined chans are prepended") + (erc-parse-server-response + erc-server-process ; with account username + (concat ":tester!~i@c.u JOIN #spam" (and fwd " tester :Tes Ter"))) + (should calls) + (erc-autojoin-add erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '((FooNet "#spam" "#chan"))))) + + (ert-info ("Duplicates skipped") + (erc-parse-server-response erc-server-process + (concat ":tester!~i@c.u JOIN #chan" + (and fwd " * :Tes Ter"))) + (should calls) + (erc-autojoin-add erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '((FooNet "#spam" "#chan"))))) + + (ert-info ("Server used for local channel") + (erc-parse-server-response erc-server-process + (concat ":tester!~i@c.u JOIN &local" + (and fwd " * :Tes Ter"))) + (should calls) + (erc-autojoin-add erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '(("foo\\.gnu\\.chat" "&local") + (FooNet "#spam" "#chan"))))))))) + +(ert-deftest erc-autojoin-add--network () + (erc-join-tests--autojoin-add--common + (lambda () (setq erc-network 'FooNet + erc-networks--id (erc-networks--id-create nil))))) + +(ert-deftest erc-autojoin-add--network-extended-syntax () + (erc-join-tests--autojoin-add--common + (lambda () (setq erc-network 'FooNet + erc-networks--id (erc-networks--id-create nil))) + 'forward-compatible)) + +(ert-deftest erc-autojoin-add--network-id () + (erc-join-tests--autojoin-add--common + (lambda () (setq erc-network 'invalid + erc-networks--id (erc-networks--id-create 'FooNet))))) + +(ert-deftest erc-autojoin-add--server () + (let (calls + erc-autojoin-channels-alist + erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook) + + (cl-letf (((symbol-function 'erc-handle-parsed-server-response) + (lambda (_p m) (push m calls)))) + + (ert-info ("Network unavailable, announced name used") + (setq erc-autojoin-channels-alist nil) + (ert-with-test-buffer (:name "foonet") + (erc-mode) + (setq erc-server-process + (start-process "true" (current-buffer) "true") + erc-server-current-nick "tester" + erc-server-announced-name "foo.gnu.chat" + erc-networks--id (make-erc-networks--id)) ; assume too early + (set-process-query-on-exit-flag erc-server-process nil) + (should-not calls) + (erc-parse-server-response erc-server-process + ":tester!~u@q6ddatxcq6txy.irc JOIN #chan") + (should calls) + (erc-autojoin-add erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '(("gnu.chat" "#chan"))))))))) + +(defun erc-join-tests--autojoin-remove--common (setup) + (let (calls + erc-autojoin-channels-alist + erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook) + + (cl-letf (((symbol-function 'erc-handle-parsed-server-response) + (lambda (_p m) (push m calls)))) + + (setq erc-autojoin-channels-alist ; mutated, so can't quote whole thing + (list '(FooNet "#spam" "##chan") + '(BarNet "#bar" "##bar") + '("foo\\.gnu\\.chat" "&local"))) + + (ert-with-test-buffer (:name "foonet") + (erc-mode) + (setq erc-server-process + (start-process "true" (current-buffer) "true") + erc-server-current-nick "tester" + erc--isupport-params (make-hash-table) + erc-server-announced-name "foo.gnu.chat") + (puthash 'CHANTYPES '("&#") erc--isupport-params) + (funcall setup) + (set-process-query-on-exit-flag erc-server-process nil) + (should-not calls) + + (ert-info ("Remove #chan") + (erc-parse-server-response erc-server-process + ":tester!~i@c.u PART ##chan") + (should calls) + (erc-autojoin-remove erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '((FooNet "#spam") + (BarNet "#bar" "##bar") + ("foo\\.gnu\\.chat" "&local"))))) + + (ert-info ("Wrong network, nothing done") + (erc-parse-server-response erc-server-process + ":tester!~i@c.u PART #bar") + (should calls) + (erc-autojoin-remove erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '((FooNet "#spam") + (BarNet "#bar" "##bar") + ("foo\\.gnu\\.chat" "&local"))))) + + (ert-info ("Local channel keyed by server found") + (erc-parse-server-response erc-server-process + ":tester!~i@c.u PART &local") + (should calls) + (erc-autojoin-remove erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '((FooNet "#spam") (BarNet "#bar" "##bar"))))))))) + +(ert-deftest erc-autojoin-remove--network () + (erc-join-tests--autojoin-remove--common + (lambda () (setq erc-network 'FooNet + erc-networks--id (erc-networks--id-create nil))))) + +(ert-deftest erc-autojoin-remove--network-id () + (erc-join-tests--autojoin-remove--common + (lambda () (setq erc-network 'fake-a-roo + erc-networks--id (erc-networks--id-create 'FooNet))))) + +(ert-deftest erc-autojoin-remove--server () + (let (calls + erc-autojoin-channels-alist + erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook) + + (cl-letf (((symbol-function 'erc-handle-parsed-server-response) + (lambda (_p m) (push m calls)))) + + (setq erc-autojoin-channels-alist (list '("gnu.chat" "#spam" "##chan") + '("fsf.chat" "#bar" "##bar"))) + + (ert-with-test-buffer (:name "foonet") + (erc-mode) + (setq erc-server-process + (start-process "true" (current-buffer) "true") + erc-server-current-nick "tester" + erc-server-announced-name "foo.gnu.chat" + ;; Assume special case w/o known network + erc-networks--id (make-erc-networks--id)) + (set-process-query-on-exit-flag erc-server-process nil) + (should-not calls) + + (ert-info ("Announced name matched, #chan removed") + (erc-parse-server-response erc-server-process + ":tester!~i@c.u PART ##chan") + (should calls) + (erc-autojoin-remove erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '(("gnu.chat" "#spam") + ("fsf.chat" "#bar" "##bar"))))) + + (ert-info ("Wrong announced name, nothing done") + (erc-parse-server-response erc-server-process + ":tester!~i@c.u PART #bar") + (should calls) + (erc-autojoin-remove erc-server-process (pop calls)) + (should (equal erc-autojoin-channels-alist + '(("gnu.chat" "#spam") + ("fsf.chat" "#bar" "##bar"))))))))) + +;;; erc-join-tests.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-reconnect.el b/test/lisp/erc/erc-scenarios-base-reconnect.el index aeb59e1870..30d692058d 100644 --- a/test/lisp/erc/erc-scenarios-base-reconnect.el +++ b/test/lisp/erc/erc-scenarios-base-reconnect.el @@ -95,7 +95,7 @@ (with-current-buffer erc-server-buffer (funcall expect 10 "Connection failed! Re-establishing"))) - (should (equal erc-autojoin-channels-alist '(("foonet.org" "#chan")))) + (should (equal erc-autojoin-channels-alist '((FooNet "#chan")))) (funcall test) diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el new file mode 100644 index 0000000000..e2e437321d --- /dev/null +++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd-id.el @@ -0,0 +1,50 @@ +;;; erc-scenarios-join-netid-newcmd-id.el --- join netid newcmd scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-join-netid--newcmd-id () + :tags '(:expensive-test) + (let ((connect (lambda () + (erc :server "127.0.0.1" + :port (with-current-buffer "oofnet" + (process-contact erc-server-process :service)) + :nick "tester" + :password "foonet:changeme" + :full-name "tester" + :id 'oofnet)))) + (erc-scenarios-common--join-network-id connect 'oofnet nil))) + +(ert-deftest erc-scenarios-join-netid--newcmd-ids () + :tags '(:expensive-test) + (let ((connect (lambda () + (erc :server "127.0.0.1" + :port (with-current-buffer "oofnet" + (process-contact erc-server-process :service)) + :nick "tester" + :password "foonet:changeme" + :full-name "tester" + :id 'oofnet)))) + (erc-scenarios-common--join-network-id connect 'oofnet 'rabnet))) + +;;; erc-scenarios-join-netid-newcmd-id.el ends here diff --git a/test/lisp/erc/erc-scenarios-join-netid-newcmd.el b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el new file mode 100644 index 0000000000..1a541a46b3 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-join-netid-newcmd.el @@ -0,0 +1,37 @@ +;;; erc-scenarios-join-netid-newcmd.el --- join netid newcmd scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-join-netid--newcmd () + :tags '(:expensive-test) + (let ((connect (lambda () + (erc :server "127.0.0.1" + :port (with-current-buffer "foonet" + (process-contact erc-server-process :service)) + :nick "tester" + :password "foonet:changeme" + :full-name "tester")))) + (erc-scenarios-common--join-network-id connect nil nil))) + +;;; erc-scenarios-join-netid-newcmd.el ends here diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon-id.el b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el new file mode 100644 index 0000000000..92bdd643de --- /dev/null +++ b/test/lisp/erc/erc-scenarios-join-netid-recon-id.el @@ -0,0 +1,46 @@ +;;; erc-scenarios-join-netid-recon-id.el --- join-netid-recon scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-join-netid--recon-id () + :tags '(:expensive-test) + (let ((connect (lambda () + (with-current-buffer "oofnet" + (erc-cmd-RECONNECT) + (should (eq (current-buffer) + (process-buffer erc-server-process))) + (current-buffer))))) + (erc-scenarios-common--join-network-id connect 'oofnet nil))) + +(ert-deftest erc-scenarios-join-netid--recon-ids () + :tags '(:expensive-test) + (let ((connect (lambda () + (with-current-buffer "oofnet" + (erc-cmd-RECONNECT) + (should (eq (current-buffer) + (process-buffer erc-server-process))) + (current-buffer))))) + (erc-scenarios-common--join-network-id connect 'oofnet 'rabnet))) + +;;; erc-scenarios-join-netid-recon-id.el ends here diff --git a/test/lisp/erc/erc-scenarios-join-netid-recon.el b/test/lisp/erc/erc-scenarios-join-netid-recon.el new file mode 100644 index 0000000000..cbdba07e25 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-join-netid-recon.el @@ -0,0 +1,36 @@ +;;; erc-scenarios-join-netid-recon.el --- join-netid-recon scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-join-netid--recon () + :tags '(:expensive-test) + (let ((connect (lambda () + (with-current-buffer "foonet" + (erc-cmd-RECONNECT) + (should (eq (current-buffer) + (process-buffer erc-server-process))) + (current-buffer))))) + (erc-scenarios-common--join-network-id connect nil nil))) + +;;; erc-scenarios-join-netid-recon.el ends here diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el index 6b380772fe..4c57624c33 100644 --- a/test/lisp/erc/resources/erc-scenarios-common.el +++ b/test/lisp/erc/resources/erc-scenarios-common.el @@ -402,6 +402,114 @@ buffer-naming collisions involving bouncers in ERC." (funcall test))) +;; XXX this is okay, but we also need to check that target buffers are +;; already associated with a new process *before* a JOIN is sent by a +;; server's playback burst. This doesn't do that. +;; +;; This *does* check that superfluous JOINs sent by the autojoin +;; module are harmless when they're not acked (superfluous because the +;; bouncer/server intitates the JOIN). + +(defun erc-scenarios-common--join-network-id (foo-reconnector foo-id bar-id) + "Ensure channels rejoined by erc-join.el DTRT. +Originally from scenario clash-of-chans/autojoin as described in +Bug#48598: 28.0.50; buffer-naming collisions involving bouncers in ERC." + (erc-scenarios-common-with-cleanup + ((chan-buf-foo (format "#chan@%s" (or foo-id "foonet"))) + (chan-buf-bar (format "#chan@%s" (or bar-id "barnet"))) + (erc-scenarios-common-dialog "join/network-id") + (erc-d-t-cleanup-sleep-secs 1) + (erc-server-flood-penalty 0.5) + (dumb-server (erc-d-run "localhost" t 'foonet 'barnet 'foonet-again)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + erc-server-buffer-foo erc-server-process-foo + erc-server-buffer-bar erc-server-process-bar) + + (should (memq 'autojoin erc-modules)) + + (ert-info ("Connect to foonet") + (with-current-buffer + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester" + :id foo-id)) + (setq erc-server-process-foo erc-server-process) + (erc-scenarios-common-assert-initial-buf-name foo-id port) + (erc-d-t-wait-for 5 (eq (erc-network) 'foonet)) + (funcall expect 5 "foonet"))) + + (ert-info ("Join #chan, find sentinel, quit") + (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan")) + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan")) + (funcall expect 5 "vile thing") + (erc-cmd-QUIT ""))) + + (erc-d-t-wait-for 2 "Foonet connection deceased" + (not (erc-server-process-alive erc-server-buffer-foo))) + + (should (equal erc-autojoin-channels-alist + (if foo-id '((oofnet "#chan")) '((foonet "#chan"))))) + + (ert-info ("Connect to barnet") + (with-current-buffer + (setq erc-server-buffer-bar (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "barnet:changeme" + :full-name "tester" + :id bar-id)) + (setq erc-server-process-bar erc-server-process) + (erc-d-t-wait-for 5 (eq erc-network 'barnet)) + (should (string= (buffer-name) (if bar-id "rabnet" "barnet"))))) + + (ert-info ("Server buffers are unique, no stray IP-based names") + (should-not (eq erc-server-buffer-foo erc-server-buffer-bar)) + (should-not (erc-scenarios-common-buflist "127.0.0.1"))) + + (ert-info ("Only one #chan buffer exists") + (should (equal (list (get-buffer "#chan")) + (erc-scenarios-common-buflist "#chan")))) + + (ert-info ("#chan is not auto-joined") + (with-current-buffer "#chan" + (erc-d-t-absent-for 0.1 "") + (should-not (process-live-p erc-server-process)) + (erc-d-t-ensure-for 0.1 "server buffer remains foonet" + (eq erc-server-process erc-server-process-foo)))) + + (with-current-buffer erc-server-buffer-bar + (erc-cmd-JOIN "#chan") + (erc-d-t-wait-for 3 (get-buffer chan-buf-foo)) + (erc-d-t-wait-for 3 (get-buffer chan-buf-bar)) + (with-current-buffer chan-buf-bar + (erc-d-t-wait-for 3 (eq erc-server-process erc-server-process-bar)) + (funcall expect 5 "marry her instantly"))) + + (ert-info ("Reconnect to foonet") + (with-current-buffer (setq erc-server-buffer-foo + (funcall foo-reconnector)) + (should (member (if foo-id '(oofnet "#chan") '(foonet "#chan")) + erc-autojoin-channels-alist)) + (erc-d-t-wait-for 3 (erc-server-process-alive)) + (setq erc-server-process-foo erc-server-process) + (erc-d-t-wait-for 2 (eq erc-network 'foonet)) + (should (string= (buffer-name) (if foo-id "oofnet" "foonet"))) + (funcall expect 5 "foonet"))) + + (ert-info ("#chan@foonet is clean, no cross-contamination") + (with-current-buffer chan-buf-foo + (erc-d-t-wait-for 3 (eq erc-server-process erc-server-process-foo)) + (funcall expect 3 "") + (erc-d-t-absent-for 0.1 "") + (funcall expect 10 "not given me"))) + + (ert-info ("All #chan@barnet output received") + (with-current-buffer chan-buf-bar + (funcall expect 10 "hath an uncle here"))))) + (provide 'erc-scenarios-common) ;;; erc-scenarios-common.el ends here diff --git a/test/lisp/erc/resources/join/legacy/foonet.eld b/test/lisp/erc/resources/join/legacy/foonet.eld new file mode 100644 index 0000000000..344ba7c1da --- /dev/null +++ b/test/lisp/erc/resources/join/legacy/foonet.eld @@ -0,0 +1,38 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 6 "JOIN #chan") + (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((mode 5 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow.")) diff --git a/test/lisp/erc/resources/join/network-id/barnet.eld b/test/lisp/erc/resources/join/network-id/barnet.eld new file mode 100644 index 0000000000..e33dd6be29 --- /dev/null +++ b/test/lisp/erc/resources/join/network-id/barnet.eld @@ -0,0 +1,43 @@ +;; -*- mode: lisp-data; -*- +((pass 2 "PASS :barnet:changeme")) +((nick 2 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 12 "MODE tester +i")) +;; No mode answer + +((join 2 "JOIN #chan") + (0 ":tester!~u@6yximxrnkg65a.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester") + (0 ":irc.barnet.org 366 tester #chan :End of NAMES list") + (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :tester, welcome!") + (0 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :tester, welcome!")) + +((mode 1 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1620608304") + ;; Wait for foonet's buffer playback + (0.1 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: Go take her hence, and marry her instantly.") + (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Of all the four, or the three, or the two, or one of the four.") + (0.1 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: And gives the crutch the cradle's infancy.") + (0.1 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Such is the simplicity of man to hearken after the flesh.") + (0.05 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: The leaf to read them. Let us toward the king.") + (0.05 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: Many can brook the weather that love not the wind.") + (0.05 ":mike!~u@6yximxrnkg65a.irc PRIVMSG #chan :joe: And now, dear maid, be you as free to us.") + (0.00 ":joe!~u@6yximxrnkg65a.irc PRIVMSG #chan :mike: He hath an uncle here in Messina will be very much glad of it.")) + +((linger 3.5 LINGER)) diff --git a/test/lisp/erc/resources/join/network-id/foonet-again.eld b/test/lisp/erc/resources/join/network-id/foonet-again.eld new file mode 100644 index 0000000000..b230eff27c --- /dev/null +++ b/test/lisp/erc/resources/join/network-id/foonet-again.eld @@ -0,0 +1,46 @@ +;; -*- mode: lisp-data; -*- +((pass-redux 10 "PASS :foonet:changeme")) +((nick-redux 1 "NICK tester")) + +((user-redux 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer ^ + + ;; History + (0 ":tester!~u@q6ddatxcq6txy.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester") + (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:23] alice: And soar with them above a common bound.") + (0 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:27] bob: And be aveng'd on cursed Tamora.") + (0 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :[02:43:29] alice: He did love her, sir, as a gentleman loves a woman.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")) + +;; As a server, we ignore useless join sent by autojoin module +((~join 10 "JOIN #chan")) + +((mode-redux 10 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620608304") + (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: Ay, madam, with the swiftest wing of speed.") + (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: Five times in that ere once in our five wits.") + (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: And bid him come to take his last farewell.") + (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: But we are spirits of another sort.") + (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: It was not given me, nor I did not buy it.")) + +((linger 6 LINGER)) diff --git a/test/lisp/erc/resources/join/network-id/foonet.eld b/test/lisp/erc/resources/join/network-id/foonet.eld new file mode 100644 index 0000000000..7d63f5f0c6 --- /dev/null +++ b/test/lisp/erc/resources/join/network-id/foonet.eld @@ -0,0 +1,39 @@ +;; -*- mode: lisp-data; -*- +((pass 10 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) + +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Mon, 10 May 2021 00:58:22 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i")) +;; No mode answer ^ + +((join 3 "JOIN #chan") + (0 ":tester!~u@q6ddatxcq6txy.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list") + (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :tester, welcome!") + (0 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :tester, welcome!")) + +((mode 3 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620608304") + (0.1 ":bob!~u@q6ddatxcq6txy.irc PRIVMSG #chan :alice: Pray you, sir, deliver me this paper.") + (0.1 ":alice!~u@q6ddatxcq6txy.irc PRIVMSG #chan :bob: Wake when some vile thing is near.")) + +((quit 3 "QUIT :\2ERC\2")) + +((drop 0 DROP)) diff --git a/test/lisp/erc/resources/join/reconnect/foonet-again.eld b/test/lisp/erc/resources/join/reconnect/foonet-again.eld new file mode 100644 index 0000000000..f1fcc439cc --- /dev/null +++ b/test/lisp/erc/resources/join/reconnect/foonet-again.eld @@ -0,0 +1,45 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is still in debug mode.")) + +((~join-chan 12 "JOIN #chan") + (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((~join-spam 12 "JOIN #spam") + (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam") + (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob") + (0 ":irc.foonet.org 366 tester #spam :End of NAMES list")) + +((~mode-chan 4 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")) + +((mode-spam 4 "MODE #spam") + (0 ":irc.foonet.org 324 tester #spam +nt") + (0 ":irc.foonet.org 329 tester #spam 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :alice: Signior Iachimo will not from it. Pray, let us follow 'em.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :bob: Our queen and all her elves come here anon.")) diff --git a/test/lisp/erc/resources/join/reconnect/foonet.eld b/test/lisp/erc/resources/join/reconnect/foonet.eld new file mode 100644 index 0000000000..efb269f5ae --- /dev/null +++ b/test/lisp/erc/resources/join/reconnect/foonet.eld @@ -0,0 +1,45 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode.") + + (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list") + + (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam") + (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob") + (0 ":irc.foonet.org 366 tester #spam :End of NAMES list")) + +((mode-chan 4 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")) + +((mode-spam 4 "MODE #spam") + (0 ":irc.foonet.org 324 tester #spam +nt") + (0 ":irc.foonet.org 329 tester #spam 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :tester, welcome!") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :tester, welcome!")) + +((drop 0 DROP)) commit 1767b0bd7e2883c9467ebf0e0aedee1fd90bcf92 Author: F. Jason Park Date: Fri May 7 01:52:41 2021 -0700 Don't call erc-auto-query twice on PRIVMSG * lisp/erc/erc-backend.el (erc-server-JOIN): Use `erc--open-target' instead of `erc-join'. (erc-server-PRIVMSG): Don't call `erc-auto-query' at all, and instead borrow the portion of its logic that detects when a query buffer should be created instead of a channel buffer. * lisp/erc/erc.el (erc-cmd-QUERY): Update the mode line explicitly after calling `erc-query' in case it's needed after `erc-setup-buffer' runs. Simplify. (erc-query, erc--open-target): Replace uses of `erc-query' with `erc--open-target' and make the former obsolete. Don't call `erc-update-mode-line' because `erc-open' already does that. (erc-auto-query): Make this function obsolete. It was previously only used in erc-backend.el and only sewed confusion. (erc-query-on-unjoined-chan-privmsg): Add note questioning its role. It was previously only used by the now deprecated `erc-auto-query'. * test/lisp/erc/erc-scenarios-misc.el (erc-scenarios-base-mask-target-routing): Add test for server masks. * test/lisp/erc/resources/base/mask-target-routing/foonet.eld: New file. diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 6fb581ca7c..bee2551d76 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -1334,16 +1334,7 @@ add things to `%s' instead." (let* ((str (cond ;; If I have joined a channel ((erc-current-nick-p nick) - (setq buffer (erc-open erc-session-server erc-session-port - nick erc-session-user-full-name - nil nil - (list chnl) chnl - erc-server-process - nil - erc-session-username - (erc-networks--id-given - erc-networks--id))) - (when buffer + (when (setq buffer (erc--open-target chnl)) (set-buffer buffer) (with-suppressed-warnings ((obsolete erc-add-default-channel)) @@ -1534,6 +1525,13 @@ add things to `%s' instead." fnick) (setf (erc-response.contents parsed) msg) (setq buffer (erc-get-buffer (if privp nick tgt) proc)) + ;; Even worth checking for empty target here? (invalid anyway) + (unless (or buffer noticep (string-empty-p tgt) (eq ?$ (aref tgt 0))) + (if (and privp msgp (not (erc-is-message-ctcp-and-not-action-p msg))) + (when erc-auto-query + (let ((erc-join-buffer erc-auto-query)) + (setq buffer (erc--open-target nick)))) + (setq buffer (erc--open-target tgt)))) (when buffer (with-current-buffer buffer (when privp (erc--unhide-prompt)) @@ -1569,13 +1567,7 @@ add things to `%s' instead." s parsed buffer nick) (run-hook-with-args-until-success 'erc-echo-notice-hook s parsed buffer nick)) - (erc-display-message parsed nil buffer s))) - (when (string= cmd "PRIVMSG") - (erc-auto-query proc parsed)))))) - -;; FIXME: need clean way of specifying extra hooks in -;; define-erc-response-handler. -(add-hook 'erc-server-PRIVMSG-functions #'erc-auto-query) + (erc-display-message parsed nil buffer s))))))) (define-erc-response-handler (QUIT) "Another user has quit IRC." nil diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index cbb0c9f4b4..4b24f953dd 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -3791,13 +3791,14 @@ on the value of `erc-query-display'." ;; `kill-buffer'? If it makes sense, re-add it. -- SK @ 2021-11-11 (interactive (list (read-string "Start a query with: "))) - (let ((session-buffer (erc-server-buffer)) - (erc-join-buffer erc-query-display)) - (if user - (erc-query user session-buffer) + (unless user ;; currently broken, evil hack to display help anyway ;(erc-delete-query)))) - (signal 'wrong-number-of-arguments "")))) + (signal 'wrong-number-of-arguments "")) + (let ((erc-join-buffer erc-query-display)) + (erc-with-server-buffer + (erc--open-target user)))) + (defalias 'erc-cmd-Q #'erc-cmd-QUERY) (defun erc-quit/part-reason-default () @@ -4473,28 +4474,30 @@ See `erc-default-server-hook'." (nconc erc-server-vectors (list parsed)) nil) -(defun erc-query (target server) - "Open a query buffer on TARGET, using SERVER. +(defun erc--open-target (target) + "Open an ERC buffer on TARGET." + (erc-open erc-session-server + erc-session-port + (erc-current-nick) + erc-session-user-full-name + nil + nil + (list target) + target + erc-server-process + nil + erc-session-username + (erc-networks--id-given erc-networks--id))) + +(defun erc-query (target server-buffer) + "Open a query buffer on TARGET using SERVER-BUFFER. To change how this query window is displayed, use `let' to bind `erc-join-buffer' before calling this." - (unless (and server - (buffer-live-p server) - (set-buffer server)) + (declare (obsolete "bind `erc-cmd-query' and call `erc-cmd-QUERY'" "29.1")) + (unless (buffer-live-p server-buffer) (error "Couldn't switch to server buffer")) - (let ((buf (erc-open erc-session-server - erc-session-port - (erc-current-nick) - erc-session-user-full-name - nil - nil - (list target) - target - erc-server-process - erc-session-username))) - (unless buf - (error "Couldn't open query window")) - (erc-update-mode-line) - buf)) + (with-current-buffer server-buffer + (erc--open-target target))) (defcustom erc-auto-query 'window-noselect "If non-nil, create a query buffer each time you receive a private message. @@ -4513,6 +4516,9 @@ a new window, but not to select it. See the documentation for (const :tag "Use current buffer" buffer) (const :tag "Use current buffer" t))) +;; FIXME either retire this or put it to use or more clearly explain +;; what it's supposed to do. It's currently only used by the obsolete +;; function `erc-auto-query'. (defcustom erc-query-on-unjoined-chan-privmsg t "If non-nil create query buffer on receiving any PRIVMSG at all. This includes PRIVMSGs directed to channels. If you are using an IRC @@ -4635,6 +4641,8 @@ and as second argument the event parsed as a vector." (erc-cmd-QUERY query)) nil)))) +(make-obsolete 'erc-auto-query "try erc-cmd-QUERY instead" "29.1") + (defun erc-is-message-ctcp-p (message) "Check if MESSAGE is a CTCP message or not." (string-match "^\C-a\\([^\C-a]*\\)\C-a?$" message)) diff --git a/test/lisp/erc/erc-scenarios-misc.el b/test/lisp/erc/erc-scenarios-misc.el index 86cfa8b10b..9d6d5bc1d6 100644 --- a/test/lisp/erc/erc-scenarios-misc.el +++ b/test/lisp/erc/erc-scenarios-misc.el @@ -104,4 +104,38 @@ (should-not erc-network) (should (string= erc-server-announced-name "irc.foonet.org")))))) +;; Targets that are host/server masks like $*, $$*, and #* are routed +;; to the server buffer: https://github.com/ircdocs/wooooms/issues/5 + +(ert-deftest erc-scenarios-base-mask-target-routing () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/mask-target-routing") + (dumb-server (erc-d-run "localhost" t 'foonet)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter))) + + (ert-info ("Connect to foonet") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester") + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (erc-d-t-wait-for 10 (get-buffer "foonet")) + + (ert-info ("Channel buffer #foo playback received") + (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#foo")) + (funcall expect 10 "Excellent workman"))) + + (ert-info ("Global notices routed to server buffer") + (with-current-buffer "foonet" + (funcall expect 10 "going down soon") + (funcall expect 10 "this is a warning") + (funcall expect 10 "second warning") + (funcall expect 10 "final warning"))) + + (should-not (get-buffer "$*")))) + ;;; erc-scenarios-misc.el ends here diff --git a/test/lisp/erc/resources/base/mask-target-routing/foonet.eld b/test/lisp/erc/resources/base/mask-target-routing/foonet.eld new file mode 100644 index 0000000000..796d5566b6 --- /dev/null +++ b/test/lisp/erc/resources/base/mask-target-routing/foonet.eld @@ -0,0 +1,45 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Mon, 31 May 2021 09:56:24 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 2 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4") + (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo") + (0 ":irc.foonet.org 353 tester = #foo :alice @bob rando tester") + (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...") + (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.") + (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.") + (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.") + (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((mode 5 "MODE #foo") + (0 ":irc.foonet.org 324 tester #foo +nt") + (0 ":irc.foonet.org 329 tester #foo 1622454985") + ;; Invalid msg + (0.1 ":rando!~u@em2i467d4ejul.irc PRIVMSG :") + (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE $* :[Global notice] going down soon.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: Well, this is the forest of Arden.") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE $$* :[Global notice] this is a warning.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: Be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG $* :[Global msg] second warning.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #foo :bob: And will you, being a man of your breeding.") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc NOTICE #* :[Global notice] final warning.")) commit 7c47d6c52d70225334444947824b40ad9f593c31 Author: F. Jason Park Date: Wed Oct 27 21:13:24 2021 -0700 Register erc-kill-buffer-function locally * lisp/erc/erc.el (erc-kill-buffer-function): Don't add hook when loading file. Move to major-mode setup and make buffer-local instead. Depends on tests in bug#48598. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 18a353ae49..cbb0c9f4b4 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1591,6 +1591,7 @@ Defaults to the server buffer." (setq-local paragraph-start (concat "\\(" (regexp-quote (erc-prompt)) "\\)")) (setq-local completion-ignore-case t) + (add-hook 'kill-buffer-hook #'erc-kill-buffer-function nil t) (add-hook 'completion-at-point-functions #'erc-complete-word-at-point nil t)) ;; activation @@ -7111,9 +7112,6 @@ See also `format-spec'." ;;; Various hook functions -;; FIXME: Don't set the hook globally! -(add-hook 'kill-buffer-hook #'erc-kill-buffer-function) - (defcustom erc-kill-server-hook '(erc-kill-server erc-networks-shrink-ids-and-buffer-names) "Invoked whenever a live server buffer is killed via `kill-buffer'." commit 922ad238403d8d821bd696372ffe58572df12670 Author: F. Jason Park Date: Thu May 13 05:55:22 2021 -0700 Add user-oriented test scenarios for ERC * test/lisp/erc/erc-scenarios-base-association-nick.el: New file. * test/lisp/erc/erc-scenarios-base-association-samenet.el: New file. * test/lisp/erc/erc-scenarios-base-association.el: New file. * test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el: New file. * test/lisp/erc/erc-scenarios-base-misc-regressions.el: New file. * test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el: New file. * test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el: New file. * test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el: New file. * test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el: New file. * test/lisp/erc/erc-scenarios-base-netid-bouncer.el: New file. * test/lisp/erc/erc-scenarios-base-netid-samenet.el: New file. * test/lisp/erc/erc-scenarios-base-reconnect.el: New file. * test/lisp/erc/erc-scenarios-base-renick.el: New file. * test/lisp/erc/erc-scenarios-base-reuse-buffers.el: New file. * test/lisp/erc/erc-scenarios-base-unstable.el: New file. * test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el: New file. * test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el: New file. * test/lisp/erc/erc-scenarios-misc.el: New file. * test/lisp/erc/erc-scenarios-services-misc.el: New file. * test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld: New file. * test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld: New file. * test/lisp/erc/resources/base/assoc/bumped/again.eld: New file. * test/lisp/erc/resources/base/assoc/bumped/foisted.eld: New file. * test/lisp/erc/resources/base/assoc/bumped/refoisted.eld: New file. * test/lisp/erc/resources/base/assoc/bumped/renicked.eld: New file. * test/lisp/erc/resources/base/assoc/multi-net/barnet.eld: New file. * test/lisp/erc/resources/base/assoc/multi-net/foonet.eld: New file. * test/lisp/erc/resources/base/assoc/reconplay/again.eld: New file. * test/lisp/erc/resources/base/assoc/reconplay/foonet.eld: New file. * test/lisp/erc/resources/base/assoc/samenet/chester.eld: New file. * test/lisp/erc/resources/base/assoc/samenet/tester.eld: New file. * test/lisp/erc/resources/base/assoc/samenet/tester2.eld: New file. * test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld: New file. * test/lisp/erc/resources/base/flood/soju.eld: New file. * test/lisp/erc/resources/base/gapless-connect/barnet.eld: New file. * test/lisp/erc/resources/base/gapless-connect/foonet.eld: New file. * test/lisp/erc/resources/base/gapless-connect/pass-stub.eld: New file. * test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld: New file. * test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld: New file. * test/lisp/erc/resources/base/netid/bouncer/barnet.eld: New file. * test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld: New file. * test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld: New file. * test/lisp/erc/resources/base/netid/bouncer/foonet.eld: New file. * test/lisp/erc/resources/base/netid/bouncer/stub-again.eld: New file. * test/lisp/erc/resources/base/netid/samenet/chester.eld: New file. * test/lisp/erc/resources/base/netid/samenet/tester.eld: New file. * test/lisp/erc/resources/base/reconnect/aborted-dupe.eld: New file. * test/lisp/erc/resources/base/reconnect/aborted.eld: New file. * test/lisp/erc/resources/base/reconnect/options-again.eld: New file. * test/lisp/erc/resources/base/reconnect/options.eld: New file. * test/lisp/erc/resources/base/reconnect/timer-last.eld: New file. * test/lisp/erc/resources/base/reconnect/timer.eld: New file. * test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld: New file. * test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld: New file. * test/lisp/erc/resources/base/renick/queries/solo.eld: New file. * test/lisp/erc/resources/base/renick/self/auto.eld: New file. * test/lisp/erc/resources/base/renick/self/manual.eld: New file. * test/lisp/erc/resources/base/renick/self/qual-chester.eld: New file. * test/lisp/erc/resources/base/renick/self/qual-tester.eld: New file. * test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld: New file. * test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld: New file. * test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld: New file. * test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld: New file. * test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld: New file. * test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld: New file. * test/lisp/erc/resources/erc-scenarios-common.el: New file. * test/lisp/erc/resources/networks/announced-missing/foonet.eld: New file. * test/lisp/erc/resources/services/password/libera.eld: New file. Add test cases for locking down fundamental client behavior, much of it involving the relationship between buffers and connections. Also add accompanying resources subdir containing canned dialog scripts and common code needed by various tests. For test cases demoing the problematic behavior originally described in the initial report, see update #4 on the bug tracker thread for bug#48598. Most reside in a file named test/lisp/erc/erc-scenarios-48598.el introduced by the patch "Add user-oriented test scenarios for ERC". diff --git a/test/lisp/erc/erc-scenarios-base-association-nick.el b/test/lisp/erc/erc-scenarios-base-association-nick.el new file mode 100644 index 0000000000..3e848be4df --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-association-nick.el @@ -0,0 +1,163 @@ +;;; erc-scenarios-base-association-nick.el --- base assoc scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +;; You register a new nick, disconnect, and log back in, but your nick +;; is not granted, so ERC obtains a backtick'd version. You open a +;; query buffer for NickServ, and ERC names it using the net-ID (which +;; includes the backtick'd nick) as a suffix. The original +;; (disconnected) NickServ buffer gets renamed with *its* net-ID as +;; well. You then identify to NickServ, and the dead session is no +;; longer considered distinct. + +(ert-deftest erc-scenarios-base-association-nick-bumped () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/assoc/bumped") + (dumb-server (erc-d-run "localhost" t 'renicked 'again)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + (erc-server-flood-penalty 0.5) + (erc-server-flood-margin 30)) + + (ert-info ("Connect to foonet with nick tester") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :full-name "tester") + (erc-scenarios-common-assert-initial-buf-name nil port) + (erc-d-t-wait-for 5 (eq erc-network 'foonet)))) + + (ert-info ("Create an account for tester and quit") + (with-current-buffer "foonet" + (funcall expect 3 "debug mode") + + (erc-cmd-QUERY "NickServ") + (with-current-buffer "NickServ" + (erc-scenarios-common-say "REGISTER changeme") + (funcall expect 5 "Account created") + (funcall expect 1 "You're now logged in as tester")) + + (with-current-buffer "foonet" + (erc-cmd-QUIT "") + (erc-d-t-wait-for 4 (not (erc-server-process-alive))) + (funcall expect 5 "ERC finished")))) + + (with-current-buffer "foonet" + (erc-cmd-RECONNECT)) + + (erc-d-t-wait-for 10 "Nick request rejection prevents reassociation (good)" + (get-buffer "foonet/tester`")) + + (ert-info ("Ask NickServ to change nick") + (with-current-buffer "foonet/tester`" + (funcall expect 3 "already in use") + (funcall expect 3 "debug mode") + (erc-cmd-QUERY "NickServ")) + + (erc-d-t-wait-for 1 "Dead NickServ query buffer renamed, now qualified" + (get-buffer "NickServ@foonet/tester")) + + (with-current-buffer "NickServ@foonet/tester`" ; new one + (erc-scenarios-common-say "IDENTIFY tester changeme") + (funcall expect 5 "You're now logged in as tester") + (ert-info ("Original buffer found, reused") + (erc-d-t-wait-for 2 (equal (buffer-name) "NickServ"))))) + + (ert-info ("Ours is the only NickServ buffer that remains") + (should-not (cdr (erc-scenarios-common-buflist "NickServ")))) + + (ert-info ("Visible network ID truncated to one component") + (should (not (get-buffer "foonet/tester`"))) + (should (not (get-buffer "foonet/tester"))) + (should (get-buffer "foonet"))))) + +;; A less common variant is when your bouncer switches to an alternate +;; nick while you're disconnected, and upon reconnecting, you get +;; a new nick. + +(ert-deftest erc-scenarios-base-association-nick-bumped-mandated-renick () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/assoc/bumped") + (dumb-server (erc-d-run "localhost" t 'foisted 'refoisted)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + (erc-server-flood-penalty 0.5) + (erc-server-flood-margin 30)) + + (ert-info ("Connect to foonet with nick tester") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :full-name "tester") + (erc-scenarios-common-assert-initial-buf-name nil port) + (erc-d-t-wait-for 5 (eq erc-network 'foonet)))) + + (ert-info ("Greet bob and quit") + (with-current-buffer "foonet" + (funcall expect 3 "debug mode") + + (erc-cmd-QUERY "bob") + (with-current-buffer "bob" + (erc-scenarios-common-say "hi") + (funcall expect 5 "hola") + (funcall expect 1 "how r u?")) + + (with-current-buffer "foonet" + (erc-cmd-QUIT "") + (erc-d-t-wait-for 4 (not (erc-server-process-alive))) + (funcall expect 5 "ERC finished")))) + + ;; Since we use reconnect, a new buffer won't be created + ;; TODO add variant with clean `erc' invocation + (with-current-buffer "foonet" + (erc-cmd-RECONNECT)) + + (ert-info ("Server-initiated renick") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "foonet/dummy")) + (should-not (get-buffer "foonet/tester")) + (funcall expect 15 "debug mode")) + + (erc-d-t-wait-for 1 "Old query renamed, now qualified" + (get-buffer "bob@foonet/tester")) + + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "bob@foonet/dummy")) + (erc-cmd-NICK "tester") + (ert-info ("Buffers combined") + (erc-d-t-wait-for 2 (equal (buffer-name) "bob"))))) + + (with-current-buffer "foonet" + (funcall expect 5 "You're now logged in as tester")) + + (ert-info ("Ours is the only bob buffer that remains") + (should-not (cdr (erc-scenarios-common-buflist "bob")))) + + (ert-info ("Visible network ID truncated to one component") + (should (not (get-buffer "foonet/dummy"))) + (should (get-buffer "foonet"))))) + +;;; erc-scenarios-base-association-nick.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-association-samenet.el b/test/lisp/erc/erc-scenarios-base-association-samenet.el new file mode 100644 index 0000000000..b7c7079df3 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-association-samenet.el @@ -0,0 +1,144 @@ +;;; erc-scenarios-base-association-samenet.el --- assoc samenet scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(declare-function erc-network-name "erc-networks") +(declare-function erc-network "erc-networks") +(defvar erc-autojoin-channels-alist) +(defvar erc-network) + +;; One network, two simultaneous connections, no IDs. +;; Reassociates on reconnect with and without server buffer. + +(defun erc-scenarios-common--base-association-samenet (after) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/assoc/samenet") + (dumb-server (erc-d-run "localhost" t 'tester 'chester 'tester2)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + (erc-server-flood-penalty 0.5) + (erc-server-flood-margin 30)) + + (ert-info ("Connect to foonet with nick tester") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester") + (erc-scenarios-common-assert-initial-buf-name nil port) + (erc-d-t-wait-for 5 (eq erc-network 'foonet)))) + + (ert-info ("Connect to foonet with nick chester") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "chester" + :password "changeme" + :full-name "chester") + (erc-scenarios-common-assert-initial-buf-name nil port))) + + (erc-d-t-wait-for 3 "Dialed Buflist is Empty" + (not (erc-scenarios-common-buflist "127.0.0.1"))) + + (with-current-buffer "foonet/tester" + (funcall expect 3 "debug mode") + (erc-cmd-JOIN "#chan")) + + (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/tester")) + (with-current-buffer "foonet/chester" (funcall expect 3 "debug mode")) + (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/chester")) + + (ert-info ("Nick tester sees other nick chester in channel") + (with-current-buffer "#chan@foonet/tester" + (funcall expect 5 "chester") + (funcall expect 5 "find the forester") + (erc-cmd-QUIT ""))) + + (ert-info ("Nick chester sees other nick tester in same channel") + (with-current-buffer "#chan@foonet/chester" + (funcall expect 5 "tester") + (funcall expect 5 "find the forester"))) + + (funcall after expect))) + +(ert-deftest erc-scenarios-base-association-samenet--reconnect-one () + :tags '(:expensive-test) + (erc-scenarios-common--base-association-samenet + (lambda (expect) + + (ert-info ("Connection tester reconnects") + (with-current-buffer "foonet/tester" + (erc-d-t-wait-for 10 (not (erc-server-process-alive))) + (funcall expect 10 "*** ERC finished") + (erc-cmd-RECONNECT) + (funcall expect 5 "debug mode"))) + + (ert-info ("Reassociated to same channel") + (with-current-buffer "#chan@foonet/tester" + (funcall expect 5 "chester") + (funcall expect 5 "welcome again") + (erc-cmd-QUIT ""))) + + (with-current-buffer "#chan@foonet/chester" + (funcall expect 5 "tester") + (funcall expect 5 "welcome again") + (funcall expect 5 "welcome again") + (erc-cmd-QUIT ""))))) + +(ert-deftest erc-scenarios-base-association-samenet--new-buffer () + :tags '(:expensive-test) + (erc-scenarios-common--base-association-samenet + (lambda (expect) + + (ert-info ("Tester kills buffer and connects from scratch") + + (let (port) + (with-current-buffer "foonet/tester" + (erc-d-t-wait-for 10 (not (erc-server-process-alive))) + (funcall expect 10 "*** ERC finished") + (setq port erc-session-port) + (kill-buffer)) + + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester") + + (erc-d-t-wait-for 5 (eq erc-network 'foonet))))) + + (with-current-buffer "foonet/tester" (funcall expect 3 "debug mode")) + + (ert-info ("Reassociated to same channel") + (with-current-buffer "#chan@foonet/tester" + (funcall expect 5 "chester") + (funcall expect 5 "welcome again") + (erc-cmd-QUIT ""))) + + (with-current-buffer "#chan@foonet/chester" + (funcall expect 5 "tester") + (funcall expect 5 "welcome again") + (funcall expect 5 "welcome again") + (erc-cmd-QUIT ""))))) + +;;; erc-scenarios-base-association-samenet.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-association.el b/test/lisp/erc/erc-scenarios-base-association.el new file mode 100644 index 0000000000..83e5101e3a --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-association.el @@ -0,0 +1,192 @@ +;;; erc-scenarios-base-association.el --- base assoc scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(declare-function erc-network-name "erc-networks") +(declare-function erc-network "erc-networks") +(defvar erc-autojoin-channels-alist) +(defvar erc-network) + +;; Two networks, same channel name, no confusion (no bouncer). Some +;; of this draws from bug#47522 "foil-in-server-buf". It shows that +;; disambiguation-related changes added for bug#48598 are not specific +;; to bouncers. + +(defun erc-scenarios-common--base-association-multi-net (second-join) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/assoc/multi-net") + (erc-server-flood-penalty 0.1) + (dumb-server-foonet-buffer (get-buffer-create "*server-foonet*")) + (dumb-server-barnet-buffer (get-buffer-create "*server-barnet*")) + (dumb-server-foonet (erc-d-run "localhost" t "server-foonet" 'foonet)) + (dumb-server-barnet (erc-d-run "localhost" t "server-barnet" 'barnet)) + (expect (erc-d-t-make-expecter))) + + (ert-info ("Connect to foonet, join #chan") + (with-current-buffer + (erc :server "127.0.0.1" + :port (process-contact dumb-server-foonet :service) + :nick "tester" + :password "changeme" + :full-name "tester") + (funcall expect 3 "debug mode") + (erc-cmd-JOIN "#chan"))) + + (erc-d-t-wait-for 2 (get-buffer "#chan")) + + (ert-info ("Connect to barnet, join #chan") + (with-current-buffer + (erc :server "127.0.0.1" + :port (process-contact dumb-server-barnet :service) + :nick "tester" + :password "changeme" + :full-name "tester") + (funcall expect 5 "debug mode"))) + + (funcall second-join) + + (erc-d-t-wait-for 3 (get-buffer "#chan@barnet")) + + (erc-d-t-wait-for 2 "Buf #chan now #chan@foonet" + (and (get-buffer "#chan@foonet") (not (get-buffer "#chan")))) + + (ert-info ("All #chan@foonet output consumed") + (with-current-buffer "#chan@foonet" + (funcall expect 3 "bob") + (funcall expect 3 "was created on") + (funcall expect 3 "prosperous"))) + + (ert-info ("All #chan@barnet output consumed") + (with-current-buffer "#chan@barnet" + (funcall expect 3 "mike") + (funcall expect 3 "was created on") + (funcall expect 20 "ingenuous"))))) + +(ert-deftest erc-scenarios-base-association-multi-net--baseline () + :tags '(:expensive-test) + (erc-scenarios-common--base-association-multi-net + (lambda () (with-current-buffer "barnet" (erc-cmd-JOIN "#chan"))))) + +;; The /join command only targets the current buffer's process. This +;; recasts scenario bug#48598 "ambiguous-join" (which was based on +;; bug#47522) to show that issuing superfluous /join commands +;; (apparently fairly common) is benign. + +(ert-deftest erc-scenarios-base-association-multi-net--ambiguous-join () + :tags '(:expensive-test) + (erc-scenarios-common--base-association-multi-net + (lambda () + (ert-info ("Nonsensical JOIN attempts silently dropped.") + (with-current-buffer "foonet" (erc-cmd-JOIN "#chan")) + (sit-for 0.1) + (with-current-buffer "#chan" (erc-cmd-JOIN "#chan")) + (sit-for 0.1) + (erc-d-t-wait-for 2 (get-buffer "#chan")) + (erc-d-t-wait-for 1 "Only one #chan buffer exists" + (should (equal (erc-scenarios-common-buflist "#chan") + (list (get-buffer "#chan"))))) + (with-current-buffer "*server-barnet*" + (erc-d-t-absent-for 0.1 "JOIN")) + (with-current-buffer "barnet" (erc-cmd-JOIN "#chan")))))) + +;; Playback for same channel on two networks routed correctly. +;; Originally from Bug#48598: 28.0.50; buffer-naming collisions +;; involving bouncers in ERC. + +(ert-deftest erc-scenarios-base-association-bouncer-history () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/assoc/bouncer-history") + (erc-d-t-cleanup-sleep-secs 1) + (dumb-server (erc-d-run "localhost" t 'foonet 'barnet)) + (port (process-contact dumb-server :service)) + (erc-server-flood-penalty 0.5) + (expect (erc-d-t-make-expecter)) + erc-autojoin-channels-alist + erc-server-buffer-foo erc-server-process-foo + erc-server-buffer-bar erc-server-process-bar) + + (ert-info ("Connect to foonet") + (with-current-buffer + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester")) + (setq erc-server-process-foo erc-server-process) + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (funcall expect 5 "foonet"))) + + (erc-d-t-wait-for 5 (get-buffer "#chan")) + + (ert-info ("Connect to barnet") + (with-current-buffer + (setq erc-server-buffer-bar (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "barnet:changeme" + :full-name "tester")) + (setq erc-server-process-bar erc-server-process) + (erc-d-t-wait-for 5 "Temporary name assigned" + (string= (buffer-name) (format "127.0.0.1:%d" port))) + (funcall expect 5 "barnet"))) + + (ert-info ("Server buffers are unique") + (should-not (eq erc-server-buffer-foo erc-server-buffer-bar))) + + (ert-info ("Networks correctly determined and adopted as buffer names") + (with-current-buffer erc-server-buffer-foo + (erc-d-t-wait-for 3 "network name foonet becomes buffer name" + (and (eq (erc-network) 'foonet) (string= (buffer-name) "foonet")))) + (with-current-buffer erc-server-buffer-bar + (erc-d-t-wait-for 3 "network name barnet becomes buffer name" + (and (eq (erc-network) 'barnet) (string= (buffer-name) "barnet"))))) + + (erc-d-t-wait-for 5 (get-buffer "#chan@barnet")) + + (ert-info ("Two channel buffers created, original #chan renamed") + (should (= 4 (length (erc-buffer-list)))) + (should (equal (list (get-buffer "#chan@barnet") + (get-buffer "#chan@foonet")) + (erc-scenarios-common-buflist "#chan")))) + + (ert-info ("#chan@foonet is exclusive, no cross-contamination") + (with-current-buffer "#chan@foonet" + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (should (eq erc-server-process erc-server-process-foo)))) + + (ert-info ("#chan@barnet is exclusive, no cross-contamination") + (with-current-buffer "#chan@barnet" + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (should (eq erc-server-process erc-server-process-bar)))) + + (ert-info ("All output sent") + (with-current-buffer "#chan@foonet" + (erc-d-t-search-for 10 "please your lordship")) + (with-current-buffer "#chan@barnet" + (erc-d-t-search-for 10 "I'll bid adieu"))))) + +;;; erc-scenarios-base-association.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el new file mode 100644 index 0000000000..474739d01b --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-compat-rename-bouncer.el @@ -0,0 +1,171 @@ +;;; erc-scenarios-compat-rename-bouncer.el --- compat-rename scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +;; Ensure deprecated option still respected when old default value +;; explicitly set ("respected" in the sense of having names reflect +;; dialed TCP endpoints with possible uniquifiers but without any of +;; the old issues, pre-bug#48598). + +(defun erc-scenarios-common--base-compat-no-rename-bouncer (dialogs auto more) + (erc-scenarios-common-with-cleanup + ;; These actually *are* (assigned-)network-id related because + ;; our kludge assigns one after the fact. + ((erc-scenarios-common-dialog "base/netid/bouncer") + (erc-d-t-cleanup-sleep-secs 1) + (erc-server-flood-penalty 0.1) + (dumb-server (apply #'erc-d-run "localhost" t dialogs)) + (port (process-contact dumb-server :service)) + (chan-buf-foo (format "#chan@127.0.0.1:%d" port)) + (chan-buf-bar (format "#chan@127.0.0.1:%d<2>" port)) + (expect (erc-d-t-make-expecter)) + (erc-server-auto-reconnect auto) + erc-server-buffer-foo erc-server-process-foo + erc-server-buffer-bar erc-server-process-bar) + + (ert-info ("Connect to foonet") + (with-current-buffer + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester" + :id nil)) + (setq erc-server-process-foo erc-server-process) + (erc-d-t-wait-for 3 (eq (erc-network) 'foonet)) + (erc-d-t-wait-for 3 "Final buffer name determined" + (string= (buffer-name) (format "127.0.0.1:%d" port))) + (funcall expect 5 "foonet"))) + + (ert-info ("Join #chan@foonet") + (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan")) + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan")) + (funcall expect 5 ""))) + + (ert-info ("Connect to barnet") + (with-current-buffer + (setq erc-server-buffer-bar (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "barnet:changeme" + :full-name "tester" + :id nil)) + (setq erc-server-process-bar erc-server-process) + (erc-d-t-wait-for 3 (eq (erc-network) 'barnet)) + (erc-d-t-wait-for 3 "Final buffer name determined" + (string= (buffer-name) (format "127.0.0.1:%d<2>" port))) + (funcall expect 5 "barnet"))) + + (ert-info ("Server buffers are unique, no names based on IPs") + (should-not (eq erc-server-buffer-foo erc-server-buffer-bar)) + (should (equal (erc-scenarios-common-buflist "127.0.0.1") + (list (get-buffer (format "127.0.0.1:%d<2>" port)) + (get-buffer (format "127.0.0.1:%d" port)))))) + + (ert-info ("Join #chan@barnet") + (with-current-buffer erc-server-buffer-bar (erc-cmd-JOIN "#chan"))) + + (erc-d-t-wait-for 5 "Exactly 2 #chan-prefixed buffers exist" + (equal (list (get-buffer chan-buf-bar) + (get-buffer chan-buf-foo)) + (erc-scenarios-common-buflist "#chan"))) + + (ert-info ("#chan@127.0.0.1:$port is exclusive to foonet") + (with-current-buffer chan-buf-foo + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (should (eq erc-server-process erc-server-process-foo)) + (erc-d-t-search-for 10 "ape is dead") + (erc-d-t-wait-for 5 (not (erc-server-process-alive))))) + + (ert-info ("#chan@127.0.0.1:$port<2> is exclusive to barnet") + (with-current-buffer chan-buf-bar + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (should (eq erc-server-process erc-server-process-bar)) + (erc-d-t-search-for 10 "keeps you from dishonour") + (erc-d-t-wait-for 5 (not (erc-server-process-alive))))) + + (when more (funcall more)))) + +(ert-deftest erc-scenarios-base-compat-no-rename-bouncer--basic () + :tags '(:expensive-test) + (with-suppressed-warnings ((obsolete erc-rename-buffers)) + (let (erc-rename-buffers) + (erc-scenarios-common--base-compat-no-rename-bouncer + '(foonet barnet) nil nil)))) + +(ert-deftest erc-scenarios-base-compat-no-rename-bouncer--reconnect () + :tags '(:expensive-test) + (let ((erc-d-tmpl-vars '((token . (group (| "barnet" "foonet"))))) + (erc-d-match-handlers + (list :pass #'erc-scenarios-common--clash-rename-pass-handler)) + (dialogs '(foonet-drop barnet-drop stub-again stub-again + foonet-again barnet-again)) + (after + (lambda () + (pcase-let* ((`(,barnet ,foonet) + (erc-scenarios-common-buflist "127.0.0.1")) + (port (process-contact (with-current-buffer foonet + erc-server-process) + :service))) + + (ert-info ("Sanity check: barnet retains uniquifying suffix") + (should (string-suffix-p "<2>" (buffer-name barnet)))) + + ;; Simulate disconnection and `erc-server-auto-reconnect' + (ert-info ("Reconnect to foonet and barnet back-to-back") + (with-current-buffer foonet + (erc-d-t-wait-for 5 (erc-server-process-alive))) + (with-current-buffer barnet + (erc-d-t-wait-for 5 (erc-server-process-alive)))) + + (ert-info ("#chan@127.0.0.1: is exclusive to foonet") + (with-current-buffer (format "#chan@127.0.0.1:%d" port) + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (erc-d-t-search-for 10 "please your lordship"))) + + (ert-info ("#chan@barnet is exclusive to barnet") + (with-current-buffer (format "#chan@127.0.0.1:%d<2>" port) + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (erc-d-t-search-for 1 "much in private"))) + + ;; Ordering deterministic here even though not so for reconnect + (should (equal (list barnet foonet) + (erc-scenarios-common-buflist "127.0.0.1"))) + (should (equal (list + (get-buffer (format "#chan@127.0.0.1:%d<2>" port)) + (get-buffer (format "#chan@127.0.0.1:%d" port))) + (erc-scenarios-common-buflist "#chan"))))))) + + (with-suppressed-warnings ((obsolete erc-rename-buffers)) + (let (erc-rename-buffers) + (erc-scenarios-common--base-compat-no-rename-bouncer dialogs + 'auto after))))) + +;;; erc-scenarios-compat-rename-bouncer.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-misc-regressions.el b/test/lisp/erc/erc-scenarios-base-misc-regressions.el new file mode 100644 index 0000000000..8f5700df14 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-misc-regressions.el @@ -0,0 +1,126 @@ +;;; erc-scenarios-base-misc-regressions.el --- misc regressions scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +(defun erc-scenarios--rebuffed-gapless-pass-handler (dialog exchange) + (when (eq (erc-d-dialog-name dialog) 'pass-stub) + (let* ((match (erc-d-exchange-match exchange 1)) + (sym (if (string= match "foonet") 'foonet 'barnet))) + (should (member match (list "foonet" "barnet"))) + (erc-d-load-replacement-dialog dialog sym 1)))) + +(ert-deftest erc-scenarios-base-gapless-connect () + "Back-to-back entry-point invocations happen successfully. +Originally from scenario rebuffed/gapless as explained in Bug#48598: +28.0.50; buffer-naming collisions involving bouncers in ERC." + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/gapless-connect") + (erc-server-flood-penalty 0.1) + (erc-server-flood-penalty erc-server-flood-penalty) + (erc-d-tmpl-vars '((token . (group (| "barnet" "foonet"))))) + (erc-d-match-handlers + (list :pass #'erc-scenarios--rebuffed-gapless-pass-handler)) + (dumb-server (erc-d-run "localhost" t + 'pass-stub 'pass-stub 'barnet 'foonet)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + erc-autojoin-channels-alist + erc-server-buffer-foo + erc-server-buffer-bar) + + (ert-info ("Connect twice to same endpoint without pausing") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester") + erc-server-buffer-bar (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "barnet:changeme" + :full-name "tester"))) + + (ert-info ("Returned server buffers are unique") + (should-not (eq erc-server-buffer-foo erc-server-buffer-bar))) + + (ert-info ("Both connections still alive") + (should (get-process (format "erc-127.0.0.1-%d" port))) + (should (get-process (format "erc-127.0.0.1-%d<1>" port)))) + + (with-current-buffer erc-server-buffer-bar + (funcall expect 2 "marked as being away")) + + (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#bar")) + (funcall expect 10 "was created on") + (funcall expect 2 "his second fit")) + + (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#foo")) + (funcall expect 10 "was created on") + (funcall expect 2 "no use of him")))) + +;; This defends against a regression in `erc-server-PRIVMSG' caused by +;; the removal of `erc-auto-query'. When an active channel buffer is +;; killed off and PRIVMSGs arrive targeting it, the buffer should be +;; recreated. See elsewhere for NOTICE logic, which is more complex. + +(ert-deftest erc-scenarios-base-channel-buffer-revival () + :tags '(:expensive-test) + + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/channel-buffer-revival") + (dumb-server (erc-d-run "localhost" t 'foonet)) + (port (process-contact dumb-server :service)) + erc-autojoin-channels-alist + erc-server-buffer-foo) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (ert-info ("Server buffer is unique and temp name is absent") + (erc-d-t-wait-for 1 (get-buffer "FooNet")) + (should-not (erc-scenarios-common-buflist "127.0.0.1")) + (with-current-buffer erc-server-buffer-foo + (erc-cmd-JOIN "#chan"))) + + (ert-info ("Channel buffer #chan alive and well") + (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#chan")) + (erc-d-t-search-for 10 "Our queen and all her elves") + (kill-buffer))) + + (should-not (get-buffer "#chan")) + + (ert-info ("Channel buffer #chan revived") + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan")) + (erc-d-t-search-for 10 "and be prosperous"))))) + +;;; erc-scenarios-base-misc-regressions.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el new file mode 100644 index 0000000000..6c6568cad6 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-id.el @@ -0,0 +1,34 @@ +;;; erc-scenarios-base-netid-bouncer-id.el --- net-id bouncer ID scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-base-netid-bouncer--id-foo () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-bouncer '(:foo-id t) 'foonet 'barnet)) + +(ert-deftest erc-scenarios-base-netid-bouncer--id-bar () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-bouncer '(:bar-id t) 'foonet 'barnet)) + +;;; erc-scenarios-base-netid-bouncer-id.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el new file mode 100644 index 0000000000..f48e1ef394 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-base.el @@ -0,0 +1,30 @@ +;;; erc-scenarios-base-netid-bouncer-recon-base.el --- net-id base scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-base-netid-bouncer--recon-base () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-bouncer--reconnect nil nil)) + +;;; erc-scenarios-base-netid-bouncer-recon-base.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el new file mode 100644 index 0000000000..2f58c3269e --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-both.el @@ -0,0 +1,32 @@ +;;; erc-scenarios-base-netid-bouncer-recon-both.el --- net-id both scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(require 'erc-scenarios-common) + +(ert-deftest erc-scenarios-base-netid-bouncer--recon-both () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-bouncer--reconnect 'foo-id 'bar-id)) + +;;; erc-scenarios-base-netid-bouncer-recon-both.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el new file mode 100644 index 0000000000..72510809ab --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer-recon-id.el @@ -0,0 +1,35 @@ +;;; erc-scenarios-base-netid-bouncer-recon-id.el --- recon ID scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-base-netid-bouncer--reconnect-id-foo () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-bouncer--reconnect 'foo-id nil)) + +(ert-deftest erc-scenarios-base-netid-bouncer--reconnect-id-bar () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-bouncer--reconnect nil 'bar-id)) + + +;;; erc-scenarios-base-netid-bouncer-recon-id.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-netid-bouncer.el b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el new file mode 100644 index 0000000000..d171e1f9f9 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-netid-bouncer.el @@ -0,0 +1,35 @@ +;;; erc-scenarios-base-netid-bouncer.el --- net-id bouncer scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-base-netid-bouncer--base () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-bouncer () 'foonet 'barnet)) + +(ert-deftest erc-scenarios-base-netid-bouncer--both () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-bouncer '(:foo-id t :bar-id t) + 'foonet 'barnet)) + +;;; erc-scenarios-base-netid-bouncer.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-netid-samenet.el b/test/lisp/erc/erc-scenarios-base-netid-samenet.el new file mode 100644 index 0000000000..248144d6f9 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-netid-samenet.el @@ -0,0 +1,147 @@ +;;; erc-scenarios-base-network-id-samenet.el --- netid-id samenet scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +(cl-defun erc-scenarios-common--base-network-id-same-network + ((&key nick id server chan + &aux (nick-a nick) (id-a id) (serv-buf-a server) (chan-buf-a chan)) + (&key nick id server chan + &aux (nick-b nick) (id-b id) (serv-buf-b server) (chan-buf-b chan))) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/netid/samenet") + (dumb-server (erc-d-run "localhost" t 'tester 'chester)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + (erc-server-flood-penalty 0.1) + (erc-server-flood-margin 30) + erc-serv-buf-a erc-serv-buf-b) + + (ert-info ("Connect to foonet with nick tester") + (with-current-buffer + (setq erc-serv-buf-a (erc :server "127.0.0.1" + :port port + :nick nick-a + :password "changeme" + :full-name nick-a + :id id-a)) + (erc-scenarios-common-assert-initial-buf-name id-a port) + (erc-d-t-wait-for 5 (eq erc-network 'foonet)))) + + (ert-info ("Connect to foonet with nick chester") + (with-current-buffer + (setq erc-serv-buf-b (erc :server "127.0.0.1" + :port port + :nick nick-b + :password "changeme" + :full-name nick-b + :id id-b)) + (erc-scenarios-common-assert-initial-buf-name id-b port))) + + (erc-d-t-wait-for 3 (not (erc-scenarios-common-buflist "127.0.0.1"))) + + (with-current-buffer erc-serv-buf-a + (should (string= (buffer-name) serv-buf-a)) + (funcall expect 8 "debug mode") + (erc-cmd-JOIN "#chan")) + + (with-current-buffer erc-serv-buf-b + (should (string= (buffer-name) serv-buf-b)) + (funcall expect 8 "debug mode") + (erc-cmd-JOIN "#chan")) + + (erc-d-t-wait-for 10 (get-buffer chan-buf-a)) + (erc-d-t-wait-for 10 (get-buffer chan-buf-b)) + + (ert-info ("Greets other nick in same channel") + (with-current-buffer chan-buf-a + (funcall expect 5 "chester") + (funcall expect 5 "find the forester") + (erc-cmd-MSG "#chan chester: hi"))) + + (ert-info ("Sees other nick in same channel") + (with-current-buffer chan-buf-b + (funcall expect 5 "tester") + (funcall expect 10 " chester: hi") + (funcall expect 5 "This was lofty") + (erc-cmd-MSG "#chan hi tester"))) + + (with-current-buffer chan-buf-a + (funcall expect 5 "To employ you towards") + (erc-cmd-QUIT "")) + + (with-current-buffer chan-buf-b + (funcall expect 5 "To employ you towards") + (erc-cmd-QUIT "")))) + +(ert-deftest erc-scenarios-base-network-id-same-network--two-ids () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-same-network + (list :nick "tester" + :id 'tester/foonet + :server "tester/foonet" + :chan "#chan@tester/foonet") + (list :nick "chester" + :id 'chester/foonet + :server "chester/foonet" + :chan "#chan@chester/foonet"))) + +(ert-deftest erc-scenarios-base-network-id-same-network--one-id-tester () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-same-network + (list :nick "tester" + :id 'tester/foonet + :server "tester/foonet" + :chan "#chan@tester/foonet") + (list :nick "chester" + :id nil + :server "foonet" + :chan "#chan@foonet"))) + +(ert-deftest erc-scenarios-base-network-id-same-network--one-id-chester () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-same-network + (list :nick "tester" + :id nil + :server "foonet" + :chan "#chan@foonet") + (list :nick "chester" + :id 'chester/foonet + :server "chester/foonet" + :chan "#chan@chester/foonet"))) + +(ert-deftest erc-scenarios-base-network-id-same-network--no-ids () + :tags '(:expensive-test) + (erc-scenarios-common--base-network-id-same-network + (list :nick "tester" + :id nil + :server "foonet/tester" + :chan "#chan@foonet/tester") ; <- note net before nick + (list :nick "chester" + :id nil + :server "foonet/chester" + :chan "#chan@foonet/chester"))) + +;;; erc-scenarios-base-network-id-samenet.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-reconnect.el b/test/lisp/erc/erc-scenarios-base-reconnect.el new file mode 100644 index 0000000000..aeb59e1870 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-reconnect.el @@ -0,0 +1,226 @@ +;;; erc-scenarios-base-reconnect.el --- Base-reconnect scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +;; This ensures we only reconnect `erc-server-reconnect-attempts' +;; (rather than infinitely many) times, which can easily happen when +;; tweaking code related to process sentinels in erc-backend.el. + +(ert-deftest erc-scenarios-base-reconnect-timer () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/reconnect") + (dumb-server (erc-d-run "localhost" t 'timer 'timer 'timer-last)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + (erc-server-auto-reconnect t) + erc-autojoin-channels-alist + erc-server-buffer) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (ert-info ("Server tries to connect thrice (including initial attempt)") + (with-current-buffer erc-server-buffer + (dotimes (n 3) + (ert-info ((format "Attempt %d" n)) + (funcall expect 3 "Opening connection") + (funcall expect 2 "Password incorrect") + (funcall expect 2 "Connection failed!") + (funcall expect 2 "Re-establishing connection"))) + (ert-info ("Prev attempt was final") + (erc-d-t-absent-for 1 "Opening connection" (point))))) + + (ert-info ("Server buffer is unique and temp name is absent") + (should (equal (list (get-buffer (format "127.0.0.1:%d" port))) + (erc-scenarios-common-buflist "127.0.0.1")))))) + +(defun erc-scenarios-common--base-reconnect-options (test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/reconnect") + (dumb-server (erc-d-run "localhost" t 'options 'options-again)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + (erc-server-flood-penalty 0.1) + (erc-server-auto-reconnect t) + erc-autojoin-channels-alist + erc-server-buffer) + + (should (memq 'autojoin erc-modules)) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (funcall expect 10 "debug mode"))) + + (ert-info ("Wait for some output in channels") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan")) + (funcall expect 10 "welcome"))) + + (ert-info ("Server buffer shows connection failed") + (with-current-buffer erc-server-buffer + (funcall expect 10 "Connection failed! Re-establishing"))) + + (should (equal erc-autojoin-channels-alist '(("foonet.org" "#chan")))) + + (funcall test) + + (with-current-buffer "FooNet" (erc-cmd-JOIN "#spam")) + + (erc-d-t-wait-for 5 "Channel #spam shown when autojoined" + (eq (window-buffer) (get-buffer "#spam"))) + + (ert-info ("Wait for auto reconnect") + (with-current-buffer erc-server-buffer + (funcall expect 10 "still in debug mode"))) + + (ert-info ("Wait for activity to recommence in channels") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan")) + (funcall expect 10 "forest of Arden")) + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#spam")) + (funcall expect 10 "her elves come here anon"))))) + +(ert-deftest erc-scenarios-base-reconnect-options--default () + :tags '(:expensive-test) + (should (eq erc-join-buffer 'buffer)) + (should-not erc-reconnect-display) + + ;; FooNet (the server buffer) is not switched to because it's + ;; already current (but not shown) when `erc-open' is called. See + ;; related conditional guard towards the end of that function. + + (erc-scenarios-common--base-reconnect-options + (lambda () + (pop-to-buffer-same-window "*Messages*") + + (erc-d-t-ensure-for 1 "Server buffer not shown" + (not (eq (window-buffer) (get-buffer "FooNet")))) + + (erc-d-t-wait-for 5 "Channel #chan shown when autojoined" + (eq (window-buffer) (get-buffer "#chan")))))) + +(ert-deftest erc-scenarios-base-reconnect-options--bury () + :tags '(:expensive-test) + (should (eq erc-join-buffer 'buffer)) + (should-not erc-reconnect-display) + + (let ((erc-reconnect-display 'bury)) + (erc-scenarios-common--base-reconnect-options + + (lambda () + (pop-to-buffer-same-window "*Messages*") + + (erc-d-t-ensure-for 1 "Server buffer not shown" + (not (eq (window-buffer) (get-buffer "FooNet")))) + + (erc-d-t-ensure-for 3 "Channel #chan not shown" + (not (eq (window-buffer) (get-buffer "#chan")))) + + (eq (window-buffer) (messages-buffer)))))) + +;; Upon reconnecting, playback for channel and target buffers is +;; routed correctly. Autojoin is irrelevant here, but for the +;; skeptical, see `erc-scenarios-common--join-network-id', which +;; overlaps with this and includes spurious JOINs ignored by the +;; server. + +(ert-deftest erc-scenarios-base-association-reconnect-playback () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/assoc/reconplay") + (erc-server-flood-penalty 0.1) + (erc-server-flood-margin 30) + (dumb-server (erc-d-run "localhost" t 'foonet 'again)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + erc-autojoin-channels-alist + erc-server-buffer-foo) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (ert-info ("Setup") + + (ert-info ("Server buffer is unique and temp name is absent") + (erc-d-t-wait-for 3 (get-buffer "foonet")) + (should-not (erc-scenarios-common-buflist "127.0.0.1"))) + + (ert-info ("Channel buffer #chan playback received") + (with-current-buffer (erc-d-t-wait-for 8 (get-buffer "#chan")) + (funcall expect 10 "But purgatory"))) + + (ert-info ("Ask for help from services or bouncer bot") + (with-current-buffer erc-server-buffer-foo + (erc-cmd-MSG "*status help"))) + + (ert-info ("Help received") + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "*status")) + (funcall expect 10 "Rehash"))) + + (ert-info ("#chan convo done") + (with-current-buffer "#chan" + (funcall expect 10 "most egregious indignity")))) + + ;; KLUDGE (see note above test) + (should erc-autojoin-channels-alist) + (setq erc-autojoin-channels-alist nil) + + (with-current-buffer erc-server-buffer-foo + (erc-cmd-QUIT "") + (erc-d-t-wait-for 4 (not (erc-server-process-alive))) + (erc-cmd-RECONNECT)) + + (ert-info ("Channel buffer found and associated") + (with-current-buffer "#chan" + (funcall expect 10 "Wilt thou rest damned"))) + + (ert-info ("Help buffer found and associated") + (with-current-buffer "*status" + (erc-scenarios-common-say "help") + (funcall expect 10 "Restart ZNC"))) + + (ert-info ("#chan convo done") + (with-current-buffer "#chan" + (funcall expect 10 "here comes the lady"))))) + +;;; erc-scenarios-base-reconnect.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-renick.el b/test/lisp/erc/erc-scenarios-base-renick.el new file mode 100644 index 0000000000..bf27f61b3f --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-renick.el @@ -0,0 +1,305 @@ +;;; erc-scenarios-base-renick.el --- Re-nicking scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +;; The server changes your nick just after registration. + +(ert-deftest erc-scenarios-base-renick-self-auto () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/renick/self") + (erc-server-flood-penalty 0.1) + (dumb-server (erc-d-run "localhost" t 'auto)) + (port (process-contact dumb-server :service)) + erc-autojoin-channels-alist + erc-server-buffer-foo) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "foonet")) + (erc-d-t-search-for 10 "Your new nickname is dummy")) + + (ert-info ("Joined by bouncer to #foo, own nick present") + (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo")) + (erc-d-t-search-for 10 "dummy") + (erc-d-t-search-for 10 "On Thursday"))))) + +;; You change your nickname manually in a server buffer; a message is +;; printed in channel buffers. + +(ert-deftest erc-scenarios-base-renick-self-manual () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/renick/self") + (erc-server-flood-penalty 0.1) + (dumb-server (erc-d-run "localhost" t 'manual)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + erc-autojoin-channels-alist + erc-server-buffer-foo) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (erc-d-t-wait-for 3 (get-buffer "foonet")) + + (ert-info ("Joined by bouncer to #foo, own nick present") + (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo")) + (funcall expect 5 "tester") + (funcall expect 5 "On Thursday") + (erc-with-server-buffer (erc-cmd-NICK "dummy")) + (funcall expect 5 "Your new nickname is dummy") + (funcall expect 5 " dummy: Hi") + ;; Regression in which changing a nick would trigger #foo@foonet + (erc-d-t-ensure-for 0.4 (equal (buffer-name) "#foo")))))) + +;; You connect to the same network with two different nicks. You +;; manually change the first nick at some point, and buffer names are +;; updated correctly. + +(ert-deftest erc-scenarios-base-renick-self-qualified () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/renick/self") + (dumb-server (erc-d-run "localhost" t 'qual-tester 'qual-chester)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + (erc-server-flood-penalty 0.1) + (erc-server-flood-margin 30) + erc-serv-buf-a erc-serv-buf-b) + + (ert-info ("Connect to foonet with nick tester") + (with-current-buffer + (setq erc-serv-buf-a (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester")) + (erc-d-t-wait-for 5 (eq erc-network 'foonet)))) + + (ert-info ("Connect to foonet with nick chester") + (with-current-buffer + (setq erc-serv-buf-b (erc :server "127.0.0.1" + :port port + :nick "chester" + :password "changeme" + :full-name "chester")))) + + (erc-d-t-wait-for 3 "Dialed Buflist is Empty" + (not (erc-scenarios-common-buflist "127.0.0.1"))) + + (with-current-buffer "foonet/tester" + (funcall expect 3 "debug mode") + (erc-cmd-JOIN "#chan")) + + (with-current-buffer "foonet/chester" + (funcall expect 3 "debug mode") + (erc-cmd-JOIN "#chan")) + + (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/tester")) + (erc-d-t-wait-for 10 (get-buffer "#chan@foonet/chester")) + + (ert-info ("Greets other nick in same channel") + (with-current-buffer "#chan@foonet/tester" + (funcall expect 5 " chester, welcome!") + (erc-cmd-NICK "dummy") + (funcall expect 5 "Your new nickname is dummy") + (funcall expect 5 "find the forester") + (erc-d-t-wait-for 5 (string= (buffer-name) "#chan@foonet/dummy")))) + + (ert-info ("Renick propagated throughout all buffers of process") + (should-not (get-buffer "#chan@foonet/tester")) + (should-not (get-buffer "foonet/tester")) + (should (get-buffer "foonet/dummy"))))) + +;; When a channel user changes their nick, any query buffers for them +;; are updated. + +(ert-deftest erc-scenarios-base-renick-queries-solo () + :tags '(:expensive-test) + + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/renick/queries") + (erc-server-flood-penalty 0.1) + (erc-server-flood-margin 20) + (dumb-server (erc-d-run "localhost" t 'solo)) + (port (process-contact dumb-server :service)) + erc-autojoin-channels-alist + erc-server-buffer-foo) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (erc-d-t-wait-for 1 (get-buffer "foonet")) + + (ert-info ("Joined by bouncer to #foo, pal persent") + (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo")) + (erc-d-t-search-for 1 "On Thursday") + (erc-scenarios-common-say "hi"))) + + (erc-d-t-wait-for 10 "Query buffer appears with message from pal" + (get-buffer "Lal")) + + (ert-info ("Chat with pal, who changes name") + (with-current-buffer "Lal" + (erc-d-t-search-for 3 "hello") + (erc-scenarios-common-say "hi") + (erc-d-t-search-for 10 "is now known as Linguo") + (should-not (search-forward "is now known as Linguo" nil t)))) + + (erc-d-t-wait-for 1 (get-buffer "Linguo")) + (should-not (get-buffer "Lal")) + + (with-current-buffer "Linguo" (erc-scenarios-common-say "howdy Linguo")) + + (with-current-buffer "#foo" + (erc-d-t-search-for 10 "is now known as Linguo") + (should-not (search-forward "is now known as Linguo" nil t)) + (erc-cmd-PART "")) + + (with-current-buffer "Linguo" + (erc-d-t-search-for 10 "get along")))) + +;; You share a channel and a query buffer with a user on two different +;; networks (through a proxy). The user changes their nick on both +;; networks at the same time. Query buffers are updated accordingly. + +(ert-deftest erc-scenarios-base-renick-queries-bouncer () + :tags '(:expensive-test) + + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/renick/queries") + (erc-server-flood-penalty 0.1) + (erc-server-flood-margin 30) + (dumb-server (erc-d-run "localhost" t 'bouncer-foonet 'bouncer-barnet)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + erc-accidental-paste-threshold-seconds + erc-autojoin-channels-alist + erc-server-buffer-foo + erc-server-buffer-bar) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (erc-d-t-wait-for 5 (get-buffer "foonet")) + + (ert-info ("Connect to barnet") + (setq erc-server-buffer-bar (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "barnet:changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-bar + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (erc-d-t-wait-for 5 (get-buffer "barnet")) + (should-not (erc-scenarios-common-buflist "127.0.0.1")) + + (ert-info ("Joined by bouncer to #chan@foonet, pal persent") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan@foonet")) + (funcall expect 1 "rando") + (funcall expect 1 "simply misused"))) + + (ert-info ("Joined by bouncer to #chan@barnet, pal persent") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan@barnet")) + (funcall expect 1 "rando") + (funcall expect 2 "come, sir, I am"))) + + (ert-info ("Query buffer exists for rando@foonet") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "rando@foonet")) + (funcall expect 1 "guess not") + (erc-scenarios-common-say "I here"))) + + (ert-info ("Query buffer exists for rando@barnet") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "rando@barnet")) + (funcall expect 2 "rentacop") + (erc-scenarios-common-say "Linda said you were gonna kill me."))) + + (ert-info ("Sync convo for rando@foonet") + (with-current-buffer "rando@foonet" + (funcall expect 1 "u are dumb") + (erc-scenarios-common-say "not so"))) + + (ert-info ("Sync convo for rando@barnet") + (with-current-buffer "rando@barnet" + (funcall expect 3 "I never saw her before") + (erc-scenarios-common-say "You aren't with Wage?"))) + + (erc-d-t-wait-for 3 (get-buffer "frenemy@foonet")) + (erc-d-t-wait-for 3 (get-buffer "frenemy@barnet")) + (should-not (get-buffer "rando@foonet")) + (should-not (get-buffer "rando@barnet")) + + (with-current-buffer "frenemy@foonet" + (funcall expect 1 "now known as") + (funcall expect 1 "doubly so")) + + (with-current-buffer "frenemy@barnet" + (funcall expect 1 "now known as") + (funcall expect 1 "reality picture")) + + (when noninteractive + (with-current-buffer "frenemy@barnet" (kill-buffer)) + (erc-d-t-wait-for 2 (get-buffer "frenemy")) + (should-not (get-buffer "frenemy@foonet"))) + + (with-current-buffer "#chan@foonet" + (funcall expect 10 "is now known as frenemy") + (should-not (search-forward "now known as frenemy" nil t)) ; regression + (funcall expect 10 "words are razors")) + + (with-current-buffer "#chan@barnet" + (funcall expect 10 "is now known as frenemy") + (should-not (search-forward "now known as frenemy" nil t)) + (erc-d-t-search-for 25 "I have lost")))) + +;;; erc-scenarios-base-renick.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-reuse-buffers.el b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el new file mode 100644 index 0000000000..2e3ed9969f --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-reuse-buffers.el @@ -0,0 +1,110 @@ +;;; erc-scenarios-base-reuse-buffers.el --- base-reuse-buffers scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +(defun erc-scenarios-common--base-reuse-buffers-server-buffers (&optional more) + "Show that `erc-reuse-buffers' doesn't affect server buffers. +Overlaps some with `clash-of-chans/uniquify'. Adapted from +rebuffed/reuseless, described in Bug#48598: 28.0.50; buffer-naming +collisions involving bouncers in ERC. Run EXTRA." + (erc-scenarios-common-with-cleanup + ((dumb-server (erc-d-run "localhost" t 'foonet 'barnet)) + (port (process-contact dumb-server :service)) + erc-autojoin-channels-alist) + + (ert-info ("Connect to foonet") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester") + (should (string= (buffer-name) + (format "127.0.0.1:%d/127.0.0.1" port))) + (erc-d-t-search-for 12 "marked as being away"))) + + (ert-info ("Connect to barnet") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "barnet:changeme" + :full-name "tester") + (should (string= (buffer-name) + (format "127.0.0.1:%d/127.0.0.1<2>" port))) + (erc-d-t-search-for 45 "marked as being away"))) + + (erc-d-t-wait-for 2 (get-buffer (format "127.0.0.1:%d/127.0.0.1" port))) + (erc-d-t-wait-for 2 (get-buffer (format "127.0.0.1:%d/127.0.0.1<2>" port))) + + (ert-info ("Server buffers are unique, no IP-based names") + (should (cdr (erc-scenarios-common-buflist "127.0.0.1")))) + (when more (funcall more port)))) + +;; XXX maybe remove: already covered many times over by other scenarios +(ert-deftest erc-scenarios-base-reuse-buffers-server-buffers--enabled () + :tags '(:expensive-test) + (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + (should erc-reuse-buffers)) + (let ((erc-scenarios-common-dialog "base/reuse-buffers/server")) + (erc-scenarios-common-with-cleanup + ((dumb-server (erc-d-run "localhost" t 'foonet 'barnet)) + (port (process-contact dumb-server :service)) + erc-autojoin-channels-alist) + + (ert-info ("Connect to foonet") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester") + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (erc-d-t-search-for 12 "marked as being away"))) + + (ert-info ("Connect to barnet") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "barnet:changeme" + :full-name "tester") + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (erc-d-t-search-for 45 "marked as being away"))) + + (erc-d-t-wait-for 2 (get-buffer "foonet")) + (erc-d-t-wait-for 2 (get-buffer "barnet")) + + (ert-info ("Server buffers are unique, no IP-based names") + (should-not (eq (get-buffer "foonet") (get-buffer "barnet"))) + (should-not (erc-scenarios-common-buflist "127.0.0.1")))))) + +;; FIXME no sense in running this twice (JOIN variant includes this) +(ert-deftest erc-scenarios-base-reuse-buffers-server-buffers--disabled () + :tags '(:expensive-test) + (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + (should erc-reuse-buffers) + (let ((erc-scenarios-common-dialog "base/reuse-buffers/server") + erc-reuse-buffers) + (erc-scenarios-common--base-reuse-buffers-server-buffers nil)))) + +;;; erc-scenarios-base-reuse-buffers.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-unstable.el b/test/lisp/erc/erc-scenarios-base-unstable.el new file mode 100644 index 0000000000..2313a15842 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-unstable.el @@ -0,0 +1,134 @@ +;;; erc-scenarios-base-unstable.el --- base unstable scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +;; Not unstable, but stashed here for now + +(ert-deftest erc-scenarios-aux-unix-socket () + :tags '(:expensive-test) + (skip-unless (featurep 'make-network-process '(:family local))) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/renick/self") + (erc-server-flood-penalty 0.1) + (sock (expand-file-name "erc-d.sock" temporary-file-directory)) + (erc-scenarios-common-extra-teardown (lambda () (delete-file sock))) + (erc-server-connect-function + (lambda (n b _ p &rest r) + (apply #'make-network-process + `(:name ,n :buffer ,b :service ,p :family local ,@r)))) + (dumb-server (erc-d-run nil sock 'auto)) + erc-autojoin-channels-alist + erc-server-buffer-foo) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer-foo (erc :server "fake" + :port sock + :nick "tester" + :password "foonet:changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "fake:%s" sock))))) + + (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "foonet")) + (erc-d-t-search-for 10 "Your new nickname is dummy")) + + (ert-info ("Joined by bouncer to #foo, own nick present") + (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#foo")) + (erc-d-t-search-for 10 "dummy") + (erc-d-t-search-for 10 "On Thursday"))))) + +;; See `erc-networks--rename-server-buffer'. A perceived loss in +;; network connectivity turns out to be a false alarm, but the bouncer +;; has already accepted the second connection + +(defun erc-scenarios--base-aborted-reconnect () + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/reconnect") + (erc-d-t-cleanup-sleep-secs 1) + (dumb-server (erc-d-run "localhost" t 'aborted 'aborted-dupe)) + (port (process-contact dumb-server :service)) + erc-autojoin-channels-alist + erc-server-buffer-foo) + + (ert-info ("Connect to foonet") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester")) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "127.0.0.1:%d" port))))) + + (ert-info ("Server buffer is unique and temp name is absent") + (erc-d-t-wait-for 10 (get-buffer "FooNet")) + (should-not (erc-scenarios-common-buflist "127.0.0.1")) + (with-current-buffer erc-server-buffer-foo + (erc-cmd-JOIN "#chan"))) + + (ert-info ("Channel buffer #chan alive and well") + (with-current-buffer (erc-d-t-wait-for 4 (get-buffer "#chan")) + (erc-d-t-search-for 10 "welcome"))) + + (ert-info ("Connect to foonet again") + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester")) + (let ((inhibit-message noninteractive)) + (with-current-buffer erc-server-buffer-foo + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (erc-d-t-wait-for 5 (not (erc-server-process-alive))) + (erc-d-t-search-for 10 "FooNet still connected")))) + + (ert-info ("Server buffer is unique and temp name is absent") + (should (equal (list (get-buffer "FooNet")) + (erc-scenarios-common-buflist "FooNet"))) + (should (equal (list (get-buffer (format "127.0.0.1:%d" port))) + (erc-scenarios-common-buflist "127.0.0.1")))) + + (ert-info ("Channel buffer #chan still going") + (with-current-buffer "#chan" + (erc-d-t-search-for 10 "and be prosperous"))))) + +(ert-deftest erc-scenarios-base-aborted-reconnect () + :tags '(:unstable) + (let ((tries 3) + (timeout 1) + failed) + (while (condition-case _err + (progn + (erc-scenarios--base-aborted-reconnect) + nil) + (ert-test-failed + (message "Test %S failed; %s attempt(s) remaining." + (ert-test-name (ert-running-test)) + tries) + (sleep-for (cl-incf timeout)) + (not (setq failed (zerop (cl-decf tries))))))) + (should-not failed))) + +;;; erc-scenarios-base-unstable.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el new file mode 100644 index 0000000000..5a5b363f31 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-soju.el @@ -0,0 +1,43 @@ +;;; erc-scenarios-upstream-recon-soju.el --- Upstream soju -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;; Commentary: +;; +;; These concern the loss and recovery of a proxy's IRC-side connection. + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-upstream-recon--soju () + :tags '(:expensive-test) + (erc-scenarios-common--upstream-reconnect + (lambda () + (with-current-buffer "foonet" + (erc-d-t-search-for 1 "disconnected from foonet") + (erc-d-t-search-for 1 "connected from foonet")) + (with-current-buffer "barnet" + (erc-d-t-search-for 1 "disconnected from barnet") + (erc-d-t-search-for 1 "connected from barnet"))) + 'soju-foonet + 'soju-barnet)) + +;;; erc-scenarios-upstream-recon-soju.el ends here diff --git a/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el new file mode 100644 index 0000000000..6e9a217245 --- /dev/null +++ b/test/lisp/erc/erc-scenarios-base-upstream-recon-znc.el @@ -0,0 +1,43 @@ +;;; erc-scenarios-upstream-recon-znc.el --- Upstream znc -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;; Commentary: +;; +;; These concern the loss and recovery of a proxy's IRC-side connection. + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(ert-deftest erc-scenarios-upstream-recon--znc () + :tags '(:expensive-test) + (erc-scenarios-common--upstream-reconnect + (lambda () + (with-current-buffer "*status@foonet" + (erc-d-t-search-for 1 "Disconnected from IRC") + (erc-d-t-search-for 1 "Connected!")) + (with-current-buffer "*status@barnet" + (erc-d-t-search-for 1 "Disconnected from IRC") + (erc-d-t-search-for 1 "Connected!"))) + 'znc-foonet + 'znc-barnet)) + +;;; erc-scenarios-upstream-recon-znc.el ends here diff --git a/test/lisp/erc/erc-scenarios-misc.el b/test/lisp/erc/erc-scenarios-misc.el new file mode 100644 index 0000000000..86cfa8b10b --- /dev/null +++ b/test/lisp/erc/erc-scenarios-misc.el @@ -0,0 +1,107 @@ +;;; erc-scenarios-misc.el --- Misc scenarios for ERC -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join)) + +(ert-deftest erc-scenarios-base-flood () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/flood") + (dumb-server (erc-d-run "localhost" t 'soju)) + (port (process-contact dumb-server :service)) + (erc-server-flood-penalty 0.5) ; this ratio MUST match + (erc-server-flood-margin 1.5) ; the default of 3:10 + (expect (erc-d-t-make-expecter)) + erc-autojoin-channels-alist) + + (ert-info ("Connect to bouncer") + (with-current-buffer + (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "changeme" + :full-name "tester") + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (funcall expect 5 "Soju"))) + + (ert-info ("#chan@foonet exists") + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan/foonet")) + (erc-d-t-search-for 2 "") + (erc-d-t-absent-for 0.1 "") + (erc-d-t-absent-for 0.1 ". + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (ert-resource-directory) load-path))) + (require 'erc-scenarios-common))) + +(eval-when-compile (require 'erc-join) + (require 'erc-services)) + +(ert-deftest erc-scenarios-services-password () + :tags '(:expensive-test) + + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "services/password") + (erc-server-flood-penalty 0.1) + (erc-modules (cons 'services erc-modules)) + (erc-nickserv-passwords '((Libera.Chat (("joe" . "bar") + ("tester" . "changeme"))))) + (expect (erc-d-t-make-expecter)) + (dumb-server (erc-d-run "localhost" t 'libera)) + (port (process-contact dumb-server :service))) + + (ert-info ("Connect without password") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :full-name "tester") + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (erc-d-t-wait-for 5 (eq erc-network 'Libera.Chat)) + (funcall expect 5 "This nickname is registered.") + (funcall expect 2 "You are now identified") + (funcall expect 1 "Last login from") + (erc-cmd-QUIT ""))) + + (erc-services-mode -1) + + (should-not (memq 'services erc-modules)))) + +(ert-deftest erc-scenarios-services-prompt () + :tags '(:expensive-test) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "services/password") + (erc-server-flood-penalty 0.1) + (inhibit-interaction nil) + (erc-modules (cons 'services erc-modules)) + (expect (erc-d-t-make-expecter)) + (dumb-server (erc-d-run "localhost" t 'libera)) + (port (process-contact dumb-server :service))) + + (ert-info ("Connect without password") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :full-name "tester") + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + (ert-simulate-keys "changeme\r" + (erc-d-t-wait-for 10 (eq erc-network 'Libera.Chat)) + (funcall expect 3 "This nickname is registered.") + (funcall expect 3 "You are now identified") + (funcall expect 3 "Last login from")) + (erc-cmd-QUIT ""))) + + (erc-services-mode -1) + + (should-not (memq 'services erc-modules)))) + +;;; erc-scenarios-services-misc.el ends here diff --git a/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld b/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld new file mode 100644 index 0000000000..4b6ccfff38 --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/bouncer-history/barnet.eld @@ -0,0 +1,44 @@ +;; -*- mode: lisp-data; -*- +((pass 3 "PASS :barnet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Wed, 28 Apr 2021 06:59:59 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + ;; No mode answer ^ + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester") + (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:25] mike: Belike, for joy the emperor hath a son.") + (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:27] joe: Protest their first of manhood.") + (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:29] mike: As frozen water to a starved snake.") + (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:34] joe: My mirth it much displeas'd, but pleas'd my woe.") + (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:38] mike: Why, Marcus, no man should be mad but I.") + (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:44] joe: Faith, I have heard too much, for your words and performances are no kin together.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0 ":irc.barnet.org NOTICE tester :[07:00:01] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.barnet.org 305 tester :You are no longer marked as being away")) + +((mode 6 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1619593200") + (0.25 ":joe!~u@svpn88yjcdj42.irc PRIVMSG #chan :mike: But, in defence, by mercy, 'tis most just.") + (0.25 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: The Marshal of France, Monsieur la Far.") + (0.25 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.") + (0.25 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: Madam, within; but never man so chang'd.") + (0.25 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: As much in private, and I'll bid adieu.")) diff --git a/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld b/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld new file mode 100644 index 0000000000..58df79e19f --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/bouncer-history/foonet.eld @@ -0,0 +1,48 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Wed, 28 Apr 2021 07:00:00 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + ;; No mode answer ^ + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@nvfhxvqm92rm6.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester") + (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:02] alice: Here come the lovers, full of joy and mirth.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:07] bob: According to the fool's bolt, sir, and such dulcet diseases.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:10] alice: And hang himself. I pray you, do my greeting.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:18] bob: And you sat smiling at his cruel prey.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:21] alice: Or never after look me in the face.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:25] bob: If that may be, than all is well. Come, sit down, every mother's son, and rehearse your parts. Pyramus, you begin: when you have spoken your speech, enter into that brake; and so every one according to his cue.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:30] alice: Where I espied the panther fast asleep.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:32] bob: Alas! he is too young: yet he looks successfully.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:37] alice: Here, at your lordship's service.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:42] bob: By my troth, and in good earnest, and so God mend me, and by all pretty oaths that are not dangerous, if you break one jot of your promise or come one minute behind your hour, I will think you the most pathetical break-promise, and the most hollow lover, and the most unworthy of her you call Rosalind, that may be chosen out of the gross band of the unfaithful. Therefore, beware my censure, and keep your promise.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0 ":irc.foonet.org NOTICE tester :[07:00:32] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((mode 6 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1619593200") + (0.9 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: Grows, lives, and dies, in single blessedness.") + (0.25 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: For these two hours, Rosalind, I will leave thee.") + (0.25 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.") + (0.25 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: That I must love a loathed enemy.") + (0.25 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: As't please your lordship: I'll leave you.")) diff --git a/test/lisp/erc/resources/base/assoc/bumped/again.eld b/test/lisp/erc/resources/base/assoc/bumped/again.eld new file mode 100644 index 0000000000..ab3c7b0621 --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/bumped/again.eld @@ -0,0 +1,30 @@ +;; -*- mode: lisp-data; -*- +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.0 ":irc.foonet.org 433 * tester :Nickname is reserved by a different account") + (0.0 ":irc.foonet.org FAIL NICK NICKNAME_RESERVED tester :Nickname is reserved by a different account")) + +((nick 3 "NICK tester`") + (0.1 ":irc.foonet.org 001 tester` :Welcome to the foonet IRC Network tester`") + (0.0 ":irc.foonet.org 002 tester` :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5") + (0.0 ":irc.foonet.org 003 tester` :This server was created Fri, 24 Sep 2021 01:38:36 UTC") + (0.0 ":irc.foonet.org 004 tester` irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.0 ":irc.foonet.org 005 tester` AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.1 ":irc.foonet.org 005 tester` MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.1 ":irc.foonet.org 005 tester` draft/CHATHISTORY=100 :are supported by this server") + (0.0 ":irc.foonet.org 251 tester` :There are 0 users and 3 invisible on 1 server(s)") + (0.0 ":irc.foonet.org 252 tester` 0 :IRC Operators online") + (0.0 ":irc.foonet.org 253 tester` 0 :unregistered connections") + (0.0 ":irc.foonet.org 254 tester` 1 :channels formed") + (0.0 ":irc.foonet.org 255 tester` :I have 3 clients and 0 servers") + (0.0 ":irc.foonet.org 265 tester` 3 3 :Current local users 3, max 3") + (0.2 ":irc.foonet.org 266 tester` 3 3 :Current global users 3, max 3") + (0.0 ":irc.foonet.org 422 tester` :MOTD File is missing")) + +((mode-user 3.2 "MODE tester` +i") + (0.0 ":irc.foonet.org 221 tester` +i") + (0.0 ":irc.foonet.org NOTICE tester` :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((privmsg 42.6 "PRIVMSG NickServ :IDENTIFY tester changeme") + (0.01 ":tester`!~u@rpaau95je67ci.irc NICK tester") + (0.0 ":NickServ!NickServ@localhost NOTICE tester :You're now logged in as tester")) diff --git a/test/lisp/erc/resources/base/assoc/bumped/foisted.eld b/test/lisp/erc/resources/base/assoc/bumped/foisted.eld new file mode 100644 index 0000000000..5c36e58d9d --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/bumped/foisted.eld @@ -0,0 +1,30 @@ +;; -*- mode: lisp-data; -*- +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5") + (0.0 ":irc.foonet.org 003 tester :This server was created Fri, 24 Sep 2021 01:38:36 UTC") + (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0.0 ":irc.foonet.org 254 tester 1 :channels formed") + (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0.0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0.0 ":irc.foonet.org 221 tester +i") + (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((privmsg 17.21 "PRIVMSG bob :hi") + (0.02 ":bob!~u@ecnnh95wr67pv.net PRIVMSG tester :hola") + (0.01 ":bob!~u@ecnnh95wr67pv.net PRIVMSG tester :how r u?")) + +((quit 18.19 "QUIT :" quit) + (0.01 ":tester!~u@rpaau95je67ci.irc QUIT :Quit: " quit)) +((drop 1 DROP)) diff --git a/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld b/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld new file mode 100644 index 0000000000..33e4168ac4 --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/bumped/refoisted.eld @@ -0,0 +1,31 @@ +;; -*- mode: lisp-data; -*- +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.1 ":irc.foonet.org 001 dummy :Welcome to the foonet IRC Network dummy") + (0.0 ":irc.foonet.org 002 dummy :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5") + (0.0 ":irc.foonet.org 003 dummy :This server was created Fri, 24 Sep 2021 01:38:36 UTC") + (0.0 ":irc.foonet.org 004 dummy irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.0 ":irc.foonet.org 005 dummy AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.1 ":irc.foonet.org 005 dummy MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.1 ":irc.foonet.org 005 dummy draft/CHATHISTORY=100 :are supported by this server") + (0.0 ":irc.foonet.org 251 dummy :There are 0 users and 3 invisible on 1 server(s)") + (0.0 ":irc.foonet.org 252 dummy 0 :IRC Operators online") + (0.0 ":irc.foonet.org 253 dummy 0 :unregistered connections") + (0.0 ":irc.foonet.org 254 dummy 1 :channels formed") + (0.0 ":irc.foonet.org 255 dummy :I have 3 clients and 0 servers") + (0.0 ":irc.foonet.org 265 dummy 3 3 :Current local users 3, max 3") + (0.2 ":irc.foonet.org 266 dummy 3 3 :Current global users 3, max 3") + ;; Could arrive anytime around this point + (0.0 ":tester!~u@rpaau95je67ci.irc NICK :dummy") + (0.0 ":irc.foonet.org 422 dummy :MOTD File is missing") + ;; Playback + (0.01 ":bob!~u@ecnnh95wr67pv.net PRIVMSG dummy :back?") + ) + +((mode-user 1.2 "MODE dummy +i") + (0.0 ":irc.foonet.org 221 dummy +i") + (0.0 ":irc.foonet.org NOTICE dummy :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((renick 42.6 "NICK tester") + (0.01 ":dummy!~u@rpaau95je67ci.irc NICK tester") + (0.0 ":NickServ!NickServ@localhost NOTICE dummy :You're now logged in as tester")) diff --git a/test/lisp/erc/resources/base/assoc/bumped/renicked.eld b/test/lisp/erc/resources/base/assoc/bumped/renicked.eld new file mode 100644 index 0000000000..4e96fd7304 --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/bumped/renicked.eld @@ -0,0 +1,30 @@ +;; -*- mode: lisp-data; -*- +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.1-937b9b02368748e5") + (0.0 ":irc.foonet.org 003 tester :This server was created Fri, 24 Sep 2021 01:38:36 UTC") + (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.1-937b9b02368748e5 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0.0 ":irc.foonet.org 254 tester 1 :channels formed") + (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0.0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 12 "MODE tester +i") + (0.0 ":irc.foonet.org 221 tester +i") + (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((privmsg 17.21 "PRIVMSG NickServ :REGISTER changeme") + (0.02 ":NickServ!NickServ@localhost NOTICE tester :Account created") + (0.01 ":NickServ!NickServ@localhost NOTICE tester :You're now logged in as tester")) + +((quit 18.19 "QUIT :" quit) + (0.01 ":tester!~u@rpaau95je67ci.irc QUIT :Quit: " quit)) +((drop 1 DROP)) diff --git a/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld b/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld new file mode 100644 index 0000000000..c62a22a11c --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/multi-net/barnet.eld @@ -0,0 +1,42 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Tue, 04 May 2021 05:06:19 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 253 tester 0 :unregistered connections") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 8 "MODE tester +i") + (0 ":irc.barnet.org 221 tester +i") + (0 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 2 "JOIN #chan") + (0 ":tester!~u@jnu48g2wrycbw.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :@mike joe tester") + (0 ":irc.barnet.org 366 tester #chan :End of NAMES list")) + +((mode 2 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1620104779") + (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: Whipp'd first, sir, and hang'd after.") + (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: We have yet many among us can gripe as hard as Cassibelan; I do not say I am one, but I have a hand. Why tribute ? why should we pay tribute ? If C sar can hide the sun from us with a blanket, or put the moon in his pocket, we will pay him tribute for light; else, sir, no more tribute, pray you now.") + (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: Double and treble admonition, and still forfeit in the same kind ? This would make mercy swear, and play the tyrant.") + (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: And secretly to greet the empress' friends.") + (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: You have not been inquired after: I have sat here all day.") + (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: That same Berowne I'll torture ere I go.") + (0.1 ":mike!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :joe: For mine own part,no offence to the general, nor any man of quality,I hope to be saved.") + (0.1 ":joe!~u@kd7gmjbnbkn8c.irc PRIVMSG #chan :mike: Mehercle! if their sons be ingenuous, they shall want no instruction; if their daughters be capable, I will put it to them. But, vir sapit qui pauca loquitur. A soul feminine saluteth us.")) diff --git a/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld b/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld new file mode 100644 index 0000000000..f30b7deca1 --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/multi-net/foonet.eld @@ -0,0 +1,45 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 8 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 2 "JOIN #chan") + (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((mode 2 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow.")) diff --git a/test/lisp/erc/resources/base/assoc/reconplay/again.eld b/test/lisp/erc/resources/base/assoc/reconplay/again.eld new file mode 100644 index 0000000000..4210c07e41 --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/reconplay/again.eld @@ -0,0 +1,42 @@ +;; -*- mode: lisp-data; -*- +((pass 4.0 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0.0 ":irc.foonet.org 003 tester :This server was created Wed, 16 Jun 2021 04:15:00 UTC") + (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0.0 ":irc.foonet.org 254 tester 1 :channels formed") + (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0.0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 10 "MODE tester +i") + ;; No mode answer + (0.0 ":tester!~u@mw6kegwt77kwe.irc JOIN #chan") + (0.0 ":irc.foonet.org 353 tester = #chan :alice @bob tester") + (0.0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.") + (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:52] bob: Thou pout'st upon thy fortune and thy love.") + (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:56] alice: With these mortals on the ground.") + (0.0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.")) + +((mode 10 "MODE #chan") + (0.0 ":irc.foonet.org 324 tester #chan +nt") + (0.0 ":irc.foonet.org 329 tester #chan 1623816901") + (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: My name, my good lord, is Parolles.") + (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: Wilt thou rest damned ? God help thee, shallow man! God make incision in thee! thou art raw.")) + +((privmsg 3.0 "PRIVMSG *status :help") + (0.0 ":*status!znc@znc.in PRIVMSG tester :In the following list all occurrences of <#chan> support wildcards (* and ?) except ListNicks") + (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Version\17: Print which version of ZNC this is") + (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Shutdown [message]\17: Shut down ZNC completely") + (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Restart [message]\17: Restart ZNC") + (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: In that word's death; no words can that woe sound.") + (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: Look, sir, here comes the lady towards my cell.")) diff --git a/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld b/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld new file mode 100644 index 0000000000..6f50ecca4e --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/reconplay/foonet.eld @@ -0,0 +1,52 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0.0 ":irc.foonet.org 003 tester :This server was created Wed, 16 Jun 2021 04:15:00 UTC") + (0.0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0.0 ":irc.foonet.org 254 tester 1 :channels formed") + (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0.0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 5 "MODE tester +i") + ;; No mode answer + (0.0 ":irc.znc.in 306 tester :You have been marked as being away") + (0.0 ":tester!~u@mw6kegwt77kwe.irc JOIN #chan") + (0.0 ":irc.foonet.org 353 tester = #chan :alice @bob tester") + (0.0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.") + (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:35:50] bob: To Laced mon did my land extend.") + (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:35:55] alice: This is but a custom in your tongue; you bear a graver purpose, I hope.") + (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:16] bob: To imitate them; faults that are rich are fair.") + (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:18] alice: Our Romeo hath not been in bed to-night.") + (0.0 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:21] bob: But, in defence, by mercy, 'tis most just.") + (0.0 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :[10:37:25] alice: Younger than she are happy mothers made.") + (0.0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0.0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((mode 3 "MODE #chan") + (1.0 ":irc.foonet.org 324 tester #chan +nt") + (0.0 ":irc.foonet.org 329 tester #chan 1623816901") + (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: At thy good heart's oppression.") + (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: But purgatory, torture, hell itself.")) + +((privmsg 3 "PRIVMSG *status :help") + (0.0 ":*status!znc@znc.in PRIVMSG tester :In the following list all occurrences of <#chan> support wildcards (* and ?) except ListNicks") + (0.0 ":*status!znc@znc.in PRIVMSG tester :\2AddPort <[+]port> [bindhost [uriprefix]]\17: Add another port for ZNC to listen on") + (0.0 ":*status!znc@znc.in PRIVMSG tester :\2DelPort [bindhost]\17: Remove a port from ZNC") + (0.0 ":*status!znc@znc.in PRIVMSG tester :\2Rehash\17: Reload global settings, modules, and listeners from znc.conf") + (0.1 ":alice!~u@mw6kegwt77kwe.irc PRIVMSG #chan :bob: And at my suit, sweet, pardon what is past.") + (0.1 ":bob!~u@mw6kegwt77kwe.irc PRIVMSG #chan :alice: My lord, you give me most egregious indignity.")) + +((quit 2 "QUIT :\2ERC\2")) + +((drop 0 DROP)) diff --git a/test/lisp/erc/resources/base/assoc/samenet/chester.eld b/test/lisp/erc/resources/base/assoc/samenet/chester.eld new file mode 100644 index 0000000000..f1aed2836c --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/samenet/chester.eld @@ -0,0 +1,40 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK chester")) +((user 1 "USER user 0 * :chester") + (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester") + (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC") + (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 chester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 chester 1 :unregistered connections") + (0 ":irc.foonet.org 254 chester 1 :channels formed") + (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4") + (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4") + (0 ":irc.foonet.org 422 chester :MOTD File is missing")) + +((mode-user 12 "MODE chester +i") + (0 ":irc.foonet.org 221 chester +i") + (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob") + (0 ":irc.foonet.org 366 chester #chan :End of NAMES list") + (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((mode 10 "MODE #chan") + (0.0 ":irc.foonet.org 324 chester #chan +nt") + (0.0 ":irc.foonet.org 329 chester #chan 1623563121") + (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.") + (0.0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit) + (0.5 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!")) + +((quit 20 "QUIT :" quit) + (0.0 ":chester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit)) diff --git a/test/lisp/erc/resources/base/assoc/samenet/tester.eld b/test/lisp/erc/resources/base/assoc/samenet/tester.eld new file mode 100644 index 0000000000..cd9cacbe5d --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/samenet/tester.eld @@ -0,0 +1,42 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4") + (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 12 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 15 "JOIN #chan") + (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((mode 10 "MODE #chan") + (0.0 ":irc.foonet.org 324 tester #chan +nt") + (0.0 ":irc.foonet.org 329 tester #chan 1623563121") + (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!") + (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!") + (0.0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.")) + +((quit 4 "QUIT ")) + +((drop 0 DROP)) diff --git a/test/lisp/erc/resources/base/assoc/samenet/tester2.eld b/test/lisp/erc/resources/base/assoc/samenet/tester2.eld new file mode 100644 index 0000000000..67c3a94a26 --- /dev/null +++ b/test/lisp/erc/resources/base/assoc/samenet/tester2.eld @@ -0,0 +1,39 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4") + (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 4.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob chester") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((~useless-join 10 "JOIN #chan")) + +((mode 10 "MODE #chan") + (0.0 ":irc.foonet.org 324 tester #chan +nt") + (0.0 ":irc.foonet.org 329 tester #chan 1623563121") + (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!") + (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome again!")) + +((quit 4 "QUIT :" quit) + (0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit)) + +((linger 5 LINGER)) diff --git a/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld b/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld new file mode 100644 index 0000000000..b09692327c --- /dev/null +++ b/test/lisp/erc/resources/base/channel-buffer-revival/foonet.eld @@ -0,0 +1,45 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 12 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 6 "JOIN #chan") + (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((mode 8 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow.")) diff --git a/test/lisp/erc/resources/base/flood/soju.eld b/test/lisp/erc/resources/base/flood/soju.eld new file mode 100644 index 0000000000..05266ca941 --- /dev/null +++ b/test/lisp/erc/resources/base/flood/soju.eld @@ -0,0 +1,87 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.13 ":soju.im 001 tester :Welcome to soju, tester") + (0.0 ":soju.im 002 tester :Your host is soju.im") + (0.0 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI") + (0.0 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii NETWORK=Soju :are supported") + (0.0 ":soju.im 422 tester :No MOTD")) + +((mode 1 "MODE tester +i") + (0.0 ":tester!tester@10.0.2.100 JOIN #chan/foonet") + (0.25 ":soju.im 331 tester #chan/foonet :No topic is set") + (0.0 ":soju.im 353 tester = #chan/foonet :@bob/foonet alice/foonet tester") + (0.01 ":soju.im 366 tester #chan/foonet :End of /NAMES list") + (0.0 ":tester!tester@10.0.2.100 JOIN #chan/barnet") + (0.04 ":soju.im 331 tester #chan/barnet :No topic is set") + (0.0 ":soju.im 353 tester = #chan/barnet :tester @mike/barnet joe/barnet") + (0.01 ":soju.im 366 tester #chan/barnet :End of /NAMES list") + (0.01 ":bob/foonet PRIVMSG #chan/foonet :alice: Then this breaking of his has been but a try for his friends.") + (0.16 ":alice/foonet PRIVMSG #chan/foonet :bob: By my troth, I take my young lord to be a very melancholy man.") + (0.91 ":bob/foonet PRIVMSG #chan/foonet :alice: No, truly, for the truest poetry is the most feigning; and lovers are given to poetry, and what they swear in poetry may be said as lovers they do feign.") + (0.01 ":alice/foonet PRIVMSG #chan/foonet :bob: Sir, his wife some two months since fled from his house: her pretence is a pilgrimage to Saint Jaques le Grand; which holy undertaking with most austere sanctimony she accomplished; and, there residing, the tenderness of her nature became as a prey to her grief; in fine, made a groan of her last breath, and now she sings in heaven.") + (0.0 ":mike/barnet PRIVMSG #chan/barnet :joe: Who ? not the duke ? yes, your beggar of fifty, and his use was to put a ducat in her clack-dish; the duke had crotchets in him. He would be drunk too; that let me inform you.") + (0.01 ":joe/barnet PRIVMSG #chan/barnet :mike: Prove it before these varlets here, thou honourable man, prove it.") + (0.0 ":mike/barnet PRIVMSG #chan/barnet :joe: That my report is just and full of truth.") + (0.0 ":joe/barnet PRIVMSG #chan/barnet :mike: It is impossible they bear it out.") + ;; Expected, since we blindly send +i + (0.0 ":soju.im 501 tester :Cannot change user mode in multi-upstream mode")) + +((~mode-foonet 5 "MODE #chan/foonet") + (0.0 ":soju.im 324 tester #chan/foonet +nt") + (0.16 ":soju.im 329 tester #chan/foonet 1647158643") + ;; Start frantic pinging + (0.0 "PING :soju-msgid-1")) + +((~mode-barnet 5 "MODE #chan/barnet") + (0.0 ":soju.im 324 tester #chan/barnet +nt") + (0.0 ":soju.im 329 tester #chan/barnet 1647158643")) + +((pong-1 5 "PONG :soju-msgid-1") + (0.0 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: The king's coming; I know by his trumpets. Sirrah, inquire further after me; I had talk of you last night: though you are a fool and a knave, you shall eat: go to, follow.") + (0.0 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: Up: so. How is 't ? Feel you your legs ? You stand.") + (0.0 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: Consider then we come but in despite.") + (0.1 "PING :soju-msgid-2")) + +((pong-2 2 "PONG :soju-msgid-2") + (0.1 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: All hail, Macbeth! that shalt be king hereafter.") + (0.1 "PING :soju-msgid-3")) + +((pong-3 2 "PONG :soju-msgid-3") + (0.1 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: And that at my bidding you could so stand up.") + (0.1 "PING :soju-msgid-4")) + +((pong-4 2 "PONG :soju-msgid-4") + (0.03 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: Now he tells how she plucked him to my chamber. O! I see that nose of yours, but not the dog I shall throw it to.") + (0.1 "PING :soju-msgid-5")) + +((pong-5 2 "PONG :soju-msgid-5") + (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: For policy sits above conscience.") + (0.1 "PING :soju-msgid-6")) + +((pong-6 2 "PONG :soju-msgid-6") + (0.0 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: Take heed o' the foul fiend. Obey thy parents; keep thy word justly; swear not; commit not with man's sworn spouse; set not thy sweet heart on proud array. Tom's a-cold.") + (0.1 "PING :soju-msgid-7")) + +((pong-7 2 "PONG :soju-msgid-7") + (0.08 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: To suffer with him. Good love, call him back.") + (0.1 "PING :soju-msgid-8")) + +((pong-9 2 "PONG :soju-msgid-8") + (0.1 ":bob/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :alice: Be not obdurate, open thy deaf ears.") + (0.0 "PING :soju-msgid-9")) + +((pong-10 2 "PONG :soju-msgid-9") + (0.04 ":joe/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :mike: To get good guard and go along with me.") + (0.1 "PING :soju-msgid-10")) + +((~privmsg 2 "PRIVMSG #chan/foonet :alice: hi") + (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :tester: Good, very good; it is so then: good, very good. Let it be concealed awhile.")) + +((pong-11 2 "PONG :soju-msgid-10") + (0.1 ":alice/foonet!~u@g56t7uz8xjj4e.irc PRIVMSG #chan/foonet :bob: Some man or other must present Wall; and let him have some plaster, or some loam, or some rough-cast about him, to signify wall; and let him hold his fingers thus, and through that cranny shall Pyramus and Thisby whisper.") + (0.0 "PING :soju-msgid-11")) + +((pong-12 5 "PONG :soju-msgid-11") + (0.1 ":mike/barnet!~u@qsidzk5cytcai.irc PRIVMSG #chan/barnet :joe: That's he that was Othello; here I am.")) diff --git a/test/lisp/erc/resources/base/gapless-connect/barnet.eld b/test/lisp/erc/resources/base/gapless-connect/barnet.eld new file mode 100644 index 0000000000..4e658802ef --- /dev/null +++ b/test/lisp/erc/resources/base/gapless-connect/barnet.eld @@ -0,0 +1,40 @@ +;; -*- mode: lisp-data; -*- +((pass 10 "PASS :barnet:changeme")) +((nick 10 "NICK tester")) +((user 0.2 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.5.1-4860c5cad0179db1") + (0 ":irc.barnet.org 003 tester :This server was created Fri, 19 Mar 2021 10:23:19 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.5.1-4860c5cad0179db1 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 MAXLIST=beI:60 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 1 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 0 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 1 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 1 1 :Current local users 1, max 1") + (0 ":irc.barnet.org 266 tester 1 1 :Current global users 1, max 1") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@8cgjyczyrjgby.irc JOIN #bar") + (0 ":irc.barnet.org 353 tester = #bar :@mike joe tester") + (0 ":irc.barnet.org 366 tester #bar :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #bar :Buffer Playback...") + (0 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:23:28] tester, welcome!") + (0 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:23:28] tester, welcome!") + (0 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:24:49] mike: Bid me farewell, and let me hear thee going.") + (0 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :[10:24:54] joe: By heaven, thy love is black as ebony.") + (0 ":***!znc@znc.in PRIVMSG #bar :Playback Complete.") + (0 ":irc.barnet.org NOTICE tester :[10:23:22] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.barnet.org 305 tester :You are no longer marked as being away")) + +((mode 20 "MODE #bar") + (0 ":irc.barnet.org 324 tester #bar +nt") + (0 ":irc.barnet.org 329 tester #bar 1616149403") + (0.1 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :joe: To ask of whence you are: report it.") + (0.1 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :mike: Friar, thou knowest not the duke so well as I do: he's a better woodman than thou takest him for.") + (0.1 ":mike!~u@8cgjyczyrjgby.irc PRIVMSG #bar :joe: Like the sequel, I. Signior Costard, adieu.") + (0.1 ":joe!~u@8cgjyczyrjgby.irc PRIVMSG #bar :mike: This is his second fit; he had one yesterday.")) diff --git a/test/lisp/erc/resources/base/gapless-connect/foonet.eld b/test/lisp/erc/resources/base/gapless-connect/foonet.eld new file mode 100644 index 0000000000..4ac4a3e596 --- /dev/null +++ b/test/lisp/erc/resources/base/gapless-connect/foonet.eld @@ -0,0 +1,41 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #foo") + (0 ":irc.foonet.org 353 tester = #foo :joe @mike tester") + (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:02:41] bob: To-morrow is the joyful day, Audrey; to-morrow will we be married.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:02:44] alice: Why dost thou call them knaves ? thou know'st them not.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:03:05] bob: Now, by the faith of my love, I will: tell me where it is.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :[07:03:09] alice: Give me the letter; I will look on it.") + (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.") + (0 ":irc.foonet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((mode 8 "MODE #foo") + (0 ":irc.foonet.org 324 tester #foo +nt") + (0 ":irc.foonet.org 329 tester #foo 1619593200") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: As living here and you no use of him.")) diff --git a/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld b/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld new file mode 100644 index 0000000000..0c8dfd19d0 --- /dev/null +++ b/test/lisp/erc/resources/base/gapless-connect/pass-stub.eld @@ -0,0 +1,4 @@ +;; -*- mode: lisp-data; -*- +((pass 3 "PASS :" token ":changeme")) + +((fake 1 "FAKE no op")) diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld new file mode 100644 index 0000000000..766035a524 --- /dev/null +++ b/test/lisp/erc/resources/base/netid/bouncer/barnet-again.eld @@ -0,0 +1,50 @@ +;; -*- mode: lisp-data; -*- +((pass 10 "PASS :barnet:changeme")) +((nick 3 "NICK tester")) +((user 3 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer ^ + + (0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :joe @mike tester") + (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:25] mike: Belike, for joy the emperor hath a son.") + (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:27] joe: Protest their first of manhood.") + (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:29] mike: As frozen water to a starved snake.") + (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:34] joe: My mirth it much displeas'd, but pleas'd my woe.") + (0 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:38] mike: Why, Marcus, no man should be mad but I.") + (0 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :[07:04:44] joe: Faith, I have heard too much, for your words and performances are no kin together.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0 ":irc.barnet.org NOTICE tester :[07:00:01] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":irc.barnet.org 305 tester :You are no longer marked as being away")) + +((~join 3 "JOIN #chan")) + +((mode 5 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1620805269") + (0.1 ":joe!~u@svpn88yjcdj42.irc PRIVMSG #chan :mike: But, in defence, by mercy, 'tis most just.") + (0.1 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: The Marshal of France, Monsieur la Far.") + (0.1 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.") + (0.1 ":mike!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :joe: Madam, within; but never man so chang'd.") + (0.1 ":joe!~u@xrir8fpe4d7ak.irc PRIVMSG #chan :mike: As much in private, and I'll bid adieu.")) + +((linger 10 LINGER)) diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld new file mode 100644 index 0000000000..2c3d297b9c --- /dev/null +++ b/test/lisp/erc/resources/base/netid/bouncer/barnet-drop.eld @@ -0,0 +1,41 @@ +;; -*- mode: lisp-data; -*- +((pass 10 "PASS :barnet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer ^ + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":irc.barnet.org 305 tester :You are no longer marked as being away")) + +((join 1 "JOIN #chan") + (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester") + (0 ":irc.barnet.org 366 tester #chan :End of NAMES list") + (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!") + (0 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!")) + +((mode 1 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1620805269") + (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: But you have outfaced them all.") + (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Why, will shall break it; will, and nothing else.") + (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: Yes, a dozen; and as many to the vantage, as would store the world they played for.") + (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: As he regards his aged father's life.") + (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it.")) + +((drop 0 DROP)) diff --git a/test/lisp/erc/resources/base/netid/bouncer/barnet.eld b/test/lisp/erc/resources/base/netid/bouncer/barnet.eld new file mode 100644 index 0000000000..abfcc6ed48 --- /dev/null +++ b/test/lisp/erc/resources/base/netid/bouncer/barnet.eld @@ -0,0 +1,41 @@ +;; -*- mode: lisp-data; -*- +((pass 3 "PASS :barnet:changeme")) +((nick 3 "NICK tester")) +((user 3 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer ^ + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":irc.barnet.org 305 tester :You are no longer marked as being away")) + +((join 1 "JOIN #chan") + (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :@joe mike tester") + (0 ":irc.barnet.org 366 tester #chan :End of NAMES list") + (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!") + (0 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :tester, welcome!")) + +((mode 3 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1620805269") + (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: But you have outfaced them all.") + (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Why, will shall break it; will, and nothing else.") + (0.1 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: Yes, a dozen; and as many to the vantage, as would store the world they played for.") + (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: As he regards his aged father's life.") + (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it.")) + +((linger 1 LINGER)) diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld new file mode 100644 index 0000000000..bf8712305a --- /dev/null +++ b/test/lisp/erc/resources/base/netid/bouncer/foonet-again.eld @@ -0,0 +1,50 @@ +;; -*- mode: lisp-data; -*- +((pass 10 "PASS :foonet:changeme")) +((nick 3 "NICK tester")) +((user 3 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer ^ + (0 ":tester!~u@nvfhxvqm92rm6.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice @bob tester") + (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:02] alice: Here come the lovers, full of joy and mirth.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:07] bob: According to the fool's bolt, sir, and such dulcet diseases.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:10] alice: And hang himself. I pray you, do my greeting.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:18] bob: And you sat smiling at his cruel prey.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:21] alice: Or never after look me in the face.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:25] bob: If that may be, than all is well. Come, sit down, every mother's son, and rehearse your parts. Pyramus, you begin: when you have spoken your speech, enter into that brake; and so every one according to his cue.") + (0 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:30] alice: Where I espied the panther fast asleep.") + (0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :[07:04:32] bob: Alas! he is too young: yet he looks successfully.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + + (0 ":irc.foonet.org NOTICE tester :[07:00:32] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((~join 3 "JOIN #chan")) + +((mode 8 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620805271") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: Grows, lives, and dies, in single blessedness.") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: For these two hours, Rosalind, I will leave thee.") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #chan :alice: That I must love a loathed enemy.") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: As't please your lordship: I'll leave you.")) + +((linger 10 LINGER)) diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld new file mode 100644 index 0000000000..e3c41e2133 --- /dev/null +++ b/test/lisp/erc/resources/base/netid/bouncer/foonet-drop.eld @@ -0,0 +1,46 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer ^ + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((join 1 "JOIN #chan") + (0 ":tester!~u@ertp7idh9jtgi.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!") + (0 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!")) + +((mode 1 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620805271") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: He cannot be heard of. Out of doubt he is transported.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: More evident than this; for this was stol'n.") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Sell when you can; you are not for all markets.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: There's the fool hangs on your back already.") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Why, if you have a stomach to't, monsieur, if you think your mystery in stratagem can bring this instrument of honour again into its native quarter, be magnanimous in the enterprise and go on; I will grace the attempt for a worthy exploit: if you speed well in it, the duke shall both speak of it, and extend to you what further becomes his greatness, even to the utmost syllable of your worthiness.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: For he hath still been tried a holy man.") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: To have the touches dearest priz'd.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: And must advise the emperor for his good.") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Orlando, my liege; the youngest son of Sir Rowland de Boys.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: The ape is dead, and I must conjure him.")) + +((drop 0 DROP)) diff --git a/test/lisp/erc/resources/base/netid/bouncer/foonet.eld b/test/lisp/erc/resources/base/netid/bouncer/foonet.eld new file mode 100644 index 0000000000..c241c59bb8 --- /dev/null +++ b/test/lisp/erc/resources/base/netid/bouncer/foonet.eld @@ -0,0 +1,46 @@ +;; -*- mode: lisp-data; -*- +((pass 3 "PASS :foonet:changeme")) +((nick 3 "NICK tester")) +((user 3 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 4.2 "MODE tester +i") + ;; No mode answer ^ + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((join 1 "JOIN #chan") + (0 ":tester!~u@ertp7idh9jtgi.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :@alice bob tester") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!") + (0 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :tester, welcome!")) + +((mode 3 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620805271") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: He cannot be heard of. Out of doubt he is transported.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: More evident than this; for this was stol'n.") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Sell when you can; you are not for all markets.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: There's the fool hangs on your back already.") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Why, if you have a stomach to't, monsieur, if you think your mystery in stratagem can bring this instrument of honour again into its native quarter, be magnanimous in the enterprise and go on; I will grace the attempt for a worthy exploit: if you speed well in it, the duke shall both speak of it, and extend to you what further becomes his greatness, even to the utmost syllable of your worthiness.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: For he hath still been tried a holy man.") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: To have the touches dearest priz'd.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: And must advise the emperor for his good.") + (0.1 ":alice!~u@ertp7idh9jtgi.irc PRIVMSG #chan :bob: Orlando, my liege; the youngest son of Sir Rowland de Boys.") + (0.1 ":bob!~u@ertp7idh9jtgi.irc PRIVMSG #chan :alice: The ape is dead, and I must conjure him.")) + +((linger 1 LINGER)) diff --git a/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld b/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld new file mode 100644 index 0000000000..c666ee4fa0 --- /dev/null +++ b/test/lisp/erc/resources/base/netid/bouncer/stub-again.eld @@ -0,0 +1,4 @@ +;; -*- mode: lisp-data; -*- +((pass 10 "PASS :" token ":changeme")) + +((fake 1 "FAKE no op")) diff --git a/test/lisp/erc/resources/base/netid/samenet/chester.eld b/test/lisp/erc/resources/base/netid/samenet/chester.eld new file mode 100644 index 0000000000..8c2448733c --- /dev/null +++ b/test/lisp/erc/resources/base/netid/samenet/chester.eld @@ -0,0 +1,48 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK chester")) +((user 1 "USER user 0 * :chester") + (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester") + (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC") + (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 chester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 chester 1 :unregistered connections") + (0 ":irc.foonet.org 254 chester 1 :channels formed") + (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4") + (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4") + (0 ":irc.foonet.org 422 chester :MOTD File is missing")) + +((mode-user 10.2 "MODE chester +i") + (0 ":irc.foonet.org 221 chester +i") + (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 14 "JOIN #chan") + (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob") + (0 ":irc.foonet.org 366 chester #chan :End of NAMES list")) + +((mode 10 "MODE #chan") + (0.0 ":irc.foonet.org 324 chester #chan +nt") + (0.0 ":irc.foonet.org 329 chester #chan 1623563121") + (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.") + (0.1 ":tester!~u@yuvqisyu7m7qs.irc PRIVMSG #chan :chester: hi") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: This was lofty! Now name the rest of the players. This is Ercles' vein, a tyrant's vein; a lover is more condoling.")) + +((privmsg 4 "PRIVMSG #chan :hi tester") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: As the ox hath his bow, sir, the horse his curb, and the falcon her bells, so man hath his desires; and as pigeons bill, so wedlock would be nibbling.") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: Most friendship is feigning, most loving mere folly.") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: To employ you towards this Roman. Come, our queen.")) + +((quit 5 "QUIT :" quit) + (0.0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit) + (0.0 ":chester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit)) diff --git a/test/lisp/erc/resources/base/netid/samenet/tester.eld b/test/lisp/erc/resources/base/netid/samenet/tester.eld new file mode 100644 index 0000000000..76312a7a14 --- /dev/null +++ b/test/lisp/erc/resources/base/netid/samenet/tester.eld @@ -0,0 +1,52 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4") + (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 15 "JOIN #chan") + (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((mode 10 "MODE #chan") + (0.0 ":irc.foonet.org 324 tester #chan +nt") + (0.0 ":irc.foonet.org 329 tester #chan 1623563121") + (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!") + (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Marry, that, I think, be young Petruchio.") + (0.4 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: You speak of him when he was less furnished than now he is with that which makes him both without and within.") + (0.2 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.")) + +((privmsg 3 "PRIVMSG #chan :chester: hi") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: This was lofty! Now name the rest of the players. This is Ercles' vein, a tyrant's vein; a lover is more condoling.") + (0.1 ":chester!~u@yuvqisyu7m7qs.irc PRIVMSG #chan :hi tester") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: As the ox hath his bow, sir, the horse his curb, and the falcon her bells, so man hath his desires; and as pigeons bill, so wedlock would be nibbling.") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: Most friendship is feigning, most loving mere folly.") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: To employ you towards this Roman. Come, our queen.")) + +((quit 4 "QUIT :" quit) + (0 ":tester!~u@yuvqisyu7m7qs.irc QUIT :Quit: " quit)) diff --git a/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld b/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld new file mode 100644 index 0000000000..8e299ec44c --- /dev/null +++ b/test/lisp/erc/resources/base/reconnect/aborted-dupe.eld @@ -0,0 +1,28 @@ +;; -*- mode: lisp-data; -*- +((pass 3 "PASS :changeme")) +((nick 1 "NICK tester")) + +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (-0.02 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (-0.02 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (-0.02 ":irc.foonet.org 253 tester 0 :unregistered connections") + (-0.02 ":irc.foonet.org 254 tester 1 :channels formed") + (-0.02 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (-0.02 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (-0.02 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (-0.02 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((~mode-user 3.2 "MODE tester +i") + (-0.02 ":irc.foonet.org 221 tester +i") + (-0.02 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((~join 10 "JOIN #chan")) +((eof 5 EOF)) +((drop 0 DROP)) diff --git a/test/lisp/erc/resources/base/reconnect/aborted.eld b/test/lisp/erc/resources/base/reconnect/aborted.eld new file mode 100644 index 0000000000..5c32070d85 --- /dev/null +++ b/test/lisp/erc/resources/base/reconnect/aborted.eld @@ -0,0 +1,45 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 12 "JOIN #chan") + (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((mode 10 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Signior Iachimo will not from it. Pray, let us follow 'em.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Our queen and all her elves come here anon.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: The ground is bloody; search about the churchyard.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: You have discharged this honestly: keep it to yourself. Many likelihoods informed me of this before, which hung so tottering in the balance that I could neither believe nor misdoubt. Pray you, leave me: stall this in your bosom; and I thank you for your honest care. I will speak with you further anon.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Give me that mattock, and the wrenching iron.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Stand you! You have land enough of your own; but he added to your having, gave you some ground.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: And will you, being a man of your breeding, be married under a bush, like a beggar ? Get you to church, and have a good priest that can tell you what marriage is: this fellow will but join you together as they join wainscot; then one of you will prove a shrunk panel, and like green timber, warp, warp.") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: Live, and be prosperous; and farewell, good fellow.")) diff --git a/test/lisp/erc/resources/base/reconnect/options-again.eld b/test/lisp/erc/resources/base/reconnect/options-again.eld new file mode 100644 index 0000000000..f1fcc439cc --- /dev/null +++ b/test/lisp/erc/resources/base/reconnect/options-again.eld @@ -0,0 +1,45 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is still in debug mode.")) + +((~join-chan 12 "JOIN #chan") + (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((~join-spam 12 "JOIN #spam") + (0 ":tester!~u@9g6b728983yd2.irc JOIN #spam") + (0 ":irc.foonet.org 353 tester = #spam :alice tester @bob") + (0 ":irc.foonet.org 366 tester #spam :End of NAMES list")) + +((~mode-chan 4 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :alice: But, as it seems, did violence on herself.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :bob: Well, this is the forest of Arden.")) + +((mode-spam 4 "MODE #spam") + (0 ":irc.foonet.org 324 tester #spam +nt") + (0 ":irc.foonet.org 329 tester #spam 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #spam :alice: Signior Iachimo will not from it. Pray, let us follow 'em.") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #spam :bob: Our queen and all her elves come here anon.")) diff --git a/test/lisp/erc/resources/base/reconnect/options.eld b/test/lisp/erc/resources/base/reconnect/options.eld new file mode 100644 index 0000000000..3b305d8559 --- /dev/null +++ b/test/lisp/erc/resources/base/reconnect/options.eld @@ -0,0 +1,35 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 04 May 2021 05:06:18 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode.") + + (0 ":tester!~u@9g6b728983yd2.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice tester @bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((mode-chan 4 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620104779") + (0.1 ":bob!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":alice!~u@rz2v467q4rwhy.irc PRIVMSG #chan :tester, welcome!")) + +((drop 0 DROP)) diff --git a/test/lisp/erc/resources/base/reconnect/timer-last.eld b/test/lisp/erc/resources/base/reconnect/timer-last.eld new file mode 100644 index 0000000000..23849bc1ba --- /dev/null +++ b/test/lisp/erc/resources/base/reconnect/timer-last.eld @@ -0,0 +1,6 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.znc.in 464 tester :Invalid Password")) +((linger 1 LINGER)) diff --git a/test/lisp/erc/resources/base/reconnect/timer.eld b/test/lisp/erc/resources/base/reconnect/timer.eld new file mode 100644 index 0000000000..95c6af8d88 --- /dev/null +++ b/test/lisp/erc/resources/base/reconnect/timer.eld @@ -0,0 +1,6 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.znc.in 464 tester :Invalid Password")) +((drop 0 DROP)) diff --git a/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld b/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld new file mode 100644 index 0000000000..fc6cdaafe9 --- /dev/null +++ b/test/lisp/erc/resources/base/renick/queries/bouncer-barnet.eld @@ -0,0 +1,54 @@ +;; -*- mode: lisp-data; -*- +((pass 3 "PASS :barnet:changeme")) +((nick 3 "NICK tester")) +((user 3 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Tue, 01 Jun 2021 07:49:23 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 3.2 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@286u8jcpis84e.irc JOIN #chan") + (0 ":irc.barnet.org 353 tester = #chan :@joe mike rando tester") + (0 ":irc.barnet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :[09:19:19] mike: Chi non te vede, non te pretia.") + (0 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :[09:19:28] joe: The valiant heart's not whipt out of his trade.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :[09:18:20] Why'd you pull that scene at the arcade?") + (0 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :[09:18:32] I had to mess up this rentacop came after me with nunchucks.") + (0 ":irc.barnet.org NOTICE tester :[09:13:24] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.barnet.org 305 tester :You are no longer marked as being away")) + +((mode 5 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1622538742") + (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: By favours several which they did bestow.") + (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: You, Roderigo! come, sir, I am for you.")) + +((privmsg-a 5 "PRIVMSG rando :Linda said you were gonna kill me.") + (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: Play, music, then! Nay, you must do it soon.") + (0.1 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :Linda said? I never saw her before I came up here.") + (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: Of arts inhibited and out of warrant.")) + +((privmsg-b 3 "PRIVMSG rando :You aren't with Wage?") + (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: But most of all, agreeing with the proclamation.") + (0.1 ":rando!~u@95i756tt32ym8.irc PRIVMSG tester :I think you screwed up, Case.") + (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: Good gentleman, go your gait, and let poor volk pass. An chud ha' bin zwaggered out of my life, 'twould not ha' bin zo long as 'tis by a vortnight. Nay, come not near th' old man; keep out, che vor ye, or ise try whether your costard or my ballow be the harder. Chill be plain with you.") + ;; Nick change + (0.1 ":rando!~u@95i756tt32ym8.irc NICK frenemy") + (0.1 ":joe!~u@286u8jcpis84e.irc PRIVMSG #chan :mike: Till time beget some careful remedy.") + (0.1 ":frenemy!~u@95i756tt32ym8.irc PRIVMSG tester :I showed up and you just fit me right into your reality picture.") + (0.1 ":mike!~u@286u8jcpis84e.irc PRIVMSG #chan :joe: For I have lost him on a dangerous sea.")) diff --git a/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld b/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld new file mode 100644 index 0000000000..162e8bf965 --- /dev/null +++ b/test/lisp/erc/resources/base/renick/queries/bouncer-foonet.eld @@ -0,0 +1,52 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Tue, 01 Jun 2021 07:49:22 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 5.2 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@u4mvbswyw8gbg.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :alice @bob rando tester") + (0 ":irc.foonet.org 366 tester #chan :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :[09:19:28] alice: Great men should drink with harness on their throats.") + (0 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :[09:19:31] bob: Your lips will feel them the sooner: shallow again. A more sounder instance; come.") + (0 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :[09:17:51] u thur?") + (0 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :[09:17:58] guess not") + (0 ":irc.foonet.org NOTICE tester :[09:12:53] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((mode 10 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1622538742") + (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: When there is nothing living but thee, thou shalt be welcome. I had rather be a beggar's dog than Apemantus.") + (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: You have simply misused our sex in your love-prate: we must have your doublot and hose plucked over your head, and show the world what the bird hath done to her own nest.")) + +((privmsg-a 6 "PRIVMSG rando :I here") + (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: And I will make thee think thy swan a crow.") + (0.1 ":rando!~u@bivkhq8yav938.irc PRIVMSG tester :u are dumb") + (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: Lie not, to say mine eyes are murderers.")) + +((privmsg-b 3 "PRIVMSG rando :not so") + (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: Commit myself, my person, and the cause.") + ;; Nick change + (0.1 ":rando!~u@bivkhq8yav938.irc NICK frenemy") + (0.1 ":alice!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :bob: Of raging waste! It cannot hold; it will not.") + (0.1 ":frenemy!~u@bivkhq8yav938.irc PRIVMSG tester :doubly so") + (0.1 ":bob!~u@u4mvbswyw8gbg.irc PRIVMSG #chan :alice: These words are razors to my wounded heart.")) diff --git a/test/lisp/erc/resources/base/renick/queries/solo.eld b/test/lisp/erc/resources/base/renick/queries/solo.eld new file mode 100644 index 0000000000..12fa7d264e --- /dev/null +++ b/test/lisp/erc/resources/base/renick/queries/solo.eld @@ -0,0 +1,55 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Mon, 31 May 2021 09:56:24 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 2 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4") + (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 8 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo") + (0 ":irc.foonet.org 353 tester = #foo :alice @bob Lal tester") + (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...") + (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.") + (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.") + (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.") + (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((mode 1 "MODE #foo") + (0 ":irc.foonet.org 324 tester #foo +nt") + (0 ":irc.foonet.org 329 tester #foo 1622454985") + (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short.")) + +((privmsg-a 10 "PRIVMSG #foo :hi") + (0.2 ":Lal!~u@b82mytupn2t5k.irc PRIVMSG tester :hello") + (0.2 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: And brought to yoke, the enemies of Rome.") + (0.2 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Thou art thy father's daughter; there's enough.")) + +((privmsg-b 10 "PRIVMSG Lal :hi") + (0.2 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: Here are the beetle brows shall blush for me.") + (0.2 ":Lal!~u@b82mytupn2t5k.irc NICK Linguo") + (0.2 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: He hath abandoned his physicians, madam; under whose practices he hath persecuted time with hope, and finds no other advantage in the process but only the losing of hope by time.")) + +((privmsg-c 10 "PRIVMSG Linguo :howdy Linguo") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: And brought to yoke, the enemies of Rome.") + (0.2 ":Linguo!~u@b82mytupn2t5k.irc PART #foo")) + +((part 10 "PART #foo :\2ERC\2") + (0 ":tester!~u@gq7yjr7gsu7nn.irc PART #foo :\2ERC\2") + (0.1 ":Linguo!~u@b82mytupn2t5k.irc PRIVMSG tester :get along little doggie")) diff --git a/test/lisp/erc/resources/base/renick/self/auto.eld b/test/lisp/erc/resources/base/renick/self/auto.eld new file mode 100644 index 0000000000..851db7f1cf --- /dev/null +++ b/test/lisp/erc/resources/base/renick/self/auto.eld @@ -0,0 +1,46 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org[188.240.145.101/6697], running version solanum-1.0-dev") + (0 ":irc.foonet.org 003 tester :This server was created Sat May 22 2021 at 19:04:17 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI") + (0 ":irc.foonet.org 005 tester WHOX FNC KNOCK SAFELIST ELIST=CTU CALLERID=g MONITOR=100 ETRACE CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server") + (0 ":irc.foonet.org 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=foonet STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server") + (0 ":irc.foonet.org 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 33 users and 14113 invisible on 17 servers") + (0 ":irc.foonet.org 252 tester 34 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 12815 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 726 clients and 1 servers") + (0 ":irc.foonet.org 265 tester 726 739 :Current local users 726, max 739") + (0 ":irc.foonet.org 266 tester 14146 14541 :Current global users 14146, max 14541") + (0 ":irc.foonet.org 250 tester :Highest connection count: 740 (739 clients) (3790 connections received)") + (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy") + (0 ":irc.foonet.org 375 dummy :- irc.foonet.org Message of the Day - ") + (0 ":irc.foonet.org 372 dummy :- This server provided by NORDUnet/SUNET") + (0 ":irc.foonet.org 372 dummy :- Welcome to foonet, the IRC network for free & open-source software") + (0 ":irc.foonet.org 372 dummy :- and peer directed projects.") + (0 ":irc.foonet.org 372 dummy :- ") + (0 ":irc.foonet.org 372 dummy :- Please visit us in #libera for questions and support.") + (0 ":irc.foonet.org 376 dummy :End of /MOTD command.")) + +((mode-user 10.2 "MODE dummy +i") + (0 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi") + (0 ":irc.znc.in 306 dummy :You have been marked as being away") + (0 ":dummy!~u@gq7yjr7gsu7nn.irc JOIN #foo") + + (0 ":irc.foonet.org 353 dummy = #foo :alice @bob Lal dummy") + (0 ":irc.foonet.org 366 dummy #foo :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...") + (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.") + (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.") + (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.") + (0 ":irc.foonet.org NOTICE dummy :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 dummy :You are no longer marked as being away")) + +((mode 10 "MODE #foo") + (0 ":irc.foonet.org 324 dummy #foo +nt") + (0 ":irc.foonet.org 329 dummy #foo 1622454985") + (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short.")) diff --git a/test/lisp/erc/resources/base/renick/self/manual.eld b/test/lisp/erc/resources/base/renick/self/manual.eld new file mode 100644 index 0000000000..dd107b806d --- /dev/null +++ b/test/lisp/erc/resources/base/renick/self/manual.eld @@ -0,0 +1,50 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org[188.240.145.101/6697], running version solanum-1.0-dev") + (0 ":irc.foonet.org 003 tester :This server was created Sat May 22 2021 at 19:04:17 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI") + (0 ":irc.foonet.org 005 tester WHOX FNC KNOCK SAFELIST ELIST=CTU CALLERID=g MONITOR=100 ETRACE CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server") + (0 ":irc.foonet.org 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=foonet STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server") + (0 ":irc.foonet.org 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 33 users and 14113 invisible on 17 servers") + (0 ":irc.foonet.org 252 tester 34 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 12815 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 726 clients and 1 servers") + (0 ":irc.foonet.org 265 tester 726 739 :Current local users 726, max 739") + (0 ":irc.foonet.org 266 tester 14146 14541 :Current global users 14146, max 14541") + (0 ":irc.foonet.org 250 tester :Highest connection count: 740 (739 clients) (3790 connections received)") + (0 ":irc.foonet.org 375 tester :- irc.foonet.org Message of the Day - ") + (0 ":irc.foonet.org 372 tester :- This server provided by NORDUnet/SUNET") + (0 ":irc.foonet.org 372 tester :- Welcome to foonet, the IRC network for free & open-source software") + (0 ":irc.foonet.org 372 tester :- and peer directed projects.") + (0 ":irc.foonet.org 372 tester :- ") + (0 ":irc.foonet.org 372 tester :- Please visit us in #libera for questions and support.") + (0 ":irc.foonet.org 376 tester :End of /MOTD command.")) + +((mode-user 1.2 "MODE tester +i") + (0 ":tester!~u@gq7yjr7gsu7nn.irc MODE tester :+RZi") + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":tester!~u@gq7yjr7gsu7nn.irc JOIN #foo") + + (0 ":irc.foonet.org 353 tester = #foo :alice @bob Lal tester") + (0 ":irc.foonet.org 366 tester #foo :End of /NAMES list.") + (0 ":***!znc@znc.in PRIVMSG #foo :Buffer Playback...") + (0 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:02] bob: All that he is hath reference to your highness.") + (0 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :[10:00:06] alice: Excellent workman! Thou canst not paint a man so bad as is thyself.") + (0 ":***!znc@znc.in PRIVMSG #foo :Playback Complete.") + (0 ":irc.foonet.org NOTICE tester :[09:56:57] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) + +((mode 1 "MODE #foo") + (0 ":irc.foonet.org 324 tester #foo +nt") + (0 ":irc.foonet.org 329 tester #foo 1622454985") + (0.1 ":alice!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :bob: Farewell, pretty lady: you must hold the credit of your father.") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :alice: On Thursday, sir ? the time is very short.")) + +((nick 2 "NICK dummy") + (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy") + (0.1 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi") + (0.1 ":bob!~u@gq7yjr7gsu7nn.irc PRIVMSG #foo :dummy: Hi.")) diff --git a/test/lisp/erc/resources/base/renick/self/qual-chester.eld b/test/lisp/erc/resources/base/renick/self/qual-chester.eld new file mode 100644 index 0000000000..75b50fe68b --- /dev/null +++ b/test/lisp/erc/resources/base/renick/self/qual-chester.eld @@ -0,0 +1,40 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK chester")) +((user 1 "USER user 0 * :chester") + (0 ":irc.foonet.org 001 chester :Welcome to the foonet IRC Network chester") + (0 ":irc.foonet.org 002 chester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 chester :This server was created Sun, 13 Jun 2021 05:45:20 UTC") + (0 ":irc.foonet.org 004 chester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 chester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 chester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 chester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 chester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 chester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 chester 1 :unregistered connections") + (0 ":irc.foonet.org 254 chester 1 :channels formed") + (0 ":irc.foonet.org 255 chester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 chester 3 4 :Current local users 3, max 4") + (0 ":irc.foonet.org 266 chester 3 4 :Current global users 3, max 4") + (0 ":irc.foonet.org 422 chester :MOTD File is missing")) + +((mode-user 1.2 "MODE chester +i") + (0 ":irc.foonet.org 221 chester +i") + (0 ":irc.foonet.org NOTICE chester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 14 "JOIN #chan") + (0 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0 ":irc.foonet.org 353 chester = #chan :tester chester @alice bob") + (0 ":irc.foonet.org 366 chester #chan :End of NAMES list")) + +((mode 10 "MODE #chan") + (0.0 ":irc.foonet.org 324 chester #chan +nt") + (0.0 ":irc.foonet.org 329 chester #chan 1623563121") + (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.")) + +((linger 10 LINGER)) diff --git a/test/lisp/erc/resources/base/renick/self/qual-tester.eld b/test/lisp/erc/resources/base/renick/self/qual-tester.eld new file mode 100644 index 0000000000..2519922665 --- /dev/null +++ b/test/lisp/erc/resources/base/renick/self/qual-tester.eld @@ -0,0 +1,46 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Sun, 13 Jun 2021 05:45:20 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 4 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 4 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 4 4 :Current local users 4, max 4") + (0 ":irc.foonet.org 266 tester 4 4 :Current global users 4, max 4") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":irc.foonet.org 221 tester +i") + (0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")) + +((join 15 "JOIN #chan") + (0 ":tester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0 ":irc.foonet.org 353 tester = #chan :tester @alice bob") + (0 ":irc.foonet.org 366 tester #chan :End of NAMES list")) + +((mode 10 "MODE #chan") + (0.0 ":irc.foonet.org 324 tester #chan +nt") + (0.0 ":irc.foonet.org 329 tester #chan 1623563121") + (0.0 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!") + (0.0 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :tester, welcome!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Marry, that, I think, be young Petruchio.") + (0.4 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: You speak of him when he was less furnished than now he is with that which makes him both without and within.") + (0.2 ":chester!~u@yuvqisyu7m7qs.irc JOIN #chan") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :chester, welcome!")) + +((nick 5 "NICK dummy") + (0 ":tester!~u@gq7yjr7gsu7nn.irc NICK :dummy") + (0.1 ":dummy!~u@gq7yjr7gsu7nn.irc MODE dummy :+RZi") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: That ever eye with sight made heart lament.") + (0.1 ":alice!~u@wyb9b355rgzi8.irc PRIVMSG #chan :bob: The bitter past, more welcome is the sweet.") + (0.1 ":bob!~u@wyb9b355rgzi8.irc PRIVMSG #chan :alice: Dispatch, I say, and find the forester.")) diff --git a/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld b/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld new file mode 100644 index 0000000000..cc7aff1007 --- /dev/null +++ b/test/lisp/erc/resources/base/reuse-buffers/server/barnet.eld @@ -0,0 +1,24 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :barnet:changeme")) +((nick 1 "NICK tester")) +((user 2 "USER user 0 * :tester") + (0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.barnet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC") + (0 ":irc.barnet.org 004 tester irc.barnet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0 ":irc.barnet.org 254 tester 1 :channels formed") + (0 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":irc.barnet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.barnet.org 305 tester :You are no longer marked as being away")) diff --git a/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld b/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld new file mode 100644 index 0000000000..3a84610846 --- /dev/null +++ b/test/lisp/erc/resources/base/reuse-buffers/server/foonet.eld @@ -0,0 +1,24 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS :foonet:changeme")) +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16") + (0 ":irc.foonet.org 003 tester :This server was created Sun, 25 Apr 2021 11:28:28 UTC") + (0 ":irc.foonet.org 004 tester irc.foonet.org oragono-2.6.0-7481bf0385b95b16 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0 ":irc.foonet.org 254 tester 1 :channels formed") + (0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 10.2 "MODE tester +i") + ;; No mode answer + (0 ":irc.znc.in 306 tester :You have been marked as being away") + (0 ":irc.foonet.org NOTICE tester :[11:29:00] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0 ":irc.foonet.org 305 tester :You are no longer marked as being away")) diff --git a/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld b/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld new file mode 100644 index 0000000000..b8fc45e57b --- /dev/null +++ b/test/lisp/erc/resources/base/upstream-reconnect/soju-barnet.eld @@ -0,0 +1,64 @@ +;; -*- mode: lisp-data; -*- +((pass 6 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER tester@vanilla/barnet 0 * :tester") + (0.01 ":soju.im 001 tester :Welcome to soju, tester") + (0.01 ":soju.im 002 tester :Your host is soju.im") + (0.00 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI") + (0.53 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii BOUNCER_NETID=2 AWAYLEN=390 CHANLIMIT=#:100 INVEX NETWORK=barnet NICKLEN=32 WHOX MODES BOT=B ELIST=U MAXLIST=beI:60 :are supported") + (0.01 ":soju.im 005 tester TOPICLEN=390 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 EXCEPTS EXTBAN=,m KICKLEN=390 TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 MAXTARGETS=4 MONITOR=100 CHANTYPES=# PREFIX=(qaohv)~&@%+ UTF8ONLY :are supported") + (0.22 ":soju.im 221 tester +Zi") + (0.00 ":soju.im 422 tester :Use /motd to read the message of the day")) + +((mode 5 "MODE tester +i") + (0.00 ":tester!tester@10.0.2.100 JOIN #chan") + (0.06 ":soju.im 353 tester = #chan :tester @mike joe") + (0.01 ":soju.im 366 tester #chan :End of /NAMES list") + (0.23 ":irc.barnet.org 221 tester +Zi")) + +((mode 5 "MODE #chan") + (0.00 ":soju.im 324 tester #chan +tn") + (0.01 ":soju.im 329 tester #chan 1652878846") + (0.01 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: There is five in the first show.") + (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Sir, I was an inward of his. A shy fellow was the duke; and, I believe I know the cause of his withdrawing.") + (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Proud of employment, willingly I go.") + (0.09 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Dull not device by coldness and delay.") + (0.09 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Our states are forfeit: seek not to undo us.") + (0.06 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Come, you are too severe a moraler. As the time, the place, and the condition of this country stands, I could heartily wish this had not befallen, but since it is as it is, mend it for your own good.") + (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Who hath upon him still that natural stamp.") + (0.07 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Arraign her first; 'tis Goneril. I here take my oath before this honourable assembly, she kicked the poor king her father.") + (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Lady, I will commend you to mine own heart.") + (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Look, what I will not, that I cannot do.") + (0.08 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: That he would wed me, or else die my lover.") + (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Come your way, sir. Bless you, good father friar.") + (0.08 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Under correction, sir, we know whereuntil it doth amount.") + (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: For I am nothing if not critical.") + (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Once more I'll read the ode that I have writ.") + (0.06 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: This is the foul fiend Flibbertigibbet: he begins at curfew, and walks till the first cock; he gives the web and the pin, squints the eye, and makes the harelip; mildews the white wheat, and hurts the poor creature of earth.") + (0.06 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Sir, I praise the Lord for you, and so may my parishioners; for their sons are well tutored by you, and their daughters profit very greatly under you: you are a good member of the commonwealth.") + (0.08 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: If it please your honour, I know not well what they are; but precise villains they are, that I am sure of, and void of all profanation in the world that good Christians ought to have.") + ;; Unexpected disconnect + (0.03 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :disconnected from barnet: failed to handle messages: failed to read IRC command: read tcp [::1]:54990->[::1]:6668: read: software caused connection abort") + ;; Eventual reconnect + (0.79 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :connected to barnet") + ;; No MOTD or other numerics + (0.01 ":soju.im 005 tester AWAYLEN=390 BOT=B CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 :are supported") + (0.01 ":soju.im 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported") + (0.22 ":irc.barnet.org 221 tester +Zi") + (0.01 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + ;; Server-initialed join + (0.01 ":tester!tester@10.0.2.100 JOIN #chan")) + +((mode 5 "MODE #chan") + (0.22 ":soju.im 353 tester = #chan :@mike joe tester") + (0.00 ":soju.im 366 tester #chan :End of /NAMES list") + (0.00 ":soju.im 324 tester #chan +nt") + (0.00 ":soju.im 329 tester #chan 1652878846") + (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :tester, welcome!") + (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :tester, welcome!") + (0.06 ":soju.im 324 tester #chan +nt") + (0.00 ":soju.im 329 tester #chan 1652878846") + (0.62 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: Thou art my brother; so we'll hold thee ever.") + (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Very well! go to! I cannot go to, man; nor 'tis not very well: by this hand, I say, it is very scurvy, and begin to find myself fobbed in it.") + (0.00 ":joe!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :mike: The heir of Alen on, Katharine her name.") + (0.09 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Go to; farewell! put money enough in your purse.")) diff --git a/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld b/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld new file mode 100644 index 0000000000..63dfcb184c --- /dev/null +++ b/test/lisp/erc/resources/base/upstream-reconnect/soju-foonet.eld @@ -0,0 +1,72 @@ +;; -*- mode: lisp-data; -*- +((pass 5 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER tester@vanilla/foonet 0 * :tester") + (0.01 ":soju.im 001 tester :Welcome to soju, tester") + (0.02 ":soju.im 002 tester :Your host is soju.im") + (0.01 ":soju.im 004 tester soju.im soju aiwroO OovaimnqpsrtklbeI") + (0.00 ":soju.im 005 tester CHATHISTORY=1000 CASEMAPPING=ascii BOUNCER_NETID=1 CHANTYPES=# PREFIX=(qaohv)~&@%+ UTF8ONLY AWAYLEN=390 NICKLEN=32 WHOX CHANLIMIT=#:100 INVEX NETWORK=foonet MODES :are supported") + (0.00 ":soju.im 005 tester TOPICLEN=390 BOT=B ELIST=U MAXLIST=beI:60 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 EXCEPTS EXTBAN=,m KICKLEN=390 MAXTARGETS=4 MONITOR=100 :are supported") + (0.00 ":soju.im 221 tester +Zi") + (0.00 ":soju.im 422 tester :Use /motd to read the message of the day")) + +((mode 5 "MODE tester +i") + (0.2 ":irc.foonet.org 221 tester +Zi") + (0.0 ":tester!tester@10.0.2.100 JOIN #chan") + (0.0 ":soju.im 353 tester = #chan :tester @alice bob") + (0.1 ":soju.im 366 tester #chan :End of /NAMES list") + (0.0 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Princely shall be thy usage every way.") + (0.1 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Tell me thy reason why thou wilt marry.")) + +((mode 5 "MODE #chan") + (0.00 ":soju.im 324 tester #chan +nt") + (0.01 ":soju.im 329 tester #chan 1652878847") + (0.02 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: There is no leprosy but what thou speak'st.") + (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: For I upon this bank will rest my head.") + (0.01 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: To ruffle in the commonwealth of Rome.") + (0.08 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: For I can nowhere find him like a man.") + (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Ay, sir; but she will none, she gives you thanks.") + (0.05 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: That man should be at woman's command, and yet no hurt done! Though honesty be no puritan, yet it will do no hurt; it will wear the surplice of humility over the black gown of a big heart. I am going, forsooth: the business is for Helen to come hither.") + (0.07 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Indeed, I should have asked you that before.") + (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Faith, we met, and found the quarrel was upon the seventh cause.") + (0.05 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: And then, I hope, thou wilt be satisfied.") + (0.06 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Well, I will forget the condition of my estate, to rejoice in yours.") + (0.05 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Ah! sirrah, this unlook'd-for sport comes well.") + (0.01 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Mayst thou inherit too! Welcome to Paris.") + (0.04 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: That I would choose, were I to choose anew.") + (0.08 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Good Tom Drum, lend me a handkercher: so, I thank thee. Wait on me home, I'll make sport with thee: let thy curtsies alone, they are scurvy ones.") + (0.06 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Excellent workman! Thou canst not paint a man so bad as is thyself.") + (0.07 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: That every braggart shall be found an ass.") + (0.07 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: This is but a custom in your tongue; you bear a graver purpose, I hope.") + (0.02 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: Well, we will have such a prologue, and it shall be written in eight and six.") + (0.01 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Tell me thy reason why thou wilt marry.") + (0.06 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: According to the measure of their states.") + + ;; Unexpected disconnect + (0.07 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :disconnected from foonet: failed to handle messages: failed to read IRC command: read tcp [::1]:57224->[::1]:6667: read: software caused connection abort") + ;; Eventual reconnect + (1.02 ":BouncerServ!BouncerServ@BouncerServ NOTICE tester :connected to foonet") + ;; No MOTD or other numerics + (0.01 ":soju.im 005 tester AWAYLEN=390 BOT=B CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m INVEX KICKLEN=390 :are supported") + (0.02 ":soju.im 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8ONLY WHOX :are supported") + (0.02 ":irc.foonet.org 221 tester +Zi") + (0.23 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + ;; Server-initialed join + (0.02 ":tester!tester@10.0.2.100 JOIN #chan")) + +((mode 5 "MODE #chan") + (0.03 ":soju.im 353 tester = #chan :@alice bob tester") + (0.03 ":soju.im 366 tester #chan :End of /NAMES list") + (0.00 ":soju.im 324 tester #chan +nt") + (0.00 ":soju.im 329 tester #chan 1652878847") + (0.00 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :tester, welcome!") + (0.00 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :tester, welcome!") + (0.46 ":soju.im 324 tester #chan +nt") + (0.01 ":soju.im 329 tester #chan 1652878847") + (0.00 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: Thou desirest me to stop in my tale against the hair.") + (0.07 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: But my intents are fix'd and will not leave me.") + (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: That last is true; the sweeter rest was mine.") + (0.09 ":alice!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :bob: No matter whither, so you come not here.") + (0.09 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: My lord, in heart; and let the health go round.")) + +((linger 12 LINGER)) diff --git a/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld b/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld new file mode 100644 index 0000000000..bf5c2b5a74 --- /dev/null +++ b/test/lisp/erc/resources/base/upstream-reconnect/znc-barnet.eld @@ -0,0 +1,93 @@ +;; -*- mode: lisp-data; -*- +((pass 6 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER tester@vanilla/barnet 0 * :tester") + (0.00 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0.01 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version ergo-v2.8.0") + (0.01 ":irc.barnet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC") + (0.00 ":irc.barnet.org 004 tester irc.barnet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.00 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.01 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.01 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0.00 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0.00 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0.11 ":irc.barnet.org 254 tester 1 :channels formed") + (0.00 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0.00 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0.00 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0.00 ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode 5 "MODE tester +i") + (0.0 ":tester!~u@fsr9fwzfeeybc.irc JOIN #chan") + (0.05 ":irc.barnet.org 353 tester = #chan :@joe mike tester") + (0.01 ":irc.barnet.org 366 tester #chan :End of /NAMES list.") + (0.0 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0.0 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:13] mike: But send the midwife presently to me.") + (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:18] joe: Alas! poor rogue, I think, i' faith, she loves me.") + (0.01 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:20] mike: They did not bless us with one happy word.") + (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:24] joe: And hear the sentence of your moved prince.") + (0.21 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:29] mike: Swear me to this, and I will ne'er say no.") + (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:32] joe: As they had seen me with these hangman's hands.") + (0.01 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:34] mike: Boyet, prepare: I will away to-night.") + (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :[05:48:36] joe: For being a little bad: so may my husband.") + (0.04 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0.0 ":irc.barnet.org 221 tester +Zi") + (2.55 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And whirl along with thee about the globe.")) + +((mode 5 "MODE #chan") + (0.00 ":irc.barnet.org 324 tester #chan +nt") + (0.00 ":irc.barnet.org 329 tester #chan 1652938384") + (0.06 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Unless good-counsel may the cause remove.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Thyself domestic officers thine enemy.") + (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Go after her: she's desperate; govern her.") + (0.30 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Or else to heaven she heaves them for revenge.") + (0.01 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Keep up your bright swords, for the dew will rust them.") + (0.04 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC (Connection aborted). Reconnecting...") + (0.41 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC. Reconnecting...") + (0.59 ":*status!znc@znc.in PRIVMSG tester :Connected!") + (0.02 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester") + (0.01 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version ergo-v2.8.0") + (0.01 ":irc.barnet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC") + (0.01 ":irc.barnet.org 004 tester irc.barnet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.01 ":irc.barnet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.01 ":irc.barnet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=barnet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.22 ":irc.barnet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0.00 ":irc.barnet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0.01 ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0.00 ":irc.barnet.org 253 tester 0 :unregistered connections") + (0.00 ":irc.barnet.org 254 tester 1 :channels formed") + (0.00 ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0.00 ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0.17 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0.00 ":irc.barnet.org 422 tester :MOTD File is missing") + (0.01 ":irc.barnet.org 221 tester +Zi") + (0.00 ":irc.barnet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0.05 ":irc.barnet.org 352 tester * ~u fsr9fwzfeeybc.irc irc.barnet.org tester H :0 ZNC - https://znc.in") + (0.02 ":irc.barnet.org 315 tester tester!*@* :End of WHO list") + (0.08 ":tester!~u@fsr9fwzfeeybc.irc JOIN #chan")) + +((mode 5 "MODE #chan") + (0.05 ":irc.barnet.org 353 tester = #chan :mike tester @joe") + (0.01 ":irc.barnet.org 366 tester #chan :End of NAMES list") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :tester, welcome!") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :tester, welcome!") + (0.02 ":irc.barnet.org 324 tester #chan +nt") + (0.01 ":irc.barnet.org 329 tester #chan 1652938384") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: See, here he comes, and I must ply my theme.") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Confine yourself but in a patient list.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And bide the penance of each three years' day.") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Bid me farewell, and let me hear thee going.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Nor shall not, if I do as I intend.") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Our corn's to reap, for yet our tithe's to sow.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: And almost broke my heart with extreme laughter.") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Of modern seeming do prefer against him.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Like humble-visag'd suitors, his high will.") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: But yet, poor Claudio! There's no remedy.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Let him make treble satisfaction.") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: He's that he is; I may not breathe my censure.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: To check their folly, passion's solemn tears.") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: Villain, I have done thy mother.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Please you, therefore, draw nigh, and take your places.") + (0.00 ":mike!~u@6t6jcije78we2.irc PRIVMSG #chan :joe: You shall not be admitted to his sight.") + (0.00 ":joe!~u@6t6jcije78we2.irc PRIVMSG #chan :mike: Sir, you shall present before her the Nine Worthies. Sir Nathaniel, as concerning some entertainment of time, some show in the posterior of this day, to be rendered by our assistance, at the king's command, and this most gallant, illustrate, and learned gentleman, before the princess; I say, none so fit as to present the Nine Worthies.") + (0.00 ":mike!~u@6d9pasqcqwb2s.irc PRIVMSG #chan :joe: Go to; farewell! put money enough in your purse.")) diff --git a/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld b/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld new file mode 100644 index 0000000000..39c2950aa0 --- /dev/null +++ b/test/lisp/erc/resources/base/upstream-reconnect/znc-foonet.eld @@ -0,0 +1,86 @@ +;; -*- mode: lisp-data; -*- +((pass 6 "PASS :changeme")) +((nick 1 "NICK tester")) +((user 1 "USER tester@vanilla/foonet 0 * :tester") + (0.16 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0.00 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0") + (0.00 ":irc.foonet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC") + (0.00 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.00 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.01 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.01 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0.00 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0.00 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0.00 ":irc.foonet.org 254 tester 1 :channels formed") + (0.00 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0.00 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0.00 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0.00 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode 6 "MODE tester +i") + (0.00 ":tester!~u@rmtvrz9zcwbdq.irc JOIN #chan") + (0.09 ":irc.foonet.org 353 tester = #chan :@alice bob tester") + (0.00 ":irc.foonet.org 366 tester #chan :End of /NAMES list.") + (0.00 ":***!znc@znc.in PRIVMSG #chan :Buffer Playback...") + (0.00 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:11] alice: And be aveng'd on cursed Tamora.") + (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:13] bob: The stronger part of it by her own letters, which make her story true, even to the point of her death: her death itself, which could not be her office to say is come, was faithfully confirmed by the rector of the place.") + (0.01 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:15] alice: The ape is dead, and I must conjure him.") + (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:17] bob: Not so; but I answer you right painted cloth, from whence you have studied your questions.") + (0.01 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:21] alice: The valiant Paris seeks you for his love.") + (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:26] bob: To prison with her; and away with him.") + (0.00 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:30] alice: Tell them there I have gold; look, so I have.") + (0.00 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :[05:48:35] bob: Will even weigh, and both as light as tales.") + (0.00 ":***!znc@znc.in PRIVMSG #chan :Playback Complete.") + (0.00 ":irc.foonet.org 221 tester +Zi") + (0.08 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: By some vile forfeit of untimely death.")) + +((mode 3.51 "MODE #chan") + (0.1 ":irc.foonet.org 324 tester #chan +nt") + (0.0 ":irc.foonet.org 329 tester #chan 1652938384") + (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: What does this knave here ? Get you gone, sirrah: the complaints I have heard of you I do not all believe: 'tis my slowness that I do not; for I know you lack not folly to commit them, and have ability enough to make such knaveries yours.") + (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: When sects and factions were newly born.") + (0.1 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Fall, when Love please! marry, to each, but one.") + (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: For I ne'er saw true beauty till this night.") + (0.1 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Or say, sweet love, what thou desir'st to eat.") + (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: Yes, and will nobly him remunerate.") + (0.1 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC (Connection aborted). Reconnecting...") + (0.4 ":*status!znc@znc.in PRIVMSG tester :Disconnected from IRC. Reconnecting...") + (0.9 ":*status!znc@znc.in PRIVMSG tester :Connected!") + (0.0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester") + (0.0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version ergo-v2.8.0") + (0.0 ":irc.foonet.org 003 tester :This server was created Thu, 19 May 2022 05:33:02 UTC") + (0.0 ":irc.foonet.org 004 tester irc.foonet.org ergo-v2.8.0 BERTZios CEIMRUabefhiklmnoqstuv Iabefhkloqv") + (0.1 ":irc.foonet.org 005 tester AWAYLEN=390 BOT=B CASEMAPPING=ascii CHANLIMIT=#:100 CHANMODES=Ibe,k,fl,CEMRUimnstu CHANNELLEN=64 CHANTYPES=# ELIST=U EXCEPTS EXTBAN=,m FORWARD=f INVEX KICKLEN=390 :are supported by this server") + (0.0 ":irc.foonet.org 005 tester MAXLIST=beI:60 MAXTARGETS=4 MODES MONITOR=100 NETWORK=foonet NICKLEN=32 PREFIX=(qaohv)~&@%+ STATUSMSG=~&@%+ TARGMAX=NAMES:1,LIST:1,KICK:,WHOIS:1,USERHOST:10,PRIVMSG:4,TAGMSG:4,NOTICE:4,MONITOR:100 TOPICLEN=390 UTF8MAPPING=rfc8265 UTF8ONLY WHOX :are supported by this server") + (0.0 ":irc.foonet.org 005 tester draft/CHATHISTORY=100 :are supported by this server") + (0.0 ":irc.foonet.org 251 tester :There are 0 users and 3 invisible on 1 server(s)") + (0.0 ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0.0 ":irc.foonet.org 253 tester 0 :unregistered connections") + (0.1 ":irc.foonet.org 254 tester 1 :channels formed") + (0.0 ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0.0 ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0.0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0.0 ":irc.foonet.org 422 tester :MOTD File is missing") + (0.0 ":irc.foonet.org 221 tester +Zi") + (0.0 ":irc.foonet.org NOTICE tester :This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.") + (0.6 ":irc.foonet.org 352 tester * ~u rmtvrz9zcwbdq.irc irc.foonet.org tester H :0 ZNC - https://znc.in") + (0.0 ":irc.foonet.org 315 tester tester!*@* :End of WHO list") + (0.0 ":tester!~u@rmtvrz9zcwbdq.irc JOIN #chan")) + +((mode 6 "MODE #chan") + (0.0 ":irc.foonet.org 353 tester = #chan :@alice bob tester") + (0.0 ":irc.foonet.org 366 tester #chan :End of NAMES list") + (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :tester, welcome!") + (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :tester, welcome!") + (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Being of no power to make his wishes good.") + (0.0 ":irc.foonet.org 324 tester #chan +nt") + (0.0 ":irc.foonet.org 329 tester #chan 1652938384") + (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: In everything I wait upon his will.") + (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Make choice of which your highness will see first.") + (0.0 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: We waste our lights in vain, like lamps by day.") + (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: No, I know that; but it is fit I should commit offence to my inferiors.") + (0.1 ":bob!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :alice: By my head, here come the Capulets.") + (0.0 ":alice!~u@rmtvrz9zcwbdq.irc PRIVMSG #chan :bob: Well, I will forget the condition of my estate, to rejoice in yours.") + (0.0 ":bob!~u@h35cf3bf7rbt4.irc PRIVMSG #chan :alice: My lord, in heart; and let the health go round.")) + +((linger 12 LINGER)) diff --git a/test/lisp/erc/resources/erc-scenarios-common.el b/test/lisp/erc/resources/erc-scenarios-common.el new file mode 100644 index 0000000000..6b380772fe --- /dev/null +++ b/test/lisp/erc/resources/erc-scenarios-common.el @@ -0,0 +1,407 @@ +;;; erc-scenarios-common.el --- Common helpers for ERC scenarios -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;;; Commentary: + +;; These are e2e-ish test cases primarily intended to assert core, +;; fundamental behavior expected of any modern IRC client. Tests may +;; also simulate specific scenarios drawn from bug reports. Incoming +;; messages are provided by playback scripts resembling I/O logs. In +;; place of time stamps, they have time deltas, which are used to +;; govern the test server in a fashion reminiscent of music rolls (or +;; the script(1) UNIX program). These scripts can be found in the +;; other directories under test/lisp/erc/resources. +;; +;; Isolation: +;; +;; The set of enabled modules is shared among all tests. The function +;; `erc-update-modules' activates them (as minor modes), but it never +;; deactivates them. So there's no going back, and let-binding +;; `erc-modules' is useless. The safest route is therefore to (1) +;; assume the set of default modules is already activated or will be +;; over the course of the test session and (2) let-bind relevant user +;; options as needed. For example, to limit the damage of +;; `erc-autojoin-channels-alist' to a given test, assume the +;; `erc-join' library has already been loaded or will be on the next +;; call to `erc-open'. And then just let-bind +;; `erc-autojoin-channels-alist' for the duration of the test. +;; +;; Playing nice: +;; +;; Right now, these tests all rely on an ugly fixture macro named +;; `erc-scenarios-common-with-cleanup', which is defined just below. +;; It helps restore (but not really prepare) the environment by +;; destroying any stray processes or buffers named in the first +;; argument, a `let*'-style VAR-LIST. Relying on such a macro is +;; unfortunate because in many ways it actually hampers readability by +;; favoring magic over verbosity. But without it (or something +;; similar), any failing test would cause all subsequent tests in this +;; file to fail like dominoes (making all but the first backtrace +;; useless). +;; +;; Misc: +;; +;; Note that in the following examples, nicknames Alice and Bob are +;; always associated with the fake network FooNet, while nicks Joe and +;; Mike are always on BarNet. (Networks are sometimes downcased.) +;; +;; XXX This file should *not* contain any test cases. + +;;; Code: + +(require 'ert-x) ; cl-lib +(eval-and-compile + (let* ((d (expand-file-name ".." (ert-resource-directory))) + (load-path (cons (concat d "/erc-d") load-path))) + (require 'erc-d-t) + (require 'erc-d))) + +(require 'erc-backend) + +(eval-when-compile (require 'erc-join) + (require 'erc-services)) + +(declare-function erc-network "erc-networks") +(defvar erc-network) + +(defvar erc-scenarios-common--resources-dir + (expand-file-name "../" (ert-resource-directory))) + +;; Teardown is already inhibited when running interactively, which +;; prevents subsequent tests from succeeding, so we might as well +;; treat inspection as the goal. +(unless noninteractive + (setq erc-server-auto-reconnect nil)) + +(defvar erc-scenarios-common-dialog nil) +(defvar erc-scenarios-common-extra-teardown nil) + +(defun erc-scenarios-common--add-silence () + (advice-add #'erc-login :around #'erc-d-t-silence-around) + (advice-add #'erc-handle-login :around #'erc-d-t-silence-around) + (advice-add #'erc-server-connect :around #'erc-d-t-silence-around)) + +(defun erc-scenarios-common--remove-silence () + (advice-remove #'erc-login #'erc-d-t-silence-around) + (advice-remove #'erc-handle-login #'erc-d-t-silence-around) + (advice-remove #'erc-server-connect #'erc-d-t-silence-around)) + +(defun erc-scenarios-common--print-trace () + (when (and (boundp 'trace-buffer) (get-buffer trace-buffer)) + (with-current-buffer trace-buffer + (message "%S" (buffer-string)) + (kill-buffer)))) + +(eval-and-compile + (defun erc-scenarios-common--make-bindings (bindings) + `((erc-d-u-canned-dialog-dir (expand-file-name + (or erc-scenarios-common-dialog + (cadr (assq 'erc-scenarios-common-dialog + ',bindings))) + erc-scenarios-common--resources-dir)) + (erc-d-tmpl-vars `(,@erc-d-tmpl-vars + (quit . ,(erc-quit/part-reason-default)) + (erc-version . ,erc-version))) + (erc-modules (copy-sequence erc-modules)) + (inhibit-interaction t) + (auth-source-do-cache nil) + (erc-autojoin-channels-alist nil) + (erc-server-auto-reconnect nil) + (erc-d-linger-secs 10) + ,@bindings))) + +(defmacro erc-scenarios-common-with-cleanup (bindings &rest body) + "Provide boilerplate cleanup tasks after calling BODY with BINDINGS. + +If an `erc-d' process exists, wait for it to start before running BODY. +If `erc-autojoin-mode' mode is bound, restore it during cleanup if +disabled by BODY. Other defaults common to these test cases are added +below and can be overridden, except when wanting the \"real\" default +value, which must be looked up or captured outside of the calling form. + +Dialog resource directories are located by expanding the variable +`erc-scenarios-common-dialog' or its value in BINDINGS." + (declare (indent 1)) + + (let* ((orig-autojoin-mode (make-symbol "orig-autojoin-mode")) + (combind `((,orig-autojoin-mode (bound-and-true-p erc-autojoin-mode)) + ,@(erc-scenarios-common--make-bindings bindings)))) + + `(erc-d-t-with-cleanup (,@combind) + + (ert-info ("Restore autojoin, etc., kill ERC buffers") + (dolist (buf (buffer-list)) + (when-let ((erc-d-u--process-buffer) + (proc (get-buffer-process buf))) + (delete-process proc))) + + (erc-scenarios-common--remove-silence) + + (when erc-scenarios-common-extra-teardown + (ert-info ("Running extra teardown") + (funcall erc-scenarios-common-extra-teardown))) + + (when (and (boundp 'erc-autojoin-mode) + (not (eq erc-autojoin-mode ,orig-autojoin-mode))) + (erc-autojoin-mode (if ,orig-autojoin-mode +1 -1))) + + (when noninteractive + (erc-scenarios-common--print-trace) + (erc-d-t-kill-related-buffers) + (delete-other-windows))) + + (erc-scenarios-common--add-silence) + + (ert-info ("Wait for dumb server") + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when erc-d-u--process-buffer + (erc-d-t-search-for 3 "Starting"))))) + + (ert-info ("Activate erc-debug-irc-protocol") + (unless (and noninteractive (not erc-debug-irc-protocol)) + (erc-toggle-debug-irc-protocol))) + + ,@body))) + +(defun erc-scenarios-common-assert-initial-buf-name (id port) + ;; Assert no limbo period when explicit ID given + (should (string= (if id + (symbol-name id) + (format "127.0.0.1:%d" port)) + (buffer-name)))) + +(defun erc-scenarios-common-buflist (prefix) + "Return list of buffers with names sharing PREFIX." + (let (case-fold-search) + (erc-networks--id-sort-buffers + (delq nil + (mapcar (lambda (b) + (when (string-prefix-p prefix (buffer-name b)) b)) + (buffer-list)))))) + +;; This is more realistic than `erc-send-message' because it runs +;; `erc-pre-send-functions', etc. Keyboard macros may be preferable, +;; but they sometimes experience complications when an earlier test +;; has failed. +(defun erc-scenarios-common-say (str) + (let (erc-accidental-paste-threshold-seconds) + (goto-char erc-input-marker) + (insert str) + (erc-send-current-line))) + + +;;;; Fixtures + +(cl-defun erc-scenarios-common--base-network-id-bouncer + ((&key autop foo-id bar-id after + &aux + (foo-id (and foo-id 'oofnet)) + (bar-id (and bar-id 'rabnet)) + (serv-buf-foo (if foo-id "oofnet" "foonet")) + (serv-buf-bar (if bar-id "rabnet" "barnet")) + (chan-buf-foo (if foo-id "#chan@oofnet" "#chan@foonet")) + (chan-buf-bar (if bar-id "#chan@rabnet" "#chan@barnet"))) + &rest dialogs) + "Ensure retired option `erc-rename-buffers' is now the default behavior. +The option `erc-rename-buffers' is now deprecated and on by default, so +this now just asserts baseline behavior. Originally from scenario +clash-of-chans/rename-buffers as explained in Bug#48598: 28.0.50; +buffer-naming collisions involving bouncers in ERC." + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/netid/bouncer") + (erc-d-t-cleanup-sleep-secs 1) + (erc-server-flood-penalty 0.1) + (dumb-server (apply #'erc-d-run "localhost" t dialogs)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter)) + (erc-server-auto-reconnect autop) + erc-server-buffer-foo erc-server-process-foo + erc-server-buffer-bar erc-server-process-bar) + + (ert-info ("Connect to foonet") + (with-current-buffer + (setq erc-server-buffer-foo (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "foonet:changeme" + :full-name "tester" + :id foo-id)) + (setq erc-server-process-foo erc-server-process) + (erc-scenarios-common-assert-initial-buf-name foo-id port) + (erc-d-t-wait-for 3 (eq (erc-network) 'foonet)) + (erc-d-t-wait-for 3 (string= (buffer-name) serv-buf-foo)) + (funcall expect 5 "foonet"))) + + (ert-info ("Join #chan@foonet") + (with-current-buffer erc-server-buffer-foo (erc-cmd-JOIN "#chan")) + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan")) + (funcall expect 5 ""))) + + (ert-info ("Connect to barnet") + (with-current-buffer + (setq erc-server-buffer-bar (erc :server "127.0.0.1" + :port port + :nick "tester" + :password "barnet:changeme" + :full-name "tester" + :id bar-id)) + (setq erc-server-process-bar erc-server-process) + (erc-scenarios-common-assert-initial-buf-name bar-id port) + (erc-d-t-wait-for 6 (eq (erc-network) 'barnet)) + (erc-d-t-wait-for 3 (string= (buffer-name) serv-buf-bar)) + (funcall expect 5 "barnet"))) + + (ert-info ("Server buffers are unique, no names based on IPs") + (should-not (eq erc-server-buffer-foo erc-server-buffer-bar)) + (should-not (erc-scenarios-common-buflist "127.0.0.1"))) + + (ert-info ("Join #chan@barnet") + (with-current-buffer erc-server-buffer-bar (erc-cmd-JOIN "#chan"))) + + (erc-d-t-wait-for 5 "Exactly 2 #chan-prefixed buffers exist" + (equal (list (get-buffer chan-buf-bar) + (get-buffer chan-buf-foo)) + (erc-scenarios-common-buflist "#chan"))) + + (ert-info ("#chan@ is exclusive to foonet") + (with-current-buffer chan-buf-foo + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (should (eq erc-server-process erc-server-process-foo)) + (erc-d-t-search-for 10 "ape is dead") + (erc-d-t-wait-for 5 (not (erc-server-process-alive))))) + + (ert-info ("#chan@ is exclusive to barnet") + (with-current-buffer chan-buf-bar + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (erc-d-t-wait-for 5 (eq erc-server-process erc-server-process-bar)) + (erc-d-t-search-for 15 "keeps you from dishonour") + (erc-d-t-wait-for 5 (not (erc-server-process-alive))))) + + (when after (funcall after)))) + +(defun erc-scenarios-common--clash-rename-pass-handler (dialog exchange) + (when (eq (erc-d-dialog-name dialog) 'stub-again) + (let* ((match (erc-d-exchange-match exchange 1)) + (sym (if (string= match "foonet") 'foonet-again 'barnet-again))) + (should (member match (list "foonet" "barnet"))) + (erc-d-load-replacement-dialog dialog sym 1)))) + +(defun erc-scenarios-common--base-network-id-bouncer--reconnect (foo-id bar-id) + (let ((erc-d-tmpl-vars '((token . (group (| "barnet" "foonet"))))) + (erc-d-match-handlers + ;; Auto reconnect is nondeterministic, so let computer decide + (list :pass #'erc-scenarios-common--clash-rename-pass-handler)) + (after + (lambda () + ;; Simulate disconnection and `erc-server-auto-reconnect' + (ert-info ("Reconnect to foonet and barnet back-to-back") + (with-current-buffer (if foo-id "oofnet" "foonet") + (erc-d-t-wait-for 10 (erc-server-process-alive))) + (with-current-buffer (if bar-id "rabnet" "barnet") + (erc-d-t-wait-for 10 (erc-server-process-alive)))) + + (ert-info ("#chan@foonet is exclusive to foonet") + (with-current-buffer (if foo-id "#chan@oofnet" "#chan@foonet") + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (erc-d-t-search-for 20 "please your lordship"))) + + (ert-info ("#chan@barnet is exclusive to barnet") + (with-current-buffer (if bar-id "#chan@rabnet" "#chan@barnet") + (erc-d-t-search-for 1 "") + (erc-d-t-absent-for 0.1 "") + (erc-d-t-search-for 20 "much in private"))) + + ;; XXX this is important (reconnects overlapped, so we'd get + ;; chan@127.0.0.1:6667) + (should-not (erc-scenarios-common-buflist "127.0.0.1")) + ;; Reconnection order doesn't matter here because session objects + ;; are persisted, meaning original timestamps preserved. + (should (equal (list (get-buffer (if bar-id "#chan@rabnet" + "#chan@barnet")) + (get-buffer (if foo-id "#chan@oofnet" + "#chan@foonet"))) + (erc-scenarios-common-buflist "#chan")))))) + (erc-scenarios-common--base-network-id-bouncer + (list :autop t :foo-id foo-id :bar-id bar-id :after after) + 'foonet-drop 'barnet-drop + 'stub-again 'stub-again + 'foonet-again 'barnet-again))) + +(defun erc-scenarios-common--upstream-reconnect (test &rest dialogs) + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "base/upstream-reconnect") + (erc-d-t-cleanup-sleep-secs 1) + (erc-server-flood-penalty 0.1) + (dumb-server (apply #'erc-d-run "localhost" t dialogs)) + (port (process-contact dumb-server :service)) + (expect (erc-d-t-make-expecter))) + + (ert-info ("Connect to foonet") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :user "tester@vanilla/foonet" + :password "changeme" + :full-name "tester") + (erc-scenarios-common-assert-initial-buf-name nil port) + (erc-d-t-wait-for 3 (eq (erc-network) 'foonet)) + (erc-d-t-wait-for 3 (string= (buffer-name) "foonet")) + (funcall expect 5 "foonet"))) + + (ert-info ("Join #chan@foonet") + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan")) + (funcall expect 5 ""))) + + (ert-info ("Connect to barnet") + (with-current-buffer (erc :server "127.0.0.1" + :port port + :nick "tester" + :user "tester@vanilla/barnet" + :password "changeme" + :full-name "tester") + (erc-scenarios-common-assert-initial-buf-name nil port) + (erc-d-t-wait-for 10 (eq (erc-network) 'barnet)) + (erc-d-t-wait-for 3 (string= (buffer-name) "barnet")) + (funcall expect 5 "barnet"))) + + (ert-info ("Server buffers are unique, no names based on IPs") + (should-not (erc-scenarios-common-buflist "127.0.0.1"))) + + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan@foonet")) + (funcall expect 5 "#chan was created on ") + (ert-info ("Joined again #chan@foonet") + (funcall expect 10 "#chan was created on ")) + (funcall expect 10 "My lord, in heart")) + + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan@barnet")) + (funcall expect 5 "#chan was created on ") + (ert-info ("Joined again #chan@barnet") + (funcall expect 10 "#chan was created on ")) + (funcall expect 10 "Go to; farewell")) + + (funcall test))) + +(provide 'erc-scenarios-common) + +;;; erc-scenarios-common.el ends here diff --git a/test/lisp/erc/resources/networks/announced-missing/foonet.eld b/test/lisp/erc/resources/networks/announced-missing/foonet.eld new file mode 100644 index 0000000000..79b0fb462a --- /dev/null +++ b/test/lisp/erc/resources/networks/announced-missing/foonet.eld @@ -0,0 +1,8 @@ +;; -*- mode: lisp-data; -*- +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0 ":irc.foonet.org 001 tester :Welcome to the FooNet Internet Relay Chat Network tester") + (0 ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":tester MODE tester :+Zi")) diff --git a/test/lisp/erc/resources/services/password/libera.eld b/test/lisp/erc/resources/services/password/libera.eld new file mode 100644 index 0000000000..c8dbc9d425 --- /dev/null +++ b/test/lisp/erc/resources/services/password/libera.eld @@ -0,0 +1,49 @@ +;; -*- mode: lisp-data; -*- +((nick 1 "NICK tester")) +((user 1 "USER user 0 * :tester") + (0.26 ":zirconium.libera.chat NOTICE * :*** Checking Ident") + (0.01 ":zirconium.libera.chat NOTICE * :*** Looking up your hostname...") + (0.01 ":zirconium.libera.chat NOTICE * :*** No Ident response") + (0.02 ":zirconium.libera.chat NOTICE * :*** Found your hostname: static-198-54-131-100.cust.tzulo.com") + (0.02 ":zirconium.libera.chat 001 tester :Welcome to the Libera.Chat Internet Relay Chat Network tester") + (0.01 ":zirconium.libera.chat 002 tester :Your host is zirconium.libera.chat[46.16.175.175/6697], running version solanum-1.0-dev") + (0.03 ":zirconium.libera.chat 003 tester :This server was created Wed Jun 9 2021 at 01:38:28 UTC") + (0.02 ":zirconium.libera.chat 004 tester zirconium.libera.chat solanum-1.0-dev DGQRSZaghilopsuwz CFILMPQSbcefgijklmnopqrstuvz bkloveqjfI") + (0.00 ":zirconium.libera.chat 005 tester ETRACE WHOX FNC MONITOR=100 SAFELIST ELIST=CTU CALLERID=g KNOCK CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstuz :are supported by this server") + (0.03 ":zirconium.libera.chat 005 tester CHANLIMIT=#:250 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 NETWORK=Libera.Chat STATUSMSG=@+ CASEMAPPING=rfc1459 NICKLEN=16 MAXNICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D :are supported by this server") + (0.02 ":zirconium.libera.chat 005 tester TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 :are supported by this server") + (0.02 ":zirconium.libera.chat 251 tester :There are 68 users and 37640 invisible on 25 servers") + (0.00 ":zirconium.libera.chat 252 tester 36 :IRC Operators online") + (0.01 ":zirconium.libera.chat 253 tester 5 :unknown connection(s)") + (0.00 ":zirconium.libera.chat 254 tester 19341 :channels formed") + (0.01 ":zirconium.libera.chat 255 tester :I have 3321 clients and 1 servers") + (0.01 ":zirconium.libera.chat 265 tester 3321 4289 :Current local users 3321, max 4289") + (0.00 ":zirconium.libera.chat 266 tester 37708 38929 :Current global users 37708, max 38929") + (0.01 ":zirconium.libera.chat 250 tester :Highest connection count: 4290 (4289 clients) (38580 connections received)") + (0.21 ":zirconium.libera.chat 375 tester :- zirconium.libera.chat Message of the Day - ") + (0.00 ":zirconium.libera.chat 372 tester :- This server provided by Seeweb ") + (0.01 ":zirconium.libera.chat 372 tester :- Welcome to Libera Chat, the IRC network for") + (0.01 ":zirconium.libera.chat 372 tester :- free & open-source software and peer directed projects.") + (0.00 ":zirconium.libera.chat 372 tester :- ") + (0.00 ":zirconium.libera.chat 372 tester :- Use of Libera Chat is governed by our network policies.") + (0.00 ":zirconium.libera.chat 372 tester :- ") + (0.01 ":zirconium.libera.chat 372 tester :- Please visit us in #libera for questions and support.") + (0.01 ":zirconium.libera.chat 372 tester :- ") + (0.01 ":zirconium.libera.chat 372 tester :- Website and documentation: https://libera.chat") + (0.01 ":zirconium.libera.chat 372 tester :- Webchat: https://web.libera.chat") + (0.01 ":zirconium.libera.chat 372 tester :- Network policies: https://libera.chat/policies") + (0.01 ":zirconium.libera.chat 372 tester :- Email: support@libera.chat") + (0.00 ":zirconium.libera.chat 376 tester :End of /MOTD command.")) + +((mode-user 1.2 "MODE tester +i") + (0.02 ":tester MODE tester :+Zi") + (0.02 ":NickServ!NickServ@services.libera.chat NOTICE tester :This nickname is registered. Please choose a different nickname, or identify via \2/msg NickServ IDENTIFY tester \2")) + +((privmsg 2 "PRIVMSG NickServ :IDENTIFY changeme") + (0.96 ":NickServ!NickServ@services.libera.chat NOTICE tester :You are now identified for \2tester\2.") + (0.25 ":NickServ!NickServ@services.libera.chat NOTICE tester :Last login from: \2~tester@school.edu/tester\2 on Jun 18 01:15:56 2021 +0000.")) + +((quit 5 "QUIT :\2ERC\2") + (0.19 ":tester!~user@static-198-54-131-100.cust.tzulo.com QUIT :Client Quit")) + +((linger 1 LINGER)) commit 752e860db4800a26599c4cd6ca2c39ab1909b425 Author: F. Jason Park Date: Mon May 3 05:54:56 2021 -0700 Address long-standing ERC buffer-naming issues * lisp/erc/erc-backend.el (erc-server-connected): Revise doc string. (erc-server-reconnect, erc-server-JOIN): Reuse original ID param from the first connection when calling `erc-open'. (erc-server-NICK): Apply same name generation process used by `erc-open'; except here, do so for the purpose of "re-nicking". Update network identifier and maybe buffer names after a user's own nick changes. * lisp/erc/erc-networks.el (erc-networks--id, erc-networks--id-fixed, erc-networks--id-qualifying): Define new set of structs to contain all info relevant to specifying a unique identifier for a network context. Add a new variable `erc-networks--id' to store a local reference to a `erc-networks--id' object, shared among all buffers in a logical session. (erc-networks--id-given, erc-networks--id-create, erc-networks--id-on-connect, erc-networks--id--equal-p, erc-networks--id-qualifying-init-parts, erc-networks--id-qualifying-init-symbol, erc-networks--id-qualifying-grow-id, erc-networks--id-qualifying-reset-id, erc-networks--id-qualifying-prefix-length, erc-networks--id-qualifying-update, erc-networks--id-reload, erc-networks--id-ensure-comparable, erc-networks--id-sort-buffers): Add new functions to support management of `erc-networks--id' struct instances. (erc-networks--id-sep): New variable for to help when formatting buffer names. (erc-obsolete-var): Define new generic context rewriter. (erc-networks-shrink-ids-and-buffer-names, erc-networks--refresh-buffer-names, erc-networks--shrink-ids-and-buffer-names-any): Add functions to reassess all network IDs and shrink them if necessary along with affected buffer names. Also add function to rename buffers so that their names are unique. Register these on all three of ERC's kill-buffer hooks because an orphaned target buffer is enough to keep its session alive. (erc-networks-rename-surviving-target-buffer): Add new function that renames a target buffer when it becomes the sole bearer of a name based on a target that has become unique across all sessions and, in most cases, all networks. IOW, remove the @NETWORK-ID suffix from the last remaining channel or query buffer after its namesakes have all been killed off. Register this function with ERC's target-related kill-buffer hooks. (erc-networks--examine-targets): Add new utility function that visits all ERC buffers and runs callbacks when a buffer-name collision is encountered. (erc-networks--qualified-sep): Add constant to hold separator between target and suffix. (erc-networks--construct-target-buffer-name, erc-networks--ensure-unique-target-buffer-name, erc-networks--ensure-unique-server-buffer-name, erc-networks--maybe-update-buffer-name): Add helpers to support `erc-networks--reconcile-buffer-names' and friends. (erc-networks--reconcile-buffer-names): Add new buffer-naming strategy function and helper for `erc-generate-new-buffer-name' that only run in target buffers. (erc-determine-network, erc-networks--determine): Deprecate former and partially replace with latter, which demotes RPL_ISUPPORT-derived NETWORK name to fallback in favor of known `erc-networks-alist' members as part of shift to network-based connection-identity policy. Return sentinel on failure. Expect `erc-server-announced-name' to be set, and signal when it's not. (erc-networks--name-missing-sentinel): Value returned when new function `erc-networks--determine' fails to find network name. The rationale for not making this customizable is that the value signifies the pathological case where a user of an uncommon IRC setup has not yet set a mapping from announced- to network name. And the chances of there being multiple unknown networks is low. (erc-set-network-name, erc-networks--set-name): Deprecate former and partially replace with latter. Ding with helpful message, and don't set `erc-network' when network name is not found. (erc-networks--ensure-announced): Add new fallback function to ensure `erc-server-announced-name' is set. Register with post-MOTD hooks. (erc-unset-network-name): Deprecate function unused internally. (erc-networks--insert-transplanted-content, erc-networks--reclaim-orphaned-target-buffers, erc-networks--copy-over-server-buffer-contents, erc--update-server-identity): Add helpers for `erc-networks--rename-server-buffer'. The first re-associates all existing target buffers that ought to be owned by the new server process. The second grabs buffer text from an old, dead server buffer before killing it. It then inserts that text above everything in the current, replacement server buffer. The other two massage the IDs of related sessions, possibly renaming them as well. They may also uniquify the current session's network ID. (erc-networks--init-identity): Add new function to perform one-time session-related setup. This could be combined with `erc-set-network-name'. (erc-networks--rename-server-buffer): Add new function to replace `erc-unset-network-name' as default `erc-disconnected-hook' member; renames server buffers once network is discovered; added to/removed from `erc-after-connect' hook on `erc-networks' minor mode. (erc-networks--bouncer-targets): Add constant to hold target symbols of well known bouncer-configuration bots. (erc-networks-on-MOTD-end): Add primary network-context handler to run on 376/422 functions, just before logical connection is officially established. (erc-networks-enable, erc-networks-mode): Register main network-setup handler with 376/422 hooks. * lisp/erc/erc.el (erc-rename-buffers): Change this option's default to t, remove the only instance where it's actually used, and make it an obsolete variable. (erc-reuse-buffers): Make this an obsolete variable, but take pains to ensure its pre-28.1 behavior is preserved. That is, undo the regression involving unwanted automatic reassociation of channel buffers during joins, which arrived in ERC 5.4 and effectively inverted the meaning of this variable, when nil, for channel buffers, all without accompanying documentation or announcement. (erc-generate-new-buffer-name): Replace current policy of appending a slash and the invocation host name. Favor instead temporary names for server buffers and network-based uniquifying suffixes for channels and query buffers. Fall back to the TCP host:port convention when necessary. Accept additional optional params after the others. (erc-get-buffer-create): Don't generate a new name when reconnecting, just return the same buffer. `erc-open' starts from a clean slate anyway, so this just keeps things simple. Also add optional params. (erc-open): Add new ID param to for a network identifier explicitly passed to an entry-point command. This is stored in the `given' slot of the `erc-network--id' object. Also initialize the latter in new connections and otherwise copy it over. As part of the push to recast erc-networks.el as an essential library, set `erc-network' explicitly, when known, rather than via hooks. (erc, erc-tls): Add new ID keyword parameter and pass it to `erc-open'. (erc-log-irc-protocol): Use `erc--network-id' instead of the function `erc-network' to determine preferred peer name. (erc-format-target-and/or-network): This is called frequently from mode-line updates, so renaming buffers here is not ideal. Instead, do so in `erc-networks--rename-server-buffer'. (erc-kill-server-hook): Add `erc-networks-shrink-ids-and-buffer-names' as default member. (erc-kill-channel-hook, erc-kill-buffer-hook): Add `erc-networks-shrink-ids-and-buffer-names' and `erc-networks-rename-surviving-target-buffer' as default member. * test/lisp/erc/erc-tests.el (erc-log-irc-protocol): Use network-ID focused internal API. * test/lisp/erc/erc-networks-tests.el: Add new file that includes tests for the above network-ID focused functions. See bug#48598 for background on all of the above. diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 305422195b..6fb581ca7c 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -196,11 +196,9 @@ escapes removed.") "Mapping of server buffers to their specific ping timer.") (defvar-local erc-server-connected nil - "Non-nil if the current buffer has been used by ERC to establish -an IRC connection. - -If you wish to determine whether an IRC connection is currently -active, use the `erc-server-process-alive' function instead.") + "Non-nil if the current buffer belongs to an active IRC connection. +To determine whether an underlying transport is connected, use the +function `erc-server-process-alive' instead.") (defvar-local erc-server-reconnect-count 0 "Number of times we have failed to reconnect to the current server.") @@ -602,7 +600,11 @@ Make sure you are in an ERC buffer when running this." (erc-open erc-session-server erc-session-port erc-server-current-nick erc-session-user-full-name t erc-session-password nil nil nil erc-session-client-certificate - erc-session-username))))) + erc-session-username + (erc-networks--id-given erc-networks--id)) + (unless (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers) + (cl-assert (not (eq buffer (current-buffer))))))))) (defun erc-server-delayed-reconnect (buffer) (if (buffer-live-p buffer) @@ -1336,7 +1338,11 @@ add things to `%s' instead." nick erc-session-user-full-name nil nil (list chnl) chnl - erc-server-process)) + erc-server-process + nil + erc-session-username + (erc-networks--id-given + erc-networks--id))) (when buffer (set-buffer buffer) (with-suppressed-warnings @@ -1427,19 +1433,27 @@ add things to `%s' instead." ;; sent to the correct nick. also add to bufs, since the user will want ;; to see the nick change in the query, and if it's a newly begun query, ;; erc-channel-users won't contain it - (erc-buffer-filter - (lambda () - (when (equal (erc-default-target) nick) - (setq erc-default-recipients (cons nn (cdr erc-default-recipients)) - erc--target (erc--target-from-string nn)) - (rename-buffer nn t) ; bug#12002 - (erc-update-mode-line) - (cl-pushnew (current-buffer) bufs)))) + ;; + ;; Possibly still relevant: bug#12002 + (when-let ((buf (erc-get-buffer nick erc-server-process)) + (tgt (erc--target-from-string nn))) + (with-current-buffer buf + (setq erc-default-recipients (cons nn (cdr erc-default-recipients)) + erc--target tgt)) + (with-current-buffer (erc-get-buffer-create erc-session-server + erc-session-port nil tgt + (erc-networks--id-given + erc-networks--id)) + ;; Current buffer is among bufs + (erc-update-mode-line))) (erc-update-user-nick nick nn host nil nil login) (cond ((string= nick (erc-current-nick)) (cl-pushnew (erc-server-buffer) bufs) (erc-set-current-nick nn) + ;; Rename session, possibly rename server buf and all targets + (when (erc-network) + (erc-networks--id-reload erc-networks--id proc parsed)) (erc-update-mode-line) (setq erc-nick-change-attempt-count 0) (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick))) diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el index 58223f37cf..091b8aa92d 100644 --- a/lisp/erc/erc-networks.el +++ b/lisp/erc/erc-networks.el @@ -731,6 +731,466 @@ MATCHER is used to find a corresponding network to a server while (defvar-local erc-network nil "The name of the network you are connected to (a symbol).") + +;;;; Identifying session context + +;; This section is concerned with identifying and managing the +;; relationship between an IRC connection and its unique identity on a +;; given network (as seen by that network's nick-granting system). +;; This relationship is quasi-permanent and transcends IRC connections +;; and Emacs sessions. As of mid 2022, only nicknames matter, and +;; whether a user is authenticated does not directly impact network +;; identity from a client's perspective. However, ERC must be +;; equipped to adapt should this ever change. And while a connection +;; is normally associated with exactly one nick, some networks (or +;; intermediaries) may allow multiple clients to control the same nick +;; by combining instance activity into a single logical client. ERC +;; must be limber enough to handle such situations. + +(defvar-local erc-networks--id nil + "Server-local instance of its namesake struct. +Also shared among all target buffers for a given connection. See +\\[describe-symbol] `erc-networks--id' for more.") + +(cl-defstruct erc-networks--id + "Persistent identifying info for a network presence. + +Here, \"presence\" refers to some local state representing a +client's existence on a network. Some clients refer to this as a +\"context\" or a \"net-id\". The management of this state +involves tracking associated buffers and what they're displaying. +Since a presence can outlast physical connections and survive +changes in back-end transports (and even outlive Emacs sessions), +its identity must be resilient. + +Essential to this notion of an enduring existence on a network is +ensuring recovery from the loss of a server buffer. Thus, any +useful identifier must be shared among server and target buffers +to allow for reassociation. Beyond that, it must ideally be +derivable from the same set of connection parameters. See the +constructor `erc-networks--id-create' for more info." + (ts nil :type float :read-only t :documentation "Creation timestamp.") + (symbol nil :type symbol :documentation "ID as a symbol.")) + +(cl-defstruct (erc-networks--id-fixed + (:include erc-networks--id) + (:constructor erc-networks--id-fixed-create + (given &aux (ts (float-time)) (symbol given))))) + +(cl-defstruct (erc-networks--id-qualifying + (:include erc-networks--id) + (:constructor erc-networks--id-qualifying-create + (&aux + (ts (float-time)) + (parts (erc-networks--id-qualifying-init-parts)) + (symbol (erc-networks--id-qualifying-init-symbol + parts)) + (len 1)))) + "A session context composed of hierarchical connection parameters. +Two identifiers are considered equivalent when their non-empty +`parts' slots compare equal. Related identifiers share a common +prefix of `parts' taken from connection parameters (given or +discovered). An identifier's unique `symbol', intended for +display purposes, is created by concatenating the shortest common +prefix among its relatives. For example, related presences [b a +r d o] and [b a z a r] would have symbols b/a/r and b/a/z +respectively. The separator is given by `erc-networks--id-sep'." + (parts nil :type sequence ; a vector of atoms + :documentation "Sequence of identifying components.") + (len 0 :type integer + :documentation "Length of active `parts' interval.")) + +;; For now, please use this instead of `erc-networks--id-fixed-p'. +(cl-defgeneric erc-networks--id-given (net-id) + "Return the preassigned identifier for a network presence, if any. +This may have originated from an `:id' arg to entry-point commands +`erc-tls' or `erc'.") + +(cl-defmethod erc-networks--id-given ((_ erc-networks--id)) + nil) + +(cl-defmethod erc-networks--id-given ((nid erc-networks--id-fixed)) + (erc-networks--id-symbol nid)) + +(cl-generic-define-context-rewriter erc-obsolete-var (var spec) + `((with-suppressed-warnings ((obsolete ,var)) ,var) ,spec)) + +;; As a catch-all, derive the symbol from the unquoted printed repr. +(cl-defgeneric erc-networks--id-create (id) + "Invoke an appropriate constructor for an `erc-networks--id' object." + (erc-networks--id-fixed-create (intern (format "%s" id)))) + +;; When a given ID is a symbol, trust it unequivocally. +(cl-defmethod erc-networks--id-create ((id symbol)) + (erc-networks--id-fixed-create id)) + +;; Otherwise, use an adaptive name derived from network params. +(cl-defmethod erc-networks--id-create ((_ null)) + (erc-networks--id-qualifying-create)) + +;; But honor an explicitly set `erc-rename-buffers' (compat). +(cl-defmethod erc-networks--id-create + ((_ null) &context (erc-obsolete-var erc-rename-buffers null)) + (erc-networks--id-fixed-create (intern (buffer-name)))) + +;; But honor an explicitly set `erc-reuse-buffers' (compat). +(cl-defmethod erc-networks--id-create + ((_ null) &context (erc-obsolete-var erc-reuse-buffers null)) + (erc-networks--id-fixed-create (intern (buffer-name)))) + +(cl-defmethod erc-networks--id-create + ((_ symbol) &context (erc-obsolete-var erc-reuse-buffers null)) + (erc-networks--id-fixed-create (intern (buffer-name)))) + +(cl-defgeneric erc-networks--id-on-connect (net-id) + "Update NET-ID `erc-networks--id' after connection params known. +This is typically during or just after MOTD.") + +(cl-defmethod erc-networks--id-on-connect ((_ erc-networks--id)) + nil) + +(cl-defmethod erc-networks--id-on-connect ((id erc-networks--id-qualifying)) + (erc-networks--id-qualifying-update id (erc-networks--id-qualifying-create))) + +(cl-defgeneric erc-networks--id-equal-p (self other) + "Return non-nil when two network identities exhibit underlying equality. +SELF and OTHER are `erc-networks--id' struct instances. This +should normally be used only for ID recovery or merging, after +which no two identities should be `equal' (timestamps aside) that +aren't also `eq'.") + +(cl-defmethod erc-networks--id-equal-p ((self erc-networks--id) + (other erc-networks--id)) + (eq self other)) + +(cl-defmethod erc-networks--id-equal-p ((a erc-networks--id-fixed) + (b erc-networks--id-fixed)) + (or (eq a b) (eq (erc-networks--id-symbol a) (erc-networks--id-symbol b)))) + +(cl-defmethod erc-networks--id-equal-p ((a erc-networks--id-qualifying) + (b erc-networks--id-qualifying)) + (or (eq a b) (equal (erc-networks--id-qualifying-parts a) + (erc-networks--id-qualifying-parts b)))) + +;; ERASE-ME: if some future extension were to come along offering +;; additional members, e.g., [Libera.Chat "bob" laptop], it'd likely +;; be cleaner to create a new struct type descending from +;; `erc-networks--id-qualifying' than to convert this function into a +;; generic. However, the latter would be simpler because it'd just +;; require something like &context (erc-v3-device erc-v3--device-t). + +(defun erc-networks--id-qualifying-init-parts () + "Return opaque list of atoms to serve as canonical identifier." + (when-let ((network (erc-network)) + (nick (erc-current-nick))) + (vector network (erc-downcase nick)))) + +(defvar erc-networks--id-sep "/" + "Separator for joining `erc-networks--id-qualifying-parts' into a net ID.") + +(defun erc-networks--id-qualifying-init-symbol (elts &optional len) + "Return symbol appropriate for network context identified by ELTS. +Use leading interval of length LEN as contributing components. +Combine them with string separator `erc-networks--id-sep'." + (when elts + (unless len + (setq len 1)) + (intern (mapconcat (lambda (s) (prin1-to-string s t)) + (seq-subseq elts 0 len) + erc-networks--id-sep)))) + +(defun erc-networks--id-qualifying-grow-id (nid) + "Grow NID by one component or return nil when at capacity." + (unless (= (length (erc-networks--id-qualifying-parts nid)) + (erc-networks--id-qualifying-len nid)) + (setf (erc-networks--id-symbol nid) + (erc-networks--id-qualifying-init-symbol + (erc-networks--id-qualifying-parts nid) + (cl-incf (erc-networks--id-qualifying-len nid)))))) + +(defun erc-networks--id-qualifying-reset-id (nid) + "Restore NID to its initial state." + (setf (erc-networks--id-qualifying-len nid) 1 + (erc-networks--id-symbol nid) + (erc-networks--id-qualifying-init-symbol + (erc-networks--id-qualifying-parts nid)))) + +(defun erc-networks--id-qualifying-prefix-length (nid-a nid-b) + "Return length of common initial prefix of NID-A and NID-B. +Return nil when no such sequence exists (instead of zero)." + (when-let* ((a (erc-networks--id-qualifying-parts nid-a)) + (b (erc-networks--id-qualifying-parts nid-b)) + (n (min (length a) (length b))) + ((> n 0)) + ((equal (elt a 0) (elt b 0))) + (i 1)) + (while (and (< i n) + (equal (elt a i) + (elt b i))) + (cl-incf i)) + i)) + +(defun erc-networks--id-qualifying-update (dest source &rest overrides) + "Update DEST from SOURCE in place. +Copy slots into DEST from SOURCE and recompute ID. Both SOURCE +and DEST must be `erc-networks--id' objects. OVERRIDES is an +optional plist of SLOT VAL pairs." + (setf (erc-networks--id-qualifying-parts dest) + (or (plist-get overrides :parts) + (erc-networks--id-qualifying-parts source)) + (erc-networks--id-qualifying-len dest) + (or (plist-get overrides :len) + (erc-networks--id-qualifying-len source)) + (erc-networks--id-symbol dest) + (or (plist-get overrides :symbol) + (erc-networks--id-qualifying-init-symbol + (erc-networks--id-qualifying-parts dest) + (erc-networks--id-qualifying-len dest))))) + +(cl-defgeneric erc-networks--id-reload (_nid &optional _proc _parsed) + "Handle an update to the current network identity. +If provided, PROC should be the current `erc-server-process' and +PARSED the current `erc-response'. NID is an `erc-networks--id' +object." + nil) + +(cl-defmethod erc-networks--id-reload ((nid erc-networks--id-qualifying) + &optional proc parsed) + "Refresh identity after an `erc-networks--id-qualifying-parts'update." + (erc-networks--id-qualifying-update nid (erc-networks--id-qualifying-create) + :len + (erc-networks--id-qualifying-len nid)) + (erc-networks--rename-server-buffer (or proc erc-server-process) parsed) + (erc-networks--shrink-ids-and-buffer-names-any) + (erc-with-all-buffers-of-server + erc-server-process #'erc--default-target + (when-let* ((new-name (erc-networks--reconcile-buffer-names erc--target + nid)) + ((not (equal (buffer-name) new-name)))) + (rename-buffer new-name 'unique)))) + +(cl-defgeneric erc-networks--id-ensure-comparable (self other) + "Take measures to ensure two net identities are in comparable states.") + +(cl-defmethod erc-networks--id-ensure-comparable ((_ erc-networks--id) + (_ erc-networks--id)) + nil) + +(cl-defmethod erc-networks--id-ensure-comparable + ((nid erc-networks--id-qualifying) (other erc-networks--id-qualifying)) + "Grow NID along with that of the current buffer. +Rename the current buffer if its NID has grown." + (when-let ((n (erc-networks--id-qualifying-prefix-length other nid))) + (while (and (<= (erc-networks--id-qualifying-len nid) n) + (erc-networks--id-qualifying-grow-id nid))) + ;; Grow and rename a visited buffer and all its targets + (when (and (> (erc-networks--id-qualifying-len nid) + (erc-networks--id-qualifying-len other)) + (erc-networks--id-qualifying-grow-id other)) + ;; Rename NID's buffers using current ID + (erc-buffer-filter (lambda () + (when (eq erc-networks--id other) + (erc-networks--maybe-update-buffer-name))))))) + +(defun erc-networks--id-sort-buffers (buffers) + "Return a list of target BUFFERS, newest to oldest." + (sort buffers + (lambda (a b) + (> (with-current-buffer a (erc-networks--id-ts erc-networks--id)) + (with-current-buffer b (erc-networks--id-ts erc-networks--id)))))) + + +;;;; Buffer association + +(cl-defgeneric erc-networks--shrink-ids-and-buffer-names () + nil) ; concrete default implementation for non-eliding IDs + +(defun erc-networks--refresh-buffer-names (identity &optional omit) + "Ensure all colliding buffers for network IDENTITY have suffixes. +Then rename current buffer appropriately. Don't consider buffer OMIT +when determining collisions." + (if (erc-networks--examine-targets identity erc--target + #'ignore + (lambda () + (unless (or (not omit) (eq (current-buffer) omit)) + (erc-networks--ensure-unique-target-buffer-name) + t))) + (erc-networks--ensure-unique-target-buffer-name) + (rename-buffer (erc--target-string erc--target) 'unique))) + +;; This currently doesn't equalize related identities that may have +;; become mismatched because that shouldn't happen after a connection +;; is up (other than for a brief moment while renicking or similar, +;; when states are inconsistent). +(defun erc-networks--shrink-ids-and-buffer-names-any (&rest omit) + (let (grown) + ;; Gather all grown identities. + (erc-buffer-filter + (lambda () + (when (and erc-networks--id + (erc-networks--id-qualifying-p erc-networks--id) + (not (memq (current-buffer) omit)) + (not (memq erc-networks--id grown)) + (> (erc-networks--id-qualifying-len erc-networks--id) 1)) + (push erc-networks--id grown)))) + ;; Check for other identities with shared prefix. If none exists, + ;; and an identity is overlong, shrink it. + (dolist (nid grown) + (let ((skip (not (null omit)))) + (catch 'found + (if (cdr grown) + (dolist (other grown) + (unless (eq nid other) + (setq skip nil) + (when (erc-networks--id-qualifying-prefix-length nid other) + (throw 'found (setq skip t))))) + (setq skip nil))) + (unless (or skip (< (erc-networks--id-qualifying-len nid) 2)) + (erc-networks--id-qualifying-reset-id nid) + (erc-buffer-filter + (lambda () + (when (and (eq erc-networks--id nid) + (not (memq (current-buffer) omit))) + (if erc--target + (erc-networks--refresh-buffer-names nid omit) + (erc-networks--maybe-update-buffer-name)))))))))) + +(cl-defmethod erc-networks--shrink-ids-and-buffer-names + (&context (erc-networks--id erc-networks--id-qualifying)) + (erc-networks--shrink-ids-and-buffer-names-any (current-buffer))) + +(defun erc-networks-rename-surviving-target-buffer () + "Maybe drop qualifying suffix from fellow target-buffer's name. +But only do so when there's a single survivor with a target +matching that of the dying buffer." + (when-let* + (((with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers)) + (target erc--target) + ;; Buffer name includes ID suffix + ((not (string= (erc--target-symbol target) ; string= t "t" -> t + (erc-downcase (buffer-name))))) + (buf (current-buffer)) + ;; All buffers, not just those belonging to same process + (others (erc-buffer-filter + (lambda () + (and-let* ((erc--target) + ((not (eq buf (current-buffer)))) + ((eq (erc--target-symbol target) + (erc--target-symbol erc--target)))))))) + ((not (cdr others)))) + (with-current-buffer (car others) + (rename-buffer (erc--target-string target))))) + +(defun erc-networks-shrink-ids-and-buffer-names () + "Recompute network IDs and buffer names, ignoring the current buffer. +Only do so when an IRC connection's context supports qualified +naming. Do not discriminate based on whether a buffer's +connection is active." + (erc-networks--shrink-ids-and-buffer-names)) + +(defun erc-networks--examine-targets (identity target on-dupe on-collision) + "Visit all ERC target buffers with the same TARGET. +Call ON-DUPE when a buffer's identity belongs to a network +IDENTITY or \"should\" after reconciliation. Call ON-COLLISION +otherwise. Neither function should accept any args. Expect +TARGET to be an `erc--target' object." + (declare (indent 2)) + (let ((announced erc-server-announced-name)) + (erc-buffer-filter + (lambda () + (when (and erc--target (eq (erc--target-symbol erc--target) + (erc--target-symbol target))) + (let ((oursp (if (erc--target-channel-local-p target) + (equal announced erc-server-announced-name) + (erc-networks--id-equal-p identity erc-networks--id)))) + (funcall (if oursp on-dupe on-collision)))))))) + +(defconst erc-networks--qualified-sep "@" + "Separator used for naming a target buffer.") + +(defun erc-networks--construct-target-buffer-name (target) + "Return TARGET@suffix." + (concat (erc--target-string target) + (if (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers) + erc-networks--qualified-sep "/") + (cond + ((not (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers)) + (cadr (split-string + (symbol-name (erc-networks--id-symbol erc-networks--id)) + "/"))) + ((erc--target-channel-local-p target) erc-server-announced-name) + (t (symbol-name (erc-networks--id-symbol erc-networks--id)))))) + +(defun erc-networks--ensure-unique-target-buffer-name () + (when-let* ((new-name (erc-networks--construct-target-buffer-name + erc--target)) + ((not (equal (buffer-name) new-name)))) + (rename-buffer new-name 'unique))) + +(defun erc-networks--ensure-unique-server-buffer-name () + (when-let* ((new-name (symbol-name (erc-networks--id-symbol + erc-networks--id))) + ((not (equal (buffer-name) new-name)))) + (rename-buffer new-name 'unique))) + +(defun erc-networks--maybe-update-buffer-name () + "Update current buffer name to reflect display ID if necessary." + (if erc--target + (erc-networks--ensure-unique-target-buffer-name) + (erc-networks--ensure-unique-server-buffer-name))) + +(defun erc-networks--reconcile-buffer-names (target nid) + "Reserve preferred buffer name for TARGET and network identifier. +Expect TARGET to be an `erc--target' instance. Guarantee that at +most one existing buffer has the same `erc-networks--id' and a +case-mapped target, i.e., `erc--target-symbol'. If other buffers +with equivalent targets exist, rename them to TARGET@their-NID +and return TARGET@our-NID. Otherwise return TARGET as a string. +When multiple buffers for TARGET exist for the current NID, +rename them with suffixes going from newest to oldest." + (let* (existing ; Former selves or unexpected dupes (for now allow > 1) + ;; Renamed ERC buffers on other networks matching target + (namesakes (erc-networks--examine-targets nid target + (lambda () (push (current-buffer) existing) nil) + ;; Append network ID as TARGET@NID, + ;; possibly qualifying to achieve uniqueness. + (lambda () + (unless (erc--target-channel-local-p erc--target) + (erc-networks--id-ensure-comparable + nid erc-networks--id)) + (erc-networks--ensure-unique-target-buffer-name) + t))) + ;; Must follow ^ because NID may have been modified + (name (if (or namesakes (not (with-suppressed-warnings + ((obsolete erc-reuse-buffers)) + erc-reuse-buffers))) + (erc-networks--construct-target-buffer-name target) + (erc--target-string target))) + placeholder) + ;; If we don't exist, claim name temporarily while renaming others + (when-let* (namesakes + (ex (get-buffer name)) + ((not (memq ex existing))) + (temp-name (generate-new-buffer-name (format "*%s*" name)))) + (setq existing (remq ex existing)) + (with-current-buffer ex + (rename-buffer temp-name) + (setq placeholder (get-buffer-create name)) + (rename-buffer name 'unique))) + (unless (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers) + (when (string-suffix-p ">" name) + (setq name (substring name 0 -3)))) + (dolist (ex (erc-networks--id-sort-buffers existing)) + (with-current-buffer ex + (rename-buffer name 'unique))) + (when placeholder (kill-buffer placeholder)) + name)) + + ;; Functions: ;;;###autoload @@ -739,6 +1199,7 @@ MATCHER is used to find a corresponding network to a server while Use the server parameter NETWORK if provided, otherwise parse the server name and search for a match in `erc-networks-alist'." ;; The server made it easy for us and told us the name of the NETWORK + (declare (obsolete "maybe see `erc-networks--determine'" "29.1")) (let ((network-name (cdr (assoc "NETWORK" erc-server-parameters)))) (if network-name (intern network-name) @@ -761,23 +1222,242 @@ server name and search for a match in `erc-networks-alist'." (defun erc-set-network-name (_proc _parsed) "Set `erc-network' to the value returned by `erc-determine-network'." + (declare (obsolete "maybe see `erc-networks--set-name'" "29.1")) (unless erc-server-connected - (setq erc-network (erc-determine-network))) + (setq erc-network (with-suppressed-warnings + ((obsolete erc-determine-network)) + (erc-determine-network)))) + nil) + +(defconst erc-networks--name-missing-sentinel (gensym "Unknown ") + "Value to cover rare case of a literal NETWORK=nil.") + +(defun erc-networks--determine () + "Return the name of the network as a symbol. +Search `erc-networks-alist' for a known entity matching +`erc-server-announced-name'. If that fails, use the display name +given by the `RPL_ISUPPORT' NETWORK parameter." + (or (cl-loop for (name matcher) in erc-networks-alist + when (and matcher (string-match (concat matcher "\\'") + erc-server-announced-name)) + return name) + (and-let* ((vanity (erc--get-isupport-entry 'NETWORK 'single)) + ((intern vanity)))) + erc-networks--name-missing-sentinel)) + +(defun erc-networks--set-name (_proc parsed) + "Set `erc-network' to the value returned by `erc-networks--determine'. +Signal an error when the network cannot be determined." + ;; Always update (possibly clobber) current value, if any. + (let ((name (erc-networks--determine))) + (when (eq name erc-networks--name-missing-sentinel) + ;; This can happen theoretically, e.g., if you're editing some + ;; settings interactively on a proxy service that impersonates IRC + ;; but aren't being proxied through to a real network. The + ;; service may send a 422 but no NETWORK param (or *any* 005s). + (let ((m (concat "Failed to determine network. Please set entry for " + erc-server-announced-name " in `erc-network-alist'."))) + (erc-display-error-notice parsed m) + (erc-error "Failed to determine network"))) ; beep + (setq erc-network name)) + nil) + +;; This lives here in this file because all the other "on connect" +;; MOTD stuff ended up here (but perhaps that needs to change). + +(defun erc-networks--ensure-announced (_ parsed) + "Set a fallback `erc-server-announced-name' if still unset. +Copy source (prefix) from MOTD-ish message as a last resort." + ;; The 004 handler never ran; see 2004-03-10 Diane Murray in change log + (unless erc-server-announced-name + (erc-display-error-notice parsed "Failed to determine server name.") + (erc-display-error-notice + parsed (concat "If this was unexpected, consider reporting it via " + (substitute-command-keys "\\[erc-bug]") ".")) + (setq erc-server-announced-name (erc-response.sender parsed))) nil) (defun erc-unset-network-name (_nick _ip _reason) "Set `erc-network' to nil." + (declare (obsolete "`erc-network' is now effectively read-only" "29.1")) (setq erc-network nil) nil) +;; TODO add note in Commentary saying that this module is considered a +;; core module and that it's as much about buffer naming and network +;; identity as anything else. + +(defun erc-networks--insert-transplanted-content (content) + (let ((inhibit-read-only t) + (buffer-undo-list t)) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (insert-before-markers content))))) + +;; This should run whenever a network identity is updated. + +(defun erc-networks--reclaim-orphaned-target-buffers (new-proc nid announced) + "Visit disowned buffers for same NID and associate with NEW-PROC. +ANNOUNCED is the server's reported host name." + (erc-buffer-filter + (lambda () + (when (and erc--target + (not erc-server-connected) + (erc-networks--id-equal-p erc-networks--id nid) + (or (not (erc--target-channel-local-p erc--target)) + (string= erc-server-announced-name announced))) + ;; If a target buffer exists for the current process, kill this + ;; stale one after transplanting its content; else reinstate. + (if-let ((existing (erc-get-buffer + (erc--target-string erc--target) new-proc))) + (progn + (widen) + (let ((content (buffer-substring (point-min) + erc-insert-marker))) + (kill-buffer) ; allow target-buf renaming hook to run + (with-current-buffer existing + (erc-networks--ensure-unique-target-buffer-name) + (erc-networks--insert-transplanted-content content)))) + (setq erc-server-process new-proc + erc-server-connected t + erc-networks--id nid)))))) + +(defun erc-networks--copy-over-server-buffer-contents (existing name) + "Kill off existing server buffer after copying its contents. +Must be called from the replacement buffer." + ;; ERC expects `erc-open' to be idempotent when setting up local + ;; vars and other context properties for a new identity. Thus, it's + ;; unlikely we'll have to copy anything else over besides text. And + ;; no reconciling of user tables, etc. happens during a normal + ;; reconnect, so we should be fine just sticking to text. (Right?) + (let ((text (with-current-buffer existing + ;; This `erc-networks--id' should be + ;; `erc-networks--id-equal-p' to caller's network + ;; identity and older if not eq. + ;; + ;; `erc-server-process' should be set but dead + ;; and eq `get-buffer-process' unless latter nil + (delete-process erc-server-process) + (buffer-substring (point-min) erc-insert-marker))) + erc-kill-server-hook + erc-kill-buffer-hook) + (erc-networks--insert-transplanted-content text) + (kill-buffer name))) + +;; This stands alone for testing purposes + +(defun erc-networks--update-server-identity () + "Maybe grow or replace the current network identity. +If a dupe is found, adopt its identity by overwriting ours. +Otherwise, take steps to ensure it can effectively be compared to +ours, now and into the future. Note that target buffers are +considered as well because server buffers are often killed." + (let* ((identity erc-networks--id) + (buffer (current-buffer)) + (f (lambda () + (unless (or (eq (current-buffer) buffer) + (eq erc-networks--id identity)) + (if (erc-networks--id-equal-p identity erc-networks--id) + (throw 'buffer erc-networks--id) + (erc-networks--id-ensure-comparable identity + erc-networks--id) + nil)))) + (found (catch 'buffer (erc-buffer-filter f)))) + (when found + (setq erc-networks--id found)))) + +;; These steps should only run when initializing a newly connected +;; server buffer, whereas `erc-networks--rename-server-buffer' can run +;; mid-session, after an identity's core components have changed. + +(defun erc-networks--init-identity (_proc _parsed) + "Update identity with real network name." + ;; Initialize identity for real now that we know the network + (cl-assert erc-network) + (unless (erc-networks--id-symbol erc-networks--id) ; unless just reconnected + (erc-networks--id-on-connect erc-networks--id)) + ;; Find duplicate identities or other conflicting ones and act + ;; accordingly. + (erc-networks--update-server-identity) + ;; + nil) + +(defun erc-networks--rename-server-buffer (new-proc &optional _parsed) + "Rename a server buffer based on its network identity. +Assume that the current buffer is a server buffer, either one +with a newly established connection whose identity has just been +fully fleshed out, or an existing one whose identity has just +been updated. Either way, assume the current identity is ready +to serve as a canonical identifier. + +When a server buffer already exists with the chosen name, copy +over its contents and kill it. However, when its process is +still alive, kill off the current buffer. This can happen, for +example, after a perceived loss in network connectivity turns out +to be a false alarm. If `erc-reuse-buffers' is nil, let +`generate-new-buffer-name' do the actual renaming." + (cl-assert (eq new-proc erc-server-process)) + (cl-assert (erc-networks--id-symbol erc-networks--id)) + ;; Always look for targets to reassociate because original server + ;; buffer may have been deleted. + (erc-networks--reclaim-orphaned-target-buffers new-proc erc-networks--id + erc-server-announced-name) + (let* ((name (symbol-name (erc-networks--id-symbol erc-networks--id))) + ;; When this ends up being the current buffer, either we have + ;; a "given" ID or the buffer was reused on reconnecting. + (existing (get-buffer name))) + (cond ((or (not existing) + (erc-networks--id-given erc-networks--id) + (eq existing (current-buffer))) + (rename-buffer name)) + ;; Abort on accidental reconnect or failure to pass :id param for + ;; avoidable collisions. + ((erc-server-process-alive existing) + (kill-local-variable 'erc-network) + (delete-process new-proc) + (erc-display-error-notice nil (format "Buffer %s still connected" + name)) + (erc-set-active-buffer existing)) + ;; Copy over old buffer's contents and kill it + ((with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers) + (erc-networks--copy-over-server-buffer-contents existing name) + (rename-buffer name)) + (t (rename-buffer (generate-new-buffer-name name))))) + nil) + +;; Soju v0.4.0 only sends ISUPPORT on upstream reconnect, so this +;; doesn't apply. ZNC 1.8.2, however, still sends the entire burst. +(defconst erc-networks--bouncer-targets '(*status bouncerserv) + "Case-mapped symbols matching known bouncer service-bot targets.") + +(defun erc-networks-on-MOTD-end (proc parsed) + "Call on-connect functions with server PROC and PARSED message. +This must run before `erc-server-connected' is set." + (when erc-server-connected + (unless (erc-buffer-filter (lambda () + (and erc--target + (memq (erc--target-symbol erc--target) + erc-networks--bouncer-targets))) + proc) + (let ((m (concat "Unexpected state detected. Please report via " + (substitute-command-keys "\\[erc-bug]") "."))) + (erc-display-error-notice parsed m)))) + + ;; For now, retain compatibility with erc-server-NNN-functions. + (or (erc-networks--ensure-announced proc parsed) + (erc-networks--set-name proc parsed) + (erc-networks--init-identity proc parsed) + (erc-networks--rename-server-buffer proc parsed))) + (define-erc-module networks nil "Provide data about IRC networks." - ((add-hook 'erc-server-375-functions #'erc-set-network-name) - (add-hook 'erc-server-422-functions #'erc-set-network-name) - (add-hook 'erc-disconnected-hook #'erc-unset-network-name)) - ((remove-hook 'erc-server-375-functions #'erc-set-network-name) - (remove-hook 'erc-server-422-functions #'erc-set-network-name) - (remove-hook 'erc-disconnected-hook #'erc-unset-network-name))) + ((add-hook 'erc-server-376-functions #'erc-networks-on-MOTD-end) + (add-hook 'erc-server-422-functions #'erc-networks-on-MOTD-end)) + ((remove-hook 'erc-server-376-functions #'erc-networks-on-MOTD-end) + (remove-hook 'erc-server-422-functions #'erc-networks-on-MOTD-end))) (defun erc-ports-list (ports) "Return a list of PORTS. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 9f17816b8d..18a353ae49 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -134,6 +134,8 @@ (defvar erc--server-last-reconnect-count) (defvar erc--server-reconnecting) (defvar erc-channel-members-changed-hook) +(defvar erc-network) +(defvar erc-networks--id) (defvar erc-server-367-functions) (defvar erc-server-announced-name) (defvar erc-server-connect-function) @@ -210,12 +212,21 @@ parameters and authentication." :set (lambda (sym val) (set sym (if (functionp val) (funcall val) val)))) -(defcustom erc-rename-buffers nil +(defcustom erc-rename-buffers t "Non-nil means rename buffers with network name, if available." :version "24.5" :group 'erc :type 'boolean) +;; For the sake of compatibility, an ID will be created on the user's +;; behalf when `erc-rename-buffers' is nil and one wasn't provided. +;; The name will simply be that of the buffer, usually SERVER:PORT. +;; This violates the policy of treating provided IDs as gospel, but +;; it'll have to do for now. + +(make-obsolete-variable 'erc-rename-buffers + "old behavior when t now permanent" "29.1") + (defvar erc-password nil "Password to use when authenticating to an IRC server. It is not strictly necessary to provide this, since ERC will @@ -1660,6 +1671,14 @@ effect when `erc-join-buffer' is set to `frame'." (erc-channel-p (erc-default-target)))) (t nil))) +;; For the sake of compatibility, a historical quirk concerning this +;; option, when nil, has been preserved: all buffers are suffixed with +;; the original dialed host name, which is usually something like +;; irc.libera.chat. Collisions are handled by adding a uniquifying +;; numeric suffix of the form . Note that channel reassociation +;; behavior involving this option (when nil) was inverted in 28.1 (ERC +;; 5.4 and 5.4.1). This was regrettable and has since been undone. + (defcustom erc-reuse-buffers t "If nil, create new buffers on joining a channel/query. If non-nil, a new buffer will only be created when you join @@ -1669,6 +1688,9 @@ the existing buffers will be reused." :group 'erc-buffers :type 'boolean) +(make-obsolete-variable 'erc-reuse-buffers + "old behavior when t now permanent" "29.1") + (defun erc-normalize-port (port) "Normalize the port specification PORT to integer form. PORT may be an integer, a string or a symbol. If it is a string or a @@ -1704,55 +1726,61 @@ symbol, it may have these values: "Check whether ports A and B are equal." (= (erc-normalize-port a) (erc-normalize-port b))) -(defun erc-generate-new-buffer-name (server port target) - "Create a new buffer name based on the arguments." - (when (numberp port) (setq port (number-to-string port))) - (let* ((buf-name (or target - (let ((name (concat server ":" port))) - (when (> (length name) 1) - name)) - ;; This fallback should in fact never happen. - "*erc-server-buffer*")) - (full-buf-name (concat buf-name "/" server)) - (dup-buf-name (buffer-name (car (erc-channel-list nil)))) - buffer-name) - ;; Reuse existing buffers, but not if the buffer is a connected server - ;; buffer and not if its associated with a different server than the - ;; current ERC buffer. - ;; If buf-name is taken by a different connection (or by something !erc) - ;; then see if "buf-name/server" meets the same criteria. - (if (and dup-buf-name (string-match-p (concat buf-name "/") dup-buf-name)) - (setq buffer-name full-buf-name) ; ERC buffer with full name already exists. - (dolist (candidate (list buf-name full-buf-name)) - (if (and (not buffer-name) - erc-reuse-buffers - (or (not (get-buffer candidate)) - ;; Looking for a server buffer, so there's no target. - (and (not target) - (with-current-buffer (get-buffer candidate) - (and (erc-server-buffer-p) - (not (erc-server-process-alive))))) - ;; Channel buffer; check that it's from the right server. - (and target - (with-current-buffer (get-buffer candidate) - (and (string= erc-session-server server) - (erc-port-equal erc-session-port port)))))) - (setq buffer-name candidate) - (when (and (not buffer-name) (get-buffer buf-name) erc-reuse-buffers) - ;; A new buffer will be created with the name buf-name/server, rename - ;; the existing name-duplicated buffer with the same format as well. - (with-current-buffer (get-buffer buf-name) - (when (derived-mode-p 'erc-mode) ; ensure it's an erc buffer - (rename-buffer - (concat buf-name "/" (or erc-session-server erc-server-announced-name))))))))) - ;; If buffer-name is unset, neither candidate worked out for us, - ;; fallback to the old uniquification method: - (or buffer-name (generate-new-buffer-name full-buf-name)))) - -(defun erc-get-buffer-create (server port target) +(defun erc-generate-new-buffer-name (server port target &optional tgt-info id) + "Determine the name of an ERC buffer. +When TGT-INFO is nil, assume this is a server buffer. If ID is non-nil, +return ID as a string unless a buffer already exists with a live server +process, in which case signal an error. When ID is nil, return a +temporary name based on SERVER and PORT to be replaced with the network +name when discovered (see `erc-networks--rename-server-buffer'). Allow +either SERVER or PORT (but not both) to be nil to accommodate oddball +`erc-server-connect-function's. + +When TGT-INFO is non-nil, expect its string field to match the redundant +param TARGET (retained for compatibility). Whenever possibly, prefer +returning TGT-INFO's string unmodified. But when a case-insensitive +collision prevents that, return target@ID when ID is non-nil or +target@network otherwise after renaming the conflicting buffer in the +same manner." + (when target ; compat + (setq tgt-info (erc--target-from-string target))) + (if tgt-info + (let* ((esid (erc-networks--id-symbol erc-networks--id)) + (name (if esid + (erc-networks--reconcile-buffer-names tgt-info + erc-networks--id) + (erc--target-string tgt-info)))) + (if (and esid (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers)) + name + (generate-new-buffer-name name))) + (if (and (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers) + id) + (progn + (when-let* ((buf (get-buffer (symbol-name id))) + ((erc-server-process-alive buf))) + (user-error "Session with ID %S already exists" id)) + (symbol-name id)) + (generate-new-buffer-name (if (and server port) + (if (with-suppressed-warnings + ((obsolete erc-reuse-buffers)) + erc-reuse-buffers) + (format "%s:%s" server port) + (format "%s:%s/%s" server port server)) + (or server port)))))) + +(defun erc-get-buffer-create (server port target &optional tgt-info id) "Create a new buffer based on the arguments." - (get-buffer-create (erc-generate-new-buffer-name server port target))) - + (when target ; compat + (setq tgt-info (erc--target-from-string target))) + (if (and erc--server-reconnecting + (not tgt-info) + (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + erc-reuse-buffers)) + (current-buffer) + (get-buffer-create + (erc-generate-new-buffer-name server port nil tgt-info id)))) (defun erc-member-ignore-case (string list) "Return non-nil if STRING is a member of LIST. @@ -2094,7 +2122,7 @@ removed from the list will be disabled." (defun erc-open (&optional server port nick full-name connect passwd tgt-list channel process - client-certificate user) + client-certificate user id) "Connect to SERVER on PORT as NICK with USER and FULL-NAME. If CONNECT is non-nil, connect to the server. Otherwise assume @@ -2111,11 +2139,17 @@ of the client certificate itself to use when connecting over TLS, or t, which means that `auth-source' will be queried for the private key and the certificate. +When non-nil, ID should be a symbol for identifying the connection. + Returns the buffer for the given server or channel." - (let ((buffer (erc-get-buffer-create server port channel)) - (old-buffer (current-buffer)) - old-point - (continued-session (and erc-reuse-buffers erc--server-reconnecting))) + (let* ((target (and channel (erc--target-from-string channel))) + (buffer (erc-get-buffer-create server port nil target id)) + (old-buffer (current-buffer)) + old-point + (continued-session (and erc--server-reconnecting + (with-suppressed-warnings + ((obsolete erc-reuse-buffers)) + erc-reuse-buffers)))) (when connect (run-hook-with-args 'erc-before-connect server port nick)) (erc-update-modules) (set-buffer buffer) @@ -2145,7 +2179,9 @@ Returns the buffer for the given server or channel." (set-marker erc-insert-marker (point)) ;; stack of default recipients (setq erc-default-recipients tgt-list) - (setq erc--target (and channel (erc--target-from-string channel))) + (when target + (setq erc--target target + erc-network (erc-network))) (setq erc-server-current-nick nil) ;; Initialize erc-server-users and erc-channel-users (if connect @@ -2184,6 +2220,10 @@ Returns the buffer for the given server or channel." :require '(:secret)))) ;; client certificate (only useful if connecting over TLS) (setq erc-session-client-certificate client-certificate) + (setq erc-networks--id (if connect + (erc-networks--id-create id) + (buffer-local-value 'erc-networks--id + old-buffer))) ;; debug output buffer (setq erc-dbuf (when erc-log-p @@ -2322,7 +2362,8 @@ parameters SERVER and NICK." (nick (erc-compute-nick)) (user (erc-compute-user)) password - (full-name (erc-compute-full-name))) + (full-name (erc-compute-full-name)) + id) "ERC is a powerful, modular, and extensible IRC client. This function is the main entry point for ERC. @@ -2335,6 +2376,7 @@ Non-interactively, it takes the keyword arguments (user (erc-compute-user)) password (full-name (erc-compute-full-name)) + id That is, if called with @@ -2342,9 +2384,13 @@ That is, if called with then the server and full-name will be set to those values, whereas `erc-compute-port' and `erc-compute-nick' will be invoked -for the values of the other parameters." +for the values of the other parameters. + +When present, ID should be an opaque object used to identify the +connection unequivocally. This is rarely needed and not available +interactively." (interactive (erc-select-read-args)) - (erc-open server port nick full-name t password nil nil nil nil user)) + (erc-open server port nick full-name t password nil nil nil nil user id)) ;;;###autoload (defalias 'erc-select #'erc) @@ -2357,7 +2403,8 @@ for the values of the other parameters." (user (erc-compute-user)) password (full-name (erc-compute-full-name)) - client-certificate) + client-certificate + id) "ERC is a powerful, modular, and extensible IRC client. This function is the main entry point for ERC over TLS. @@ -2371,6 +2418,7 @@ Non-interactively, it takes the keyword arguments password (full-name (erc-compute-full-name)) client-certificate + id That is, if called with @@ -2393,12 +2441,18 @@ Example usage: (erc-tls :server \"irc.libera.chat\" :port 6697 :client-certificate \\='(\"/home/bandali/my-cert.key\" - \"/home/bandali/my-cert.crt\"))" + \"/home/bandali/my-cert.crt\")) + +When present, ID should be an opaque object for identifying the +connection unequivocally. (In most cases, this would be a string or a +symbol composed of letters from the Latin alphabet.) This option is +generally unneeded, however. See info node `(erc) Connecting' for use +cases. Not available interactively." (interactive (let ((erc-default-port erc-default-port-tls)) (erc-select-read-args))) (let ((erc-server-connect-function 'erc-open-tls-stream)) (erc-open server port nick full-name t password - nil nil nil client-certificate user))) + nil nil nil client-certificate user id))) (defun erc-open-tls-stream (name buffer host port &rest parameters) "Open an TLS stream to an IRC server. @@ -2463,13 +2517,20 @@ The buffer is created if it doesn't exist. If OUTBOUND is non-nil, STRING is being sent to the IRC server and appears in face `erc-input-face' in the buffer. Lines must already -contain CRLF endings. Peer is identified by the most precise label -available at run time, starting with the network name, followed by the -announced host name, and falling back to the dialed :." +contain CRLF endings. A peer is identified by the most precise label +available, starting with the session ID followed by the server-reported +hostname, and falling back to the dialed : pair. + +When capturing logs for multiple peers and sorting them into buckets, +such inconsistent labeling may pose a problem until the MOTD is +received. Setting a fixed `erc-networks--id' can serve as a +workaround." (when erc-debug-irc-protocol - (let ((esid (or (and (erc-network) (erc-network-name)) - erc-server-announced-name - (format "%s:%s" erc-session-server erc-session-port))) + (let ((esid (if-let ((erc-networks--id) + (esid (erc-networks--id-symbol erc-networks--id))) + (symbol-name esid) + (or erc-server-announced-name + (format "%s:%s" erc-session-server erc-session-port)))) (ts (when erc-debug-irc-protocol-time-format (format-time-string erc-debug-irc-protocol-time-format)))) (with-current-buffer (get-buffer-create "*erc-protocol*") @@ -3866,7 +3927,8 @@ the message given by REASON." (when process (delete-process process)) (erc-server-reconnect) - (with-suppressed-warnings ((obsolete erc-server-reconnecting)) + (with-suppressed-warnings ((obsolete erc-server-reconnecting) + ((obsolete erc-reuse-buffers))) (if erc-reuse-buffers (progn (cl-assert (not erc--server-reconnecting)) (cl-assert (not erc-server-reconnecting))) @@ -6626,21 +6688,13 @@ This should be a string with substitution variables recognized by "Return the network or the current target and network combined. If the name of the network is not available, then use the shortened server name instead." - (let ((network-name (or (and (fboundp 'erc-network-name) (erc-network-name)) - (erc-shorten-server-name - (or erc-server-announced-name - erc-session-server))))) - (when (and network-name (symbolp network-name)) - (setq network-name (symbol-name network-name))) - (cond ((erc-default-target) - (concat (erc-string-no-properties (erc-default-target)) - "@" network-name)) - ((and network-name - (not (get-buffer network-name))) - (when erc-rename-buffers - (rename-buffer network-name)) - network-name) - (t (buffer-name (current-buffer)))))) + (if-let ((erc--target) + (name (if-let ((esid (erc-networks--id-symbol erc-networks--id))) + (symbol-name esid) + (erc-shorten-server-name (or erc-server-announced-name + erc-session-server))))) + (concat (erc--target-string erc--target) "@" name) + (buffer-name))) (defun erc-format-away-status () "Return a formatted `erc-mode-line-away-status-format' if `erc-away' is non-nil." @@ -7060,20 +7114,29 @@ See also `format-spec'." ;; FIXME: Don't set the hook globally! (add-hook 'kill-buffer-hook #'erc-kill-buffer-function) -(defcustom erc-kill-server-hook '(erc-kill-server) - "Invoked whenever a server buffer is killed via `kill-buffer'." +(defcustom erc-kill-server-hook '(erc-kill-server + erc-networks-shrink-ids-and-buffer-names) + "Invoked whenever a live server buffer is killed via `kill-buffer'." + :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA :group 'erc-hooks :type 'hook) -(defcustom erc-kill-channel-hook '(erc-kill-channel) +(defcustom erc-kill-channel-hook + '(erc-kill-channel + erc-networks-shrink-ids-and-buffer-names + erc-networks-rename-surviving-target-buffer) "Invoked whenever a channel-buffer is killed via `kill-buffer'." + :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA :group 'erc-hooks :type 'hook) -(defcustom erc-kill-buffer-hook nil - "Hook run whenever a non-server or channel buffer is killed. +(defcustom erc-kill-buffer-hook + '(erc-networks-shrink-ids-and-buffer-names + erc-networks-rename-surviving-target-buffer) + "Hook run whenever a query buffer is killed. See also `kill-buffer'." + :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA :group 'erc-hooks :type 'hook) diff --git a/test/lisp/erc/erc-networks-tests.el b/test/lisp/erc/erc-networks-tests.el new file mode 100644 index 0000000000..dcda04692e --- /dev/null +++ b/test/lisp/erc/erc-networks-tests.el @@ -0,0 +1,1707 @@ +;;; erc-networks-tests.el --- Tests for erc-networks. -*- lexical-binding:t -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published +;; by the Free Software Foundation, either version 3 of the License, +;; or (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + +(require 'ert-x) ; cl-lib +(require 'erc-networks) + +(defun erc-networks-tests--create-dead-proc (&optional buf) + (let ((p (start-process "true" (or buf (current-buffer)) "true"))) + (while (process-live-p p) (sit-for 0.1)) + p)) + +(defun erc-networks-tests--create-live-proc (&optional buf) + (let ((proc (start-process "sleep" (or buf (current-buffer)) "sleep" "1"))) + (set-process-query-on-exit-flag proc nil) + proc)) + +;; When we drop 27, call `get-buffer-create with INHIBIT-BUFFER-HOOKS. +(defun erc-networks-tests--clean-bufs () + (let (erc-kill-channel-hook + erc-kill-server-hook + erc-kill-buffer-hook) + (dolist (buf (erc-buffer-list)) + (kill-buffer buf)))) + +(defun erc-networks-tests--bufnames (prefix) + (let* ((case-fold-search) + (pred (lambda (b) (string-prefix-p prefix (buffer-name b)))) + (prefixed (seq-filter pred (buffer-list)))) + (sort (mapcar #'buffer-name prefixed) #'string<))) + +(ert-deftest erc-networks--id () + (cl-letf (((symbol-function 'float-time) + (lambda () 0.0))) + + ;; Fixed + (should (equal (erc-networks--id-fixed-create 'foo) + (make-erc-networks--id-fixed :ts (float-time) + :symbol 'foo))) + + ;; Eliding + (let* ((erc-network 'FooNet) + (erc-server-current-nick "Joe") + (identity (erc-networks--id-create nil))) + + (should (equal identity #s(erc-networks--id-qualifying + 0.0 FooNet [FooNet "joe"] 1))) + (should (equal (erc-networks--id-qualifying-grow-id identity) + 'FooNet/joe)) + (should (equal identity #s(erc-networks--id-qualifying + 0.0 FooNet/joe [FooNet "joe"] 2))) + (should-not (erc-networks--id-qualifying-grow-id identity)) + (should (equal identity #s(erc-networks--id-qualifying + 0.0 FooNet/joe [FooNet "joe"] 2)))) + + ;; Compat + (with-current-buffer (get-buffer-create "fake.chat") + (with-suppressed-warnings ((obsolete erc-rename-buffers)) + (let (erc-rename-buffers) + (should (equal (erc-networks--id-create nil) + (make-erc-networks--id-fixed :ts (float-time) + :symbol 'fake.chat))))) + (kill-buffer)))) + +(ert-deftest erc-networks--id-create () + (cl-letf (((symbol-function 'float-time) + (lambda () 0.0))) + + (should (equal (erc-networks--id-create 'foo) + (make-erc-networks--id-fixed :ts (float-time) + :symbol 'foo))) + (should (equal (erc-networks--id-create "foo") + (make-erc-networks--id-fixed :ts (float-time) + :symbol 'foo))) + (should (equal (erc-networks--id-create [h i]) + (make-erc-networks--id-fixed :ts (float-time) + :symbol (quote \[h\ \i\])))) + + (with-current-buffer (get-buffer-create "foo") + (let ((expected (make-erc-networks--id-fixed :ts (float-time) + :symbol 'foo))) + (with-suppressed-warnings ((obsolete erc-rename-buffers)) + (let (erc-rename-buffers) + (should (equal (erc-networks--id-create nil) expected)))) + (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + (let (erc-reuse-buffers) + (should (equal (erc-networks--id-create nil) expected)) + (should (equal (erc-networks--id-create 'bar) expected))))) + (kill-buffer)))) + +(ert-deftest erc-networks--id-qualifying-prefix-length () + (should-not (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying) + (make-erc-networks--id-qualifying))) + + (should-not (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts [1 2]) + (make-erc-networks--id-qualifying :parts [2 3]))) + + (should (= 1 (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts [1]) + (make-erc-networks--id-qualifying :parts [1 2])))) + + (should (= 1 (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts [1 2]) + (make-erc-networks--id-qualifying :parts [1 3])))) + + (should (= 2 (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts [1 2]) + (make-erc-networks--id-qualifying :parts [1 2])))) + + (should (= 1 (erc-networks--id-qualifying-prefix-length + (make-erc-networks--id-qualifying :parts ["1"]) + (make-erc-networks--id-qualifying :parts ["1"]))))) + +(ert-deftest erc-networks--id-sort-buffers () + (let (oldest middle newest) + + (with-temp-buffer + (setq erc-networks--id (erc-networks--id-fixed-create 'oldest) + oldest (current-buffer)) + + (with-temp-buffer + (setq erc-networks--id (erc-networks--id-fixed-create 'middle) + middle (current-buffer)) + + (with-temp-buffer + (setq erc-networks--id (erc-networks--id-fixed-create 'newest) + newest (current-buffer)) + + (should (equal (erc-networks--id-sort-buffers + (list oldest newest middle)) + (list newest middle oldest)))))))) + +(ert-deftest erc-networks-rename-surviving-target-buffer--channel () + (should (memq #'erc-networks-rename-surviving-target-buffer + erc-kill-channel-hook)) + + (let ((chan-foonet-buffer (get-buffer-create "#chan@foonet"))) + + (with-current-buffer chan-foonet-buffer + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1) + erc--target (erc--target-from-string "#chan"))) + + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [barnet "bob"] :len 1) + erc--target (erc--target-from-string "#chan"))) + + (kill-buffer "#chan@barnet") + (should (equal (erc-networks-tests--bufnames "#chan") '("#chan"))) + (should (eq chan-foonet-buffer (get-buffer "#chan")))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks-rename-surviving-target-buffer--query () + (should (memq #'erc-networks-rename-surviving-target-buffer + erc-kill-buffer-hook)) + + (let ((bob-foonet (get-buffer-create "bob@foonet"))) + + (with-current-buffer bob-foonet + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1) + erc--target (erc--target-from-string "bob"))) + + (with-current-buffer (get-buffer-create "bob@barnet") + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [barnet "bob"] :len 1) + erc--target (erc--target-from-string "bob"))) + + (kill-buffer "bob@barnet") + (should (equal (erc-networks-tests--bufnames "bob") '("bob"))) + (should (eq bob-foonet (get-buffer "bob")))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks-rename-surviving-target-buffer--multi () + + (ert-info ("Multiple leftover channels untouched") + (with-current-buffer (get-buffer-create "#chan@foonet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan"))) + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan"))) + (with-current-buffer (get-buffer-create "#chan@baznet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan"))) + (kill-buffer "#chan@baznet") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet"))) + (erc-networks-tests--clean-bufs)) + + (ert-info ("Multiple leftover queries untouched") + (with-current-buffer (get-buffer-create "bob@foonet") + (erc-mode) + (setq erc--target (erc--target-from-string "bob"))) + (with-current-buffer (get-buffer-create "bob@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "bob"))) + (with-current-buffer (get-buffer-create "bob@baznet") + (erc-mode) + (setq erc--target (erc--target-from-string "bob"))) + (kill-buffer "bob@baznet") + (should (equal (erc-networks-tests--bufnames "bob") + '("bob@barnet" "bob@foonet"))) + (erc-networks-tests--clean-bufs))) + +;; As of May 2022, this "shrink" stuff runs whenever an ERC buffer is +;; killed because `erc-networks-shrink-ids-and-buffer-names' is a +;; default member of all three erc-kill-* functions. + +;; Note: this overlaps a fair bit with the "hook" variants, i.e., +;; `erc-networks--shrink-ids-and-buffer-names--hook-outstanding-*' If +;; this ever fails, just delete this and fix those. But please copy +;; over and adapt the comments first. + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--perform-outstanding () + ;; While some buffer #a@barnet/dummy is being killed, its display ID + ;; is not collapsed because collisions still exist. + ;; + ;; Note that we don't have to set `erc-server-connected' because + ;; this function is intentionally connectivity agnostic. + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-server-current-nick "tester" ; Always set (`erc-open') + ;; Set when transport connected + erc-server-process (erc-networks-tests--create-live-proc) + ;; Both set just before IRC (logically) connected (post MOTD) + erc-network 'foonet + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2))) ; is/was a plain foonet collision + + ;; Presumably, some server buffer named foonet/dummy was just + ;; killed, hence the length 2 display ID. + + ;; A target buffer for chan #a exists for foonet/tester. The + ;; precise form of its name should not affect shrinking. + (with-current-buffer (get-buffer-create + (elt ["#a" "#a@foonet" "#a@foonet/tester"] (random 3))) + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/tester")) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/tester")) + erc--target (erc--target-from-string "#a"))) + + ;; Another network context exists (so we have buffers to iterate + ;; over), and it's also part of a collision group. + (with-current-buffer (get-buffer-create "barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/tester + :parts [barnet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "barnet/dummy") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/dummy + :parts [barnet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + ;; The buffer being killed is not part of the foonet collision + ;; group, which contains one display ID eligible for shrinkage. + (with-current-buffer (get-buffer-create + (elt ["#a@barnet" "#a@barnet/tester"] (random 2))) + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet/tester")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet/tester")) + erc--target (erc--target-from-string "#a"))) + + (with-temp-buffer ; doesn't matter what the current buffer is + (setq erc-networks--id (make-erc-networks--id-qualifying)) ; mock + (erc-networks--shrink-ids-and-buffer-names)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" ; shrunk + "#a@foonet" ; shrunk + "barnet/tester" + "barnet/dummy" + "#a@barnet/tester"))) + + (erc-networks-tests--clean-bufs)) + +;; This likewise overlaps with the "hook" variants below. If this +;; should ever fail, just delete it and optionally fix those. + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--perform-collapse () + ;; This is similar to the "outstanding" variant above, but both + ;; groups are eligible for renaming, which is abnormal but possible + ;; when recovering from some mishap. + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer + (get-buffer-create (elt ["#a" "#a@foonet/tester"] (random 2))) + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/tester")) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/tester")) + erc--target (erc--target-from-string "#a"))) + + (with-current-buffer (get-buffer-create "barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/tester + :parts [barnet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer + (get-buffer-create (elt ["#b" "#b@foonet/tester"] (random 2))) + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet/tester")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet/tester")) + erc--target (erc--target-from-string "#b"))) + + (with-temp-buffer + (setq erc-networks--id (make-erc-networks--id-qualifying)) + (erc-networks--shrink-ids-and-buffer-names)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" "#a" "barnet" "#b"))) + + (erc-networks-tests--clean-bufs)) + +(defun erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common () + + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#a@foonet/tester") + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/tester")) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/tester")) + erc--target (erc--target-from-string "#a"))) + + (with-current-buffer (get-buffer-create "barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/tester + :parts [barnet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "barnet/dummy") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/dummy + :parts [barnet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#a@barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet/tester")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet/tester")) + erc--target (erc--target-from-string "#a")))) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-outstanding-srv () + (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common) + (with-current-buffer (get-buffer-create "foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc)) + (kill-buffer)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" + "#a@foonet" + "barnet/tester" + "barnet/dummy" + "#a@barnet/tester"))) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-outstanding-tgt () + (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common) + (with-current-buffer (get-buffer-create "#a@foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + erc--target (erc--target-from-string "#a") + erc-server-process (with-temp-buffer + (erc-networks-tests--create-dead-proc)))) + + (with-current-buffer "#a@foonet/dummy" (kill-buffer)) + + ;; Identical to *-server variant above + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" + "#a@foonet" + "barnet/tester" + "barnet/dummy" + "#a@barnet/tester"))) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks-rename-surviving-target-buffer--shrink () + (erc-networks--shrink-ids-and-buffer-names--hook-outstanding-common) + + ;; This buffer isn't "#a@foonet" (yet) because the shrink-ids hook + ;; hasn't run. However, when it's the rename hook runs, its network + ;; id *is* "foonet", not "foonet/tester". + (with-current-buffer "#a@foonet/tester" (kill-buffer)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" + "barnet/tester" + "barnet/dummy" + "#a"))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--server () + + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-dead-proc)) + (kill-buffer)) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) '("foonet"))) + + (erc-networks-tests--clean-bufs)) + +(defun erc-networks--shrink-ids-and-buffer-names--hook-collapse (check) + + (with-current-buffer (get-buffer-create "foonet/tester") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/tester + :parts [foonet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#a@foonet/tester") + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/tester")) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/tester")) + erc--target (erc--target-from-string "#a"))) + + (with-current-buffer (get-buffer-create "barnet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'barnet/tester + :parts [barnet "tester"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#b@foonet/tester") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet/tester")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet/tester")) + erc--target (erc--target-from-string "#b"))) + + (funcall check) + + (should (equal (mapcar #'buffer-name (erc-buffer-list)) + '("foonet" "#a" "barnet" "#b"))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-collapse-server () + (erc-networks--shrink-ids-and-buffer-names--hook-collapse + (lambda () + (with-current-buffer (get-buffer-create "foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc)) + (kill-buffer))))) + +(ert-deftest erc-networks--shrink-ids-and-buffer-names--hook-collapse-target () + (erc-networks--shrink-ids-and-buffer-names--hook-collapse + (lambda () + (with-current-buffer (get-buffer-create "#a@foonet/dummy") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "dummy" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/dummy + :parts [foonet "dummy"] + :len 2) + ;; `erc-kill-buffer-function' uses legacy target detection + ;; but falls back on buffer name, so no need for: + ;; + ;; erc-default-recipients '("#a") + ;; + erc--target (erc--target-from-string "#a") + erc-server-process (with-temp-buffer + (erc-networks-tests--create-dead-proc))) + (kill-buffer))))) + +;; FIXME this test is old and may describe impossible states: +;; leftover identities being qual-equal but not eq (implies +;; `erc-networks--reclaim-orphaned-target-buffers' is somehow broken). +;; +;; Otherwise, the point of this test is to show that server process +;; identity does not impact the hunt for duplicates. + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates (start) + + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-process (funcall start))) + + (with-current-buffer (get-buffer-create "#chan") ; prior session + (erc-mode) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet")) + erc--target (erc--target-from-string "#chan") + erc-networks--id (erc-networks--id-create nil))) + + (ert-info ("Conflicts not recognized as ERC buffers and not renamed") + (get-buffer-create "#chan@foonet") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan" "#chan@foonet")))) + + ;; These are dupes (not "collisions") + + (with-current-buffer "#chan@foonet" ; same proc + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-network 'foonet + erc-server-current-nick "tester" + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet")) + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "#chan@foonet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (erc-networks-tests--create-dead-proc) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "#chan@foonet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (erc-networks-tests--create-live-proc) + erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil))) + + (let ((created (list (get-buffer "#chan@foonet") + (get-buffer "#chan@foonet") + (get-buffer "#chan@foonet")))) + + (with-current-buffer "foonet" + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan"))) + + (ert-info ("All buffers considered dupes renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan" "#chan<2>" "#chan<3>" "#chan<4>")))) + + (ert-info ("All buffers renamed from newest to oldest") + (should (equal created (list (get-buffer "#chan<2>") + (get-buffer "#chan<3>") + (get-buffer "#chan<4>")))))) + + (erc-networks-tests--clean-bufs)) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given (go) + + ;; The connection's network is discovered before target buffers are + ;; created. This shows that the network doesn't matter when only + ;; "given" IDs are present. + (with-current-buffer (get-buffer-create "oofnet") + (erc-mode) + (setq erc-networks--id (erc-networks--id-create 'oofnet) + erc-network 'foonet + erc-server-current-nick "tester" + erc-server-process (funcall go))) + + (with-current-buffer (get-buffer-create "#chan") ; prior session + (erc-mode) + (setq erc-networks--id (erc-networks--id-create 'oofnet) + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "oofnet")) + erc--target (erc--target-from-string "#chan"))) + + (with-current-buffer (get-buffer-create "#chan@oofnet") ;dupe/not collision + (erc-mode) + (setq erc-networks--id (erc-networks--id-create 'oofnet) + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "oofnet")) + erc--target (erc--target-from-string "#chan"))) + + (with-current-buffer "oofnet" + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan"))) + + (ert-info ("All buffers matching target and network renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan" "#chan<2>")))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--duplicates () + (ert-info ("Process live, no error") + (erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates + #'erc-networks-tests--create-live-proc)) + + (ert-info ("Process live, no error, given ID") + (erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given + #'erc-networks-tests--create-live-proc)) + + (ert-info ("Process dead") + (erc-tests--prep-erc-networks--reconcile-buffer-names--duplicates + #'erc-networks-tests--create-dead-proc)) + + (ert-info ("Process dead, given ID") + (erc-tests--prep-erc-networks--reconcile-buffer-names--dupes-given + #'erc-networks-tests--create-dead-proc))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf (check) + (let ((foonet-proc (with-temp-buffer + (erc-networks-tests--create-dead-proc)))) + (with-current-buffer (get-buffer-create "barnet") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-process (erc-networks-tests--create-dead-proc))) + + ;; Different proc and not "qual-equal" (different elts) + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc--target (erc--target-from-string "#chan") + erc-server-process foonet-proc)) + (funcall check) + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--reconcile-buffer-names--no-server-buf () + (ert-info ("Existing #chan buffer respected") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf + (lambda () + (with-current-buffer "barnet" + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@barnet"))) + (ert-info ("Existing #chan buffer found and renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@foonet"))))))) + + (ert-info ("Existing #chan buffer") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf + (lambda () + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) + erc-server-process (erc-networks-tests--create-dead-proc)) + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan"))) + (ert-info ("Nothing renamed") + (should (equal (erc-networks-tests--bufnames "#chan") '("#chan"))))))) + + (ert-info ("Existing #chan@foonet and #chan@barnet buffers") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf + (lambda () + (with-current-buffer "#chan" + (rename-buffer "#chan@foonet")) + (should-not (get-buffer "#chan@barnet")) + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet")) + erc-networks--id (erc-networks--id-create nil))) + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (set-process-query-on-exit-flag erc-server-process nil) + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@foonet"))) + (ert-info ("Nothing renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet")))))))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given + (check) + (let ((oofnet-proc (with-temp-buffer + (erc-networks-tests--create-dead-proc)))) + + (with-current-buffer (get-buffer-create "rabnet") + (erc-mode) + ;; Again, given name preempts network lookup (unrealistic but + ;; highlights priorities) + (setq erc-networks--id (erc-networks--id-create 'rabnet) + erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-dead-proc))) + + ;; Identity is not "qual-equal" to above + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-networks--id (erc-networks--id-create 'oofnet) + erc-network 'foonet + erc--target (erc--target-from-string "#chan") + erc-server-process oofnet-proc)) + (funcall check) + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--reconcile-buffer-names--no-server-buf-given () + + (ert-info ("Existing #chan buffer respected") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given + (lambda () + (with-current-buffer "rabnet" + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@rabnet"))) + + (ert-info ("Existing #chan buffer found and renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet"))))))) + + (ert-info ("Existing #chan@oofnet and #chan@rabnet buffers") + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given + (lambda () + ;; #chan has already been uniquified (but not grown) + (with-current-buffer "#chan" (rename-buffer "#chan@oofnet")) + (should-not (get-buffer "#chan@rabnet")) + + (with-current-buffer (get-buffer-create "#chan@rabnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "rabnet")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "rabnet")))) + + (with-current-buffer (get-buffer-create "oofnet") + (erc-mode) + (setq erc-network 'oofnet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create 'oofnet)) ; given + (set-process-query-on-exit-flag erc-server-process nil) + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@oofnet"))) + + (ert-info ("Nothing renamed") + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet" "#chan@rabnet")))))))) + +;; This shows a corner case where a user explicitly assigns a "given" +;; ID via `erc-tls' but later connects again without one. It would +;; actually probably be better if the given identity were to win and +;; the derived one got an -suffix. +;; +;; If we just compared net identities, the two would match, but they +;; don't here because one has a given name and the other a +;; discovered/assembled one; so they are *not* qual-equal. +(ert-deftest erc-networks--reconcile-buffer-names--no-srv-buf-given-mismatch () + ;; Existing #chan buffer *not* respected + (erc-tests--prep-erc-networks--reconcile-buffer-names--no-srv-buf-given + (lambda () + (with-current-buffer (get-buffer-create "oofnet") + (erc-mode) + (setq erc-network 'oofnet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-dead-proc) + erc-networks--id (erc-networks--id-create nil)) ; derived + (should (string= (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id) + "#chan@oofnet"))) + + (ert-info ("Collision renamed but not grown (because it's a given)") + ;; Original chan uniquified and moved out of the way + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet<2>"))))))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net (check) + + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-dead-proc) + erc-networks--id (erc-networks--id-create nil))) ; derived + + (with-current-buffer (get-buffer-create "barnet") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-dead-proc) + erc-networks--id (erc-networks--id-create nil))) ; derived + + (with-current-buffer + (get-buffer-create (elt ["#chan" "#chan@foonet"] (random 2))) + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "foonet" + (list erc-server-process erc-networks--id)))) + + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "barnet" + (list erc-server-process erc-networks--id)))) + + (funcall check) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--multi-net () + (ert-info ("Same network rename") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net + (lambda () + (with-current-buffer "foonet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@foonet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet")))))) + + (ert-info ("Same network keep name") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net + (lambda () + (with-current-buffer "barnet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@barnet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet"))))))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given + (check) + + (with-current-buffer (get-buffer-create "oofnet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create 'oofnet) ; one given + erc-server-process (erc-networks-tests--create-dead-proc))) + + (with-current-buffer (get-buffer-create "rabnet") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create 'rabnet) ; another given + erc-server-process (erc-networks-tests--create-dead-proc))) + + (with-current-buffer (get-buffer-create (elt ["chan" "#chan@oofnet"] + (random 2))) + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "oofnet" + (list erc-server-process erc-networks--id)))) + + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "rabnet" + (list erc-server-process erc-networks--id)))) + + (funcall check) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--multi-net-given () + (ert-info ("Same network rename") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given + (lambda () + (with-current-buffer "oofnet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@oofnet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet" "#chan@rabnet")))))) + + (ert-info ("Same network keep name") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-given + (lambda () + (with-current-buffer "rabnet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@rabnet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@oofnet" "#chan@rabnet"))))))) + +(defun erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed + (check) + + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create nil) ; one derived + erc-server-process (erc-networks-tests--create-dead-proc))) + + (with-current-buffer (get-buffer-create "my-conn") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick "tester" + erc-networks--id (erc-networks--id-create 'my-conn) ; one given + erc-server-process (erc-networks-tests--create-dead-proc))) + + (with-current-buffer (get-buffer-create (elt ["#chan" "#chan@foonet"] + (random 2))) + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "foonet" + (list erc-server-process erc-networks--id)))) + + (with-current-buffer (get-buffer-create "#chan@my-conn") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan")) + (cl-multiple-value-setq (erc-server-process erc-networks--id) + (with-current-buffer "my-conn" + (list erc-server-process erc-networks--id)))) + + (funcall check) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--multi-net-existing () + + (ert-info ("Buf name derived from network") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed + (lambda () + (with-current-buffer "foonet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@foonet")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@foonet" "#chan@my-conn")))))) + + (ert-info ("Buf name given") + (erc-tests--prep-erc-networks--reconcile-buffer-names--multi-net-mixed + (lambda () + (with-current-buffer "my-conn" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@my-conn")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@foonet" "#chan@my-conn"))))))) + +(ert-deftest erc-networks--reconcile-buffer-names--multi-net-suffixed () + ;; Two networks, same channel. One network has two connections. + ;; When the same channel is joined on the latter under a different + ;; nick, all buffer names involving that network are suffixed with + ;; the network identity. + + (with-current-buffer (get-buffer-create "foonet/bob") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "bob" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/bob + :parts [foonet "bob"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create + (elt ["#chan@foonet" "#chan@foonet/bob"] (random 2))) + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "foonet/bob")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/bob")))) + + (with-current-buffer (get-buffer-create "barnet") + (erc-mode) + (setq erc-network 'barnet + erc-server-current-nick (elt ["alice" "bob"] (random 2)) + erc-networks--id (erc-networks--id-create 'barnet) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer (get-buffer-create "#chan@barnet") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "barnet")) + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "barnet")))) + + (with-current-buffer (get-buffer-create "foonet/alice") + (erc-mode) + (setq erc-network 'foonet + erc-server-current-nick "alice" + erc-networks--id (make-erc-networks--id-qualifying + :symbol 'foonet/alice + :parts [foonet "alice"] + :len 2) + erc-server-process (erc-networks-tests--create-live-proc))) + + (with-current-buffer "foonet/alice" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "#chan") erc-networks--id))) + (should (string= result "#chan@foonet/alice")))) + + (should (equal (erc-networks-tests--bufnames "#chan") + '("#chan@barnet" "#chan@foonet/bob"))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--reconcile-buffer-names--local () + (with-current-buffer (get-buffer-create "DALnet") + (erc-mode) + (setq erc-network 'DALnet + erc-server-announced-name "elysium.ga.us.dal.net" + erc-server-process (erc-networks-tests--create-dead-proc) + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + (puthash 'CHANTYPES '("&#") erc--isupport-params)) + + (ert-info ("Local chan buffer from older, disconnected identity") + (with-current-buffer (get-buffer-create "&chan") + (erc-mode) + ;; Cheat here because localp is determined on identity init + (setq erc--target (with-current-buffer "DALnet" + (erc--target-from-string "&chan")) + erc-network 'DALnet + erc-server-announced-name "twisted.ma.us.dal.net" + erc-server-process (erc-networks-tests--create-dead-proc) + erc-networks--id (erc-networks--id-create nil)))) + + (ert-info ("Local channels renamed using network server names") + (with-current-buffer "DALnet" + (let ((result (erc-networks--reconcile-buffer-names + (erc--target-from-string "&chan") erc-networks--id))) + (should (string= result "&chan@elysium.ga.us.dal.net"))))) + + (should (get-buffer "&chan@twisted.ma.us.dal.net")) + (should-not (get-buffer "&chan")) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--set-name () + (with-current-buffer (get-buffer-create "localhost:6667") + (let (erc-server-announced-name + (erc--isupport-params (make-hash-table)) + erc-network + calls) + (erc-mode) + + (cl-letf (((symbol-function 'erc-display-line) + (lambda (&rest r) (push r calls)))) + + (ert-info ("Signals when `erc-server-announced-name' unset") + (should-error (erc-networks--set-name nil (make-erc-response))) + (should-not calls)) + + (ert-info ("Signals when table empty and NETWORK param unset") + (setq erc-server-announced-name "irc.fake.gnu.org") + (let ((err (should-error (erc-networks--set-name + nil (make-erc-response))))) + (should (string-match-p "failed" (cadr err))) + (should (eq (car err) 'error))) + (should (string-match-p "*** Failed" (car (pop calls))))))) + + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--ensure-announced () + (with-current-buffer (get-buffer-create "localhost:6667") + (should (local-variable-if-set-p 'erc-server-announced-name)) + (let (erc-insert-modify-hook + (erc-server-process (erc-networks-tests--create-live-proc)) + (parsed (make-erc-response + :unparsed ":irc.barnet.org 422 tester :MOTD File is missing" + :sender "irc.barnet.org" + :command "422" + :command-args '("tester" "MOTD File is missing") + :contents "MOTD File is missing"))) + + (erc-mode) ; boilerplate displayable start (needs `erc-server-process') + (insert "\n\n") + (setq erc-input-marker (make-marker) erc-insert-marker (make-marker)) + (set-marker erc-insert-marker (point-max)) + (erc-display-prompt) ; boilerplate displayable end + + (erc-networks--ensure-announced erc-server-process parsed) + (goto-char (point-min)) + (search-forward "Failed") + (should (string= erc-server-announced-name "irc.barnet.org"))) + (when noninteractive (kill-buffer)))) + +(ert-deftest erc-networks--rename-server-buffer--no-existing--orphan () + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc--target (erc--target-from-string "#chan") + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet"))) + + (ert-info ("Channel buffer reassociated") + (erc-server-process-alive "#chan") + (with-current-buffer "#chan" + (should erc-server-connected) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet"))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--existing--reuse () + (let* ((old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil) + erc--target (erc--target-from-string "#chan"))) + + (ert-info ("New buffer steals name, content") + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer reassociated") + (erc-server-process-alive "#chan") + (with-current-buffer "#chan" + (should erc-server-connected) + (should-not (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet"))))) + + (ert-info ("Original buffer killed off") + (should-not (buffer-live-p old-buf)))) + + (erc-networks-tests--clean-bufs)) + +;; This is for compatibility with pre-28.1 behavior. Basically, we're +;; trying to match the behavior bug for bug. All buffers were always +;; suffixed and never reassociated. 28.1 introduced a regression that +;; reversed the latter, but we've reverted that. + +(ert-deftest erc-networks--rename-server-buffer--existing--noreuse () + (with-suppressed-warnings ((obsolete erc-reuse-buffers)) + (should erc-reuse-buffers) ; default + (let* ((old-buf (get-buffer-create "irc.foonet.org:6697/irc.foonet.org")) + (old-proc (erc-networks-tests--create-dead-proc old-buf)) + erc-reuse-buffers) + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil))) + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-networks--id (buffer-local-value 'erc-networks--id old-buf) + erc--target (erc--target-from-string "#chan")) + (rename-buffer (erc-networks--construct-target-buffer-name erc--target))) + + (ert-info ("Server buffer uniquely renamed") + (with-current-buffer + (get-buffer-create "irc.foonet.org:6697/irc.foonet.org<2>") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) + "irc.foonet.org:6697/irc.foonet.org<2>")) + (goto-char (point-min)) + (should-not (search-forward "Old buf" nil t)))) + + (ert-info ("Channel buffer not reassociated") + (should-not + (erc-server-process-alive + (should (get-buffer "#chan/irc.foonet.org")))) + (with-current-buffer (get-buffer "#chan/irc.foonet.org") + (should-not erc-server-connected) + (should (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) + "irc.foonet.org:6697/irc.foonet.org"))))) + + (ert-info ("Old buffer still around") + (should (buffer-live-p old-buf))))) + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--reconnecting () + (let* ((old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil))) + + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc--target (erc--target-from-string "#chan") + erc-networks--id (erc-networks--id-create nil))) + + (ert-info ("No new buffer") + (with-current-buffer old-buf + (setq erc-server-process (erc-networks-tests--create-live-proc)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer updated with live proc") + (erc-server-process-alive "#chan") + (with-current-buffer "#chan" + (should erc-server-connected) + (should-not (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet")))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--id () + (let* ((old-buf (get-buffer-create "MySession")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-networks--id (erc-networks--id-create 'MySession) + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc)) + + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-networks--id (erc-networks--id-create 'MySession) + erc-server-process old-proc + erc--target (erc--target-from-string "#chan"))) + + (ert-info ("No new buffer") + (with-current-buffer old-buf + (setq erc-server-process (erc-networks-tests--create-live-proc)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "MySession")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer updated with live proc") + (erc-server-process-alive "#chan") + (with-current-buffer "#chan" + (should erc-server-connected) + (should-not (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "MySession")))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--existing--live () + (let* (erc-kill-server-hook + erc-insert-modify-hook + (old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-live-proc old-buf))) ; live + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil)) + (should (erc-server-process-alive))) + + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-networks--id (erc-networks--id-create nil) + erc-server-connected t + erc--target (erc--target-from-string "#chan"))) + + (ert-info ("New buffer rejected, abandoned, not killed") + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process (erc-networks-tests--create-live-proc) + erc-networks--id (erc-networks--id-create nil)) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (eq erc-active-buffer old-buf)) + (should-not (erc-server-process-alive)) + (should (string= (buffer-name) "irc.foonet.org")) + (goto-char (point-min)) + (search-forward "still connected"))) + + (ert-info ("Channel buffer updated with live proc") + (should (erc-server-process-alive "#chan")) + (with-current-buffer "#chan" + (should erc-server-connected) + (should (erc-server-buffer-live-p)) + (should (eq erc-server-process old-proc)) + (should (buffer-live-p (process-buffer erc-server-process))) + (with-current-buffer (process-buffer erc-server-process) + (should (eq (current-buffer) (get-buffer "FooNet"))) + (should (eq (current-buffer) old-buf)))))) + + (should (get-buffer "FooNet")) + (should (get-buffer "irc.foonet.org")) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--rename-server-buffer--local-match () + (let* ((old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-announced-name "us-east.foonet.org" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + (puthash 'CHANTYPES '("&#") erc--isupport-params)) + + (with-current-buffer (get-buffer-create "&chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-server-announced-name "us-east.foonet.org" + erc--target (erc--target-from-string "&chan") + erc-networks--id (erc-networks--id-create nil))) + + (ert-info ("New server buffer steals name, content") + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-announced-name "us-east.foonet.org" + erc-server-process (erc-networks-tests--create-live-proc) + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + (puthash 'CHANTYPES '("&#") erc--isupport-params) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer reassociated when &local server matches") + (should (erc-server-process-alive "&chan")) + (with-current-buffer "&chan" + (should erc-server-connected) + (should-not (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet"))))) + + (ert-info ("Original buffer killed off") + (should-not (buffer-live-p old-buf))) + + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--rename-server-buffer--local-nomatch () + (let* ((old-buf (get-buffer-create "FooNet")) + (old-proc (erc-networks-tests--create-dead-proc old-buf))) + + (with-current-buffer old-buf + (erc-mode) + (insert "*** Old buf") + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-announced-name "us-west.foonet.org" + erc-insert-marker (set-marker (make-marker) (point-max)) + erc-server-process old-proc + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + (puthash 'CHANTYPES '("&#") erc--isupport-params)) + + (with-current-buffer (get-buffer-create "&chan") + (erc-mode) + (setq erc-network 'FooNet + erc-server-process old-proc + erc-server-announced-name "us-west.foonet.org" ; west + erc--target (erc--target-from-string "&chan") + erc-networks--id (erc-networks--id-create nil))) + + (ert-info ("New server buffer steals name, content") + (with-current-buffer (get-buffer-create "irc.foonet.org") + (erc-mode) + (setq erc-network 'FooNet + erc-server-current-nick "tester" + erc-server-announced-name "us-east.foonet.org" ; east + erc-server-process (erc-networks-tests--create-live-proc) + erc--isupport-params (make-hash-table) + erc-networks--id (erc-networks--id-create nil)) + + (puthash 'CHANTYPES '("&#") erc--isupport-params) + (should-not (erc-networks--rename-server-buffer erc-server-process)) + (should (string= (buffer-name) "FooNet")) + (goto-char (point-min)) + (should (search-forward "Old buf")))) + + (ert-info ("Channel buffer now orphaned even though network matches") + (should-not (erc-server-process-alive "&chan")) + (with-current-buffer "&chan" + (should-not erc-server-connected) + (should (eq erc-server-process old-proc)) + (erc-with-server-buffer + (should (string= (buffer-name) "FooNet"))))) + + (ert-info ("Original buffer killed off") + (should-not (buffer-live-p old-buf))) + + (erc-networks-tests--clean-bufs))) + +(ert-deftest erc-networks--update-server-identity--double-existing () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1)) + + (with-current-buffer (get-buffer-create "#chan@foonet/bob") + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 2))) + (with-current-buffer (get-buffer-create "foonet/alice") + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 2))) + + (ert-info ("Adopt equivalent identity") + (should (eq (erc-networks--update-server-identity) + (buffer-local-value 'erc-networks--id + (get-buffer "#chan@foonet/bob"))))) + + (ert-info ("Ignore non-matches") + (should-not (erc-networks--update-server-identity)) + (should (eq erc-networks--id + (buffer-local-value 'erc-networks--id + (get-buffer "#chan@foonet/bob")))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--update-server-identity--double-new () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1)) + + (with-current-buffer (get-buffer-create "foonet/alice") + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 2))) + (with-current-buffer (get-buffer-create "#chan@foonet/alice") + (erc-mode) + (setq erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet/alice")))) + + (ert-info ("Evolve identity to prevent ambiguity") + (should-not (erc-networks--update-server-identity)) + (should (= (erc-networks--id-qualifying-len erc-networks--id) 2)) + (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob)))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--update-server-identity--double-bounded () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "bob"] :len 1)) + + (with-current-buffer (get-buffer-create "foonet/alice/home") + (erc-mode) + (setq erc-networks--id (make-erc-networks--id-qualifying + :parts [foonet "alice" home] :len 3))) + (with-current-buffer (get-buffer-create "#chan@foonet/alice/home") + (erc-mode) + (setq erc-networks--id + (buffer-local-value 'erc-networks--id + (get-buffer "foonet/alice/home")))) + + (ert-info ("Evolve identity to prevent ambiguity") + (should-not (erc-networks--update-server-identity)) + (should (= (erc-networks--id-qualifying-len erc-networks--id) 2)) + (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob)))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--update-server-identity--double-even () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "bob"] :len 1)) + + (with-current-buffer (get-buffer-create "foonet") + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "alice"] :len 1))) + (with-current-buffer (get-buffer-create "#chan") + (erc-mode) + (setq erc--target (erc--target-from-string "#chan") + erc-networks--id (buffer-local-value 'erc-networks--id + (get-buffer "foonet")))) + + (ert-info ("Evolve identity to prevent ambiguity") + (should-not (erc-networks--update-server-identity)) + (should (= (erc-networks--id-qualifying-len erc-networks--id) 2)) + (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/bob))) + + (ert-info ("Collision renamed") + (with-current-buffer "foonet/alice" + (should (eq (erc-networks--id-symbol erc-networks--id) 'foonet/alice))) + + (with-current-buffer "#chan@foonet/alice" + (should (eq (erc-networks--id-symbol erc-networks--id) + 'foonet/alice))))) + + (erc-networks-tests--clean-bufs)) + +(ert-deftest erc-networks--update-server-identity--triple-new () + (with-temp-buffer + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "bob" home] :len 1)) + + (with-current-buffer (get-buffer-create "foonet/bob/office") + (erc-mode) + (setq erc-networks--id + (make-erc-networks--id-qualifying :parts [foonet "bob" office] + :len 3))) + (with-current-buffer (get-buffer-create "#chan@foonet/bob/office") + (erc-mode) + (setq erc-networks--id + (buffer-local-value 'erc-networks--id + (get-buffer "foonet/bob/office")))) + + (ert-info ("Extend our identity's canonical ID so that it's unique") + (should-not (erc-networks--update-server-identity)) + (should (= (erc-networks--id-qualifying-len erc-networks--id) 3)))) + + (erc-networks-tests--clean-bufs)) + +;;; erc-networks-tests.el ends here diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 5b04bff617..618d7eeea0 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -566,8 +566,9 @@ (erc-log-irc-protocol ":irc.gnu.org 001 tester :Welcome") (erc-log-irc-protocol ":irc.gnu.org 002 tester :Your host is irc.gnu.org") (setq erc-network 'FooNet) + (setq erc-networks--id (erc-networks--id-create nil)) (erc-log-irc-protocol ":irc.gnu.org 422 tester :MOTD missing") - (setq erc-network 'BarNet) + (setq erc-networks--id (erc-networks--id-create 'BarNet)) (erc-log-irc-protocol ":irc.gnu.org 221 tester +i") (set-process-query-on-exit-flag erc-server-process nil))) (with-current-buffer "*erc-protocol*" commit 9be08ceb314888c7f86bddbec6490e7ead718a88 Author: F. Jason Park Date: Thu May 13 03:33:33 2021 -0700 Add ERC test server and related resources * test/lisp/erc/resources/erc-d/erc-d.el: New file. * test/lisp/erc/resources/erc-d/erc-d-u.el: New file. * test/lisp/erc/resources/erc-d/erc-d-i.el: New file. * test/lisp/erc/resources/erc-d/erc-d-t.el: New file. * test/lisp/erc/resources/erc-d/erc-d-tests.el: New file. * test/lisp/erc/erc-scenarios-internal.el: New file to serve as discoverable proxy for erc-d-tests. diff --git a/test/lisp/erc/erc-scenarios-internal.el b/test/lisp/erc/erc-scenarios-internal.el new file mode 100644 index 0000000000..e4e1edb97e --- /dev/null +++ b/test/lisp/erc/erc-scenarios-internal.el @@ -0,0 +1,27 @@ +;;; erc-scenarios-internal.el --- Proxy file for erc-d tests -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (expand-file-name "erc-d" (ert-resource-directory)) + load-path))) + (load "erc-d-tests" nil 'silent))) + +;;; erc-scenarios-internal.el ends here diff --git a/test/lisp/erc/resources/erc-d/erc-d-i.el b/test/lisp/erc/resources/erc-d/erc-d-i.el new file mode 100644 index 0000000000..27b1bf6083 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/erc-d-i.el @@ -0,0 +1,126 @@ +;;; erc-d-i.el --- IRC helpers for ERC test server -*- lexical-binding: t -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;;; Commentary: + +;;; Code: + +(require 'cl-lib) + +(cl-defstruct (erc-d-i-message (:conc-name erc-d-i-message.)) + "Identical to `erc-response'. +When member `compat' is nil, it means the raw message was decoded as +UTF-8 text before parsing, which is nonstandard." + (unparsed "" :type string) + (sender "" :type string) + (command "" :type string) + (command-args nil :type (list-of string)) + (contents "" :type string) + (tags nil :type (list-of (cons symbol string))) + (compat t :type boolean)) + +(defconst erc-d-i--tag-escapes + '((";" . "\\:") (" " . "\\s") ("\\" . "\\\\") ("\r" . "\\r") ("\n" . "\\n"))) + +;; XXX these are not mirror inverses; unescaping may degenerate +;; original by dropping stranded/misplaced backslashes. + +(defconst erc-d-i--tag-escaped-regexp (rx (or ?\; ?\ ?\\ ?\r ?\n))) + +(defconst erc-d-i--tag-unescaped-regexp + (rx (or "\\:" "\\s" "\\\\" "\\r" "\\n" + (seq "\\" (or string-end (not (or ":" "n" "r" "\\"))))))) + +(defun erc-d-i--unescape-tag-value (str) + "Undo substitution of char placeholders in raw tag value STR." + (replace-regexp-in-string erc-d-i--tag-unescaped-regexp + (lambda (s) + (or (car (rassoc s erc-d-i--tag-escapes)) + (substring s 1))) + str t t)) + +(defun erc-d-i--escape-tag-value (str) + "Swap out banned chars in tag value STR with message representation." + (replace-regexp-in-string erc-d-i--tag-escaped-regexp + (lambda (s) + (cdr (assoc s erc-d-i--tag-escapes))) + str t t)) + +(defconst erc-d-i--invalid-tag-regexp (rx (any "\0\7\r\n; "))) + +;; This is `erc-v3-message-tags' with fatal errors. + +(defun erc-d-i--validate-tags (raw) + "Validate tags portion of some RAW incoming message. +RAW must not have a leading \"@\" or a trailing space. The spec says +validation shouldn't be performed on keys and that undecodeable values +or ones with illegal (unescaped) chars may be dropped. This does not +respect any of that. Its purpose is to catch bad input created by us." + (unless (> 4094 (string-bytes raw)) + ;; 417 ERR_INPUTTOOLONG Input line was too long + (error "Message tags exceed 4094 bytes: %S" raw)) + (let (tags + (tag-strings (split-string raw ";"))) + (dolist (s tag-strings (nreverse tags)) + (let* ((m (if (>= emacs-major-version 28) + (string-search "=" s) + (string-match-p "=" s))) + (key (if m (substring s 0 m) s)) + (val (when-let* (m ; check first, like (m), but shadow + (v (substring s (1+ m))) + ((not (string-equal v "")))) + (when (string-match-p erc-d-i--invalid-tag-regexp v) + (error "Bad tag: %s" s)) + (thread-first v + (decode-coding-string 'utf-8 t) + (erc-d-i--unescape-tag-value))))) + (when (string-empty-p key) + (error "Tag missing key: %S" s)) + (setf (alist-get (intern key) tags) val))))) + +(defun erc-d-i--parse-message (s &optional decode) + "Parse string S into `erc-d-i-message' object. +With DECODE, decode as UTF-8 text." + (when (string-suffix-p "\r\n" s) + (error "Unstripped message encountered")) + (when decode + (setq s (decode-coding-string s 'utf-8 t))) + (let ((mes (make-erc-d-i-message :unparsed s :compat (not decode))) + tokens) + (when-let* (((not (string-empty-p s))) + ((eq ?@ (aref s 0))) + (m (string-match " " s)) + (u (substring s 1 m))) + (setf (erc-d-i-message.tags mes) (erc-d-i--validate-tags u) + s (substring s (1+ m)))) + (if-let* ((m (string-match " :" s)) + (other-toks (split-string (substring s 0 m) " " t)) + (rest (substring s (+ 2 m)))) + (setf (erc-d-i-message.contents mes) rest + tokens (nconc other-toks (list rest))) + (setq tokens (split-string s " " t " "))) + (when (and tokens (eq ?: (aref (car tokens) 0))) + (setf (erc-d-i-message.sender mes) (substring (pop tokens) 1))) + (setf (erc-d-i-message.command mes) (or (pop tokens) "") + (erc-d-i-message.command-args mes) tokens) + mes)) + +(provide 'erc-d-i) +;;; erc-d-i.el ends here diff --git a/test/lisp/erc/resources/erc-d/erc-d-t.el b/test/lisp/erc/resources/erc-d/erc-d-t.el new file mode 100644 index 0000000000..a1a7e7e88d --- /dev/null +++ b/test/lisp/erc/resources/erc-d/erc-d-t.el @@ -0,0 +1,170 @@ +;;; erc-d-t.el --- ERT helpers for ERC test server -*- lexical-binding: t -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;;; Commentary: + +;;; Code: +(eval-and-compile + (let* ((d (file-name-directory (or (macroexp-file-name) buffer-file-name))) + (load-path (cons (directory-file-name d) load-path))) + (require 'erc-d-u))) + +(require 'ert) + +(defun erc-d-t-kill-related-buffers () + "Kill all erc- or erc-d- related buffers." + (let (buflist) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (or erc-d-u--process-buffer + (derived-mode-p 'erc-mode)) + (push buf buflist)))) + (dolist (buf buflist) + (when (and (boundp 'erc-server-flood-timer) + (timerp erc-server-flood-timer)) + (cancel-timer erc-server-flood-timer)) + (when-let ((proc (get-buffer-process buf))) + (delete-process proc)) + (when (buffer-live-p buf) + (kill-buffer buf)))) + (while (when-let ((buf (pop erc-d-u--canned-buffers))) + (kill-buffer buf)))) + +(defun erc-d-t-silence-around (orig &rest args) + "Run ORIG function with ARGS silently. +Use this on `erc-handle-login' and `erc-server-connect'." + (let ((inhibit-message t)) + (apply orig args))) + +(defvar erc-d-t-cleanup-sleep-secs 0.1) + +(defmacro erc-d-t-with-cleanup (bindings cleanup &rest body) + "Execute BODY and run CLEANUP form regardless of outcome. +`let*'-bind BINDINGS and make them available in BODY and CLEANUP. +After CLEANUP, destroy any values in BINDINGS that remain bound to +buffers or processes. Sleep `erc-d-t-cleanup-sleep-secs' before +returning." + (declare (indent 2)) + `(let* ,bindings + (unwind-protect + (progn ,@body) + ,cleanup + (when noninteractive + (let (bufs procs) + (dolist (o (list ,@(mapcar (lambda (b) (or (car-safe b) b)) + bindings))) + (when (bufferp o) + (push o bufs)) + (when (processp o) + (push o procs))) + (dolist (proc procs) + (delete-process proc) + (when-let ((buf (process-buffer proc))) + (push buf bufs))) + (dolist (buf bufs) + (when-let ((proc (get-buffer-process buf))) + (delete-process proc)) + (when (bufferp buf) + (ignore-errors (kill-buffer buf))))) + (sleep-for erc-d-t-cleanup-sleep-secs))))) + +(defmacro erc-d-t-wait-for (max-secs msg &rest body) + "Wait for BODY to become non-nil. +Or signal error with MSG after MAX-SECS. When MAX-SECS is negative, +signal if BODY is ever non-nil before MAX-SECS elapses. On success, +return BODY's value. + +Note: this assumes BODY is waiting on a peer's output. It tends to +artificially accelerate consumption of all process output, which may not +be desirable." + (declare (indent 2)) + (unless (or (stringp msg) (memq (car-safe msg) '(format concat))) + (push msg body) + (setq msg (prin1-to-string body))) + (let ((inverted (make-symbol "inverted")) + (time-out (make-symbol "time-out")) + (result (make-symbol "result"))) + `(ert-info ((concat "Awaiting: " ,msg)) + (let ((,time-out (abs ,max-secs)) + (,inverted (< ,max-secs 0)) + (,result ',result)) + (with-timeout (,time-out (if ,inverted + (setq ,inverted nil) + (error "Failed awaiting: %s" ,msg))) + (while (not (setq ,result (progn ,@body))) + (when (and (accept-process-output nil 0.1) (not noninteractive)) + (redisplay)))) + (when ,inverted + (error "Failed awaiting: %s" ,msg)) + ,result)))) + +(defmacro erc-d-t-ensure-for (max-secs msg &rest body) + "Ensure BODY remains non-nil for MAX-SECS. +On failure, emit MSG." + (declare (indent 2)) + (unless (or (stringp msg) (memq (car-safe msg) '(format concat))) + (push msg body) + (setq msg (prin1-to-string body))) + `(erc-d-t-wait-for (- (abs ,max-secs)) ,msg (not (progn ,@body)))) + +(defun erc-d-t-search-for (timeout text &optional from on-success) + "Wait for TEXT to appear in current buffer before TIMEOUT secs. +With marker or number FROM, only consider the portion of the buffer from +that point forward. If TEXT is a cons, interpret it as an RX regular +expression. If ON-SUCCESS is a function, call it when TEXT is found." + (save-restriction + (widen) + (let* ((rxp (consp text)) + (fun (if rxp #'search-forward-regexp #'search-forward)) + (pat (if rxp (rx-to-string text) text)) + res) + (erc-d-t-wait-for timeout (format "string: %s" text) + (goto-char (or from (point-min))) + (setq res (funcall fun pat nil t)) + (if (and on-success res) + (funcall on-success) + res))))) + +(defun erc-d-t-absent-for (timeout text &optional from on-success) + "Assert TEXT doesn't appear in current buffer for TIMEOUT secs." + (erc-d-t-search-for (- (abs timeout)) text from on-success)) + +(defun erc-d-t-make-expecter () + "Return function to search for new output in buffer. +Assume new text is only inserted at or after `erc-insert-marker'. + +The returned function works like `erc-d-t-search-for', but it never +revisits previously covered territory, and the optional fourth argument, +ON-SUCCESS, is nonexistent. To reset, specify a FROM argument." + (let (positions) + (lambda (timeout text &optional reset-from) + (let* ((pos (cdr (assq (current-buffer) positions))) + (cb (lambda () + (unless pos + (push (cons (current-buffer) (setq pos (make-marker))) + positions)) + (marker-position + (set-marker pos (min (point) (1- (point-max)))))))) + (when reset-from + (set-marker pos reset-from)) + (erc-d-t-search-for timeout text pos cb))))) + +(provide 'erc-d-t) +;;; erc-d-t.el ends here diff --git a/test/lisp/erc/resources/erc-d/erc-d-tests.el b/test/lisp/erc/resources/erc-d/erc-d-tests.el new file mode 100644 index 0000000000..f64b5e8a74 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/erc-d-tests.el @@ -0,0 +1,1346 @@ +;;; erc-d-tests.el --- tests for erc-d -*- lexical-binding: t -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;;; Commentary: + +;;; Code: +(require 'ert-x) +(eval-and-compile + (let ((load-path (cons (expand-file-name ".." (ert-resource-directory)) + load-path))) + (require 'erc-d) + (require 'erc-d-t))) + +(require 'erc) + +;; Temporary kludge to silence warning +(put 'erc-parse-tags 'erc-v3-warned-p t) + +(ert-deftest erc-d-u--canned-load-dialog--basic () + (should-not (get-buffer "basic.eld")) + (should-not erc-d-u--canned-buffers) + (let* ((exes (erc-d-u--canned-load-dialog 'basic)) + (reap (lambda () + (cl-loop with e = (erc-d-u--read-dialog exes) + for s = (erc-d-u--read-exchange e) + while s collect s)))) + (should (get-buffer "basic.eld")) + (should (memq (get-buffer "basic.eld") erc-d-u--canned-buffers)) + (should (equal (funcall reap) '((pass 10.0 "PASS " (? ?:) "changeme")))) + (should (equal (funcall reap) '((nick 0.2 "NICK tester")))) + (let ((r (funcall reap))) + (should (equal (car r) '(user 0.2 "USER user 0 * :tester"))) + (should (equal + (car (last r)) + '(0 ":irc.example.org 422 tester :MOTD File is missing")))) + (should (equal (car (funcall reap)) '(mode-user 5 "MODE tester +i"))) + (should (equal (funcall reap) + '((mode-chan 1.2 "MODE #chan") + (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey")))) + ;; See `define-error' site for `iter-end-of-sequence' + (ert-info ("EOB detected") (should-not (erc-d-u--read-dialog exes)))) + (should-not (get-buffer "basic.eld")) + (should-not erc-d-u--canned-buffers)) + +(defun erc-d-tests--make-hunk-reader (hunks) + (let ((p (erc-d-u--read-dialog hunks))) + (lambda () (erc-d-u--read-exchange p)))) + +;; Fuzzies need to be able to access any non-exhausted genny. +(ert-deftest erc-d-u--canned-load-dialog--intermingled () + (should-not (get-buffer "basic.eld")) + (should-not erc-d-u--canned-buffers) + (let* ((exes (erc-d-u--canned-load-dialog 'basic)) + (pass (erc-d-tests--make-hunk-reader exes)) + (nick (erc-d-tests--make-hunk-reader exes)) + (user (erc-d-tests--make-hunk-reader exes)) + (modu (erc-d-tests--make-hunk-reader exes)) + (modc (erc-d-tests--make-hunk-reader exes))) + + (should (equal (funcall user) '(user 0.2 "USER user 0 * :tester"))) + (should (equal (funcall modu) '(mode-user 5 "MODE tester +i"))) + (should (equal (funcall modc) '(mode-chan 1.2 "MODE #chan"))) + + (cl-loop repeat 8 do (funcall user)) ; skip a few + (should (equal (funcall user) + '(0 ":irc.example.org 254 tester 1 :channels formed"))) + (should (equal (funcall modu) + '(0 ":irc.example.org 221 tester +Zi"))) + (should (equal (cl-loop for s = (funcall modc) while s collect s) ; done + '((0.1 ":bob!~bob@example.org PRIVMSG #chan :hey")))) + + (cl-loop repeat 3 do (funcall user)) + (cl-loop repeat 3 do (funcall modu)) + + (ert-info ("Change up the order") + (should + (equal (funcall modu) + '(0 ":irc.example.org 366 alice #chan :End of NAMES list"))) + (should + (equal (funcall user) + '(0 ":irc.example.org 422 tester :MOTD File is missing")))) + + ;; Exhaust these + (should (equal (cl-loop for s = (funcall pass) while s collect s) ; done + '((pass 10.0 "PASS " (? ?:) "changeme")))) + (should (equal (cl-loop for s = (funcall nick) while s collect s) ; done + '((nick 0.2 "NICK tester")))) + + (ert-info ("End of file but no teardown because hunks outstanding") + (should-not (erc-d-u--read-dialog exes)) + (should (get-buffer "basic.eld"))) + + ;; Finish + (should-not (funcall user)) + (should-not (funcall modu))) + + (should-not (get-buffer "basic.eld")) + (should-not erc-d-u--canned-buffers)) + +;; This indirectly tests `erc-d-u--canned-read' cleanup/teardown + +(ert-deftest erc-d-u--rewrite-for-slow-mo () + (should-not (get-buffer "basic.eld")) + (should-not (get-buffer "basic.eld<2>")) + (should-not (get-buffer "basic.eld<3>")) + (should-not erc-d-u--canned-buffers) + (let ((exes (erc-d-u--canned-load-dialog 'basic)) + (exes-lower (erc-d-u--canned-load-dialog 'basic)) + (exes-custom (erc-d-u--canned-load-dialog 'basic)) + (reap (lambda (e) (cl-loop with p = (erc-d-u--read-dialog e) + for s = (erc-d-u--read-exchange p) + while s collect s)))) + (should (get-buffer "basic.eld")) + (should (get-buffer "basic.eld<2>")) + (should (get-buffer "basic.eld<3>")) + (should (equal (list (get-buffer "basic.eld<3>") + (get-buffer "basic.eld<2>") + (get-buffer "basic.eld")) + erc-d-u--canned-buffers)) + + (ert-info ("Rewrite for slowmo basic") + (setq exes (erc-d-u--rewrite-for-slow-mo 10 exes)) + (should (equal (funcall reap exes) + '((pass 20.0 "PASS " (? ?:) "changeme")))) + (should (equal (funcall reap exes) + '((nick 10.2 "NICK tester")))) + (let ((r (funcall reap exes))) + (should (equal (car r) '(user 10.2 "USER user 0 * :tester"))) + (should (equal + (car (last r)) + '(0 ":irc.example.org 422 tester :MOTD File is missing")))) + (should (equal (car (funcall reap exes)) + '(mode-user 15 "MODE tester +i"))) + (should (equal (car (funcall reap exes)) + '(mode-chan 11.2 "MODE #chan"))) + (should-not (erc-d-u--read-dialog exes))) + + (ert-info ("Rewrite for slowmo bounded") + (setq exes-lower (erc-d-u--rewrite-for-slow-mo -5 exes-lower)) + (should (equal (funcall reap exes-lower) + '((pass 10.0 "PASS " (? ?:) "changeme")))) + (should (equal (funcall reap exes-lower) + '((nick 5 "NICK tester")))) + (should (equal (car (funcall reap exes-lower)) + '(user 5 "USER user 0 * :tester"))) + (should (equal (car (funcall reap exes-lower)) + '(mode-user 5 "MODE tester +i"))) + (should (equal (car (funcall reap exes-lower)) + '(mode-chan 5 "MODE #chan"))) + (should-not (erc-d-u--read-dialog exes-lower))) + + (ert-info ("Rewrite for slowmo custom") + (setq exes-custom (erc-d-u--rewrite-for-slow-mo + (lambda (n) (* 2 n)) exes-custom)) + (should (equal (funcall reap exes-custom) + '((pass 20.0 "PASS " (? ?:) "changeme")))) + (should (equal (funcall reap exes-custom) + '((nick 0.4 "NICK tester")))) + (should (equal (car (funcall reap exes-custom)) + '(user 0.4 "USER user 0 * :tester"))) + (should (equal (car (funcall reap exes-custom)) + '(mode-user 10 "MODE tester +i"))) + (should (equal (car (funcall reap exes-custom)) + '(mode-chan 2.4 "MODE #chan"))) + (should-not (erc-d-u--read-dialog exes-custom)))) + + (should-not (get-buffer "basic.eld")) + (should-not (get-buffer "basic.eld<2>")) + (should-not (get-buffer "basic.eld<3>")) + (should-not erc-d-u--canned-buffers)) + +(ert-deftest erc-d--active-ex-p () + (let ((ring (make-ring 5))) + (ert-info ("Empty ring returns nil for not active") + (should-not (erc-d--active-ex-p ring))) + (ert-info ("One fuzzy member returns nil for not active") + (ring-insert ring (make-erc-d-exchange :tag '~foo)) + (should-not (erc-d--active-ex-p ring))) + (ert-info ("One active member returns t for active") + (ring-insert-at-beginning ring (make-erc-d-exchange :tag 'bar)) + (should (erc-d--active-ex-p ring))))) + +(defun erc-d-tests--parse-message-upstream (raw) + "Hack shim for parsing RAW line recvd from peer." + (cl-letf (((symbol-function #'erc-handle-parsed-server-response) + (lambda (_ p) p))) + (let ((erc-active-buffer nil)) + (erc-parse-server-response nil raw)))) + +(ert-deftest erc-d-i--validate-tags () + (should (erc-d-i--validate-tags + (concat "batch=4cc99692bf24a4bec4aa03da437364f5;" + "time=2021-01-04T00:32:13.839Z"))) + (should (erc-d-i--validate-tags "+foo=bar;baz=spam")) + (should (erc-d-i--validate-tags "foo=\\:ok;baz=\\s")) + (should (erc-d-i--validate-tags "foo=\303\247edilla")) + (should (erc-d-i--validate-tags "foo=\\")) + (should (erc-d-i--validate-tags "foo=bar\\baz")) + (should-error (erc-d-i--validate-tags "foo=\\\\;baz=\\\r\\\n")) + (should-error (erc-d-i--validate-tags "foo=\n")) + (should-error (erc-d-i--validate-tags "foo=\0ok")) + (should-error (erc-d-i--validate-tags "foo=bar baz")) + (should-error (erc-d-i--validate-tags "foo=bar\r")) + (should-error (erc-d-i--validate-tags "foo=bar;"))) + +(ert-deftest erc-d-i--parse-message () + (let* ((raw (concat "@time=2020-11-23T09:10:33.088Z " + ":tilde.chat BATCH +1 chathistory :#meta")) + (upstream (erc-d-tests--parse-message-upstream raw)) + (ours (erc-d-i--parse-message raw))) + + (ert-info ("Baseline upstream") + (should (equal (erc-response.unparsed upstream) raw)) + (should (equal (erc-response.sender upstream) "tilde.chat")) + (should (equal (erc-response.command upstream) "BATCH")) + (should (equal (erc-response.command-args upstream) + '("+1" "chathistory" "#meta"))) + (should (equal (erc-response.contents upstream) "#meta"))) + + (ert-info ("Ours my not compare cl-equalp but is otherwise the same") + (should (equal (erc-d-i-message.unparsed ours) raw)) + (should (equal (erc-d-i-message.sender ours) "tilde.chat")) + (should (equal (erc-d-i-message.command ours) "BATCH")) + (should (equal (erc-d-i-message.command-args ours) + '("+1" "chathistory" "#meta"))) + (should (equal (erc-d-i-message.contents ours) "#meta")) + (should (equal (erc-d-i-message.tags ours) + '((time . "2020-11-23T09:10:33.088Z"))))) + + (ert-info ("No compat decodes the whole message as utf-8") + (setq ours (erc-d-i--parse-message + "@foo=\303\247edilla TAGMSG #ch\303\240n" + 'decode)) + (should-not (erc-d-i-message.compat ours)) + (should (equal (erc-d-i-message.command-args ours) '("#chàn"))) + (should (equal (erc-d-i-message.contents ours) "")) + (should (equal (erc-d-i-message.tags ours) '((foo . "çedilla"))))))) + +(ert-deftest erc-d-i--unescape-tag-value () + (should (equal (erc-d-i--unescape-tag-value + "\\sabc\\sdef\\s\\sxyz\\s") + " abc def xyz ")) + (should (equal (erc-d-i--unescape-tag-value + "\\\\abc\\\\def\\\\\\\\xyz\\\\") + "\\abc\\def\\\\xyz\\")) + (should (equal (erc-d-i--unescape-tag-value "a\\bc") "abc")) + (should (equal (erc-d-i--unescape-tag-value + "\\\\abc\\\\def\\\\\\\\xyz\\") + "\\abc\\def\\\\xyz")) + (should (equal (erc-d-i--unescape-tag-value "a\\:b\\r\\nc\\sd") + "a;b\r\nc d"))) + +(ert-deftest erc-d-i--escape-tag-value () + (should (equal (erc-d-i--escape-tag-value " abc def xyz ") + "\\sabc\\sdef\\s\\sxyz\\s")) + (should (equal (erc-d-i--escape-tag-value "\\abc\\def\\\\xyz\\") + "\\\\abc\\\\def\\\\\\\\xyz\\\\")) + (should (equal (erc-d-i--escape-tag-value "a;b\r\nc d") + "a\\:b\\r\\nc\\sd"))) + +;; TODO add tests for msg-join, mask-match, userhost-split, +;; validate-hostname + +(ert-deftest erc-d-i--parse-message--irc-parser-tests () + (let* ((data (with-temp-buffer + (insert-file-contents + (expand-file-name "irc-parser-tests.eld" + (ert-resource-directory))) + (read (current-buffer)))) + (tests (assoc-default 'tests (assoc-default 'msg-split data))) + input atoms m ours) + (dolist (test tests) + (setq input (assoc-default 'input test) + atoms (assoc-default 'atoms test) + m (erc-d-i--parse-message input)) + (ert-info ("Parses tags correctly") + (setq ours (erc-d-i-message.tags m)) + (if-let ((tags (assoc-default 'tags atoms))) + (pcase-dolist (`(,key . ,value) ours) + (should (string= (cdr (assq key tags)) (or value "")))) + (should-not ours))) + (ert-info ("Parses verbs correctly") + (setq ours (erc-d-i-message.command m)) + (if-let ((verbs (assoc-default 'verb atoms))) + (should (string= (downcase verbs) (downcase ours))) + (should (string-empty-p ours)))) + (ert-info ("Parses sources correctly") + (setq ours (erc-d-i-message.sender m)) + (if-let ((source (assoc-default 'source atoms))) + (should (string= source ours)) + (should (string-empty-p ours)))) + (ert-info ("Parses params correctly") + (setq ours (erc-d-i-message.command-args m)) + (if-let ((params (assoc-default 'params atoms))) + (should (equal ours params)) + (should-not ours)))))) + +(defun erc-d-tests--new-ex (existing raw-hunk) + (let* ((f (lambda (_) (pop raw-hunk))) + (sd (make-erc-d-u-scan-d :f f))) + (setf (erc-d-exchange-hunk existing) (make-erc-d-u-scan-e :sd sd) + (erc-d-exchange-spec existing) (make-erc-d-spec))) + (erc-d--iter existing)) + +(ert-deftest erc-d--render-entries () + (let* ((erc-nick "foo") + (dialog (make-erc-d-dialog :vars `((:a . 1) + (c . ((a b) (: a space b))) + (d . (c alpha digit)) + (bee . 2) + (f . ,(lambda () "3")) + (i . erc-nick)))) + (exchange (make-erc-d-exchange :dialog dialog)) + (mex (apply-partially #'erc-d-tests--new-ex exchange)) + it) + + (erc-d-exchange-reload dialog exchange) + + (ert-info ("Baseline Outgoing") + (setq it (funcall mex '((0 "abc")))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "abc"))) + + (ert-info ("Incoming are regexp escaped") + (setq it (funcall mex '((i 0.0 "fsf" ".org")))) + (should (equal (cons (funcall it) (funcall it)) '(i . 0.0))) + (should (equal (funcall it) "\\`fsf\\.org"))) + + (ert-info ("Incoming can access vars via rx-let") + (setq it (funcall mex '((i 0.0 bee)))) + (should (equal (cons (funcall it) (funcall it)) '(i . 0.0))) + (should (equal (funcall it) "\\`\002"))) + + (ert-info ("Incoming rx-let params") + (setq it (funcall mex '((i 0.0 d)))) + (should (equal (cons (funcall it) (funcall it)) '(i . 0.0))) + (should (equal (funcall it) "\\`[[:alpha:]][[:space:]][[:digit:]]"))) + + (ert-info ("Incoming literal rx forms") + (setq it (funcall mex '((i 0.0 (= 3 alpha) ".org")))) + (should (equal (cons (funcall it) (funcall it)) '(i . 0.0))) + (should (equal (funcall it) "\\`[[:alpha:]]\\{3\\}\\.org"))) + + (ert-info ("Self-quoting disallowed") + (setq it (funcall mex '((0 :a "abc")))) + (should (equal (funcall it) 0)) + (should-error (funcall it))) + + (ert-info ("Global vars and short vars") + (setq it (funcall mex '((0 i f erc-nick)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "foo3foo"))) + + (ert-info ("Exits clean") + (when (listp (alist-get 'f (erc-d-dialog-vars dialog))) ; may be compiled + (should (eq 'closure (car (alist-get 'f (erc-d-dialog-vars dialog)))))) + (should-not (funcall it)) + (should (equal (erc-d-dialog-vars dialog) + `((:a . 1) + (c . ((a b) (: a space b))) + (d . (c alpha digit)) + (bee . 2) + (f . ,(alist-get 'f (erc-d-dialog-vars dialog))) + (i . erc-nick))))))) + +(ert-deftest erc-d--render-entries--matches () + (let* ((alist (list + (cons 'f (lambda (a) (funcall a :match 1))) + (cons 'g (lambda () (match-string 2 "foo bar baz"))) + (cons 'h (lambda (a) (concat (funcall a :match 0) + (funcall a :request)))) + (cons 'i (lambda (_ e) (erc-d-exchange-request e))) + (cons 'j (lambda () + (set-match-data '(0 1)) + (match-string 0 "j"))))) + (dialog (make-erc-d-dialog :vars alist)) + (exchange (make-erc-d-exchange :dialog dialog + :request "foo bar baz" + ;; 11 222 + :match-data '(4 11 4 6 8 11))) + (mex (apply-partially #'erc-d-tests--new-ex exchange)) + it) + + (erc-d-exchange-reload dialog exchange) + + (ert-info ("One arg, match") + (setq it (funcall mex '((0 f)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "ba"))) + + (ert-info ("No args") + (setq it (funcall mex '((0 g)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "baz"))) + + (ert-info ("Second arg is exchange object") + (setq it (funcall mex '((0 i)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "foo bar baz"))) + + (ert-info ("One arg, multiple calls") + (setq it (funcall mex '((0 h)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "bar bazfoo bar baz"))) + + (ert-info ("Match data restored") + (setq it (funcall mex '((0 j)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "j")) + + (setq it (funcall mex '((0 g)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "baz"))) + + (ert-info ("Bad signature") + (let ((qlist (list 'f '(lambda (p q x) (ignore))))) + (setf (erc-d-dialog-vars dialog) qlist) + (should-error (erc-d-exchange-reload dialog exchange)))))) + +(ert-deftest erc-d--render-entries--dynamic () + (let* ((alist (list + (cons 'foo "foo") + (cons 'f (lambda (a) (funcall a :get-binding 'foo))) + (cons 'h (lambda (a) (upcase (funcall a :get-var 'foo)))) + (cons 'g (lambda (a) + (funcall a :rebind 'g (funcall a :get-var 'f)) + "bar")) + (cons 'j (lambda (a) (funcall a :set "123") "abc")) + (cons 'k (lambda () "abc")))) + (dialog (make-erc-d-dialog :vars alist)) + (exchange (make-erc-d-exchange :dialog dialog)) + (mex (apply-partially #'erc-d-tests--new-ex exchange)) + it) + + (erc-d-exchange-reload dialog exchange) + + (ert-info ("Initial reference calls function") + (setq it (funcall mex '((0 j) (0 j)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "abc"))) + + (ert-info ("Subsequent reference expands to string") + (should (equal (funcall it) 0)) + (should (equal (funcall it) "123"))) + + (ert-info ("Outside manipulation: initial reference calls function") + (setq it (funcall mex '((0 k) (0 k)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "abc"))) + + (ert-info ("Outside manipulation: subsequent reference expands to string") + (erc-d-exchange-rebind dialog exchange 'k "123") + (should (equal (funcall it) 0)) + (should (equal (funcall it) "123"))) + + (ert-info ("Swap one function for another") + (setq it (funcall mex '((0 g) (0 g)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "bar")) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "foo"))) + + (ert-info ("Bindings accessible inside functions") + (setq it (funcall mex '((0 f h)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "fooFOO"))) + + (ert-info ("Rebuild alist by sending flag") + (setq it (funcall mex '((0 f) (1 f) (2 f) (i 3 f)))) + (should (equal (funcall it) 0)) + (should (equal (funcall it) "foo")) + (erc-d-exchange-rebind dialog exchange 'f "bar") + (should (equal (funcall it) 1)) + (should (equal (funcall it) "bar")) + (setq alist (setf (alist-get 'f (erc-d-dialog-vars dialog)) + (lambda nil "baz"))) + (should (eq (funcall it) 2)) + (should (equal (funcall it 'reload) "baz")) + (setq alist (setf (alist-get 'f (erc-d-dialog-vars dialog)) "spam")) + (should (eq (funcall it) 'i)) + (should (eq (funcall it 'reload) 3)) + (should (equal (funcall it) "\\`spam"))))) + +(ert-deftest erc-d-t-with-cleanup () + (should-not (get-buffer "*echo*")) + (should-not (get-buffer "*foo*")) + (should-not (get-buffer "*bar*")) + (should-not (get-buffer "*baz*")) + (erc-d-t-with-cleanup + ((echo (start-process "echo" (get-buffer-create "*echo*") "sleep" "1")) + (buffer-foo (get-buffer-create "*foo*")) + (buffer-bar (get-buffer-create "*bar*")) + (clean-up (list (intern (process-name echo)))) ; let* + buffer-baz) + (ert-info ("Clean Up") + (should (equal clean-up '(ran echo))) + (should (bufferp buffer-baz)) + (should (bufferp buffer-foo)) + (setq buffer-foo nil)) + (setq buffer-baz (get-buffer-create "*baz*")) + (push 'ran clean-up)) + (ert-info ("Buffers and procs destroyed") + (should-not (get-buffer "*echo*")) + (should-not (get-buffer "*bar*")) + (should-not (get-buffer "*baz*"))) + (ert-info ("Buffer foo spared") + (should (get-buffer "*foo*")) + (kill-buffer "*foo*"))) + +(ert-deftest erc-d-t-wait-for () + :tags '(:unstable) + (let (v) + (run-at-time 0.2 nil (lambda () (setq v t))) + (should (erc-d-t-wait-for 0.4 "result becomes non-nil" v)) + (should-error (erc-d-t-wait-for 0.4 "result stays nil" (not v))) + (setq v nil) + (should-not (erc-d-t-wait-for -0.4 "inverted stays nil" v)) + (run-at-time 0.2 nil (lambda () (setq v t))) + (setq v nil) + (should-error (erc-d-t-wait-for -0.4 "inverted becomes non-nil" v)))) + +(defvar erc-d-tests-with-server-password "changeme") + +;; Compromise between removing `autojoin' from `erc-modules' entirely +;; and allowing side effects to meddle excessively +(defvar erc-autojoin-channels-alist) + +;; This is only meant to be used by tests in this file. +(cl-defmacro erc-d-tests-with-server ((dumb-server-var erc-server-buffer-var) + dialog &rest body) + "Create server for DIALOG and run BODY. +DIALOG may also be a list of dialogs. ERC-SERVER-BUFFER-VAR and +DUMB-SERVER-VAR are bound accordingly in BODY." + (declare (indent 2)) + (when (eq '_ dumb-server-var) + (setq dumb-server-var (make-symbol "dumb-server-var"))) + (when (eq '_ erc-server-buffer-var) + (setq erc-server-buffer-var (make-symbol "erc-server-buffer-var"))) + (if (listp dialog) + (setq dialog (mapcar (lambda (f) (list 'quote f)) dialog)) + (setq dialog `((quote ,dialog)))) + `(let* (auth-source-do-cache + (,dumb-server-var (erc-d-run "localhost" t ,@dialog)) + ,erc-server-buffer-var + ;; + (erc-server-flood-penalty 0.05) + erc-autojoin-channels-alist + erc-server-auto-reconnect) + (should-not erc-d--slow-mo) + (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting")) + ;; Allow important messages through, even in -batch mode. + (advice-add #'erc-handle-login :around #'erc-d-t-silence-around) + (advice-add #'erc-server-connect :around #'erc-d-t-silence-around) + (unless (or noninteractive erc-debug-irc-protocol) + (erc-toggle-debug-irc-protocol)) + (setq ,erc-server-buffer-var + (erc :server "localhost" + :password erc-d-tests-with-server-password + :port (process-contact ,dumb-server-var :service) + :nick "tester" + :full-name "tester")) + (unwind-protect + (progn + ,@body + (erc-d-t-wait-for 1 "dumb-server death" + (not (process-live-p ,dumb-server-var)))) + (when (process-live-p erc-server-process) + (delete-process erc-server-process)) + (advice-remove #'erc-handle-login #'erc-d-t-silence-around) + (advice-remove #'erc-server-connect #'erc-d-t-silence-around) + (when noninteractive + (kill-buffer ,erc-server-buffer-var) + (erc-d-t-kill-related-buffers))))) + +(defmacro erc-d-tests-with-failure-spy (found func-syms &rest body) + "Wrap functions with advice for inspecting errors caused by BODY. +Do this for functions whose names appear in FUNC-SYMS. When running +advice code, add errors to list FOUND. Note: the teardown finalizer is +not added by default. Also, `erc-d-linger-secs' likely has to be +nonzero for this to work." + (declare (indent 2)) + ;; Catch errors thrown by timers that `should-error'ignores + `(progn + (let ((ad (lambda (f o &rest r) + (condition-case err + (apply o r) + (error (push err ,found) + (advice-remove f 'spy)))))) + (dolist (sym ,func-syms) + (advice-add sym :around (apply-partially ad sym) '((name . spy))))) + (progn ,@body) + (dolist (sym ,func-syms) + (advice-remove sym 'spy)) + (setq ,found (nreverse ,found)))) + +(ert-deftest erc-d-run-nonstandard-messages () + :tags '(:expensive-test) + (let* ((erc-d-linger-secs 0.2) + (dumb-server (erc-d-run "localhost" t 'nonstandard)) + (dumb-server-buffer (get-buffer "*erc-d-server*")) + (expect (erc-d-t-make-expecter)) + client) + (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting")) + (setq client (open-network-stream "erc-d-client" nil + "localhost" + (process-contact dumb-server :service) + :coding 'binary)) + (ert-info ("Server splits CRLF delimited lines") + (process-send-string client "ONE one\r\nTWO two\r\n") + (with-current-buffer dumb-server-buffer + (funcall expect 1 '(: "<- nonstandard:" (+ digit) " ONE one" eol)) + (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ TWO two$")))) + (ert-info ("Server doesn't discard empty lines") + (process-send-string client "\r\n") + (with-current-buffer dumb-server-buffer + (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ $")))) + (ert-info ("Server preserves spaces") + (process-send-string client " \r\n") + (with-current-buffer dumb-server-buffer + (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ \\{2\\}$"))) + (process-send-string client " \r\n") + (with-current-buffer dumb-server-buffer + (funcall expect 1 '(regex "<- nonstandard:[[:digit:]]+ \\{3\\}$")))) + (erc-d-t-wait-for 3 "dumb-server death" + (not (process-live-p dumb-server))) + (delete-process client) + (when noninteractive + (kill-buffer dumb-server-buffer)))) + +(ert-deftest erc-d-run-basic () + :tags '(:expensive-test) + (erc-d-tests-with-server (_ _) basic + (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan")) + (erc-d-t-search-for 2 "hey")) + (when noninteractive + (kill-buffer "#chan")))) + +(ert-deftest erc-d-run-eof () + :tags '(:expensive-test) + (skip-unless noninteractive) + (erc-d-tests-with-server (_ erc-s-buf) eof + (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan")) + (erc-d-t-search-for 2 "hey")) + (with-current-buffer erc-s-buf + (process-send-eof erc-server-process)))) + +(ert-deftest erc-d-run-eof-fail () + :tags '(:expensive-test) + (let (errors) + (erc-d-tests-with-failure-spy errors '(erc-d--teardown) + (erc-d-tests-with-server (_ _) eof + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan")) + (erc-d-t-search-for 2 "hey")) + (erc-d-t-wait-for 10 errors))) + (should (string-match-p "Timed out awaiting request.*__EOF__" + (cadr (pop errors)))))) + +(ert-deftest erc-d-run-linger () + :tags '(:expensive-test) + (erc-d-tests-with-server (dumb-s _) linger + (with-current-buffer (erc-d-t-wait-for 6 (get-buffer "#chan")) + (erc-d-t-search-for 2 "hey")) + (with-current-buffer (process-buffer dumb-s) + (erc-d-t-search-for 2 "Lingering for 1.00 seconds")) + (with-current-buffer (process-buffer dumb-s) + (erc-d-t-search-for 3 "Lingered for 1.00 seconds")))) + +(ert-deftest erc-d-run-linger-fail () + :tags '(:expensive-test) + (let ((erc-server-flood-penalty 0.1) + errors) + (erc-d-tests-with-failure-spy + errors '(erc-d--teardown erc-d-command) + (erc-d-tests-with-server (_ _) linger + (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan")) + (erc-d-t-search-for 2 "hey") + (erc-cmd-MSG "#chan hi")) + (erc-d-t-wait-for 10 "Bad match" errors))) + (should (string-match-p "Match failed.*hi" (cadr (pop errors)))))) + +(ert-deftest erc-d-run-linger-direct () + :tags '(:expensive-test) + (let* ((dumb-server (erc-d-run "localhost" t + 'linger-multi-a 'linger-multi-b)) + (port (process-contact dumb-server :service)) + (dumb-server-buffer (get-buffer "*erc-d-server*")) + (client-buffer-a (get-buffer-create "*erc-d-client-a*")) + (client-buffer-b (get-buffer-create "*erc-d-client-b*")) + (start (current-time)) + client-a client-b) + (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting")) + (setq client-a (open-network-stream "erc-d-client-a" client-buffer-a + "localhost" port + :coding 'binary) + client-b (open-network-stream "erc-d-client-b" client-buffer-b + "localhost" port + :coding 'binary)) + (process-send-string client-a "PASS :a\r\n") + (sleep-for 0.01) + (process-send-string client-b "PASS :b\r\n") + (sleep-for 0.01) + (erc-d-t-wait-for 3 "dumb-server death" + (not (process-live-p dumb-server))) + (ert-info ("Ensure linger of one second") + (should (time-less-p 1 (time-subtract (current-time) start))) + (should (time-less-p (time-subtract (current-time) start) 1.5))) + (delete-process client-a) + (delete-process client-b) + (when noninteractive + (kill-buffer client-buffer-a) + (kill-buffer client-buffer-b) + (kill-buffer dumb-server-buffer)))) + +(ert-deftest erc-d-run-drop-direct () + :tags '(:unstable) + (let* ((dumb-server (erc-d-run "localhost" t 'drop-a 'drop-b)) + (port (process-contact dumb-server :service)) + (dumb-server-buffer (get-buffer "*erc-d-server*")) + (client-buffer-a (get-buffer-create "*erc-d-client-a*")) + (client-buffer-b (get-buffer-create "*erc-d-client-b*")) + (start (current-time)) + client-a client-b) + (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting")) + (setq client-a (open-network-stream "erc-d-client-a" client-buffer-a + "localhost" port + :coding 'binary) + client-b (open-network-stream "erc-d-client-b" client-buffer-b + "localhost" port + :coding 'binary)) + (process-send-string client-a "PASS :a\r\n") + (sleep-for 0.01) + (process-send-string client-b "PASS :b\r\n") + (erc-d-t-wait-for 3 "client-a dies" (not (process-live-p client-a))) + (should (time-less-p (time-subtract (current-time) start) 0.32)) + (erc-d-t-wait-for 3 "dumb-server death" + (not (process-live-p dumb-server))) + (ert-info ("Ensure linger of one second") + (should (time-less-p 1 (time-subtract (current-time) start)))) + (delete-process client-a) + (delete-process client-b) + (when noninteractive + (kill-buffer client-buffer-a) + (kill-buffer client-buffer-b) + (kill-buffer dumb-server-buffer)))) + +(ert-deftest erc-d-run-no-match () + :tags '(:expensive-test) + (let ((erc-d-linger-secs 1) + erc-server-auto-reconnect + errors) + (erc-d-tests-with-failure-spy errors '(erc-d--teardown erc-d-command) + (erc-d-tests-with-server (_ erc-server-buffer) no-match + (with-current-buffer erc-server-buffer + (erc-d-t-search-for 2 "away") + (erc-cmd-JOIN "#foo") + (erc-d-t-wait-for 10 "Bad match" errors)))) + (should (string-match-p "Match failed.*foo.*chan" (cadr (pop errors)))) + (should-not (get-buffer "#foo")))) + +(ert-deftest erc-d-run-timeout () + :tags '(:expensive-test) + (let ((erc-d-linger-secs 1) + err errors) + (erc-d-tests-with-failure-spy errors '(erc-d--teardown) + (erc-d-tests-with-server (_ _) timeout + (erc-d-t-wait-for 10 "error caught" errors))) + (setq err (pop errors)) + (should (eq (car err) 'erc-d-timeout)) + (should (string-match-p "Timed out" (cadr err))))) + +(ert-deftest erc-d-run-unexpected () + :tags '(:expensive-test) + (let ((erc-d-linger-secs 2) + errors) + (erc-d-tests-with-failure-spy + errors '(erc-d--teardown erc-d-command) + (erc-d-tests-with-server (_ _) unexpected + (ert-info ("All specs consumed when more input arrives") + (erc-d-t-wait-for 10 "error caught" (cdr errors))))) + (should (string-match-p "unexpected.*MODE" (cadr (pop errors)))) + ;; Nonsensical normally because func would have already exited when + ;; first error was thrown + (should (string-match-p "Match failed" (cadr (pop errors)))))) + +(ert-deftest erc-d-run-unexpected-depleted () + :tags '(:expensive-test) + (let ((erc-d-linger-secs 3) + errors) + (erc-d-tests-with-failure-spy errors '(erc-d--teardown erc-d-command) + (let* ((dumb-server-buffer (get-buffer-create "*erc-d-server*")) + (dumb-server (erc-d-run "localhost" t 'depleted)) + (expect (erc-d-t-make-expecter)) + (client-buf (get-buffer-create "*erc-d-client*")) + client-proc) + (with-current-buffer dumb-server-buffer + (erc-d-t-search-for 3 "Starting")) + (setq client-proc (make-network-process + :buffer client-buf + :name "erc-d-client" + :family 'ipv4 + :noquery t + :coding 'binary + :service (process-contact dumb-server :service) + :host "localhost")) + (with-current-buffer dumb-server-buffer + (funcall expect 3 "open from")) + (process-send-string client-proc "PASS :changeme\r\n") + (sleep-for 0.01) + (process-send-string client-proc "NICK tester\r\n") + (sleep-for 0.01) + (process-send-string client-proc "USER user 0 * :tester\r\n") + (sleep-for 0.01) + (when (process-live-p client-proc) + (process-send-string client-proc "BLAH :too much\r\n") + (sleep-for 0.01)) + (with-current-buffer client-buf + (funcall expect 3 "Welcome to the Internet")) + (erc-d-t-wait-for 2 "dumb-server death" + (not (process-live-p dumb-server))) + (delete-process client-proc) + (when noninteractive + (kill-buffer client-buf) + (kill-buffer dumb-server-buffer)))) + (should (string-match-p "unexpected.*BLAH" (cadr (pop errors)))) + ;; Wouldn't happen IRL + (should (string-match-p "unexpected.*BLAH" (cadr (pop errors)))) + (should-not errors))) + +(defun erc-d-tests--dynamic-match-user (_dialog exchange) + "Shared pattern/response handler for canned dynamic DIALOG test." + (should (string= (match-string 1 (erc-d-exchange-request exchange)) + "tester"))) + +(defun erc-d-tests--run-dynamic () + "Perform common assertions for \"dynamic\" dialog." + (erc-d-tests-with-server (dumb-server erc-server-buffer) dynamic + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan")) + (erc-d-t-search-for 2 "tester: hey")) + (with-current-buffer erc-server-buffer + (let ((expect (erc-d-t-make-expecter))) + (funcall expect 2 "host is irc.fsf.org") + (funcall expect 2 "modes for tester"))) + (with-current-buffer (process-buffer dumb-server) + (erc-d-t-search-for 2 "irc.fsf.org")) + (when noninteractive + (kill-buffer "#chan")))) + +(ert-deftest erc-d-run-dynamic-default-match () + :tags '(:expensive-test) + (let* (dynamic-tally + (erc-d-tmpl-vars '((user . "user") + (ignored . ((a b) (: a space b))) + (realname . (group (+ graph))))) + (nick (lambda (a) + (push '(nick . match-user) dynamic-tally) + (funcall a :set (funcall a :match 1) 'export))) + (dom (lambda (a) + (push '(dom . match-user) dynamic-tally) + (funcall a :set erc-d-server-fqdn))) + (erc-d-match-handlers + (list :user (lambda (d e) + (erc-d-exchange-rebind d e 'nick nick) + (erc-d-exchange-rebind d e 'dom dom) + (erc-d-tests--dynamic-match-user d e)) + :mode-user (lambda (d e) + (erc-d-exchange-rebind d e 'nick "tester") + (erc-d-exchange-rebind d e 'dom dom)))) + (erc-d-server-fqdn "irc.fsf.org")) + (erc-d-tests--run-dynamic) + (should (equal '((dom . match-user) (nick . match-user) (dom . match-user)) + dynamic-tally)))) + +(ert-deftest erc-d-run-dynamic-default-match-rebind () + :tags '(:expensive-test) + (let* (tally + ;; + (erc-d-tmpl-vars '((user . "user") + (ignored . ((a b) (: a space b))) + (realname . (group (+ graph))))) + (erc-d-match-handlers + (list :user + (lambda (d e) + (erc-d-exchange-rebind + d e 'nick + (lambda (a) + (push 'bind-nick tally) + (funcall a :rebind 'nick (funcall a :match 1) 'export))) + (erc-d-exchange-rebind + d e 'dom + (lambda () + (push 'bind-dom tally) + (erc-d-exchange-rebind d e 'dom erc-d-server-fqdn))) + (erc-d-tests--dynamic-match-user d e)) + :mode-user + (lambda (d e) + (erc-d-exchange-rebind d e 'nick "tester") + (erc-d-exchange-rebind d e 'dom erc-d-server-fqdn)))) + (erc-d-server-fqdn "irc.fsf.org")) + (erc-d-tests--run-dynamic) + (should (equal '(bind-nick bind-dom) tally)))) + +(ert-deftest erc-d-run-dynamic-runtime-stub () + :tags '(:expensive-test) + (let ((erc-d-tmpl-vars '((token . (group (or "barnet" "foonet"))))) + (erc-d-match-handlers + (list :pass (lambda (d _e) + (erc-d-load-replacement-dialog d 'dynamic-foonet)))) + (erc-d-tests-with-server-password "foonet:changeme")) + (erc-d-tests-with-server (_ erc-server-buffer) + (dynamic-stub dynamic-foonet) + (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan")) + (erc-d-t-search-for 2 "alice:") + (erc-d-t-absent-for 0.1 "joe")) + (with-current-buffer erc-server-buffer + (let ((expect (erc-d-t-make-expecter))) + (funcall expect 2 "host is irc.foonet.org") + (funcall expect 2 "NETWORK=FooNet"))) + (when noninteractive + (kill-buffer "#chan"))))) + +(ert-deftest erc-d-run-dynamic-runtime-stub-skip () + :tags '(:expensive-test) + (let ((erc-d-tmpl-vars '((token . "barnet"))) + (erc-d-match-handlers + (list :pass (lambda (d _e) + (erc-d-load-replacement-dialog + d 'dynamic-barnet 1)))) + (erc-d-tests-with-server-password "barnet:changeme")) + (erc-d-tests-with-server (_ erc-server-buffer) + (dynamic-stub dynamic-barnet) + (with-current-buffer (erc-d-t-wait-for 3 (get-buffer "#chan")) + (erc-d-t-search-for 2 "joe:") + (erc-d-t-absent-for 0.1 "alice")) + (with-current-buffer erc-server-buffer + (let ((expect (erc-d-t-make-expecter))) + (funcall expect 2 "host is irc.barnet.org") + (funcall expect 2 "NETWORK=BarNet"))) + (when noninteractive + (kill-buffer "#chan"))))) + +;; Two servers, in-process, one client per +(ert-deftest erc-d-run-dual-direct () + :tags '(:expensive-test) + (let* ((erc-d--slow-mo -1) + (server-a (erc-d-run "localhost" t "erc-d-server-a" 'dynamic-foonet)) + (server-b (erc-d-run "localhost" t "erc-d-server-b" 'dynamic-barnet)) + (server-a-buffer (get-buffer "*erc-d-server-a*")) + (server-b-buffer (get-buffer "*erc-d-server-b*")) + (client-a-buffer (get-buffer-create "*erc-d-client-a*")) + (client-b-buffer (get-buffer-create "*erc-d-client-b*")) + client-a client-b) + (with-current-buffer server-a-buffer (erc-d-t-search-for 4 "Starting")) + (with-current-buffer server-b-buffer (erc-d-t-search-for 4 "Starting")) + (setq client-a (make-network-process + :buffer client-a-buffer + :name "erc-d-client-a" + :family 'ipv4 + :noquery t + :coding 'binary + :service (process-contact server-a :service) + :host "localhost") + client-b (make-network-process + :buffer client-b-buffer + :name "erc-d-client-b" + :family 'ipv4 + :noquery t + :coding 'binary + :service (process-contact server-b :service) + :host "localhost")) + ;; Also tests slo-mo indirectly because FAKE would fail without it + (process-send-string client-a "NICK tester\r\n") + (process-send-string client-b "FAKE noop\r\nNICK tester\r\n") + (sleep-for 0.01) + (process-send-string client-a "USER user 0 * :tester\r\n") + (process-send-string client-b "USER user 0 * :tester\r\n") + (sleep-for 0.01) + (process-send-string client-a "MODE tester +i\r\n") + (process-send-string client-b "MODE tester +i\r\n") + (sleep-for 0.01) + (process-send-string client-a "MODE #chan\r\n") + (process-send-string client-b "MODE #chan\r\n") + (sleep-for 0.01) + (erc-d-t-wait-for 2 "server-a death" (not (process-live-p server-a))) + (erc-d-t-wait-for 2 "server-b death" (not (process-live-p server-b))) + (when noninteractive + (kill-buffer client-a-buffer) + (kill-buffer client-b-buffer) + (kill-buffer server-a-buffer) + (kill-buffer server-b-buffer)))) + +;; This can be removed; only exists to get a baseline for next test +(ert-deftest erc-d-run-fuzzy-direct () + :tags '(:expensive-test) + (let* ((erc-d-tmpl-vars + `((now . ,(lambda () (format-time-string "%FT%T.%3NZ" nil t))))) + (dumb-server (erc-d-run "localhost" t 'fuzzy)) + (dumb-server-buffer (get-buffer "*erc-d-server*")) + (client-buffer (get-buffer-create "*erc-d-client*")) + client) + (with-current-buffer "*erc-d-server*" (erc-d-t-search-for 4 "Starting")) + (setq client (make-network-process + :buffer client-buffer + :name "erc-d-client" + :family 'ipv4 + :noquery t + :coding 'binary + :service (process-contact dumb-server :service) + :host "localhost")) + ;; We could also just send this as a single fatty + (process-send-string client "PASS :changeme\r\n") + (sleep-for 0.01) + (process-send-string client "NICK tester\r\n") + (sleep-for 0.01) + (process-send-string client "USER user 0 * :tester\r\n") + (sleep-for 0.01) + (process-send-string client "MODE tester +i\r\n") + (sleep-for 0.01) + (process-send-string client "JOIN #bar\r\n") + (sleep-for 0.01) + (process-send-string client "JOIN #foo\r\n") + (sleep-for 0.01) + (process-send-string client "MODE #bar\r\n") + (sleep-for 0.01) + (process-send-string client "MODE #foo\r\n") + (sleep-for 0.01) + (erc-d-t-wait-for 1 "dumb-server death" + (not (process-live-p dumb-server))) + (when noninteractive + (kill-buffer client-buffer) + (kill-buffer dumb-server-buffer)))) + +;; Without adjusting penalty, takes ~15 secs. With is comprable to direct ^. +(ert-deftest erc-d-run-fuzzy () + :tags '(:expensive-test) + (let ((erc-server-flood-penalty 1.2) ; penalty < margin/sends is basically 0 + (erc-d-linger-secs 0.1) + (erc-d-tmpl-vars + `((now . ,(lambda () (format-time-string "%FT%T.%3NZ" nil t))))) + erc-server-auto-reconnect) + (erc-d-tests-with-server (_ erc-server-buffer) fuzzy + (with-current-buffer erc-server-buffer + (erc-d-t-search-for 2 "away") + (goto-char erc-input-marker) + (erc-cmd-JOIN "#bar")) + (erc-d-t-wait-for 2 (get-buffer "#bar")) + (with-current-buffer erc-server-buffer + (erc-cmd-JOIN "#foo")) + (erc-d-t-wait-for 20 (get-buffer "#foo")) + (with-current-buffer "#bar" + (erc-d-t-search-for 1 "was created on")) + (with-current-buffer "#foo" + (erc-d-t-search-for 5 "was created on"))))) + +(ert-deftest erc-d-run-no-block () + :tags '(:expensive-test) + (let ((erc-server-flood-penalty 1) + (erc-d-linger-secs 1.2) + (expect (erc-d-t-make-expecter)) + erc-server-auto-reconnect) + (erc-d-tests-with-server (_ erc-server-buffer) no-block + (with-current-buffer erc-server-buffer + (funcall expect 2 "away") + (funcall expect 1 erc-prompt) + (with-current-buffer erc-server-buffer (erc-cmd-JOIN "#foo"))) + (with-current-buffer (erc-d-t-wait-for 2 (get-buffer "#foo")) + (funcall expect 2 "was created on")) + + (ert-info ("Join #bar") + (with-current-buffer erc-server-buffer (erc-cmd-JOIN "#bar")) + (erc-d-t-wait-for 2 (get-buffer "#bar"))) + + (with-current-buffer "#bar" (funcall expect 1 "was created on")) + + (ert-info ("Server expects next pattern but keeps sending") + (with-current-buffer "#foo" (funcall expect 2 "Rosalind, I will ")) + (with-current-buffer "#bar" (funcall expect 1 "hi 123")) + (with-current-buffer "#foo" + (should-not (search-forward " I am heard" nil t)) + (funcall expect 1.5 " I am heard")))))) + +(defun erc-d-tests--run-proxy-direct (dumb-server dumb-server-buffer port) + "Start DUMB-SERVER with DUMB-SERVER-BUFFER and PORT. +These are steps shared by in-proc and subproc variants testing a +bouncer-like setup." + (when (version< emacs-version "28") (ert-skip "TODO connection refused")) + (let ((client-buffer-foo (get-buffer-create "*erc-d-client-foo*")) + (client-buffer-bar (get-buffer-create "*erc-d-client-bar*")) + (expect (erc-d-t-make-expecter)) + client-foo + client-bar) + (setq client-foo (make-network-process + :buffer client-buffer-foo + :name "erc-d-client-foo" + :family 'ipv4 + :noquery t + :coding 'binary + :service port + :host "localhost") + client-bar (make-network-process + :buffer client-buffer-bar + :name "erc-d-client-bar" + :family 'ipv4 + :noquery t + :coding 'binary + :service port + :host "localhost")) + (with-current-buffer dumb-server-buffer + (funcall expect 3 "open from")) + (process-send-string client-foo "PASS :foo:changeme\r\n") + (process-send-string client-bar "PASS :bar:changeme\r\n") + (sleep-for 0.01) + (process-send-string client-foo "NICK tester\r\n") + (process-send-string client-bar "NICK tester\r\n") + (sleep-for 0.01) + (process-send-string client-foo "USER user 0 * :tester\r\n") + (process-send-string client-bar "USER user 0 * :tester\r\n") + (sleep-for 0.01) + (process-send-string client-foo "MODE tester +i\r\n") + (process-send-string client-bar "MODE tester +i\r\n") + (sleep-for 0.01) + (with-current-buffer client-buffer-foo + (funcall expect 3 "FooNet") + (funcall expect 3 "irc.foo.net") + (funcall expect 3 "marked as being away") + (goto-char (point-min)) + (should-not (search-forward "bar" nil t))) + (with-current-buffer client-buffer-bar + (funcall expect 3 "BarNet") + (funcall expect 3 "irc.bar.net") + (funcall expect 3 "marked as being away") + (goto-char (point-min)) + (should-not (search-forward "foo" nil t))) + (erc-d-t-wait-for 2 "dumb-server death" + (not (process-live-p dumb-server))) + (delete-process client-foo) + (delete-process client-bar) + (when noninteractive + (kill-buffer client-buffer-foo) + (kill-buffer client-buffer-bar) + (kill-buffer dumb-server-buffer)))) + +;; This test shows the simplest way to set up template variables: put +;; everything needed for the whole session in `erc-d-tmpl-vars' before +;; starting the server. + +(ert-deftest erc-d-run-proxy-direct-spec-vars () + :tags '(:expensive-test) + (let* ((dumb-server-buffer (get-buffer-create "*erc-d-server*")) + (erc-d-linger-secs 0.5) + (erc-d-tmpl-vars + `((network . (group (+ alpha))) + (fqdn . ,(lambda (a) + (let ((network (funcall a :match 1 'pass))) + (should (member network '("foo" "bar"))) + (funcall a :set (concat "irc." network ".net"))))) + (net . ,(lambda (a) + (let ((network (funcall a :match 1 'pass))) + (should (member network '("foo" "bar"))) + (concat (capitalize network) "Net")))))) + (dumb-server (erc-d-run "localhost" t 'proxy-foonet 'proxy-barnet)) + (port (process-contact dumb-server :service))) + (with-current-buffer dumb-server-buffer + (erc-d-t-search-for 3 "Starting")) + (erc-d-tests--run-proxy-direct dumb-server dumb-server-buffer port))) + +(cl-defun erc-d-tests--start-server (&key dialogs buffer linger program libs) + "Start and return a server in a subprocess using BUFFER and PORT. +DIALOGS are symbols representing the base names of dialog files in +`erc-d-u-canned-dialog-dir'. LIBS are extra files to load." + (push (locate-library "erc-d" nil (list erc-d-u--library-directory)) libs) + (cl-assert (car libs)) + (let* ((args `("erc-d-server" ,buffer + ,(concat invocation-directory invocation-name) + "-Q" "-batch" "-L" ,erc-d-u--library-directory + ,@(let (o) (while libs (push (pop libs) o) (push "-l" o)) o) + "-eval" ,(format "%S" program) "-f" "erc-d-serve" + ,@(when linger (list "--linger" (number-to-string linger))) + ,@(mapcar #'erc-d-u--expand-dialog-symbol dialogs))) + (proc (apply #'start-process args))) + (set-process-query-on-exit-flag proc nil) + (with-current-buffer buffer + (erc-d-t-search-for 5 "Starting") + (search-forward " (") + (backward-char)) + (let ((pair (read buffer))) + (cons proc (cdr pair))))) + +(ert-deftest erc-d-run-proxy-direct-subprocess () + :tags '(:expensive-test) + (let* ((buffer (get-buffer-create "*erc-d-server*")) + ;; These are quoted because they're passed as printed forms to subproc + (fqdn '(lambda (a e) + (let* ((d (erc-d-exchange-dialog e)) + (name (erc-d-dialog-name d))) + (funcall a :set (if (eq name 'proxy-foonet) + "irc.foo.net" + "irc.bar.net"))))) + (net '(lambda (a) + (funcall a :rebind 'net + (if (eq (funcall a :dialog-name) 'proxy-foonet) + "FooNet" + "BarNet")))) + (program `(setq erc-d-tmpl-vars '((fqdn . ,fqdn) + (net . ,net) + (network . (group (+ alpha)))))) + (port (erc-d-tests--start-server + :linger 0.3 + :program program + :buffer buffer + :dialogs '(proxy-foonet proxy-barnet))) + (server (pop port))) + (erc-d-tests--run-proxy-direct server buffer port))) + +(ert-deftest erc-d-run-proxy-direct-subprocess-lib () + :tags '(:expensive-test) + (let* ((buffer (get-buffer-create "*erc-d-server*")) + (lib (expand-file-name "proxy-subprocess.el" + (ert-resource-directory))) + (port (erc-d-tests--start-server :linger 0.3 + :buffer buffer + :dialogs '(proxy-foonet proxy-barnet) + :libs (list lib))) + (server (pop port))) + (erc-d-tests--run-proxy-direct server buffer port))) + +(ert-deftest erc-d-run-no-pong () + :tags '(:expensive-test) + (let* (erc-d-auto-pong + ;; + (erc-d-tmpl-vars + `((nonce . (group (: digit digit))) + (echo . ,(lambda (a) + (should (string= (funcall a :match 1) "42")) "42")))) + (dumb-server-buffer (get-buffer-create "*erc-d-server*")) + (dumb-server (erc-d-run "localhost" t 'no-pong)) + (expect (erc-d-t-make-expecter)) + (client-buf (get-buffer-create "*erc-d-client*")) + client-proc) + (with-current-buffer dumb-server-buffer + (erc-d-t-search-for 3 "Starting")) + (setq client-proc (make-network-process + :buffer client-buf + :name "erc-d-client" + :family 'ipv4 + :noquery t + :coding 'binary + :service (process-contact dumb-server :service) + :host "localhost")) + (with-current-buffer dumb-server-buffer + (funcall expect 3 "open from")) + (process-send-string client-proc "PASS :changeme\r\nNICK tester\r\n") + (sleep-for 0.01) + (process-send-string client-proc "USER user 0 * :tester\r\n") + (sleep-for 0.01) + (process-send-string client-proc "MODE tester +i\r\n") + (sleep-for 0.01) + (with-current-buffer client-buf + (funcall expect 3 "ExampleOrg") + (funcall expect 3 "irc.example.org") + (funcall expect 3 "marked as being away")) + (ert-info ("PING is not intercepted by specialized method") + (process-send-string client-proc "PING 42\r\n") + (with-current-buffer client-buf + (funcall expect 3 "PONG"))) + (erc-d-t-wait-for 2 "dumb-server death" + (not (process-live-p dumb-server))) + (delete-process client-proc) + (when noninteractive + (kill-buffer client-buf) + (kill-buffer dumb-server-buffer)))) + +;; Inspect replies as they arrive within a single exchange, i.e., ensure we +;; don't regress to prior buggy version in which inspection wasn't possible +;; until all replies had been sent by the server. +(ert-deftest erc-d-run-incremental () + :tags '(:expensive-test) + (let ((erc-server-flood-penalty 0) + (expect (erc-d-t-make-expecter)) + erc-d-linger-secs) + (erc-d-tests-with-server (_ erc-server-buffer) incremental + (with-current-buffer erc-server-buffer + (funcall expect 3 "marked as being away")) + (with-current-buffer erc-server-buffer + (erc-cmd-JOIN "#foo")) + (with-current-buffer (erc-d-t-wait-for 1 (get-buffer "#foo")) + (funcall expect 1 "Users on #foo") + (funcall expect 1 "Look for me") + (not (search-forward "Done" nil t)) + (funcall expect 10 "Done") + (erc-send-message "Hi"))))) + +(ert-deftest erc-d-unix-socket-direct () + :tags '(:expensive-test) + (skip-unless (featurep 'make-network-process '(:family local))) + (let* ((erc-d-linger-secs 0.1) + (sock (expand-file-name "erc-d.sock" temporary-file-directory)) + (dumb-server (erc-d-run nil sock 'basic)) + (dumb-server-buffer (get-buffer "*erc-d-server*")) + (client-buffer (get-buffer-create "*erc-d-client*")) + client) + (with-current-buffer "*erc-d-server*" + (erc-d-t-search-for 4 "Starting")) + (unwind-protect + (progn + (setq client (make-network-process + :buffer client-buffer + :name "erc-d-client" + :family 'local + :noquery t + :coding 'binary + :service sock)) + (process-send-string client "PASS :changeme\r\n") + (sleep-for 0.01) + (process-send-string client "NICK tester\r\n") + (sleep-for 0.01) + (process-send-string client "USER user 0 * :tester\r\n") + (sleep-for 0.1) + (process-send-string client "MODE tester +i\r\n") + (sleep-for 0.01) + (process-send-string client "MODE #chan\r\n") + (sleep-for 0.01) + (erc-d-t-wait-for 1 "dumb-server death" + (not (process-live-p dumb-server))) + (when noninteractive + (kill-buffer client-buffer) + (kill-buffer dumb-server-buffer))) + (delete-file sock)))) + +;;; erc-d-tests.el ends here diff --git a/test/lisp/erc/resources/erc-d/erc-d-u.el b/test/lisp/erc/resources/erc-d/erc-d-u.el new file mode 100644 index 0000000000..ce13efef62 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/erc-d-u.el @@ -0,0 +1,213 @@ +;;; erc-d-u.el --- Helpers for ERC test server -*- lexical-binding: t -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;;; Commentary: + +;; The utilities here are kept separate from those in `erc-d' so that +;; tests running the server in a subprocess can use them without +;; having to require the main lib. If migrating outside of test/lisp, +;; there may be no reason to continue this. +;; +;; Another (perhaps misguided) goal here is to avoid having ERC itself +;; as a dependency. +;; +;; FIXME this ^ is no longer the case (ERC is not a dependency) + +;;; Code: +(require 'rx) +(require 'subr-x) +(eval-when-compile (require 'ert)) + +(defvar erc-d-u--canned-buffers nil + "List of canned dialog buffers currently open for reading.") + +(cl-defstruct (erc-d-u-scan-d) ; dialog scanner + (buf nil :type buffer) + (done nil :type boolean) + (last nil :type integer) + (hunks nil :type (list-of marker)) + (f #'erc-d-u--read-exchange-default :type function)) + +(cl-defstruct (erc-d-u-scan-e) ; exchange scanner + (sd nil :type erc-d-u-scan-d) + (pos nil :type marker)) + +(defun erc-d-u--read-dialog (info) + "Read dialog file and stash relevant state in `erc-d-u-scan-d' INFO." + (if (and (buffer-live-p (erc-d-u-scan-d-buf info)) + (with-current-buffer (erc-d-u-scan-d-buf info) + (condition-case _err + (progn + (when (erc-d-u-scan-d-last info) + (goto-char (erc-d-u-scan-d-last info)) + (forward-list)) + (setf (erc-d-u-scan-d-last info) (point)) + (down-list) + (push (set-marker (make-marker) (point)) + (erc-d-u-scan-d-hunks info))) + ((end-of-buffer scan-error) + (setf (erc-d-u-scan-d-done info) t) + nil)))) + (make-erc-d-u-scan-e :sd info :pos (car (erc-d-u-scan-d-hunks info))) + (unless (erc-d-u-scan-d-hunks info) + (kill-buffer (erc-d-u-scan-d-buf info)) + nil))) + +(defun erc-d-u--read-exchange-default (info) + "Read from marker in exchange `erc-d-u-scan-e' object INFO." + (let ((hunks (erc-d-u-scan-e-sd info)) + (pos (erc-d-u-scan-e-pos info))) + (or (and (erc-d-u-scan-d-hunks hunks) + (with-current-buffer (erc-d-u-scan-d-buf hunks) + (goto-char pos) + (condition-case _err + (read pos) + ;; Raised unless malformed + (invalid-read-syntax + nil)))) + (unless (or (cl-callf (lambda (s) (delq pos s)) ; flip + (erc-d-u-scan-d-hunks hunks)) + (not (erc-d-u-scan-d-done hunks))) + (kill-buffer (erc-d-u-scan-d-buf hunks)) + nil)))) + +(defun erc-d-u--read-exchange (info) + "Call exchange reader assigned in `erc-d-u-scan-e' object INFO." + (funcall (erc-d-u-scan-d-f (erc-d-u-scan-e-sd info)) info)) + +(defun erc-d-u--canned-read (file) + "Dispense a reader for each exchange in dialog FILE." + (let ((buf (generate-new-buffer (file-name-nondirectory file)))) + (push buf erc-d-u--canned-buffers) + (with-current-buffer buf + (setq-local parse-sexp-ignore-comments t + coding-system-for-read 'utf-8) + (add-hook 'kill-buffer-hook + (lambda () (setq erc-d-u--canned-buffers + (delq buf erc-d-u--canned-buffers))) + nil 'local) + (insert-file-contents-literally file) + (lisp-data-mode)) + (make-erc-d-u-scan-d :buf buf))) + +(defvar erc-d-u--library-directory (file-name-directory load-file-name)) +(defvar erc-d-u-canned-dialog-dir + (file-name-as-directory (expand-file-name "resources" + erc-d-u--library-directory))) + +(defun erc-d-u--normalize-canned-name (dialog) + "Return DIALOG name as a symbol without validating it." + (if (symbolp dialog) + dialog + (intern (file-name-base dialog)))) + +(defvar erc-d-u-canned-file-name-extension ".eld") + +(defun erc-d-u--expand-dialog-symbol (dialog) + "Return filename based on symbol DIALOG." + (let ((name (symbol-name dialog))) + (unless (equal (file-name-extension name) + erc-d-u-canned-file-name-extension) + (setq name (concat name erc-d-u-canned-file-name-extension))) + (expand-file-name name erc-d-u-canned-dialog-dir))) + +(defun erc-d-u--massage-canned-name (dialog) + "Return DIALOG in a form acceptable to `erc-d-run'." + (if (or (symbolp dialog) (file-exists-p dialog)) + dialog + (erc-d-u--expand-dialog-symbol (intern dialog)))) + +(defun erc-d-u--canned-load-dialog (dialog) + "Load dispensing exchanges from DIALOG. +If DIALOG is a string, consider it a filename. Otherwise find a file +in `erc-d-u-canned-dialog-dir' with a base name matching the symbol's +name. + +Return an iterator that yields exchanges, each one an iterator of spec +forms. The first is a so-called request spec and the rest are composed +of zero or more response specs." + (when (symbolp dialog) + (setq dialog (erc-d-u--expand-dialog-symbol dialog))) + (unless (file-exists-p dialog) + (error "File not found: %s" dialog)) + (erc-d-u--canned-read dialog)) + +(defun erc-d-u--read-exchange-slowly (num orig info) + (when-let ((spec (funcall orig info))) + (when (symbolp (car spec)) + (setf spec (copy-sequence spec) + (nth 1 spec) (cond ((functionp num) (funcall num (nth 1 spec))) + ((< num 0) (max (nth 1 spec) (- num))) + (t (+ (nth 1 spec) num))))) + spec)) + +(defun erc-d-u--rewrite-for-slow-mo (num read-info) + "Return READ-INFO with a modified reader. +When NUM is a positive number, delay incoming requests by NUM more +seconds. If NUM is negative, raise insufficient incoming delays to at +least -NUM seconds. If NUM is a function, set each delay to whatever it +returns when called with the existing value." + (let ((orig (erc-d-u-scan-d-f read-info))) + (setf (erc-d-u-scan-d-f read-info) + (apply-partially #'erc-d-u--read-exchange-slowly num orig)) + read-info)) + +(defun erc-d-u--get-remote-port (process) + "Return peer TCP port for client PROCESS. +When absent, just generate an id." + (let ((remote (plist-get (process-contact process t) :remote))) + (if (vectorp remote) + (aref remote (1- (length remote))) + (format "%s:%d" (process-contact process :local) + (logand 1023 (time-convert nil 'integer)))))) + +(defun erc-d-u--format-bind-address (process) + "Return string or (STRING . INT) for bind address of network PROCESS." + (let ((local (process-contact process :local))) + (if (vectorp local) ; inet + (cons (mapconcat #'number-to-string (seq-subseq local 0 -1) ".") + (aref local (1- (length local)))) + local))) + +(defun erc-d-u--unkeyword (plist) + "Return a copy of PLIST with keywords keys converted to non-keywords." + (cl-loop for (key value) on plist by #'cddr + when (keywordp key) + do (setq key (intern (substring (symbol-name key) 1))) + append (list key value))) + +(defun erc-d-u--massage-rx-args (key val) + " Massage val so it's suitable for an `rx-let' binding. +Handle cases in which VAL is ([ARGLIST] RX-FORM) rather than just +RX-FORM. KEY becomes the binding name." + (if (and (listp val) + (cdr val) + (not (cddr val)) + (consp (car val))) + (cons key val) + (list key val))) + +(defvar-local erc-d-u--process-buffer nil + "Beacon for erc-d process buffers. +The server process is usually deleted first, but we may want to examine +the buffer afterward.") + +(provide 'erc-d-u) +;;; erc-d-u.el ends here diff --git a/test/lisp/erc/resources/erc-d/erc-d.el b/test/lisp/erc/resources/erc-d/erc-d.el new file mode 100644 index 0000000000..ee9b6a7fec --- /dev/null +++ b/test/lisp/erc/resources/erc-d/erc-d.el @@ -0,0 +1,997 @@ +;;; erc-d.el --- A dumb test server for ERC -*- lexical-binding: t -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;;; Commentary: + +;; This is a netcat style server for testing ERC. The "d" in the name +;; stands for "daemon" as well as for "dialog" (as well as for "dumb" +;; because this server isn't very smart). It either spits out a +;; canned reply when an incoming request matches the expected regexp +;; or signals an error and dies. The entry point function is +;; `erc-d-run'. +;; +;; Canned scripts, or "dialogs," should be Lisp-Data files containing +;; one or more request/reply forms like this: +;; +;; | ((mode-chan 1.5 "MODE #chan") ; request: tag, expr, regex +;; | (0.1 ":irc.org 324 bob #chan +Cint") ; reply: delay, content +;; | (0.0 ":irc.org 329 bob #chan 12345")) ; reply: ... +;; +;; These are referred to as "exchanges." The first element is a list +;; whose CAR is a descriptive "tag" and whose CDR is an incoming +;; "spec" representing an inbound message from the client. The rest +;; of the exchange is composed of outgoing specs representing +;; server-to-client messages. A tag can be any symbol (ideally unique +;; in the dialog), but a leading tilde means the request should be +;; allowed to arrive out of order (within the allotted time). +;; +;; The first element in an incoming spec is a number indicating the +;; maximum number of seconds to wait for a match before raising an +;; error. The CDR is interpreted as the collective arguments of an +;; `rx' form to be matched against the raw request (stripped of its +;; CRLF line ending). A "string-start" backslash assertion, "\\`", is +;; prepended to all patterns. +;; +;; Similarly, the leading number in an *outgoing* spec indicates how +;; many seconds to wait before sending the line, which is rendered by +;; concatenating the other members after evaluating each in place. +;; CRLF line endings are appended on the way out and should be absent. +;; +;; Recall that IRC is "asynchronous," meaning some flow intervals +;; don't jibe with lockstep request-reply semantics. However, for our +;; purposes, grouping things as [input, output1, ..., outputN] makes +;; sense, even though input and output may be completely unrelated. +;; +;; Template interpolation: +;; +;; A rudimentary templating facility is provided for additional +;; flexibility. However, it's best to keep things simple (even if +;; overly verbose), so others can easily tell what's going on at a +;; glance. If necessary, consult existing tests for examples (grep +;; for the variables `erc-d-tmpl-vars' and `erc-d-match-handlers'). +;; +;; Subprocess or in-process?: +;; +;; Running in-process confers better visibility and easier setup at +;; the cost of additional cleanup and resource wrangling. With a +;; subprocess, cleanup happens by pulling the plug, but configuration +;; means loading a separate file or passing -eval "(forms...)" during +;; invocation. In some cases, a subprocess may be the only option, +;; like when trying to avoid `require'ing this file. +;; +;; Dialog objects: +;; +;; For a given exchange, the first argument passed to a request +;; handler is the `erc-d-dialog' object representing the overall +;; conversation with the connecting peer. It can be used to pass +;; information between handlers during a session. Some important +;; items are: +;; +;; * name (symbol); name of the current dialog +;; +;; * queue (ring); a backlog of unhandled raw requests, minus CRLF +;; endings. +;; +;; * timers (list of timers); when run, these send messages originally +;; deferred as per the most recently matched exchange's delay info. +;; Normally, all outgoing messages must be sent before another request +;; is considered. (See `erc-d--send-outgoing' for an escape hatch.) +;; +;; * hunks (iterator of iterators); unconsumed exchanges as read from +;; a Lisp-Data dialog file. The exchange iterators being dispensed +;; themselves yield portions of member forms as a 2- or 3-part +;; sequence: [tag] spec. (Here, "hunk" just means "list of raw, +;; unrendered exchange elements") +;; +;; * vars (alist of cons pairs); for sharing state among template +;; functions during the lifetime of an exchange. Initially populated +;; by `erc-d-tmpl-vars', these KEY/VALUE pairs are expanded in the +;; templates and optionally updated by "exchange handlers" (see +;; `erc-d-match-handlers'). When VALUE is a function, occurrences of +;; KEY in an outgoing spec are replaced with the result of calling +;; VALUE with match data set appropriately. See +;; `erc-d--render-entries' for details. +;; +;; * exchanges (ring of erc-d-exchange objects); activated hunks +;; allowed to match out of order, plus the current active exchange +;; being yielded from, if any. See `erc-d-exchange'. +;; +;; TODO +;; +;; - Remove un(der)used functionality and simplify API +;; - Maybe migrate d-u and d-i dependencies here + +;;; Code: +(eval-and-compile + (let* ((d (file-name-directory (or (macroexp-file-name) buffer-file-name))) + (load-path (cons (directory-file-name d) load-path))) + (require 'erc-d-i) + (require 'erc-d-u))) + +(require 'ring) + +(defvar erc-d-server-name "erc-d-server" + "Default name of a server process and basis for its buffer name. +Only relevant when starting a server with `erc-d-run'.") + +(defvar erc-d-server-fqdn "irc.example.org" + "Usually the same as the server's RPL_MYINFO \"announced name\". +Possibly used by overriding handlers, like the one for PING, and/or +dialog templates for the sender portion of a reply message.") + +(defvar erc-d-linger-secs nil + "Seconds to wait before quitting for all dialogs. +For more granular control, use the provided LINGER `rx' variable (alone) +as the incoming template spec of a dialog's last exchange.") + +(defvar erc-d-tmpl-vars nil + "An alist of template bindings available to client dialogs. +Populate it when calling `erc-d-run', and the contents will be made +available to all client dialogs through the `erc-d-dialog' \"vars\" +field and (therefore) to all templates as variables when rendering. For +example, a key/value pair like (network . \"oftc\") will cause instances +of the (unquoted) symbol `network' to be replaced with \"oftc\" in the +rendered template string. + +This list provides default template bindings common to all dialogs. +Each new client-connection process makes a shallow copy on init, but the +usual precautions apply when mutating member items. Within the span of +a dialog, updates not applicable to all exchanges should die with their +exchange. See `erc-d--render-entries' for details. In the unlikely +event that an exchange-specific handler is needed, see +`erc-d-match-handlers'.") + +(defvar erc-d-match-handlers nil + "A plist of exchange-tag symbols mapped to request-handler functions. +This is meant to address edge cases for which `erc-d-tmpl-vars' comes up +short. These may include (1) needing access to the client process +itself and/or (2) adding or altering outgoing response templates before +rendering. Note that (2) requires using `erc-d-exchange-rebind' instead +of manipulating exchange bindings directly. + +The hook-like function `erc-d-on-match' calls any handler whose key is +`eq' to the tag of the currently matched exchange (passing the client +`erc-d-dialog' as the first argument and the current `erc-d-exchange' +object as the second). The handler runs just prior to sending the first +response.") + +(defvar erc-d-auto-pong t + "Handle PING requests automatically.") + +(defvar erc-d--in-process t + "Whether the server is running in the same Emacs as ERT.") + +(defvar erc-d--slow-mo nil + "Adjustment for all incoming timeouts. +This is to allow for human interaction or a slow Emacs or CI runner. +The value is the number of seconds to extend all incoming spec timeouts +by on init. If the value is a negative number, it's negated and +interpreted as a lower bound to raise all incoming timeouts to. If the +value is a function, it should take an existing timeout in seconds and +return a replacement.") + +(defconst erc-d--eof-sentinel "__EOF__") +(defconst erc-d--linger-sentinel "__LINGER__") +(defconst erc-d--drop-sentinel "__DROP__") + +(defvar erc-d--clients nil + "List containing all clients for this server session.") + +;; Some :type names may just be made up (not actual CL types) + +(cl-defstruct (erc-d-spec) ; see `erc-d--render-entries' + (head nil :type symbol) ; or number? + (entry nil :type list) + (state 0 :type integer)) + +(cl-defstruct (erc-d-exchange) + "Object representing a request/response unit from a canned dialog." + (dialog nil :type erc-d-dialog) ; owning dialog + (tag nil :type symbol) ; a.k.a. tag, the caar + (pattern nil :type string) ; regexp to match requests against + (inspec nil :type list) ; original unrendered incoming spec + (hunk nil :type erc-d-u-scan-e) ; active raw exchange hunk being yielded + (spec nil :type erc-d-spec) ; active spec, see `erc-d--render-entries' + (timeout nil :type number) ; time allotted for current request + (timer nil :type timer) ; match timer fires when timeout expires + (bindings nil :type list) ; `eval'-style env pairs (KEY . VAL) ... + (rx-bindings nil :type list) ; rx-let bindings + (deferred nil :type boolean) ; whether sender is paused + ;; Post-match + (match-data nil :type match-data) ; from the latest matched request + (request nil :type string)) ; the original request sans CRLF + +(cl-defstruct (erc-d-dialog) + "Session state for managing a client conversation." + (process nil :type process) ; client-connection process + (name nil :type symbol) ; likely the interned stem of the file + (queue nil :type ring) ; backlog of incoming lines to process + (hunks nil :type erc-d-u-scan-d) ; nil when done; info on raw exchange hunks + (timers nil :type list) ; unsent replies + (vars nil :type list) ; template bindings for rendering + (exchanges nil :type ring) ; ring of erc-d-exchange objects + (state nil :type symbol) ; handler's last recorded control state + (matched nil :type erc-d-exchange) ; currently matched exchange + (message nil :type erc-d-i-message) ; `erc-d-i-message' + (match-handlers nil :type list) ; copy of `erc-d-match-handlers' + (server-fqdn nil :type string) ; copy of `erc-d-server-fqdn' + (finalizer nil :type function) ; custom teardown, passed dialog and exchange + ;; Post-match history is a plist whose keys are exchange tags + ;; (symbols) and whose values are a cons of match-data and request + ;; values from prior matches. + (history nil :type list)) + +(defun erc-d--initialize-client (process) + "Initialize state variables used by a client PROCESS." + ;; Discard server-only/owned props + (process-put process :dialog-dialogs nil) + (let* ((server (process-get process :server)) + (reader (pop (process-get server :dialog-dialogs))) + (name (pop reader)) + ;; Copy handlers so they can self-mutate per process + (mat-h (copy-sequence (process-get process :dialog-match-handlers))) + (fqdn (copy-sequence (process-get process :dialog-server-fqdn))) + (vars (copy-sequence (process-get process :dialog-vars))) + (dialog (make-erc-d-dialog :name name + :process process + :queue (make-ring 5) + :exchanges (make-ring 10) + :match-handlers mat-h + :server-fqdn fqdn))) + ;; Add items expected by convenience commands like `erc-d-exchange-reload'. + (setf (alist-get 'EOF vars) `(: ,erc-d--eof-sentinel eot) + (alist-get 'LINGER vars) `(: ,erc-d--linger-sentinel eot) + (alist-get 'DROP vars) `(: ,erc-d--drop-sentinel eot) + (erc-d-dialog-vars dialog) vars + (erc-d-dialog-hunks dialog) reader) + ;; Add reverse link, register client, launch + (process-put process :dialog dialog) + (push process erc-d--clients) + (erc-d--command-refresh dialog nil) + (erc-d--on-request process))) + +(defun erc-d-load-replacement-dialog (dialog replacement &optional skip) + "Find REPLACEMENT among backlog and swap out current DIALOG's iterator. +With int SKIP, advance past that many exchanges." + (let* ((process (erc-d-dialog-process dialog)) + (server (process-get process :server)) + (reader (assoc-default replacement + (process-get server :dialog-dialogs) + #'eq))) + (when skip (while (not (zerop skip)) + (erc-d-u--read-dialog reader) + (cl-decf skip))) + (dolist (timer (erc-d-dialog-timers dialog)) + (cancel-timer timer)) + (dolist (exchange (ring-elements (erc-d-dialog-exchanges dialog))) + (cancel-timer (erc-d-exchange-timer exchange))) + (setf (erc-d-dialog-hunks dialog) reader) + (erc-d--command-refresh dialog nil))) + +(defvar erc-d--m-debug (getenv "ERC_D_DEBUG")) + +(defmacro erc-d--m (process format-string &rest args) + "Output ARGS using FORMAT-STRING somewhere depending on context. +PROCESS should be a client connection or a server network process." + `(let ((format-string (if erc-d--m-debug + (concat (format-time-string "%s.%N: ") + ,format-string) + ,format-string)) + (want-insert (and ,process erc-d--in-process))) + (when want-insert + (with-current-buffer (process-buffer (process-get ,process :server)) + (goto-char (point-max)) + (insert (concat (format ,format-string ,@args) "\n")))) + (when (or erc-d--m-debug (not want-insert)) + (message format-string ,@args)))) + +(defmacro erc-d--log (process string &optional outbound) + "Log STRING sent to (OUTBOUND) or received from PROCESS peer." + `(let ((id (or (process-get ,process :log-id) + (let ((port (erc-d-u--get-remote-port ,process))) + (process-put ,process :log-id port) + port))) + (name (erc-d-dialog-name (process-get ,process :dialog)))) + (if ,outbound + (erc-d--m process "-> %s:%s %s" name id ,string) + (dolist (line (split-string ,string "\r\n")) + (erc-d--m process "<- %s:%s %s" name id line))))) + +(defun erc-d--log-process-event (server process msg) + (erc-d--m server "%s: %s" process (string-trim-right msg))) + +(defun erc-d--send (process string) + "Send STRING to PROCESS peer." + (erc-d--log process string 'outbound) + (process-send-string process (concat string "\r\n"))) + +(define-inline erc-d--fuzzy-p (exchange) + (inline-letevals (exchange) + (inline-quote + (let ((tag (symbol-name (erc-d-exchange-tag ,exchange)))) + (eq ?~ (aref tag 0)))))) + +(define-error 'erc-d-timeout "Timed out awaiting expected request") + +(defun erc-d--finalize-dialog (dialog) + "Delete client-connection and finalize DIALOG. +Return associated server." + (let ((process (erc-d-dialog-process dialog))) + (setq erc-d--clients (delq process erc-d--clients)) + (dolist (timer (erc-d-dialog-timers dialog)) + (cancel-timer timer)) + (dolist (exchange (ring-elements (erc-d-dialog-exchanges dialog))) + (cancel-timer (erc-d-exchange-timer exchange))) + (prog1 (process-get process :server) + (delete-process process)))) + +(defun erc-d--teardown (&optional sig &rest msg) + "Clean up processes and maybe send signal SIG using MSG." + (unless erc-d--in-process + (when sig + (erc-d--m nil "%s %s" sig (apply #'format-message msg))) + (kill-emacs (if msg 1 0))) + (let (process servers) + (while (setq process (pop erc-d--clients)) + (push (erc-d--finalize-dialog (process-get process :dialog)) servers)) + (dolist (server servers) + (delete-process server))) + (dolist (timer timer-list) + (when (memq (timer--function timer) + '(erc-d--send erc-d--command-handle-all)) + (erc-d--m nil "Stray timer found: %S" (timer--function timer)) + (cancel-timer timer))) + (when sig + (dolist (buf erc-d-u--canned-buffers) + (kill-buffer buf)) + (setq erc-d-u--canned-buffers nil) + (signal sig (list (apply #'format-message msg))))) + +(defun erc-d--teardown-this-dialog-at-least (dialog) + "Run `erc-d--teardown' after destroying DIALOG if it's the last one." + (let ((server (process-get (erc-d-dialog-process dialog) :server)) + (us (erc-d-dialog-process dialog))) + (erc-d--finalize-dialog dialog) + (cl-assert (not (memq us erc-d--clients))) + (unless (or (process-get server :dialog-dialogs) + (catch 'other + (dolist (process erc-d--clients) + (when (eq (process-get process :server) server) + (throw 'other process))))) + (push us erc-d--clients) + (erc-d--teardown)))) + +(defun erc-d--expire (dialog exchange) + "Raise timeout error for EXCHANGE. +This will start the teardown for DIALOG." + (setf (erc-d-exchange-spec exchange) nil) + (if-let ((finalizer (erc-d-dialog-finalizer dialog))) + (funcall finalizer dialog exchange) + (erc-d--teardown 'erc-d-timeout "Timed out awaiting request: %s" + (list :name (erc-d-exchange-tag exchange) + :pattern (erc-d-exchange-pattern exchange) + :timeout (erc-d-exchange-timeout exchange) + :dialog (erc-d-dialog-name dialog))))) + +;; Using `run-at-time' here allows test cases to examine replies as +;; they arrive instead of forcing tests to wait until an exchange +;; completes. The `run-at-time' in `erc-d--command-meter-replies' +;; does the same. When running as a subprocess, a normal while loop +;; with a `sleep-for' works fine (including with multiple dialogs). +;; FYI, this issue was still present in older versions that called +;; this directly from `erc-d--filter'. + +(defun erc-d--on-request (process) + "Handle one request for client-connection PROCESS." + (when (process-live-p process) + (let* ((dialog (process-get process :dialog)) + (queue (erc-d-dialog-queue dialog))) + (unless (ring-empty-p queue) + (let* ((parsed (ring-remove queue)) + (cmd (intern (erc-d-i-message.command parsed)))) + (setf (erc-d-dialog-message dialog) parsed) + (erc-d-command dialog cmd))) + (run-at-time nil nil #'erc-d--on-request process)))) + +(defun erc-d--drop-p (exchange) + (memq 'DROP (erc-d-exchange-inspec exchange))) + +(defun erc-d--linger-p (exchange) + (memq 'LINGER (erc-d-exchange-inspec exchange))) + +(defun erc-d--fake-eof (dialog) + "Simulate receiving a fictitious \"EOF\" message from peer." + (setf (erc-d-dialog-message dialog) ; use downcase for internal cmds + (make-erc-d-i-message :command "eof" :unparsed erc-d--eof-sentinel)) + (run-at-time nil nil #'erc-d-command dialog 'eof)) + +(defun erc-d--process-sentinel (process event) + "Set up or tear down client-connection PROCESS depending on EVENT." + (erc-d--log-process-event process process event) + (if (eq 'open (process-status process)) + (erc-d--initialize-client process) + (let* ((dialog (process-get process :dialog)) + (exes (and dialog (erc-d-dialog-exchanges dialog)))) + (if (and exes (not (ring-empty-p exes))) + (cond ((string-prefix-p "connection broken" event) + (erc-d--fake-eof dialog)) + ;; Ignore disconnecting peer when pattern is DROP + ((and (string-prefix-p "deleted" event) + (erc-d--drop-p (ring-ref exes -1)))) + (t (erc-d--teardown))) + (erc-d--teardown))))) + +(defun erc-d--filter (process string) + "Handle input received from peer. +PROCESS represents a client peer connection and STRING is a raw request +including line delimiters." + (let ((queue (erc-d-dialog-queue (process-get process :dialog)))) + (setq string (concat (process-get process :stashed-input) string)) + (while (and string (string-match (rx (+ "\r\n")) string)) + (let ((line (substring string 0 (match-beginning 0)))) + (setq string (unless (= (match-end 0) (length string)) + (substring string (match-end 0)))) + (erc-d--log process line nil) + (ring-insert queue (erc-d-i--parse-message line 'decode)))) + (when string + (setf (process-get process :stashed-input) string)))) + +;; Misc process properties: +;; +;; The server property `:dialog-dialogs' is an alist of (symbol +;; . erc-d-u-scan-d) conses, each of which pairs a dialogs name with +;; info on its read progress (described above in the Commentary). +;; This list is populated by `erc-d-run' at the start of each session. +;; +;; Client-connection processes keep a reference to their server via a +;; `:server' property, which can be used to share info with other +;; clients. There is currently no built-in way to do the same with +;; clients of other servers. Clients also keep references to their +;; dialogs and raw messages via `:dialog' and `:stashed-input'. +;; +;; The logger stores a unique, human-friendly process name in the +;; client-process property `:log-id'. + +(defun erc-d--start (host service name &rest plist) + "Serve canned replies on HOST at SERVICE. +Return the new server process immediately when `erc-d--in-process' is +non-nil. Otherwise, serve forever. PLIST becomes the plist of the +server process and is used to initialize the plists of connection +processes. NAME is used for the process and the buffer." + (let* ((buf (get-buffer-create (concat "*" name "*"))) + (proc (make-network-process :server t + :buffer buf + :noquery t + :filter #'erc-d--filter + :log #'erc-d--log-process-event + :sentinel #'erc-d--process-sentinel + :name name + :family (if host 'ipv4 'local) + :coding 'binary + :service (or service t) + :host host + :plist plist))) + (process-put proc :server proc) + ;; We don't have a minor mode, so use an arbitrary variable to mark + ;; buffers owned by us instead + (with-current-buffer buf (setq erc-d-u--process-buffer t)) + (erc-d--m proc "Starting network process: %S %S" + proc (erc-d-u--format-bind-address proc)) + (if erc-d--in-process + proc + (while (process-live-p proc) + (accept-process-output nil 0.01))))) + +(defun erc-d--wrap-func-val (dialog exchange key func) + "Return a form invoking FUNC when evaluated. +Arrange for FUNC to be called with the args it expects based on +the description in `erc-d--render-entries'." + (let (args) + ;; Ignore &rest or &optional + (pcase-let ((`(,n . ,_) (func-arity func))) + (pcase n + (0) + (1 (push (apply-partially #'erc-d-exchange-multi dialog exchange key) + args)) + (2 (push exchange args) + (push (apply-partially #'erc-d-exchange-multi dialog exchange key) + args)) + (_ (error "Incompatible function: %s" func)))) + (lambda () (apply func args)))) + +(defun erc-d-exchange-reload (dialog exchange) + "Rebuild all bindings for EXCHANGE from those in DIALOG." + (cl-loop for (key . val) in (erc-d-dialog-vars dialog) + unless (keywordp key) + do (push (erc-d-u--massage-rx-args key val) + (erc-d-exchange-rx-bindings exchange)) + when (functionp val) do + (setq val (erc-d--wrap-func-val dialog exchange key val)) + do (push (cons key val) (erc-d-exchange-bindings exchange)))) + +(defun erc-d-exchange-rebind (dialog exchange key val &optional export) + "Modify a binding between renders. + +Bind symbol KEY to VAL, replacing whatever existed before, which may +have been a function. A third, optional argument, if present and +non-nil, results in the DIALOG's bindings for all EXCHANGEs adopting +this binding. VAL can either be a function of the type described in +`erc-d--render-entries' or any value acceptable as an argument to the +function `concat'. + +DIALOG and EXCHANGE are the current `erc-d-dialog' and `erc-d-exchange' +objects for the request context." + (when export + (setf (alist-get key (erc-d-dialog-vars dialog)) val)) + (if (functionp val) + (setf (alist-get key (erc-d-exchange-bindings exchange)) + (erc-d--wrap-func-val dialog exchange key val)) + (setf (alist-get key (erc-d-exchange-rx-bindings exchange)) (list val) + (alist-get key (erc-d-exchange-bindings exchange)) val)) + val) + +(defun erc-d-exchange-match (exchange match-number &optional tag) + "Return match portion of current or previous request. +MATCH-NUMBER is the match group number. TAG, if provided, means the +exchange tag (name) from some previously matched request." + (if tag + (pcase-let* ((dialog (erc-d-exchange-dialog exchange)) + (`(,m-d . ,req) (plist-get (erc-d-dialog-history dialog) + tag))) + (set-match-data m-d) + (match-string match-number req)) + (match-string match-number (erc-d-exchange-request exchange)))) + +(defun erc-d-exchange-multi (dialog exchange key cmd &rest args) + "Call CMD with ARGS. +This is a utility passed as the first argument to all template +functions. DIALOG and EXCHANGE are pre-applied. A few pseudo +commands, like `:request', are provided for convenience so that +the caller's definition doesn't have to include this file. The +rest are access and mutation utilities, such as `:set', which +assigns KEY a new value, `:get-binding', which looks up KEY in +`erc-d-exchange-bindings', and `:get-var', which looks up KEY in +`erc-d-dialog-vars'." + (pcase cmd + (:set (apply #'erc-d-exchange-rebind dialog exchange key args)) + (:reload (apply #'erc-d-exchange-reload dialog exchange args)) + (:rebind (apply #'erc-d-exchange-rebind dialog exchange args)) + (:match (apply #'erc-d-exchange-match exchange args)) + (:request (erc-d-exchange-request exchange)) + (:match-data (erc-d-exchange-match-data exchange)) + (:dialog-name (erc-d-dialog-name dialog)) + (:get-binding (cdr (assq (car args) (erc-d-exchange-bindings exchange)))) + (:get-var (alist-get (car args) (erc-d-dialog-vars dialog))))) + +(defun erc-d--render-incoming-entry (exchange spec) + (let ((rx--local-definitions (rx--extend-local-defs + (erc-d-exchange-rx-bindings exchange)))) + (rx-to-string `(: bos ,@(erc-d-spec-entry spec)) 'no-group))) + +(defun erc-d--render-outgoing-entry (exchange entry) + (let (out this) + (while (setq this (pop entry)) + (set-match-data (erc-d-exchange-match-data exchange)) + (unless (stringp this) + (cl-assert (symbolp this)) + (setq this (or (alist-get this (erc-d-exchange-bindings exchange)) + (symbol-value this))) + ;; Allow reference to overlong var name unbecoming of a template + (when this + (when (symbolp this) (setq this (symbol-value this))) + (when (functionp this) (setq this (save-match-data (funcall this)))) + (unless (stringp this) (error "Unexpected token %S" this)))) + (push this out)) + (apply #'concat (nreverse out)))) + +(defun erc-d--render-entries (exchange &optional yield-result) + "Act as an iterator producing rendered strings from EXCHANGE hunks. +When an entry's CAR is an arbitrary symbol, yield that back first, and +consider the entry an \"incoming\" entry. Then, regardless of the +entry's type (incoming or outgoing), yield back the next element, which +should be a number representing either a timeout (incoming) or a +delay (outgoing). After that, yield a rendered template (outgoing) or a +regular expression (incoming); both should be treated as immutable. + +When evaluating a template, bind the keys in the alist stored in the +dialog's `vars' field to its values, but skip any self-quoters, like +:foo. When an entry is incoming, replace occurrences of a key with its +value, which can be any valid `rx' form (see Info node `(elisp) +Extending Rx'). Do the same when an entry is outgoing, but expect a +value's form to be (anything that evaluates to) something acceptable by +`concat' or, alternatively, a function that returns a string or nil. + +Repeat the last two steps for the remaining entries, all of which are +assumed to be outgoing. That is, continue yielding a timeout/delay and +a rendered string for each entry, and yield nil when exhausted. + +Once again, for an incoming entry, the yielded string is a regexp to be +matched against the raw request. For outgoing, it's the final response, +ready to be sent out (after adding the appropriate line ending). + +To help with testing, bindings are not automatically created from +DIALOG's \"vars\" alist when this function is invoked. But this can be +forced by sending a non-nil YIELD-RESULT into the generator on the +second \"next\" invocation of a given iteration. This clobbers any +temporary bindings that don't exist in the DIALOG's `vars' alist, such +as those added via `erc-d-exchange-rebind' (unless \"exported\"). + +As noted earlier, template symbols can be bound to functions. When +called during rendering, the match data from the current (matched) +request is accessible by calling the function `match-data'. + +A function may ask for up to two required args, which are provided as +needed. When applicable, the first required arg is a `funcall'-able +helper that accepts various keyword-based commands, like :rebind, and a +variable number of args. See `erc-d-exchange-multi' for details. When +specified, the second required arg is the current `erc-d-exchange' +object, which has among its members its owning `erc-d-dialog' object. +This should suffice as a safety valve for any corner-case needs. +Non-required args are ignored." + (let ((spec (erc-d-exchange-spec exchange)) + (dialog (erc-d-exchange-dialog exchange)) + (entries (erc-d-exchange-hunk exchange))) + (unless (erc-d-spec-entry spec) + (setf (erc-d-spec-entry spec) (erc-d-u--read-exchange entries))) + (catch 'yield + (while (erc-d-spec-entry spec) + (pcase (erc-d-spec-state spec) + (0 (cl-incf (erc-d-spec-state spec)) + (throw 'yield (setf (erc-d-spec-head spec) + (pop (erc-d-spec-entry spec))))) + (1 (cl-incf (erc-d-spec-state spec)) + (when yield-result + (erc-d-exchange-reload dialog exchange)) + (unless (numberp (erc-d-spec-head spec)) + (setf (erc-d-exchange-inspec exchange) (erc-d-spec-entry spec)) + (throw 'yield + (prog1 (pop (erc-d-spec-entry spec)) + (setf (erc-d-spec-entry spec) + (erc-d--render-incoming-entry exchange spec)))))) + (2 (setf (erc-d-spec-state spec) 0) + (throw 'yield + (let ((entry (erc-d-spec-entry spec))) + (setf (erc-d-spec-entry spec) nil) + (if (stringp entry) + entry + (erc-d--render-outgoing-entry exchange entry)))))))))) + +(defun erc-d--iter (exchange) + (apply-partially #'erc-d--render-entries exchange)) + +(defun erc-d-on-match (dialog exchange) + "Handle matched exchange request. +Allow the first handler in `erc-d-match-handlers' whose key matches TAG +to manipulate replies before they're sent to the DIALOG peer." + (when-let* ((tag (erc-d-exchange-tag exchange)) + (handler (plist-get (erc-d-dialog-match-handlers dialog) tag))) + (let ((md (erc-d-exchange-match-data exchange))) + (set-match-data md) + (funcall handler dialog exchange)))) + +(defun erc-d--send-outgoing (dialog exchange) + "Send outgoing lines for EXCHANGE to DIALOG peer. +Assume the next spec is outgoing. If its delay value is zero, render +the template and send the resulting message straight away. Do the same +when DELAY is negative, only arrange for its message to be sent (abs +DELAY) seconds later, and then keep on processing. If DELAY is +positive, pause processing and yield DELAY." + (let ((specs (erc-d--iter exchange)) + (process (erc-d-dialog-process dialog)) + (deferred (erc-d-exchange-deferred exchange)) + delay) + ;; Could stash/pass thunk instead to ensure specs can't be mutated + ;; between calls (by temporarily replacing dialog member with a fugazi) + (when deferred + (erc-d--send process (funcall specs)) + (setf deferred nil (erc-d-exchange-deferred exchange) deferred)) + (while (and (not deferred) (setq delay (funcall specs))) + (cond ((zerop delay) (erc-d--send process (funcall specs))) + ((< delay 0) (push (run-at-time (- delay) nil #'erc-d--send + process (funcall specs)) + (erc-d-dialog-timers dialog))) + ((setf deferred t (erc-d-exchange-deferred exchange) deferred)))) + delay)) + +(defun erc-d--add-dialog-linger (dialog exchange) + "Add finalizer for EXCHANGE in DIALOG." + (erc-d--m (erc-d-dialog-process dialog) + "Lingering for %.2f seconds" (erc-d-exchange-timeout exchange)) + (let ((start (current-time))) + (setf (erc-d-dialog-finalizer dialog) + (lambda (&rest _) + (erc-d--m (erc-d-dialog-process dialog) + "Lingered for %.2f seconds" + (float-time (time-subtract (current-time) start))) + (erc-d--teardown-this-dialog-at-least dialog))))) + +(defun erc-d--add-dialog-drop (dialog exchange) + "Add finalizer for EXCHANGE in DIALOG." + (erc-d--m (erc-d-dialog-process dialog) + "Dropping in %.2f seconds" (erc-d-exchange-timeout exchange)) + (setf (erc-d-dialog-finalizer dialog) + (lambda (&rest _) + (erc-d--m (erc-d-dialog-process dialog) + "Dropping %S" (erc-d-dialog-name dialog)) + (erc-d--finalize-dialog dialog)))) + +(defun erc-d--create-exchange (dialog hunk) + "Initialize next exchange HUNK for DIALOG." + (let* ((spec (make-erc-d-spec)) + (exchange (make-erc-d-exchange :dialog dialog :hunk hunk :spec spec)) + (specs (erc-d--iter exchange))) + (setf (erc-d-exchange-tag exchange) (funcall specs) + (erc-d-exchange-timeout exchange) (funcall specs t) + (erc-d-exchange-pattern exchange) (funcall specs)) + (cond ((erc-d--linger-p exchange) + (erc-d--add-dialog-linger dialog exchange)) + ((erc-d--drop-p exchange) + (erc-d--add-dialog-drop dialog exchange))) + (setf (erc-d-exchange-timer exchange) + (run-at-time (erc-d-exchange-timeout exchange) + nil #'erc-d--expire dialog exchange)) + exchange)) + +(defun erc-d--command-consider-prep-fail (dialog line exes) + (list 'error "Match failed: %S %S" line + (list :exes (mapcar #'erc-d-exchange-pattern + (ring-elements exes)) + :dialog (erc-d-dialog-name dialog)))) + +(defun erc-d--command-consider-prep-success (dialog line exes matched) + (setf (erc-d-exchange-request matched) line + (erc-d-exchange-match-data matched) (match-data) + ;; Also add current to match history, indexed by exchange tag + (plist-get (erc-d-dialog-history dialog) + (erc-d-exchange-tag matched)) + (cons (match-data) line)) ; do we need to make a copy of this? + (cancel-timer (erc-d-exchange-timer matched)) + (ring-remove exes (ring-member exes matched))) + +(cl-defun erc-d--command-consider (dialog) + "Maybe return next matched exchange for DIALOG. +Upon encountering a mismatch, return an error of the form (ERROR-SYMBOL +DATA). But when only fuzzies remain in the exchange pool, return nil." + (let* ((parsed (erc-d-dialog-message dialog)) + (line (erc-d-i-message.unparsed parsed)) + (exes (erc-d-dialog-exchanges dialog)) + ;; + matched) + (let ((elts (ring-elements exes))) + (while (and (setq matched (pop elts)) + (not (string-match (erc-d-exchange-pattern matched) line))) + (if (and (not elts) (erc-d--fuzzy-p matched)) + ;; Nothing to do, so advance + (cl-return-from erc-d--command-consider nil) + (cl-assert (or (not elts) (erc-d--fuzzy-p matched)))))) + (if matched + (erc-d--command-consider-prep-success dialog line exes matched) + (erc-d--command-consider-prep-fail dialog line exes)))) + +(defun erc-d--active-ex-p (ring) + "Return non-nil when RING has a non-fuzzy exchange. +That is, return nil when RING is empty or when it only has exchanges +with leading-tilde tags." + (let ((i 0) + (len (ring-length ring)) + ex found) + (while (and (not found) (< i len)) + (unless (erc-d--fuzzy-p (setq ex (ring-ref ring i))) + (setq found ex)) + (cl-incf i)) + found)) + +(defun erc-d--finalize-done (dialog) + ;; Linger logic for individual dialogs is handled elsewhere + (if-let ((finalizer (erc-d-dialog-finalizer dialog))) + (funcall finalizer dialog) + (let ((d (process-get (erc-d-dialog-process dialog) :dialog-linger-secs))) + (push (run-at-time d nil #'erc-d--teardown) + (erc-d-dialog-timers dialog))))) + +(defun erc-d--advance-or-die (dialog) + "Govern the lifetime of DIALOG. +Replenish exchanges from reader and insert them into the pool of +expected matches, as produced. Return a symbol indicating session +status: deferring, matching, depleted, or done." + (let ((exes (erc-d-dialog-exchanges dialog)) + hunk) + (cond ((erc-d--active-ex-p exes) 'deferring) + ((setq hunk (erc-d-u--read-dialog (erc-d-dialog-hunks dialog))) + (let ((exchange (erc-d--create-exchange dialog hunk))) + (if (erc-d--fuzzy-p exchange) + (ring-insert exes exchange) + (ring-insert-at-beginning exes exchange))) + 'matching) + ((not (ring-empty-p exes)) 'depleted) + (t 'done)))) + +(defun erc-d--command-meter-replies (dialog exchange &optional cmd) + "Ignore requests until all replies have been sent. +Do this for some previously matched EXCHANGE in DIALOG based on CMD, a +symbol. As a side effect, maybe schedule the resumption of the main +loop after some delay." + (let (delay) + (if (or (not cmd) (eq 'resume cmd)) + (when (setq delay (erc-d--send-outgoing dialog exchange)) + (push (run-at-time delay nil #'erc-d--command-handle-all + dialog 'resume) + (erc-d-dialog-timers dialog)) + (erc-d-dialog-state dialog)) + (setf (erc-d-dialog-state dialog) 'sending)))) + +(defun erc-d--die-unexpected (dialog) + (erc-d--teardown 'error "Received unexpected input: %S" + (erc-d-i-message.unparsed (erc-d-dialog-message dialog)))) + +(defun erc-d--command-refresh (dialog matched) + (let ((state (erc-d--advance-or-die dialog))) + (when (eq state 'done) + (erc-d--finalize-done dialog)) + (unless matched + (when (eq state 'depleted) + (erc-d--die-unexpected dialog)) + (cl-assert (memq state '(matching depleted)) t)) + (setf (erc-d-dialog-state dialog) state))) + +(defun erc-d--command-handle-all (dialog cmd) + "Create handler to act as control agent and process DIALOG requests. +Have it ingest internal control commands (lowercase symbols) and yield +back others indicating the lifecycle stage of the current dialog." + (let ((matched (erc-d-dialog-matched dialog))) + (cond + (matched + (or (erc-d--command-meter-replies dialog matched cmd) + (setf (erc-d-dialog-matched dialog) nil) + (erc-d--command-refresh dialog t))) + ((pcase cmd ; FIXME remove command facility or make extensible + ('resume nil) + ('eof (erc-d--m (erc-d-dialog-process dialog) "Received an EOF") nil))) + (t ; matching + (setq matched nil) + (catch 'yield + (while (not matched) + (when (ring-empty-p (erc-d-dialog-exchanges dialog)) + (erc-d--die-unexpected dialog)) + (when (setq matched (erc-d--command-consider dialog)) + (if (eq (car-safe matched) 'error) + (apply #'erc-d--teardown matched) + (erc-d-on-match dialog matched) + (setf (erc-d-dialog-matched dialog) matched) + (if-let ((s (erc-d--command-meter-replies dialog matched nil))) + (throw 'yield s) + (setf (erc-d-dialog-matched dialog) nil)))) + (erc-d--command-refresh dialog matched))))))) + +;;;; Handlers for IRC commands + +(cl-defgeneric erc-d-command (dialog cmd) + "Handle new CMD from client for DIALOG. +By default, defer to this dialog's `erc-d--command-handle-all' instance, +which is stored in its `handler' field.") + +(cl-defmethod erc-d-command ((dialog erc-d-dialog) cmd) + (when (eq 'sending (erc-d--command-handle-all dialog cmd)) + (ring-insert-at-beginning (erc-d-dialog-queue dialog) + (erc-d-dialog-message dialog)))) + +;; A similar PONG handler would be useless because we know when to +;; expect them + +(cl-defmethod erc-d-command ((dialog erc-d-dialog) (_cmd (eql PING)) + &context (erc-d-auto-pong (eql t))) + "Respond to PING request from DIALOG peer when ERC-D-AUTO-PONG is t." + (let* ((parsed (erc-d-dialog-message dialog)) + (process (erc-d-dialog-process dialog)) + (nonce (car (erc-d-i-message.command-args parsed))) + (fqdn (erc-d-dialog-server-fqdn dialog))) + (erc-d--send process (format ":%s PONG %s :%s" fqdn fqdn nonce)))) + + +;;;; Entry points + +(defun erc-d-run (host service &optional server-name &rest dialogs) + "Start serving DIALOGS on HOST at SERVICE. +Pass HOST and SERVICE directly to `make-network-process'. When present, +use string SERVER-NAME for the server-process name as well as that of +its buffer (w. surrounding asterisks). When absent, do the same with +`erc-d-server-name'. When running \"in process,\" return the server +process, otherwise sleep for the duration of the server process. + +A dialog must be a symbol matching the base name of a dialog file in +`erc-d-u-canned-dialog-dir'. + +The variable `erc-d-tmpl-vars' determines the common members of the +`erc-d--render-entries' ENTRIES param. Variables `erc-d-server-fqdn' +and `erc-d-linger-secs' determine the `erc-d-dialog' items +`:server-fqdn' and `:linger-secs' for all client processes. + +The variable `erc-d-tmpl-vars' can be used to initialize the +process's `erc-d-dialog' vars item." + (when (and server-name (symbolp server-name)) + (push server-name dialogs) + (setq server-name nil)) + (let (loaded) + (dolist (dialog (nreverse dialogs)) + (let ((reader (erc-d-u--canned-load-dialog dialog))) + (when erc-d--slow-mo + (setq reader (erc-d-u--rewrite-for-slow-mo erc-d--slow-mo reader))) + (push (cons (erc-d-u--normalize-canned-name dialog) reader) loaded))) + (setq dialogs loaded)) + (erc-d--start host service (or server-name erc-d-server-name) + :dialog-dialogs dialogs + :dialog-vars erc-d-tmpl-vars + :dialog-linger-secs erc-d-linger-secs + :dialog-server-fqdn erc-d-server-fqdn + :dialog-match-handlers (erc-d-u--unkeyword + erc-d-match-handlers))) + +(defun erc-d-serve () + "Start serving canned dialogs from the command line. +Although not autoloaded, this function is meant to be summoned via the +Emacs -f flag while starting a batch session. It prints incoming and +outgoing messages to standard out. + +The main options are --host HOST and --port PORT, which default to +localhost and auto, respectively. The args are the dialogs to run. +Unlike with `erc-d-run', dialogs here *must* be files, meaning Lisp-Data +files adhering to the required format. (These consist of \"specs\" +detailing timing and template info; see commentary for specifics.) + +An optional --add-time N option can also be passed to hike up timeouts +by some number of seconds N. For example, you might run: + + $ emacs -Q -batch -L . \\ + > -l erc-d.el \\ + > -f erc-d-serve \\ + > --host 192.168.124.1 \\ + > --port 16667 \\ + > --add-time 10 \\ + > ./my-dialog.eld + +from a Makefile or manually with \\\\[compile]. And then in +another terminal, do: + + $ nc -C 192.168.124.1 16667 ; or telnet if your nc doesn't have -C + > PASS changeme + ... + +Use `erc-d-run' instead to start the server from within Emacs." + (unless noninteractive + (error "Command-line func erc-d-serve not run in -batch session")) + (setq erc-d--in-process nil) + (let (port host dialogs erc-d--slow-mo) + (while command-line-args-left + (pcase (pop command-line-args-left) + ("--add-time" (setq erc-d--slow-mo + (string-to-number (pop command-line-args-left)))) + ("--linger" (setq erc-d-linger-secs + (string-to-number (pop command-line-args-left)))) + ("--host" (setq host (pop command-line-args-left))) + ("--port" (setq port (string-to-number (pop command-line-args-left)))) + (dialog (push dialog dialogs)))) + (setq dialogs (mapcar #'erc-d-u--massage-canned-name dialogs)) + (when erc-d--slow-mo + (message "Slow mo is ON")) + (apply #'erc-d-run (or host "localhost") port nil (nreverse dialogs)))) + +(provide 'erc-d) + +;;; erc-d.el ends here diff --git a/test/lisp/erc/resources/erc-d/resources/basic.eld b/test/lisp/erc/resources/erc-d/resources/basic.eld new file mode 100644 index 0000000000..a020eec3ff --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/basic.eld @@ -0,0 +1,32 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :tester") + (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester") + (0 ":irc.example.org 002 tester :Your host is irc.example.org") + (0 ":irc.example.org 003 tester :This server was created just now") + (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + ;; Just to mix thing's up (force handler to schedule timer) + (0.1 ":irc.example.org 252 tester 0 :IRC Operators online") + (0 ":irc.example.org 253 tester 0 :unregistered connections") + (0 ":irc.example.org 254 tester 1 :channels formed") + (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers") + (0.1 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.example.org 422 tester :MOTD File is missing")) + +((mode-user 5 "MODE tester +i") + (0 ":irc.example.org 221 tester +Zi") + (0 ":irc.example.org 306 tester :You have been marked as being away") + (0 ":tester!~tester@localhost JOIN #chan") + (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 ":irc.example.org 366 alice #chan :End of NAMES list")) + +;; Some comment (to prevent regression) +((mode-chan 1.2 "MODE #chan") + (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey")) diff --git a/test/lisp/erc/resources/erc-d/resources/depleted.eld b/test/lisp/erc/resources/erc-d/resources/depleted.eld new file mode 100644 index 0000000000..e5a7f03efb --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/depleted.eld @@ -0,0 +1,12 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS :changeme")) + +((~fake 3.2 "FAKE ") + (0.1 ":irc.example.org FAKE irc.example.com :ok")) + +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :tester") + (0 ":irc.example.org 001 tester :Welcome to the Internet tester") + (0 ":irc.example.org 422 tester :MOTD File is missing")) diff --git a/test/lisp/erc/resources/erc-d/resources/drop-a.eld b/test/lisp/erc/resources/erc-d/resources/drop-a.eld new file mode 100644 index 0000000000..2e23eeb20f --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/drop-a.eld @@ -0,0 +1,4 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS " (? ?:) "a") + (0 "hi")) +((drop 0.01 DROP)) diff --git a/test/lisp/erc/resources/erc-d/resources/drop-b.eld b/test/lisp/erc/resources/erc-d/resources/drop-b.eld new file mode 100644 index 0000000000..facecd5e81 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/drop-b.eld @@ -0,0 +1,4 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS " (? ?:) "b") + (0 "hi")) +((linger 1 LINGER)) diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld new file mode 100644 index 0000000000..36b1cc2308 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld @@ -0,0 +1,33 @@ +;;; -*- mode: lisp-data -*- +((fake 0 "FAKE noop")) + +((nick 1.2 "NICK tester")) + +((user 2.2 "USER user 0 * :tester") + (0. ":irc.barnet.org 001 tester :Welcome to the BAR Network tester") + (0. ":irc.barnet.org 002 tester :Your host is irc.barnet.org") + (0. ":irc.barnet.org 003 tester :This server was created just now") + (0. ":irc.barnet.org 004 tester irc.barnet.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0. ":irc.barnet.org 005 tester MODES NETWORK=BarNet NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server") + (0. ":irc.barnet.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0. ":irc.barnet.org 252 tester 0 :IRC Operators online") + (0. ":irc.barnet.org 253 tester 0 :unregistered connections") + (0. ":irc.barnet.org 254 tester 1 :channels formed") + (0. ":irc.barnet.org 255 tester :I have 3 clients and 0 servers") + (0. ":irc.barnet.org 265 tester 3 3 :Current local users 3, max 3") + (0. ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3") + (0. ":irc.barnet.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0. ":irc.barnet.org 221 tester +Zi") + (0. ":irc.barnet.org 306 tester :You have been marked as being away") + (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan") + (0 ":irc.barnet.org 353 joe = #chan :+joe!~joe@example.com @%+mike!~mike@example.org") + (0 ":irc.barnet.org 366 joe #chan :End of NAMES list")) + +((mode 1 "MODE #chan") + (0 ":irc.barnet.org 324 tester #chan +nt") + (0 ":irc.barnet.org 329 tester #chan 1620805269") + (0.1 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: Yes, a dozen; and as many to the vantage, as would store the world they played for.") + (0.05 ":mike!~u@awyxgybtkx7uq.irc PRIVMSG #chan :joe: As he regards his aged father's life.") + (0.05 ":joe!~u@awyxgybtkx7uq.irc PRIVMSG #chan :mike: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it.")) diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld new file mode 100644 index 0000000000..5dbea50f86 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld @@ -0,0 +1,32 @@ +;;; -*- mode: lisp-data -*- + +((nick 1.2 "NICK tester")) + +((user 2.2 "USER user 0 * :tester") + (0. ":irc.foonet.org 001 tester :Welcome to the FOO Network tester") + (0. ":irc.foonet.org 002 tester :Your host is irc.foonet.org") + (0. ":irc.foonet.org 003 tester :This server was created just now") + (0. ":irc.foonet.org 004 tester irc.foonet.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0. ":irc.foonet.org 005 tester MODES NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server") + (0. ":irc.foonet.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0. ":irc.foonet.org 252 tester 0 :IRC Operators online") + (0. ":irc.foonet.org 253 tester 0 :unregistered connections") + (0. ":irc.foonet.org 254 tester 1 :channels formed") + (0. ":irc.foonet.org 255 tester :I have 3 clients and 0 servers") + (0. ":irc.foonet.org 265 tester 3 3 :Current local users 3, max 3") + (0. ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3") + (0. ":irc.foonet.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0. ":irc.foonet.org 221 tester +Zi") + (0. ":irc.foonet.org 306 tester :You have been marked as being away") + (0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan") + (0 ":irc.foonet.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 ":irc.foonet.org 366 alice #chan :End of NAMES list")) + +((mode 2 "MODE #chan") + (0 ":irc.foonet.org 324 tester #chan +nt") + (0 ":irc.foonet.org 329 tester #chan 1620805269") + (0.1 ":alice!~u@awyxgybtkx7uq.irc PRIVMSG #chan :bob: Yes, a dozen; and as many to the vantage, as would store the world they played for.") + (0.05 ":bob!~u@awyxgybtkx7uq.irc PRIVMSG #chan :alice: As he regards his aged father's life.") + (0.05 ":alice!~u@awyxgybtkx7uq.irc PRIVMSG #chan :bob: It is a rupture that you may easily heal; and the cure of it not only saves your brother, but keeps you from dishonour in doing it.")) diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld b/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld new file mode 100644 index 0000000000..d93313023d --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/dynamic-stub.eld @@ -0,0 +1,4 @@ +;;; -*- mode: lisp-data -*- +((pass 10.0 "PASS " (? ?:) token ":changeme")) + +((fake 0 "FAKE")) diff --git a/test/lisp/erc/resources/erc-d/resources/dynamic.eld b/test/lisp/erc/resources/erc-d/resources/dynamic.eld new file mode 100644 index 0000000000..459b6e52bf --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/dynamic.eld @@ -0,0 +1,30 @@ +;;; -*- mode: lisp-data -*- +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 2.2 "NICK tester")) + +((user 2.2 "USER " user " " (ignored digit "*") " :" realname) + (0.0 ":" dom " 001 " nick " :Welcome to the Internet Relay Network tester") + (0.0 ":" dom " 002 " nick " :Your host is " dom) + (0.0 ":" dom " 003 " nick " :This server was created just now") + (0.0 ":" dom " 004 " nick " " dom " BERios CEIRabehiklmnoqstv Iabehkloqv") + (0.0 ":" dom " 005 " nick " MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0.0 ":" dom " 251 " nick " :There are 3 users and 0 invisible on 1 server(s)") + (0.0 ":" dom " 252 " nick " 0 :IRC Operators online") + (0.0 ":" dom " 253 " nick " 0 :unregistered connections") + (0.0 ":" dom " 254 " nick " 1 :channels formed") + (0.0 ":" dom " 255 " nick " :I have 3 clients and 0 servers") + (0.0 ":" dom " 265 " nick " 3 3 :Current local users 3, max 3") + (0.0 ":" dom " 266 " nick " 3 3 :Current global users 3, max 3") + (0.0 ":" dom " 422 " nick " :MOTD File is missing")) + +((mode-user 2.2 "MODE tester +i") + (0.0 ":" dom " 221 " nick " +Zi") + + (0.0 ":" dom " 306 " nick " :You have been marked as being away") + (0.0 ":" nick "!~" nick "@localhost JOIN #chan") + (0.0 ":" dom " 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org") + (0.0 ":" dom " 366 alice #chan :End of NAMES list")) + +((mode 2.2 "MODE #chan") + (0.1 ":bob!~bob@example.org PRIVMSG #chan :" nick ": hey")) diff --git a/test/lisp/erc/resources/erc-d/resources/eof.eld b/test/lisp/erc/resources/erc-d/resources/eof.eld new file mode 100644 index 0000000000..5da84b2e74 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/eof.eld @@ -0,0 +1,33 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :tester") + (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester") + (0 ":irc.example.org 002 tester :Your host is irc.example.org") + (0 ":irc.example.org 003 tester :This server was created just now") + (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + ;; Just to mix thing's up (force handler to schedule timer) + (0.1 ":irc.example.org 252 tester 0 :IRC Operators online") + (0 ":irc.example.org 253 tester 0 :unregistered connections") + (0 ":irc.example.org 254 tester 1 :channels formed") + (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.example.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":irc.example.org 221 tester +Zi") + (0 ":irc.example.org 306 tester :You have been marked as being away") + (0 ":tester!~tester@localhost JOIN #chan") + (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 ":irc.example.org 366 alice #chan :End of NAMES list")) + +((mode-chan 1.2 "MODE #chan") + (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey")) + +((eof 1.0 EOF)) diff --git a/test/lisp/erc/resources/erc-d/resources/fuzzy.eld b/test/lisp/erc/resources/erc-d/resources/fuzzy.eld new file mode 100644 index 0000000000..0504b6a668 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/fuzzy.eld @@ -0,0 +1,42 @@ +;;; -*- mode: lisp-data -*- +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.5 "USER user 0 * :tester") + (0.0 "@time=" now " :irc.org 001 tester :Welcome to the Internet Relay Network tester") + (0.0 "@time=" now " :irc.org 002 tester :Your host is irc.org") + (0.0 "@time=" now " :irc.org 003 tester :This server was created just now") + (0.0 "@time=" now " :irc.org 004 tester irc.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0.0 "@time=" now " :irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server") + (0.0 "@time=" now " :irc.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0.0 "@time=" now " :irc.org 252 tester 0 :IRC Operators online") + (0.0 "@time=" now " :irc.org 253 tester 0 :unregistered connections") + (0.0 "@time=" now " :irc.org 254 tester 1 :channels formed") + (0.0 "@time=" now " :irc.org 255 tester :I have 3 clients and 0 servers") + (0.0 "@time=" now " :irc.org 265 tester 3 3 :Current local users 3, max 3") + (0.0 "@time=" now " :irc.org 266 tester 3 3 :Current global users 3, max 3") + (0.0 "@time=" now " :irc.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0.0 "@time=" now " :irc.org 221 tester +Zi") + (0.0 "@time=" now " :irc.org 306 tester :You have been marked as being away")) + +((~join-foo 3.2 "JOIN #foo") + (0 "@time=" now " :tester!~tester@localhost JOIN #foo") + (0 "@time=" now " :irc.example.org 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 "@time=" now " :irc.example.org 366 alice #foo :End of NAMES list")) + +((~join-bar 1.2 "JOIN #bar") + (0 "@time=" now " :tester!~tester@localhost JOIN #bar") + (0 "@time=" now " :irc.example.org 353 alice = #bar :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 "@time=" now " :irc.example.org 366 alice #bar :End of NAMES list")) + +((~mode-foo 3.2 "MODE #foo") + (0.0 "@time=" now " :irc.example.org 324 tester #foo +Cint") + (0.0 "@time=" now " :irc.example.org 329 tester #foo 1519850102") + (0.1 "@time=" now " :bob!~bob@example.org PRIVMSG #foo :hey")) + +((mode-bar 10.2 "MODE #bar") + (0.0 "@time=" now " :irc.example.org 324 tester #bar +HMfnrt 50:5h :10:5") + (0.0 "@time=" now " :irc.example.org 329 tester #bar :1602642829") + (0.1 "@time=" now " :alice!~alice@example.com PRIVMSG #bar :hi")) diff --git a/test/lisp/erc/resources/erc-d/resources/incremental.eld b/test/lisp/erc/resources/erc-d/resources/incremental.eld new file mode 100644 index 0000000000..ab940fe612 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/incremental.eld @@ -0,0 +1,43 @@ +;;; -*- mode: lisp-data -*- +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :tester") + (0.0 ":irc.foo.net 001 tester :Welcome to the Internet Relay Network tester") + (0.0 ":irc.foo.net 002 tester :Your host is irc.foo.net") + (0.0 ":irc.foo.net 003 tester :This server was created just now") + (0.0 ":irc.foo.net 004 tester irc.foo.net BERios CEIRabehiklmnoqstv Iabehkloqv") + (0.0 ":irc.foo.net 005 tester MODES NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0.0 ":irc.foo.net 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0.0 ":irc.foo.net 252 tester 0 :IRC Operators online") + (0.0 ":irc.foo.net 253 tester 0 :unregistered connections") + (0.0 ":irc.foo.net 254 tester 1 :channels formed") + (0.0 ":irc.foo.net 255 tester :I have 3 clients and 0 servers") + (0.0 ":irc.foo.net 265 tester 3 3 :Current local users 3, max 3") + (0.0 ":irc.foo.net 266 tester 3 3 :Current global users 3, max 3") + (0.0 ":irc.foo.net 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0.0 ":irc.foo.net 221 tester +Zi") + (0.0 ":irc.foo.net 306 tester :You have been marked as being away")) + +((join 3 "JOIN #foo") + (0 ":tester!~tester@localhost JOIN #foo") + (0 ":irc.foo.net 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 ":irc.foo.net 366 alice #foo :End of NAMES list")) + +((mode 3 "MODE #foo") + (0.0 ":irc.foo.net 324 tester #foo +Cint") + (0.0 ":irc.foo.net 329 tester #foo 1519850102") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: But, in defence, by mercy, 'tis most just.") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: Grows, lives, and dies, in single blessedness.") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :Look for me.") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: As't please your lordship: I'll leave you.") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: Then there is no true lover in the forest; else sighing every minute and groaning every hour would detect the lazy foot of Time as well as a clock.") + (0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.") + (0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :Done")) + +((hi 10 "PRIVMSG #foo :Hi")) diff --git a/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld b/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld new file mode 100644 index 0000000000..168569f548 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/irc-parser-tests.eld @@ -0,0 +1,380 @@ +;;; -*- mode: lisp-data; -*- + +;; https://github.com/DanielOaks/irc-parser-tests +((mask-match + (tests + ((mask . "*@127.0.0.1") + (matches "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1") + (fails "coolguy!ab@127.0.0.5" "cooldud3!~d@124.0.0.1")) + ((mask . "cool*@*") + (matches "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1" "cool132!ab@example.com") + (fails "koolguy!ab@127.0.0.5" "cooodud3!~d@124.0.0.1")) + ((mask . "cool!*@*") + (matches "cool!guyab@127.0.0.1" "cool!~dudebc@127.0.0.1" "cool!312ab@example.com") + (fails "coolguy!ab@127.0.0.1" "cooldud3!~bc@127.0.0.1" "koolguy!ab@127.0.0.5" "cooodud3!~d@124.0.0.1")) + ((mask . "cool!?username@*") + (matches "cool!ausername@127.0.0.1" "cool!~username@127.0.0.1") + (fails "cool!username@127.0.0.1")) + ((mask . "cool!a?*@*") + (matches "cool!ab@127.0.0.1" "cool!abc@127.0.0.1") + (fails "cool!a@127.0.0.1")) + ((mask . "cool[guy]!*@*") + (matches "cool[guy]!guy@127.0.0.1" "cool[guy]!a@example.com") + (fails "coolg!ab@127.0.0.1" "cool[!ac@127.0.1.1")))) + (msg-join + (tests + ((desc . "Simple test with verb and params.") + (atoms + (verb . "foo") + (params "bar" "baz" "asdf")) + (matches "foo bar baz asdf" "foo bar baz :asdf")) + ((desc . "Simple test with source and no params.") + (atoms + (source . "src") + (verb . "AWAY")) + (matches ":src AWAY")) + ((desc . "Simple test with source and empty trailing param.") + (atoms + (source . "src") + (verb . "AWAY") + (params "")) + (matches ":src AWAY :")) + ((desc . "Simple test with source.") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" "asdf")) + (matches ":coolguy foo bar baz asdf" ":coolguy foo bar baz :asdf")) + ((desc . "Simple test with trailing param.") + (atoms + (verb . "foo") + (params "bar" "baz" "asdf quux")) + (matches "foo bar baz :asdf quux")) + ((desc . "Simple test with empty trailing param.") + (atoms + (verb . "foo") + (params "bar" "baz" "")) + (matches "foo bar baz :")) + ((desc . "Simple test with trailing param containing colon.") + (atoms + (verb . "foo") + (params "bar" "baz" ":asdf")) + (matches "foo bar baz ::asdf")) + ((desc . "Test with source and trailing param.") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" "asdf quux")) + (matches ":coolguy foo bar baz :asdf quux")) + ((desc . "Test with trailing containing beginning+end whitespace.") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" " asdf quux ")) + (matches ":coolguy foo bar baz : asdf quux ")) + ((desc . "Test with trailing containing what looks like another trailing param.") + (atoms + (source . "coolguy") + (verb . "PRIVMSG") + (params "bar" "lol :) ")) + (matches ":coolguy PRIVMSG bar :lol :) ")) + ((desc . "Simple test with source and empty trailing.") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" "")) + (matches ":coolguy foo bar baz :")) + ((desc . "Trailing contains only spaces.") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" " ")) + (matches ":coolguy foo bar baz : ")) + ((desc . "Param containing tab (tab is not considered SPACE for message splitting).") + (atoms + (source . "coolguy") + (verb . "foo") + (params "b ar" "baz")) + (matches ":coolguy foo b ar baz" ":coolguy foo b ar :baz")) + ((desc . "Tag with no value and space-filled trailing.") + (atoms + (tags + (asd . "")) + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" " ")) + (matches "@asd :coolguy foo bar baz : ")) + ((desc . "Tags with escaped values.") + (atoms + (verb . "foo") + (tags + (a . "b\\and\nk") + (d . "gh;764"))) + (matches "@a=b\\\\and\\nk;d=gh\\:764 foo" "@d=gh\\:764;a=b\\\\and\\nk foo")) + ((desc . "Tags with escaped values and params.") + (atoms + (verb . "foo") + (tags + (a . "b\\and\nk") + (d . "gh;764")) + (params "par1" "par2")) + (matches "@a=b\\\\and\\nk;d=gh\\:764 foo par1 par2" "@a=b\\\\and\\nk;d=gh\\:764 foo par1 :par2" "@d=gh\\:764;a=b\\\\and\\nk foo par1 par2" "@d=gh\\:764;a=b\\\\and\\nk foo par1 :par2")) + ((desc . "Tag with long, strange values (including LF and newline).") + (atoms + (tags + (foo . "\\\\;\\s \n")) + (verb . "COMMAND")) + (matches "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND")))) + (msg-split + (tests + ((input . "foo bar baz asdf") + (atoms + (verb . "foo") + (params "bar" "baz" "asdf"))) + ((input . ":coolguy foo bar baz asdf") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" "asdf"))) + ((input . "foo bar baz :asdf quux") + (atoms + (verb . "foo") + (params "bar" "baz" "asdf quux"))) + ((input . "foo bar baz :") + (atoms + (verb . "foo") + (params "bar" "baz" ""))) + ((input . "foo bar baz ::asdf") + (atoms + (verb . "foo") + (params "bar" "baz" ":asdf"))) + ((input . ":coolguy foo bar baz :asdf quux") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" "asdf quux"))) + ((input . ":coolguy foo bar baz : asdf quux ") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" " asdf quux "))) + ((input . ":coolguy PRIVMSG bar :lol :) ") + (atoms + (source . "coolguy") + (verb . "PRIVMSG") + (params "bar" "lol :) "))) + ((input . ":coolguy foo bar baz :") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" ""))) + ((input . ":coolguy foo bar baz : ") + (atoms + (source . "coolguy") + (verb . "foo") + (params "bar" "baz" " "))) + ((input . "@a=b;c=32;k;rt=ql7 foo") + (atoms + (verb . "foo") + (tags + (a . "b") + (c . "32") + (k . "") + (rt . "ql7")))) + ((input . "@a=b\\\\and\\nk;c=72\\s45;d=gh\\:764 foo") + (atoms + (verb . "foo") + (tags + (a . "b\\and\nk") + (c . "72 45") + (d . "gh;764")))) + ((input . "@c;h=;a=b :quux ab cd") + (atoms + (tags + (c . "") + (h . "") + (a . "b")) + (source . "quux") + (verb . "ab") + (params "cd"))) + ((input . ":src JOIN #chan") + (atoms + (source . "src") + (verb . "JOIN") + (params "#chan"))) + ((input . ":src JOIN :#chan") + (atoms + (source . "src") + (verb . "JOIN") + (params "#chan"))) + ((input . ":src AWAY") + (atoms + (source . "src") + (verb . "AWAY"))) + ((input . ":src AWAY ") + (atoms + (source . "src") + (verb . "AWAY"))) + ((input . ":cool guy foo bar baz") + (atoms + (source . "cool guy") + (verb . "foo") + (params "bar" "baz"))) + ((input . ":coolguy!ag@net5work.admin PRIVMSG foo :bar baz") + (atoms + (source . "coolguy!ag@net5work.admin") + (verb . "PRIVMSG") + (params "foo" "bar baz"))) + ((input . ":coolguy!~ag@net05work.admin PRIVMSG foo :bar baz") + (atoms + (source . "coolguy!~ag@net05work.admin") + (verb . "PRIVMSG") + (params "foo" "bar baz"))) + ((input . "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4= :irc.example.com COMMAND param1 param2 :param3 param3") + (atoms + (tags + (tag1 . "value1") + (tag2 . "") + (vendor1/tag3 . "value2") + (vendor2/tag4 . "")) + (source . "irc.example.com") + (verb . "COMMAND") + (params "param1" "param2" "param3 param3"))) + ((input . ":irc.example.com COMMAND param1 param2 :param3 param3") + (atoms + (source . "irc.example.com") + (verb . "COMMAND") + (params "param1" "param2" "param3 param3"))) + ((input . "@tag1=value1;tag2;vendor1/tag3=value2;vendor2/tag4 COMMAND param1 param2 :param3 param3") + (atoms + (tags + (tag1 . "value1") + (tag2 . "") + (vendor1/tag3 . "value2") + (vendor2/tag4 . "")) + (verb . "COMMAND") + (params "param1" "param2" "param3 param3"))) + ((input . "COMMAND") + (atoms + (verb . "COMMAND"))) + ((input . "@foo=\\\\\\\\\\:\\\\s\\s\\r\\n COMMAND") + (atoms + (tags + (foo . "\\\\;\\s \n")) + (verb . "COMMAND"))) + ((input . ":gravel.mozilla.org 432 #momo :Erroneous Nickname: Illegal characters") + (atoms + (source . "gravel.mozilla.org") + (verb . "432") + (params "#momo" "Erroneous Nickname: Illegal characters"))) + ((input . ":gravel.mozilla.org MODE #tckk +n ") + (atoms + (source . "gravel.mozilla.org") + (verb . "MODE") + (params "#tckk" "+n"))) + ((input . ":services.esper.net MODE #foo-bar +o foobar ") + (atoms + (source . "services.esper.net") + (verb . "MODE") + (params "#foo-bar" "+o" "foobar"))) + ((input . "@tag1=value\\\\ntest COMMAND") + (atoms + (tags + (tag1 . "value\\ntest")) + (verb . "COMMAND"))) + ((input . "@tag1=value\\1 COMMAND") + (atoms + (tags + (tag1 . "value1")) + (verb . "COMMAND"))) + ((input . "@tag1=value1\\ COMMAND") + (atoms + (tags + (tag1 . "value1")) + (verb . "COMMAND"))) + ((input . "@tag1=1;tag2=3;tag3=4;tag1=5 COMMAND") + (atoms + (tags + (tag1 . "5") + (tag2 . "3") + (tag3 . "4")) + (verb . "COMMAND"))) + ((input . "@tag1=1;tag2=3;tag3=4;tag1=5;vendor/tag2=8 COMMAND") + (atoms + (tags + (tag1 . "5") + (tag2 . "3") + (tag3 . "4") + (vendor/tag2 . "8")) + (verb . "COMMAND"))) + ((input . ":SomeOp MODE #channel :+i") + (atoms + (source . "SomeOp") + (verb . "MODE") + (params "#channel" "+i"))) + ((input . ":SomeOp MODE #channel +oo SomeUser :AnotherUser") + (atoms + (source . "SomeOp") + (verb . "MODE") + (params "#channel" "+oo" "SomeUser" "AnotherUser"))))) + (userhost-split + (tests + ((source . "coolguy") + (atoms + (nick . "coolguy"))) + ((source . "coolguy!ag@127.0.0.1") + (atoms + (nick . "coolguy") + (user . "ag") + (host . "127.0.0.1"))) + ((source . "coolguy!~ag@localhost") + (atoms + (nick . "coolguy") + (user . "~ag") + (host . "localhost"))) + ((source . "coolguy@127.0.0.1") + (atoms + (nick . "coolguy") + (host . "127.0.0.1"))) + ((source . "coolguy!ag") + (atoms + (nick . "coolguy") + (user . "ag"))) + ((source . "coolguy!ag@net5work.admin") + (atoms + (nick . "coolguy") + (user . "ag") + (host . "net5work.admin"))) + ((source . "coolguy!~ag@net05work.admin") + (atoms + (nick . "coolguy") + (user . "~ag") + (host . "net05work.admin"))))) + (validate-hostname + (tests + ((host . "irc.example.com") + (valid . t)) + ((host . "i.coolguy.net") + (valid . t)) + ((host . "irc-srv.net.uk") + (valid . t)) + ((host . "iRC.CooLguY.NeT") + (valid . t)) + ((host . "gsf.ds342.co.uk") + (valid . t)) + ((host . "324.net.uk") + (valid . t)) + ((host . "xn--bcher-kva.ch") + (valid . t)) + ((host . "-lol-.net.uk") + (valid . :false)) + ((host . "-lol.net.uk") + (valid . :false)) + ((host . "_irc._sctp.lol.net.uk") + (valid . :false)) + ((host . "irc") + (valid . :false)) + ((host . "com") + (valid . :false)) + ((host . "") + (valid . :false))))) diff --git a/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld b/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld new file mode 100644 index 0000000000..751500537d --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/linger-multi-a.eld @@ -0,0 +1,3 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS " (? ?:) "a")) +((linger 100 LINGER)) \ No newline at end of file diff --git a/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld b/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld new file mode 100644 index 0000000000..c906c9e649 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/linger-multi-b.eld @@ -0,0 +1,3 @@ +;; -*- mode: lisp-data; -*- +((pass 1 "PASS " (? ?:) "b")) +((linger 1 LINGER)) diff --git a/test/lisp/erc/resources/erc-d/resources/linger.eld b/test/lisp/erc/resources/erc-d/resources/linger.eld new file mode 100644 index 0000000000..36c81a3af4 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/linger.eld @@ -0,0 +1,33 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :tester") + (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester") + (0 ":irc.example.org 002 tester :Your host is irc.example.org") + (0 ":irc.example.org 003 tester :This server was created just now") + (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + ;; Just to mix thing's up (force handler to schedule timer) + (0.1 ":irc.example.org 252 tester 0 :IRC Operators online") + (0 ":irc.example.org 253 tester 0 :unregistered connections") + (0 ":irc.example.org 254 tester 1 :channels formed") + (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.example.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":irc.example.org 221 tester +Zi") + (0 ":irc.example.org 306 tester :You have been marked as being away") + (0 ":tester!~tester@localhost JOIN #chan") + (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 ":irc.example.org 366 alice #chan :End of NAMES list")) + +((mode-chan 1.2 "MODE #chan") + (0 ":bob!~bob@example.org PRIVMSG #chan :hey")) + +((linger 1.0 LINGER)) diff --git a/test/lisp/erc/resources/erc-d/resources/no-block.eld b/test/lisp/erc/resources/erc-d/resources/no-block.eld new file mode 100644 index 0000000000..1b1f396563 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/no-block.eld @@ -0,0 +1,55 @@ +;;; -*- mode: lisp-data -*- +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :tester") + (0.0 ":irc.org 001 tester :Welcome to the Internet Relay Network tester") + (0.0 ":irc.org 002 tester :Your host is irc.org") + (0.0 ":irc.org 003 tester :This server was created just now") + (0.0 ":irc.org 004 tester irc.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0.0 ":irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0.0 ":irc.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0.0 ":irc.org 252 tester 0 :IRC Operators online") + (0.0 ":irc.org 253 tester 0 :unregistered connections") + (0.0 ":irc.org 254 tester 1 :channels formed") + (0.0 ":irc.org 255 tester :I have 3 clients and 0 servers") + (0.0 ":irc.org 265 tester 3 3 :Current local users 3, max 3") + (0.0 ":irc.org 266 tester 3 3 :Current global users 3, max 3") + (0.0 ":irc.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0.0 ":irc.org 221 tester +Zi") + (0.0 ":irc.org 306 tester :You have been marked as being away")) + +((join-foo 1.2 "JOIN #foo") + (0 ":tester!~tester@localhost JOIN #foo") + (0 ":irc.example.org 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 ":irc.example.org 366 alice #foo :End of NAMES list")) + +;; This would time out if the mode-foo's outgoing blocked (remove minus signs to see) +((~join-bar 1.5 "JOIN #bar") + (0 ":tester!~tester@localhost JOIN #bar") + (0 ":irc.example.org 353 alice = #bar :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 ":irc.example.org 366 alice #bar :End of NAMES list")) + +((mode-foo 1.2 "MODE #foo") + (0.0 ":irc.example.org 324 tester #foo +Cint") + (0.0 ":irc.example.org 329 tester #foo 1519850102") + (-0.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: But, in defence, by mercy, 'tis most just.") + (-0.2 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: Grows, lives, and dies, in single blessedness.") + (-0.3 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: For these two hours, Rosalind, I will leave thee.") + (-0.4 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: By this hand, it will not kill a fly. But come, now I will be your Rosalind in a more coming-on disposition; and ask me what you will, I will grant it.") + (-0.5 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That I must love a loathed enemy.") + (-0.6 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: As't please your lordship: I'll leave you.") + (-0.7 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: Then there is no true lover in the forest; else sighing every minute and groaning every hour would detect the lazy foot of Time as well as a clock.") + (-0.8 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: His discretion, I am sure, cannot carry his valour, for the goose carries not the fox. It is well: leave it to his discretion, and let us listen to the moon.") + (-0.9 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: As living here and you no use of him.") + (-1.0 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #foo :bob: If there be truth in sight, you are my Rosalind.") + (-1.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :alice: That is another's lawful promis'd love.") + (-1.1 ":bob!~u@svpn88yjcdj42.irc PRIVMSG #foo :I am heard.")) + +((mode-bar 1.5 "MODE #bar") + (0.0 ":irc.example.org 324 tester #bar +HMfnrt 50:5h :10:5") + (0.0 ":irc.example.org 329 tester #bar :1602642829") + (0.1 ":alice!~alice@example.com PRIVMSG #bar :hi 123")) diff --git a/test/lisp/erc/resources/erc-d/resources/no-match.eld b/test/lisp/erc/resources/erc-d/resources/no-match.eld new file mode 100644 index 0000000000..d147be1e08 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/no-match.eld @@ -0,0 +1,32 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :tester") + (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester") + (0 ":irc.example.org 002 tester :Your host is irc.example.org") + (0 ":irc.example.org 003 tester :This server was created just now") + (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0 ":irc.example.org 252 tester 0 :IRC Operators online") + (0 ":irc.example.org 253 tester 0 :unregistered connections") + (0 ":irc.example.org 254 tester 1 :channels formed") + (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.example.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":irc.example.org 221 tester +Zi") + (0 ":irc.example.org 306 tester :You have been marked as being away")) + +((join 1.2 "JOIN #chan") + (0 ":tester!~tester@localhost JOIN #chan") + (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org") + (0 ":irc.example.org 366 alice #chan :End of NAMES list")) + +((mode-chan 0.2 "MODE #chan") + (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey")) diff --git a/test/lisp/erc/resources/erc-d/resources/no-pong.eld b/test/lisp/erc/resources/erc-d/resources/no-pong.eld new file mode 100644 index 0000000000..30cd805d76 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/no-pong.eld @@ -0,0 +1,27 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((~ping 1.2 "PING " nonce) + (0.1 ":irc.example.org PONG irc.example.com " echo)) + +((user 0.2 "USER user 0 * :tester") + (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester") + (0 ":irc.example.org 002 tester :Your host is irc.example.org") + (0 ":irc.example.org 003 tester :This server was created just now") + (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0 ":irc.example.org 252 tester 0 :IRC Operators online") + (0 ":irc.example.org 253 tester 0 :unregistered connections") + (0 ":irc.example.org 254 tester 1 :channels formed") + (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.example.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":irc.example.org 221 tester +Zi") + (0 ":irc.example.org 306 tester :You have been marked as being away")) diff --git a/test/lisp/erc/resources/erc-d/resources/nonstandard.eld b/test/lisp/erc/resources/erc-d/resources/nonstandard.eld new file mode 100644 index 0000000000..c9cd608e6b --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/nonstandard.eld @@ -0,0 +1,6 @@ +;;; -*- mode: lisp-data -*- +((one 1 "ONE one")) +((two 1 "TWO two")) +((blank 1 "")) +((one-space 1 " ")) +((two-spaces 1 " ")) diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld b/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld new file mode 100644 index 0000000000..e74d20d5b3 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/proxy-barnet.eld @@ -0,0 +1,24 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) network ":changeme")) +((nick 1.2 "NICK tester")) + +((user 1.2 "USER user 0 * :tester") + (0.001 ":" fqdn " 001 tester :Welcome to the BAR Network tester") + (0.002 ":" fqdn " 002 tester :Your host is " fqdn) + (0.003 ":" fqdn " 003 tester :This server was created just now") + (0.004 ":" fqdn " 004 tester " fqdn " BERios CEIRabehiklmnoqstv Iabehkloqv") + (0.005 ":" fqdn " 005 tester MODES NETWORK=" net " NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0.006 ":" fqdn " 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0.007 ":" fqdn " 252 tester 0 :IRC Operators online") + (0.008 ":" fqdn " 253 tester 0 :unregistered connections") + (0.009 ":" fqdn " 254 tester 1 :channels formed") + (0.010 ":" fqdn " 255 tester :I have 3 clients and 0 servers") + (0.011 ":" fqdn " 265 tester 3 3 :Current local users 3, max 3") + (0.012 ":" fqdn " 266 tester 3 3 :Current global users 3, max 3") + (0.013 ":" fqdn " 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0.014 ":" fqdn " 221 tester +Zi") + (0.015 ":" fqdn " 306 tester :You have been marked as being away")) diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld b/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld new file mode 100644 index 0000000000..cc2e9d253c --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/proxy-foonet.eld @@ -0,0 +1,24 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) network ":changeme")) +((nick 1.2 "NICK tester")) + +((user 2.2 "USER user 0 * :tester") + (0.015 ":" fqdn " 001 tester :Welcome to the FOO Network tester") + (0.014 ":" fqdn " 002 tester :Your host is " fqdn) + (0.013 ":" fqdn " 003 tester :This server was created just now") + (0.012 ":" fqdn " 004 tester " fqdn " BERios CEIRabehiklmnoqstv Iabehkloqv") + (0.011 ":" fqdn " 005 tester MODES NETWORK=" net " NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0.010 ":" fqdn " 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0.009 ":" fqdn " 252 tester 0 :IRC Operators online") + (0.008 ":" fqdn " 253 tester 0 :unregistered connections") + (0.007 ":" fqdn " 254 tester 1 :channels formed") + (0.006 ":" fqdn " 255 tester :I have 3 clients and 0 servers") + (0.005 ":" fqdn " 265 tester 3 3 :Current local users 3, max 3") + (0.004 ":" fqdn " 266 tester 3 3 :Current global users 3, max 3") + (0.003 ":" fqdn " 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0.002 ":" fqdn " 221 tester +Zi") + (0.001 ":" fqdn " 306 tester :You have been marked as being away")) diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld b/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld new file mode 100644 index 0000000000..af216c80ed --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/proxy-solo.eld @@ -0,0 +1,9 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :" (group (+ alpha)) eos) + (0 ":*status!znc@znc.in NOTICE " nick " :You have no networks configured." + " Use /znc AddNetwork to add one.") + (0 ":irc.znc.in 001 " nick " :Welcome " nick "!")) diff --git a/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el new file mode 100644 index 0000000000..bb8869dff6 --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/proxy-subprocess.el @@ -0,0 +1,45 @@ +;;; proxy-subprocess.el --- Example setup file for erc-d -*- lexical-binding: t; -*- + +;; Copyright (C) 2020-2022 Free Software Foundation, Inc. +;; +;; This file is part of GNU Emacs. +;; +;; This program is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see +;; . + +;;; Commentary: +;;; Code: + +(defvar erc-d-tmpl-vars) + +(setq erc-d-tmpl-vars + + (list + (cons 'fqdn (lambda (helper) + (let ((name (funcall helper :dialog-name))) + (funcall helper :set + (if (eq name 'proxy-foonet) + "irc.foo.net" + "irc.bar.net"))))) + + (cons 'net (lambda (helper) + (let ((name (funcall helper :dialog-name))) + (funcall helper :set + (if (eq name 'proxy-foonet) + "FooNet" + "BarNet"))))) + + (cons 'network '(group (+ alpha))))) + +;;; proxy-subprocess.el ends here diff --git a/test/lisp/erc/resources/erc-d/resources/timeout.eld b/test/lisp/erc/resources/erc-d/resources/timeout.eld new file mode 100644 index 0000000000..9cfad4fa8c --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/timeout.eld @@ -0,0 +1,27 @@ +;;; -*- mode: lisp-data -*- + +((pass 10.0 "PASS " (? ?:) "changeme")) +((nick 0.2 "NICK tester")) + +((user 0.2 "USER user 0 * :tester") + (0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester") + (0 ":irc.example.org 002 tester :Your host is irc.example.org") + (0 ":irc.example.org 003 tester :This server was created just now") + (0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0 ":irc.example.org 252 tester 0 :IRC Operators online") + (0 ":irc.example.org 253 tester 0 :unregistered connections") + (0 ":irc.example.org 254 tester 1 :channels formed") + (0 ":irc.example.org 255 tester :I have 3 clients and 0 servers") + (0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3") + (0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3") + (0 ":irc.example.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0 ":irc.example.org 221 tester +Zi") + (0 ":irc.example.org 306 tester :You have been marked as being away")) + +((mode 0.2 "MODE #chan") + (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey")) diff --git a/test/lisp/erc/resources/erc-d/resources/unexpected.eld b/test/lisp/erc/resources/erc-d/resources/unexpected.eld new file mode 100644 index 0000000000..ac0a8fecfa --- /dev/null +++ b/test/lisp/erc/resources/erc-d/resources/unexpected.eld @@ -0,0 +1,28 @@ +;;; -*- mode: lisp-data -*- +((t 10.0 "PASS " (? ?:) "changeme")) +((t 0.2 "NICK tester")) + +((t 0.2 "USER user 0 * :tester") + (0.0 ":irc.example.org 001 tester :Welcome to the Internet Relay Network tester") + (0.0 ":irc.example.org 002 tester :Your host is irc.example.org") + (0.0 ":irc.example.org 003 tester :This server was created just now") + (0.0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv") + (0.0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+" + " :are supported by this server") + (0.0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)") + (0.0 ":irc.example.org 252 tester 0 :IRC Operators online") + (0.0 ":irc.example.org 253 tester 0 :unregistered connections") + (0.0 ":irc.example.org 254 tester 1 :channels formed") + (0.0 ":irc.example.org 255 tester :I have 3 clients and 0 servers") + (0.0 ":irc.example.org 265 tester 3 3 :Current local users 3, max 3") + (0.0 ":irc.example.org 266 tester 3 3 :Current global users 3, max 3") + (0.0 ":irc.example.org 422 tester :MOTD File is missing")) + +((mode-user 1.2 "MODE tester +i") + (0.0 ":irc.example.org 221 tester +Zi") + + (0.0 ":irc.example.org 306 tester :You have been marked as being away") + (0.0 ":tester!~tester@localhost JOIN #chan") + (0.0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org") + (0.0 ":irc.example.org 366 alice #chan :End of NAMES list") + (0.1 ":bob!~bob@example.org PRIVMSG #chan :hey")) commit e958a2b726fdcb5a4f58169e6f4f384f5786f86a Author: F. Jason Park Date: Wed Oct 20 03:52:18 2021 -0700 Discourage ill-defined use of buffer targets in ERC * lisp/erc/erc.el (erc-default-recipients, erc-default-target): Explain that the variable has fallen out of favor and that the function may have been used historically by third-party code for detecting channel subscription status, even though that's never been the case internally since at least the adoption of version control. Recommend newer alternatives. (erc--current-buffer-joined-p): Add possibly temporary predicate for detecting whether a buffer's target is a joined channel. The existing means are inconsistent, as discussed in bug#48598. The mere fact that they are disparate is unfriendly to new contributors. For example, in the function `erc-autojoin-channels', the `process-status' of the `erc-server-process' is used to detect whether a buffer needs joining. That's fine in that specific situation, but it won't work elsewhere. And neither will checking whether `erc-default-target' is nil, so long as `erc-delete-default-channel' and friends remain in play. (erc-add-default-channel, erc-delete-default-channel, erc-add-query, erc-delete-query): Deprecate these helpers, which rely on an unused usage variant of `erc-default-recipients'. * lisp/erc/erc-services.el: remove stray `erc-default-recipients' declaration. * lisp/erc/erc-backend.el (erc-server-NICK, erc-server-JOIN, erc-server-KICK, erc-server-PART): wrap deprecated helpers to suppress warnings. * lisp/erc/erc-join.el (erc-autojoin-channels): Use helper to detect whether a buffer needs joining. Prefer this to server liveliness, as explained above. diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index bb423eadc0..305422195b 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -1339,7 +1339,9 @@ add things to `%s' instead." erc-server-process)) (when buffer (set-buffer buffer) - (erc-add-default-channel chnl) + (with-suppressed-warnings + ((obsolete erc-add-default-channel)) + (erc-add-default-channel chnl)) (erc-server-send (format "MODE %s" chnl))) (erc-with-buffer (chnl proc) (erc-channel-begin-receiving-names)) @@ -1376,7 +1378,8 @@ add things to `%s' instead." (erc-with-buffer (buffer) (erc-remove-channel-users)) - (erc-delete-default-channel ch buffer) + (with-suppressed-warnings ((obsolete erc-delete-default-channel)) + (erc-delete-default-channel ch buffer)) (erc-update-mode-line buffer)) ((string= nick (erc-current-nick)) (erc-display-message @@ -1465,7 +1468,8 @@ add things to `%s' instead." (erc-with-buffer (buffer) (erc-remove-channel-users)) - (erc-delete-default-channel chnl buffer) + (with-suppressed-warnings ((obsolete erc-delete-default-channel)) + (erc-delete-default-channel chnl buffer)) (erc-update-mode-line buffer) (when erc-kill-buffer-on-part (kill-buffer buffer)))))) diff --git a/lisp/erc/erc-join.el b/lisp/erc/erc-join.el index b9788c192b..425de4dc56 100644 --- a/lisp/erc/erc-join.el +++ b/lisp/erc/erc-join.el @@ -176,7 +176,7 @@ This function is run from `erc-nickserv-identified-hook'." (erc-downcase current))))))))) (when (or (not buffer) (not (with-current-buffer buffer - (erc-server-process-alive)))) + (erc--current-buffer-joined-p)))) (erc-server-join-channel server chan)))))))) ;; Return nil to avoid stomping on any other hook funcs. nil) diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el index 9118d7b994..e8117f9a89 100644 --- a/lisp/erc/erc-track.el +++ b/lisp/erc/erc-track.el @@ -353,8 +353,6 @@ of `erc-track-shorten-start' characters." (> (length s) erc-track-shorten-cutoff)) erc-track-shorten-start)) -(defvar erc-default-recipients) - (defun erc-all-buffer-names () "Return all channel or query buffer names. Note that we cannot use `erc-channel-list' with a nil argument, diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 078a446a1c..9f17816b8d 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1907,6 +1907,21 @@ all channel buffers on all servers." ;; Some local variables +;; TODO eventually deprecate this variable +;; +;; In the ancient, pre-CVS days (prior to June 2001), this list may +;; have been used for supporting the changing of a buffer's target on +;; the fly (mid-session). Such usage, which allowed cons cells like +;; (QUERY . bob) to serve as the list's head, was either never fully +;; integrated or was partially clobbered prior to the introduction of +;; version control. But vestiges remain (see `erc-dcc-chat-mode'). +;; And despite appearances, no evidence has emerged that ERC ever +;; supported one-to-many target buffers. If such a thing was aspired +;; to, it was never realized. +;; +;; New library code should use the `erc--target' struct instead. +;; Third-party code can continue to use this until a getter for +;; `erc--target' (or whatever replaces it) is exported. (defvar-local erc-default-recipients nil "List of default recipients of the current buffer.") @@ -5868,6 +5883,27 @@ See also `erc-downcase'." ;; default target handling +(defun erc--current-buffer-joined-p () + "Return whether the current target buffer is joined." + ;; This may be a reliable means of detecting subscription status, + ;; but it's also roundabout and awkward. Perhaps it's worth + ;; discussing adding a joined slot to `erc--target' for this. + (cl-assert erc--target) + (and (erc--target-channel-p erc--target) + (erc-get-channel-user (erc-current-nick)) t)) + +;; This function happens to return nil in channel buffers previously +;; parted or those from which a user had been kicked. While this +;; "works" for detecting whether a channel is currently subscribed to, +;; new code should consider using +;; +;; (erc-get-channel-user (erc-current-nick)) +;; +;; instead. For retrieving a target regardless of subscription or +;; connection status, use replacements based on `erc--target'. +;; (Coming soon.) +;; +;; TODO deprecate this (defun erc-default-target () "Return the current default target (as a character string) or nil if none." (let ((tgt (car erc-default-recipients))) @@ -5878,12 +5914,14 @@ See also `erc-downcase'." (defun erc-add-default-channel (channel) "Add CHANNEL to the default channel list." + (declare (obsolete "use `erc-cmd-JOIN' or similar instead" "29.1")) (let ((chl (downcase channel))) (setq erc-default-recipients (cons chl erc-default-recipients)))) (defun erc-delete-default-channel (channel &optional buffer) "Delete CHANNEL from the default channel list." + (declare (obsolete "use `erc-cmd-PART' or similar instead" "29.1")) (with-current-buffer (if (and buffer (bufferp buffer)) buffer @@ -5895,6 +5933,7 @@ See also `erc-downcase'." "Add QUERY'd NICKNAME to the default channel list. The previous default target of QUERY type gets removed." + (declare (obsolete "use `erc-cmd-QUERY' or similar instead" "29.1")) (let ((d1 (car erc-default-recipients)) (d2 (cdr erc-default-recipients)) (qt (cons 'QUERY (downcase nickname)))) @@ -5905,7 +5944,7 @@ The previous default target of QUERY type gets removed." (defun erc-delete-query () "Delete the topmost target if it is a QUERY." - + (declare (obsolete "use one query buffer per target instead" "29.1")) (let ((d1 (car erc-default-recipients)) (d2 (cdr erc-default-recipients))) (if (and (listp d1) commit 529e46f1287ddb6fc16779a3f14016d0c305037c Author: F. Jason Park Date: Tue Oct 19 22:53:03 2021 -0700 Add eventual replacement for erc-default-recipients * lisp/erc/erc.el (erc--target, erc--target-channel, erc--target-channel-local): Add new structs to hold info on a buffer's target; stored in a local variable of the same name. (erc--target-from-string): Add standalone constructor for `erc--target'. (erc--default-target): Add temporary internal getter to ease transition to `erc--target' everywhere. (erc-open): Create above items in non-server buffers. * lisp/erc/erc-backend.el (erc-server-NICK): Recreate `erc--target' when necessary. diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 3534a937b8..bb423eadc0 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -1427,8 +1427,8 @@ add things to `%s' instead." (erc-buffer-filter (lambda () (when (equal (erc-default-target) nick) - (setq erc-default-recipients - (cons nn (cdr erc-default-recipients))) + (setq erc-default-recipients (cons nn (cdr erc-default-recipients)) + erc--target (erc--target-from-string nn)) (rename-buffer nn t) ; bug#12002 (erc-update-mode-line) (cl-pushnew (current-buffer) bufs)))) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index d4cf28a86d..078a446a1c 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1391,6 +1391,45 @@ if ARG is omitted or nil. (put ',enable 'definition-name ',name) (put ',disable 'definition-name ',name)))) +;; The rationale for favoring inheritance here (nicer dispatch) is +;; kinda flimsy since there aren't yet any actual methods. + +(cl-defstruct erc--target + (string "" :type string :documentation "Received name of target.") + (symbol nil :type symbol :documentation "Case-mapped name as symbol.")) + +;; These should probably take on a `joined' field to track joinedness, +;; which should be toggled by `erc-server-JOIN', `erc-server-PART', +;; etc. Functions like `erc--current-buffer-joined-p' (bug#48598) may +;; find it useful. + +(cl-defstruct (erc--target-channel (:include erc--target))) + +(cl-defstruct (erc--target-channel-local (:include erc--target-channel))) + +;; At some point, it may make sense to add a query type with an +;; account field, which may help support reassociation across +;; reconnects and nick changes (likely requires v3 extensions). + +(defun erc--target-from-string (string) + "Construct an `erc--target' variant from STRING." + (funcall (if (erc-channel-p string) + (if (erc--valid-local-channel-p string) + #'make-erc--target-channel-local + #'make-erc--target-channel) + #'make-erc--target) + :string string :symbol (intern (erc-downcase string)))) + +(defvar-local erc--target nil + "Info about a buffer's target, if any.") + +;; Temporary internal getter to ease transition to `erc--target' +;; everywhere. Will be replaced by updated `erc-default-target'. +(defun erc--default-target () + "Return target string or nil." + (when erc--target + (erc--target-string erc--target))) + (defun erc-once-with-server-event (event f) "Run function F the next time EVENT occurs in the `current-buffer'. @@ -2091,6 +2130,7 @@ Returns the buffer for the given server or channel." (set-marker erc-insert-marker (point)) ;; stack of default recipients (setq erc-default-recipients tgt-list) + (setq erc--target (and channel (erc--target-from-string channel))) (setq erc-server-current-nick nil) ;; Initialize erc-server-users and erc-channel-users (if connect diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 4026ebaf33..5b04bff617 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -478,6 +478,18 @@ (should-not (erc--valid-local-channel-p "#chan")) (should (erc--valid-local-channel-p "&local"))))) +(ert-deftest erc--target-from-string () + (should (equal (erc--target-from-string "#chan") + #s(erc--target-channel "#chan" \#chan))) + + (should (equal (erc--target-from-string "Bob") + #s(erc--target "Bob" bob))) + + (let ((erc--isupport-params (make-hash-table))) + (puthash 'CHANTYPES '("&#") erc--isupport-params) + (should (equal (erc--target-from-string "&Bitlbee") + #s(erc--target-channel-local "&Bitlbee" &bitlbee))))) + (ert-deftest erc-ring-previous-command-base-case () (ert-info ("Create ring when nonexistent and do nothing") (let (erc-input-ring commit 1c24af0fcb8a8326fe5cdc75672bf4099b191a00 Author: F. Jason Park Date: Mon Aug 16 05:01:16 2021 -0700 Add helper to determine local channels in ERC * lisp/erc/erc.el (erc--valid-local-channel-p): Add internal helper to determine whether an IRC channel is local according to its network's CHANTYPES ISUPPORT parameter. * test/lisp/erc/erc-tests.el (erc--valid-local-channel-p): Add test for this helper. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 4c54ef2ef9..d4cf28a86d 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -3251,6 +3251,14 @@ For a list of user commands (/join /part, ...): (concat " " password) ""))))) +(defun erc--valid-local-channel-p (channel) + "Non-nil when channel is server-local on a network that allows them." + (and-let* (((eq ?& (aref channel 0))) + (chan-types (erc--get-isupport-entry 'CHANTYPES 'single)) + ((if (>= emacs-major-version 28) + (string-search "&" chan-types) + (string-match-p "&" chan-types)))))) + (defun erc-cmd-JOIN (channel &optional key) "Join the channel given in CHANNEL, optionally with KEY. If CHANNEL is specified as \"-invite\", join the channel to which you diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index cffb61f708..4026ebaf33 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -466,6 +466,18 @@ (should (equal (erc-downcase "Tilde~") "tilde~" )) (should (equal (erc-downcase "\\O/") "|o/" ))))) +(ert-deftest erc--valid-local-channel-p () + (ert-info ("Local channels not supported") + (let ((erc--isupport-params (make-hash-table))) + (puthash 'CHANTYPES '("#") erc--isupport-params) + (should-not (erc--valid-local-channel-p "#chan")) + (should-not (erc--valid-local-channel-p "&local")))) + (ert-info ("Local channels supported") + (let ((erc--isupport-params (make-hash-table))) + (puthash 'CHANTYPES '("&#") erc--isupport-params) + (should-not (erc--valid-local-channel-p "#chan")) + (should (erc--valid-local-channel-p "&local"))))) + (ert-deftest erc-ring-previous-command-base-case () (ert-info ("Create ring when nonexistent and do nothing") (let (erc-input-ring commit 4e312c07f7a6998a818901e46341356316d248e0 Author: F. Jason Park Date: Sun Aug 15 21:57:24 2021 -0700 Make ERC respect spaces in server passwords * lisp/erc/erc.el (erc-login): Also known as connection passwords, these are sent as the sole arg to the PASS command, which is nowadays often overloaded with other semantics imposed by various entities to convey things like bouncer or services creds. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 1584948e93..4c54ef2ef9 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -6185,7 +6185,7 @@ user input." erc-session-server erc-session-user-full-name)) (if erc-session-password - (erc-server-send (format "PASS %s" erc-session-password)) + (erc-server-send (concat "PASS :" erc-session-password)) (message "Logging in without password")) (erc-server-send (format "NICK %s" (erc-current-nick))) (erc-server-send commit ecafe1cbb5297ba4df5717b7222fe2c73ef9077c Author: F. Jason Park Date: Tue Oct 5 19:03:56 2021 -0700 Recognize ASCII and strict CASEMAPPINGs in ERC * lisp/erc/erc.el (erc-downcase, erc--casemapping-rfc1459-strict, erc--casemapping-rfc1459): Add new translation tables for the latter two mappings and use them in `erc-downcase'. * test/lisp/erc/erc-tests.el: Add test for `erc-downcase'. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 80fc3dfe5f..1584948e93 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -393,18 +393,30 @@ erc-channel-user struct.") "Hash table of users on the current server. It associates nicknames with `erc-server-user' struct instances.") +(defconst erc--casemapping-rfc1459 + (make-translation-table + '((?\[ . ?\{) (?\] . ?\}) (?\\ . ?\|) (?~ . ?^)) + (mapcar (lambda (c) (cons c (+ c 32))) "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) + +(defconst erc--casemapping-rfc1459-strict + (make-translation-table + '((?\[ . ?\{) (?\] . ?\}) (?\\ . ?\|)) + (mapcar (lambda (c) (cons c (+ c 32))) "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) + (defun erc-downcase (string) - "Convert STRING to IRC standard conforming downcase." - (let ((s (downcase string)) - (c '((?\[ . ?\{) - (?\] . ?\}) - (?\\ . ?\|) - (?~ . ?^)))) - (save-match-data - (while (string-match "[]\\[~]" s) - (aset s (match-beginning 0) - (cdr (assq (aref s (match-beginning 0)) c))))) - s)) + "Return a downcased copy of STRING with properties. +Use the CASEMAPPING ISUPPORT parameter to determine the style." + (let* ((mapping (erc--get-isupport-entry 'CASEMAPPING 'single)) + (inhibit-read-only t)) + (if (equal mapping "ascii") + (downcase string) + (with-temp-buffer + (insert string) + (translate-region (point-min) (point-max) + (if (equal mapping "rfc1459-strict") + erc--casemapping-rfc1459-strict + erc--casemapping-rfc1459)) + (buffer-string))))) (defmacro erc-with-server-buffer (&rest body) "Execute BODY in the current ERC server buffer. diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 91e7d50eac..cffb61f708 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -442,6 +442,30 @@ (erc-call-hooks nil parsed)) (should (= hooked 2))))) +(ert-deftest erc-downcase () + (let ((erc--isupport-params (make-hash-table))) + + (puthash 'PREFIX '("(ov)@+") erc--isupport-params) + (puthash 'BOT '("B") erc--isupport-params) + + (ert-info ("ascii") + (puthash 'CASEMAPPING '("ascii") erc--isupport-params) + (should (equal (erc-downcase "Bob[m]`") "bob[m]`")) + (should (equal (erc-downcase "Tilde~") "tilde~" )) + (should (equal (erc-downcase "\\O/") "\\o/" ))) + + (ert-info ("rfc1459") + (puthash 'CASEMAPPING '("rfc1459") erc--isupport-params) + (should (equal (erc-downcase "Bob[m]`") "bob{m}`" )) + (should (equal (erc-downcase "Tilde~") "tilde^" )) + (should (equal (erc-downcase "\\O/") "|o/" ))) + + (ert-info ("rfc1459-strict") + (puthash 'CASEMAPPING '("rfc1459-strict") erc--isupport-params) + (should (equal (erc-downcase "Bob[m]`") "bob{m}`")) + (should (equal (erc-downcase "Tilde~") "tilde~" )) + (should (equal (erc-downcase "\\O/") "|o/" ))))) + (ert-deftest erc-ring-previous-command-base-case () (ert-info ("Create ring when nonexistent and do nothing") (let (erc-input-ring commit c356f86b51f0e0adc85a9162816cb853b2583a5f Author: F. Jason Park Date: Thu Aug 12 03:10:31 2021 -0700 Update ISUPPORT handling in ERC * lisp/erc/erc-backend (erc--isupport-params): Add new variable to hold a hashmap of parsed `erc-server-parameters' in a more useful format. But keep `erc-server-parameters' around for public use. We currently lack dedicated local variables for certain discovered IRC session properties, such as what prefix characters are supported for channels, etc. And the truth of this needs querying many times per second at various points. As such, caching here seems justified but can be easily removed if deemed otherwise because all ingredients are internal. (erc--parse-isupport-value): Add helper function that parses an ISUPPORT value and returns the component parts with backslash-x hex escapes removed. This can probably use some streamlining. (erc--with-memoization): Add compat alias for use in internal ISUPPORT getter. Should be moved to `erc-compat.el' when that library is fully reincorporated. (erc--get-isupport-entry): Add internal getter to look up ISUPPORT items. (erc-server-005): Treat `erc-server-response' "command args" field as read-only. Previously, this field was set to nil after processing, which was unhelpful to other parts of the library. Also call above mentioned helper to parse values. And add some bookkeeping to handle negation. * lisp/erc/erc-capab.el (erc-capab-identify-send-messages): Use internal ISUPPORT getter. * lisp/erc/erc.el (erc-cmd-NICK, erc-parse-prefix, erc-nickname-in-use): Use internal ISUPPORT getter. * test/lisp/erc/erc-tests.el: Add tests for the above mentioned changes in erc-backend.el. diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 5812fa4139..3534a937b8 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -185,6 +185,11 @@ SILENCE=10 - supports the SILENCE command, maximum allowed number of entries TOPICLEN=160 - maximum allowed topic length WALLCHOPS - supports sending messages to all operators in a channel") +(defvar-local erc--isupport-params nil + "Hash map of \"ISUPPORT\" params. +Keys are symbols. Values are lists of zero or more strings with hex +escapes removed.") + ;;; Server and connection state (defvar erc-server-ping-timer-alist nil @@ -1625,6 +1630,67 @@ Then display the welcome message." ?U (nth 3 (erc-response.command-args parsed)) ?C (nth 4 (erc-response.command-args parsed))))) +(defun erc--parse-isupport-value (value) + "Return list of unescaped components from an \"ISUPPORT\" VALUE." + ;; https://tools.ietf.org/html/draft-brocklesby-irc-isupport-03#section-2 + ;; + ;; > The server SHOULD send "X", not "X="; this is the normalised form. + ;; + ;; Note: for now, assume the server will only send non-empty values, + ;; possibly with printable ASCII escapes. Though in practice, the + ;; only two escapes we're likely to see are backslash and space, + ;; meaning the pattern is too liberal. + (let (case-fold-search) + (mapcar + (lambda (v) + (let ((start 0) + m + c) + (while (and (< start (length v)) + (string-match "[\\]x[0-9A-F][0-9A-F]" v start)) + (setq m (substring v (+ 2 (match-beginning 0)) (match-end 0)) + c (string-to-number m 16)) + (if (<= ?\ c ?~) + (setq v (concat (substring v 0 (match-beginning 0)) + (string c) + (substring v (match-end 0))) + start (- (match-end 0) 3)) + (setq start (match-end 0)))) + v)) + (if (if (>= emacs-major-version 28) + (string-search "," value) + (string-match-p "," value)) + (split-string value ",") + (list value))))) + +;; FIXME move to erc-compat (once we decide how to load it) +(defalias 'erc--with-memoization + (cond + ((fboundp 'with-memoization) #'with-memoization) ; 29.1 + ((fboundp 'cl--generic-with-memoization) #'cl--generic-with-memoization) + (t (lambda (_ v) v)))) + +(defun erc--get-isupport-entry (key &optional single) + "Return an item for \"ISUPPORT\" token KEY, a symbol. +When a lookup fails return nil. Otherwise return a list whose +CAR is KEY and whose CDR is zero or more strings. With SINGLE, +just return the first value, if any. The latter is potentially +ambiguous and only useful for tokens supporting a single +primitive value." + (if-let* ((table (or erc--isupport-params + (erc-with-server-buffer erc--isupport-params))) + (value (erc--with-memoization (gethash key table) + (when-let ((v (assoc (symbol-name key) + erc-server-parameters))) + (if (cdr v) + (erc--parse-isupport-value (cdr v)) + '--empty--))))) + (pcase value + ('--empty-- (unless single (list key))) + (`(,head . ,_) (if single head (cons key value)))) + (when table + (remhash key table)))) + (define-erc-response-handler (005) "Set the variable `erc-server-parameters' and display the received message. @@ -1636,21 +1702,25 @@ certain commands are accepted and more. See documentation for A server may send more than one 005 message." nil - (let ((line (mapconcat #'identity - (setf (erc-response.command-args parsed) - (cdr (erc-response.command-args parsed))) - " "))) - (while (erc-response.command-args parsed) - (let ((section (pop (erc-response.command-args parsed)))) - ;; fill erc-server-parameters - (when (string-match "^\\([A-Z]+\\)=\\(.*\\)$\\|^\\([A-Z]+\\)$" + (unless erc--isupport-params + (setq erc--isupport-params (make-hash-table))) + (let* ((args (cdr (erc-response.command-args parsed))) + (line (string-join args " "))) + (while args + (let ((section (pop args)) + key + value + negated) + (when (string-match "^\\([A-Z]+\\)=\\(.*\\)$\\|^\\(-\\)?\\([A-Z]+\\)$" section) - (add-to-list 'erc-server-parameters - `(,(or (match-string 1 section) - (match-string 3 section)) - . - ,(match-string 2 section)))))) - (erc-display-message parsed 'notice proc line))) + (setq key (or (match-string 1 section) (match-string 4 section)) + value (match-string 2 section) + negated (and (match-string 3 section) '-)) + (setf (alist-get key erc-server-parameters '- 'remove #'equal) + (or value negated)) + (remhash (intern key) erc--isupport-params)))) + (erc-display-message parsed 'notice proc line) + nil)) (define-erc-response-handler (221) "Display the current user modes." nil diff --git a/lisp/erc/erc-capab.el b/lisp/erc/erc-capab.el index 8d0f40af99..c590b45fd2 100644 --- a/lisp/erc/erc-capab.el +++ b/lisp/erc/erc-capab.el @@ -137,7 +137,7 @@ These arguments are sent to this function when called as a hook in ;; could possibly check for '("IRCD" . "dancer") in ;; `erc-server-parameters' instead of looking for a specific name ;; in `erc-server-version' - (assoc "CAPAB" erc-server-parameters)) + (erc--get-isupport-entry 'CAPAB)) (erc-log "Sending CAPAB IDENTIFY-MSG and IDENTIFY-CTCP") (erc-server-send "CAPAB IDENTIFY-MSG") (erc-server-send "CAPAB IDENTIFY-CTCP") diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index a23ff5e059..80fc3dfe5f 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -141,7 +141,6 @@ (defvar erc-server-current-nick) (defvar erc-server-lag) (defvar erc-server-last-sent-time) -(defvar erc-server-parameters) (defvar erc-server-process) (defvar erc-server-quitting) (defvar erc-server-reconnect-count) @@ -3566,8 +3565,8 @@ The rest of LINE is the message to send." (defun erc-cmd-NICK (nick) "Change current nickname to NICK." (erc-log (format "cmd: NICK: %s (erc-bad-nick: %S)" nick erc-bad-nick)) - (let ((nicklen (cdr (assoc "NICKLEN" (erc-with-server-buffer - erc-server-parameters))))) + (let ((nicklen (erc-with-server-buffer + (erc--get-isupport-entry 'NICKLEN 'single)))) (and nicklen (> (length nick) (string-to-number nicklen)) (erc-display-message nil 'notice 'active 'nick-too-long @@ -4436,9 +4435,8 @@ See also `erc-display-error-notice'." (format "Nickname %s is %s, try another." nick reason)) (setq erc-nick-change-attempt-count (+ erc-nick-change-attempt-count 1)) (let ((newnick (nth 1 erc-default-nicks)) - (nicklen (cdr (assoc "NICKLEN" - (erc-with-server-buffer - erc-server-parameters))))) + (nicklen (erc-with-server-buffer + (erc--get-isupport-entry 'NICKLEN 'single)))) (setq erc-bad-nick t) ;; try to use a different nick (if erc-default-nicks @@ -5049,8 +5047,7 @@ See also `erc-channel-begin-receiving-names'." (defun erc-parse-prefix () "Return an alist of valid prefix character types and their representations. Example: (operator) o => @, (voiced) v => +." - (let ((str (or (cdr (assoc "PREFIX" (erc-with-server-buffer - erc-server-parameters))) + (let ((str (or (erc-with-server-buffer (erc--get-isupport-entry 'PREFIX t)) ;; provide a sane default "(qaohv)~&@%+")) types chars) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 061dfc2f5e..91e7d50eac 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -349,6 +349,99 @@ (setq erc-lurker-ignore-chars "_-`") ; set of chars, not character alts (should (string= "nick" (erc-lurker-maybe-trim "nick-_`"))))) +(ert-deftest erc--parse-isupport-value () + (should (equal (erc--parse-isupport-value "a,b") '("a" "b"))) + (should (equal (erc--parse-isupport-value "a,b,c") '("a" "b" "c"))) + + (should (equal (erc--parse-isupport-value "abc") '("abc"))) + (should (equal (erc--parse-isupport-value "\\x20foo") '(" foo"))) + (should (equal (erc--parse-isupport-value "foo\\x20") '("foo "))) + (should (equal (erc--parse-isupport-value "a\\x20b\\x20c") '("a b c"))) + (should (equal (erc--parse-isupport-value "a\\x20b\\x20c\\x20") '("a b c "))) + (should (equal (erc--parse-isupport-value "\\x20a\\x20b\\x20c") '(" a b c"))) + (should (equal (erc--parse-isupport-value "a\\x20\\x20c") '("a c"))) + (should (equal (erc--parse-isupport-value "\\x20\\x20\\x20") '(" "))) + (should (equal (erc--parse-isupport-value "\\x5Co/") '("\\o/"))) + (should (equal (erc--parse-isupport-value "\\x7F,\\x19") '("\\x7F" "\\x19"))) + (should (equal (erc--parse-isupport-value "a\\x2Cb,c") '("a,b" "c")))) + +(ert-deftest erc--get-isupport-entry () + (let ((erc--isupport-params (make-hash-table)) + (erc-server-parameters '(("FOO" . "1") ("BAR") ("BAZ" . "A,B,C"))) + (items (lambda () + (cl-loop for k being the hash-keys of erc--isupport-params + using (hash-values v) collect (cons k v))))) + + (should-not (erc--get-isupport-entry 'FAKE)) + (should-not (erc--get-isupport-entry 'FAKE 'single)) + (should (zerop (hash-table-count erc--isupport-params))) + + (should (equal (erc--get-isupport-entry 'BAR) '(BAR))) + (should-not (erc--get-isupport-entry 'BAR 'single)) + (should (= 1 (hash-table-count erc--isupport-params))) + + (should (equal (erc--get-isupport-entry 'BAZ) '(BAZ "A" "B" "C"))) + (should (equal (erc--get-isupport-entry 'BAZ 'single) "A")) + (should (= 2 (hash-table-count erc--isupport-params))) + + (should (equal (erc--get-isupport-entry 'FOO 'single) "1")) + (should (equal (erc--get-isupport-entry 'FOO) '(FOO "1"))) + + (should (equal (funcall items) + '((BAR . --empty--) (BAZ "A" "B" "C") (FOO "1")))))) + +(ert-deftest erc-server-005 () + (let* ((hooked 0) + (verify #'ignore) + (hook (lambda (_ _) (funcall verify) (cl-incf hooked))) + (erc-server-005-functions (list #'erc-server-005 hook #'ignore)) + erc-server-parameters + erc--isupport-params + erc-timer-hook + calls + args + parsed) + + (cl-letf (((symbol-function 'erc-display-message) + (lambda (_ _ _ line) (push line calls)))) + + (ert-info ("Baseline") + (setq args '("tester" "BOT=B" "EXCEPTS" "PREFIX=(ov)@+" "are supp...") + parsed (make-erc-response :command-args args :command "005")) + + (setq verify + (lambda () + (should (equal erc-server-parameters + '(("PREFIX" . "(ov)@+") ("EXCEPTS") + ("BOT" . "B")))) + (should (zerop (hash-table-count erc--isupport-params))) + (should (equal "(ov)@+" (erc--get-isupport-entry 'PREFIX t))) + (should (equal '(EXCEPTS) (erc--get-isupport-entry 'EXCEPTS))) + (should (equal "B" (erc--get-isupport-entry 'BOT t))) + (should (string= (pop calls) + "BOT=B EXCEPTS PREFIX=(ov)@+ are supp...")) + (should (equal args (erc-response.command-args parsed))))) + + (erc-call-hooks nil parsed)) + + (ert-info ("Negated, updated") + (setq args '("tester" "-EXCEPTS" "-FAKE" "PREFIX=(ohv)@%+" "are su...") + parsed (make-erc-response :command-args args :command "005")) + + (setq verify + (lambda () + (should (equal erc-server-parameters + '(("PREFIX" . "(ohv)@%+") ("BOT" . "B")))) + (should (string= (pop calls) + "-EXCEPTS -FAKE PREFIX=(ohv)@%+ are su...")) + (should (equal "(ohv)@%+" (erc--get-isupport-entry 'PREFIX t))) + (should (equal "B" (erc--get-isupport-entry 'BOT t))) + (should-not (erc--get-isupport-entry 'EXCEPTS)) + (should (equal args (erc-response.command-args parsed))))) + + (erc-call-hooks nil parsed)) + (should (= hooked 2))))) + (ert-deftest erc-ring-previous-command-base-case () (ert-info ("Create ring when nonexistent and do nothing") (let (erc-input-ring commit 485b84cb7c4c61b434273fc25be0a25b84fca31d Author: F. Jason Park Date: Tue Aug 17 01:50:29 2021 -0700 Require erc-networks in erc.el * lisp/erc/erc.el: Require erc-networks.el, which ERC can't run without these days. To sidestep the circular dependency, require it last, just after erc-goodies. Remove the `declare-function' for `erc-network-name' because it's not currently needed at load time. (erc-log-irc-protocol, erc-hide-current-message-p): Remove `fboundp' guard logic from `erc-network-name' invocations but preserve meaning by interpreting `erc-network' being unset to mean module isn't loaded or authoritative network detection has failed. (erc-format-network): Likewise here. At the moment, this function always returns the empty string because the function `erc-network-name' always returns non-nil, perhaps from the fallback/failure sentinel "Unknown", perhaps from the printed form of nil. * lisp/erc/erc-networks.el (erc-network): This is called throughout erc.el but was previously cumbersome to use on account of being guarded by `fboundp'. It now relies on the fact that its namesake variable is set in target buffers as well. diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el index 553697ae84..58223f37cf 100644 --- a/lisp/erc/erc-networks.el +++ b/lisp/erc/erc-networks.el @@ -753,7 +753,7 @@ server name and search for a match in `erc-networks-alist'." (defun erc-network () "Return the value of `erc-network' for the current server." - (erc-with-server-buffer erc-network)) + (or erc-network (erc-with-server-buffer erc-network))) (defun erc-network-name () "Return the name of the current network as a string." diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 7f102dcefb..a23ff5e059 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2388,8 +2388,6 @@ but you won't see it. WARNING: Do not set this variable directly! Instead, use the function `erc-toggle-debug-irc-protocol' to toggle its value.") -(declare-function erc-network-name "erc-networks" ()) - (defun erc-log-irc-protocol (string &optional outbound) "Append STRING to the buffer *erc-protocol*. @@ -2403,9 +2401,7 @@ contain CRLF endings. Peer is identified by the most precise label available at run time, starting with the network name, followed by the announced host name, and falling back to the dialed :." (when erc-debug-irc-protocol - (let ((esid (or (and (fboundp 'erc-network) - (erc-network) - (erc-network-name)) + (let ((esid (or (and (erc-network) (erc-network-name)) erc-server-announced-name (format "%s:%s" erc-session-server erc-session-port))) (ts (when erc-debug-irc-protocol-time-format @@ -2808,7 +2804,7 @@ returns non-nil." (let* ((command (erc-response.command parsed)) (sender (car (erc-parse-user (erc-response.sender parsed)))) (channel (car (erc-response.command-args parsed))) - (network (or (and (fboundp 'erc-network-name) (erc-network-name)) + (network (or (and (erc-network) (erc-network-name)) (erc-shorten-server-name (or erc-server-announced-name erc-session-server)))) @@ -6528,10 +6524,7 @@ This should be a string with substitution variables recognized by (defun erc-format-network () "Return the name of the network we are currently on." - (let ((network (and (fboundp 'erc-network-name) (erc-network-name)))) - (if (and network (symbolp network)) - (symbol-name network) - ""))) + (erc-network-name)) (defun erc-format-target-and/or-network () "Return the network or the current target and network combined. @@ -7085,5 +7078,6 @@ Otherwise, connect to HOST:PORT as USER and /join CHANNEL." ;; IMPORTANT: This require must appear _after_ the above (provide 'erc) to ;; avoid a recursive require error when byte-compiling the entire package. (require 'erc-goodies) +(require 'erc-networks) ;;; erc.el ends here commit de53d18a4d81e8b49d1dfecaf5481382a0ad8d08 Author: F. Jason Park Date: Mon Jun 14 23:40:45 2021 -0700 Don't set erc-server-announced-name unless known * lisp/erc/erc.el (erc-open): whenever this function is called, the variable `erc-server-announced-name' may be set locally in the calling server buffer. However, if that buffer's dialed server matches that of the one being created, the announced name is copied over on faith. But there's no guarantee that the name will match the one ultimately emitted by the server during its introductory burst. Beyond potentially causing confusion in protocol logs, this behavior may complicate debugging efforts. Setting the variable to nil helps ensure a consistent environment when preparing a buffer for all newly dialed connections. This commit also simplifies the setting of `erc-server-connected', which is always nil when connecting and vice-versa. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 2ee461a663..7f102dcefb 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2047,11 +2047,7 @@ or t, which means that `auth-source' will be queried for the private key and the certificate. Returns the buffer for the given server or channel." - (let ((server-announced-name (when (and (boundp 'erc-session-server) - (string= server erc-session-server)) - erc-server-announced-name)) - (connected-p (unless connect erc-server-connected)) - (buffer (erc-get-buffer-create server port channel)) + (let ((buffer (erc-get-buffer-create server port channel)) (old-buffer (current-buffer)) old-point (continued-session (and erc-reuse-buffers erc--server-reconnecting))) @@ -2062,8 +2058,9 @@ Returns the buffer for the given server or channel." (let ((old-recon-count erc-server-reconnect-count)) (erc-mode) (setq erc-server-reconnect-count old-recon-count)) - (setq erc-server-announced-name server-announced-name) - (setq erc-server-connected connected-p) + (when (setq erc-server-connected (not connect)) + (setq erc-server-announced-name + (buffer-local-value 'erc-server-announced-name old-buffer))) ;; connection parameters (setq erc-server-process process) (setq erc-insert-marker (make-marker)) commit 873499ce065144682852643b7d0e04cd45f7eac3 Author: F. Jason Park Date: Sun Mar 13 01:34:10 2022 -0800 Allow exemption from flood penalty in erc-backend * lisp/erc/erc-backend (erc-server-send, erc-server-PING): Change name of param `forcep' in `erc-server-send' to `force' and change its type to the union of the symbol `no-penalty' and the set of all other non-nil values. In `erc-server-PING', use this exemption when calling `erc-server-send'. This fix was fast tracked and summarily incorporated into bug#48598 because users of the soju bouncer are all affected. See update #5 in the bug's email thread under the section entitled "Riders" for an explanation. diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 13303c71f5..5812fa4139 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -815,11 +815,12 @@ Use DISPLAY-FN to show the results." (erc-split-line text))) ;; From Circe, with modifications -(defun erc-server-send (string &optional forcep target) +(defun erc-server-send (string &optional force target) "Send STRING to the current server. -If FORCEP is non-nil, no flood protection is done - the string is -sent directly. This might cause the messages to arrive in a wrong -order. +When FORCE is non-nil, bypass flood protection so that STRING is +sent directly without modifying the queue. When FORCE is the +symbol `no-penalty', exempt this round from accumulating a +timeout penalty. If TARGET is specified, look up encoding information for that channel in `erc-encoding-coding-alist' or @@ -835,11 +836,11 @@ protection algorithm." (if (erc-server-process-alive) (erc-with-server-buffer (let ((str (concat string "\r\n"))) - (if forcep + (if force (progn - (setq erc-server-flood-last-message - (+ erc-server-flood-penalty - erc-server-flood-last-message)) + (unless (eq force 'no-penalty) + (cl-incf erc-server-flood-last-message + erc-server-flood-penalty)) (erc-log-irc-protocol str 'outbound) (condition-case nil (progn @@ -1469,7 +1470,7 @@ add things to `%s' instead." (let ((pinger (car (erc-response.command-args parsed)))) (erc-log (format "PING: %s" pinger)) ;; ping response to the server MUST be forced, or you can lose big - (erc-server-send (format "PONG :%s" pinger) t) + (erc-server-send (format "PONG :%s" pinger) 'no-penalty) (when erc-verbose-server-ping (erc-display-message parsed 'error proc commit c5b78a337900fd2a8d29317df7a27dd4e7006e89 Author: F. Jason Park Date: Thu Nov 18 23:39:54 2021 -0800 Customize displaying of ERC buffers on reconnect * lisp/erc/erc-backend.el (erc--server-last-reconnect-count): Add variable to record last reconnect tally. * lisp/erc/erc.el (erc-reconnect-display): Add new option to specify channel-buffer display behavior on reconnect. (erc-setup-buffer): Use option `erc-reconnect-display' if warranted. (erc-cmd-JOIN): Forget last reconnect count when issuing a manual /JOIN command. (erc-connection-established): Record reconnect count in internal var before resetting. (Bug#51753) diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 7aec02e897..13303c71f5 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -200,6 +200,9 @@ active, use the `erc-server-process-alive' function instead.") (defvar-local erc-server-reconnect-count 0 "Number of times we have failed to reconnect to the current server.") +(defvar-local erc--server-last-reconnect-count 0 + "Snapshot of reconnect count when the connection was established.") + (defvar-local erc-server-quitting nil "Non-nil if the user requests a quit.") diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index f9bff7e0c0..2ee461a663 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -131,6 +131,7 @@ :group 'erc) ;; Defined in erc-backend +(defvar erc--server-last-reconnect-count) (defvar erc--server-reconnecting) (defvar erc-channel-members-changed-hook) (defvar erc-server-367-functions) @@ -1562,6 +1563,22 @@ The available choices are: (const :tag "Use current buffer" buffer) (const :tag "Use current buffer" t))) +(defcustom erc-reconnect-display nil + "How (and whether) to display a channel buffer upon reconnecting. + +This only affects automatic reconnections and is ignored when +issuing a /reconnect command or reinvoking `erc-tls' with the +same args (assuming success, of course). See `erc-join-buffer' +for a description of possible values." + :package-version '(ERC . "5.4.1") ; FIXME increment upon publishing to ELPA + :group 'erc-buffers + :type '(choice (const :tag "Use value of `erc-join-buffer'" nil) + (const :tag "Split window and select" window) + (const :tag "Split window, don't select" window-noselect) + (const :tag "New frame" frame) + (const :tag "Bury in new buffer" bury) + (const :tag "Use current buffer" buffer))) + (defcustom erc-frame-alist nil "Alist of frame parameters for creating erc frames. A value of nil means to use `default-frame-alist'." @@ -1983,7 +2000,10 @@ removed from the list will be disabled." (defun erc-setup-buffer (buffer) "Consults `erc-join-buffer' to find out how to display `BUFFER'." - (pcase erc-join-buffer + (pcase (if (zerop (erc-with-server-buffer + erc--server-last-reconnect-count)) + erc-join-buffer + (or erc-reconnect-display erc-join-buffer)) ('window (if (active-minibuffer-window) (display-buffer buffer) @@ -3250,6 +3270,7 @@ were most recently invited. See also `invitation'." (switch-to-buffer (if (get-buffer chnl-name) chnl-name (concat chnl-name "/" server))) + (setq erc--server-last-reconnect-count 0) (erc-server-join-channel server chnl key))))) t) @@ -4741,7 +4762,8 @@ Set user modes and run `erc-after-connect' hook." (nick (car (erc-response.command-args parsed))) (buffer (process-buffer proc))) (setq erc-server-connected t) - (setq erc-server-reconnect-count 0) + (setq erc--server-last-reconnect-count erc-server-reconnect-count + erc-server-reconnect-count 0) (erc-update-mode-line) (erc-set-initial-user-mode nick buffer) (erc-server-setup-periodical-ping buffer) commit a63ed6f78a6f7169574cfb0a2d5df45890b540d6 Author: F. Jason Park Date: Tue Apr 5 17:45:00 2022 -0700 Remove duplicate ERC prompt on reconnect * lisp/erc/erc-backend.el (erc--unhide-prompt, erc--hide-prompt, erc--unhide-prompt-on-self-insert): Add functions to ensure prompt is hidden on disconnect and shown when a user types /reconnect in a disconnected server buffer. (erc-process-sentinel): Register aforementioned function with `pre-command-hook' when prompt is deleted after disconnecting. (erc-server-PRIVMSG): Ensure prompt is showing when a new message arrives from target. * lisp/erc/erc.el (erc-hide-prompt): Repurpose unused option by changing meaning slightly to mean "selectively hide prompt when disconnected." Also delete obsolete, commented-out code that at some point used this option in its prior incarnation. (erc-prompt-hidden): Add new option to specify look of prompt when hidden. (erc-unhide-query-prompt): Add option to force-reveal query prompts on reconnect. (erc-open): Augment earlier reconnect-detection semantics by incorporating `erc--server-reconnecting'. In existing buffers, remove prompt-related hooks and reveal prompt, if necessary. (erc-cmd-RECONNECT): Allow a user to reconnect when already connected (by first disconnecting). (erc-connection-established): Possibly unhide query prompts. (Bug#54826) * test/lisp/erc/erc-tests.el (erc-tests--test-prep, erc-tests--set-fake-server-process): Factor out some common buffer-prep boilerplate involving user input and the server process. Shared with bug#54536. diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 5651d8271c..7aec02e897 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -705,6 +705,39 @@ Conditionally try to reconnect and take appropriate action." ;; unexpected disconnect (erc-process-sentinel-2 event buffer)))) +(defun erc--unhide-prompt () + (remove-hook 'pre-command-hook #'erc--unhide-prompt-on-self-insert t) + (when (and (marker-position erc-insert-marker) + (marker-position erc-input-marker)) + (with-silent-modifications + (remove-text-properties erc-insert-marker erc-input-marker + '(display nil))))) + +(defun erc--unhide-prompt-on-self-insert () + (when (and (eq this-command #'self-insert-command) + (or (eobp) (= (point) erc-input-marker))) + (erc--unhide-prompt))) + +(defun erc--hide-prompt (proc) + (erc-with-all-buffers-of-server + proc nil ; sorta wish this was indent 2 + (when (and erc-hide-prompt + (or (eq erc-hide-prompt t) + ;; FIXME use `erc--target' after bug#48598 + (memq (if (erc-default-target) + (if (erc-channel-p (car erc-default-recipients)) + 'channel + 'query) + 'server) + erc-hide-prompt)) + (marker-position erc-insert-marker) + (marker-position erc-input-marker) + (get-text-property erc-insert-marker 'erc-prompt)) + (with-silent-modifications + (add-text-properties erc-insert-marker (1- erc-input-marker) + `(display ,erc-prompt-hidden))) + (add-hook 'pre-command-hook #'erc--unhide-prompt-on-self-insert 0 t)))) + (defun erc-process-sentinel (cproc event) "Sentinel function for ERC process." (let ((buf (process-buffer cproc))) @@ -727,11 +760,8 @@ Conditionally try to reconnect and take appropriate action." (dolist (buf (erc-buffer-filter (lambda () (boundp 'erc-channel-users)) cproc)) (with-current-buffer buf (setq erc-channel-users (make-hash-table :test 'equal)))) - ;; Remove the prompt - (goto-char (or (marker-position erc-input-marker) (point-max))) - (forward-line 0) - (erc-remove-text-properties-region (point) (point-max)) - (delete-region (point) (point-max)) + ;; Hide the prompt + (erc--hide-prompt cproc) ;; Decide what to do with the buffer ;; Restart if disconnected (erc-process-sentinel-1 event buf)))))) @@ -1479,6 +1509,7 @@ add things to `%s' instead." (setq buffer (erc-get-buffer (if privp nick tgt) proc)) (when buffer (with-current-buffer buffer + (when privp (erc--unhide-prompt)) ;; update the chat partner info. Add to the list if private ;; message. We will accumulate private identities indefinitely ;; at this point. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 1a6911a511..f9bff7e0c0 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -244,13 +244,34 @@ prompt you for it.") :group 'erc :type 'boolean) -(defcustom erc-hide-prompt nil - "If non-nil, do not display the prompt for commands. - -\(A command is any input starting with a `/'). +(defcustom erc-prompt-hidden ">" + "Text to show in lieu of the prompt when hidden." + :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release + :group 'erc-display + :type 'string) -See also the variables `erc-prompt' and `erc-command-indicator'." +(defcustom erc-hide-prompt t + "If non-nil, hide input prompt upon disconnecting. +To unhide, type something in the input area. Once revealed, a +prompt remains unhidden until the next disconnection. Channel +prompts are unhidden upon rejoining. See +`erc-unhide-query-prompt' for behavior concerning query prompts." + :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release :group 'erc-display + :type '(choice (const :tag "Always hide prompt" t) + (set (const server) + (const query) + (const channel)))) + +(defcustom erc-unhide-query-prompt nil + "When non-nil, always reveal query prompts upon reconnecting. +Otherwise, prompts in a connection's query buffers remain hidden +until the user types in the input area or a new message arrives +from the target." + :package-version '(ERC . "5.4.1") ; FIXME increment on next ELPA release + :group 'erc-display + ;; Extensions may one day offer a way to discover whether a target + ;; is online. When that happens, this can be expanded accordingly. :type 'boolean) ;; tunable GUI stuff @@ -2013,7 +2034,7 @@ Returns the buffer for the given server or channel." (buffer (erc-get-buffer-create server port channel)) (old-buffer (current-buffer)) old-point - continued-session) + (continued-session (and erc-reuse-buffers erc--server-reconnecting))) (when connect (run-hook-with-args 'erc-before-connect server port nick)) (erc-update-modules) (set-buffer buffer) @@ -2031,7 +2052,7 @@ Returns the buffer for the given server or channel." ;; (the buffer may have existed) (goto-char (point-max)) (forward-line 0) - (when (get-text-property (point) 'erc-prompt) + (when (or continued-session (get-text-property (point) 'erc-prompt)) (setq continued-session t) (set-marker erc-input-marker (or (next-single-property-change (point) 'erc-prompt) @@ -2089,7 +2110,8 @@ Returns the buffer for the given server or channel." (goto-char (point-max)) (insert "\n")) (if continued-session - (goto-char old-point) + (progn (goto-char old-point) + (erc--unhide-prompt)) (set-marker erc-insert-marker (point)) (erc-display-prompt) (goto-char (point-max))) @@ -3753,12 +3775,15 @@ the message given by REASON." (setq erc--server-reconnecting t) (setq erc-server-reconnect-count 0) (setq process (get-buffer-process (erc-server-buffer))) - (if process - (delete-process process) - (erc-server-reconnect)) + (when process + (delete-process process)) + (erc-server-reconnect) (with-suppressed-warnings ((obsolete erc-server-reconnecting)) - (setq erc-server-reconnecting nil)) - (setq erc--server-reconnecting nil))) + (if erc-reuse-buffers + (progn (cl-assert (not erc--server-reconnecting)) + (cl-assert (not erc-server-reconnecting))) + (setq erc--server-reconnecting nil + erc-server-reconnecting nil))))) t) (put 'erc-cmd-RECONNECT 'process-not-needed t) @@ -4720,7 +4745,14 @@ Set user modes and run `erc-after-connect' hook." (erc-update-mode-line) (erc-set-initial-user-mode nick buffer) (erc-server-setup-periodical-ping buffer) - (run-hook-with-args 'erc-after-connect server nick))))) + (run-hook-with-args 'erc-after-connect server nick)))) + + (when erc-unhide-query-prompt + (erc-with-all-buffers-of-server proc + nil ; FIXME use `erc--target' after bug#48598 + (when (and (erc-default-target) + (not (erc-channel-p (car erc-default-recipients)))) + (erc--unhide-prompt))))) (defun erc-set-initial-user-mode (nick buffer) "If `erc-user-mode' is non-nil for NICK, set the user modes. @@ -5674,27 +5706,6 @@ Return non-nil only if we actually send anything." (erc-process-input-line (concat string "\n") t nil)) t)))))) -;; (defun erc-display-command (line) -;; (when erc-insert-this -;; (let ((insert-position (point))) -;; (unless erc-hide-prompt -;; (erc-display-prompt nil nil (erc-command-indicator) -;; (and (erc-command-indicator) -;; 'erc-command-indicator-face))) -;; (let ((beg (point))) -;; (insert line) -;; (erc-put-text-property beg (point) -;; 'font-lock-face 'erc-command-indicator-face) -;; (insert "\n")) -;; (when (processp erc-server-process) -;; (set-marker (process-mark erc-server-process) (point))) -;; (set-marker erc-insert-marker (point)) -;; (save-excursion -;; (save-restriction -;; (narrow-to-region insert-position (point)) -;; (run-hooks 'erc-send-modify-hook) -;; (run-hooks 'erc-send-post-hook)))))) - (defun erc-display-msg (line) "Display LINE as a message of the user to the current target at point." (when erc-insert-this diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 3c76cb97ca..061dfc2f5e 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -135,6 +135,150 @@ (should (get-buffer "#spam")) (kill-buffer "#spam"))) +(defun erc-tests--send-prep () + ;; Caller should probably shadow `erc-insert-modify-hook' or + ;; populate user tables for erc-button. + (erc-mode) + (insert "\n\n") + (setq erc-input-marker (make-marker) + erc-insert-marker (make-marker)) + (set-marker erc-insert-marker (point-max)) + (erc-display-prompt) + (should (= (point) erc-input-marker))) + +(defun erc-tests--set-fake-server-process (&rest args) + (setq erc-server-process + (apply #'start-process (car args) (current-buffer) args)) + (set-process-query-on-exit-flag erc-server-process nil)) + +(ert-deftest erc-hide-prompt () + (let (erc-kill-channel-hook erc-kill-server-hook erc-kill-buffer-hook) + + (with-current-buffer (get-buffer-create "ServNet") + (erc-tests--send-prep) + (goto-char erc-insert-marker) + (should (looking-at-p (regexp-quote erc-prompt))) + (erc-tests--set-fake-server-process "sleep" "1") + (set-process-sentinel erc-server-process #'ignore) + (setq erc-network 'ServNet) + (set-process-query-on-exit-flag erc-server-process nil)) + + (with-current-buffer (get-buffer-create "#chan") + (erc-tests--send-prep) + (goto-char erc-insert-marker) + (should (looking-at-p (regexp-quote erc-prompt))) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "ServNet")) + erc-default-recipients '("#chan"))) + + (with-current-buffer (get-buffer-create "bob") + (erc-tests--send-prep) + (goto-char erc-insert-marker) + (should (looking-at-p (regexp-quote erc-prompt))) + (setq erc-server-process (buffer-local-value 'erc-server-process + (get-buffer "ServNet")) + erc-default-recipients '("bob"))) + + (ert-info ("Value: t (default)") + (should (eq erc-hide-prompt t)) + (with-current-buffer "ServNet" + (should (= (point) erc-insert-marker)) + (erc--hide-prompt erc-server-process) + (should (string= ">" (get-text-property (point) 'display)))) + + (with-current-buffer "#chan" + (goto-char erc-insert-marker) + (should (string= ">" (get-text-property (point) 'display))) + (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook)) + (goto-char erc-input-marker) + (ert-simulate-command '(self-insert-command 1 ?/)) + (goto-char erc-insert-marker) + (should-not (get-text-property (point) 'display)) + (should-not (memq #'erc--unhide-prompt-on-self-insert + pre-command-hook))) + + (with-current-buffer "bob" + (goto-char erc-insert-marker) + (should (string= ">" (get-text-property (point) 'display))) + (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook)) + (goto-char erc-input-marker) + (ert-simulate-command '(self-insert-command 1 ?/)) + (goto-char erc-insert-marker) + (should-not (get-text-property (point) 'display)) + (should-not (memq #'erc--unhide-prompt-on-self-insert + pre-command-hook))) + + (with-current-buffer "ServNet" + (should (get-text-property erc-insert-marker 'display)) + (should (memq #'erc--unhide-prompt-on-self-insert pre-command-hook)) + (erc--unhide-prompt) + (should-not (memq #'erc--unhide-prompt-on-self-insert + pre-command-hook)) + (should-not (get-text-property erc-insert-marker 'display)))) + + (ert-info ("Value: server") + (setq erc-hide-prompt '(server)) + (with-current-buffer "ServNet" + (erc--hide-prompt erc-server-process) + (should (string= ">" (get-text-property erc-insert-marker 'display)))) + + (with-current-buffer "#chan" + (should-not (get-text-property erc-insert-marker 'display))) + + (with-current-buffer "bob" + (should-not (get-text-property erc-insert-marker 'display))) + + (with-current-buffer "ServNet" + (erc--unhide-prompt) + (should-not (get-text-property erc-insert-marker 'display)))) + + (ert-info ("Value: channel") + (setq erc-hide-prompt '(channel)) + (with-current-buffer "ServNet" + (erc--hide-prompt erc-server-process) + (should-not (get-text-property erc-insert-marker 'display))) + + (with-current-buffer "bob" + (should-not (get-text-property erc-insert-marker 'display))) + + (with-current-buffer "#chan" + (should (string= ">" (get-text-property erc-insert-marker 'display))) + (erc--unhide-prompt) + (should-not (get-text-property erc-insert-marker 'display)))) + + (ert-info ("Value: query") + (setq erc-hide-prompt '(query)) + (with-current-buffer "ServNet" + (erc--hide-prompt erc-server-process) + (should-not (get-text-property erc-insert-marker 'display))) + + (with-current-buffer "bob" + (should (string= ">" (get-text-property erc-insert-marker 'display))) + (erc--unhide-prompt) + (should-not (get-text-property erc-insert-marker 'display))) + + (with-current-buffer "#chan" + (should-not (get-text-property erc-insert-marker 'display)))) + + (ert-info ("Value: nil") + (setq erc-hide-prompt nil) + (with-current-buffer "ServNet" + (erc--hide-prompt erc-server-process) + (should-not (get-text-property erc-insert-marker 'display))) + + (with-current-buffer "bob" + (should-not (get-text-property erc-insert-marker 'display))) + + (with-current-buffer "#chan" + (should-not (get-text-property erc-insert-marker 'display)) + (erc--unhide-prompt) ; won't blow up when prompt already showing + (should-not (get-text-property erc-insert-marker 'display)))) + + (when noninteractive + (kill-buffer "#chan") + (kill-buffer "bob") + (kill-buffer "ServNet")))) + (ert-deftest erc--switch-to-buffer () (defvar erc-modified-channels-alist) ; lisp/erc/erc-track.el @@ -218,14 +362,10 @@ (ert-deftest erc-ring-previous-command () (with-current-buffer (get-buffer-create "*#fake*") (erc-mode) - (insert "\n\n") + (erc-tests--send-prep) + (setq-local erc-last-input-time 0) (should-not (local-variable-if-set-p 'erc-send-completed-hook)) (set (make-local-variable 'erc-send-completed-hook) nil) ; skip t (globals) - (setq erc-input-marker (make-marker) - erc-insert-marker (make-marker)) - (set-marker erc-insert-marker (point-max)) - (erc-display-prompt) - (should (= (point) erc-input-marker)) ;; Just in case erc-ring-mode is already on (setq-local erc-pre-send-functions nil) (add-hook 'erc-pre-send-functions #'erc-add-to-input-ring) commit 4ae0707704eecb38836c1b0159bc3c456889a7a9 Author: F. Jason Park Date: Sun Apr 3 14:24:24 2022 -0700 Accept user keyword arg in ERC entry-point commands * lisp/erc/erc-backend.el (erc-server-reconnect): Reuse the username argument from the previous session's USER command when reconnecting. Also pass the existing client certificate, fixing an issue related to bug#47788. (erc-session-user-full-name): Move variable here from erc.el. (erc-session-username): Add new local variable to store entry point parameter. * lisp/erc/erc.el (erc-session-user-full-name): Move variable to erc-backend. (erc-open, erc-determine-parameters, erc, erc-tls): Accept new optional user parameter. (erc-query): Preserve current `erc-session-username' when calling `erc-open'. (erc-login): Use `erc-session-username' instead of deriving it. (erc-compute-user): Add new function to determine user name from explicit argument or user options. (Bug#54824) diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 5250df31f6..5651d8271c 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -123,6 +123,14 @@ "Nickname on the current server. Use `erc-current-nick' to access this.") +(defvar-local erc-session-user-full-name nil + "Real name used for the current session. +Sent as the last argument to the USER command.") + +(defvar-local erc-session-username nil + "Username used for the current session. +Sent as the first argument of the USER command.") + ;;; Server attributes (defvar-local erc-server-process nil @@ -584,7 +592,9 @@ Make sure you are in an ERC buffer when running this." (let ((erc-server-connect-function (or erc-session-connector #'erc-open-network-stream))) (erc-open erc-session-server erc-session-port erc-server-current-nick - erc-session-user-full-name t erc-session-password))))) + erc-session-user-full-name t erc-session-password + nil nil nil erc-session-client-certificate + erc-session-username))))) (defun erc-server-delayed-reconnect (buffer) (if (buffer-live-p buffer) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 9240791b1e..1a6911a511 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -149,6 +149,8 @@ (defvar erc-session-connector) (defvar erc-session-port) (defvar erc-session-server) +(defvar erc-session-user-full-name) +(defvar erc-session-username) ;; tunable connection and authentication parameters @@ -1820,9 +1822,6 @@ all channel buffers on all servers." (defvar-local erc-default-recipients nil "List of default recipients of the current buffer.") -(defvar-local erc-session-user-full-name nil - "Full name of the user on the current server.") - (defvar-local erc-channel-user-limit nil "Limit of users per channel.") @@ -1989,8 +1988,8 @@ removed from the list will be disabled." (defun erc-open (&optional server port nick full-name connect passwd tgt-list channel process - client-certificate) - "Connect to SERVER on PORT as NICK with FULL-NAME. + client-certificate user) + "Connect to SERVER on PORT as NICK with USER and FULL-NAME. If CONNECT is non-nil, connect to the server. Otherwise assume already connected and just create a separate buffer for the new @@ -2095,7 +2094,7 @@ Returns the buffer for the given server or channel." (erc-display-prompt) (goto-char (point-max))) - (erc-determine-parameters server port nick full-name) + (erc-determine-parameters server port nick full-name user) ;; Saving log file on exit (run-hook-with-args 'erc-connect-pre-hook buffer) @@ -2216,6 +2215,7 @@ parameters SERVER and NICK." (cl-defun erc (&key (server (erc-compute-server)) (port (erc-compute-port)) (nick (erc-compute-nick)) + (user (erc-compute-user)) password (full-name (erc-compute-full-name))) "ERC is a powerful, modular, and extensible IRC client. @@ -2227,6 +2227,7 @@ Non-interactively, it takes the keyword arguments (server (erc-compute-server)) (port (erc-compute-port)) (nick (erc-compute-nick)) + (user (erc-compute-user)) password (full-name (erc-compute-full-name)) @@ -2238,7 +2239,7 @@ then the server and full-name will be set to those values, whereas `erc-compute-port' and `erc-compute-nick' will be invoked for the values of the other parameters." (interactive (erc-select-read-args)) - (erc-open server port nick full-name t password)) + (erc-open server port nick full-name t password nil nil nil nil user)) ;;;###autoload (defalias 'erc-select #'erc) @@ -2248,6 +2249,7 @@ for the values of the other parameters." (cl-defun erc-tls (&key (server (erc-compute-server)) (port (erc-compute-port)) (nick (erc-compute-nick)) + (user (erc-compute-user)) password (full-name (erc-compute-full-name)) client-certificate) @@ -2291,7 +2293,7 @@ Example usage: (erc-select-read-args))) (let ((erc-server-connect-function 'erc-open-tls-stream)) (erc-open server port nick full-name t password - nil nil nil client-certificate))) + nil nil nil client-certificate user))) (defun erc-open-tls-stream (name buffer host port &rest parameters) "Open an TLS stream to an IRC server. @@ -4311,7 +4313,8 @@ To change how this query window is displayed, use `let' to bind nil (list target) target - erc-server-process))) + erc-server-process + erc-session-username))) (unless buf (error "Couldn't open query window")) (erc-update-mode-line) @@ -6153,14 +6156,14 @@ user input." (erc-server-send (format "USER %s %s %s :%s" ;; hacked - S.B. - (if erc-anonymous-login erc-email-userid (user-login-name)) + erc-session-username "0" "*" erc-session-user-full-name)) (erc-update-mode-line)) ;; connection properties' heuristics -(defun erc-determine-parameters (&optional server port nick name) +(defun erc-determine-parameters (&optional server port nick name user) "Determine the connection and authentication parameters. Sets the buffer local variables: @@ -6168,11 +6171,13 @@ Sets the buffer local variables: - `erc-session-server' - `erc-session-port' - `erc-session-user-full-name' +- `erc-session-username' - `erc-server-current-nick'" (setq erc-session-connector erc-server-connect-function erc-session-server (erc-compute-server server) erc-session-port (or port erc-default-port) - erc-session-user-full-name (erc-compute-full-name name)) + erc-session-user-full-name (erc-compute-full-name name) + erc-session-username (erc-compute-user user)) (erc-set-current-nick (erc-compute-nick nick))) (defun erc-compute-server (&optional server) @@ -6190,6 +6195,10 @@ non-nil value is found. (getenv "IRCSERVER") erc-default-server)) +(defun erc-compute-user (&optional user) + "Return a suitable value for the session user name." + (or user (if erc-anonymous-login erc-email-userid (user-login-name)))) + (defun erc-compute-nick (&optional nick) "Return user's IRC nick. @@ -7018,6 +7027,7 @@ This function should be on `erc-kill-channel-hook'." ;; Teach url.el how to open irc:// URLs with ERC. ;; To activate, customize `url-irc-function' to `url-irc-erc'. +;; FIXME change user to nick, and use API to find server buffer ;;;###autoload (defun erc-handle-irc-url (host port channel user password) "Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD. commit 54414ec846c9b3615138355fb4f1c4890038e231 Author: F. Jason Park Date: Tue Apr 5 01:30:07 2022 -0700 Initialize erc-server-filter-data in erc-backend * lisp/erc/erc-backend.el (erc-server-connect): Set `erc-server-filter-data' to nil upon (re)connecting. * lisp/erc/erc.el (erc-open): For the sake of clarity, don't initialize `erc-server-filter-data' here because non-connect invocations merely set up a target buffer and have no business touching this variable. diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 2f0b523d1b..5250df31f6 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -534,6 +534,7 @@ TLS (see `erc-session-client-certificate' for more details)." (error "Connection attempt failed")) ;; Misc server variables (with-current-buffer buffer + (setq erc-server-filter-data nil) (setq erc-server-process process) (setq erc-server-quitting nil) (setq erc-server-reconnecting nil diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index c4689a4b78..9240791b1e 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -138,7 +138,6 @@ (defvar erc-server-connect-function) (defvar erc-server-connected) (defvar erc-server-current-nick) -(defvar erc-server-filter-data) (defvar erc-server-lag) (defvar erc-server-last-sent-time) (defvar erc-server-parameters) @@ -2055,8 +2054,6 @@ Returns the buffer for the given server or channel." (setq erc-server-users nil) (setq erc-channel-users (make-hash-table :test 'equal)))) - ;; clear last incomplete line read - (setq erc-server-filter-data nil) (setq erc-channel-topic "") ;; limit on the number of users on the channel (mode +l) (setq erc-channel-user-limit nil) commit 0f52e7ac68457ca8beb22cd382b1637fed35fd73 Author: F. Jason Park Date: Mon Apr 4 22:38:22 2022 -0700 Rework mutual dependency between erc and erc-backend * lisp/erc/erc.el: Declare needed variables exported by erc-backend.el as special near the top of the file, and only require `erc-backend' after providing `erc' as a feature at the very end. * lisp/erc/erc-backend.el: Don't preemptively provide `erc-backend'. * test/lisp/erc/erc-tests.el (erc--meta--backend-dependencies): Add utility test to scrape for unused vars that may accumulate over time. (Bug#54825) diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index 1252a5b4fa..2f0b523d1b 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -102,7 +102,6 @@ ;; There's a fairly strong mutual dependency between erc.el and erc-backend.el. ;; Luckily, erc.el does not need erc-backend.el for macroexpansion whereas the ;; reverse is true: -(provide 'erc-backend) (require 'erc) ;;;; Variables and options diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index ff482d4933..c4689a4b78 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -130,7 +130,26 @@ "Running scripts at startup and with /LOAD." :group 'erc) -(require 'erc-backend) +;; Defined in erc-backend +(defvar erc--server-reconnecting) +(defvar erc-channel-members-changed-hook) +(defvar erc-server-367-functions) +(defvar erc-server-announced-name) +(defvar erc-server-connect-function) +(defvar erc-server-connected) +(defvar erc-server-current-nick) +(defvar erc-server-filter-data) +(defvar erc-server-lag) +(defvar erc-server-last-sent-time) +(defvar erc-server-parameters) +(defvar erc-server-process) +(defvar erc-server-quitting) +(defvar erc-server-reconnect-count) +(defvar erc-server-reconnecting) +(defvar erc-session-client-certificate) +(defvar erc-session-connector) +(defvar erc-session-port) +(defvar erc-session-server) ;; tunable connection and authentication parameters @@ -7023,6 +7042,8 @@ Otherwise, connect to HOST:PORT as USER and /join CHANNEL." (provide 'erc) +(require 'erc-backend) + ;; Deprecated. We might eventually stop requiring the goodies automatically. ;; IMPORTANT: This require must appear _after_ the above (provide 'erc) to ;; avoid a recursive require error when byte-compiling the entire package. diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 520f10dd4e..3c76cb97ca 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -48,6 +48,27 @@ (cl-letf (((symbol-function 'read-string) (lambda (&rest _) "1d"))) (should (equal (erc--read-time-period "foo: ") 86400)))) +(ert-deftest erc--meta--backend-dependencies () + (with-temp-buffer + (insert-file-contents-literally + (concat (file-name-sans-extension (symbol-file 'erc)) ".el")) + (let ((beg (search-forward ";; Defined in erc-backend")) + (end (search-forward "\n\n")) + vars) + (save-excursion + (save-restriction + (narrow-to-region beg end) + (goto-char (point-min)) + (with-syntax-table lisp-data-mode-syntax-table + (condition-case _ + (while (push (cadr (read (current-buffer))) vars)) + (end-of-file))))) + (should (= (point) end)) + (dolist (var vars) + (setq var (concat "\\_<" (symbol-name var) "\\_>")) + (ert-info (var) + (should (save-excursion (search-forward-regexp var nil t)))))))) + (ert-deftest erc-with-all-buffers-of-server () (let (proc-exnet proc-onet commit 6908309827c573288a029b74aa999adc057958be Author: Stefan Kangas Date: Thu Jun 30 23:15:54 2022 +0200 Doc fixes: don't refer to some obsolete items * admin/notes/multi-tty: * lisp/chistory.el (command-history): * lisp/emacs-lisp/nadvice.el: * lisp/vc/diff-mode.el: Doc fix; don't refer to obsolete variables and functions. diff --git a/admin/notes/multi-tty b/admin/notes/multi-tty index 9b3f1606a1..84bc1b77d4 100644 --- a/admin/notes/multi-tty +++ b/admin/notes/multi-tty @@ -474,7 +474,7 @@ THINGS TO DO definition. Exceptions found so far: x-select-text and - x-selection-value (old name: x-cut-buffer-or-selection-value). + x-selection-value. ** Have a look at fatal_error_hook. diff --git a/lisp/chistory.el b/lisp/chistory.el index dd0f499743..33b2142211 100644 --- a/lisp/chistory.el +++ b/lisp/chistory.el @@ -165,11 +165,11 @@ The buffer for that command is the previous current buffer." "Examine commands from variable `command-history' in a buffer. The number of commands listed is controlled by `list-command-history-max'. The command history is filtered by `list-command-history-filter' if non-nil. -Use \\\\[command-history-repeat] to repeat the command on the current line. +Use \\\\[command-history-repeat] to repeat the command on the current line. Otherwise much like Emacs-Lisp Mode except that there is no self-insertion and digits provide prefix arguments. Tab does not indent. -\\{command-history-map} +\\{command-history-mode-map} This command always recompiles the Command History listing and runs the normal hook `command-history-hook'." diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el index 212499d10b..eae4a0f0ec 100644 --- a/lisp/emacs-lisp/nadvice.el +++ b/lisp/emacs-lisp/nadvice.el @@ -277,7 +277,7 @@ different, but `function-equal' will hopefully ignore those differences.") (defmacro add-function (where place function &optional props) ;; TODO: ;; - maybe let `where' specify some kind of predicate and use it - ;; to implement things like mode-local or eieio-defmethod. + ;; to implement things like mode-local or cl-defmethod. ;; Of course, that only makes sense if the predicates of all advices can ;; be combined and made more efficient. ;; :before is like a normal add-hook on a normal hook. diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index cd1e1b9d08..f366261ae0 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -2053,7 +2053,7 @@ For use in `add-log-current-defun-function'." (re-search-forward "^[^ ]" nil t)) (pcase-let ((`(,buf ,_line-offset ,pos ,src ,dst ,switched) (ignore-errors ;Signals errors in place of prompting. - ;; Use `noprompt' since this is used in which-func-mode + ;; Use `noprompt' since this is used in which-function-mode ;; and such. (diff-find-source-location nil nil 'noprompt)))) (when buf commit dc3cb749f3d7aa5c807049f62141168e0ee580f2 Author: Stefan Kangas Date: Thu Jun 30 22:37:21 2022 +0200 Remove obsolete cust-print from elisp index * doc/lispref/edebug.texi (Printing in Edebug): Remove obsolete library "cust-print" from index. diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi index ed57802bed..8f38e57624 100644 --- a/doc/lispref/edebug.texi +++ b/doc/lispref/edebug.texi @@ -832,7 +832,6 @@ you continue execution, and recreated next time it is needed. @cindex printing (Edebug) @cindex printing circular structures -@pindex cust-print If an expression in your program produces a value containing circular list structure, you may get an error when Edebug attempts to print it. commit a3311dbce0008a23d8d6626ae6245d96ce3a20b2 Author: Lars Ingebrigtsen Date: Thu Jun 30 20:23:42 2022 +0200 Regenerate ldefs-boot.el diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index 2d1e327597..c38ede4d67 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -5930,8 +5930,7 @@ The value of PACKAGE needs to be unique and it needs to match the PACKAGE value appearing in the :package-version keyword. Since the user might see the value in an error message, a good choice is the official name of the package, such as MH-E or Gnus.") -(define-obsolete-function-alias 'customize-changed-options #'customize-changed "\ -28.1") +(define-obsolete-function-alias 'customize-changed-options #'customize-changed "28.1") (autoload 'customize-changed "cus-edit" "\ Customize all settings whose meanings have changed in Emacs itself. This includes new user options and faces, and new customization @@ -6140,8 +6139,7 @@ The mode's hook is called both when the mode is enabled and when it is disabled. (fn &optional ARG)" t nil) -(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "\ -24.1") +(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "24.1") (put 'global-cwarn-mode 'globalized-minor-mode t) (defvar global-cwarn-mode nil "\ Non-nil if Global Cwarn mode is enabled. @@ -11879,10 +11877,8 @@ Variables of interest include: List of functions to be called if the other file has been created. (fn &optional IN-OTHER-WINDOW IGNORE-INCLUDE EVENT)" t nil) -(define-obsolete-function-alias 'ff-mouse-find-other-file #'ff-find-other-file "\ -28.1") -(define-obsolete-function-alias 'ff-mouse-find-other-file-other-window #'ff-find-other-file-other-window "\ -28.1") +(define-obsolete-function-alias 'ff-mouse-find-other-file #'ff-find-other-file "28.1") +(define-obsolete-function-alias 'ff-mouse-find-other-file-other-window #'ff-find-other-file-other-window "28.1") (autoload 'ff-find-other-file-other-window "find-file" "\ Visit the file you point at in another window. @@ -14908,8 +14904,7 @@ See `help-make-xrefs'. Add xrefs for symbols in `pp's output between FROM and TO. (fn FROM TO)" nil nil) -(define-obsolete-function-alias 'help-xref-interned 'describe-symbol "\ -25.1") +(define-obsolete-function-alias 'help-xref-interned 'describe-symbol "25.1") (autoload 'help-bookmark-jump "help-mode" "\ Jump to `help-mode' bookmark BOOKMARK. Handler function for record returned by `help-bookmark-make-record'. @@ -16553,8 +16548,7 @@ See `inferior-emacs-lisp-mode' for details. ;;; Generated autoloads from iimage.el -(define-obsolete-function-alias 'turn-on-iimage-mode 'iimage-mode "\ -24.1") +(define-obsolete-function-alias 'turn-on-iimage-mode 'iimage-mode "24.1") (autoload 'iimage-mode "iimage" "\ Toggle Iimage mode on or off. @@ -16907,10 +16901,8 @@ easy-to-use form." t nil) Default bookmark handler for Image-Dired buffers. (fn BOOKMARK)" nil nil) -(define-obsolete-function-alias 'tumme #'image-dired "\ -24.4") -(define-obsolete-function-alias 'image-dired-setup-dired-keybindings #'image-dired-minor-mode "\ -26.1") +(define-obsolete-function-alias 'tumme #'image-dired "24.4") +(define-obsolete-function-alias 'image-dired-setup-dired-keybindings #'image-dired-minor-mode "26.1") (register-definition-prefixes "image-dired" '("image-dired-")) @@ -18149,8 +18141,7 @@ and the return value is the length of the conversion. (global-set-key [f4] #'kmacro-end-or-call-macro) (global-set-key "\C-x\C-k" #'kmacro-keymap) (autoload 'kmacro-keymap "kmacro" "Keymap for keyboard macro commands." t 'keymap) -(define-obsolete-function-alias 'kmacro-exec-ring-item #'funcall "\ -29.1" "Execute item ITEM from the macro ring. +(define-obsolete-function-alias 'kmacro-exec-ring-item #'funcall "29.1" "Execute item ITEM from the macro ring. ARG is the number of times to execute the item.") (autoload 'kmacro-start-macro "kmacro" "\ Record subsequent keyboard input, defining a keyboard macro. @@ -20140,8 +20131,7 @@ Major mode for the mixal asm language. ;;; Generated autoloads from gnus/mm-encode.el -(define-obsolete-function-alias 'mm-default-file-encoding #'mm-default-file-type "\ -28.1") +(define-obsolete-function-alias 'mm-default-file-encoding #'mm-default-file-type "28.1") (autoload 'mm-default-file-type "mm-encode" "\ Return a default content type for FILE. @@ -20999,8 +20989,7 @@ remaining elements should be a keyword list accepted by gnutls-boot (as returned by `gnutls-boot-parameters'). (fn NAME BUFFER HOST SERVICE &rest PARAMETERS)" nil nil) -(define-obsolete-function-alias 'open-protocol-stream #'open-network-stream "\ -26.1") +(define-obsolete-function-alias 'open-protocol-stream #'open-network-stream "26.1") (register-definition-prefixes "network-stream" '("network-stream-")) @@ -21739,8 +21728,7 @@ startup file, `~/.emacs-octave'. ;;; Generated autoloads from progmodes/opascal.el -(define-obsolete-function-alias 'delphi-mode #'opascal-mode "\ -24.4") +(define-obsolete-function-alias 'delphi-mode #'opascal-mode "24.4") (autoload 'opascal-mode "opascal" "\ Major mode for editing OPascal code. \\ @@ -29345,8 +29333,7 @@ Query the user for a process and return the process object. ;;; Generated autoloads from progmodes/subword.el -(define-obsolete-function-alias 'capitalized-words-mode 'subword-mode "\ -25.1") +(define-obsolete-function-alias 'capitalized-words-mode 'subword-mode "25.1") (autoload 'subword-mode "subword" "\ Toggle subword movement and editing (Subword mode). @@ -31128,8 +31115,7 @@ The mode's hook is called both when the mode is enabled and when it is disabled. (fn &optional ARG)" t nil) -(define-obsolete-function-alias 'display-time-world #'world-clock "\ -28.1") +(define-obsolete-function-alias 'display-time-world #'world-clock "28.1") (autoload 'world-clock "time" "\ Display a world clock buffer with times in various time zones. The variable `world-clock-list' specifies which time zones to use. @@ -31170,8 +31156,7 @@ Return the time elapsed since TIME. TIME should be either a time value or a date-time string. (fn TIME)" nil nil) -(define-obsolete-function-alias 'subtract-time 'time-subtract "\ -26.1") +(define-obsolete-function-alias 'subtract-time 'time-subtract "26.1") (autoload 'date-to-day "time-date" "\ Return the absolute date of DATE, a date-time string. The absolute date is the number of days elapsed since the imaginary @@ -34639,8 +34624,7 @@ Please submit bug reports and other feedback to the author, Neil W. Van Dyke (put 'which-func-format 'risky-local-variable t) (put 'which-func-current 'risky-local-variable t) -(define-obsolete-function-alias 'which-func-mode 'which-function-mode "\ -24.1") +(define-obsolete-function-alias 'which-func-mode 'which-function-mode "24.1") (defvar which-function-mode nil "\ Non-nil if Which-Function mode is enabled. See the `which-function-mode' command @@ -35549,8 +35533,7 @@ If LIMIT is non-nil, then do not consider characters beyond LIMIT. (push (purecopy '(xref 1 4 1)) package--builtin-versions) (autoload 'xref-find-backend "xref" nil nil nil) -(define-obsolete-function-alias 'xref-pop-marker-stack #'xref-go-back "\ -29.1") +(define-obsolete-function-alias 'xref-pop-marker-stack #'xref-go-back "29.1") (autoload 'xref-go-back "xref" "\ Go back to the previous position in xref history. To undo, use \\[xref-go-forward]." t nil) commit 2736e61274381ee432f0cd0d15d308b0095436ab Author: Lars Ingebrigtsen Date: Thu Jun 30 20:23:32 2022 +0200 Fix define-obsolete-function-alias formatting in loaddefs-gen.el * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--print-form): Fix formatting of define-obsolete-function-alias statements (bug#56292). diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index 7545ba1e5e..2c92a8e7fe 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -633,7 +633,8 @@ If GENERATE-FULL, don't update, but regenerate all the loaddefs files." "Print DEF in the way make-docfile.c expects it." (if (or (not (consp def)) (not (symbolp (car def))) - (eq (car def) 'make-obsolete) + (memq (car def) '( make-obsolete + define-obsolete-function-alias)) (not (stringp (nth 3 def)))) (prin1 def (current-buffer) t) ;; The salient point here is that we have to have the doc string commit 15b2138719b34083967001c3903e7560d5e0947c Author: Stefan Monnier Date: Thu Jun 30 13:20:33 2022 -0400 (syntax-wholeline-max): New var Try and reduce the pain caused by font-lock and syntax-propertize's wholeline-based operation in buffers made up of a few very long lines (bug#45898). * lisp/emacs-lisp/syntax.el (syntax-wholeline-max): New var. (syntax--lbp): New function. (syntax-propertize-wholelines): Use it. * lisp/jit-lock.el (jit-lock--antiblink-post-command): Use `syntax--lbp`. * lisp/font-lock.el (font-lock-extend-region-wholelines): Rewrite, using `syntax-propertize-wholelines`. diff --git a/etc/NEWS b/etc/NEWS index e757435ff9..d3dd896526 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -317,6 +317,17 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 +** New config variable 'syntax-wholeline-max' to reduce the cost of long lines. +This variable is used by some operations (mostly syntax-propertization +and font-locking) to treat lines longer than this variable as if they +were made up of various smaller lines. This can help reduce the +pathological slowdowns seen in buffers made of a single long line, but +can also cause misbehavior in the presence of such long lines (tho +most of that misbehavior should usually be limited to mis-highlighting). +You can recover the previous behavior with: + + (setq syntax-wholeline-max most-positive-fixnum) + --- ** New bindings in 'find-function-setup-keys' for 'find-library'. When 'find-function-setup-keys' is enabled, 'C-x L' is now bound to diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el index 36b0c56e95..e1be301583 100644 --- a/lisp/emacs-lisp/syntax.el +++ b/lisp/emacs-lisp/syntax.el @@ -124,15 +124,49 @@ When the last position scanned holds the first character of a otherwise nil. That construct can be a two character comment delimiter or an Escaped or Char-quoted character.")) -(defun syntax-propertize-wholelines (start end) - "Extend the region delimited by START and END to whole lines. +(defvar syntax-wholeline-max 10000 + "Maximum line length for syntax operations. +If lines are longer than that, syntax operations will treat them as chunks +of this size. Misfontification may then occur. +This is a tradeoff between correctly applying the syntax rules, +and avoiding major slowdown on pathologically long lines.") + +(defun syntax--lbp (&optional arg) + "Like `line-beginning-position' but obeying `syntax-wholeline-max'." + (let ((pos (point)) + (res (line-beginning-position arg))) + (cond + ((< (abs (- pos res)) syntax-wholeline-max) res) + ;; For lines that are too long, round to the nearest multiple of + ;; `syntax-wholeline-max'. We use rounding rather than just + ;; (min res (+ pos syntax-wholeline-max)) so that repeated calls + ;; to `syntax-propertize-wholelines' don't keep growing the bounds, + ;; i.e. it really behaves like additional line-breaks. + ((< res pos) + (let ((max syntax-wholeline-max)) + (max (point-min) (* max (truncate pos max))))) + (t + (let ((max syntax-wholeline-max)) + (min (point-max) (* max (ceiling pos max)))))))) + +(defun syntax-propertize-wholelines (beg end) + "Extend the region delimited by BEG and END to whole lines. This function is useful for `syntax-propertize-extend-region-functions'; see Info node `(elisp) Syntax Properties'." - (goto-char start) - (cons (line-beginning-position) - (progn (goto-char end) - (if (bolp) (point) (line-beginning-position 2))))) + ;; This let-binding was taken from + ;; `font-lock-extend-region-wholelines' where it was used to avoid + ;; inf-looping (Bug#21615) but for some reason it was not applied + ;; here in syntax.el and was used only for the "beg" side. + (let ((inhibit-field-text-motion t)) + (let ((new-beg (progn (goto-char beg) + (if (bolp) beg + (syntax--lbp)))) + (new-end (progn (goto-char end) + (if (bolp) end + (syntax--lbp 2))))) + (unless (and (eql beg new-beg) (eql end new-end)) + (cons new-beg new-end))))) (defun syntax-propertize-multiline (beg end) "Let `syntax-propertize' pay attention to the syntax-multiline property." diff --git a/lisp/font-lock.el b/lisp/font-lock.el index df0a26f4d0..7eeaf2f547 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -1260,18 +1260,11 @@ Put first the functions more likely to cause a change and cheaper to compute.") (defun font-lock-extend-region-wholelines () "Move fontification boundaries to beginning of lines." - (let ((changed nil)) - (goto-char font-lock-beg) - (unless (bolp) - (setq changed t font-lock-beg - (let ((inhibit-field-text-motion t)) - (line-beginning-position)))) - (goto-char font-lock-end) - (unless (bolp) - (unless (eq font-lock-end - (setq font-lock-end (line-beginning-position 2))) - (setq changed t))) - changed)) + (let ((new (syntax-propertize-wholelines font-lock-beg font-lock-end))) + (when new + (setq font-lock-beg (car new)) + (setq font-lock-end (cdr new)) + t))) (defun font-lock-default-fontify-region (beg end loudly) "Fontify the text between BEG and END. @@ -1565,7 +1558,7 @@ see `font-lock-syntactic-keywords'." (or (nth 3 highlight) (error "No match %d in highlight %S" match highlight)) (when (and (consp value) (not (numberp (car value)))) - (setq value (eval value))) + (setq value (eval value t))) (when (stringp value) (setq value (string-to-syntax value))) ;; Flush the syntax-cache. I believe this is not necessary for ;; font-lock's use of syntax-ppss, but I'm not 100% sure and it can @@ -1589,7 +1582,7 @@ KEYWORDS should be of the form MATCH-ANCHORED, see `font-lock-keywords', LIMIT can be modified by the value of its PRE-MATCH-FORM." (let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights ;; Evaluate PRE-MATCH-FORM. - (pre-match-value (eval (nth 1 keywords)))) + (pre-match-value (eval (nth 1 keywords) t))) ;; Set LIMIT to value of PRE-MATCH-FORM or the end of line. (if (and (numberp pre-match-value) (> pre-match-value (point))) (setq limit pre-match-value) @@ -1605,7 +1598,7 @@ LIMIT can be modified by the value of its PRE-MATCH-FORM." (font-lock-apply-syntactic-highlight (car highlights)) (setq highlights (cdr highlights))))) ;; Evaluate POST-MATCH-FORM. - (eval (nth 2 keywords)))) + (eval (nth 2 keywords) t))) (defun font-lock-fontify-syntactic-keywords-region (start end) "Fontify according to `font-lock-syntactic-keywords' between START and END. @@ -1718,7 +1711,7 @@ HIGHLIGHT should be of the form MATCH-HIGHLIGHT, see `font-lock-keywords'." ;; No match but we might not signal an error. (or (nth 3 highlight) (error "No match %d in highlight %S" match highlight)) - (let ((val (eval (nth 1 highlight)))) + (let ((val (eval (nth 1 highlight) t))) (when (eq (car-safe val) 'face) (add-text-properties start end (cddr val)) (setq val (cadr val))) @@ -1753,7 +1746,7 @@ LIMIT can be modified by the value of its PRE-MATCH-FORM." (let ((matcher (nth 0 keywords)) (lowdarks (nthcdr 3 keywords)) highlights (lead-start (match-beginning 0)) ;; Evaluate PRE-MATCH-FORM. - (pre-match-value (eval (nth 1 keywords)))) + (pre-match-value (eval (nth 1 keywords) t))) ;; Set LIMIT to value of PRE-MATCH-FORM or the end of line. (if (not (and (numberp pre-match-value) (> pre-match-value (point)))) (setq limit (line-end-position)) @@ -1778,7 +1771,7 @@ LIMIT can be modified by the value of its PRE-MATCH-FORM." (font-lock-apply-highlight (car highlights)) (setq highlights (cdr highlights))))) ;; Evaluate POST-MATCH-FORM. - (eval (nth 2 keywords)))) + (eval (nth 2 keywords) t))) (defun font-lock-fontify-keywords-region (start end &optional loudly) "Fontify according to `font-lock-keywords' between START and END. @@ -1884,7 +1877,7 @@ If SYNTACTIC-KEYWORDS is non-nil, it means these keywords are used for (cond ((or (functionp keyword) (nlistp keyword)) ; MATCHER (list keyword '(0 font-lock-keyword-face))) ((eq (car keyword) 'eval) ; (eval . FORM) - (font-lock-compile-keyword (eval (cdr keyword)))) + (font-lock-compile-keyword (eval (cdr keyword) t))) ((eq (car-safe (cdr keyword)) 'quote) ; (MATCHER . 'FORM) ;; If FORM is a FACENAME then quote it. Otherwise ignore the quote. (if (symbolp (nth 2 keyword)) @@ -1905,7 +1898,7 @@ If SYNTACTIC-KEYWORDS is non-nil, it means these keywords are used for keywords (font-lock-eval-keywords (if (fboundp keywords) (funcall keywords) - (eval keywords))))) + (eval keywords t))))) (defun font-lock-value-in-major-mode (values) "If VALUES is a list, use `major-mode' as a key and return the `assq' value. diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el index 17969d5762..a3ada44370 100644 --- a/lisp/jit-lock.el +++ b/lisp/jit-lock.el @@ -242,20 +242,20 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'." (when (and jit-lock-stealth-time (null jit-lock-stealth-timer)) (setq jit-lock-stealth-timer (run-with-idle-timer jit-lock-stealth-time t - 'jit-lock-stealth-fontify))) + #'jit-lock-stealth-fontify))) ;; Create, but do not activate, the idle timer for repeated ;; stealth fontification. (when (and jit-lock-stealth-time (null jit-lock-stealth-repeat-timer)) (setq jit-lock-stealth-repeat-timer (timer-create)) (timer-set-function jit-lock-stealth-repeat-timer - 'jit-lock-stealth-fontify '(t))) + #'jit-lock-stealth-fontify '(t))) ;; Init deferred fontification timer. (when (and jit-lock-defer-time (null jit-lock-defer-timer)) (setq jit-lock-defer-timer (run-with-idle-timer jit-lock-defer-time t - 'jit-lock-deferred-fontify))) + #'jit-lock-deferred-fontify))) ;; Initialize contextual fontification if requested. (when (eq jit-lock-contextually t) @@ -265,13 +265,13 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'." (lambda () (unless jit-lock--antiblink-grace-timer (jit-lock-context-fontify)))))) - (add-hook 'post-command-hook 'jit-lock--antiblink-post-command nil t) + (add-hook 'post-command-hook #'jit-lock--antiblink-post-command nil t) (setq jit-lock-context-unfontify-pos (or jit-lock-context-unfontify-pos (point-max)))) ;; Setup our hooks. - (add-hook 'after-change-functions 'jit-lock-after-change nil t) - (add-hook 'fontification-functions 'jit-lock-function nil t)) + (add-hook 'after-change-functions #'jit-lock-after-change nil t) + (add-hook 'fontification-functions #'jit-lock-function nil t)) ;; Turn Just-in-time Lock mode off. (t @@ -294,8 +294,9 @@ If you need to debug code run from jit-lock, see `jit-lock-debug-mode'." (setq jit-lock-defer-timer nil))) ;; Remove hooks. - (remove-hook 'after-change-functions 'jit-lock-after-change t) - (remove-hook 'fontification-functions 'jit-lock-function)))) + (remove-hook 'post-command-hook #'jit-lock--antiblink-post-command t) + (remove-hook 'after-change-functions #'jit-lock-after-change t) + (remove-hook 'fontification-functions #'jit-lock-function)))) (define-minor-mode jit-lock-debug-mode "Minor mode to help debug code run from jit-lock. @@ -707,8 +708,8 @@ will take place when text is fontified stealthily." (min jit-lock-context-unfontify-pos jit-lock-start)))))) (defun jit-lock--antiblink-post-command () - (let* ((new-l-b-p (copy-marker (line-beginning-position))) - (l-b-p-2 (line-beginning-position 2)) + (let* ((new-l-b-p (copy-marker (syntax--lbp))) + (l-b-p-2 (syntax--lbp 2)) (same-line (and jit-lock-antiblink-grace (not (= new-l-b-p l-b-p-2)) commit 77e99dcacb57cae558f833334a8367fbc9b4fd8a Author: Mattias Engdegård Date: Thu Jun 30 15:19:15 2022 +0200 ; * lisp/emacs-lisp/rx.el: Don't set indentation prop for `repeat`. diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index 182e48d785..18eb168a70 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el @@ -1113,11 +1113,10 @@ can expand to any number of values." ;; Declare Lisp indentation rules for constructs that take 1 or 2 ;; parameters before a body of RX forms. ;; (`>=' and `=' are omitted because they are more likely to be used -;; as Lisp functions than RX constructs.) +;; as Lisp functions than RX constructs; `repeat' is a `defcustom' type.) (put 'group-n 'lisp-indent-function 1) (put 'submatch-n 'lisp-indent-function 1) (put '** 'lisp-indent-function 2) -(put 'repeat 'lisp-indent-function 2) (defun rx--translate (item) commit 9ffbbddf8e1c3878d8fe3324bfaa7687a456e505 Author: Stefan Kangas Date: Thu Jun 30 14:31:04 2022 +0200 * admin/make-tarball.txt: Minor clarifications. diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt index 98001e24e7..6990f27bfa 100644 --- a/admin/make-tarball.txt +++ b/admin/make-tarball.txt @@ -15,8 +15,8 @@ Steps to take before starting on the first pretest in any release sequence: 2. Consider increasing the value of the variable 'customize-changed-options-previous-release' in cus-edit.el to refer to a newer version of Emacs. (This is now done when cutting - the release branch, see admin/release-branch.txt.) - Commit cus-edit.el if changed. + the release branch, see admin/release-branch.txt, but it can't + hurt to double check its value.) Commit cus-edit.el if changed. 3. Remove any old pretests from https://alpha.gnu.org/gnu/emacs/pretest. You can use 'gnupload --delete' (see below for more gnupload details). @@ -24,8 +24,8 @@ Steps to take before starting on the first pretest in any release sequence: General steps (for each step, check for possible errors): -1. git pull # fetch from the repository - git status # check for locally modified files +1. git pull # fetch from the repository + git status # check for locally modified files Ensure that you have a clean, unmodified state. If you switched in-place from another branch to the release branch, @@ -49,6 +49,9 @@ General steps (for each step, check for possible errors): files will end up in the tarball. Otherwise, the *.eln files might not build correctly on the user's system. + ./autogen.sh + ./configure --with-native-compilation && make + For a release (as opposed to pretest), delete any left-over "---" and "+++" markers from etc/NEWS, as well as the "Temporary note" section at the beginning of that file, and commit etc/NEWS if it @@ -284,7 +287,8 @@ General steps (for each step, check for possible errors): https://alpha.gnu.org/gnu/emacs/pretest/ for a pretest, or https://ftp.gnu.org/gnu/emacs/ for a release. - Download them and check the signatures. Check they build. + Download them and check the signatures and SHA1/SHA256 checksums. + Check they build. 11. Send an announcement to: emacs-devel, and bcc: info-gnu-emacs@gnu.org. For a pretest, also bcc: platform-testers@gnu.org. @@ -302,12 +306,20 @@ General steps (for each step, check for possible errors): To create the included SHA1 and SHA256 checksums, run: - sha1sum emacs-NEW.tar.xz - sha256sum emacs-NEW.tar.xz + sha1sum emacs-NEW.tar.xz + sha256sum emacs-NEW.tar.xz + + You can optionally sign the announcement email, probably using the + same PGP key that you used for signing the tarball. + (Use e.g. `M-x mml-secure-message-sign' in `message-mode' to sign + an email.) 12. After a release, update the Emacs pages as described below. -13. Bump the Emacs version on the release branch. +13. After a release, bump the Emacs version on the release branch. + There is no need to bump the version after a pretest; the version + is bumped before the next pretest or release instead. + If the released version was XX.Y, use 'set-version' from admin/admin.el to bump the version on the release branch to XX.Y.50. Commit the changes. @@ -315,8 +327,8 @@ General steps (for each step, check for possible errors): UPDATING THE EMACS WEB PAGES AFTER A RELEASE As soon as possible after a release, the Emacs web pages at -https://www.gnu.org/software/emacs/ should be updated. (See -admin/notes/www for general information.) +https://www.gnu.org/software/emacs/ should be updated. +(See admin/notes/www for general information.) The pages to update are: @@ -332,7 +344,7 @@ looks like this:
          -

          Emacs 27.1 is out, download it here!

          +

          Emacs 28.1 is out, download it here!

          commit a68508c10b0ab60e23d13164bd6c83e38ce36f93 Author: Mattias Engdegård Date: Thu Jun 30 14:55:45 2022 +0200 Don't say that macro-expansion error is a warning * lisp/emacs-lisp/gv.el: * lisp/emacs-lisp/macroexp.el (internal-macroexpand-for-load): Since eager macro-expansion errors are no longer warnings, don't say so. diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el index 7cfa1f2dad..54ddc7ac75 100644 --- a/lisp/emacs-lisp/gv.el +++ b/lisp/emacs-lisp/gv.el @@ -602,7 +602,7 @@ This is like the `*' operator of the C language. REF must have been previously obtained with `gv-ref'." (funcall (car ref))) ;; Don't use `declare' because it seems to introduce circularity problems: -;; Warning: Eager macro-expansion skipped due to cycle: +;; Eager macro-expansion skipped due to cycle: ;; … => (load "gv.el") => (macroexpand-all (defsubst gv-deref …)) => (macroexpand (defun …)) => (load "gv.el") (gv-define-setter gv-deref (v ref) `(funcall (cdr ,ref) ,v)) diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index 0fb4cf680a..4db50bbaa9 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -796,7 +796,7 @@ test of free variables in the following ways: (if (eq (car-safe (car bt)) 'macroexpand-all) (setq bt (cdr bt))) (if macroexp--debug-eager (debug 'eager-macroexp-cycle) - (error "Warning: Eager macro-expansion skipped due to cycle:\n %s" + (error "Eager macro-expansion skipped due to cycle:\n %s" (mapconcat #'prin1-to-string (nreverse bt) " => "))) (push 'skip macroexp--pending-eager-loads) form)) commit f819882edcb3724823a962d16863be3f5a76d634 Author: Stefan Kangas Date: Thu Jun 30 14:58:11 2022 +0200 * lisp/eshell/em-term.el (eshell-visual-commands): Add vim. diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el index 9000e8c878..a4fa699aa9 100644 --- a/lisp/eshell/em-term.el +++ b/lisp/eshell/em-term.el @@ -56,7 +56,7 @@ which commands are considered visual in nature." :type 'hook) (defcustom eshell-visual-commands - '("vi" ; what is going on?? + '("vi" "vim" ; what is going on?? "screen" "tmux" "top" "htop" ; ok, a valid program... "less" "more" ; M-x view-file "lynx" "links" "ncftp" ; eww, ange-ftp @@ -67,7 +67,7 @@ Commands listed here are run in a term buffer. See also `eshell-visual-subcommands' and `eshell-visual-options'." :type '(repeat string) - :version "27.1") + :version "29.1") (defcustom eshell-visual-subcommands nil commit a6a92b8e4df551af113fcba5304457168b487cfa Author: Lars Ingebrigtsen Date: Thu Jun 30 14:45:55 2022 +0200 Also add elisp-eval/byte-compile-buffer to lisp-interaction-mode * lisp/progmodes/elisp-mode.el (lisp-interaction-mode-map): Also add elisp-eval-buffer and elisp-byte-compile-buffer to this map. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 056e87abba..fb114ec990 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1230,6 +1230,8 @@ All commands in `lisp-mode-shared-map' are inherited by this map." :parent lisp-mode-shared-map "C-M-x" #'eval-defun "C-M-q" #'indent-pp-sexp + "C-c C-e" #'elisp-eval-buffer + "C-c C-b" #'elisp-byte-compile-buffer "M-TAB" #'completion-at-point "C-j" #'eval-print-last-sexp) commit 00dbc5937d3015e23285251f0417d4b508080ecc Author: Mattias Engdegård Date: Thu Jun 30 14:31:47 2022 +0200 Don't change indentation rules for `>=` and `=` * lisp/emacs-lisp/rx.el: `>=` and `=` are much more likely functions than RX constructs and the indentation machinery currently has no way to tell them apart. Suggested by Michael Herdeegen. diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index 07ede57d39..182e48d785 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el @@ -1112,10 +1112,12 @@ can expand to any number of values." ;; Declare Lisp indentation rules for constructs that take 1 or 2 ;; parameters before a body of RX forms. -(dolist (sym '( group-n submatch-n = >=)) - (put sym 'lisp-indent-function 1)) -(dolist (sym '( ** repeat)) - (put sym 'lisp-indent-function 2)) +;; (`>=' and `=' are omitted because they are more likely to be used +;; as Lisp functions than RX constructs.) +(put 'group-n 'lisp-indent-function 1) +(put 'submatch-n 'lisp-indent-function 1) +(put '** 'lisp-indent-function 2) +(put 'repeat 'lisp-indent-function 2) (defun rx--translate (item) commit 6f773186e3e9bd963afbf780e6f72e5f0bbbb40f Author: Lars Ingebrigtsen Date: Thu Jun 30 14:29:49 2022 +0200 Fix typo in previous elisp-byte-compile-buffer change * lisp/progmodes/elisp-mode.el (elisp-byte-compile-buffer): Make warnings point to the correct place. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 65a76daf25..056e87abba 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -2214,7 +2214,7 @@ interactively, this is the prefix argument." (when load (load (funcall byte-compile-dest-file-function buffer-file-name)))) -(defun elisp-byte-compile-buffero (&optional load) +(defun elisp-byte-compile-buffer (&optional load) "Byte compile the current buffer, but don't write a file. If LOAD is non-nil, load byte-compiled data. When called interactively, this is the prefix argument." commit 3015af515eceb9d5901b6de4cc83f1874b53efcb Author: Lars Ingebrigtsen Date: Thu Jun 30 14:29:04 2022 +0200 Fix up warning links in elisp-byte-compile-buffer * lisp/progmodes/elisp-mode.el (elisp-byte-compile-buffer): Make warnings point to the correct place. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 7acf7316a9..65a76daf25 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -2214,12 +2214,13 @@ interactively, this is the prefix argument." (when load (load (funcall byte-compile-dest-file-function buffer-file-name)))) -(defun elisp-byte-compile-buffer (&optional load) +(defun elisp-byte-compile-buffero (&optional load) "Byte compile the current buffer, but don't write a file. If LOAD is non-nil, load byte-compiled data. When called interactively, this is the prefix argument." (interactive "P") - (let (file elc) + (let ((bfn buffer-file-name) + file elc) (unwind-protect (progn (setq file (make-temp-file "compile" nil ".el") @@ -2228,8 +2229,25 @@ interactively, this is the prefix argument." (let ((set-message-function (lambda (message) (when (string-match-p "\\`Wrote " message) - 'ignore)))) + 'ignore))) + (byte-compile-log-warning-function + (lambda (string position &optional fill level) + (if bfn + ;; Massage the warnings to that they point to + ;; this file, not the one in /tmp. + (let ((byte-compile-current-file bfn) + (byte-compile-root-dir (file-name-directory bfn))) + (byte-compile--log-warning-for-byte-compile + string position fill level)) + ;; We don't have a file name, so the warnings + ;; will point to a file that doesn't exist. This + ;; should be fixed in some way. + (byte-compile--log-warning-for-byte-compile + string position fill level))))) (byte-compile-file file)) + (when (and bfn (get-buffer "*Compile-Log*")) + (with-current-buffer "*Compile-Log*" + (setq default-directory (file-name-directory bfn)))) (if load (load elc) (message "Byte-compiled the current buffer"))) commit b77d8617e7841ea8526f09de9d3246ff7e62aa87 Author: Stefan Kangas Date: Thu Jun 30 14:11:28 2022 +0200 ; * lisp/emacs-lisp/testcover.el: Remove duplicate provide. diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el index 302f89cc1c..cd2e388ce4 100644 --- a/lisp/emacs-lisp/testcover.el +++ b/lisp/emacs-lisp/testcover.el @@ -65,7 +65,6 @@ (eval-when-compile (require 'cl-lib)) (require 'edebug) -(provide 'testcover) ;;;========================================================================== commit bf65073767de47e3dfdb9b3086d4abd3ecb0089b Author: Stefan Kangas Date: Thu Jun 30 13:47:59 2022 +0200 New hook save-place-after-find-file-hook This is intended for use in Org mode, where we currently use advise. * lisp/saveplace.el (save-place-after-find-file-hook): New hook. (save-place-find-file-hook): Run new hook. diff --git a/etc/NEWS b/etc/NEWS index ad0acd674e..e757435ff9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2911,6 +2911,10 @@ when used as part of a property list specification for the ** 'defalias' records a more precise history of definitions. This is recorded in the 'function-history' symbol property. +--- +** New hook 'save-place-after-find-file-hook'. +This is called at the end of 'save-place-find-file-hook'. + --- ** 'indian-tml-base-table' no longer translates digits. Use 'indian-tml-base-digits-table' if you want digits translation. diff --git a/lisp/saveplace.el b/lisp/saveplace.el index a23454b0bb..3830e4b16c 100644 --- a/lisp/saveplace.el +++ b/lisp/saveplace.el @@ -346,7 +346,12 @@ may have changed) back to `save-place-alist'." (save-place-to-alist)) (setq buf-list (cdr buf-list)))))) +(defvar save-place-after-find-file-hook nil + "Hook run at the end of `save-place-find-file-hook'.") + (defun save-place-find-file-hook () + "Function added to `find-file-hook' by `save-place-mode'. +It runs the hook `save-place-after-find-file-hook'." (or save-place-loaded (load-save-place-alist-from-file)) (let ((cell (assoc buffer-file-name save-place-alist))) (if cell @@ -355,7 +360,8 @@ may have changed) back to `save-place-alist'." (and (integerp (cdr cell)) (goto-char (cdr cell)))) ;; and make sure it will be saved again for later - (setq save-place-mode t))))) + (setq save-place-mode t)))) + (run-hooks 'save-place-after-find-file-hook)) (declare-function dired-goto-file "dired" (file)) commit 80cf13a3d27d8a967feafeec32fd130529635592 Author: Lars Ingebrigtsen Date: Thu Jun 30 13:18:15 2022 +0200 Make "eager macro-expansion" warning into an error * doc/lispref/loading.texi (How Programs Do Loading): Update documentation. * lisp/emacs-lisp/macroexp.el: (internal-macroexpand-for-load): We've been warning about eager macro expansion for many years, so finally change that into an error (bug#18154). diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index 8a2bb5fa2d..00a1fe05fd 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -149,10 +149,9 @@ up the execution of uncompiled code. Sometimes, this macro expansion cannot be done, owing to a cyclic dependency. In the simplest example of this, the file you are loading refers to a macro defined in another file, and that file in turn requires the file you are -loading. This is generally harmless. Emacs prints a warning +loading. Emacs will issue an error about (@samp{Eager macro-expansion skipped due to cycle@dots{}}) -giving details of the problem, but it still loads the file, just -leaving the macro unexpanded for now. You may wish to restructure +giving details of the problem. You have to restructure your code so that this does not happen. Loading a compiled file does not cause macroexpansion, because this should already have happened during compilation. @xref{Compiling Macros}. diff --git a/etc/NEWS b/etc/NEWS index 1d56547d0d..ad0acd674e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -159,6 +159,9 @@ of 'user-emacs-directory'. * Incompatible changes in Emacs 29.1 ++++ +** Warning about "eager macro-expansion failure" is changed into an error. + --- ** Previously, the X reverseVideo value at startup was heeded for all frames. This meant that if you had a reverseVideo resource on the initial diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index bae303c213..0fb4cf680a 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -796,8 +796,8 @@ test of free variables in the following ways: (if (eq (car-safe (car bt)) 'macroexpand-all) (setq bt (cdr bt))) (if macroexp--debug-eager (debug 'eager-macroexp-cycle) - (message "Warning: Eager macro-expansion skipped due to cycle:\n %s" - (mapconcat #'prin1-to-string (nreverse bt) " => "))) + (error "Warning: Eager macro-expansion skipped due to cycle:\n %s" + (mapconcat #'prin1-to-string (nreverse bt) " => "))) (push 'skip macroexp--pending-eager-loads) form)) (t @@ -811,7 +811,7 @@ test of free variables in the following ways: ;; Hopefully this shouldn't happen thanks to the cycle detection, ;; but in case it does happen, let's catch the error and give the ;; code a chance to macro-expand later. - (message "Eager macro-expansion failure: %S" err) + (error "Eager macro-expansion failure: %S" err) form)))))) ;; ¡¡¡ Big Ugly Hack !!! commit a9ebd2130417e02ccb42dac1af4d27a9054c9dd4 Author: Lars Ingebrigtsen Date: Thu Jun 30 12:50:45 2022 +0200 Do NEWS tagging diff --git a/etc/NEWS b/etc/NEWS index 0dc7674655..1d56547d0d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -314,6 +314,7 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 +--- ** New bindings in 'find-function-setup-keys' for 'find-library'. When 'find-function-setup-keys' is enabled, 'C-x L' is now bound to 'find-library', 'C-x 4 L' is now bound to 'find-library-other-window' commit f5421104e9753a2d3ead19ba31ac5ed1f3a5c03a Author: Eli Zaretskii Date: Thu Jun 30 13:50:34 2022 +0300 Fix external image conversion on MS-Windows * lisp/image/image-converter.el (image-converter--convert-magick) (image-converter--convert): Force encoding/decoding to avoid any text or EOL conversions, since we are reading/writing binary data. (Bug#56317) diff --git a/lisp/image/image-converter.el b/lisp/image/image-converter.el index 460ff16adb..d3d560f021 100644 --- a/lisp/image/image-converter.el +++ b/lisp/image/image-converter.el @@ -227,19 +227,21 @@ Only suffixes that map to `image-mode' are returned." (cadr (split-string (symbol-name image-format) "/")))) (defun image-converter--convert-magick (type source image-format) - (let ((command (image-converter--value type :command))) + (let ((command (image-converter--value type :command)) + (coding-system-for-read 'no-conversion)) (unless (zerop (if image-format ;; We have the image data in SOURCE. (progn (insert source) - (apply #'call-process-region (point-min) (point-max) - (car command) t t nil - (append - (cdr command) - (list (format "%s:-" - (image-converter--mime-type - image-format)) - "png:-")))) + (let ((coding-system-for-write 'no-conversion)) + (apply #'call-process-region (point-min) (point-max) + (car command) t t nil + (append + (cdr command) + (list (format "%s:-" + (image-converter--mime-type + image-format)) + "png:-"))))) ;; SOURCE is a file name. (apply #'call-process (car command) nil t nil @@ -252,18 +254,20 @@ Only suffixes that map to `image-mode' are returned." (cl-defmethod image-converter--convert ((type (eql 'ffmpeg)) source image-format) "Convert using ffmpeg." - (let ((command (image-converter--value type :command))) + (let ((command (image-converter--value type :command)) + (coding-system-for-read 'no-conversion)) (unless (zerop (if image-format (progn (insert source) - (apply #'call-process-region - (point-min) (point-max) (car command) - t '(t nil) nil - (append - (cdr command) - (list "-i" "-" - "-c:v" "png" - "-f" "image2pipe" "-")))) + (let ((coding-system-for-write 'no-conversion)) + (apply #'call-process-region + (point-min) (point-max) (car command) + t '(t nil) nil + (append + (cdr command) + (list "-i" "-" + "-c:v" "png" + "-f" "image2pipe" "-"))))) (apply #'call-process (car command) nil '(t nil) nil commit 2f0ed2280e0075c68ab9b110068bf5395fe256e3 Author: Lars Ingebrigtsen Date: Thu Jun 30 12:49:40 2022 +0200 Add find-function-setup-keys bindings for find-library commands * lisp/emacs-lisp/find-func.el (find-function-setup-keys): Add `L' bindings for the find-library family of commands (bug#51240). diff --git a/etc/NEWS b/etc/NEWS index 1ec9603640..0dc7674655 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -314,6 +314,11 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 +** New bindings in 'find-function-setup-keys' for 'find-library'. +When 'find-function-setup-keys' is enabled, 'C-x L' is now bound to +'find-library', 'C-x 4 L' is now bound to 'find-library-other-window' +and 'C-x 5 L' is now bound to 'find-library-other-frame'. + +++ ** New key binding after 'M-x' or 'M-X': 'M-X'. Emacs allows different completion predicates to be used with 'M-x' diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index ac84b50b5f..486d5d0861 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -800,7 +800,10 @@ See `find-function-on-key'." (define-key ctl-x-5-map "K" 'find-function-on-key-other-frame) (define-key ctl-x-map "V" 'find-variable) (define-key ctl-x-4-map "V" 'find-variable-other-window) - (define-key ctl-x-5-map "V" 'find-variable-other-frame)) + (define-key ctl-x-5-map "V" 'find-variable-other-frame) + (define-key ctl-x-map "L" 'find-library) + (define-key ctl-x-4-map "L" 'find-library-other-window) + (define-key ctl-x-5-map "L" 'find-library-other-frame)) (provide 'find-func) commit 274fcfa8508dd50a975aa891ee9376e389a1af19 Author: Lars Ingebrigtsen Date: Thu Jun 30 12:35:55 2022 +0200 Restore temp-buffer-resize-mode behaviour wrt. [back] buttons * lisp/help.el (help--window-setup): If temp-buffer-resize-mode, do the window setup after adding [back] buttons (bug#56306). diff --git a/lisp/help.el b/lisp/help.el index fbcf8461e6..d7ee1a84a4 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1999,8 +1999,10 @@ The `temp-buffer-window-setup-hook' hook is called." (prog1 (funcall callback) (run-hooks 'temp-buffer-window-setup-hook))) - (help-window-setup (temp-buffer-window-show (current-buffer))) - (help-make-xrefs (current-buffer)))))) + (help-make-xrefs (current-buffer)) + ;; This must be done after the buffer has been completely + ;; generated, since `temp-buffer-resize-mode' may be enabled. + (help-window-setup (temp-buffer-window-show (current-buffer))))))) ;; Called from C, on encountering `help-char' when reading a char. ;; Don't print to *Help*; that would clobber Help history. commit 528fb3e087b2a3ead7bcc7491205c952c291ccc7 Author: Lars Ingebrigtsen Date: Thu Jun 30 12:13:03 2022 +0200 Fix typo in previous server.el change * lisp/server.el (server-process-filter): Fix typo in previous change. diff --git a/lisp/server.el b/lisp/server.el index 229942c19a..a06f2f952f 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -1315,7 +1315,7 @@ The following commands are accepted by the client: ;; When resuming on a tty, tty-name is nil. (tty-name (server-create-tty-frame tty-name tty-type proc - frame-parameters)))) + frame-parameters)) ;; If there won't be a current frame to use, fall ;; back to trying to create a new one. commit 3933ece030150908c9189c11cf683bb3df9e4e18 Author: Michael Shields Date: Thu Jun 30 12:10:45 2022 +0200 Don't ignore emacsclient's --frame-parameters option when -t * lisp/server.el (server-process-filter): Add part of patch that was mistakenly missed when the patch was applied (bug#24147). This also fixes bug#56309. diff --git a/lisp/server.el b/lisp/server.el index 8f47a99a31..229942c19a 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -1314,7 +1314,8 @@ The following commands are accepted by the client: frame-parameters)) ;; When resuming on a tty, tty-name is nil. (tty-name - (server-create-tty-frame tty-name tty-type proc)) + (server-create-tty-frame tty-name tty-type proc + frame-parameters)))) ;; If there won't be a current frame to use, fall ;; back to trying to create a new one. commit 7b9d755b816ca697b879b7c5c61526f96e9f4b9a Author: Lars Ingebrigtsen Date: Thu Jun 30 12:00:49 2022 +0200 Add new commands to elisp mode for eval/compilation * lisp/progmodes/elisp-mode.el (emacs-lisp-mode-map): Add new keystrokes. (elisp-eval-buffer, elisp-byte-compile-file) (elisp-byte-compile-buffer): New commands. diff --git a/etc/NEWS b/etc/NEWS index 14747eaf92..1ec9603640 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -983,6 +983,15 @@ so automatically. * Changes in Specialized Modes and Packages in Emacs 29.1 +** Elisp + +*** New command 'elisp-eval-buffer' (bound to 'C-c C-e'). +This command evals the forms in the the current buffer. + +*** New commands 'elisp-byte-compile-file' and 'elisp-byte-compile-buffer'. +These commands (bound to 'C-c C-f' and 'C-c C-b', respectively) +byte-compile the visited file and the current buffer, respectively. + ** Games --- diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 0bf13a0e09..7acf7316a9 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -52,6 +52,9 @@ All commands in `lisp-mode-shared-map' are inherited by this map." :parent lisp-mode-shared-map "M-TAB" #'completion-at-point "C-M-x" #'eval-defun + "C-c C-e" #'elisp-eval-buffer + "C-c C-f" #'elisp-byte-compile-file + "C-c C-b" #'elisp-byte-compile-buffer "C-M-q" #'indent-pp-sexp) (easy-menu-define emacs-lisp-mode-menu emacs-lisp-mode-map @@ -2194,6 +2197,48 @@ Runs in a batch-mode Emacs. Interactively use variable (terpri) (pp collected))) +(defun elisp-eval-buffer () + "Evaluate the forms in the current buffer." + (interactive) + (eval-buffer) + (message "Evaluated the %s buffer" (buffer-name))) + +(defun elisp-byte-compile-file (&optional load) + "Byte compile the file the current buffer is visiting. +If LOAD is non-nil, load the resulting .elc file. When called +interactively, this is the prefix argument." + (interactive "P") + (unless buffer-file-name + (error "This buffer is not visiting a file")) + (byte-compile-file buffer-file-name) + (when load + (load (funcall byte-compile-dest-file-function buffer-file-name)))) + +(defun elisp-byte-compile-buffer (&optional load) + "Byte compile the current buffer, but don't write a file. +If LOAD is non-nil, load byte-compiled data. When called +interactively, this is the prefix argument." + (interactive "P") + (let (file elc) + (unwind-protect + (progn + (setq file (make-temp-file "compile" nil ".el") + elc (funcall byte-compile-dest-file-function file)) + (write-region (point-min) (point-max) file nil 'silent) + (let ((set-message-function + (lambda (message) + (when (string-match-p "\\`Wrote " message) + 'ignore)))) + (byte-compile-file file)) + (if load + (load elc) + (message "Byte-compiled the current buffer"))) + (when file + (when (file-exists-p file) + (delete-file file)) + (when (file-exists-p elc) + (delete-file elc)))))) + (put 'read-symbol-shorthands 'safe-local-variable #'consp) commit 931bb26bb2b22f4aa2ee3263e16f74039c18b13a Author: Mike Kupfer Date: Thu Jun 30 11:21:12 2022 +0200 Clarify `version-control' in the Emacs manual * doc/emacs/files.texi (Backup Names): Rephrase for greater clarity (bug#56291). diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index fa02d264f9..7b4e31e5f8 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -655,10 +655,10 @@ Never make numbered backups; always make single backups. The usual way to set this variable is globally, through your init file or the customization buffer. However, you can set @code{version-control} locally in an individual buffer to control the -making of backups for that buffer's file (@pxref{Locals}). You can -have Emacs set @code{version-control} locally whenever you visit a -given file (@pxref{File Variables}). Some modes, such as Rmail mode, -set this variable. +making of backups for that buffer's file (@pxref{Locals}). Some +modes, such as Rmail mode, set this variable. You can also have Emacs +set @code{version-control} locally whenever you visit a given file +(@pxref{File Variables}). @cindex @env{VERSION_CONTROL} environment variable If you set the environment variable @env{VERSION_CONTROL}, to tell commit c59b8dfefa01f10687e1b5597088b2371275c421 Author: Lars Ingebrigtsen Date: Thu Jun 30 11:04:15 2022 +0200 Recognize Gradle error messages in compile-mode * lisp/progmodes/compile.el (compilation-error-regexp-alist-alist): Recognize Gradle errors (bug#56249). diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index db57093559..9f33186d8b 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -276,7 +276,16 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1)) "): ") 3 4 5 (1 . 2)) - (iar + (gradle-android + ,(rx bol (* " ") "ERROR:" + (group-n 1 ; file + (+ (not (in ":\n")))) + ":" + (group-n 2 (+ digit)) ; line + ": ") + 1 2) + + (iar "^\"\\(.*\\)\",\\([0-9]+\\)\\s-+\\(?:Error\\|Warnin\\(g\\)\\)\\[[0-9]+\\]:" 1 2 nil (3)) commit febefd6adb9c4b4f6d3a98c678e52b97859c8066 Author: Lars Ingebrigtsen Date: Thu Jun 30 10:58:14 2022 +0200 Add provide to testcover * lisp/emacs-lisp/testcover.el (testcover): Provide (bug#55388). diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el index 33628d8f47..302f89cc1c 100644 --- a/lisp/emacs-lisp/testcover.el +++ b/lisp/emacs-lisp/testcover.el @@ -677,4 +677,6 @@ The list is 1valued if all of its constituent elements are also 1valued." (testcover-analyze-coverage (cadr form))) (t (testcover-analyze-coverage-backquote form)))) +(provide 'testcover) + ;;; testcover.el ends here commit 8c200afe46768a5964390b8c6fde408672e0c4ab Author: Lars Ingebrigtsen Date: Thu Jun 30 10:47:34 2022 +0200 Regenerated ldefs-boot.el diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index 7d06328a54..2d1e327597 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -2784,6 +2784,9 @@ Compile a file of Lisp code named FILENAME into a file of byte code. The output file's name is generated by passing FILENAME to the function `byte-compile-dest-file' (which see). The value is non-nil if there were no errors, nil if errors. +If the file sets the file variable `no-byte-compile', it is not +compiled, any existing output file is removed, and the return +value is `no-byte-compile'. See also `emacs-lisp-byte-compile-and-load'. @@ -8943,7 +8946,7 @@ To change the default, set the variable `ediff-use-toolbar-p', which see." t nil (autoload 'edit-kbd-macro "edmacro" "\ Edit a keyboard macro. At the prompt, type any key sequence which is bound to a keyboard macro. -Or, type `\\[kmacro-end-and-call-macro]' or RET to edit the last +Or, type `\\[kmacro-end-and-call-macro]' or \\`RET' to edit the last keyboard macro, `\\[view-lossage]' to edit the last 300 keystrokes as a keyboard macro, or `\\[execute-extended-command]' to edit a macro by its command name. @@ -9504,6 +9507,17 @@ If called from Lisp, return the name as a string; return nil if the name is not known. (fn GLYPH &optional INTERACTIVE)" t nil) +(autoload 'emoji-zoom-increase "emoji" "\ +Increase the size of the character under point. +FACTOR is the multiplication factor for the size. + +This command will be repeatable if `repeat-mode' is switched on. + +(fn &optional FACTOR)" t nil) +(autoload 'emoji-zoom-decrease "emoji" "\ +Decrease the size of the character under point. + +This command will be repeatable if `repeat-mode' is switched on." t nil) (register-definition-prefixes "emoji" '("emoji-")) @@ -11207,7 +11221,7 @@ the same amount). (fn LEVEL)" t nil) (autoload 'text-scale-increase "face-remap" "\ -Increase the height of the default face in the current buffer by INC steps. +Increase the font size of the default face in current buffer by INC steps. If the new height is other than the default, `text-scale-mode' is enabled. Each step scales the height of the default face by the variable @@ -11217,7 +11231,7 @@ will remove any scaling currently active. (fn INC)" t nil) (autoload 'text-scale-decrease "face-remap" "\ -Decrease the height of the default face in the current buffer by DEC steps. +Decrease the font size of the default face in the current buffer by DEC steps. See `text-scale-increase' for more details. (fn DEC)" t nil) @@ -11226,19 +11240,18 @@ See `text-scale-increase' for more details. (define-key ctl-x-map [(control ?=)] 'text-scale-adjust) (define-key ctl-x-map [(control ?0)] 'text-scale-adjust) (autoload 'text-scale-adjust "face-remap" "\ -Adjust the height of the default face by INC. - +Adjust the font size in the current buffer by INC steps. INC may be passed as a numeric prefix argument. The actual adjustment made depends on the final component of the keybinding used to invoke the command, with all modifiers removed: - +, = Increase the height of the default face by one step - - Decrease the height of the default face by one step - 0 Reset the height of the default face to the global default + +, = Increase font size in current buffer by one step + - Decrease font size in current buffer by one step + 0 Reset the font size to the global default After adjusting, continue to read input events and further adjust -the face height as long as the input event read +the font size as long as the input event read (with all modifiers removed) is one of the above characters. Each step scales the height of the default face by the variable @@ -11252,6 +11265,11 @@ even when it is bound in a non-top-level keymap. For binding in a top-level keymap, `text-scale-increase' or `text-scale-decrease' may be more appropriate. +Most faces are affected by these font size changes, but not faces +that have an explicit `:height' setting. The two exceptions to +this are the `default' and `header-line' faces: they will both be +scaled even if they have an explicit `:height' setting. + (fn INC)" t nil) (define-key global-map [pinch] 'text-scale-pinch) (autoload 'text-scale-pinch "face-remap" "\ @@ -11747,6 +11765,19 @@ Collect output in the \"*Find*\" buffer. To kill the job before it finishes, type \\[kill-find]. (fn DIR ARGS)" t nil) +(autoload 'find-dired-with-command "find-dired" "\ +Run `find' and go into Dired mode on a buffer of the output. +The user-supplied COMMAND is run after changing into DIR and should look like + + find . GLOBALARGS \\( ARGS \\) -ls + +The car of the variable `find-ls-option' specifies what to +use in place of \"-ls\" as the starting input. + +Collect output in the \"*Find*\" buffer. To kill the job before +it finishes, type \\[kill-find]. + +(fn DIR COMMAND)" t nil) (autoload 'find-name-dired "find-dired" "\ Search DIR recursively for files matching the globbing PATTERN, and run Dired on those files. @@ -14862,6 +14893,9 @@ regexp. TYPE is the type of button to use. Any remaining arguments are passed to the button's help-function when it is invoked. See `help-make-xrefs'. +This function removes quotes surrounding the match if the +variable `help-clean-buttons' is non-nil. + (fn MATCH-NUMBER TYPE &rest ARGS)" nil nil) (autoload 'help-insert-xref-button "help-mode" "\ Insert STRING and make a hyperlink from cross-reference text on it. @@ -16684,13 +16718,15 @@ SPECS is a list of image specifications. Each image specification in SPECS is a property list. The contents of a specification are image type dependent. All specifications must at -least contain the properties `:type TYPE' and either `:file FILE' or -`:data DATA', where TYPE is a symbol specifying the image type, -e.g. `xbm', FILE is the file to load the image from, and DATA is a -string containing the actual image data. The specification whose TYPE -is supported, and FILE exists, is used to construct the image -specification to be returned. Return nil if no specification is -satisfied. +least contain either the property `:file FILE' or `:data DATA', +where FILE is the file to load the image from, and DATA is a string +containing the actual image data. If the property `:type TYPE' is +omitted or nil, try to determine the image type from its first few +bytes of image data. If that doesn't work, and the property `:file +FILE' provide a file name, use its file extension as image type. +If `:type TYPE' is provided, it must match the actual type +determined for FILE or DATA by `create-image'. Return nil if no +specification is satisfied. If CACHE is non-nil, results are cached and returned on subsequent calls. @@ -19940,7 +19976,15 @@ Copy ARG characters, but not past the end of that line. If no argument given, copy the entire rest of the line. The characters copied are inserted in the buffer before point. +Also see the `duplicate-line' command. + (fn &optional ARG)" t nil) +(autoload 'duplicate-line "misc" "\ +Duplicate the current line N times. +Interactively, N is the prefix numeric argument, and defaults to 1. +Also see the `copy-from-above-command' command. + +(fn &optional N)" t nil) (autoload 'zap-up-to-char "misc" "\ Kill up to, but not including ARGth occurrence of CHAR. When run interactively, the argument INTERACTIVE is non-nil. @@ -23307,6 +23351,11 @@ Turning on Perl mode runs the normal hook `perl-mode-hook'. (fn)" t nil) (register-definition-prefixes "perl-mode" '("indent-perl-exp" "mark-perl-function" "perl-")) + +;;; Generated autoloads from pgtk-dnd.el + +(register-definition-prefixes "pgtk-dnd" '("pgtk-dnd-")) + ;;; Generated autoloads from textmodes/picture.el @@ -25053,6 +25102,12 @@ provided in the Commentary section of this library." t nil) ;;; Generated autoloads from recentf.el +(autoload 'recentf-open "recentf" "\ +Prompt for FILE in `recentf-list' and visit it. +Enable `recentf-mode' if it isn't already. + +(fn FILE)" t nil) +(defalias 'recentf 'recentf-open) (defvar recentf-mode nil "\ Non-nil if Recentf mode is enabled. See the `recentf-mode' command @@ -25062,7 +25117,14 @@ either customize it (see the info node `Easy Customization') or call the function `recentf-mode'.") (custom-autoload 'recentf-mode "recentf" nil) (autoload 'recentf-mode "recentf" "\ -Toggle \"Open Recent\" menu (Recentf mode). +Toggle keeping track of opened files (Recentf mode). + +This mode maintains a list of recently opened files and makes it +easy to visit them. The recent files list is automatically saved +across Emacs sessions. + +You can use `recentf-open' or `recentf-open-files' to visit +files. When Recentf mode is enabled, a \"Open Recent\" submenu is displayed in the \"File\" menu, containing a list of files that @@ -26171,57 +26233,6 @@ sender of the current message. (fn SENDERS)" t nil) (register-definition-prefixes "rmailsum" '("rmail-")) - -;;; Generated autoloads from emacs-lisp/rmc.el - -(autoload 'read-multiple-choice "rmc" "\ -Ask user to select an entry from CHOICES, promting with PROMPT. -This function allows to ask the user a multiple-choice question. - -CHOICES should be a list of the form (KEY NAME [DESCRIPTION]). -KEY is a character the user should type to select the entry. -NAME is a short name for the entry to be displayed while prompting -(if there's no room, it might be shortened). -DESCRIPTION is an optional longer description of the entry; it will -be displayed in a help buffer if the user requests more help. This -help description has a fixed format in columns. For greater -flexibility, instead of passing a DESCRIPTION, the caller can pass -the optional argument HELP-STRING. This argument is a string that -should contain a more detailed description of all of the possible -choices. `read-multiple-choice' will display that description in a -help buffer if the user requests that. -If optional argument SHOW-HELP is non-nil, show the help screen -immediately, before any user input. If SHOW-HELP is a string, -use it as the name of the help buffer. - -This function translates user input into responses by consulting -the bindings in `query-replace-map'; see the documentation of -that variable for more information. The relevant bindings for the -purposes of this function are `recenter', `scroll-up', `scroll-down', -and `edit'. -If the user types the `recenter', `scroll-up', or `scroll-down' -responses, the function performs the requested window recentering or -scrolling, and then asks the question again. If the user enters `edit', -the function starts a recursive edit. When the user exit the recursive -edit, the multiple-choice prompt gains focus again. - -When `use-dialog-box' is t (the default), and the command using this -function was invoked via the mouse, this function pops up a GUI dialog -to collect the user input, but only if Emacs is capable of using GUI -dialogs. Otherwise, the function will always use text-mode dialogs. - -The return value is the matching entry from the CHOICES list. - -Usage example: - -(read-multiple-choice \"Continue connecting?\" - \\='((?a \"always\") - (?s \"session only\") - (?n \"no\"))) - -(fn PROMPT CHOICES &optional HELP-STRING SHOW-HELP)" nil nil) -(register-definition-prefixes "rmc" '("rmc--")) - ;;; Generated autoloads from nxml/rng-cmpct.el @@ -27300,106 +27311,6 @@ Like `mail' command, but display mail buffer in another frame. ;;; Generated autoloads from emacs-lisp/seq.el (push (purecopy '(seq 2 23)) package--builtin-versions) -(autoload 'seq-subseq "seq" "\ -Return the sequence of elements of SEQUENCE from START to END. -END is exclusive. - -If END is omitted, it defaults to the length of the sequence. If -START or END is negative, it counts from the end. Signal an -error if START or END are outside of the sequence (i.e too large -if positive or too small if negative). - -(fn SEQUENCE START &optional END)" nil nil) -(autoload 'seq-take "seq" "\ -Take the first N elements of SEQUENCE and return the result. -The result is a sequence of the same type as SEQUENCE. - -If N is a negative integer or zero, an empty sequence is -returned. - -(fn SEQUENCE N)" nil nil) -(autoload 'seq-sort-by "seq" "\ -Sort SEQUENCE using PRED as a comparison function. -Elements of SEQUENCE are transformed by FUNCTION before being -sorted. FUNCTION must be a function of one argument. - -(fn FUNCTION PRED SEQUENCE)" nil nil) -(autoload 'seq-filter "seq" "\ -Return a list of all elements for which (PRED element) is non-nil in SEQUENCE. - -(fn PRED SEQUENCE)" nil nil) -(autoload 'seq-remove "seq" "\ -Return a list of all the elements for which (PRED element) is nil in SEQUENCE. - -(fn PRED SEQUENCE)" nil nil) -(autoload 'seq-reduce "seq" "\ -Reduce the function FUNCTION across SEQUENCE, starting with INITIAL-VALUE. - -Return the result of calling FUNCTION with INITIAL-VALUE and the -first element of SEQUENCE, then calling FUNCTION with that result -and the second element of SEQUENCE, then with that result and the -third element of SEQUENCE, etc. FUNCTION will be called with -INITIAL-VALUE (and then the accumulated value) as the first -argument, and the elements from SEQUENCE as the second argument. - -If SEQUENCE is empty, return INITIAL-VALUE and FUNCTION is not called. - -(fn FUNCTION SEQUENCE INITIAL-VALUE)" nil nil) -(autoload 'seq-every-p "seq" "\ -Return non-nil if (PRED element) is non-nil for all elements of SEQUENCE. - -(fn PRED SEQUENCE)" nil nil) -(autoload 'seq-some "seq" "\ -Return non-nil if PRED is satisfied for at least one element of SEQUENCE. -If so, return the first non-nil value returned by PRED. - -(fn PRED SEQUENCE)" nil nil) -(autoload 'seq-find "seq" "\ -Return the first element for which (PRED element) is non-nil in SEQUENCE. -If no element is found, return DEFAULT. - -Note that `seq-find' has an ambiguity if the found element is -identical to DEFAULT, as it cannot be known if an element was -found or not. - -(fn PRED SEQUENCE &optional DEFAULT)" nil nil) -(autoload 'seq-position "seq" "\ -Return the index of the first element in SEQUENCE that is equal to ELT. -Equality is defined by TESTFN if non-nil or by `equal' if nil. - -(fn SEQUENCE ELT &optional TESTFN)" nil nil) -(autoload 'seq-uniq "seq" "\ -Return a list of the elements of SEQUENCE with duplicates removed. -TESTFN is used to compare elements, or `equal' if TESTFN is nil. - -(fn SEQUENCE &optional TESTFN)" nil nil) -(autoload 'seq-union "seq" "\ -Return a list of all elements that appear in either SEQUENCE1 or SEQUENCE2. -Equality is defined by TESTFN if non-nil or by `equal' if nil. - -(fn SEQUENCE1 SEQUENCE2 &optional TESTFN)" nil nil) -(autoload 'seq-intersection "seq" "\ -Return a list of the elements that appear in both SEQUENCE1 and SEQUENCE2. -Equality is defined by TESTFN if non-nil or by `equal' if nil. - -(fn SEQUENCE1 SEQUENCE2 &optional TESTFN)" nil nil) -(autoload 'seq-group-by "seq" "\ -Apply FUNCTION to each element of SEQUENCE. -Separate the elements of SEQUENCE into an alist using the results as -keys. Keys are compared using `equal'. - -(fn FUNCTION SEQUENCE)" nil nil) -(autoload 'seq-max "seq" "\ -Return the largest element of SEQUENCE. -SEQUENCE must be a sequence of numbers or markers. - -(fn SEQUENCE)" nil nil) -(autoload 'seq-random-elt "seq" "\ -Return a random element from SEQUENCE. -Signal an error if SEQUENCE is empty. - -(fn SEQUENCE)" nil nil) -(register-definition-prefixes "seq" '("seq-")) ;;; Generated autoloads from server.el @@ -27800,6 +27711,70 @@ Make the shell buffer the current buffer, and return it. ;;; Generated autoloads from emacs-lisp/shortdoc.el +(defvar shortdoc--groups nil) +(defmacro define-short-documentation-group (group &rest functions) "\ +Add GROUP to the list of defined documentation groups. +FUNCTIONS is a list of elements on the form: + + (FUNC + :no-manual BOOL + :args ARGS + :eval EVAL + :no-eval EXAMPLE-FORM + :no-value EXAMPLE-FORM + :no-eval* EXAMPLE-FORM + :result RESULT-FORM + :result-string RESULT-STRING + :eg-result RESULT-FORM + :eg-result-string RESULT-STRING) + +FUNC is the function being documented. + +NO-MANUAL should be non-nil if FUNC isn't documented in the +manual. + +ARGS is optional list of function FUNC's arguments. FUNC's +signature is displayed automatically if ARGS is not present. +Specifying ARGS might be useful where you don't want to document +some of the uncommon arguments a function might have. + +While the `:no-manual' and `:args' property can be used for +any (FUNC ..) form, all of the other properties shown above +cannot be used simultaneously in such a form. + +Here are some common forms with examples of properties that go +together: + +1. Document a form or string, and its evaluated return value. + (FUNC + :eval EVAL) + +If EVAL is a string, it will be inserted as is, and then that +string will be `read' and evaluated. + +2. Document a form or string, but manually document its evaluation + result. The provided form will not be evaluated. + + (FUNC + :no-eval EXAMPLE-FORM + :result RESULT-FORM) ;Use `:result-string' if value is in string form + +Using `:no-value' is the same as using `:no-eval'. + +Use `:no-eval*' instead of `:no-eval' where the successful +execution of the documented form depends on some conditions. + +3. Document a form or string EXAMPLE-FORM. Also manually + document an example result. This result could be unrelated to + the documented form. + + (FUNC + :no-eval EXAMPLE-FORM + :eg-result RESULT-FORM) ;Use `:eg-result-string' if value is in string form + +A FUNC form can have any number of `:no-eval' (or `:no-value'), +`:no-eval*', `:result', `:result-string', `:eg-result' and +`:eg-result-string' properties." (declare (indent defun)) `(progn (setq shortdoc--groups (delq (assq ',group shortdoc--groups) shortdoc--groups)) (push (cons ',group ',functions) shortdoc--groups))) (autoload 'shortdoc-display-group "shortdoc" "\ Pop to a buffer with short documentation summary for functions in GROUP. If FUNCTION is non-nil, place point on the entry for FUNCTION (if any). @@ -27807,7 +27782,7 @@ If SAME-WINDOW, don't pop to a new window. (fn GROUP &optional FUNCTION SAME-WINDOW)" t nil) (defalias 'shortdoc #'shortdoc-display-group) -(register-definition-prefixes "shortdoc" '("alist" "buffer" "define-short-documentation-group" "file" "hash-table" "keymaps" "list" "number" "overlay" "process" "regexp" "sequence" "shortdoc-" "string" "text-properties" "vector")) +(register-definition-prefixes "shortdoc" '("alist" "buffer" "file" "hash-table" "keymaps" "list" "number" "overlay" "process" "regexp" "sequence" "shortdoc-" "string" "text-properties" "vector")) ;;; Generated autoloads from net/shr.el @@ -28219,7 +28194,7 @@ values), despite potential performance issues, type \\[so-long-revert]. Use \\[so-long-commentary] for more information. Use \\[so-long-customize] to open the customization group `so-long' to -configure the behaviour. +configure the behavior. (fn)" t nil) (autoload 'so-long "so-long" "\ @@ -28266,7 +28241,7 @@ When such files are detected by `so-long-predicate', we invoke the selected Use \\[so-long-commentary] for more information. Use \\[so-long-customize] to open the customization group `so-long' to -configure the behaviour. +configure the behavior. This is a global minor mode. If called interactively, toggle the `Global So-Long mode' mode. If the prefix argument is positive, @@ -29365,7 +29340,7 @@ this defaults to the current buffer. Query the user for a process and return the process object. (fn PROMPT)" nil nil) -(register-definition-prefixes "subr-x" '("hash-table-" "internal--thread-argument" "named-let" "replace-region-contents" "string-" "thread-" "with-")) +(register-definition-prefixes "subr-x" '("hash-table-" "internal--thread-argument" "named-let" "replace-region-contents" "string-" "thread-" "with-buffer-unmodified-if-unchanged")) ;;; Generated autoloads from progmodes/subword.el commit 371c4f642a1476ce2cd3514caeb66125c53aea26 Author: Lars Ingebrigtsen Date: Thu Jun 30 10:46:59 2022 +0200 Add new commands to zoom emojis * lisp/international/emoji.el (emoji-zoom-map) (emoji-zoom-increase, emoji-zoom-decrease): New commands. * lisp/international/mule-cmds.el (ctl-x-map): Bind them. diff --git a/etc/NEWS b/etc/NEWS index ce32542028..14747eaf92 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -607,6 +607,11 @@ inserted. This command will tell you the name of the Emoji at point. (This command also works for non-Emoji characters.) +--- +*** New commands 'emoji-zoom-increase' and 'emoji-zoom-decrease'. +These are bound to 'C-x 8 e +' and 'C-x 8 e -', respectively. They +can be used on any character, but are mainly useful for emoji. + --- *** New input method 'emoji'. This allows you to enter emoji using short strings, eg ':face_palm:' diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index 8970a466b7..6a65bc43dc 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -700,6 +700,46 @@ We prefer the earliest unique letter." (emoji--define-transient (cons "Choose Emoji" (cons glyph derived)))))))))) +(defvar-keymap emoji-zoom-map + "+" #'emoji-zoom-increase + "-" #'emoji-zoom-decrease) + +;;;###autoload +(defun emoji-zoom-increase (&optional factor) + "Increase the size of the character under point. +FACTOR is the multiplication factor for the size. + +This command will be repeatable if `repeat-mode' is switched on." + (interactive) + (let* ((factor (or factor 1.1)) + (old (get-text-property (point) 'face)) + (height (or (and (consp old) + (plist-get old :height)) + 1.0)) + (inhibit-read-only t)) + (with-silent-modifications + (if (consp old) + (add-text-properties + (point) (1+ (point)) + (list 'face (plist-put (copy-sequence old) :height (* height factor)) + 'rear-nonsticky t)) + (add-face-text-property (point) (1+ (point)) + (list :height (* height factor))) + (put-text-property (point) (1+ (point)) + 'rear-nonsticky t))))) + +(put 'emoji-zoom-increase 'repeat-map 'emoji-zoom-map) + +;;;###autoload +(defun emoji-zoom-decrease () + "Decrease the size of the character under point. + +This command will be repeatable if `repeat-mode' is switched on." + (interactive) + (emoji-zoom-increase 0.9)) + +(put 'emoji-zoom-decrease 'repeat-map 'emoji-zoom-map) + (provide 'emoji) ;;; emoji.el ends here diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el index 27defef648..48c8d2b081 100644 --- a/lisp/international/mule-cmds.el +++ b/lisp/international/mule-cmds.el @@ -3257,7 +3257,9 @@ as names, not numbers." "s" #'emoji-search "d" #'emoji-describe "r" #'emoji-recent - "l" #'emoji-list)) + "l" #'emoji-list + "+" #'emoji-zoom-increase + "-" #'emoji-zoom-decrease)) (defface confusingly-reordered '((((supports :underline (:style wave))) commit ebd980bc7e45acaa65adae91400903384fd6dfb2 Author: Po Lu Date: Thu Jun 30 16:41:58 2022 +0800 Disable unrelated drag-and-drop protocols during XDS drop * doc/lispref/frames.texi (Drag and Drop): Document variables used to control drag-and-drop protocols. * lisp/x-dnd.el (x-dnd-do-direct-save): Disable irrelevant DND protocols. * src/xterm.c (x_dnd_get_target_window_1): (x_dnd_get_target_window): (handle_one_xevent): Respect new variable. (syms_of_xterm): New variable `x-dnd-disable-motif-protocol'. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 860258a964..720753edad 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4258,6 +4258,28 @@ chosen by the target. For example, callers should delete the buffer text that was dragged if this function returns @code{XdndActionMove}. @end defun +@cindex drag and drop protocols, X + + On X Windows, several different drag-and-drop protocols are +supported by @code{x-begin-drag}. When dragging content that is known +to not be supported by a specific drag-and-drop protocol, it might be +desirable to turn that protocol off, by changing the values of the +following variables: + +@defvar x-dnd-disable-motif-protocol +When this is non-@code{nil}, the Motif drag and drop protocols are +disabled, and dropping onto programs that only understand them will +not work. +@end defvar + +@defvar x-dnd-use-offix-drop +When this is @code{nil}, the OffiX (old KDE) drag and drop protocol is +disabled. When this is the symbol @code{files}, the OffiX protocol +will only be used if @code{"FILE_NAME"} is one of the targets given to +@code{x-begin-drag}. Any other value means to use the OffiX protocol +to drop all supported content. +@end defvar + @node Color Names @section Color Names diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 762d42175e..c3d56f327d 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -1143,6 +1143,8 @@ ACTION is the action given to `x-begin-drag'." (defvar x-dnd-xds-performed nil "Whether or not the drop target made a request for `XdndDirectSave0'.") +(defvar x-dnd-disable-motif-protocol) + (defun x-dnd-handle-direct-save (_selection _type _value) "Handle a selection request for `XdndDirectSave'." (setq x-dnd-xds-performed t) @@ -1198,6 +1200,10 @@ was taken, or the direct save failed." (x-dnd-xds-current-file nil) (x-dnd-xds-source-frame frame) (x-dnd-xds-performed nil) + ;; The XDS protocol is built on top of XDND, and cannot + ;; possibly work with Motif or OffiX programs. + (x-dnd-disable-motif-protocol t) + (x-dnd-use-offix-drop nil) (prop-deleted nil) encoded-name) (unwind-protect diff --git a/src/xterm.c b/src/xterm.c index 9d260ded83..500443ebaa 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3542,6 +3542,7 @@ x_dnd_get_target_window_1 (struct x_display_info *dpyinfo, root_x and root_y are. */ *motif_out = XM_DRAG_STYLE_NONE; + for (tem = x_dnd_toplevels; tem; tem = tem->next) { if (!tem->mapped_p || tem->wm_state != NormalState) @@ -3616,7 +3617,9 @@ x_dnd_get_target_window_1 (struct x_display_info *dpyinfo, if (chosen) { - *motif_out = chosen->xm_protocol_style; + *motif_out = (x_dnd_disable_motif_protocol + ? XM_DRAG_STYLE_NONE + : chosen->xm_protocol_style); return chosen->window; } else @@ -4147,7 +4150,8 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, || proto != -1 || motif != XM_DRAG_STYLE_NONE) { *proto_out = proto; - *motif_out = motif; + *motif_out = (x_dnd_disable_motif_protocol + ? XM_DRAG_STYLE_NONE : motif); *toplevel_out = child_return; x_uncatch_errors (); @@ -18925,6 +18929,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window, &drag_receiver_info) + && !x_dnd_disable_motif_protocol && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE && (x_dnd_allow_current_frame || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))) @@ -20330,6 +20335,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (!xm_read_drag_receiver_info (dpyinfo, x_dnd_last_seen_window, &drag_receiver_info) + && !x_dnd_disable_motif_protocol && drag_receiver_info.protocol_style != XM_DRAG_STYLE_NONE && (x_dnd_allow_current_frame || x_dnd_last_seen_window != FRAME_OUTER_WINDOW (x_dnd_frame))) @@ -28063,4 +28069,10 @@ This lets you inspect the contents of `XdndSelection' after a drag-and-drop operation, which is useful when writing tests for drag-and-drop code. */); x_dnd_preserve_selection_data = false; + + DEFVAR_BOOL ("x-dnd-disable-motif-protocol", x_dnd_disable_motif_protocol, + doc: /* Disable the Motif drag-and-drop protocols. +When non-nil, `x-begin-drag' will not drop onto any window that only +supports the Motif drag-and-drop protocols. */); + x_dnd_disable_motif_protocol = false; } commit 25887d634f624369559ab072beea0d1e2d6886cd Author: Po Lu Date: Thu Jun 30 14:13:30 2022 +0800 Improve compliance with the XDS and XDND protocols * lisp/select.el (xselect-convert-to-text-uri-list): Return a type of `text/uri-list' instead of STRING or C_STRING. * lisp/x-dnd.el (x-dnd-xds-performed): New defvar. (x-dnd-handle-direct-save): Set it to t and handle URIs with hostnames correctly. Also return errors correctly. (x-dnd-handle-octet-stream): New function. (x-dnd-do-direct-save): Handle application/octet-stream, check results. diff --git a/lisp/select.el b/lisp/select.el index 127a6a5c61..8ffe16e7b3 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -721,16 +721,18 @@ This function returns the string \"emacs\"." (user-real-login-name)) (defun xselect-convert-to-text-uri-list (_selection _type value) - (if (stringp value) - (xselect--encode-string 'TEXT - (concat (url-encode-url value) "\n")) - (when (vectorp value) - (with-temp-buffer - (cl-loop for tem across value - do (progn - (insert (url-encode-url tem)) - (insert "\n"))) - (xselect--encode-string 'TEXT (buffer-string)))))) + (let ((string + (if (stringp value) + (xselect--encode-string 'TEXT + (concat (url-encode-url value) "\n")) + (when (vectorp value) + (with-temp-buffer + (cl-loop for tem across value + do (progn + (insert (url-encode-url tem)) + (insert "\n"))) + (xselect--encode-string 'TEXT (buffer-string))))))) + (cons 'text/uri-list (cdr string)))) (defun xselect-convert-to-xm-file (selection _type value) (when (and (stringp value) diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index d92009f85c..762d42175e 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -1140,23 +1140,43 @@ ACTION is the action given to `x-begin-drag'." (defvar x-dnd-xds-source-frame nil "The frame from which a direct save is currently being performed.") +(defvar x-dnd-xds-performed nil + "Whether or not the drop target made a request for `XdndDirectSave0'.") + (defun x-dnd-handle-direct-save (_selection _type _value) "Handle a selection request for `XdndDirectSave'." + (setq x-dnd-xds-performed t) (let* ((uri (x-window-property "XdndDirectSave0" x-dnd-xds-source-frame "AnyPropertyType" nil t)) - (local-name (dnd-get-local-file-name uri nil))) + (local-file-uri (if (and (string-match "^file://\\([^/]*\\)" uri) + (not (equal (match-string 1 uri) ""))) + (dnd-get-local-file-uri uri) + uri)) + (local-name (dnd-get-local-file-name local-file-uri))) (if (not local-name) '(STRING . "F") (condition-case nil (progn - (rename-file x-dnd-xds-current-file - local-name t) + (copy-file x-dnd-xds-current-file + local-name t) (when (equal x-dnd-xds-current-file dnd-last-dragged-remote-file) (dnd-remove-last-dragged-remote-file))) (:success '(STRING . "S")) - (error '(STRING . "F")))))) + (error '(STRING . "E")))))) + +(defun x-dnd-handle-octet-stream (_selection _type _value) + "Handle a selecton request for `application/octet-stream'. +Return the contents of the XDS file." + (cons 'application/octet-stream + (ignore-errors + (with-temp-buffer + (set-buffer-multibyte nil) + (setq buffer-file-coding-system 'binary) + (insert-file-contents-literally x-dnd-xds-current-file) + (buffer-substring-no-properties (point-min) + (point-max)))))) (defun x-dnd-do-direct-save (file name frame allow-same-frame) "Perform a direct save operation on FILE, from FRAME. @@ -1166,16 +1186,19 @@ FRAME is the frame from which the drop will originate. ALLOW-SAME-FRAME means whether or not dropping will be allowed on FRAME. -Return the action taken by the drop target, or nil." +Return the action taken by the drop target, or nil if no action +was taken, or the direct save failed." (dnd-remove-last-dragged-remote-file) (let ((file-name file) (original-file-name file) (selection-converter-alist - (cons (cons 'XdndDirectSave0 - #'x-dnd-handle-direct-save) - selection-converter-alist)) + (append '((XdndDirectSave0 . x-dnd-handle-direct-save) + (application/octet-stream . x-dnd-handle-octet-stream)) + selection-converter-alist)) (x-dnd-xds-current-file nil) (x-dnd-xds-source-frame frame) + (x-dnd-xds-performed nil) + (prop-deleted nil) encoded-name) (unwind-protect (progn @@ -1195,12 +1218,23 @@ Return the action taken by the drop target, or nil." ;; FIXME: this does not work with GTK file managers, since ;; they always reach for `text/uri-list' first, contrary to ;; the spec. - (x-begin-drag '("XdndDirectSave0" "text/uri-list") - 'XdndActionDirectSave - frame nil allow-same-frame)) + (let ((action (x-begin-drag '("XdndDirectSave0" "text/uri-list") + 'XdndActionDirectSave + frame nil allow-same-frame))) + (if (not x-dnd-xds-performed) + action + (let ((property (x-window-property "XdndDirectSave0" frame + "AnyPropertyType" nil t))) + (setq prop-deleted t) + ;; "System-G" deletes the property upon success. + (and (or (null property) + (and (stringp property) + (not (equal property "")))) + action))))) ;; TODO: check for failure and implement selection-based file ;; transfer. - (x-delete-window-property "XdndDirectSave0" frame) + (unless prop-deleted + (x-delete-window-property "XdndDirectSave0" frame)) ;; Delete any remote copy that was made. (when (not (equal file-name original-file-name)) (delete-file file-name))))) commit 76e4179774fc32dae878b135ca58a53b1a294e78 Author: Thomas Fitzsimmons Date: Wed Jun 29 21:53:39 2022 -0400 EUDC: Use "Surname" instead of "Name" in prompts * lisp/net/eudc-vars.el (eudc-user-attribute-names-alist): Add name/"Surname" association. * lisp/net/eudc.el (eudc-get-email): Prompt for surname. * lisp/net/eudc.el (eudc-get-phone): Likewise. diff --git a/lisp/net/eudc-vars.el b/lisp/net/eudc-vars.el index 90d89e87fb..59347ccc89 100644 --- a/lisp/net/eudc-vars.el +++ b/lisp/net/eudc-vars.el @@ -283,6 +283,7 @@ If nil, query all servers available from `eudc-inline-expansion-servers'." (firstname . "First Name") (cn . "Full Name") (sn . "Surname") + (name . "Surname") (givenname . "First Name") (ou . "Unit") (labeledurl . "URL") diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el index fc35d6a084..ca4e4c9f37 100644 --- a/lisp/net/eudc.el +++ b/lisp/net/eudc.el @@ -721,7 +721,7 @@ server for future sessions." (defun eudc-get-email (name &optional error) "Get the email field of NAME from the directory server. If ERROR is non-nil, report an error if there is none." - (interactive "sName: \np") + (interactive "sSurname: \np") (or eudc-server (call-interactively 'eudc-set-server)) (let ((result (eudc-query (list (cons 'name name)) '(email))) @@ -739,7 +739,7 @@ If ERROR is non-nil, report an error if there is none." (defun eudc-get-phone (name &optional error) "Get the phone field of NAME from the directory server. If ERROR is non-nil, report an error if there is none." - (interactive "sName: \np") + (interactive "sSurname: \np") (or eudc-server (call-interactively 'eudc-set-server)) (let ((result (eudc-query (list (cons 'name name)) '(phone))) commit e161b5fa3c8241a34961b378501247fb3978e6dc Author: Po Lu Date: Thu Jun 30 09:45:49 2022 +0800 Fix preservation of the original value of PRIMARY after dropping on xterm * src/xselect.c (x_own_selection): New arg `dnd_data'. Record it. (x_get_local_selection, x_handle_selection_request) (x_convert_selection): Convert the DND data instead if the situation warrants. (Fx_own_selection_internal, Fx_get_selection_internal) (Fx_get_local_selection): Update calls to x_get_local_selection. * src/xterm.c (x_dnd_do_unsupported_drop): If obtaining selection ownership failed, return. Record DND value and preserve the current value of PRIMARY, if it exists. * src/xterm.h: Update prototypes. diff --git a/src/xselect.c b/src/xselect.c index 5796b0034a..41fa837c5a 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -47,7 +47,7 @@ struct selection_data; static void x_decline_selection_request (struct selection_input_event *); static bool x_convert_selection (Lisp_Object, Lisp_Object, Atom, bool, - struct x_display_info *); + struct x_display_info *, bool); static bool waiting_for_other_props_on_window (Display *, Window); static struct prop_location *expect_property_change (Display *, Window, Atom, int); @@ -250,20 +250,26 @@ x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) /* Do protocol to assert ourself as a selection owner. FRAME shall be the owner; it must be a valid X frame. + TIMESTAMP should be the timestamp where selection ownership will be + assumed. + DND_DATA is the local value that will be used for selection requests + with `pending_dnd_time'. Update the Vselection_alist so that we can reply to later requests for our selection. */ void x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, - Lisp_Object frame) + Lisp_Object frame, Lisp_Object dnd_data, Time timestamp) { struct frame *f = XFRAME (frame); Window selecting_window = FRAME_X_WINDOW (f); struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Display *display = dpyinfo->display; - Time timestamp = dpyinfo->last_user_time; Atom selection_atom = symbol_to_x_atom (dpyinfo, selection_name); + if (!timestamp) + timestamp = dpyinfo->last_user_time; + block_input (); x_catch_errors (display); XSetSelectionOwner (display, selection_atom, selecting_window, timestamp); @@ -276,8 +282,9 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, Lisp_Object selection_data; Lisp_Object prev_value; - selection_data = list4 (selection_name, selection_value, - INT_TO_INTEGER (timestamp), frame); + selection_data = list5 (selection_name, selection_value, + INT_TO_INTEGER (timestamp), frame, + dnd_data); prev_value = LOCAL_SELECTION (selection_name, dpyinfo); tset_selection_alist @@ -310,12 +317,15 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, If LOCAL_VALUE is non-nil, use it as the local copy. Also allow quitting in that case, and let DPYINFO be NULL. + If NEED_ALTERNATE is true, use the drag-and-drop local value + instead. + This calls random Lisp code, and may signal or gc. */ static Lisp_Object x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, bool local_request, struct x_display_info *dpyinfo, - Lisp_Object local_value) + Lisp_Object local_value, bool need_alternate) { Lisp_Object tem; Lisp_Object handler_fn, value, check; @@ -354,7 +364,10 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, if (CONSP (handler_fn)) handler_fn = XCDR (handler_fn); - tem = XCAR (XCDR (local_value)); + if (!need_alternate) + tem = XCAR (XCDR (local_value)); + else + tem = XCAR (XCDR (XCDR (XCDR (XCDR (local_value))))); if (STRINGP (tem)) { @@ -788,7 +801,7 @@ x_handle_selection_request (struct selection_input_event *event) Lisp_Object local_selection_data; bool success = false; specpdl_ref count = SPECPDL_INDEX (); - bool pushed; + bool pushed, use_alternate; Lisp_Object alias, tem; alias = Vx_selection_alias_alist; @@ -814,14 +827,6 @@ x_handle_selection_request (struct selection_input_event *event) if (!dpyinfo) goto REALLY_DONE; - /* This is how the XDND protocol recommends dropping text onto a - target that doesn't support XDND. */ - if (SELECTION_EVENT_TIME (event) == pending_dnd_time + 1 - || SELECTION_EVENT_TIME (event) == pending_dnd_time + 2) - /* Always reply with the contents of PRIMARY, since that's where - the selection data is. */ - selection_symbol = QPRIMARY; - local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo); /* Decline if we don't own any selections. */ @@ -834,6 +839,14 @@ x_handle_selection_request (struct selection_input_event *event) && local_selection_time > SELECTION_EVENT_TIME (event)) goto DONE; + use_alternate = false; + + /* This is how the XDND protocol recommends dropping text onto a + target that doesn't support XDND. */ + if (SELECTION_EVENT_TIME (event) == pending_dnd_time + 1 + || SELECTION_EVENT_TIME (event) == pending_dnd_time + 2) + use_alternate = true; + block_input (); pushed = true; x_push_current_selection_request (event, dpyinfo); @@ -874,7 +887,8 @@ x_handle_selection_request (struct selection_input_event *event) if (subproperty != None) subsuccess = x_convert_selection (selection_symbol, subtarget, - subproperty, true, dpyinfo); + subproperty, true, dpyinfo, + use_alternate); if (!subsuccess) ASET (multprop, 2*j+1, Qnil); } @@ -891,7 +905,8 @@ x_handle_selection_request (struct selection_input_event *event) property = SELECTION_EVENT_TARGET (event); success = x_convert_selection (selection_symbol, target_symbol, property, - false, dpyinfo); + false, dpyinfo, + use_alternate); } DONE: @@ -926,7 +941,8 @@ x_handle_selection_request (struct selection_input_event *event) static bool x_convert_selection (Lisp_Object selection_symbol, Lisp_Object target_symbol, Atom property, - bool for_multiple, struct x_display_info *dpyinfo) + bool for_multiple, struct x_display_info *dpyinfo, + bool use_alternate) { Lisp_Object lisp_selection; struct selection_data *cs; @@ -934,7 +950,7 @@ x_convert_selection (Lisp_Object selection_symbol, lisp_selection = x_get_local_selection (selection_symbol, target_symbol, - false, dpyinfo, Qnil); + false, dpyinfo, Qnil, use_alternate); frame = selection_request_stack; @@ -2100,7 +2116,7 @@ On Nextstep, FRAME is unused. */) CHECK_SYMBOL (selection); if (NILP (value)) error ("VALUE may not be nil"); - x_own_selection (selection, value, frame); + x_own_selection (selection, value, frame, Qnil, 0); return value; } @@ -2150,7 +2166,7 @@ On Nextstep, TIME-STAMP and TERMINAL are unused. */) } val = x_get_local_selection (selection_symbol, target_type, true, - FRAME_DISPLAY_INFO (f), Qnil); + FRAME_DISPLAY_INFO (f), Qnil, false); if (NILP (val) && FRAME_LIVE_P (f)) { @@ -2318,7 +2334,7 @@ run. */) check_window_system (decode_live_frame (frame)); result = x_get_local_selection (name, target, true, - NULL, value); + NULL, value, false); if (CONSP (result) && SYMBOLP (XCAR (result))) { diff --git a/src/xterm.c b/src/xterm.c index 76da1064eb..9d260ded83 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3798,7 +3798,14 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, { XEvent event; int dest_x, dest_y; - Window child_return, child; + Window child_return, child, owner; + Lisp_Object current_value; + struct frame *f; + + f = decode_window_system_frame (frame); + + if (NILP (value)) + return; event.xbutton.serial = 0; event.xbutton.send_event = True; @@ -3806,7 +3813,6 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, event.xbutton.root = dpyinfo->root_window; event.xbutton.x_root = root_x; event.xbutton.y_root = root_y; - x_catch_errors (dpyinfo->display); child = dpyinfo->root_window; @@ -3819,11 +3825,25 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, && child_return != None) child = child_return; - if (CONSP (value)) - x_own_selection (QPRIMARY, Fnth (make_fixnum (1), value), - frame); - else - error ("Lost ownership of XdndSelection"); + if (!CONSP (value)) + goto cancel; + + current_value = assq_no_quit (QPRIMARY, + dpyinfo->terminal->Vselection_alist); + + if (!NILP (current_value)) + current_value = XCAR (XCDR (current_value)); + + x_own_selection (QPRIMARY, current_value, frame, + XCAR (XCDR (value)), before); + + owner = XGetSelectionOwner (dpyinfo->display, XA_PRIMARY); + + /* If we didn't successfully obtain selection ownership, refrain + from generating events that will insert something else. */ + + if (owner != FRAME_X_WINDOW (f)) + goto cancel; event.xbutton.window = child; event.xbutton.subwindow = None; @@ -3847,6 +3867,7 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, XSendEvent (dpyinfo->display, child, True, ButtonReleaseMask, &event); + cancel: x_uncatch_errors (); } diff --git a/src/xterm.h b/src/xterm.h index f7b93529cb..76d35aaf34 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1600,7 +1600,8 @@ extern void x_clipboard_manager_save_all (void); extern Lisp_Object x_timestamp_for_selection (struct x_display_info *, Lisp_Object); extern void x_set_pending_dnd_time (Time); -extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object); +extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object, + Lisp_Object, Time); extern Atom x_intern_cached_atom (struct x_display_info *, const char *, bool); extern char *x_get_atom_name (struct x_display_info *, Atom, bool *) commit d7dc8c5fe4ac1735a7565473621d7504cc5ef089 Author: Thomas Fitzsimmons Date: Wed Jun 29 21:37:57 2022 -0400 EUDC: Prevent field overlap when query form is reset * lisp/net/eudc.el (eudc-query-form): Delete all overlays before erasing buffer. Remove widget-after-change from after-change-functions. diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el index 1d9dbbeb75..fc35d6a084 100644 --- a/lisp/net/eudc.el +++ b/lisp/net/eudc.el @@ -1026,7 +1026,10 @@ queries the server for the existing fields and displays a corresponding form." pt) (switch-to-buffer buffer) (let ((inhibit-read-only t)) + (remove-hook 'after-change-functions 'widget-after-change t) + (delete-all-overlays) (erase-buffer) + (add-hook 'after-change-functions 'widget-after-change nil t) (kill-all-local-variables) (make-local-variable 'eudc-form-widget-list) (widget-insert "Directory Query Form\n") commit 6f22631a63e95c8264c5eda269e12400a1bcb9ca Author: Stefan Monnier Date: Wed Jun 29 13:41:59 2022 -0400 * doc/emacs/buffers.texi (Indirect Buffers): Mention modification hook quirk diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi index 8a8584689f..a1ad4926be 100644 --- a/doc/emacs/buffers.texi +++ b/doc/emacs/buffers.texi @@ -616,10 +616,11 @@ select it in another window (@code{clone-indirect-buffer-other-window}). The text of the indirect buffer is always identical to the text of its base buffer; changes made by editing either one are visible immediately -in the other. But in all other respects, the indirect buffer and its +in the other. ``Text'' here includes both the characters and their text +properties. But in all other respects, the indirect buffer and its base buffer are completely separate. They can have different names, different values of point, different narrowing, different markers, -different major modes, and different local variables. +different overlays, different major modes, and different local variables. An indirect buffer cannot visit a file, but its base buffer can. If you try to save the indirect buffer, that actually works by saving the @@ -645,6 +646,14 @@ buffer in another window. These functions run the hook named @var{indirect-name} from a buffer @var{base-buffer}, prompting for both using the minibuffer. +Note: When a modification is made to the text of a buffer, the +modification hooks are run only in the base buffer, because most of +the functions on those hooks are not prepared to work correctly in +indirect buffers. So if you need a modification hook function in an +indirect buffer, you need to manually add that function to the hook +@emph{in the base buffer} and then make the function operate in the +desired indirect buffer. + @node Buffer Convenience @section Convenience Features and Customization of Buffer Handling commit fb3d582e7ba595b7680e2c2adf22c7ab699e5792 Author: Eli Zaretskii Date: Wed Jun 29 20:15:36 2022 +0300 Fix hscrolling of :align-to when display-line-numbers is in effect * src/dispextern.h (struct it): Rename 'tab_offset' member to 'stretch_adjust'. * src/xdisp.c (gui_produce_glyphs, produce_stretch_glyph) (display_line): All users of 'tab_offset' changed. (produce_stretch_glyph): Fix calculation of ':align-to' when line numbers are displayed and the window is hscrolled. (calc_pixel_width_or_height): Fix calculation of width of 'space' display property when 'display-line-numbers' is turned on, but the line number was not yet produced for the current glyph row. (Bug#56176) diff --git a/src/dispextern.h b/src/dispextern.h index 9dec8b7d12..ca7834dec5 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -2742,11 +2742,11 @@ struct it /* The line number of point's line, or zero if not computed yet. */ ptrdiff_t pt_lnum; - /* Number of pixels to offset tab stops due to width fixup of the - first glyph that crosses first_visible_x. This is only needed on - GUI frames, only when display-line-numbers is in effect, and only - in hscrolled windows. */ - int tab_offset; + /* Number of pixels to adjust tab stops and stretch glyphs due to + width fixup of the first stretch glyph that crosses first_visible_x. + This is only needed on GUI frames, only when display-line-numbers + is in effect, and only in hscrolled windows. */ + int stretch_adjust; /* Left fringe bitmap number (enum fringe_bitmap_type). */ unsigned left_user_fringe_bitmap : FRINGE_ID_BITS; diff --git a/src/xdisp.c b/src/xdisp.c index a46fe99830..4089525e10 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -24183,7 +24183,7 @@ display_line (struct it *it, int cursor_vpos) row->displays_text_p = true; row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p; it->starts_in_middle_of_char_p = false; - it->tab_offset = 0; + it->stretch_adjust = 0; it->line_number_produced_p = false; /* Arrange the overlays nicely for our purposes. Usually, we call @@ -28371,6 +28371,11 @@ static bool calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, struct font *font, bool width_p, int *align_to) { + /* Don't adjust for line number if we didn't yet produce it for this + screen line. This is for when this function is called from + move_it_in_display_line_to that was called by display_line to get + past the glyphs hscrolled off the left side of the window. */ + int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0; double pixels; # define OK_PIXELS(val) (*res = (val), true) @@ -28427,7 +28432,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, if (EQ (prop, Qtext)) return OK_PIXELS (width_p ? (window_box_width (it->w, TEXT_AREA) - - it->lnum_pixel_width) + - lnum_pixel_width) : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w)); /* ':align_to'. First time we compute the value, window @@ -28439,14 +28444,14 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, /* 'left': left edge of the text area. */ if (EQ (prop, Qleft)) return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA) - + it->lnum_pixel_width); + + lnum_pixel_width); /* 'right': right edge of the text area. */ if (EQ (prop, Qright)) return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA)); /* 'center': the center of the text area. */ if (EQ (prop, Qcenter)) return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA) - + it->lnum_pixel_width + + lnum_pixel_width + window_box_width (it->w, TEXT_AREA) / 2); /* 'left-fringe': left edge of the left fringe. */ if (EQ (prop, Qleft_fringe)) @@ -28499,7 +28504,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, ? FRAME_COLUMN_WIDTH (it->f) : FRAME_LINE_HEIGHT (it->f)); if (width_p && align_to && *align_to < 0) - return OK_PIXELS (XFLOATINT (prop) * base_unit + it->lnum_pixel_width); + return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width); return OK_PIXELS (XFLOATINT (prop) * base_unit); } @@ -28561,7 +28566,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, { double fact; int offset = - width_p && align_to && *align_to < 0 ? it->lnum_pixel_width : 0; + width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0; pixels = XFLOATINT (car); if (NILP (cdr)) return OK_PIXELS (pixels + offset); @@ -30778,13 +30783,39 @@ produce_stretch_glyph (struct it *it) && calc_pixel_width_or_height (&tem, it, prop, font, true, &align_to)) { + int x = it->current_x + it->continuation_lines_width; + int x0 = x; + /* Adjust for line numbers, if needed. */ + if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) + { + x -= it->lnum_pixel_width; + /* Restore the original width, if required. */ + if (x + it->stretch_adjust >= it->first_visible_x) + x += it->stretch_adjust; + } + if (it->glyph_row == NULL || !it->glyph_row->mode_line_p) align_to = (align_to < 0 ? 0 : align_to - window_box_left_offset (it->w, TEXT_AREA)); else if (align_to < 0) align_to = window_box_left_offset (it->w, TEXT_AREA); - width = max (0, (int)tem + align_to - it->current_x); + width = max (0, (int)tem + align_to - x); + + int next_x = x + width; + if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) + { + /* If the line is hscrolled, and the stretch starts before + the first visible pixel, simulate negative row->x. */ + if (x < it->first_visible_x) + { + next_x -= it->first_visible_x - x; + it->stretch_adjust = it->first_visible_x - x; + } + else + next_x -= it->stretch_adjust; + } + width = next_x - x0; zero_width_ok_p = true; } else @@ -31574,8 +31605,8 @@ gui_produce_glyphs (struct it *it) { x -= it->lnum_pixel_width; /* Restore the original TAB width, if required. */ - if (x + it->tab_offset >= it->first_visible_x) - x += it->tab_offset; + if (x + it->stretch_adjust >= it->first_visible_x) + x += it->stretch_adjust; } int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; @@ -31593,10 +31624,10 @@ gui_produce_glyphs (struct it *it) if (x < it->first_visible_x) { next_tab_x -= it->first_visible_x - x; - it->tab_offset = it->first_visible_x - x; + it->stretch_adjust = it->first_visible_x - x; } else - next_tab_x -= it->tab_offset; + next_tab_x -= it->stretch_adjust; } it->pixel_width = next_tab_x - x0; commit aee101af911655ff3dd7a4e032ee5366ce533578 Author: Stefan Monnier Date: Wed Jun 29 11:47:24 2022 -0400 * lisp/vc/diff-mode.el (diff--font-lock-prettify): Fix `diff-buffers` case diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 0fd67422d5..3f3e503a3f 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -2682,7 +2682,17 @@ fixed, visit it in a buffer." ((and (null (match-string 4)) (match-string 5)) (concat "New " kind filemode newfile)) ((null (match-string 2)) - (concat "Deleted" kind filemode oldfile)) + ;; We used to use + ;; (concat "Deleted" kind filemode oldfile) + ;; here but that misfires for `diff-buffers' + ;; (see 24 Jun 2022 message in bug#54034). + ;; AFAIK if (match-string 2) is nil then so is + ;; (match-string 1), so "Deleted" doesn't sound right, + ;; so better just let the header in plain sight for now. + ;; FIXME: `diff-buffers' should maybe try to better + ;; mimic Git's format with "a/" and "b/" so prettification + ;; can "just work!" + nil) (t (concat "Modified" kind filemode oldfile))) 'face '(diff-file-header diff-header)) commit e4df6203e27fbb4458fda21f029f90a114465c1a Author: Mattias Engdegård Date: Wed Jun 29 17:18:04 2022 +0200 More robust `gnu` pattern (bug#56249) * lisp/progmodes/compile.el (compilation-error-regexp-alist-alist): Don't allow spaces in the file names, to avoid false matches. Don't allow ad-hoc spaces preceding the program name either. diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 3393aa9b63..db57093559 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -368,17 +368,18 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1)) ;; Match an optional program name which is used for ;; non-interactive programs other than compilers (e.g. the ;; "jade:" entry in compilation.txt). - (? (: (* " ") ; Allow space to precede the program name. - (| (: alpha (+ (in ?. ?- alnum)) ":" (? " ")) - ;; Skip indentation generated by GCC's -fanalyzer. - (: (+ " ") "|")))) + (? (| (: alpha (+ (in ?. ?- alnum)) ":" (? " ")) + ;; Skip indentation generated by GCC's -fanalyzer. + (: (+ " ") "|"))) ;; File name group. (group-n 1 ;; Avoid matching the file name as a program in the pattern ;; above by disallowing file names entirely composed of digits. - (* (in "0-9")) - (not (in "0-9" "\n")) + ;; Do not allow file names beginning with a space. + (| (not (in "0-9" "\n\t ")) + (: (+ (in "0-9")) + (not (in "0-9" "\n")))) ;; A file name can be composed of any non-newline char, but ;; rule out some valid but unlikely cases, such as a trailing ;; space or a space followed by a -, or a colon followed by a commit d462c8133bfb9ac9325228184e5dcf0c9b7011cc Author: Mattias Engdegård Date: Wed Jun 29 12:34:39 2022 +0200 Complete transition to rx for compilation `gnu` pattern * lisp/progmodes/compile.el (compilation-error-regexp-alist-alist): Change from a mixture of traditional regexp syntax and rx, to make intentions clearer. diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 28a49fc0dd..3393aa9b63 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -359,12 +359,15 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1)) ": \\*\\*\\* \\[\\(\\(.+?\\):\\([0-9]+\\): .+\\)\\]" 2 3 nil 0 1) (gnu + ;; The `gnu' message syntax is + ;; [PROGRAM:]FILE:LINE[-ENDLINE]:[COL[-ENDCOL]:] MESSAGE + ;; or + ;; [PROGRAM:]FILE:LINE[.COL][-ENDLINE[.ENDCOL]]: MESSAGE ,(rx bol - ;; Match an optional program name in the format - ;; PROGRAM:SOURCE-FILE-NAME:LINENO: MESSAGE - ;; which is used for non-interactive programs other than - ;; compilers (e.g. the "jade:" entry in compilation.txt). + ;; Match an optional program name which is used for + ;; non-interactive programs other than compilers (e.g. the + ;; "jade:" entry in compilation.txt). (? (: (* " ") ; Allow space to precede the program name. (| (: alpha (+ (in ?. ?- alnum)) ":" (? " ")) ;; Skip indentation generated by GCC's -fanalyzer. @@ -372,54 +375,56 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1)) ;; File name group. (group-n 1 - ;; Avoid matching the file name as a program in the pattern - ;; above by disallow file names entirely composed of digits. - (: (regexp "[0-9]*[^0-9\n]") - ;; This rule says that a file name can be composed - ;; of any non-newline char, but it also rules out - ;; some valid but unlikely cases, such as a - ;; trailing space or a space followed by a -, or a - ;; colon followed by a space. - (*? (| (regexp "[^\n :]") - (regexp " [^-/\n]") - (regexp ":[^ \n]"))))) - (regexp ": ?") + ;; Avoid matching the file name as a program in the pattern + ;; above by disallowing file names entirely composed of digits. + (* (in "0-9")) + (not (in "0-9" "\n")) + ;; A file name can be composed of any non-newline char, but + ;; rule out some valid but unlikely cases, such as a trailing + ;; space or a space followed by a -, or a colon followed by a + ;; space. + (*? (| (not (in "\n :")) + (: " " (not (in ?- "/\n"))) + (: ":" (not (in " \n")))))) + ":" (? " ") ;; Line number group. - (group-n 2 (regexp "[0-9]+")) + (group-n 2 (+ (in "0-9"))) (? (| (: "-" - (group-n 4 (regexp "[0-9]+")) ; ending line - (? "." (group-n 5 (regexp "[0-9]+")))) ; ending column + (group-n 4 (+ (in "0-9"))) ; ending line + (? "." (group-n 5 (+ (in "0-9"))))) ; ending column (: (in ".:") - (group-n 3 (regexp "[0-9]+")) ; starting column + (group-n 3 (+ (in "0-9"))) ; starting column (? "-" - (? (group-n 4 (regexp "[0-9]+")) ".") ; ending line - (group-n 5 (regexp "[0-9]+")))))) ; ending column + (? (group-n 4 (+ (in "0-9"))) ".") ; ending line + (group-n 5 (+ (in "0-9"))))))) ; ending column ":" (| (: (* " ") (group-n 6 (| "FutureWarning" "RuntimeWarning" - "Warning" - "warning" + "Warning" "warning" "W:"))) (: (* " ") - (group-n 7 (| (regexp "[Ii]nfo\\(?:\\>\\|rmationa?l?\\)") - "I:" - (: "[ skipping " (+ nonl) " ]") - "instantiated from" - "required from" - (regexp "[Nn]ote")))) + (group-n 7 + (| (| "Info" "info" + "Information" "information" + "Informational" "informational" + "I:" + "instantiated from" + "required from" + "Note" "note") + (: "[ skipping " (+ nonl) " ]")))) (: (* " ") - (regexp "[Ee]rror")) + (| "Error" "error")) ;; Avoid matching time stamps on the form "HH:MM:SS" where ;; MM is interpreted as a line number by trying to rule out ;; messages where the text after the line number starts with ;; a 2-digit number. - (: (regexp "[0-9]?") - (| (regexp "[^0-9\n]") + (: (? (in "0-9")) + (| (not (in "0-9\n")) eol)) - (regexp "[0-9][0-9][0-9]"))) + (: (in "0-9") (in "0-9") (in "0-9")))) 1 (2 . 4) (3 . 5) (6 . 7)) (cucumber commit 3447e79f2493580864962db69859bda1afd4643b Author: Mattias Engdegård Date: Wed Jun 29 11:01:16 2022 +0200 * lisp/emacs-lisp/rx.el: Indent some rx constructs correctly. This includes group-n, submatch-n, =, >=, ** and repeat, whose first 1 or 2 arguments are special. diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el index aa2486b47e..07ede57d39 100644 --- a/lisp/emacs-lisp/rx.el +++ b/lisp/emacs-lisp/rx.el @@ -1110,6 +1110,14 @@ can expand to any number of values." (append rx--builtin-forms rx--builtin-symbols) "List of built-in rx names. These cannot be redefined by the user.") +;; Declare Lisp indentation rules for constructs that take 1 or 2 +;; parameters before a body of RX forms. +(dolist (sym '( group-n submatch-n = >=)) + (put sym 'lisp-indent-function 1)) +(dolist (sym '( ** repeat)) + (put sym 'lisp-indent-function 2)) + + (defun rx--translate (item) "Translate the rx-expression ITEM. Return (REGEXP . PRECEDENCE)." (cond commit 3bd232ab39d1e479bc4654539bfb15a7ad86c643 Author: Stefan Kangas Date: Wed Jun 29 16:13:51 2022 +0200 ; Manually sync ChangeLog and AUTHORS with emacs-28 * ChangeLog.3: * etc/AUTHORS: Manually sync with emacs-28 to fix merge errors. diff --git a/ChangeLog.3 b/ChangeLog.3 index c02fb67805..d0ff14117b 100644 --- a/ChangeLog.3 +++ b/ChangeLog.3 @@ -5,7 +5,7 @@ * doc/misc/trampver.texi: * lisp/net/trampver.el: Change version to "2.5.3". -2022-06-29 Michael Albinus +2022-06-28 Michael Albinus Tramp shall not trap unrelated D-Bus errors @@ -14,7 +14,7 @@ (tramp-gvfs-dbus-event-vector): Fix docstring. (tramp-gvfs-maybe-open-connection): Do not set it globally. (Bug#56162) -2022-06-29 Basil L. Contovounesios +2022-06-28 Basil L. Contovounesios Fix hash table function return values in manual @@ -22,17 +22,17 @@ values of puthash and clrhash with their respective docstrings (bug#55562). -2022-06-29 Kyle Meyer +2022-06-27 Kyle Meyer Update to Org 9.5.4-3-g6dc785 -2022-06-29 Paul Eggert +2022-06-27 Paul Eggert Mention Solaris 10 'make clean' and 'make check' Mention further crashes on Solaris 10 -2022-06-29 Paul Eggert +2022-06-26 Paul Eggert Port distribution tarball to Solaris 10 @@ -47,32 +47,32 @@ (cherry picked from commit 4410f5d86997b6b238ff05c2ece338b28e1163b1) -2022-06-29 Stefan Kangas +2022-06-24 Stefan Kangas Avoid treating number as an enum in the org manual * doc/misc/org.org (The Agenda Dispatcher): Avoid treating number as enum. -2022-06-29 Eli Zaretskii +2022-06-22 Eli Zaretskii Improve last change in autotype.texi * doc/misc/autotype.texi (Autoinserting): Fix wording. Suggested by Richard Stallman . -2022-06-29 Stefan Kangas +2022-06-21 Stefan Kangas * lisp/repeat.el (repeat-mode): Fix message format. -2022-06-29 Earl Hyatt +2022-06-21 Earl Hyatt Clarify autotype.texi text slightly * doc/misc/autotype.texi (Autoinserting): Make text slightly clearer (bug#56118). -2022-06-29 Eli Zaretskii +2022-06-20 Eli Zaretskii Support builds configured with a separate --bindir @@ -82,11 +82,11 @@ This is needed to support builds with a separate --bindir configure-time option and native-compilation. (Bug#55741) -2022-06-29 Stefan Kangas +2022-06-20 Stefan Kangas * doc/misc/eww.texi (Overview, Basics): Fix typos. -2022-06-29 Richard Hansen +2022-06-18 Richard Hansen Fix invalid defcustom :group when :predicate is used @@ -94,14 +94,14 @@ invalid `:group' argument for the `-modes' defcustom that is created when `:predicate' is used (bug#56049). -2022-06-29 Lars Ingebrigtsen +2022-06-17 Lars Ingebrigtsen Prune the Gnus FAQ of some outdated data * doc/misc/gnus-faq.texi (FAQ 9-2): Remove some outdated advice (bug#56042). -2022-06-29 Lars Ingebrigtsen +2022-06-17 Lars Ingebrigtsen Fix efaq-w32.texi build warning @@ -110,43 +110,43 @@ Do not merge to master. -2022-06-29 Lars Ingebrigtsen +2022-06-17 Lars Ingebrigtsen Update cl-struct-sequence-type doc string * lisp/emacs-lisp/cl-macs.el (cl-struct-sequence-type): Fix doc string to reflect what it does (bug#46523). -2022-06-29 Lars Ingebrigtsen +2022-06-17 Lars Ingebrigtsen Fix a tagging problem in tramp.texi * doc/misc/tramp.texi (Frequently Asked Questions): Restore an @end lisp removed by accident. -2022-06-29 Lars Ingebrigtsen +2022-06-17 Lars Ingebrigtsen Mention face quirks after the final line in the lispref manual * doc/lispref/display.texi (Face Attributes): Mention the quirks about point after the final line (bug#56011). -2022-06-29 Stefan Kangas +2022-06-17 Stefan Kangas Delete reference to obsolete library complete.el * doc/misc/tramp.texi (Frequently Asked Questions): Delete reference to obsolete library complete.el. -2022-06-29 Stefan Kangas +2022-06-16 Stefan Kangas * lisp/textmodes/artist.el: Minor doc fixes. -2022-06-29 Michael Albinus +2022-06-16 Michael Albinus * lisp/net/tramp.el (tramp-methods): Fix quoting in docstring. -2022-06-29 Arash Esbati +2022-06-16 Arash Esbati Update MS Windows FAQ for MinGW64-w64/MSYS2 @@ -161,14 +161,14 @@ Fix link for MinGW homepage. Remove entry for defunct UWIN project. (Bug#55930) -2022-06-29 Robert Pluim +2022-06-15 Robert Pluim Describe 'set-file-modes' argument prompting * src/fileio.c (Fset_file_modes): Document that FILENAME is prompted for. (Bug#55984) -2022-06-29 Lars Ingebrigtsen +2022-06-14 Lars Ingebrigtsen Revert "Clarify what a Calc registeri in in calc-insert-register" @@ -176,21 +176,21 @@ This has been fixed in Emacs 29 by making it possible to use regular registers in calc. -2022-06-29 Lars Ingebrigtsen +2022-06-13 Lars Ingebrigtsen Clarify what a Calc registeri in in calc-insert-register * lisp/calc/calc-yank.el (calc-insert-register): Note that these aren't normal registers (bug#55943). -2022-06-29 Eli Zaretskii +2022-06-11 Eli Zaretskii Fix doc strings in whitespace.el * lisp/whitespace.el (whitespace-style, whitespace-action): Untabify the doc strings. (Bug#55904) -2022-06-29 Eli Zaretskii +2022-06-10 Eli Zaretskii Improve documentation of "etags -I" @@ -198,14 +198,14 @@ * doc/emacs/maintaining.texi (Create Tags Table): Elaborate on the importance of the '-I' option to 'etags'. (Bug#45246) -2022-06-29 Lars Ingebrigtsen +2022-06-09 Lars Ingebrigtsen Mention the #f syntax from cl-prin1 * doc/lispref/objects.texi (Special Read Syntax): Mention #f, which is in cl-prin1 output (bug#55853). -2022-06-29 Michael Albinus +2022-06-09 Michael Albinus Fix file name quoting in tramp-smb.el (do not merge) @@ -215,13 +215,13 @@ * test/lisp/net/tramp-tests.el (tramp-test03-file-name-method-rules): Remove superfluous checks. -2022-06-29 Jeff Walsh +2022-06-09 Jeff Walsh Update error message to reflect variable rename * src/comp.c (Fcomp_el_to_eln_filename): Update error message. (Bug#55861) -2022-06-29 Ken Brown +2022-06-08 Ken Brown Fix error reporting in process-async-https-with-delay @@ -229,18 +229,18 @@ 'plist-get' instead of 'assq' in testing for a connection error. The 'status' variable is a plist, not an alist. (Bug#55849) -2022-06-29 Stefan Kangas +2022-06-08 Stefan Kangas * doc/misc/org.org: Remove spurious markup. -2022-06-29 Michael Albinus +2022-06-08 Michael Albinus Make Tramp version check more robust * lisp/net/trampver.el (tramp-repository-branch) (tramp-repository-version): Check for "git" executable. -2022-06-29 Eli Zaretskii +2022-06-07 Eli Zaretskii Fix debugging with GDB when a breakpoint has multiple locations @@ -252,7 +252,7 @@ also any locations in multiple-location breakpoints, which are supported since GDB 6.8. -2022-06-29 Eli Zaretskii +2022-06-05 Eli Zaretskii Update documentation of 'aset' and 'store-substring' @@ -261,11 +261,11 @@ have fewer or more bytes than the original. Add recommendations regarding unibyte vs multibyte strings and characters. (Bug#55801) -2022-06-29 Kyle Meyer +2022-06-04 Kyle Meyer Update to Org 9.5.4 -2022-06-29 Eli Zaretskii +2022-06-04 Eli Zaretskii Clarify documentation of 'string-to-unibyte' @@ -273,7 +273,7 @@ what 'string-to-unibyte' does. Reported by Richard Hansen . (Bug#55777) -2022-06-29 Ikumi Keita (tiny change) +2022-06-02 Ikumi Keita (tiny change) Improve keystrokes in doc strings in some find-file functions @@ -282,7 +282,7 @@ (find-file-other-frame): Include the correct keymap so that keystrokes are displayed better (bug#55761). -2022-06-29 Eli Zaretskii +2022-06-02 Eli Zaretskii Fix segfaults when starting on 80x26 TTY frames @@ -292,7 +292,7 @@ (adjust_frame_glyphs): Add assertions for when we fail to allocate valid frame glyph matrices for a TTY frame. -2022-06-29 Lars Ingebrigtsen +2022-06-01 Lars Ingebrigtsen Make it explicit that a couple of _s in lispref are underscores @@ -300,7 +300,7 @@ * doc/lispref/control.texi (pcase Macro): Make it explicit that it's an underscore (bug#55742). -2022-06-29 Eli Zaretskii +2022-05-31 Eli Zaretskii Remove from FAQ the MS-Windows info about BDF fonts @@ -308,14 +308,14 @@ specific steps, as BDF fonts are no longer supported on MS-Windows. (Bug#55740) -2022-06-29 Ikumi Keita (tiny change) +2022-05-31 Ikumi Keita (tiny change) Fix Display Property manual example * doc/lispref/display.texi (Display Property): Fix syntax of example (bug#55736). -2022-06-29 Michael Albinus +2022-05-29 Michael Albinus Some Tramp cleanup on MS Windows @@ -325,7 +325,7 @@ * test/lisp/net/tramp-tests.el (tramp-test31-interrupt-process): Skip on MS Windows. -2022-06-29 Alan Mackenzie +2022-05-28 Alan Mackenzie do_switch_frame: before leaving mini-window, check other (mru) window is live @@ -339,7 +339,7 @@ this ostensible window is an actual live window. Otherwise leave the mini-window selected. -2022-06-29 Eli Zaretskii +2022-05-28 Eli Zaretskii Fix commands used to produce on-line HTML docs @@ -352,28 +352,28 @@ Reported by "Facundo Lander via RT" , see gnu.org ticket #1840138. -2022-06-29 Eli Zaretskii +2022-05-28 Eli Zaretskii Fix a bad cross-reference in elisp.pdf * doc/lispref/control.texi (pcase Macro): Fix a conditional cross-reference (bug#55689). -2022-06-29 Eli Zaretskii +2022-05-28 Eli Zaretskii Fix documentation of 'string-pad' * doc/lispref/strings.texi (Creating Strings): Fix description of 'string-pad'. (Bug#55688) -2022-06-29 Juri Linkov +2022-05-27 Juri Linkov Fix more occurrences of renamed kmacro-keymap command * doc/emacs/kmacro.texi (Basic Keyboard Macro): Fix documentation after recent kmacro-redisplay command name change. -2022-06-29 Eli Zaretskii +2022-05-27 Eli Zaretskii Mention "unspecified-fg" and "unspecified-bg" in some doc strings @@ -382,14 +382,14 @@ * lisp/color.el (color-name-to-rgb): Mention "unspecified-fg" and "unspecified-bg" pseudo-colors on TTY frames. (Bug#55623) -2022-06-29 Hayden Shenk (tiny change) +2022-05-26 Hayden Shenk (tiny change) Fix format specifiers in tramp-adb.el * lisp/net/tramp-adb.el (tramp-adb-get-device): Fix format specifiers for port. (Bug#55651) -2022-06-29 Damien Cassou +2022-05-22 Damien Cassou Improve documentation of mail-user-agent. @@ -397,28 +397,28 @@ * lisp/simple.el (mail-user-agent): Mention additional options of non-bundled MUA. (Bug#5569) -2022-06-29 Eli Zaretskii +2022-05-21 Eli Zaretskii More fixes in abbrev.el doc strings * lisp/abbrev.el (inverse-add-global-abbrev, inverse-add-mode-abbrev): Document the effect of negative ARG. (Bug#55527) -2022-06-29 Lars Ingebrigtsen +2022-05-21 Lars Ingebrigtsen Add note about Tramp completion to completion-styles doc string * lisp/minibuffer.el (completion-styles): Add note about Tramp completion (bug#37954). -2022-06-29 Arash Esbati +2022-05-21 Arash Esbati Remove mention of removed nnimap-nov-is-evil variable * doc/misc/gnus.texi (Slow/Expensive Connection): Remove mention of removed nnimap-nov-is-evil variable (bug#55556). -2022-06-29 Eli Zaretskii +2022-05-21 Eli Zaretskii Improve documentation strings and prompts in abbrev.el @@ -444,7 +444,7 @@ (add-abbrev, inverse-add-abbrev): Improve the prompt text. (Bug#55527) -2022-06-29 Alan Mackenzie +2022-05-20 Alan Mackenzie Restore the Fselect_window call in gui_consider_frame_title. @@ -467,28 +467,28 @@ * src/xdisp.c (gui_consider_frame_title): Replace the Fselect_window call and associated ancillary settings. -2022-06-29 Eli Zaretskii +2022-05-20 Eli Zaretskii Advise against settings in the MS-Windows system registry * doc/emacs/cmdargs.texi (MS-Windows Registry): Advise against setting environment variables in the system registry. (Bug#16429) -2022-06-29 Lars Ingebrigtsen +2022-05-17 Lars Ingebrigtsen Fix kmacro-keymap binding after previous change * lisp/kmacro.el (kmacro-keymap): Fix binding after kmacro-redisplay command name change. -2022-06-29 Lars Ingebrigtsen +2022-05-17 Lars Ingebrigtsen Add glossary entries for "interactively" * doc/emacs/glossary.texi (Glossary): Mention "interactively" and how it relates to the "command" concept (bug#55461). -2022-06-29 Eli Zaretskii +2022-05-17 Eli Zaretskii Fix the name of a kmacro command. @@ -497,7 +497,7 @@ * etc/NEWS: Announce the change. (Bug#55471) -2022-06-29 Michael Albinus +2022-05-17 Michael Albinus Fix Tramp sshfs tests (don't merge) @@ -507,7 +507,7 @@ (tramp-test26-file-name-completion, tramp--test-check-files): Use it. (tramp--test-check-files): Delete directory recursively. -2022-06-29 Michael Albinus +2022-05-17 Michael Albinus Some minor Tramp fixes @@ -520,11 +520,11 @@ * lisp/net/tramp-gvfs.el (tramp-gvfs-handler-askquestion): Keep regression tests running. -2022-06-29 Kyle Meyer +2022-05-15 Kyle Meyer Update to Org 9.5.3-6-gef41f3 -2022-06-29 Michael Albinus +2022-05-15 Michael Albinus Hide temporary FUSE files in Tramp @@ -532,18 +532,18 @@ (tramp-fuse-handle-directory-files) (tramp-fuse-handle-file-name-all-completions): Use it. -2022-06-29 Michael Albinus +2022-05-15 Michael Albinus * test/lisp/net/tramp-tests.el (tramp-test27-load): Adapt test. Don't merge -2022-06-29 Po Lu +2022-05-13 Po Lu Fix tooltip face overwriting dragged text strings during mouse DND * lisp/mouse.el (mouse-drag-and-drop-region): Copy `text-tooltip' before showing it. Do not merge to master. -2022-06-29 Eli Zaretskii +2022-05-13 Eli Zaretskii Fix lexical-binding fallout in vhdl-mode.el @@ -553,7 +553,7 @@ (vhdl-speedbar-insert-hierarchy): Rename the PACK-ALIST argument to PACKAGE-ALIST, to avoid shadowing the global variable. -2022-06-29 Michael Albinus +2022-05-12 Michael Albinus Fix ControlPath quoting in Tramp @@ -561,35 +561,35 @@ Adapt docstring. Do not quote ControlPath. Reported by Daniel Kessler . -2022-06-29 Eli Zaretskii +2022-05-09 Eli Zaretskii Remove the AUCTeX subsection from MS-Windows FAQ * doc/misc/efaq-w32.texi (AUCTeX): Remove the subsection, it is no longer useful. (Bug#55330) -2022-06-29 Arash Esbati +2022-05-09 Arash Esbati Update AUCTeX FAQ entry * doc/misc/efaq-w32.texi (AUCTeX): AUCTeX project isn't providing pre-compiled versions for Windows anymore (bug#55330). -2022-06-29 Lars Ingebrigtsen +2022-05-09 Lars Ingebrigtsen Update string-to-number documentation to bignum Emacs * doc/lispref/strings.texi (String Conversion): string-to-number no longer converts integers to floating point numbers (bug#55334). -2022-06-29 Lars Ingebrigtsen +2022-05-09 Lars Ingebrigtsen Fix doc string references to tags-loop-continue * lisp/vc/vc-dir.el (vc-dir-search, vc-dir-query-replace-regexp): Fix reference to obsolete tags-loop-continue (bug#55311). -2022-06-29 Visuwesh M +2022-05-08 Visuwesh M dired-do-query-replace-regexp doc string fix @@ -599,7 +599,7 @@ (cherry picked from commit 4c505203f9171886f47638779326e257a95a1d79) -2022-06-29 Alan Mackenzie +2022-05-08 Alan Mackenzie Linux console: don't translate ESC TAB to `backtab' in input-decode-map. @@ -613,7 +613,7 @@ wrongly doing the same thing as M-TAB, giving tips about amending the Linux keyboard layout. -2022-06-29 Michael Albinus +2022-05-08 Michael Albinus Handle changed scp protocol in Tramp, don't merge @@ -624,21 +624,21 @@ * lisp/net/tramp.el (tramp-methods): Adapt docstring. -2022-06-29 Michael Albinus +2022-05-06 Michael Albinus Fix bug#55274 * lisp/dired-aux.el (dired-do-compress-to): Use `file-local-name' for shell out-file. (Bug#55274) -2022-06-29 Eli Zaretskii +2022-05-06 Eli Zaretskii Provide reference for OTF tags in the ELisp manual * doc/lispref/display.texi (Low-Level Font): Provide the canonical reference URL for OTF tags. -2022-06-29 Lars Ingebrigtsen +2022-05-05 Lars Ingebrigtsen Be more resilient towards errors during error handling @@ -647,7 +647,7 @@ (cherry picked from commit 8364f058b821eba31f84dcded175cca403a965a5) -2022-06-29 Eli Zaretskii +2022-04-28 Eli Zaretskii Improve documentation of font- and face-related attribute functions @@ -662,18 +662,18 @@ (Attribute Functions): Add cross-reference to the description of face attributes. -2022-06-29 Kyle Meyer +2022-04-25 Kyle Meyer Update to Org 9.5.3-3-gd54104 -2022-06-29 Eli Zaretskii +2022-04-24 Eli Zaretskii Improve indexing in "Programmed Completion" * doc/lispref/minibuf.texi (Programmed Completion): Improve indexing. (Bug#55095) -2022-06-29 Eli Zaretskii +2022-04-24 Eli Zaretskii Improve documentation of 'set-fontset-font' @@ -682,21 +682,21 @@ documentation of 'set-fontset-font'. Rename the arguments to be more self-explanatory. (Bug#55086) -2022-06-29 Michael Albinus +2022-04-23 Michael Albinus Fix problem with Solaris ls in Tramp * lisp/net/tramp-sh.el (tramp-sunos-unames): Move up. (tramp-sh--quoting-style-options): Handle erroneous Solaris ls. -2022-06-29 Eli Zaretskii +2022-04-22 Eli Zaretskii Another fix for non-ASCII 'overlay-arrow-string' * src/xdisp.c (get_overlay_arrow_glyph_row): Fix yet another place that assumed each character is a single byte. -2022-06-29 Eli Zaretskii +2022-04-21 Eli Zaretskii Avoid a redisplay loop when 'overlay-arrow-string' is non-ASCII @@ -704,7 +704,7 @@ character in 'overlay-arrow-string' is one byte long. Reported by Yuri D'Elia . -2022-06-29 Eli Zaretskii +2022-04-21 Eli Zaretskii Add minimum instructions to 'query-replace' commands @@ -723,7 +723,7 @@ instructions for dealing with matches, with a link to the command that shows the full instructions. (Bug#55050) -2022-06-29 Eli Zaretskii +2022-04-21 Eli Zaretskii Fix customization-group of 'python-forward-sexp-function' @@ -731,7 +731,7 @@ be part of both 'python' and 'python-flymake' groups. (Bug#55027) Do not merge to master. -2022-06-29 Paul Eggert +2022-04-20 Paul Eggert Update from gnulib @@ -746,7 +746,7 @@ misleading compiler version numbers. See discussion starting at https://lists.gnu.org/archive/html/emacs-devel/2022-04/msg00779.html -2022-06-29 Lars Ingebrigtsen +2022-04-20 Lars Ingebrigtsen Revert prompting changes in viper-cmd @@ -757,7 +757,7 @@ Do not merge to master. -2022-06-29 Lars Ingebrigtsen +2022-04-19 Lars Ingebrigtsen Fix regression with multiple mode: entries in the prop line @@ -766,7 +766,7 @@ Do not merge to master. -2022-06-29 Lars Ingebrigtsen +2022-04-18 Lars Ingebrigtsen Avoid hangs in python-mode with debug-on-error set @@ -777,7 +777,7 @@ Do not merge to master. -2022-06-29 Lars Ingebrigtsen +2022-04-18 Lars Ingebrigtsen Fix major-mode setting regression when there's a mode: cookie @@ -786,11 +786,11 @@ Do not merge to master. -2022-06-29 Kyle Meyer +2022-04-17 Kyle Meyer Update to Org 9.5.2-38-g682ccd -2022-06-29 Eli Zaretskii +2022-04-17 Eli Zaretskii Revert "Don’t assume openat" @@ -802,7 +802,7 @@ for the benefit of a proprietary platform with a 13-year old OS is a tail wagging the dog. Please don't do that without discussing first. -2022-06-29 Paul Eggert +2022-04-17 Paul Eggert Don’t assume openat @@ -818,7 +818,7 @@ (emacs_open_noquit): Reimplement as per the old emacs_openat_noquit, but use plain 'open'. -2022-06-29 Paul Eggert +2022-04-17 Paul Eggert Fix GC bug in filelock.c @@ -834,13 +834,13 @@ (make_lock_file_name): Return the encoded name, not the original. All callers changed. -2022-06-29 Lars Ingebrigtsen +2022-04-16 Lars Ingebrigtsen Clarify when mode tagging is used * etc/NEWS: Clarify when mode tagging is used (bug#54964). -2022-06-29 Lars Ingebrigtsen +2022-04-16 Lars Ingebrigtsen Further vcs-cvs/rcs-responsible-p updates from master @@ -856,7 +856,7 @@ * lisp/vc/vc.el: Update comments. -2022-06-29 Mattias Engdegård +2022-04-16 Mattias Engdegård Fix builds on older versions of macOS @@ -868,7 +868,7 @@ (system_process_attributes): Use alternative code or exclude features when building on older macOS versions. -2022-06-29 Eli Zaretskii +2022-04-16 Eli Zaretskii Fix documentation of Outline minor mode options @@ -876,7 +876,7 @@ (outline-minor-mode-cycle, outline-minor-mode-highlight) (outline-cycle, outline-cycle-buffer): Doc fixes. (Bug#54967) -2022-06-29 Eli Zaretskii +2022-04-15 Eli Zaretskii Improve discoverability of 'insert-directory-program' @@ -885,7 +885,7 @@ * lisp/dired.el (dired): Mention 'insert-directory-program' in the doc string. (Bug#54962) -2022-06-29 Eli Zaretskii +2022-04-15 Eli Zaretskii Fix cursor motion under truncate-lines with Flymake fringe indicator @@ -893,7 +893,7 @@ as "images" for the purpose of vertical-motion logic dealing with overshooting buffer positions. (Bug#54946) -2022-06-29 Lars Ingebrigtsen +2022-04-14 Lars Ingebrigtsen Make all vc-*-responsible-p functions return a string @@ -908,7 +908,7 @@ Do not merge to master. -2022-06-29 Eli Zaretskii +2022-04-14 Eli Zaretskii Describe problems with invoking Python on MS-Windows @@ -916,20 +916,20 @@ interpreter due to the MS-Windows "App Execution Aliases" feature. (Bug#54860) -2022-06-29 Eli Zaretskii +2022-04-13 Eli Zaretskii A better fix for bug#54800 * lisp/calc/calc.el (calc-align-stack-window): Improve scrolling when windows have non-integral dimensions. -2022-06-29 Lars Ingebrigtsen +2022-04-13 Lars Ingebrigtsen Add a comment about cl-concatenate * lisp/emacs-lisp/cl-extra.el (cl-concatenate): Add a comment. -2022-06-29 Lars Ingebrigtsen +2022-04-13 Lars Ingebrigtsen Revert "Make cl-concatenate an alias of seq-concatenate" @@ -938,7 +938,7 @@ The commit made calls to cl-concatenate bug out, since autoloading defalises doesn't work very well (bug#54901). -2022-06-29 Eli Zaretskii +2022-04-12 Eli Zaretskii Fix 'window-text-pixel-width' when starting from display property @@ -946,11 +946,11 @@ there's a display property at START, and move_it_to overshoots. Do not merge to master. (Bug#54862) -2022-06-29 Stefan Monnier +2022-04-11 Stefan Monnier * lisp/gnus/mm-encode.el (mm-default-file-encoding): Fix "when" arg -2022-06-29 Eli Zaretskii +2022-04-11 Eli Zaretskii Fix default-directory of buffers visiting files in renamed directories @@ -962,18 +962,18 @@ benefit of files that were renamed/removed, because file-in-directory-p returns nil in those cases. (Bug#54838) -2022-06-29 Lars Ingebrigtsen +2022-04-11 Lars Ingebrigtsen Fix a kill-append regression * lisp/simple.el (kill-append): Fix a regression when kill-ring-max is zero (bug#54842). -2022-06-29 Eli Zaretskii +2022-04-10 Eli Zaretskii * doc/misc/eww.texi (Advanced): Correct outdated info (bug#54839). -2022-06-29 Eli Zaretskii +2022-04-10 Eli Zaretskii Clean up the MSDOS port @@ -988,14 +988,14 @@ (GL_GNULIB_SIGDESCR_NP): Define to 1, to get the prototypes from Gnulib headers. -2022-06-29 Daniel Martín +2022-04-10 Daniel Martín Fix typo in next-error-find-buffer-function * lisp/simple.el (next-error-find-buffer-function): Fix typo (bug#54830). -2022-06-29 Lars Ingebrigtsen +2022-04-10 Lars Ingebrigtsen Revert "Make shell-resync-dirs handle whitespace in directory names" @@ -1005,14 +1005,14 @@ Do not merge to master; it has been fixed in a more encompassing way there. -2022-06-29 Eli Zaretskii +2022-04-09 Eli Zaretskii Fix scrolling of the stack window in Calc * lisp/calc/calc.el (calc-align-stack-window): Fix off-by-one error in computing the window-start point. (Bug#54800) -2022-06-29 Eli Zaretskii +2022-04-08 Eli Zaretskii Update and fix instructions and scripts for updating the Web pages @@ -1026,14 +1026,14 @@ * etc/refcards/Makefile (pl-refcard.dvi): If mex.fmt cannot be found, invoke 'mex' instead of 'tex'. -2022-06-29 Michael Albinus +2022-04-08 Michael Albinus Extend tramp-archive-test45-auto-load * test/lisp/net/tramp-archive-tests.el (tramp-archive-test45-auto-load): Extend test. -2022-06-29 Michael Albinus +2022-04-08 Michael Albinus Ensure local `default-directory' in Tramp when needed @@ -1041,7 +1041,7 @@ `default-directory' when calling `list-system-processes' and `process-attributes'. -2022-06-29 Eli Zaretskii +2022-04-08 Eli Zaretskii Clarify "idleness" in the ELisp manual @@ -1049,7 +1049,7 @@ input with timeout doesn't make Emacs idle. Suggested by Ignacio . (Bug#54371) -2022-06-29 Jürgen Hötzel +2022-04-07 Jürgen Hötzel Use correct signal oldset in posix_spawn implementation @@ -1067,7 +1067,7 @@ (cherry picked from commit 8103b060d89ac63a12c439087bd46c30da72cd97) -2022-06-29 Felix Dietrich (tiny change) +2022-04-07 Felix Dietrich (tiny change) Fix error in tramp-archive-autoload-file-name-handler @@ -1081,13 +1081,13 @@ does not expect nil. Always returning nil is also false in general. -2022-06-29 Michael Albinus +2022-04-07 Michael Albinus Commit missing file from previous commit (Do not merge with master) Commit missing file from previous commit -2022-06-29 Michael Albinus +2022-04-07 Michael Albinus Merge with Tramp 2.5.2.3 (Do not merge with master) @@ -1186,7 +1186,7 @@ (tramp--test-asynchronous-processes-p): New defun. (tramp--test-hpux-p, tramp--test-macos-p): Protect against errors. -2022-06-29 Stefan Monnier +2022-04-06 Stefan Monnier cl-generic.el: Fix bug#46722 @@ -1197,14 +1197,14 @@ Backport from `master` (cherrypick from commit 61f8f7f68f). -2022-06-29 Eli Zaretskii +2022-04-05 Eli Zaretskii Fix fallout from lexical-binding in vhdl-mode.el * lisp/progmodes/vhdl-mode.el (vhdl-update-sensitivity-list): Fix production of a list with embedded function calls. (Bug#54730) -2022-06-29 Eli Zaretskii +2022-04-03 Eli Zaretskii Update logs and HISTORY for Emacs 28.1 @@ -1212,7 +1212,7 @@ * etc/HISTORY: * etc/AUTHORS: Update for Emacs 28.1 release. -2022-06-29 Eli Zaretskii +2022-04-03 Eli Zaretskii Bump Emacs version to 28.1 @@ -1221,8 +1221,7 @@ * nt/README.W32: * msdos/sed2v2.inp: Bump Emacs version to 28.1 -2022-06-29 Tassilo Horn -2022-04-13 Tassilo Horn +2022-03-30 Tassilo Horn dired: implement feature from 7b50ed553f differently @@ -1231,29 +1230,29 @@ (dired-clean-up-after-deletion): Use dired-buffers-for-dir-or-subdir instead dired-buffers-for-dir. -2022-04-13 Eli Zaretskii +2022-03-30 Eli Zaretskii Fix regression in 'dired-buffers-for-dir' * lisp/dired.el (dired-buffers-for-dir): Fix inadvertently swapped arguments. (Bug#54636) -2022-04-13 Eli Zaretskii +2022-03-27 Eli Zaretskii * lisp/desktop.el (desktop-read): Clarify warning text. -2022-04-13 Po Lu +2022-03-26 Po Lu * doc/emacs/anti.texi (Antinews): Unannounce removal of Motif. -2022-04-13 Lars Ingebrigtsen +2022-03-25 Lars Ingebrigtsen Fix eshell-explicit-command-char doc string typo * lisp/eshell/esh-ext.el (eshell-explicit-command-char): Fix typo in doc string (bug#54567). -2022-04-13 Eli Zaretskii +2022-03-24 Eli Zaretskii Clarify the description of "selected tags table" @@ -1261,7 +1260,7 @@ distinction between the "selected tags table" and the "current list of tags tables". (Bug#54543) -2022-04-13 Lars Ingebrigtsen +2022-03-21 Lars Ingebrigtsen Add notes about command modes and nativecomp interaction @@ -1272,11 +1271,11 @@ Do not merge to master. -2022-04-13 Kyle Meyer +2022-03-20 Kyle Meyer Update to Org 9.5.2-25-gaf6f12 -2022-04-13 Eli Zaretskii +2022-03-20 Eli Zaretskii Improve doc strings of read-char-from-minibuffer-insert-* commands @@ -1284,7 +1283,7 @@ (read-char-from-minibuffer-insert-other): Clarify the doc strings. (Bug#54479) -2022-04-13 Eli Zaretskii +2022-03-19 Eli Zaretskii Fix region highlight in non-selected windows @@ -1292,25 +1291,25 @@ to pre-redisplay-functions windows whose point was moved from the last recorded position. (Bug#54450) -2022-04-13 Eli Zaretskii +2022-03-18 Eli Zaretskii Fix a regression in 'decipher-digram-list' * lisp/play/decipher.el (decipher-stats-buffer): Don't assume the statistics buffer always exists. (Bug#54443) -2022-04-13 Karl Fogel +2022-03-17 Karl Fogel Improve documentation of bookmark default sorting * lisp/bookmark.el (bookmark-alist, bookmark-store, bookmark-maybe-sort-alist): Update doc strings and comments. -2022-04-13 Juri Linkov +2022-03-15 Juri Linkov * doc/misc/transient.texi: Fix @dircategory to "Emacs misc features" for dir. -2022-04-13 Jim Porter +2022-03-13 Jim Porter Fix evaluation of negated argument predicates in Eshell @@ -1321,7 +1320,7 @@ Do not merge to master. -2022-04-13 Eli Zaretskii +2022-03-12 Eli Zaretskii Emacs pretest 28.0.92 @@ -1335,7 +1334,7 @@ * ChangeLog.3: Regenerate. -2022-04-13 Eli Zaretskii +2022-03-10 Eli Zaretskii Fix regression in 'custom-prompt-customize-unsaved-options' @@ -1344,7 +1343,7 @@ the doc string. Patch by Sebastian Miele . (Bug#54329) -2022-04-13 Eli Zaretskii +2022-03-10 Eli Zaretskii Improve documentation of 'map-charset-chars' @@ -1352,35 +1351,35 @@ * src/charset.c (Fmap_charset_chars): Clarify the codepoint issue in using 'map-charset-chars'. -2022-04-13 Eli Zaretskii +2022-03-08 Eli Zaretskii Avoid assertion violations in 'bidi_resolve_brackets' * src/bidi.c (bidi_resolve_brackets): Move assertion to where it really matters. (Bug#54295) -2022-04-13 Lars Ingebrigtsen +2022-03-07 Lars Ingebrigtsen Fix which-func-update doc string * lisp/progmodes/which-func.el (which-func-update): Make the doc string match the code (bug#54288). -2022-04-13 Eli Zaretskii +2022-03-07 Eli Zaretskii Improve wording of 'dired-jump's description * doc/emacs/dired.texi (Dired Enter): Clarify wording. Reported by Natalie . -2022-04-13 Lars Ingebrigtsen +2022-03-06 Lars Ingebrigtsen Add a comment for previous browse-url-of-dired-file change * lisp/net/browse-url.el (browse-url-of-dired-file): Add a comment for previous change. -2022-04-13 Lars Ingebrigtsen +2022-03-06 Lars Ingebrigtsen Restore documented Emacs 27.2 behaviour of browse-url-of-dired-file @@ -1388,22 +1387,22 @@ documented behaviour -- open a web browser instead of passing to the various handlers. -2022-04-13 Kyle Meyer +2022-03-06 Kyle Meyer Update to Org 9.5.2-24-g668205 -2022-04-13 Andreas Schwab +2022-03-05 Andreas Schwab * lib-src/seccomp-filter.c (main): Use faccessat2 only if defined. -2022-04-13 Lars Ingebrigtsen +2022-03-04 Lars Ingebrigtsen Fix regression in derived-mode-init-mode-variables * lisp/emacs-lisp/derived.el (derived-mode-init-mode-variables): Fix regression caused by lexical-binding derived.el (bug#54240). -2022-04-13 Eli Zaretskii +2022-03-03 Eli Zaretskii Avoid crashes when fringe bitmaps are defined in daemon mode @@ -1416,7 +1415,7 @@ not available when a fringe bitmap is about to be drawn. Don't try to draw a bitmap that is not known to fringe.c. (Bug#54183) -2022-04-13 Eli Zaretskii +2022-03-03 Eli Zaretskii One more fix of the BPA implementation @@ -1424,7 +1423,7 @@ when there are no strong directional characters inside the bracketed pair. (Bug#54219) -2022-04-13 Eli Zaretskii +2022-03-03 Eli Zaretskii Fix handling of brackets in BPA @@ -1432,14 +1431,14 @@ N0 rule when there are no strong directional characters inside the bracketed pair. (Bug#54219) -2022-04-13 Po Lu +2022-03-02 Po Lu Correct etc/NEWS entry about bitmapped fonts * etc/NEWS: Don't say that bitmap font issues are due to Pango, that's not accurate. -2022-04-13 Jim Porter +2022-03-01 Jim Porter Improve/correct documentation about Eshell variable expansion @@ -1449,7 +1448,7 @@ * doc/misc/eshell.texi (Dollars Expansion): Add documentation for $"var"/$'var' and $ syntaxes. -2022-04-13 Jim Porter +2022-03-01 Jim Porter Partially revert b03f74e0f2a578b1580e8b1c368665850ee7f808 @@ -1462,7 +1461,7 @@ * test/lisp/eshell/eshell-tests.el (eshell-test/interp-temp-cmd): New test. -2022-04-13 Paul Eggert +2022-03-01 Paul Eggert Backport: Port pre-commit hook to Git 2.35.0 @@ -1471,32 +1470,32 @@ (cherry picked from commit b8a96f055624f86fe965a0d1b7b2495b2db80e63) -2022-04-13 Lars Ingebrigtsen +2022-02-28 Lars Ingebrigtsen Fix :tag for eol in tab-first-completion * lisp/indent.el (tab-first-completion): Fix the :tag description (bug#54179). -2022-04-13 Kyle Meyer +2022-02-28 Kyle Meyer Update to Org 9.5.2-22-g33543d -2022-04-13 Dmitry Gutov +2022-02-27 Dmitry Gutov Add explicit '--no-heading' for ripgrep * lisp/progmodes/xref.el (xref-search-program-alist): Add explicit '--no-heading' for ripgrep (bug#54177). -2022-04-13 Michael Albinus +2022-02-26 Michael Albinus Follow OpenSSH changes in Tramp * lisp/net/tramp-sh.el (tramp-ssh-controlmaster-options): Reimplement. OpenSSH has changed its diagnostics messages. -2022-04-13 Eli Zaretskii +2022-02-26 Eli Zaretskii Document better how to reset attributes of faces for new frames @@ -1504,25 +1503,25 @@ * lisp/faces.el (set-face-attribute): Explain how to reset an attribute's value for future frames. (Bug#54156) -2022-04-13 Michael Albinus +2022-02-25 Michael Albinus * lisp/net/tramp-sh.el (tramp-ssh-controlmaster-options): Adapt test. -2022-04-13 Lars Ingebrigtsen +2022-02-24 Lars Ingebrigtsen Mention flyspell-prog-mode in flyspell-mode doc string * lisp/textmodes/flyspell.el (flyspell-mode): Mention flyspell-prog-mode (bug#54131). -2022-04-13 Lars Ingebrigtsen +2022-02-23 Lars Ingebrigtsen Reword face-remap-add-relative manual entry * doc/lispref/display.texi (Face Remapping): Clarify the face-remap-add-relative (bug#54114). -2022-04-13 Philipp Stephani +2022-02-22 Philipp Stephani Fix indexing of module functions that return enumeration types. @@ -1533,25 +1532,25 @@ * doc/lispref/internals.texi (Module Misc, Module Nonlocal): Enclose multi-word return types in braces. -2022-04-13 Eli Zaretskii +2022-02-22 Eli Zaretskii * doc/misc/transient.texi (Other Options): Fix a @ref. (Bug#54108) -2022-04-13 Glenn Morris +2022-02-22 Glenn Morris tramp.texi texinfo 4.13 compatibility * doc/misc/tramp.texi (Frequently Asked Questions): Restore compatibility with Texinfo < 5. -2022-04-13 Michael Albinus +2022-02-22 Michael Albinus Explain "Tramp" spelling in its manual * doc/misc/tramp.texi (Frequently Asked Questions): Explain "Tramp" spelling. -2022-04-13 Eli Zaretskii +2022-02-21 Eli Zaretskii Fix 'display-line-numbers-mode' in hide-show buffers @@ -1560,25 +1559,25 @@ 'display-line-numbers-mode' is turned on in the buffer. (Bug#54091) -2022-04-13 Martin Rudalics +2022-02-21 Martin Rudalics Don't check whether a deleted window is deletable (Bug#54028) * lisp/window.el (window-state-put): Make sure window is live before calling 'window-deletable-p' on it (Bug#54028). -2022-04-13 Eli Zaretskii +2022-02-21 Eli Zaretskii A friendlier error message from image-mode in an empty buffer * lisp/image-mode.el (image-mode): Handle the case where the empty buffer doesn't visit a file (Bug#54084) -2022-04-13 Kyle Meyer +2022-02-20 Kyle Meyer Update to Org 9.5.2-17-gea6b74 -2022-04-13 Eli Zaretskii +2022-02-18 Eli Zaretskii Improve documentation of filling and justification commands @@ -1590,11 +1589,11 @@ (set-justification-left, set-justification-right) (set-justification-full): Improve wording of doc strings. -2022-04-13 Eli Zaretskii +2022-02-18 Eli Zaretskii * lisp/progmodes/subword.el (superword-mode): Doc fix. (Bug#54045) -2022-04-13 Philipp Stephani +2022-02-17 Philipp Stephani Fix indexing of module functions that return complex types. @@ -1605,7 +1604,7 @@ * doc/lispref/internals.texi (Module Values): Enclose multi-word return types in braces. -2022-04-13 Po Lu +2022-02-17 Po Lu Prevent crashes caused by invalid locale coding systems @@ -1615,25 +1614,25 @@ Do not merge to master. -2022-04-13 Michael Albinus +2022-02-15 Michael Albinus Fix problem with popd for in remote shell buffers * lisp/shell.el (shell-prefixed-directory-name): Use `file-local-name' for DIR. (Bug#53927) -2022-04-13 Jonas Bernoulli +2022-02-15 Jonas Bernoulli Import texi source file for transient manual * doc/misc/Makefile.in: Add transient to INFO_COMMON. * doc/misc/transient.texi: New file. -2022-04-13 Kyle Meyer +2022-02-13 Kyle Meyer Update to Org 9.5.2-15-gc5ceb6 -2022-04-13 Eli Zaretskii +2022-02-13 Eli Zaretskii Fix 'exchange-point-and-mark' in 'transient-mark-mode' @@ -1642,7 +1641,7 @@ (cherry picked from commit 415ed4b42515ff2e6dd9b94e964b479e50c6392e) -2022-04-13 Eli Zaretskii +2022-02-13 Eli Zaretskii Fix "C-SPC C-SPC" after "C-x C-x" @@ -1651,31 +1650,31 @@ (cherry picked from commit 19c6cad1821eb896b2ddd0f6eab030f0880ea254) -2022-04-13 Eli Zaretskii +2022-02-13 Eli Zaretskii Fix a typo in fontset.el * lisp/international/fontset.el (xlfd-regexp-spacing-subnum): Fix a typo. Reported by Greg A. Woods . -2022-04-13 Eli Zaretskii +2022-02-12 Eli Zaretskii Note in ELisp manual that too-wide images are truncated * doc/lispref/display.texi (Showing Images): Note that images are truncated at the window's edge. (Bug#53952) -2022-04-13 Andrea Corallo +2022-02-11 Andrea Corallo * lisp/mail/emacsbug.el (report-emacs-bug): Report libgccjit status. * lisp/startup.el (normal-top-level): Small code move, improve 202d3be873. -2022-04-13 Andrea Corallo +2022-02-10 Andrea Corallo * lisp/startup.el (normal-top-level): Disable native-comp if not available -2022-04-13 Andrea Corallo +2022-02-09 Andrea Corallo Fix integer arithmetic miss-compilation (bug#53451) @@ -1685,14 +1684,14 @@ * test/src/comp-tests.el (comp-tests-type-spec-tests): Add test to verify this is effective. -2022-04-13 Robert Pluim +2022-02-08 Robert Pluim Mark flymake as compatible with emacs-26.1 * lisp/progmodes/flymake.el: Bump package version and set emacs version in Package-Requires to 26.1 (Bug#53853). -2022-04-13 Brian Leung +2022-02-08 Brian Leung flymake: Ensure compatibility with older Emacsen @@ -1700,7 +1699,7 @@ replace-regexp-in-string instead of Emacs 28's string-replace (bug#53853). -2022-04-13 Eric Abrahamsen +2022-02-07 Eric Abrahamsen Don't remove dummy.group from gnus-newsrc-alist on Gnus save @@ -1710,20 +1709,20 @@ function was removing dummy.group from the global value of `gnus-newsrc-alist' on save; we only wanted to remove it temporarily. -2022-04-13 Bob Rogers +2022-02-05 Bob Rogers Fix ietf-drums-get-comment doc string * lisp/mail/ietf-drums.el (ietf-drums-get-comment): We really return the last comment (bug#53810). -2022-04-13 Daniel Martín +2022-02-05 Daniel Martín Fix typo in display.texi * doc/lispref/display.texi (Making Buttons): Fix typo. (Bug#53807) -2022-04-13 Michael Albinus +2022-02-03 Michael Albinus Revert an erroneous change in tramp-cache.el @@ -1731,7 +1730,7 @@ Use `string-match-p' instead of `string-search'. The latter one was introduced by accident. Reported by Kai Tetzlaff . -2022-04-13 Eli Zaretskii +2022-02-02 Eli Zaretskii Improve documentation of 'emacs-version' @@ -1740,11 +1739,11 @@ * lisp/version.el (emacs-version): Improve doc string. (Bug#53720) -2022-04-13 Michael Albinus +2022-02-01 Michael Albinus * etc/NEWS: Apply final fixes after proofreading. -2022-04-13 Eli Zaretskii +2022-01-31 Eli Zaretskii Clarify documentation of a "face's font" @@ -1753,7 +1752,7 @@ the font returned by 'face-font' are by default for ASCII characters. (Bug#53664) -2022-04-13 Alan Mackenzie +2022-01-31 Alan Mackenzie Bind Qdebugger to Qdebug in signal_or_quit. @@ -1761,18 +1760,18 @@ Vdebugger) to Qdebug in the section for errors in batch jobs. (syms_of_eval): New DEFSYM for Qdebugger. -2022-04-13 Kyle Meyer +2022-01-30 Kyle Meyer Update to Org 9.5.2-13-gdd6486 -2022-04-13 Eli Zaretskii +2022-01-30 Eli Zaretskii Fix regression in Occur Edit mode * lisp/replace.el (occur-after-change-function): Fix the algorithm to find the smallest change in some corner cases. (Bug#53598) -2022-04-13 Eli Zaretskii +2022-01-29 Eli Zaretskii Fix last change of Malayalam composition rules @@ -1781,7 +1780,7 @@ Malayalam characters to the existing patterns, so as not to lose the patterns that use ZWJ and ZWNJ. (Bug#53625) -2022-04-13 Eli Zaretskii +2022-01-29 Eli Zaretskii Fix rendering of Malayalam script @@ -1790,21 +1789,21 @@ Instead, pass any sequence of Malayalam codepoints to the shaping engine. (Bug#53625) -2022-04-13 Eli Zaretskii +2022-01-29 Eli Zaretskii Improve documentation of Occur mode * doc/emacs/search.texi (Other Repeating Search): Improve wording and document Occur Edit mode better. -2022-04-13 Alan Third +2022-01-29 Alan Third Remove debug logging * src/nsterm.m ([EmacsView copyRect:to:]): Remove logging as it's no longer required. -2022-04-13 Michael Albinus +2022-01-29 Michael Albinus Fix error in filelock.c @@ -1814,11 +1813,11 @@ (Flock_file): Do not check for create_lockfiles. Call file name handler if appropriate. (Bug#53207) -2022-04-13 Juri Linkov +2022-01-27 Juri Linkov * lisp/frame.el (clone-frame): Filter out 'parent-id' (bug#51883). -2022-04-13 Lars Ingebrigtsen +2022-01-26 Lars Ingebrigtsen Partially revert a fill-region-as-paragraph regression @@ -1826,14 +1825,14 @@ e186af261 (bug#53537), because it leads to regressions. (But leave tests in place.) -2022-04-13 Eli Zaretskii +2022-01-26 Eli Zaretskii Fix 'make_lispy_position' when there's an image at EOB * src/xdisp.c (move_it_to): Don't compare IT_CHARPOS with an invalid TO_CHARPOS. (Bug#53546) -2022-04-13 Lars Ingebrigtsen +2022-01-26 Lars Ingebrigtsen Fix copyright-find-copyright when searching from the end @@ -1842,7 +1841,7 @@ Do not merge to master. -2022-04-13 Lars Ingebrigtsen +2022-01-26 Lars Ingebrigtsen Fix copyright.el comment and add a test @@ -1851,18 +1850,18 @@ Do not merge to master. -2022-04-13 Philipp Stephani +2022-01-24 Philipp Stephani * configure.ac (LIBSECCOMP): Bump minimum version for faccessat2. -2022-04-13 Lars Ingebrigtsen +2022-01-24 Lars Ingebrigtsen Make the `f' command work in image-mode again * lisp/image.el (image-show-frame): Protect against not having computed the animation data yed (bug#53489). -2022-04-13 Philipp Stephani +2022-01-22 Philipp Stephani Seccomp: improve support for newer versions of glibc (Bug#51073) @@ -1871,14 +1870,14 @@ with commits 95c1056962a3f2297c94ce47f0eaf0c5b6563231 and 3d3ab573a5f3071992cbc4f57d50d1d29d55bde2, respectively). -2022-04-13 Thomas Fitzsimmons +2022-01-21 Thomas Fitzsimmons EUDC: Fix a quoting bug in the BBDB backend * lisp/net/eudcb-bbdb.el (eudc-bbdb-query-internal): Fix a quoting bug introduced during lexical-binding conversion. -2022-04-13 Sergey Vinokurov +2022-01-21 Sergey Vinokurov Fix memory-report-object-size to initialize memory-report--type-size @@ -1887,7 +1886,7 @@ Do not merge to master. -2022-04-13 Stefan Monnier +2022-01-20 Stefan Monnier Fix menu-bar mouse clicks in "C-h c" and "C-h k" (bug#53322) @@ -1898,7 +1897,7 @@ (cherry picked from commit 9ceb3070e34ad8a54184fd0deda477bf5ff77000) -2022-04-13 Eli Zaretskii (tiny change) +2022-01-20 Eli Zaretskii (tiny change) Fix UB in ebrowse @@ -1906,14 +1905,14 @@ limits of 'matching_regexp_buffer'. Patch by Jan Stranik . (Bug#53333) -2022-04-13 Lars Ingebrigtsen +2022-01-20 Lars Ingebrigtsen Fix execute-extended-command-for-buffer in fundamental-mode * lisp/simple.el (execute-extended-command-for-buffer): Protect against the current local map being nil (bug#52907). -2022-04-13 Martin Rudalics +2022-01-20 Martin Rudalics Add workaround to handle a problem with Enlightenment WM (Bug#53298) @@ -1926,14 +1925,14 @@ Enlightenment WM and 'x-set-frame-visibility-more-laxly' workaround. -2022-04-13 Po Lu +2022-01-17 Po Lu Fix regression leading to flickering tooltips when the mouse is moved * lisp/tooltip.el (tooltip-show-help): Compare string with previous tooltip string ignoring properties. -2022-04-13 Andrea Corallo +2022-01-17 Andrea Corallo * Fix native comp for non trivial function names (bug#52833) @@ -1945,15 +1944,15 @@ Do not merge to master -2022-04-13 Kyle Meyer +2022-01-15 Kyle Meyer Update to Org 9.5.2-9-g7ba24c -2022-04-13 Juri Linkov +2022-01-15 Juri Linkov * lisp/net/dictionary.el (dictionary-context-menu): Use package prefix. -2022-04-13 Philipp Stephani +2022-01-15 Philipp Stephani Mark a few more map tests as unstable on Emacs 28 (Bug#46722). @@ -1965,24 +1964,24 @@ (test-map-merge, test-map-merge-with, test-map-merge-empty): Mark as unstable. -2022-04-13 Philipp Stephani +2022-01-15 Philipp Stephani * lisp/indent.el (tab-first-completion): Fix incorrect choices. -2022-04-13 Philipp Stephani +2022-01-14 Philipp Stephani * lisp/simple.el (undo-no-redo): Fix customization group * lisp/progmodes/xref.el (xref-file-name-display): Fix docstring. -2022-04-13 Eli Zaretskii +2022-01-14 Eli Zaretskii Avoid another segfault in 'face_at_buffer_position' * src/xfaces.c (face_at_buffer_position): Make really sure the default face is usable. (Bug#53254) -2022-04-13 Lars Ingebrigtsen +2022-01-14 Lars Ingebrigtsen Mark test-map-into as unstable @@ -1991,7 +1990,7 @@ Do not merge to master. -2022-04-13 Philipp Stephani +2022-01-13 Philipp Stephani Fix Edebug specification for inline functions (Bug#53068). @@ -2000,7 +1999,7 @@ * test/lisp/emacs-lisp/edebug-tests.el (edebug-tests-inline): New unit test. -2022-04-13 N. Jackson +2022-01-13 N. Jackson Remove mention of removed `gnus-treat-play-sounds' variable from manual @@ -2008,7 +2007,7 @@ manual. According to lisp/gnus/ChangeLog.3 this variable was removed in 2010 (bug#53192). -2022-04-13 Mattias Engdegård +2022-01-12 Mattias Engdegård Revert "Fix closure-conversion of shadowed captured lambda-lifted vars" @@ -2017,18 +2016,18 @@ It was committed to a stable branch without prior discussion; see bug#53071. -2022-04-13 Juri Linkov +2022-01-12 Juri Linkov * doc/lispref/windows.texi (Textual Scrolling): Remove obsolete text. Remove text about scrolling the minibuffer from the buffer, obsolete since Emacs 27 (bug#51210). -2022-04-13 Glenn Morris +2022-01-12 Glenn Morris * lisp/files.el (lock-file-name-transforms): Doc tweaks. -2022-04-13 Mattias Engdegård +2022-01-12 Mattias Engdegård Fix closure-conversion of shadowed captured lambda-lifted vars @@ -2047,7 +2046,7 @@ (cherry picked from commit 45252ad8f932c98a373ef0ab7f3363a3e27ccbe4) -2022-04-13 Philipp Stephani +2022-01-12 Philipp Stephani Fix test lisp/cedet/semantic/bovine/gcc-tests on macOS (Bug#52431) @@ -2057,7 +2056,7 @@ (cherry picked from commit 6e52becfbe2a33c025b8c4838b3c8f06ba5a6fb8) -2022-04-13 Mattias Engdegård +2022-01-12 Mattias Engdegård Don't fail flymake-tests if `gcc` actually is Clang @@ -2067,7 +2066,7 @@ (cherry picked from commit b2167d98432a78442522b7564e22f47d75a98b6f) -2022-04-13 Eli Zaretskii +2022-01-10 Eli Zaretskii Revert "Remove the filename argument from the command line after an ELC+ELN build" @@ -2076,14 +2075,14 @@ Please don't install anything non-trivial on the release branch without asking first. -2022-04-13 Alan Mackenzie +2022-01-10 Alan Mackenzie Remove the filename argument from the command line after an ELC+ELN build This fixes bug #53164. Without this fix, bootstrap-emacs loads the source file uselessly into a buffer after completing the compilation. -2022-04-13 Stefan Monnier +2022-01-09 Stefan Monnier (save-some-buffers): Simplify the fix for bug#46374 @@ -2096,14 +2095,14 @@ with `pred` set to `save-some-buffers-root` since it's not an appropriate function for that any more. -2022-04-13 Stefan Kangas +2022-01-09 Stefan Kangas Improve docstring of edit-abbrevs * lisp/abbrev.el (edit-abbrevs): Doc fix; don't use obsolete name. Improve docstring formatting. -2022-04-13 Eli Zaretskii +2022-01-09 Eli Zaretskii Revert "Fix alignment on font size change in tabulated-list-mode" @@ -2112,21 +2111,21 @@ That change caused a regression in a much more important use case, see bug#53133. -2022-04-13 Stefan Kangas +2022-01-08 Stefan Kangas Clarify docstring of package-native-compile * lisp/emacs-lisp/package.el (package-native-compile): Clarify docstring. -2022-04-13 Eli Zaretskii +2022-01-08 Eli Zaretskii Fix Subject "simplification" in Rmail * lisp/mail/rmail.el (rmail-simplified-subject): Match against "[external]" _after_ decoding the Subject by RFC-2047. -2022-04-13 Stefan Kangas +2022-01-08 Stefan Kangas Bump Emacs version to 28.0.91 @@ -236202,9 +236201,7 @@ This file records repository revisions from commit 9d56a21e6a696ad19ac65c4b405aeca44785884a (exclusive) to -2022-06-29e44dbd50430e14f319b4c4d3f767740b10b (inclusive). -2022-04-13e39829812098d8269eafbc0fcb98959ee5bb7 (inclusive). -commit e7aa3ece52d26cc7e4d3f3990aff56127389779f (inclusive). +commit 7f749e44dbd50430e14f319b4c4d3f767740b10b (inclusive). See ChangeLog.2 for earlier changes. ;; Local Variables: diff --git a/etc/AUTHORS b/etc/AUTHORS index f961852cee..b5444e60a7 100644 --- a/etc/AUTHORS +++ b/etc/AUTHORS @@ -105,9 +105,9 @@ and co-wrote cc-align.el cc-cmds.el cc-defs.el cc-engine.el cc-fonts.el cc-langs.el cc-mode.el cc-styles.el cc-vars.el and changed cc-mode.texi minibuf.c bytecomp.el edebug.el follow.el window.c display.texi subr.el syntax.texi progmodes/compile.el - programs.texi keyboard.c lisp.h modes.texi window.el windows.texi - cus-start.el eval.c font-lock.el isearch.el newcomment.el - and 166 other files + programs.texi eval.c keyboard.c lisp.h modes.texi window.el + windows.texi cus-start.el font-lock.el frame.c isearch.el + and 167 other files Alan Modra: changed unexelf.c @@ -127,8 +127,7 @@ and changed nsterm.m nsterm.h nsfns.m image.c nsmenu.m configure.ac Alastair Burt: changed gnus-art.el smiley.el Albert Krewinkel: co-wrote sieve-manage.el -and changed sieve.el gnus-msg.el gnus.texi mail/sieve-manage.el - message.el sieve.texi +and changed sieve.el gnus-msg.el gnus.texi message.el sieve.texi Albert L. Ting: changed gnus-group.el mail-hist.el @@ -181,7 +180,7 @@ Alexandre Julliard: wrote vc-git.el and changed vc.el ewoc.el Alexandre Oliva: wrote gnus-mlspl.el -and changed unexelf.c emacs-regex.c format.el iris4d.h iris5d.h unexsgi.c +and changed unexelf.c format.el iris4d.h iris5d.h regex-emacs.c unexsgi.c Alexandre Veyrenc: changed fr-refcard.tex @@ -332,9 +331,9 @@ Andreas Schwab: changed configure.ac lisp.h xdisp.c process.c alloc.c Andreas Seltenreich: changed nnweb.el gnus.texi message.el gnus-sum.el gnus.el nnslashdot.el gnus-srvr.el gnus-util.el mm-url.el mm-uu.el - url-http.el xterm.c battery.el comint.el doc/misc/gnus.texi - easy-mmode.el gmm-utils.el gnus-art.el gnus-cite.el gnus-draft.el - gnus-group.el and 7 other files + url-http.el xterm.c battery.el comint.el easy-mmode.el gmm-utils.el + gnus-art.el gnus-cite.el gnus-draft.el gnus-group.el gnus-ml.el + and 6 other files Andreas Vögele: changed pgg-def.el @@ -376,9 +375,9 @@ Andrew Hyatt: changed bug-triage CONTRIBUTE org-archive.el org.el org.texi Andrew Innes: changed makefile.nt w32fns.c w32term.c w32.c w32proc.c - fileio.c w32-fns.el dos-w32.el inc/ms-w32.h w32term.h makefile.def + fileio.c ms-w32.h w32-fns.el dos-w32.el w32term.h makefile.def unexw32.c w32menu.c w32xfns.c addpm.c cmdproxy.c emacs.c w32-win.el - w32inevt.c configure.bat lread.c and 129 other files + w32inevt.c configure.bat lread.c and 128 other files Andrew L. Moore: changed executable.el @@ -442,8 +441,9 @@ Antoine Levitt: changed gnus-group.el gnus-sum.el message.texi Antonin Houska: changed newcomment.el -Arash Esbati: changed reftex-vars.el reftex-auc.el reftex-ref.el - reftex.el nnmaildir.el reftex-cite.el reftex-dcr.el reftex-toc.el +Arash Esbati: changed reftex-vars.el efaq-w32.texi reftex-auc.el + reftex-ref.el reftex.el gnus.texi nnmaildir.el reftex-cite.el + reftex-dcr.el reftex-toc.el Arik Mitschang: changed smime.el @@ -479,11 +479,11 @@ Arthur Miller: changed help-fns.el ange-ftp.el bytecomp.el comp.c comp.el Artur Malabarba: wrote char-fold-tests.el faces-tests.el isearch-tests.el let-alist.el simple-tests.el sort-tests.el tabulated-list-tests.el -and changed package.el isearch.el lisp/char-fold.el files.el - tabulated-list.el package-test.el menu-bar.el replace.el bytecomp.el - faces.el files-x.el custom.el custom.texi help-fns.el - let-alist-tests.el simple.el subr-tests.el align.el bindings.el - cl-lib-tests.el cl-macs.el and 43 other files +and changed package.el isearch.el char-fold.el files.el tabulated-list.el + package-test.el menu-bar.el replace.el bytecomp.el faces.el files-x.el + custom.el custom.texi help-fns.el let-alist-tests.el simple.el + subr-tests.el align.el bindings.el cl-lib-tests.el cl-macs.el + and 43 other files Artyom Loenko: changed Info.plist.in @@ -543,7 +543,7 @@ Basil L. Contovounesios: changed simple.el message.el subr.el eww.el custom.el bibtex.el text.texi gnus-sum.el modes.texi customize.texi files.texi gnus-group.el gnus-win.el gravatar.el internals.texi json.el shr.el window.c battery-tests.el button.el custom-tests.el - and 278 other files + and 279 other files Bastian Beischer: changed semantic/complete.el calc-yank.el include.el mru-bookmark.el refs.el senator.el @@ -576,7 +576,7 @@ and changed org-clock.el org.el Benjamin Ragheb: changed fortune.el Benjamin Riefenstahl: changed files.el image-mode.el nnrss-tests.el - w32select.c emacs.c image.el inc/ms-w32.h lisp.h mac-win.el macterm.c + w32select.c emacs.c image.el lisp.h mac-win.el macterm.c ms-w32.h mule-cmds.el nnrss.el runemacs.c tcl.el w32.c w32.h Benjamin Rutt: co-wrote gnus-dired.el @@ -584,7 +584,7 @@ and changed vc.el gnus-msg.el message.el diff-mode.el ffap.el nnimap.el nnmbox.el simple.el vc-cvs.el Ben Key: changed w32.c w32fns.c w32menu.c configure.bat INSTALL w32.h - w32term.c configure.ac emacs.c inc/ms-w32.h keyboard.c make-docfile.c + w32term.c configure.ac emacs.c keyboard.c make-docfile.c ms-w32.h nsfont.m nsterm.m sound.c xfaces.c Ben Menasha: changed nnmh.el @@ -656,8 +656,8 @@ Bob Nnamtrop: changed viper-cmd.el Bob Olson: co-wrote cperl-mode.el Bob Rogers: changed vc-dir.el vc-svn.el cperl-mode.el diff.el ewoc.el - ffap.el files.el maintaining.texi sql.el thingatpt.el vc.el - vc1-xtra.texi + ffap.el files.el ietf-drums.el maintaining.texi sql.el thingatpt.el + vc.el vc1-xtra.texi Bob Weiner: changed info.el quail.el dframe.el etags.c rmail.el rmailsum.el speedbar.el @@ -709,7 +709,8 @@ Brian Fox: changed Makefile.in Makefile configure.ac minibuf.c dired.el Brian Jenkins: changed frame.c frames.texi hooks.texi Brian Leung: changed comint.el gud.el advice.el comp.c comp.el em-hist.el - files.el find-func.el gdb-mi.el help.el nadvice.el shell.el shortdoc.el + files.el find-func.el flymake.el gdb-mi.el help.el nadvice.el shell.el + shortdoc.el Brian Marick: co-wrote hideif.el @@ -850,8 +851,8 @@ Chris Hall: changed callproc.c frame.c Chris Hanson: changed xscheme.el scheme.el xterm.c hpux.h x11term.c hp9000s300.h keyboard.c process.c texinfmt.el sort.el syntax.c - texnfo-upd.el x11fns.c xfns.c dired.el emacs-regex.c emacsclient.c - fileio.c hp9000s800.h indent.c info.el and 17 other files + texnfo-upd.el x11fns.c xfns.c dired.el emacsclient.c fileio.c + hp9000s800.h indent.c info.el man.el and 17 other files Chris Hecker: changed calc-aent.el @@ -973,12 +974,10 @@ Claudio Fontana: changed Makefile.in leim/Makefile.in lib-src/Makefile.in Clemens Radermacher: changed cus-start.el frame.c minibuf.texi window.el -Clément Pit--Claudel: changed debugging.texi emacs-lisp/debug.el eval.c - progmodes/python.el subr-tests.el subr.el url-http.el url-vars.el - Clément Pit-Claudel: changed Dockerfile.emba button.el configure.ac - display.texi ert.el gitlab-ci.yml keyboard.c tex-mode.el text.texi - xdisp.c + debugging.texi display.texi emacs-lisp/debug.el ert.el eval.c + gitlab-ci.yml keyboard.c progmodes/python.el subr-tests.el subr.el + tex-mode.el text.texi url-http.el url-vars.el xdisp.c Codruț Constantin Gușoi: changed files.el @@ -1032,11 +1031,11 @@ Dale Sedivec: changed sgml-mode.el wisent/python.el Damien Cassou: wrote auth-source-pass-tests.el hierarchy-tests.el hierarchy.el and co-wrote auth-source-pass.el auth-source-tests.el -and changed auth.texi checkdoc.el ispell.el message.el seq-tests.el - seq.el simple-tests.el simple.el auth-source.el autorevert.el +and changed simple.el auth.texi checkdoc.el ispell.el message.el + seq-tests.el seq.el simple-tests.el auth-source.el autorevert.el checkdoc-tests.el imenu-tests.el imenu.el info.el isearch.el - json-tests.el json.el message-tests.el package.el rmc.el sequences.texi - xref.el + json-tests.el json.el message-tests.el package.el rmc.el sending.texi + and 3 other files Damien Elmes: changed erc.el erc-dcc.el erc-track.el erc-log.el erc-pcomplete.el README erc-button.el erc-nets.el erc-ring.el Makefile @@ -1114,9 +1113,9 @@ Daniel Lublin: changed dns-mode.el Daniel Martín: changed shortdoc.el nsterm.m erc.texi files.el files.texi msdos-xtra.texi ns-win.el basic.texi cmacexp.el compilation.txt - compile-tests.el cscope.el diff.el dired.el editfns.c emacs.texi - files-tests.el find-func-tests.el find-func.el frame.c frame.el - and 16 other files + compile-tests.el cscope.el diff.el dired.el display.texi editfns.c + emacs.texi files-tests.el find-func-tests.el find-func.el frame.c + and 18 other files Daniel McClanahan: changed lisp-mode.el @@ -1273,7 +1272,7 @@ David Hedbor: changed nnmail.el David Hull: changed etags.c vc-hg.el -David Hunter: changed flymake.el inc/ms-w32.h process.c +David Hunter: changed flymake.el ms-w32.h process.c David J. Biesack: changed antlr-mode.el quickurl.el @@ -1477,7 +1476,7 @@ and changed xref.el ruby-mode.el project.el vc-git.el elisp-mode.el etags.el ruby-mode-tests.el js.el vc.el vc-hg.el package.el symref/grep.el dired-aux.el simple.el log-edit.el minibuffer.el progmodes/grep.el ido.el maintaining.texi menu-bar.el package-test.el - and 123 other files + and 122 other files Dmitry Kurochkin: changed isearch.el @@ -1515,8 +1514,8 @@ and changed dired.el cus-edit.el imenu.el info.el ls-lisp.el menu-bar.el apropos.el bindings.el and 22 other files Earl Hyatt: changed ffap.el seq-tests.el sequences.texi windows.texi - control.texi cus-edit.el hi-lock.el misc.texi pcase-tests.el pcase.el - replace.el search.texi seq.el tab-bar.el + autotype.texi control.texi cus-edit.el hi-lock.el misc.texi + pcase-tests.el pcase.el replace.el search.texi seq.el tab-bar.el E. Choroba: changed cperl-mode.el simple.el @@ -1573,7 +1572,7 @@ Eli Zaretskii: wrote [bidirectional display in xdisp.c] chartab-tests.el coding-tests.el etags-tests.el rxvt.el tty-colors.el and co-wrote help-tests.el and changed xdisp.c display.texi w32.c msdos.c w32fns.c simple.el - files.el fileio.c keyboard.c emacs.c w32term.c text.texi dispnew.c + files.el fileio.c emacs.c keyboard.c w32term.c text.texi dispnew.c w32proc.c files.texi frames.texi configure.ac dispextern.h lisp.h process.c ms-w32.h and 1236 other files @@ -1763,10 +1762,10 @@ Fabrice Nicol: changed etags.c etags.1 Fabrice Niessen: wrote leuven-theme.el and changed org-agenda.el -Fabrice Popineau: changed w32.c ms-w32.h w32fns.c w32heap.c w32term.c +Fabrice Popineau: changed ms-w32.h w32.c w32fns.c w32heap.c w32term.c configure.ac lisp.h unexw32.c buffer.c emacs.c image.c w32heap.h w32proc.c w32term.h INSTALL addsection.c alloc.c dispextern.h - emacs-regex.c emacs-x64.manifest emacs-x86.manifest and 25 other files + emacs-x64.manifest emacs-x86.manifest etags.c and 24 other files Fan Kai: changed esh-arg.el @@ -1784,6 +1783,8 @@ Felicián Németh: changed project.el xref.el Felipe Ochoa: changed faces.el js.el paren.el +Felix Dietrich: changed tramp-archive.el + Felix E. Klee: co-wrote svg.el and changed display.texi @@ -1821,7 +1822,7 @@ Florian Adamsky: changed recentf.el Florian Beck: changed org.el -Florian Ragwitz: changed gnus-html.el mail/sieve-manage.el +Florian Ragwitz: changed gnus-html.el sieve-manage.el Florian V. Savigny: changed sql.el @@ -1949,7 +1950,7 @@ and changed edebug.el cl-print.el edebug.texi emacs-lisp/debug.el cl-print-tests.el debugging.texi cl-macs.el edebug-test-code.el subr.el testcases.el testcover.el cl-generic.el ert-x.el eval.c eieio-compat.el elisp.texi ert.el ert.texi eval-tests.el generator.el print.c - and 24 other files + and 23 other files Geoff Gole: changed align.el ibuffer.el whitespace.el @@ -1960,9 +1961,9 @@ Geoff Kuenning: changed gnus-art.el gnus.texi Geoff Voelker: wrote ms-w32.h w32-fns.el w32.c w32.h w32heap.c w32heap.h w32inevt.c w32proc.c w32term.c and changed makefile.nt w32fns.c fileio.c makefile.def callproc.c - s/ms-w32.h emacs.bat.in unexw32.c w32term.h dos-w32.el loadup.el - w32-win.el emacs.c keyboard.c ntterm.c process.c w32console.c addpm.c - cmdproxy.c comint.el files.el and 100 other files + emacs.bat.in unexw32.c w32term.h dos-w32.el loadup.el w32-win.el + emacs.c keyboard.c ntterm.c process.c w32console.c addpm.c cmdproxy.c + comint.el files.el sysdep.c and 97 other files Georg C. F. Greve: changed pgg-gpg.el @@ -2008,7 +2009,7 @@ and changed configure.ac Makefile.in src/Makefile.in calendar.el lisp/Makefile.in diary-lib.el files.el make-dist rmail.el progmodes/f90.el bytecomp.el admin.el misc/Makefile.in simple.el authors.el startup.el emacs.texi lib-src/Makefile.in display.texi - ack.texi subr.el and 1790 other files + ack.texi subr.el and 1786 other files Glynn Clements: wrote gamegrid.el snake.el tetris.el @@ -2120,6 +2121,8 @@ Harald Meland: changed gnus-art.el gnus-salt.el gnus-score.el Harri Kiiskinen: changed org-protocol.el ox-publish.el +Hayden Shenk: changed tramp-adb.el + H. Dieter Wilhelm: changed calc-help.el maintaining.texi paragraphs.el Heiko Muenkel: changed b2m.c @@ -2218,7 +2221,8 @@ Ihor Radchenko: changed fns.c Iku Iwasa: changed auth-source-pass-tests.el auth-source-pass.el -Ikumi Keita: changed characters.el japan-util.el kinsoku.el minibuf.c +Ikumi Keita: changed characters.el display.texi files.el japan-util.el + kinsoku.el minibuf.c Ilja Weis: co-wrote gnus-topic.el @@ -2232,7 +2236,7 @@ Ilya Shlyakhter: changed org.el ob-lilypond.el org-clock.el Ilya Zakharevich: wrote tmm.el and co-wrote cperl-mode.el and changed w32fns.c syntax.c intervals.c syntax.h textprop.c dired.c - emacs-regex.c emacs-regex.h font-lock.el intervals.h search.c + font-lock.el intervals.h regex-emacs.c regex-emacs.h search.c Ilya Zonov: changed org-mouse.el @@ -2456,7 +2460,7 @@ Jason Rumney: wrote w32-vars.el and changed w32fns.c w32term.c w32font.c w32menu.c w32-win.el w32term.h w32.c w32uniscribe.c w32-fns.el makefile.nt w32console.c w32bdf.c configure.bat keyboard.c w32proc.c w32select.c font.c image.c w32font.h - w32gui.h xdisp.c and 153 other files + w32gui.h xdisp.c and 152 other files Jason S. Cornez: changed keyboard.c @@ -2521,7 +2525,7 @@ and changed mh-e.el mh-comp.el mh-utils.el mh-mime.el mh-customize.el Jeff Spencer: changed dired.el -Jeff Walsh: changed xwidget.c +Jeff Walsh: changed comp.c xwidget.c Jelle Licht: changed auth-source-pass-tests.el auth-source-pass.el @@ -2573,8 +2577,8 @@ Jesper Harder: wrote yenc.el and changed gnus-sum.el gnus-art.el message.el gnus-group.el gnus-msg.el gnus.el gnus-util.el rfc2047.el mm-bodies.el mm-util.el mml.el mm-decode.el nnrss.el gnus-srvr.el gnus-topic.el nnmail.el - gnus-start.el gnus-uu.el spam-stat.el gnus-score.el gnus.texi - and 202 other files + gnus-start.el gnus-uu.el gnus.texi spam-stat.el gnus-score.el + and 200 other files Jhair Tocancipa Triana: changed gnus-audio.el @@ -2796,7 +2800,7 @@ and changed epa.el epa-file.el lisp-mnt.el tips.texi dired-aux.el dired-x.el dired.el eieio.el epa-dired.el font-lock.el progmodes/compile.el simple.el allout.el button.el comint.el cus-edit.el eldoc.el emacs-module-tests.el epa-hook.el epg-config.el - epg.el and 9 other files + epg.el and 11 other files Jonas Hoersch: changed org-inlinetask.el org.el @@ -2903,7 +2907,7 @@ and co-wrote help-tests.el keymap-tests.el and changed subr.el desktop.el w32fns.c faces.el simple.el emacsclient.c files.el server.el bs.el help-fns.el xdisp.c org.el w32term.c w32.c buffer.c keyboard.c ido.el image.c window.c eval.c allout.el - and 1226 other files + and 1223 other files Juan Pechiar: changed ob-octave.el @@ -2926,7 +2930,7 @@ Julien Danjou: wrote erc-desktop-notifications.el gnus-gravatar.el and co-wrote color.el and changed shr.el org-agenda.el gnus-art.el nnimap.el gnus-html.el gnus.el message.el gnus-group.el gnus-sum.el gnus-util.el mm-decode.el - mm-view.el org.el gnus.texi mail/sieve-manage.el nnir.el mm-uu.el + mm-view.el org.el gnus.texi nnir.el sieve-manage.el mm-uu.el color-lab.el gnus-demon.el gnus-int.el gnus-msg.el and 96 other files Julien Gilles: wrote gnus-ml.el @@ -2942,8 +2946,8 @@ Jure Cuhalev: changed ispell.el Jürgen Hartmann: changed window.el Jürgen Hötzel: wrote tramp-adb.el -and changed tramp-gvfs.el tramp-sh.el comint.el em-unix.el esh-util.el - tramp-cache.el tramp.el url-handlers.el wid-edit.el +and changed tramp-gvfs.el tramp-sh.el callproc.c comint.el em-unix.el + esh-util.el tramp-cache.el tramp.el url-handlers.el wid-edit.el Juri Linkov: wrote compose.el files-x.el misearch.el repeat-tests.el replace-tests.el tab-bar-tests.el tab-bar.el tab-line.el @@ -3048,7 +3052,7 @@ Katsumi Yamaoka: wrote canlock.el and changed gnus-art.el gnus-sum.el message.el mm-decode.el gnus.texi mm-util.el mm-view.el gnus-group.el gnus-util.el gnus-msg.el mml.el shr.el rfc2047.el gnus-start.el gnus.el nntp.el gnus-agent.el nnrss.el - mm-uu.el nnmail.el emacs-mime.texi and 161 other files + mm-uu.el nnmail.el emacs-mime.texi and 159 other files Kaushal Modi: changed dired-aux.el files.el isearch.el apropos.el calc-yank.el custom.texi desktop.el dired.el dired.texi ediff-diff.el @@ -3062,7 +3066,7 @@ Kaveh R. Ghazi: changed delta88k.h xterm.c Kayvan Sylvan: changed supercite.el Kazuhiro Ito: changed coding.c uudecode.el flow-fill.el font.c - japan-util.el keyboard.c make-mode.el net/starttls.el xdisp.c + japan-util.el keyboard.c make-mode.el starttls.el xdisp.c Kazushi Marukawa: changed filelock.c hexl.c profile.c unexalpha.c @@ -3147,7 +3151,7 @@ and changed edt.texi Kevin Gallo: wrote w32-win.el and changed makefile.nt dispnew.c addpm.c config.w95 dispextern.h emacs.c facemenu.el faces.el fns.c frame.c frame.h keyboard.c makefile.def - mouse.el ntterm.c process.c s/ms-w32.h scroll.c startup.el sysdep.c + mouse.el ms-w32.h ntterm.c process.c scroll.c startup.el sysdep.c term.c and 18 other files Kevin Greiner: wrote legacy-gnus-agent.el @@ -3304,10 +3308,10 @@ and co-wrote gnus-kill.el gnus-mh.el gnus-msg.el gnus-score.el mm-encode.el mm-util.el nnbabyl.el nndoc.el nneething.el nnfolder.el nnheader.el nnimap.el nnmbox.el nnmh.el nnml.el nnspool.el nnvirtual.el rfc2047.el svg.el time-date.el -and changed gnus.texi simple.el subr.el files.el process.c text.texi - display.texi dired.el gnutls.c gnus-ems.el smtpmail.el help-fns.el +and changed gnus.texi simple.el subr.el files.el process.c display.texi + text.texi dired.el gnutls.c gnus-ems.el smtpmail.el help-fns.el auth-source.el url-http.el edebug.el image.el gnus-cite.el pop3.el - dired-aux.el fns.c image.c and 860 other files + dired-aux.el fns.c image.c and 866 other files Lars Rasmusson: changed ebrowse.c @@ -3379,6 +3383,8 @@ Liang Wang: changed etags.el Liāu, Kiong-Gē 廖宮毅: changed comp.c mingw-cfg.site +Lin Zhou: changed w32fns.c w32term.h + Lixin Chin: changed bibtex.el Lloyd Zusman: changed mml.el pgg-gpg.el @@ -3732,7 +3738,7 @@ Mattias Engdegård: changed byte-opt.el rx.el rx-tests.el searching.texi bytecomp-tests.el bytecomp.el calc-tests.el progmodes/compile.el subr.el autorevert.el gdb-mi.el files.el regex-emacs-tests.el mouse.el regexp-opt.el replace.el calc.el coding.c filenotify.el regex-emacs.c - calc-ext.el and 537 other files + calc-ext.el and 539 other files Mattias M: changed asm-mode-tests.el asm-mode.el @@ -3775,7 +3781,7 @@ and co-wrote tramp-cache.el tramp-sh.el tramp.el and changed tramp.texi tramp-adb.el trampver.el trampver.texi dbusbind.c files.el ange-ftp.el file-notify-tests.el files.texi dbus.texi autorevert.el tramp-fish.el kqueue.c tramp-gw.el os.texi shell.el - tramp-imap.el gitlab-ci.yml lisp.h README xesam.el and 280 other files + tramp-imap.el gitlab-ci.yml lisp.h README xesam.el and 278 other files Michael Ben-Gershon: changed acorn.h configure.ac riscix1-1.h riscix1-2.h unexec.c @@ -3878,8 +3884,8 @@ Michael Staats: wrote pc-select.el Michael Vehrs: changed quail.el woman.el Michael Welsh Duggan: changed nnimap.el lisp.h sh-script.el w32term.c - buffer.c gnus-spec.el gud.el keyboard.c mail/sieve-manage.el nnir.el - nnmail.el print.c termhooks.h url-http.el w32-win.el w32fns.c w32menu.c + buffer.c gnus-spec.el gud.el keyboard.c nnir.el nnmail.el print.c + sieve-manage.el termhooks.h url-http.el w32-win.el w32fns.c w32menu.c w32term.h woman.el xdisp.c xterm.c Michael Weylandt: changed ox-latex.el @@ -3897,11 +3903,11 @@ Michał Krzywkowski: changed elide-head.el Michal Nazarewicz: wrote cc-mode-tests.el descr-text-tests.el tildify-tests.el and co-wrote tildify.el -and changed emacs-regex.c casefiddle.c simple.el - test/src/regex-emacs-tests.el casefiddle-tests.el emacs-regex.h - message.el search.c buffer.h cc-mode.el cc-mode.texi ert-x.el files.el - frame.c remember.el sgml-mode.el unidata-gen.el README - SpecialCasing.txt bindings.el buffer.c and 41 other files +and changed regex-emacs.c casefiddle.c regex-emacs-tests.el simple.el + casefiddle-tests.el message.el regex-emacs.h search.c buffer.h + cc-mode.el cc-mode.texi ert-x.el files.el frame.c remember.el + sgml-mode.el unidata-gen.el README SpecialCasing.txt bindings.el + buffer.c and 41 other files Michal Nowak: changed gnutls.el @@ -4168,7 +4174,7 @@ Nils Ackermann: changed message.el nnmh.el reftex-vars.el Nitish Chinta: changed progmodes/python.el sendmail.el simple.el -N. Jackson: changed emacs.texi forms.texi os.texi +N. Jackson: changed emacs.texi forms.texi gnus.info os.texi Noah Evans: changed follow.el @@ -4187,7 +4193,7 @@ Noam Postavsky: changed progmodes/python.el lisp-mode.el bytecomp.el lisp-mode-tests.el term.el xdisp.c cl-macs.el eval.c simple.el data.c emacs-lisp/debug.el modes.texi help-fns.el subr.el elisp-mode.el ert.el isearch.el processes.texi search.c cl-print.el diff-mode.el - and 363 other files + and 362 other files Nobuyoshi Nakada: co-wrote ruby-mode.el and changed ruby-mode-tests.el @@ -4307,7 +4313,7 @@ and co-wrote cal-dst.el and changed lisp.h configure.ac alloc.c fileio.c process.c editfns.c sysdep.c xdisp.c fns.c image.c keyboard.c data.c emacs.c lread.c xterm.c eval.c gnulib-comp.m4 callproc.c Makefile.in frame.c buffer.c - and 1854 other files + and 1847 other files Paul Fisher: changed fns.c @@ -4508,9 +4514,9 @@ Philipp Stephani: wrote callint-tests.el checkdoc-tests.el cl-preloaded-tests.el ediff-diff-tests.el eval-tests.el ido-tests.el lread-tests.el mouse-tests.el startup-tests.el xt-mouse-tests.el and changed emacs-module.c emacs-module-tests.el configure.ac json.c - process.c eval.c json-tests.el process-tests.el internals.texi alloc.c + process.c eval.c internals.texi json-tests.el process-tests.el alloc.c emacs-module.h.in emacs.c lread.c nsterm.m lisp.h pdumper.c bytecomp.el - callproc.c seccomp-filter.c gtkutil.c files.el and 179 other files + callproc.c seccomp-filter.c gtkutil.c files.el and 184 other files Phillip Lord: wrote ps-print-tests.el w32-feature.el and changed build-zips.sh build-dep-zips.py lisp/Makefile.in undo.c @@ -4565,8 +4571,8 @@ and changed xdisp.c comp.c fns.c pdumper.c alloc.c byte-opt.el comp-tests.el comp.el composite.c and 28 other files Po Lu: changed xdisp.c anti.texi browse-url.el callproc.c cc-compat.el - config.bat esh-cmd.el fileio.c langinfo.h loadup.el msdos.c msdos.h - nsfns.m nsterm.m process.c sed1v2.inp sed2v2.inp sed3v2.inp + config.bat esh-cmd.el fileio.c langinfo.h loadup.el mouse.el msdos.c + msdos.h nsfns.m nsterm.m process.c sed1v2.inp sed2v2.inp sed3v2.inp sedlibmk.inp tooltip.el xterm.c Pontus Michael: changed simple.el @@ -4663,7 +4669,7 @@ Reiner Steib: wrote gmm-utils.el and changed message.el gnus.texi gnus-art.el gnus-sum.el gnus-group.el gnus.el mml.el gnus-faq.texi mm-util.el gnus-score.el message.texi gnus-msg.el gnus-start.el gnus-util.el spam-report.el mm-uu.el spam.el - mm-decode.el files.el gnus-agent.el nnmail.el and 172 other files + mm-decode.el files.el gnus-agent.el nnmail.el and 171 other files Remek Trzaska: changed gnus-ems.el @@ -4697,6 +4703,8 @@ Richard Dawe: changed config.in src/Makefile.in Richard G. Bielawski: changed modes.texi paren.el +Richard Hansen: changed easy-mmode.el + Richard Hoskins: changed message.el Richard Kim: wrote wisent/python.el @@ -4727,7 +4735,7 @@ and co-wrote cc-align.el cc-cmds.el cc-defs.el cc-engine.el cc-langs.el and changed files.el keyboard.c simple.el xterm.c xdisp.c rmail.el fileio.c process.c sysdep.c buffer.c xfns.c window.c subr.el configure.ac startup.el sendmail.el emacs.c Makefile.in editfns.c - info.el dired.el and 1338 other files + info.el dired.el and 1336 other files Richard Ryniker: changed sendmail.el @@ -4777,7 +4785,7 @@ Robert Pluim: wrote nsm-tests.el and changed configure.ac process.c blocks.awk network-stream-tests.el font.c processes.texi ftfont.c gtkutil.c vc-git.el process-tests.el emoji-zwj.awk gnutls.el network-stream.el nsm.el tramp.texi mml-sec.el - nsterm.m unicode xfns.c auth.texi composite.c and 134 other files + nsterm.m unicode xfns.c auth.texi composite.c and 136 other files Robert Thorpe: changed cus-start.el indent.el rmail.texi @@ -5033,6 +5041,7 @@ Sergey Poznyakoff: changed rmail.el mh-mime.el rmail.texi smtpmail.el Sergey Trofimov: changed window.el Sergey Vinokurov: changed emacs-module-tests.el emacs-module.c + memory-report.el Sergio Durigan Junior: changed eudcb-bbdb.el gdb-mi.el @@ -5114,9 +5123,8 @@ and co-wrote gnus-sieve.el gssapi.el mml1991.el nnfolder.el nnimap.el nnml.el rot13.el sieve-manage.el and changed message.el gnus-sum.el gnus-art.el smtpmail.el pgg-gpg.el pgg.el gnus-agent.el mml2015.el mml.el gnus-group.el mm-decode.el - gnus-msg.el gnus.texi mail/sieve-manage.el pgg-pgp5.el browse-url.el - gnus-int.el gnus.el hashcash.el mm-view.el password.el - and 101 other files + gnus-msg.el gnus.texi pgg-pgp5.el browse-url.el gnus-int.el gnus.el + hashcash.el mm-view.el password.el gnus-cache.el and 99 other files Simon Lang: changed building.texi icomplete.el misterioso-theme.el progmodes/grep.el @@ -5171,7 +5179,7 @@ and co-wrote help-tests.el keymap-tests.el and changed efaq.texi checkdoc.el package.el cperl-mode.el bookmark.el help.el keymap.c subr.el simple.el erc.el ediff-util.el idlwave.el time.el bytecomp-tests.el comp.el speedbar.el bytecomp.el edebug.el - emacs-lisp-intro.texi flyspell.el ibuffer.el and 1337 other files + emacs-lisp-intro.texi flyspell.el ibuffer.el and 1339 other files Stefan Merten: co-wrote rst.el @@ -5188,7 +5196,7 @@ and co-wrote font-lock.el gitmerge.el pcvs.el and changed subr.el simple.el keyboard.c bytecomp.el cl-macs.el files.el lisp.h vc.el xdisp.c alloc.c eval.c sh-script.el progmodes/compile.el keymap.c buffer.c window.c tex-mode.el lisp-mode.el newcomment.el - help-fns.el lread.c and 1616 other files + help-fns.el lread.c and 1612 other files Stefano Facchini: changed gtkutil.c @@ -5336,10 +5344,9 @@ Svante Carl V. Erichsen: changed cl-indent.el Svend Tollak Munkejord: changed deuglify.el Sven Joachim: changed files.el de-refcard.tex dired-aux.el emacs.1 - arc-mode.el dired-x.el doc/misc/gnus.texi em-cmpl.el em-hist.el - em-ls.el esh-cmd.el esh-ext.el esh-io.el files.texi gnus-sum.el - gnus.texi help.el make-dist message.el movemail.c mule.texi - and 9 other files + gnus.texi arc-mode.el dired-x.el em-cmpl.el em-hist.el em-ls.el + esh-cmd.el esh-ext.el esh-io.el files.texi gnus-sum.el help.el + make-dist message.el movemail.c mule.texi sed3v2.inp and 8 other files Sylvain Chouleur: changed gnus-icalendar.el icalendar.el @@ -5366,7 +5373,7 @@ Takahashi Naoto: wrote ethio-util.el language/ethiopic.el latin-post.el and co-wrote latin-ltx.el quail.el and changed ethiopic.el fontset.el mule-conf.el -Takai Kousuke: changed ccl.el image/compface.el +Takai Kousuke: changed ccl.el compface.el Takeshi Yamada: changed fns.c @@ -5471,7 +5478,7 @@ Thomas Dye: changed org.texi org-bibtex.el ob-R.el org.el Thomas Fitzsimmons: wrote soap-client.el and changed soap-inspect.el ldap.el eudc.texi eudc-vars.el eudc.el - ntlm.el url-http.el eudcb-ldap.el eudcb-bbdb.el ntlm-tests.el + ntlm.el url-http.el eudcb-bbdb.el eudcb-ldap.el ntlm-tests.el eudc-bob.el eudc-export.el eudcb-ph.el package.el README authinfo diary-lib.el display.texi eudc-hotlist.el eudcb-macos-contacts.el icalendar.el and 3 other files @@ -5676,8 +5683,8 @@ Tsuchiya Masatoshi: changed gnus-art.el mm-view.el gnus-sum.el Tsugutomo Enami: changed frame.c keyboard.c configure.ac dispnew.c fileio.c process.c simple.el sysdep.c xdisp.c add-log.el bytecomp.el - editfns.c emacs-regex.c emacs-regex.h emacs.c frame.h gnus-group.el - netbsd.h nnheader.el nnimap.el perl-mode.el and 6 other files + editfns.c emacs.c frame.h gnus-group.el netbsd.h nnheader.el nnimap.el + perl-mode.el regex-emacs.c regex-emacs.h and 6 other files Tsuyoshi Akiho: changed gnus-sum.el nnrss.el @@ -5786,6 +5793,8 @@ and changed ps-prin1.ps ps-bdf.el ps-prin0.ps blank-mode.el ps-prin3.ps easymenu.el loading.texi menu-bar.el misc.texi progmodes/compile.el ps-print-def.el ps-vars.el +Visuwesh M: changed dired-aux.el + Vitalie Spinu: changed comint.el eieio-base.el message.el ob-R.el ob-core.el ob-tangle.el subr.el commit 995490d8c7b48167803354a66abe1cad664fe427 Merge: 8f4b2adb4d f1de6c0e28 Author: Stefan Kangas Date: Wed Jun 29 15:34:22 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: f1de6c0e28 Bump Emacs version to 28.1.90 commit 8f4b2adb4d362e3f6fa9bfa1034771177af5a4c3 Merge: a4b95d3c34 6c26f089a7 Author: Stefan Kangas Date: Wed Jun 29 15:34:22 2022 +0200 Merge from origin/emacs-28 6c26f089a7 Update ChangeLog and AUTHORS for 28.1.90 pretest # Conflicts: # ChangeLog.3 # etc/AUTHORS commit a4b95d3c3497f07137321d8b7e3b4818420fe49e Merge: 26e838e1df 7f749e44db Author: Stefan Kangas Date: Wed Jun 29 15:34:21 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: 7f749e44db ; Auto-commit of loaddefs files. commit 26e838e1df66a5b53ebc06ee4635bf59587375a6 Merge: 6606c14d36 bf137fdbd2 Author: Stefan Kangas Date: Wed Jun 29 15:34:21 2022 +0200 Merge from origin/emacs-28 bf137fdbd2 ; * admin/make-tarball.txt: Small clarification. commit 6606c14d36bc5688a4dc5064ba327935657d657d Merge: d3492bcf30 3d91d55432 Author: Stefan Kangas Date: Wed Jun 29 15:34:21 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: 3d91d55432 Update Tramp version (don't merge with master) commit d3492bcf3075ba1ca18fb9e759878c8467ae838c Author: Po Lu Date: Wed Jun 29 21:24:51 2022 +0800 Fix handling invalidated selection requests * src/xselect.c (x_handle_selection_request): Correctly punt when !dpyinfo. diff --git a/src/xselect.c b/src/xselect.c index 7993899b2c..5796b0034a 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -812,7 +812,7 @@ x_handle_selection_request (struct selection_input_event *event) pushed = false; if (!dpyinfo) - goto DONE; + goto REALLY_DONE; /* This is how the XDND protocol recommends dropping text onto a target that doesn't support XDND. */ @@ -910,6 +910,9 @@ x_handle_selection_request (struct selection_input_event *event) CALLN (Frun_hook_with_args, Qx_sent_selection_functions, selection_symbol, target_symbol, success ? Qt : Qnil); + /* Used to punt when dpyinfo is NULL. */ + REALLY_DONE: + unbind_to (count, Qnil); } commit f1de6c0e28fdd34227b24efbd7a0eebff90dd33f (tag: refs/tags/emacs-28.1.90) Author: Stefan Kangas Date: Wed Jun 29 15:21:26 2022 +0200 Bump Emacs version to 28.1.90 * README: * configure.ac: * msdos/sed2v2.inp: * nt/README.W32: Bump Emacs version to 28.1.90. diff --git a/README b/README index 559c8aeca0..c822650f6d 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ Copyright (C) 2001-2022 Free Software Foundation, Inc. See the end of the file for license conditions. -This directory tree holds version 28.1.50 of GNU Emacs, the extensible, +This directory tree holds version 28.1.90 of GNU Emacs, the extensible, customizable, self-documenting real-time display editor. The file INSTALL in this directory says how to build and install GNU diff --git a/configure.ac b/configure.ac index 7314eb6978..312243a41c 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ dnl along with GNU Emacs. If not, see . AC_PREREQ(2.65) dnl Note this is parsed by (at least) make-dist and lisp/cedet/ede/emacs.el. -AC_INIT(GNU Emacs, 28.1.50, bug-gnu-emacs@gnu.org, , https://www.gnu.org/software/emacs/) +AC_INIT(GNU Emacs, 28.1.90, bug-gnu-emacs@gnu.org, , https://www.gnu.org/software/emacs/) dnl Set emacs_config_options to the options of 'configure', quoted for the shell, dnl and then quoted again for a C string. Separate options with spaces. diff --git a/msdos/sed2v2.inp b/msdos/sed2v2.inp index fedccef4ef..2914838d8b 100644 --- a/msdos/sed2v2.inp +++ b/msdos/sed2v2.inp @@ -67,7 +67,7 @@ /^#undef PACKAGE_NAME/s/^.*$/#define PACKAGE_NAME ""/ /^#undef PACKAGE_STRING/s/^.*$/#define PACKAGE_STRING ""/ /^#undef PACKAGE_TARNAME/s/^.*$/#define PACKAGE_TARNAME ""/ -/^#undef PACKAGE_VERSION/s/^.*$/#define PACKAGE_VERSION "28.1.50"/ +/^#undef PACKAGE_VERSION/s/^.*$/#define PACKAGE_VERSION "28.1.90"/ /^#undef SYSTEM_TYPE/s/^.*$/#define SYSTEM_TYPE "ms-dos"/ /^#undef HAVE_DECL_GETENV/s/^.*$/#define HAVE_DECL_GETENV 1/ /^#undef SYS_SIGLIST_DECLARED/s/^.*$/#define SYS_SIGLIST_DECLARED 1/ diff --git a/nt/README.W32 b/nt/README.W32 index f0a8c8c326..b02935e51a 100644 --- a/nt/README.W32 +++ b/nt/README.W32 @@ -1,7 +1,7 @@ Copyright (C) 2001-2022 Free Software Foundation, Inc. See the end of the file for license conditions. - Emacs version 28.1.50 for MS-Windows + Emacs version 28.1.90 for MS-Windows This README file describes how to set up and run a precompiled distribution of the latest version of GNU Emacs for MS-Windows. You commit 6c26f089a79f4b665a3a75adbb5dc1087951ce2b Author: Stefan Kangas Date: Wed Jun 29 15:19:55 2022 +0200 Update ChangeLog and AUTHORS for 28.1.90 pretest * ChangeLog.3: * etc/AUTHORS: Update. diff --git a/ChangeLog.3 b/ChangeLog.3 index ecd966fb69..d0ff14117b 100644 --- a/ChangeLog.3 +++ b/ChangeLog.3 @@ -1,3 +1,1226 @@ +2022-06-29 Michael Albinus + + Update Tramp version (don't merge with master) + + * doc/misc/trampver.texi: + * lisp/net/trampver.el: Change version to "2.5.3". + +2022-06-28 Michael Albinus + + Tramp shall not trap unrelated D-Bus errors + + * lisp/net/tramp-gvfs.el (tramp-gvfs-dbus-event-vector): Declare. + (tramp-gvfs-file-name-handler): Let-bind it. + (tramp-gvfs-dbus-event-vector): Fix docstring. + (tramp-gvfs-maybe-open-connection): Do not set it globally. (Bug#56162) + +2022-06-28 Basil L. Contovounesios + + Fix hash table function return values in manual + + * doc/lispref/hash.texi (Hash Access): Reconcile documented return + values of puthash and clrhash with their respective + docstrings (bug#55562). + +2022-06-27 Kyle Meyer + + Update to Org 9.5.4-3-g6dc785 + +2022-06-27 Paul Eggert + + Mention Solaris 10 'make clean' and 'make check' + + Mention further crashes on Solaris 10 + +2022-06-26 Paul Eggert + + Port distribution tarball to Solaris 10 + + * make-dist (taropt): Use 'tar -H ustar' to generate a portable + tar file format instead of a GNU-specific format. Needed now that + Emacs tarballs contain file names longer than 100 bytes, e.g.: + emacs-28.1/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C072AF82DCCCB9A7F1B85FFA10B802DC4ED16703.key + emacs-28.1/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-success.el + Without this patch, extracting a tarball on Solaris 10 fails with + many diagnostics like “tar: ././@LongLink: typeflag 'L' not + recognized, converting to regular file”. + + (cherry picked from commit 4410f5d86997b6b238ff05c2ece338b28e1163b1) + +2022-06-24 Stefan Kangas + + Avoid treating number as an enum in the org manual + + * doc/misc/org.org (The Agenda Dispatcher): Avoid treating number as + enum. + +2022-06-22 Eli Zaretskii + + Improve last change in autotype.texi + + * doc/misc/autotype.texi (Autoinserting): Fix wording. Suggested + by Richard Stallman . + +2022-06-21 Stefan Kangas + + * lisp/repeat.el (repeat-mode): Fix message format. + +2022-06-21 Earl Hyatt + + Clarify autotype.texi text slightly + + * doc/misc/autotype.texi (Autoinserting): Make text slightly + clearer (bug#56118). + +2022-06-20 Eli Zaretskii + + Support builds configured with a separate --bindir + + * src/emacs.c (load_pdump): Don't overwrite the leading + directories of the Emacs executable just because the pdumper file + was not found in the expected directory relative to the binary. + This is needed to support builds with a separate --bindir + configure-time option and native-compilation. (Bug#55741) + +2022-06-20 Stefan Kangas + + * doc/misc/eww.texi (Overview, Basics): Fix typos. + +2022-06-18 Richard Hansen + + Fix invalid defcustom :group when :predicate is used + + * lisp/emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Fix + invalid `:group' argument for the `-modes' defcustom that is created + when `:predicate' is used (bug#56049). + +2022-06-17 Lars Ingebrigtsen + + Prune the Gnus FAQ of some outdated data + + * doc/misc/gnus-faq.texi (FAQ 9-2): Remove some outdated advice + (bug#56042). + +2022-06-17 Lars Ingebrigtsen + + Fix efaq-w32.texi build warning + + * doc/misc/efaq-w32.texi (Other useful ports): Fix ordering to + match nodes (or should the nodes be moved instead?). + + Do not merge to master. + +2022-06-17 Lars Ingebrigtsen + + Update cl-struct-sequence-type doc string + + * lisp/emacs-lisp/cl-macs.el (cl-struct-sequence-type): Fix doc + string to reflect what it does (bug#46523). + +2022-06-17 Lars Ingebrigtsen + + Fix a tagging problem in tramp.texi + + * doc/misc/tramp.texi (Frequently Asked Questions): Restore an + @end lisp removed by accident. + +2022-06-17 Lars Ingebrigtsen + + Mention face quirks after the final line in the lispref manual + + * doc/lispref/display.texi (Face Attributes): Mention the quirks + about point after the final line (bug#56011). + +2022-06-17 Stefan Kangas + + Delete reference to obsolete library complete.el + + * doc/misc/tramp.texi (Frequently Asked Questions): Delete reference + to obsolete library complete.el. + +2022-06-16 Stefan Kangas + + * lisp/textmodes/artist.el: Minor doc fixes. + +2022-06-16 Michael Albinus + + * lisp/net/tramp.el (tramp-methods): Fix quoting in docstring. + +2022-06-16 Arash Esbati + + Update MS Windows FAQ for MinGW64-w64/MSYS2 + + * doc/misc/efaq-w32.texi (Compiling, Debugging): Mention + MinGW64-w64/MSYS2 as the preferred way for building Emacs on + capable systems. + (Attachments with Gnus): Catch up with emacs-mime.texi in the + example given. + (Spell check): Add the availability of GNU Aspell and Hunspell + in MSYS2 distribution. + (Other useful ports): Add an entry for MinGW64-w64/MSYS2. + Fix link for MinGW homepage. + Remove entry for defunct UWIN project. (Bug#55930) + +2022-06-15 Robert Pluim + + Describe 'set-file-modes' argument prompting + + * src/fileio.c (Fset_file_modes): Document that FILENAME is prompted + for. (Bug#55984) + +2022-06-14 Lars Ingebrigtsen + + Revert "Clarify what a Calc registeri in in calc-insert-register" + + This reverts commit 73400e4002ce8fca060093548e6791b3a784eeaa. + + This has been fixed in Emacs 29 by making it possible to use regular registers in calc. + +2022-06-13 Lars Ingebrigtsen + + Clarify what a Calc registeri in in calc-insert-register + + * lisp/calc/calc-yank.el (calc-insert-register): Note that these + aren't normal registers (bug#55943). + +2022-06-11 Eli Zaretskii + + Fix doc strings in whitespace.el + + * lisp/whitespace.el (whitespace-style, whitespace-action): + Untabify the doc strings. (Bug#55904) + +2022-06-10 Eli Zaretskii + + Improve documentation of "etags -I" + + * doc/man/etags.1: + * doc/emacs/maintaining.texi (Create Tags Table): Elaborate on the + importance of the '-I' option to 'etags'. (Bug#45246) + +2022-06-09 Lars Ingebrigtsen + + Mention the #f syntax from cl-prin1 + + * doc/lispref/objects.texi (Special Read Syntax): Mention #f, + which is in cl-prin1 output (bug#55853). + +2022-06-09 Michael Albinus + + Fix file name quoting in tramp-smb.el (do not merge) + + * lisp/net/tramp-smb.el (tramp-smb-handle-write-region): Quote tmpfile. + (tramp-smb-get-localname): Remove superfluous test. (Bug#55855) + + * test/lisp/net/tramp-tests.el (tramp-test03-file-name-method-rules): + Remove superfluous checks. + +2022-06-09 Jeff Walsh + + Update error message to reflect variable rename + + * src/comp.c (Fcomp_el_to_eln_filename): Update error message. (Bug#55861) + +2022-06-08 Ken Brown + + Fix error reporting in process-async-https-with-delay + + * test/src/process-tests.el (process-async-https-with-delay): Use + 'plist-get' instead of 'assq' in testing for a connection error. + The 'status' variable is a plist, not an alist. (Bug#55849) + +2022-06-08 Stefan Kangas + + * doc/misc/org.org: Remove spurious markup. + +2022-06-08 Michael Albinus + + Make Tramp version check more robust + + * lisp/net/trampver.el (tramp-repository-branch) + (tramp-repository-version): Check for "git" executable. + +2022-06-07 Eli Zaretskii + + Fix debugging with GDB when a breakpoint has multiple locations + + * lisp/progmodes/gdb-mi.el (gdb-breakpoints--add-breakpoint-row): + New function, extracted from 'gdb-breakpoints-list-handler-custom'. + Don't print "in " for header-rows of breakpoints with + multiple locations that don't have a function name attached. + (gdb-breakpoints-list-handler-custom): Add to the breakpoint table + also any locations in multiple-location breakpoints, which are + supported since GDB 6.8. + +2022-06-05 Eli Zaretskii + + Update documentation of 'aset' and 'store-substring' + + * doc/lispref/strings.texi (Modifying Strings): Adjust to + implementation changes: it is possible for the modified string to + have fewer or more bytes than the original. Add recommendations + regarding unibyte vs multibyte strings and characters. (Bug#55801) + +2022-06-04 Kyle Meyer + + Update to Org 9.5.4 + +2022-06-04 Eli Zaretskii + + Clarify documentation of 'string-to-unibyte' + + * doc/lispref/nonascii.texi (Converting Representations): Clarify + what 'string-to-unibyte' does. Reported by Richard Hansen + . (Bug#55777) + +2022-06-02 Ikumi Keita (tiny change) + + Improve keystrokes in doc strings in some find-file functions + + * lisp/files.el (find-file): + (find-file-other-window): + (find-file-other-frame): Include the correct keymap so that + keystrokes are displayed better (bug#55761). + +2022-06-02 Eli Zaretskii + + Fix segfaults when starting on 80x26 TTY frames + + * src/dispnew.c (adjust_frame_glyphs_for_frame_redisplay): Make + sure we have valid frame glyph matrices for the interactive + session. (Bug#55760) + (adjust_frame_glyphs): Add assertions for when we fail to allocate + valid frame glyph matrices for a TTY frame. + +2022-06-01 Lars Ingebrigtsen + + Make it explicit that a couple of _s in lispref are underscores + + * doc/lispref/strings.texi (Custom Format Strings): + * doc/lispref/control.texi (pcase Macro): Make it explicit that + it's an underscore (bug#55742). + +2022-05-31 Eli Zaretskii + + Remove from FAQ the MS-Windows info about BDF fonts + + * doc/misc/efaq.texi (How to add fonts): Remove the MS-Windows + specific steps, as BDF fonts are no longer supported on + MS-Windows. (Bug#55740) + +2022-05-31 Ikumi Keita (tiny change) + + Fix Display Property manual example + + * doc/lispref/display.texi (Display Property): Fix syntax of + example (bug#55736). + +2022-05-29 Michael Albinus + + Some Tramp cleanup on MS Windows + + * lisp/net/tramp.el (tramp-restricted-shell-hosts-alist): Do not add + localhost when `tramp-encoding-shell' is a POSIX shell. + + * test/lisp/net/tramp-tests.el (tramp-test31-interrupt-process): + Skip on MS Windows. + +2022-05-28 Alan Mackenzie + + do_switch_frame: before leaving mini-window, check other (mru) window is live + + This fixes bug#55684. There, with a minibuffer-only frame at start up, + Emacs tried to switch to this frame, whose selected window was the + mini-window. There is no other active window in this frame, so the + attempt to swith to another window failed. + + * src/frame.c (do_switch_frame): On switching to a frame whose selected + window is as above, before selecting the most recently used window, check + this ostensible window is an actual live window. Otherwise leave the + mini-window selected. + +2022-05-28 Eli Zaretskii + + Fix commands used to produce on-line HTML docs + + * admin/admin.el (manual-meta-string): Only include the first + line, and move the rest... + (manual-links-string): ...to this new string. + (manual-html-fix-headers): Don't remove the ', + see gnu.org ticket #1840138. + +2022-05-28 Eli Zaretskii + + Fix a bad cross-reference in elisp.pdf + + * doc/lispref/control.texi (pcase Macro): Fix a conditional + cross-reference (bug#55689). + +2022-05-28 Eli Zaretskii + + Fix documentation of 'string-pad' + + * doc/lispref/strings.texi (Creating Strings): Fix description of + 'string-pad'. (Bug#55688) + +2022-05-27 Juri Linkov + + Fix more occurrences of renamed kmacro-keymap command + + * doc/emacs/kmacro.texi (Basic Keyboard Macro): Fix documentation + after recent kmacro-redisplay command name change. + +2022-05-27 Eli Zaretskii + + Mention "unspecified-fg" and "unspecified-bg" in some doc strings + + * lisp/faces.el (face-foreground, face-background) + (foreground-color-at-point, background-color-at-point): + * lisp/color.el (color-name-to-rgb): Mention "unspecified-fg" and + "unspecified-bg" pseudo-colors on TTY frames. (Bug#55623) + +2022-05-26 Hayden Shenk (tiny change) + + Fix format specifiers in tramp-adb.el + + * lisp/net/tramp-adb.el (tramp-adb-get-device): Fix format + specifiers for port. (Bug#55651) + +2022-05-22 Damien Cassou + + Improve documentation of mail-user-agent. + + * doc/emacs/sending.texi (Mail Methods): + * lisp/simple.el (mail-user-agent): Mention additional options + of non-bundled MUA. (Bug#5569) + +2022-05-21 Eli Zaretskii + + More fixes in abbrev.el doc strings + + * lisp/abbrev.el (inverse-add-global-abbrev, inverse-add-mode-abbrev): + Document the effect of negative ARG. (Bug#55527) + +2022-05-21 Lars Ingebrigtsen + + Add note about Tramp completion to completion-styles doc string + + * lisp/minibuffer.el (completion-styles): Add note about Tramp + completion (bug#37954). + +2022-05-21 Arash Esbati + + Remove mention of removed nnimap-nov-is-evil variable + + * doc/misc/gnus.texi (Slow/Expensive Connection): Remove mention + of removed nnimap-nov-is-evil variable (bug#55556). + +2022-05-21 Eli Zaretskii + + Improve documentation strings and prompts in abbrev.el + + * lisp/abbrev.el (abbrev-file-name, only-global-abbrevs) + (copy-abbrev-table, insert-abbrevs, list-abbrevs) + (abbrev-table-name, edit-abbrevs, define-abbrevs) + (read-abbrev-file, quietly-read-abbrev-file, write-abbrev-file) + (abbrev-edit-save-to-file, abbrev-edit-save-buffer) + (add-mode-abbrev, add-global-abbrev, inverse-add-mode-abbrev) + (inverse-add-global-abbrev, abbrev-prefix-mark) + (expand-region-abbrevs, abbrev-table-get, abbrev-table-put) + (abbrev-get, abbrev-minor-mode-table-alist, abbrevs-changed) + (abbrev-all-caps, last-abbrev-text, last-abbrev-location) + (clear-abbrev-table, define-abbrev, define-global-abbrev) + (define-mode-abbrev, abbrev--active-tables, abbrev--symbol) + (abbrev-symbol, abbrev-expansion, abbrev-insert) + (abbrev-expand-function, abbrev--suggest-above-threshold) + (abbrev--suggest-saved-recommendations) + (abbrev--suggest-shortest-abbrev, abbrev--suggest-get-totals) + (insert-abbrev-table-description, define-abbrev-table) + (abbrev-table-menu): Fix doc strings: wording, punctuation, + clarity. + (add-abbrev, inverse-add-abbrev): Improve the prompt text. + (Bug#55527) + +2022-05-20 Alan Mackenzie + + Restore the Fselect_window call in gui_consider_frame_title. + + This fixes bug #55412. The call to Fselect_window was removed on 2021-03-21 + in the commit "Prevent open minibuffers getting lost when their frame gets + deleted". This call is actually needed to determine current elements of the + pertinent window and frame when these are used in the frame title. + + * src/frame.c (do_switch_frame): When the selected window in the target frame + is the mini-window, switch away from this window unless there is a valid + minibuffer there. + + * src/frame.h (struct frame): Add an incidental comment about the element + selected_window. + + * src/minibuf.c (move_minibuffers_onto_frame): No longer set the selected + window of the source frame. This action is now performed later, on returning + to that frame, in do_switch_frame when needed (see above). + + * src/xdisp.c (gui_consider_frame_title): Replace the Fselect_window call and + associated ancillary settings. + +2022-05-20 Eli Zaretskii + + Advise against settings in the MS-Windows system registry + + * doc/emacs/cmdargs.texi (MS-Windows Registry): Advise against + setting environment variables in the system registry. (Bug#16429) + +2022-05-17 Lars Ingebrigtsen + + Fix kmacro-keymap binding after previous change + + * lisp/kmacro.el (kmacro-keymap): Fix binding after + kmacro-redisplay command name change. + +2022-05-17 Lars Ingebrigtsen + + Add glossary entries for "interactively" + + * doc/emacs/glossary.texi (Glossary): Mention "interactively" and + how it relates to the "command" concept (bug#55461). + +2022-05-17 Eli Zaretskii + + Fix the name of a kmacro command. + + * lisp/kmacro.el (kmacro-redisplay): Rename from + 'kdb-macro-redisplay' (which was wrong and included a typo). + + * etc/NEWS: Announce the change. (Bug#55471) + +2022-05-17 Michael Albinus + + Fix Tramp sshfs tests (don't merge) + + * test/lisp/net/tramp-tests.el (tramp-fuse-remove-hidden-files): Declare. + (tramp-test16-directory-files) + (tramp-test16-file-expand-wildcards) + (tramp-test26-file-name-completion, tramp--test-check-files): Use it. + (tramp--test-check-files): Delete directory recursively. + +2022-05-17 Michael Albinus + + Some minor Tramp fixes + + * lisp/net/tramp-cmds.el (tramp-list-tramp-buffers) + (tramp-list-remote-buffers): Add ;;;###tramp-autoload cookie. + + * lisp/net/tramp-fuse.el (tramp-fuse-remove-hidden-files): New defvar. + (tramp-fuse-remove-hidden-files): Use it. + + * lisp/net/tramp-gvfs.el (tramp-gvfs-handler-askquestion): + Keep regression tests running. + +2022-05-15 Kyle Meyer + + Update to Org 9.5.3-6-gef41f3 + +2022-05-15 Michael Albinus + + Hide temporary FUSE files in Tramp + + * lisp/net/tramp-fuse.el (tramp-fuse-remove-hidden-files): New defsubst. + (tramp-fuse-handle-directory-files) + (tramp-fuse-handle-file-name-all-completions): Use it. + +2022-05-15 Michael Albinus + + * test/lisp/net/tramp-tests.el (tramp-test27-load): Adapt test. Don't merge + +2022-05-13 Po Lu + + Fix tooltip face overwriting dragged text strings during mouse DND + + * lisp/mouse.el (mouse-drag-and-drop-region): Copy + `text-tooltip' before showing it. Do not merge to master. + +2022-05-13 Eli Zaretskii + + Fix lexical-binding fallout in vhdl-mode.el + + * lisp/progmodes/vhdl-mode.el (arch-alist, pack-alist) + (file-alist, unit-alist, rule-alist): Defvar them, since vhdl-aput + expects them to be dynamically bound. (Bug#55389) + (vhdl-speedbar-insert-hierarchy): Rename the PACK-ALIST argument + to PACKAGE-ALIST, to avoid shadowing the global variable. + +2022-05-12 Michael Albinus + + Fix ControlPath quoting in Tramp + + * lisp/net/tramp-sh.el (tramp-ssh-controlmaster-options): + Adapt docstring. Do not quote ControlPath. Reported by Daniel + Kessler . + +2022-05-09 Eli Zaretskii + + Remove the AUCTeX subsection from MS-Windows FAQ + + * doc/misc/efaq-w32.texi (AUCTeX): Remove the subsection, it is no + longer useful. (Bug#55330) + +2022-05-09 Arash Esbati + + Update AUCTeX FAQ entry + + * doc/misc/efaq-w32.texi (AUCTeX): AUCTeX project isn't providing + pre-compiled versions for Windows anymore (bug#55330). + +2022-05-09 Lars Ingebrigtsen + + Update string-to-number documentation to bignum Emacs + + * doc/lispref/strings.texi (String Conversion): string-to-number + no longer converts integers to floating point numbers (bug#55334). + +2022-05-09 Lars Ingebrigtsen + + Fix doc string references to tags-loop-continue + + * lisp/vc/vc-dir.el (vc-dir-search, vc-dir-query-replace-regexp): + Fix reference to obsolete tags-loop-continue (bug#55311). + +2022-05-08 Visuwesh M + + dired-do-query-replace-regexp doc string fix + + * lisp/dired-aux.el (dired-do-query-replace-regexp): Refer + 'fileloop-continue' instead of the obsolete command + 'tags-loop-continue'. (Bug#55311) + + (cherry picked from commit 4c505203f9171886f47638779326e257a95a1d79) + +2022-05-08 Alan Mackenzie + + Linux console: don't translate ESC TAB to `backtab' in input-decode-map. + + This translation happened after the terminfo entry for TAB in the linux + section was changed to kcbt=\E^I in ncurses version 6.3. + + * lisp/term/linux.el (terminal-init-linux): Add a define-key form to remove + the entry for "\e\t" from input-decode-map. + + * etc/PROBLEMS: Add a new section under "character terminals" about S-TAB + wrongly doing the same thing as M-TAB, giving tips about amending the Linux + keyboard layout. + +2022-05-08 Michael Albinus + + Handle changed scp protocol in Tramp, don't merge + + * lisp/net/tramp-sh.el (tramp-scp-force-scp-protocol): New defvar. + (tramp-scp-force-scp-protocol): New defun. + (tramp-do-copy-or-rename-file-out-of-band): Use it. + (tramp-methods) : Use "%y". + + * lisp/net/tramp.el (tramp-methods): Adapt docstring. + +2022-05-06 Michael Albinus + + Fix bug#55274 + + * lisp/dired-aux.el (dired-do-compress-to): Use `file-local-name' + for shell out-file. (Bug#55274) + +2022-05-06 Eli Zaretskii + + Provide reference for OTF tags in the ELisp manual + + * doc/lispref/display.texi (Low-Level Font): Provide the canonical + reference URL for OTF tags. + +2022-05-05 Lars Ingebrigtsen + + Be more resilient towards errors during error handling + + * src/print.c (print_error_message): Avoid infinite recursion if + `substitute-command-keys' bugs out (bug#55269). + + (cherry picked from commit 8364f058b821eba31f84dcded175cca403a965a5) + +2022-04-28 Eli Zaretskii + + Improve documentation of font- and face-related attribute functions + + * lisp/faces.el (face-attribute): + * src/xfaces.c (Fx_family_fonts): + * src/font.c (Ffont_get, Ffont_put): Improve and clarify the doc + strings. + + * doc/lispref/display.texi (Low-Level Font): Document the :type + attribute of a font. Improve documentation of 'font-get' and + 'font-put'. + (Attribute Functions): Add cross-reference to the description of + face attributes. + +2022-04-25 Kyle Meyer + + Update to Org 9.5.3-3-gd54104 + +2022-04-24 Eli Zaretskii + + Improve indexing in "Programmed Completion" + + * doc/lispref/minibuf.texi (Programmed Completion): Improve + indexing. (Bug#55095) + +2022-04-24 Eli Zaretskii + + Improve documentation of 'set-fontset-font' + + * doc/lispref/display.texi (Fontsets): + * src/fontset.c (Fset_fontset_font): Improve and clarify the + documentation of 'set-fontset-font'. Rename the arguments to be + more self-explanatory. (Bug#55086) + +2022-04-23 Michael Albinus + + Fix problem with Solaris ls in Tramp + + * lisp/net/tramp-sh.el (tramp-sunos-unames): Move up. + (tramp-sh--quoting-style-options): Handle erroneous Solaris ls. + +2022-04-22 Eli Zaretskii + + Another fix for non-ASCII 'overlay-arrow-string' + + * src/xdisp.c (get_overlay_arrow_glyph_row): Fix yet another place + that assumed each character is a single byte. + +2022-04-21 Eli Zaretskii + + Avoid a redisplay loop when 'overlay-arrow-string' is non-ASCII + + * src/xdisp.c (get_overlay_arrow_glyph_row): Don't assume every + character in 'overlay-arrow-string' is one byte long. Reported by + Yuri D'Elia . + +2022-04-21 Eli Zaretskii + + Add minimum instructions to 'query-replace' commands + + * lisp/vc/vc-dir.el (vc-dir-query-replace-regexp): + * lisp/textmodes/reftex-global.el (reftex-query-replace-document): + * lisp/progmodes/project.el (project-query-replace-regexp): + * lisp/progmodes/etags.el (tags-query-replace): + * lisp/progmodes/ebrowse.el (ebrowse-tags-query-replace): + * lisp/isearch.el (isearch-query-replace, isearch-occur): + * lisp/emulation/viper-cmd.el (viper-query-replace): + * lisp/dired-aux.el (dired-do-query-replace-regexp) + (dired-do-find-regexp-and-replace): + * lisp/progmodes/xref.el (xref-query-replace-in-results): + * lisp/replace.el (query-replace, query-replace-regexp) + (query-replace-regexp-eval, map-query-replace-regexp): Add minimal + instructions for dealing with matches, with a link to the command + that shows the full instructions. (Bug#55050) + +2022-04-21 Eli Zaretskii + + Fix customization-group of 'python-forward-sexp-function' + + * lisp/progmodes/python.el (python-forward-sexp-function): Make it + be part of both 'python' and 'python-flymake' groups. (Bug#55027) + Do not merge to master. + +2022-04-20 Paul Eggert + + Update from gnulib + + (cherry picked from commit 992cf3cb675e074079341cc54c3b16d37a8b9ca8) + + This is a partial backport from master: it only includes the changes below. + + * lib/mini-gmp.c (gmp_assert_nocarry): Avoid many Clang + unused-variable warnings when building with optimisation. + * lib/verify.h (_GL_HAVE__STATIC_ASSERT): Modify condition for using + _Static_assert to cope with older Apple builds of Clang exposing + misleading compiler version numbers. See discussion starting at + https://lists.gnu.org/archive/html/emacs-devel/2022-04/msg00779.html + +2022-04-20 Lars Ingebrigtsen + + Revert prompting changes in viper-cmd + + * lisp/emulation/viper-cmd.el (viper-quote-region) + (viper-read-string-with-history, viper-query-replace): Revert + prompting changes done in 50512e3 -- the way viper prompts in + command mode is special (bug#55007). + + Do not merge to master. + +2022-04-19 Lars Ingebrigtsen + + Fix regression with multiple mode: entries in the prop line + + * lisp/files.el (hack-local-variables): Fix regression with multiple + mode: entries in the prop line. + + Do not merge to master. + +2022-04-18 Lars Ingebrigtsen + + Avoid hangs in python-mode with debug-on-error set + + * lisp/progmodes/python.el (python-nav-end-of-statement): Avoid + using cl-assert here, because this is called from the font-lock + machinery, and if debug-on-error is set here, we'll hang Emacs + (bug#54996). + + Do not merge to master. + +2022-04-18 Lars Ingebrigtsen + + Fix major-mode setting regression when there's a mode: cookie + + * lisp/files.el (hack-local-variables): Fix regression in setting + the major mode when there are mode: cookies in the file (bug#54993). + + Do not merge to master. + +2022-04-17 Kyle Meyer + + Update to Org 9.5.2-38-g682ccd + +2022-04-17 Eli Zaretskii + + Revert "Don’t assume openat" + + This reverts commit 3cccf0a9107d585173e527550bbc45253624ca2e. + + This is a change with far-reaching effects on MS-Windows at the least, + where file-related APIs are shadowed to support transparent support + for UTF-8 encoded file names. Making such changes on a stable branch + for the benefit of a proprietary platform with a 13-year old OS is a + tail wagging the dog. Please don't do that without discussing first. + +2022-04-17 Paul Eggert + + Don’t assume openat + + Use openat only on platforms with O_PATH. + This ports to OS X 10.9 and earlier. + Problem reported by Keith David Bershatsky in: + https://lists.gnu.org/r/emacs-devel/2022-04/msg00805.html + * lib-src/emacsclient.c (local_sockname): Use open, not openat. + * src/sysdep.c (sys_openat): New static function, + which uses openat only if O_PATH is defined. + (emacs_openat): Use it instead of openat. + (emacs_openat_noquit): Remove. + (emacs_open_noquit): Reimplement as per the old emacs_openat_noquit, + but use plain 'open'. + +2022-04-17 Paul Eggert + + Fix GC bug in filelock.c + + Fix a bug where if GC occurred at the wrong moment when locking a + file, the lock file’s name was trashed so file locking did not work. + This bug was introduced in Emacs 28.1. The bug sometimes caused + filelock-tests-detect-external-change test failures on Fedora 35 + x86-64 in an en_US.utf8 locale. + * src/filelock.c (lock_file_1, current_lock_owner, lock_if_free) + (lock_file, unlock_file, Ffile_locked_p): + Use Lisp_Object, not char *, for string, so that GC doesn’t trash + string contents. + (make_lock_file_name): Return the encoded name, not the original. + All callers changed. + +2022-04-16 Lars Ingebrigtsen + + Clarify when mode tagging is used + + * etc/NEWS: Clarify when mode tagging is used (bug#54964). + +2022-04-16 Lars Ingebrigtsen + + Further vcs-cvs/rcs-responsible-p updates from master + + * lisp/vc/vc-bzr.el (vc-bzr-responsible-p): + * lisp/vc/vc-sccs.el (vc-sccs-responsible-p): + * lisp/vc/vc-dav.el (vc-dav-responsible-p): Update doc string. + + * lisp/vc/vc-rcs.el (vc-rcs-responsible-p): + * lisp/vc/vc-cvs.el (vc-cvs-responsible-p): Further fixes from + master. + + * lisp/vc/vc-src.el (vc-src-responsible-p): Return the directory. + + * lisp/vc/vc.el: Update comments. + +2022-04-16 Mattias Engdegård + + Fix builds on older versions of macOS + + This adds back macOS-specific code replaced earlier (bug#48548), + specifically to fix build errors on macOS 10.7.5. See discussion at + https://lists.gnu.org/archive/html/emacs-devel/2022-04/msg00779.html . + + * src/sysdep.c (HAVE_RUSAGE_INFO_CURRENT, HAVE_PROC_PIDINFO): New. + (system_process_attributes): Use alternative code or exclude features + when building on older macOS versions. + +2022-04-16 Eli Zaretskii + + Fix documentation of Outline minor mode options + + * lisp/outline.el (outline-minor-mode-cycle-filter) + (outline-minor-mode-cycle, outline-minor-mode-highlight) + (outline-cycle, outline-cycle-buffer): Doc fixes. (Bug#54967) + +2022-04-15 Eli Zaretskii + + Improve discoverability of 'insert-directory-program' + + * lisp/files.el (insert-directory-program): Mention 'dired' in the + doc string. + * lisp/dired.el (dired): Mention 'insert-directory-program' in the + doc string. (Bug#54962) + +2022-04-15 Eli Zaretskii + + Fix cursor motion under truncate-lines with Flymake fringe indicator + + * src/indent.c (Fvertical_motion): Don't consider fringe bitmaps + as "images" for the purpose of vertical-motion logic dealing with + overshooting buffer positions. (Bug#54946) + +2022-04-14 Lars Ingebrigtsen + + Make all vc-*-responsible-p functions return a string + + * lisp/vc/vc-sccs.el (vc-sccs-responsible-p): + * lisp/vc/vc-rcs.el (vc-rcs-responsible-p): + * lisp/vc/vc-dav.el (vc-dav-responsible-p): + * lisp/vc/vc-cvs.el (vc-cvs-responsible-p): Return a file name + instead of t when we get a match (which is what + vc-backend-for-registration expects) (bug#51800). + + This fixes the regression reported in bug#54935. + + Do not merge to master. + +2022-04-14 Eli Zaretskii + + Describe problems with invoking Python on MS-Windows + + * etc/PROBLEMS: Describe problems with running an inferior Python + interpreter due to the MS-Windows "App Execution Aliases" feature. + (Bug#54860) + +2022-04-13 Eli Zaretskii + + A better fix for bug#54800 + + * lisp/calc/calc.el (calc-align-stack-window): Improve scrolling + when windows have non-integral dimensions. + +2022-04-13 Lars Ingebrigtsen + + Add a comment about cl-concatenate + + * lisp/emacs-lisp/cl-extra.el (cl-concatenate): Add a comment. + +2022-04-13 Lars Ingebrigtsen + + Revert "Make cl-concatenate an alias of seq-concatenate" + + This reverts commit 78f76fe16e2737b40694f82af28d17a90a21ed7b. + + The commit made calls to cl-concatenate bug out, since + autoloading defalises doesn't work very well (bug#54901). + +2022-04-12 Eli Zaretskii + + Fix 'window-text-pixel-width' when starting from display property + + * src/xdisp.c (Fwindow_text_pixel_size): Handle the case where + there's a display property at START, and move_it_to overshoots. + Do not merge to master. (Bug#54862) + +2022-04-11 Stefan Monnier + + * lisp/gnus/mm-encode.el (mm-default-file-encoding): Fix "when" arg + +2022-04-11 Eli Zaretskii + + Fix default-directory of buffers visiting files in renamed directories + + * lisp/dired-aux.el (dired-rename-file): Take note of whether FILE + is a directory before it is renamed, which makes it impossible to + determine if it was a directory. + (dired-rename-subdir, dired-rename-subdir-1): Revert to using + dired-in-this-tree-p instead of file-in-directory-p, for the + benefit of files that were renamed/removed, because + file-in-directory-p returns nil in those cases. (Bug#54838) + +2022-04-11 Lars Ingebrigtsen + + Fix a kill-append regression + + * lisp/simple.el (kill-append): Fix a regression when + kill-ring-max is zero (bug#54842). + +2022-04-10 Eli Zaretskii + + * doc/misc/eww.texi (Advanced): Correct outdated info (bug#54839). + +2022-04-10 Eli Zaretskii + + Clean up the MSDOS port + + * src/msdos.h (tcdrain): Redirect to '_dos_commit'. + (openat, fchmodat, futimens, utimensat): Add prototypes. + + * msdos/sed1v2.inp (MAKE_PDUMPER_FINGERPRINT): Fix indentation, so + that Make won't consider this line a command. + ($(etc)/DOC): Chdir back to ../src, since "make-docfile -d" leaves + us in a wrong directory. + * msdos/sedlibmk.inp (GL_GNULIB_GETRANDOM, GL_GNULIB_MEMMEM) + (GL_GNULIB_SIGDESCR_NP): Define to 1, to get the prototypes from + Gnulib headers. + +2022-04-10 Daniel Martín + + Fix typo in next-error-find-buffer-function + + * lisp/simple.el (next-error-find-buffer-function): Fix typo + (bug#54830). + +2022-04-10 Lars Ingebrigtsen + + Revert "Make shell-resync-dirs handle whitespace in directory names" + + This reverts commit 90e65c826fab2092ad2099d7763538194c93e021. + + This change led to hangs (bug#54776). + + Do not merge to master; it has been fixed in a more encompassing way there. + +2022-04-09 Eli Zaretskii + + Fix scrolling of the stack window in Calc + + * lisp/calc/calc.el (calc-align-stack-window): Fix off-by-one + error in computing the window-start point. (Bug#54800) + +2022-04-08 Eli Zaretskii + + Update and fix instructions and scripts for updating the Web pages + + * admin/admin.el (manual-html-fix-index-2): Support Texinfo 6.8 + and later by not converting TOC menus into tables. (Bug#49719) + * admin/upload-manuals (New directory): Invoke "cvs add" in + $webdir, to pick up the correct CVSROOT. + * admin/make-tarball.txt: Update the section about the Emacs Web + pages. + + * etc/refcards/Makefile (pl-refcard.dvi): If mex.fmt cannot be + found, invoke 'mex' instead of 'tex'. + +2022-04-08 Michael Albinus + + Extend tramp-archive-test45-auto-load + + * test/lisp/net/tramp-archive-tests.el (tramp-archive-test45-auto-load): + Extend test. + +2022-04-08 Michael Albinus + + Ensure local `default-directory' in Tramp when needed + + * lisp/net/tramp.el (tramp-process-running-p): Ensure local + `default-directory' when calling `list-system-processes' and + `process-attributes'. + +2022-04-08 Eli Zaretskii + + Clarify "idleness" in the ELisp manual + + * doc/lispref/os.texi (Idle Timers): Clarify that waiting for + input with timeout doesn't make Emacs idle. Suggested by Ignacio + . (Bug#54371) + +2022-04-07 Jürgen Hötzel + + Use correct signal oldset in posix_spawn implementation + + posix_spawn was restoring the wrong signal set, which still had + SIGCHLD and SIGINT masked, causing problems with child processes that + spawned child processes. (Bug#54667) + + See the thread ending at + https://lists.gnu.org/archive/html/emacs-devel/2022-03/msg00067.html + for more details. + + * src/callproc.c (emacs_spawn): Pass oldset parameter. + (emacs_posix_spawn_init_attributes): Use correct oldset. + (emacs_posix_spawn_init): Remove intermediate function. + + (cherry picked from commit 8103b060d89ac63a12c439087bd46c30da72cd97) + +2022-04-07 Felix Dietrich (tiny change) + + Fix error in tramp-archive-autoload-file-name-handler + + * lisp/net/tramp-archive.el (tramp-archive-autoload-file-name-handler): + Always call `tramp-autoload-file-name'. Otherwise, when + `tramp-archive-enabled’ is nil and + `tramp-archive-autoload-file-name-handler’ is in the + `file-name-handler-alist’ results in an error “Invalid handler in + `file-name-handler-alist” once Emacs calls + `tramp-archive-autoload-file-name-handler’ with a handler that + does not expect nil. Always returning nil is also false in + general. + +2022-04-07 Michael Albinus + + Commit missing file from previous commit (Do not merge with master) + + Commit missing file from previous commit + +2022-04-07 Michael Albinus + + Merge with Tramp 2.5.2.3 (Do not merge with master) + + * doc/misc/tramp.texi (Archive file names): Explicitly say how to + open an archive with Tramp (Bug#25076). + + * doc/misc/trampver.texi: + * lisp/net/trampver.el: Change version to "2.5.3-pre". + + * lisp/net/tramp-adb.el (tramp-adb-handle-process-file) + * lisp/net/tramp-sh.el (tramp-sh-handle-process-file): + * lisp/net/tramp-smb.el (tramp-smb-handle-process-file): + * lisp/net/tramp-sshfs.el (tramp-sshfs-handle-process-file): + Improve implementation. (Bug#53854) + + * lisp/net/tramp-adb.el (tramp-adb-tolerate-tilde): + * lisp/net/tramp-sshfs.el (tramp-sshfs-tolerate-tilde): + New defuns. Advice `shell-mode' with them. + + * lisp/net/tramp.el (tramp-register-autoload-file-name-handlers): + * lisp/net/tramp-archive.el (tramp-register-archive-file-name-handler): + Check, whether the real file name handler is already registered. + rules. (Bug#54542) + + * lisp/net/tramp.el (tramp-autoload-file-name-handler) + (tramp-register-autoload-file-name-handlers) + (tramp-unload-file-name-handlers, tramp-unload-tramp): + * lisp/net/tramp-archive.el (tramp-archive-autoload-file-name-regexp) + (tramp-archive-autoload-file-name-handler) + (tramp-register-archive-file-name-handler): + Add `tramp-autoload' property. + + * lisp/net/tramp-crypt.el (tramp-crypt-file-name-handler-alist): + * lisp/net/tramp-rclone.el (tramp-rclone-file-name-handler-alist): + * lisp/net/tramp-sudoedit.el (tramp-sudoedit-file-name-handler-alist): + * lisp/net/tramp-sshfs.el (tramp-sshfs-file-name-handler-alist): + Use `tramp-handle-file-notify-add-watch', + `tramp-handle-file-notify-rm-watch' and + `tramp-handle-file-notify-valid-p'. + + * lisp/net/tramp-crypt.el (tramp-crypt-file-name-handler-alist): + Use `tramp-handle-insert-file-contents'. + + * lisp/net/tramp-gvfs.el (tramp-gvfs-maybe-open-connection): + * lisp/net/tramp-rclone.el (tramp-rclone-maybe-open-connection): + * lisp/net/tramp-sshfs.el (tramp-sshfs-maybe-open-connection): + * lisp/net/tramp-sudoedit.el + (tramp-sudoedit-maybe-open-connection): Do not set "lock-pid" + connection-property. + (tramp-sudoedit-handle-delete-file): Use "rm -f". + + * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-executable-p): + * lisp/net/tramp-sh.el (tramp-sh-handle-file-executable-p): + Check also for setuid/setgid bit. + (tramp-gvfs-handle-expand-file-name): + Respect `tramp-tolerate-tilde'. + + * lisp/net/tramp-sh.el (tramp-sh-handle-insert-directory): + * lisp/net/tramp-smb.el (tramp-smb-handle-insert-directory): + Do not modify disk space information when + `dired--insert-disk-space' is available. (Bug#54512) + + * lisp/net/tramp-sh.el (tramp-maybe-open-connection): Extend suppression + (tramp-get-remote-dev-tty): New defun. + (tramp-sh-handle-make-process): Use it. + + * lisp/net/tramp-sshfs.el (tramp-methods) : + Add "-t -t" to `tramp-login-args'. + Add "-o dir_cache=no" to `tramp-mount-args'. (Bug#54126) + Add "-o transform_symlinks" to `tramp-mount-args'. + (tramp-sshfs-file-name-handler-alist): + Use `tramp-sshfs-handle-file-writable-p'. + (tramp-sshfs-handle-file-writable-p): New defun. (Bug#54130) + (tramp-sshfs-handle-write-region): Set file modification time. + (Bug#54016) + (tramp-sshfs-file-name-handler-alist): + Use `tramp-sshfs-handle-set-file-times'. + (tramp-sshfs-handle-set-file-times): New defun. + + * test/lisp/net/tramp-tests.el (tramp--test-expensive-test-p): + Rename from `tramp--test-expensive-test'. Make it a defun. Adapt + all callees. + (tramp-test07-file-exists-p, tramp-test14-delete-directory) + (tramp-test18-file-attributes, tramp-test20-file-modes) + (tramp-test28-process-file, tramp-test29-start-file-process) + (tramp-test30-make-process, tramp-test32-shell-command) + (tramp-test33-environment-variables, tramp--test-check-files) + (tramp--test-special-characters, tramp-test46-unload): Adapt tests. + (tramp-test39-detect-external-change): New test. + (tramp-test29-start-file-process) + (tramp--test--deftest-direct-async-process) + (tramp-test30-make-process, tramp-test31-interrupt-process) + (tramp-test34-explicit-shell-file-name) + (tramp-test44-asynchronous-requests): + Add :tramp-asynchronous-processes tag. + (tramp--test-asynchronous-processes-p): New defun. + (tramp--test-hpux-p, tramp--test-macos-p): Protect against errors. + +2022-04-06 Stefan Monnier + + cl-generic.el: Fix bug#46722 + + Fix longstanding bug due to unexpected interference via side-effect. + + * lisp/emacs-lisp/cl-generic.el (cl--generic-get-dispatcher): + Copy the `dispatch` arg before storing it into the hash-table. + + Backport from `master` (cherrypick from commit 61f8f7f68f). + +2022-04-05 Eli Zaretskii + + Fix fallout from lexical-binding in vhdl-mode.el + + * lisp/progmodes/vhdl-mode.el (vhdl-update-sensitivity-list): Fix + production of a list with embedded function calls. (Bug#54730) + +2022-04-03 Eli Zaretskii + + Update logs and HISTORY for Emacs 28.1 + + * ChangeLog.3: + * etc/HISTORY: + * etc/AUTHORS: Update for Emacs 28.1 release. + +2022-04-03 Eli Zaretskii + + Bump Emacs version to 28.1 + + * README: + * configure.ac: + * nt/README.W32: + * msdos/sed2v2.inp: Bump Emacs version to 28.1 + 2022-03-30 Tassilo Horn dired: implement feature from 7b50ed553f differently @@ -234978,7 +236201,7 @@ This file records repository revisions from commit 9d56a21e6a696ad19ac65c4b405aeca44785884a (exclusive) to -commit f2ae39829812098d8269eafbc0fcb98959ee5bb7 (inclusive). +commit 7f749e44dbd50430e14f319b4c4d3f767740b10b (inclusive). See ChangeLog.2 for earlier changes. ;; Local Variables: diff --git a/etc/AUTHORS b/etc/AUTHORS index 61bdf93661..b5444e60a7 100644 --- a/etc/AUTHORS +++ b/etc/AUTHORS @@ -68,7 +68,7 @@ Adrian Robert: co-wrote ns-win.el and changed nsterm.m nsfns.m nsfont.m nsterm.h nsmenu.m configure.ac src/Makefile.in macos.texi README config.in emacs.c font.c keyboard.c nsgui.h nsimage.m xdisp.c image.c lib-src/Makefile.in lisp.h menu.c - Makefile.in and 79 other files + Makefile.in and 78 other files Ævar Arnfjörð Bjarmason: changed rcirc.el @@ -106,8 +106,8 @@ and co-wrote cc-align.el cc-cmds.el cc-defs.el cc-engine.el cc-fonts.el and changed cc-mode.texi minibuf.c bytecomp.el edebug.el follow.el window.c display.texi subr.el syntax.texi progmodes/compile.el programs.texi eval.c keyboard.c lisp.h modes.texi window.el - windows.texi cus-start.el font-lock.el isearch.el newcomment.el - and 166 other files + windows.texi cus-start.el font-lock.el frame.c isearch.el + and 167 other files Alan Modra: changed unexelf.c @@ -433,16 +433,17 @@ Ansgar Burchardt: changed latin-ltx.el Antoine Beaupré: changed vc-git.el -Antoine Levitt: changed gnus-group.el gnus-sum.el message.texi ada-prj.el +Antoine Levitt: changed gnus-group.el gnus-sum.el message.texi ange-ftp.el cus-edit.el dired-x.el ebnf2ps.el emerge.el erc-button.el erc-goodies.el erc-stamp.el erc-track.el files.el find-file.el gnus-art.el gnus-uu.el gnus.el gnus.texi message.el mh-funcs.el - and 8 other files + mh-mime.el and 7 other files Antonin Houska: changed newcomment.el -Arash Esbati: changed reftex-vars.el reftex-auc.el reftex-ref.el - reftex.el nnmaildir.el reftex-cite.el reftex-dcr.el reftex-toc.el +Arash Esbati: changed reftex-vars.el efaq-w32.texi reftex-auc.el + reftex-ref.el reftex.el gnus.texi nnmaildir.el reftex-cite.el + reftex-dcr.el reftex-toc.el Arik Mitschang: changed smime.el @@ -542,7 +543,7 @@ Basil L. Contovounesios: changed simple.el message.el subr.el eww.el custom.el bibtex.el text.texi gnus-sum.el modes.texi customize.texi files.texi gnus-group.el gnus-win.el gravatar.el internals.texi json.el shr.el window.c battery-tests.el button.el custom-tests.el - and 278 other files + and 279 other files Bastian Beischer: changed semantic/complete.el calc-yank.el include.el mru-bookmark.el refs.el senator.el @@ -833,7 +834,7 @@ and co-wrote longlines.el tango-dark-theme.el tango-theme.el and changed simple.el display.texi xdisp.c files.el frames.texi cus-edit.el files.texi custom.el subr.el text.texi faces.el keyboard.c startup.el package.el misc.texi emacs.texi modes.texi mouse.el - custom.texi image.c window.el and 934 other files + custom.texi image.c window.el and 932 other files Chris Chase: co-wrote idlw-shell.el idlwave.el @@ -1030,11 +1031,11 @@ Dale Sedivec: changed sgml-mode.el wisent/python.el Damien Cassou: wrote auth-source-pass-tests.el hierarchy-tests.el hierarchy.el and co-wrote auth-source-pass.el auth-source-tests.el -and changed auth.texi checkdoc.el ispell.el message.el seq-tests.el - seq.el simple-tests.el simple.el auth-source.el autorevert.el +and changed simple.el auth.texi checkdoc.el ispell.el message.el + seq-tests.el seq.el simple-tests.el auth-source.el autorevert.el checkdoc-tests.el imenu-tests.el imenu.el info.el isearch.el - json-tests.el json.el message-tests.el package.el rmc.el sequences.texi - xref.el + json-tests.el json.el message-tests.el package.el rmc.el sending.texi + and 3 other files Damien Elmes: changed erc.el erc-dcc.el erc-track.el erc-log.el erc-pcomplete.el README erc-button.el erc-nets.el erc-ring.el Makefile @@ -1114,7 +1115,7 @@ Daniel Martín: changed shortdoc.el nsterm.m erc.texi files.el files.texi msdos-xtra.texi ns-win.el basic.texi cmacexp.el compilation.txt compile-tests.el cscope.el diff.el dired.el display.texi editfns.c emacs.texi files-tests.el find-func-tests.el find-func.el frame.c - and 17 other files + and 18 other files Daniel McClanahan: changed lisp-mode.el @@ -1199,7 +1200,7 @@ and co-wrote latin-ltx.el socks.el and changed configure.ac help.el mule-cmds.el fortran.el mule-conf.el xterm.c browse-url.el mule.el coding.c src/Makefile.in european.el fns.c mule-diag.el simple.el wid-edit.el cus-edit.el cus-start.el - files.el keyboard.c byte-opt.el info.el and 772 other files + files.el keyboard.c byte-opt.el info.el and 771 other files Dave Pearson: wrote 5x5.el quickurl.el @@ -1369,10 +1370,10 @@ Debarshi Ray: changed erc-backend.el erc.el Decklin Foster: changed nngateway.el -Deepak Goel: changed idlw-shell.el ada-xref.el feedmail.el files.el - find-func.el flymake.el mh-search.el mh-seq.el mh-thread.el mh-xface.el - org.el simple.el vc.el vhdl-mode.el wdired.el README ada-mode.el - allout.el appt.el apropos.el artist.el and 85 other files +Deepak Goel: changed idlw-shell.el feedmail.el files.el find-func.el + flymake.el mh-search.el mh-seq.el mh-thread.el mh-xface.el org.el + simple.el vc.el vhdl-mode.el wdired.el README allout.el appt.el + apropos.el artist.el bibtex.el bindings.el and 83 other files D. E. Evans: changed basic.texi @@ -1513,8 +1514,8 @@ and changed dired.el cus-edit.el imenu.el info.el ls-lisp.el menu-bar.el apropos.el bindings.el and 22 other files Earl Hyatt: changed ffap.el seq-tests.el sequences.texi windows.texi - control.texi cus-edit.el hi-lock.el misc.texi pcase-tests.el pcase.el - replace.el search.texi seq.el tab-bar.el + autotype.texi control.texi cus-edit.el hi-lock.el misc.texi + pcase-tests.el pcase.el replace.el search.texi seq.el tab-bar.el E. Choroba: changed cperl-mode.el simple.el @@ -1571,7 +1572,7 @@ Eli Zaretskii: wrote [bidirectional display in xdisp.c] chartab-tests.el coding-tests.el etags-tests.el rxvt.el tty-colors.el and co-wrote help-tests.el and changed xdisp.c display.texi w32.c msdos.c w32fns.c simple.el - files.el fileio.c keyboard.c emacs.c w32term.c text.texi dispnew.c + files.el fileio.c emacs.c keyboard.c w32term.c text.texi dispnew.c w32proc.c files.texi frames.texi configure.ac dispextern.h lisp.h process.c ms-w32.h and 1236 other files @@ -1594,7 +1595,7 @@ Emilio C. Lopes: changed woman.el cmuscheme.el help.el vc.el advice.el and 58 other files Emmanuel Briot: wrote xml.el -and changed ada-mode.el ada-stmt.el ada-prj.el ada-xref.el +and changed ada-stmt.el Era Eriksson: changed bibtex.el dired.el json.el ses.el ses.texi shell.el tramp.el tramp.texi @@ -1782,6 +1783,8 @@ Felicián Németh: changed project.el xref.el Felipe Ochoa: changed faces.el js.el paren.el +Felix Dietrich: changed tramp-archive.el + Felix E. Klee: co-wrote svg.el and changed display.texi @@ -1978,7 +1981,7 @@ Gerd Möllmann: wrote authors.el ebrowse.el jit-lock.el tooltip.el and changed xdisp.c xterm.c dispnew.c dispextern.h xfns.c xfaces.c window.c keyboard.c lisp.h faces.el alloc.c buffer.c startup.el xterm.h fns.c simple.el term.c configure.ac frame.c xmenu.c emacs.c - and 610 other files + and 607 other files Gergely Nagy: changed erc.el @@ -2006,7 +2009,7 @@ and changed configure.ac Makefile.in src/Makefile.in calendar.el lisp/Makefile.in diary-lib.el files.el make-dist rmail.el progmodes/f90.el bytecomp.el admin.el misc/Makefile.in simple.el authors.el startup.el emacs.texi lib-src/Makefile.in display.texi - ack.texi subr.el and 1789 other files + ack.texi subr.el and 1786 other files Glynn Clements: wrote gamegrid.el snake.el tetris.el @@ -2118,6 +2121,8 @@ Harald Meland: changed gnus-art.el gnus-salt.el gnus-score.el Harri Kiiskinen: changed org-protocol.el ox-publish.el +Hayden Shenk: changed tramp-adb.el + H. Dieter Wilhelm: changed calc-help.el maintaining.texi paragraphs.el Heiko Muenkel: changed b2m.c @@ -2216,7 +2221,8 @@ Ihor Radchenko: changed fns.c Iku Iwasa: changed auth-source-pass-tests.el auth-source-pass.el -Ikumi Keita: changed characters.el japan-util.el kinsoku.el minibuf.c +Ikumi Keita: changed characters.el display.texi files.el japan-util.el + kinsoku.el minibuf.c Ilja Weis: co-wrote gnus-topic.el @@ -2274,8 +2280,7 @@ Itai Y. Efrat: changed browse-url.el Itai Zukerman: changed mm-decode.el Ivan Andrus: changed editfns.c epg.el ffap.el find-file.el ibuf-ext.el - ibuffer.el newcomment.el nextstep/templates/Info.plist.in nxml-mode.el - progmodes/python.el + ibuffer.el newcomment.el nxml-mode.el progmodes/python.el Ivan Boldyrev: changed mml1991.el @@ -2520,7 +2525,7 @@ and changed mh-e.el mh-comp.el mh-utils.el mh-mime.el mh-customize.el Jeff Spencer: changed dired.el -Jeff Walsh: changed xwidget.c +Jeff Walsh: changed comp.c xwidget.c Jelle Licht: changed auth-source-pass-tests.el auth-source-pass.el @@ -2857,7 +2862,7 @@ Jorge P. De Morais Neto: changed TUTORIAL cl.texi Jose A. Ortega Ruiz: changed mixal-mode.el gnus-sum.el url-http.el -Jose E. Marchesi: changed ada-mode.el gomoku.el simple.el smtpmail.el +Jose E. Marchesi: changed gomoku.el simple.el smtpmail.el José L. Doménech: changed dired-aux.el @@ -2902,7 +2907,7 @@ and co-wrote help-tests.el keymap-tests.el and changed subr.el desktop.el w32fns.c faces.el simple.el emacsclient.c files.el server.el bs.el help-fns.el xdisp.c org.el w32term.c w32.c buffer.c keyboard.c ido.el image.c window.c eval.c allout.el - and 1225 other files + and 1223 other files Juan Pechiar: changed ob-octave.el @@ -2941,8 +2946,8 @@ Jure Cuhalev: changed ispell.el Jürgen Hartmann: changed window.el Jürgen Hötzel: wrote tramp-adb.el -and changed tramp-gvfs.el tramp-sh.el comint.el em-unix.el esh-util.el - tramp-cache.el tramp.el url-handlers.el wid-edit.el +and changed tramp-gvfs.el tramp-sh.el callproc.c comint.el em-unix.el + esh-util.el tramp-cache.el tramp.el url-handlers.el wid-edit.el Juri Linkov: wrote compose.el files-x.el misearch.el repeat-tests.el replace-tests.el tab-bar-tests.el tab-bar.el tab-line.el @@ -3017,7 +3022,7 @@ and changed simple.el files.el CONTRIBUTE doc-view.el image-mode.el Karl Heuer: changed keyboard.c lisp.h xdisp.c buffer.c xfns.c xterm.c alloc.c files.el frame.c configure.ac window.c data.c minibuf.c editfns.c fns.c process.c Makefile.in fileio.c simple.el keymap.c - indent.c and 447 other files + indent.c and 446 other files Karl Kleinpaste: changed gnus-sum.el gnus-art.el gnus-picon.el gnus-score.el gnus-uu.el gnus-xmas.el gnus.el mm-uu.el mml.el nnmail.el @@ -3181,7 +3186,7 @@ Kim F. Storm: wrote bindat.el cua-base.el cua-gmrk.el cua-rect.el ido.el and changed xdisp.c dispextern.h process.c simple.el window.c keyboard.c xterm.c dispnew.c subr.el w32term.c lisp.h fringe.c display.texi macterm.c alloc.c fns.c xfaces.c keymap.c xfns.c xterm.h .gdbinit - and 249 other files + and 248 other files Kimit Yada: changed copyright.el @@ -3220,10 +3225,10 @@ Konrad Hinsen: wrote ol-eshell.el and changed ob-python.el Konstantin Kharlamov: changed smerge-mode.el diff-mode.el files.el - ada-mode.el autorevert.el calc-aent.el calc-ext.el calc-lang.el - cc-mode.el cperl-mode.el css-mode.el cua-rect.el dnd.el ebnf-abn.el - ebnf-dtd.el ebnf-ebx.el emacs-module-tests.el epg.el faces.el - gnus-art.el gtkutil.c and 27 other files + autorevert.el calc-aent.el calc-ext.el calc-lang.el cc-mode.el + cperl-mode.el css-mode.el cua-rect.el dnd.el ebnf-abn.el ebnf-dtd.el + ebnf-ebx.el emacs-module-tests.el epg.el faces.el gnus-art.el gtkutil.c + hideif.el and 26 other files Konstantin Kliakhandler: changed org-agenda.el @@ -3303,10 +3308,10 @@ and co-wrote gnus-kill.el gnus-mh.el gnus-msg.el gnus-score.el mm-encode.el mm-util.el nnbabyl.el nndoc.el nneething.el nnfolder.el nnheader.el nnimap.el nnmbox.el nnmh.el nnml.el nnspool.el nnvirtual.el rfc2047.el svg.el time-date.el -and changed gnus.texi simple.el subr.el files.el process.c text.texi - display.texi dired.el gnutls.c gnus-ems.el smtpmail.el help-fns.el +and changed gnus.texi simple.el subr.el files.el process.c display.texi + text.texi dired.el gnutls.c gnus-ems.el smtpmail.el help-fns.el auth-source.el url-http.el edebug.el image.el gnus-cite.el pop3.el - dired-aux.el fns.c image.c and 860 other files + dired-aux.el fns.c image.c and 866 other files Lars Rasmusson: changed ebrowse.c @@ -3336,11 +3341,11 @@ Lele Gaifax: changed TUTORIAL.it progmodes/python.el flymake.el python-tests.el flymake-proc.el flymake.texi isearch.el Lennart Borgman: co-wrote ert-x.el -and changed nxml-mode.el tutorial.el re-builder.el window.el ada-xref.el - buff-menu.el emacs-lisp/debug.el emacsclient.c filesets.el flymake.el - help-fns.el isearch.el linum.el lisp-mode.el lisp.el mouse.el - progmodes/grep.el recentf.el remember.el replace.el reveal.el - and 6 other files +and changed nxml-mode.el tutorial.el re-builder.el window.el buff-menu.el + emacs-lisp/debug.el emacsclient.c filesets.el flymake.el help-fns.el + isearch.el linum.el lisp-mode.el lisp.el mouse.el progmodes/grep.el + recentf.el remember.el replace.el reveal.el ruby-mode.el + and 5 other files Lennart Staflin: changed dired.el diary-ins.el diary-lib.el tq.el xdisp.c @@ -3429,7 +3434,7 @@ Lute Kamstra: changed modes.texi emacs-lisp/debug.el generic-x.el generic.el font-lock.el simple.el subr.el battery.el debugging.texi easy-mmode.el elisp.texi emacs-lisp/generic.el hl-line.el info.el octave.el basic.texi bindings.el calc.el cmdargs.texi diff-mode.el - doclicense.texi and 289 other files + doclicense.texi and 288 other files Lynn Slater: wrote help-macro.el @@ -3551,7 +3556,7 @@ Mark Oteiza: wrote mailcap-tests.el md4-tests.el xdg-tests.el xdg.el and changed image-dired.el dunnet.el mpc.el eww.el json.el calc-units.el lcms.c subr-x.el subr.el message.el tex-mode.el cl-macs.el cl.texi ibuffer.el lcms-tests.el mailcap.el progmodes/python.el cl-print.el - eldoc.el emacs-lisp/chart.el files.el and 172 other files + eldoc.el emacs-lisp/chart.el files.el and 173 other files Mark Plaksin: changed nnrss.el term.el @@ -3574,7 +3579,7 @@ and changed cus-edit.el files.el progmodes/compile.el rmail.el tex-mode.el find-func.el rmailsum.el simple.el cus-dep.el dired.el mule-cmds.el rmailout.el checkdoc.el configure.ac custom.el emacsbug.el gnus.el help-fns.el ls-lisp.el mwheel.el sendmail.el - and 126 other files + and 125 other files Markus Sauermann: changed lisp-mode.el @@ -3619,7 +3624,7 @@ Martin Pohlack: changed iimage.el pc-select.el Martin Rudalics: changed window.el window.c windows.texi frame.c xdisp.c xterm.c frames.texi w32fns.c w32term.c xfns.c frame.el display.texi frame.h cus-start.el help.el buffer.c window.h mouse.el dispnew.c - nsfns.m gtkutil.c and 213 other files + nsfns.m gtkutil.c and 212 other files Martin Stjernholm: wrote cc-bytecomp.el and co-wrote cc-align.el cc-cmds.el cc-compat.el cc-defs.el cc-engine.el @@ -3733,7 +3738,7 @@ Mattias Engdegård: changed byte-opt.el rx.el rx-tests.el searching.texi bytecomp-tests.el bytecomp.el calc-tests.el progmodes/compile.el subr.el autorevert.el gdb-mi.el files.el regex-emacs-tests.el mouse.el regexp-opt.el replace.el calc.el coding.c filenotify.el regex-emacs.c - calc-ext.el and 537 other files + calc-ext.el and 539 other files Mattias M: changed asm-mode-tests.el asm-mode.el @@ -3978,7 +3983,7 @@ Miles Bader: wrote button.el face-remap.el image-file.el macroexp.el and changed comint.el faces.el simple.el editfns.c xfaces.c xdisp.c info.el minibuf.c display.texi quick-install-emacs wid-edit.el xterm.c dispextern.h subr.el window.el cus-edit.el diff-mode.el xfns.c - bytecomp.el help.el lisp.h and 272 other files + bytecomp.el help.el lisp.h and 271 other files Milton Wulei: changed gdb-ui.el @@ -4308,7 +4313,7 @@ and co-wrote cal-dst.el and changed lisp.h configure.ac alloc.c fileio.c process.c editfns.c sysdep.c xdisp.c fns.c image.c keyboard.c data.c emacs.c lread.c xterm.c eval.c gnulib-comp.m4 callproc.c Makefile.in frame.c buffer.c - and 1849 other files + and 1847 other files Paul Fisher: changed fns.c @@ -4334,7 +4339,7 @@ Paul Reilly: changed dgux.h lwlib-Xm.c lwlib.c xlwmenu.c configure.ac lwlib/Makefile.in mail/rmailmm.el rmailedit.el rmailkwd.el and 10 other files -Paul Rivier: changed ada-mode.el mixal-mode.el reftex-vars.el reftex.el +Paul Rivier: changed mixal-mode.el reftex-vars.el reftex.el Paul Rubin: changed config.h sun2.h texinfmt.el window.c @@ -4355,7 +4360,7 @@ Pavel Janík: co-wrote eudc-bob.el eudc-export.el eudc-hotlist.el and changed keyboard.c xterm.c COPYING xdisp.c process.c emacs.c lisp.h menu-bar.el ldap.el make-dist xfns.c buffer.c coding.c eval.c fileio.c flyspell.el fns.c indent.c Makefile.in callint.c cus-start.el - and 702 other files + and 699 other files Pavel Kobiakov: wrote flymake-proc.el flymake.el and changed flymake.texi @@ -4566,8 +4571,8 @@ and changed xdisp.c comp.c fns.c pdumper.c alloc.c byte-opt.el comp-tests.el comp.el composite.c and 28 other files Po Lu: changed xdisp.c anti.texi browse-url.el callproc.c cc-compat.el - config.bat esh-cmd.el fileio.c langinfo.h loadup.el msdos.c msdos.h - nsfns.m nsterm.m process.c sed1v2.inp sed2v2.inp sed3v2.inp + config.bat esh-cmd.el fileio.c langinfo.h loadup.el mouse.el msdos.c + msdos.h nsfns.m nsterm.m process.c sed1v2.inp sed2v2.inp sed3v2.inp sedlibmk.inp tooltip.el xterm.c Pontus Michael: changed simple.el @@ -4684,9 +4689,8 @@ and changed vhdl-mode.texi Reuben Thomas: changed ispell.el whitespace.el dired-x.el files.el sh-script.el emacsclient-tests.el remember.el README emacsclient.c - misc.texi msdos.c simple.el INSTALL ada-mode.el ada-xref.el alloc.c - arc-mode.el authors.el config.bat copyright dired-x.texi - and 37 other files + misc.texi msdos.c simple.el INSTALL alloc.c arc-mode.el authors.el + config.bat copyright dired-x.texi dired.el dosfns.c and 35 other files Ricardo Wurmus: changed xwidget.el xwidget.c configure.ac xwidget.h @@ -4699,6 +4703,8 @@ Richard Dawe: changed config.in src/Makefile.in Richard G. Bielawski: changed modes.texi paren.el +Richard Hansen: changed easy-mmode.el + Richard Hoskins: changed message.el Richard Kim: wrote wisent/python.el @@ -4729,7 +4735,7 @@ and co-wrote cc-align.el cc-cmds.el cc-defs.el cc-engine.el cc-langs.el and changed files.el keyboard.c simple.el xterm.c xdisp.c rmail.el fileio.c process.c sysdep.c buffer.c xfns.c window.c subr.el configure.ac startup.el sendmail.el emacs.c Makefile.in editfns.c - info.el dired.el and 1338 other files + info.el dired.el and 1336 other files Richard Ryniker: changed sendmail.el @@ -4779,7 +4785,7 @@ Robert Pluim: wrote nsm-tests.el and changed configure.ac process.c blocks.awk network-stream-tests.el font.c processes.texi ftfont.c gtkutil.c vc-git.el process-tests.el emoji-zwj.awk gnutls.el network-stream.el nsm.el tramp.texi mml-sec.el - nsterm.m unicode xfns.c auth.texi composite.c and 135 other files + nsterm.m unicode xfns.c auth.texi composite.c and 136 other files Robert Thorpe: changed cus-start.el indent.el rmail.texi @@ -4847,10 +4853,9 @@ Roy Liu: changed ns-win.el Rüdiger Sonderfeld: wrote inotify-tests.el reftex-tests.el and changed eww.el octave.el shr.el bibtex.el configure.ac - misc/Makefile.in reftex-vars.el vc-git.el TUTORIAL.de ada-mode.el - autoinsert.el building.texi bytecomp.el calc-lang.el cc-langs.el - dired.texi editfns.c emacs.c emacs.texi epa.el erc.el - and 40 other files + misc/Makefile.in reftex-vars.el vc-git.el TUTORIAL.de autoinsert.el + building.texi bytecomp.el calc-lang.el cc-langs.el dired.texi editfns.c + emacs.c emacs.texi epa.el erc.el eww.texi and 39 other files Rui-Tao Dong: changed nnweb.el @@ -4909,7 +4914,7 @@ Sam Steingold: wrote gulp.el midnight.el and changed progmodes/compile.el cl-indent.el simple.el vc-cvs.el vc.el mouse.el vc-hg.el etags.el files.el font-lock.el tex-mode.el ange-ftp.el gnus-sum.el message.el sgml-mode.el vc-git.el window.el - add-log.el bindings.el bookmark.el bug-reference.el and 188 other files + add-log.el bindings.el bookmark.el bug-reference.el and 186 other files Samuel Bronson: changed custom.el emacsclient.c keyboard.c progmodes/grep.el semantic/format.el unexmacosx.c @@ -5013,9 +5018,8 @@ Sébastien Vauban: changed org.el org-agenda.el ox-latex.el ob-core.el org-clock.el ox-ascii.el ox-html.el Seiji Zenitani: changed nsfns.m frame.c xterm.c PkgInfo document.icns - find-func.el frame.h help-fns.el macfns.c - nextstep/templates/Info.plist.in nsfont.m nsterm.m w32fns.c xdisp.c - xfns.c + find-func.el frame.h help-fns.el macfns.c nsfont.m nsterm.m w32fns.c + xdisp.c xfns.c Sen Nagata: wrote crm.el rfc2368.el @@ -5175,7 +5179,7 @@ and co-wrote help-tests.el keymap-tests.el and changed efaq.texi checkdoc.el package.el cperl-mode.el bookmark.el help.el keymap.c subr.el simple.el erc.el ediff-util.el idlwave.el time.el bytecomp-tests.el comp.el speedbar.el bytecomp.el edebug.el - emacs-lisp-intro.texi flyspell.el ibuffer.el and 1334 other files + emacs-lisp-intro.texi flyspell.el ibuffer.el and 1339 other files Stefan Merten: co-wrote rst.el @@ -5192,7 +5196,7 @@ and co-wrote font-lock.el gitmerge.el pcvs.el and changed subr.el simple.el keyboard.c bytecomp.el cl-macs.el files.el lisp.h vc.el xdisp.c alloc.c eval.c sh-script.el progmodes/compile.el keymap.c buffer.c window.c tex-mode.el lisp-mode.el newcomment.el - help-fns.el lread.c and 1615 other files + help-fns.el lread.c and 1612 other files Stefano Facchini: changed gtkutil.c @@ -5252,11 +5256,11 @@ and changed time-stamp.el time-stamp-tests.el mh-e.el mh-junk.el Stephen J. Turnbull: changed ediff-init.el strings.texi subr.el Stephen Leake: wrote elisp-mode-tests.el -and changed ada-mode.el ada-xref.el elisp-mode.el xref.el window.el - mode-local.el CONTRIBUTE ada-prj.el project.el vc-mtn.el ada-stmt.el - cedet-global.el ede/generic.el simple.el autoload.el bytecomp.el - cl-generic.el ede/locate.el files.texi functions.texi package.el - and 35 other files +and changed elisp-mode.el xref.el window.el mode-local.el CONTRIBUTE + project.el vc-mtn.el ada-stmt.el cedet-global.el ede/generic.el + simple.el autoload.el bytecomp.el cl-generic.el ede/locate.el + files.texi functions.texi package.el progmodes/grep.el windows.texi + INSTALL.REPO and 32 other files Stephen Pegoraro: changed xterm.c @@ -5446,7 +5450,7 @@ and co-wrote hideshow.el and changed ewoc.el vc.el info.el processes.texi zone.el lisp-mode.el scheme.el text.texi vc-rcs.el display.texi fileio.c files.el vc-git.el TUTORIAL.it bindat.el cc-vars.el configure.ac dcl-mode.el diff-mode.el - dired.el elisp.texi and 169 other files + dired.el elisp.texi and 168 other files Thierry Banel: co-wrote ob-C.el and changed calc-arith.el @@ -5656,8 +5660,6 @@ Toru Tsuneyoshi: changed ange-ftp.el buff-menu.el cus-start.el fileio.c Toshiaki Nomura: changed uxpds.h -Travis Jeffery: changed nextstep/templates/Info.plist.in - Trent W. Buck: changed rcirc.el remember.el rx.el Trevor Murphy: changed find-dired.el gnus.texi nnimap.el org.el window.el @@ -5791,6 +5793,8 @@ and changed ps-prin1.ps ps-bdf.el ps-prin0.ps blank-mode.el ps-prin3.ps easymenu.el loading.texi menu-bar.el misc.texi progmodes/compile.el ps-print-def.el ps-vars.el +Visuwesh M: changed dired-aux.el + Vitalie Spinu: changed comint.el eieio-base.el message.el ob-R.el ob-core.el ob-tangle.el subr.el commit e83919f7214aad67995171b22dab8b76685943b9 Author: Po Lu Date: Wed Jun 29 21:12:12 2022 +0800 Fix some bugs found while testing drag-and-drop * lisp/x-dnd.el (x-dnd-get-drop-width-height): (x-dnd-get-drop-x-y): Fix doc string. (x-dnd-handle-xdnd): Don't set update rect if `dnd-indicate-insertion-point'. Bug found testing with "JX Application Framework". diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index b7a20d37ce..d92009f85c 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -522,7 +522,7 @@ message (format 32) that caused EVENT to be generated." frame "ATOM" 32 t)) (defun x-dnd-get-drop-width-height (frame w accept) - "Return the width/height to be sent in a XDndStatus message. + "Return the width/height to be sent in a XdndStatus message. FRAME is the frame and W is the window where the drop happened. If ACCEPT is nil return 0 (empty rectangle), otherwise if W is a window, return its width/height, @@ -539,7 +539,7 @@ otherwise return the frame width/height." 0)) (defun x-dnd-get-drop-x-y (frame w) - "Return the x/y coordinates to be sent in a XDndStatus message. + "Return the x/y coordinates to be sent in a XdndStatus message. Coordinates are required to be absolute. FRAME is the frame and W is the window where the drop happened. If W is a window, return its absolute coordinates, @@ -609,10 +609,13 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (list-to-send (list (string-to-number (frame-parameter frame 'outer-window-id)) - accept ;; 1 = Accept, 0 = reject. - (x-dnd-get-drop-x-y frame window) - (x-dnd-get-drop-width-height - frame window (eq accept 1)) + (+ 2 accept) ;; 1 = accept, 0 = reject. 2 = + ;; "want position updates". + (if dnd-indicate-insertion-point 0 + (x-dnd-get-drop-x-y frame window)) + (if dnd-indicate-insertion-point 0 + (x-dnd-get-drop-width-height + frame window (eq accept 1))) ;; The no-toolkit Emacs build can actually ;; receive drops from programs that speak ;; versions of XDND earlier than 3 (such as commit 7a9353d444cf656eed1eae865afd73565cba5a29 Author: Stefan Monnier Date: Wed Jun 29 08:58:13 2022 -0400 (cl--generic-compiler): Revert last change That change (introduced to circumvent an error now that `seq.el` is preloaded) caused all dispatchers to be left uncompiled, which slows down method dispatch very significantly. Fix the problem in the old way, i.e. by adding an explicit call to `cl--generic-prefill-dispatchers`. * lisp/emacs-lisp/cl-generic.el (cl--generic-compiler): Revert last change. Add (cl--generic-prefill-dispatchers 1 integer) instead to handle the new dispatchers needed for `seq.el`. (cl--generic-prefill-generalizer-sample): New function. (cl--generic-get-dispatcher): Use it to signal an error giving precise instructions for what to do if we're about the load the byte-compiler during the preload. (cl--generic-oclosure-generalizer): Rename from `cl-generic--oclosure-generalizer` for consistency with all other generalizers. diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 6c5813959f..0560ddda26 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -658,9 +658,13 @@ The set of acceptable TYPEs (also called \"specializers\") is defined ;; compiled. Otherwise the byte-compiler and all the code on ;; which it depends needs to be usable before cl-generic is loaded, ;; which imposes a significant burden on the bootstrap. - (if (or (consp (lambda (x) (+ x 1))) - (not (featurep 'bytecomp))) + (if (consp (lambda (x) (+ x 1))) (lambda (exp) (eval exp t)) + ;; But do byte-compile the dispatchers once bootstrap is passed: + ;; the performance difference is substantial (like a 5x speedup on + ;; the `eieio' elisp-benchmark)). + ;; To avoid loading the byte-compiler during the final preload, + ;; see `cl--generic-prefill-dispatchers'. #'byte-compile)) (defun cl--generic-get-dispatcher (dispatch) @@ -668,6 +672,22 @@ The set of acceptable TYPEs (also called \"specializers\") is defined ;; We need `copy-sequence` here because this `dispatch' object might be ;; modified by side-effect in `cl-generic-define-method' (bug#46722). (gethash (copy-sequence dispatch) cl--generic-dispatchers) + + (when (and purify-flag ;FIXME: Is this a reliable test of the final dump? + (eq cl--generic-compiler #'byte-compile)) + ;; We don't want to preload the byte-compiler!! + (error + "Missing cl-generic dispatcher in the prefilled cache! +Missing for: %S +You might need to add: %S" + (mapcar (lambda (x) (if (cl--generic-generalizer-p x) + (cl--generic-generalizer-name x) + x)) + dispatch) + `(cl--generic-prefill-dispatchers + ,@(delq nil (mapcar #'cl--generic-prefill-generalizer-sample + dispatch))))) + ;; (message "cl--generic-get-dispatcher (%S)" dispatch) (let* ((dispatch-arg (car dispatch)) (generalizers (cdr dispatch)) @@ -932,6 +952,20 @@ those methods.") (if (eq specializer t) (list cl--generic-t-generalizer) (error "Unknown specializer %S" specializer))) +(defun cl--generic-prefill-generalizer-sample (x) + "Return an example specializer." + (if (not (cl--generic-generalizer-p x)) + x + (pcase (cl--generic-generalizer-name x) + ('cl--generic-t-generalizer nil) + ('cl--generic-head-generalizer '(head 'x)) + ('cl--generic-eql-generalizer '(eql 'x)) + ('cl--generic-struct-generalizer 'cl--generic) + ('cl--generic-typeof-generalizer 'integer) + ('cl--generic-derived-generalizer '(derived-mode c-mode)) + ('cl--generic-oclosure-generalizer 'oclosure) + (_ x)))) + (eval-when-compile ;; This macro is brittle and only really important in order to be ;; able to preload cl-generic without also preloading the byte-compiler, @@ -1329,6 +1363,7 @@ See the full list and their hierarchy in `cl--typeof-types'." (cl-call-next-method))) (cl--generic-prefill-dispatchers 0 integer) +(cl--generic-prefill-dispatchers 1 integer) (cl--generic-prefill-dispatchers 0 cl--generic-generalizer integer) ;;; Dispatch on major mode. @@ -1377,7 +1412,7 @@ Used internally for the (major-mode MODE) context specializers." (when (cl-typep class 'oclosure--class) (oclosure--class-allparents class))))) -(cl-generic-define-generalizer cl-generic--oclosure-generalizer +(cl-generic-define-generalizer cl--generic-oclosure-generalizer ;; Give slightly higher priority than the struct specializer, so that ;; for a generic function with methods dispatching structs and on OClosures, ;; we first try `oclosure-type' before `type-of' since `type-of' will return @@ -1394,7 +1429,7 @@ Used internally for the (major-mode MODE) context specializers." ;; take place without requiring cl-lib. (let ((class (cl--find-class type))) (and (cl-typep class 'oclosure--class) - (list cl-generic--oclosure-generalizer)))) + (list cl--generic-oclosure-generalizer)))) (cl-call-next-method))) (cl--generic-prefill-dispatchers 0 oclosure) commit 7f749e44dbd50430e14f319b4c4d3f767740b10b Author: Stefan Kangas Date: Wed Jun 29 14:20:24 2022 +0200 ; Auto-commit of loaddefs files. diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index 78d6bb5201..3aff6bddf9 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -1452,25 +1452,25 @@ Variables This is a brief overview of the different variables. For more info, see the documentation for the variables (type \\[describe-variable] RET). - artist-rubber-banding Interactively do rubber-banding or not - artist-first-char What to set at first/second point... - artist-second-char ...when not rubber-banding - artist-interface-with-rect If cut/copy/paste should interface with rect - artist-arrows The arrows to use when drawing arrows - artist-aspect-ratio Character height-to-width for squares - artist-trim-line-endings Trimming of line endings - artist-flood-fill-right-border Right border when flood-filling - artist-flood-fill-show-incrementally Update display while filling - artist-pointer-shape Pointer shape to use while drawing - artist-ellipse-left-char Character to use for narrow ellipses - artist-ellipse-right-char Character to use for narrow ellipses - artist-borderless-shapes If shapes should have borders - artist-picture-compatibility Whether or not to be picture mode compatible - artist-vaporize-fuzziness Tolerance when recognizing lines - artist-spray-interval Seconds between repeated sprayings - artist-spray-radius Size of the spray-area - artist-spray-chars The spray-\"color\" - artist-spray-new-chars Initial spray-\"color\" + `artist-rubber-banding' Interactively do rubber-banding or not + `artist-first-char' What to set at first/second point... + `artist-second-char' ...when not rubber-banding + `artist-interface-with-rect' Should cut/copy/paste interface with rect + `artist-arrows' The arrows to use when drawing arrows + `artist-aspect-ratio' Character height-to-width for squares + `artist-trim-line-endings' Trimming of line endings + `artist-flood-fill-right-border' Right border when flood-filling + `artist-flood-fill-show-incrementally' Update display while filling + `artist-pointer-shape' Pointer shape to use while drawing + `artist-ellipse-left-char' Character to use for narrow ellipses + `artist-ellipse-right-char' Character to use for narrow ellipses + `artist-borderless-shapes' If shapes should have borders + `artist-picture-compatibility' Picture mode compatibility on or off + `artist-vaporize-fuzziness' Tolerance when recognizing lines + `artist-spray-interval' Seconds between repeated sprayings + `artist-spray-radius' Size of the spray-area + `artist-spray-chars' The spray-\"color\" + `artist-spray-new-char' Initial spray-\"color\" Hooks @@ -5284,6 +5284,10 @@ Convert COLOR string to a list of normalized RGB components. COLOR should be a color name (e.g. \"white\") or an RGB triplet string (e.g. \"#ffff1122eecc\"). +COLOR can also be the symbol `unspecified' or one of the strings +\"unspecified-fg\" or \"unspecified-bg\", in which case the +return value is nil. + Normally the return value is a list of three floating-point numbers, (RED GREEN BLUE), each between 0.0 and 1.0 inclusive. @@ -8059,8 +8063,11 @@ The directory name must be absolute, but need not be fully expanded.") (autoload 'dired "dired" "\ \"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it. -Optional second argument SWITCHES specifies the `ls' options used. -\(Interactively, use a prefix argument to be able to specify SWITCHES.) +Optional second argument SWITCHES specifies the options to be used +when invoking `insert-directory-program', usually `ls', which produces +the listing of the directory files and their attributes. +Interactively, a prefix argument will cause the command to prompt +for SWITCHES. If DIRNAME is a string, Dired displays a list of files in DIRNAME (which may also have shell wildcards appended to select certain files). @@ -8562,7 +8569,7 @@ If REVERSE, look up an IP address. (autoload 'dns-mode "dns-mode" "\ Major mode for viewing and editing DNS master files. -This mode is inherited from text mode. It add syntax +This mode is derived from text mode. It adds syntax highlighting, and some commands for handling DNS master files. Its keymap inherits from `text-mode' and it has the same variables for customizing indentation. It has its own abbrev @@ -9261,6 +9268,11 @@ If regular expression is nil, repeat last search. Query replace FROM with TO in all files of a class tree. With prefix arg, process files of marked classes only. +As each match is found, the user must type a character saying +what to do with it. Type SPC or `y' to replace the match, +DEL or `n' to skip and go to the next match. For more directions, +type \\[help-command] at that time. + \(fn FROM TO)" t nil) (autoload 'ebrowse-tags-search-member-use "ebrowse" "\ @@ -11524,7 +11536,13 @@ Do `query-replace-regexp' of FROM with TO on all files listed in tags table. Third arg DELIMITED (prefix arg) means replace only word-delimited matches. If you exit (\\[keyboard-quit], RET or q), you can resume the query replace with the command \\[fileloop-continue]. -For non-interactive use, superseded by `fileloop-initialize-replace'. + +As each match is found, the user must type a character saying +what to do with it. Type SPC or `y' to replace the match, +DEL or `n' to skip and go to the next match. For more directions, +type \\[help-command] at that time. + +For non-interactive use, this is superseded by `fileloop-initialize-replace'. \(fn FROM TO &optional DELIMITED FILES)" t nil) @@ -19978,7 +19996,7 @@ Create lambda form for macro bound to symbol or key. \(fn MAC &optional COUNTER FORMAT)" nil nil) -(register-definition-prefixes "kmacro" '("kdb-macro-redisplay" "kmacro-")) +(register-definition-prefixes "kmacro" '("kmacro-")) ;;;*** @@ -22099,7 +22117,7 @@ Major mode for the mixal asm language. ;;;### (autoloads nil "mm-encode" "gnus/mm-encode.el" (0 0 0 0)) ;;; Generated autoloads from gnus/mm-encode.el -(define-obsolete-function-alias 'mm-default-file-encoding #'mm-default-file-type "future") +(define-obsolete-function-alias 'mm-default-file-encoding #'mm-default-file-type "28.1") (autoload 'mm-default-file-type "mm-encode" "\ Return a default content type for FILE. @@ -24057,7 +24075,7 @@ Coloring: ;;;### (autoloads nil "org" "org/org.el" (0 0 0 0)) ;;; Generated autoloads from org/org.el -(push (purecopy '(org 9 5 2)) package--builtin-versions) +(push (purecopy '(org 9 5 4)) package--builtin-versions) (autoload 'org-babel-do-load-languages "org" "\ Load the languages defined in `org-babel-load-languages'. @@ -24421,7 +24439,7 @@ is active. \(fn &optional TODO-ONLY STRING EDIT-AT)" t nil) (autoload 'org-todo-list "org-agenda" "\ -Show all (not done) TODO entries from all agenda file in a single list. +Show all (not done) TODO entries from all agenda files in a single list. The prefix arg can be used to select a specific TODO keyword and limit the list to these. When using `\\[universal-argument]', you will be prompted for a keyword. A numeric prefix directly selects the Nth keyword in @@ -26628,6 +26646,10 @@ command \\[fileloop-continue]. (autoload 'project-query-replace-regexp "project" "\ Query-replace REGEXP in all the files of the project. Stops when a match is found and prompts for whether to replace it. +At that prompt, the user must type a character saying what to do +with the match. Type SPC or `y' to replace the match, +DEL or `n' to skip and go to the next match. For more directions, +type \\[help-command] at that time. If you exit the `query-replace', you can later continue the `query-replace' loop using the command \\[fileloop-continue]. @@ -31072,7 +31094,7 @@ values), despite potential performance issues, type \\[so-long-revert]. Use \\[so-long-commentary] for more information. Use \\[so-long-customize] to open the customization group `so-long' to -configure the behaviour. +configure the behavior. \(fn)" t nil) @@ -31138,7 +31160,7 @@ When such files are detected by `so-long-predicate', we invoke the selected Use \\[so-long-commentary] for more information. Use \\[so-long-customize] to open the customization group `so-long' to -configure the behaviour. +configure the behavior. \(fn &optional ARG)" t nil) @@ -34908,7 +34930,7 @@ like \"/sys\" or \"/C:\".") Load Tramp file name handler, and perform OPERATION." (tramp-unload-file-name-handlers) (when tramp-mode (let ((default-directory temporary-file-directory)) (when (bound-and-true-p tramp-archive-autoload) (load "tramp-archive" 'noerror 'nomessage)) (load "tramp" 'noerror 'nomessage))) (apply operation args)) (defun tramp-register-autoload-file-name-handlers nil "\ -Add Tramp file name handlers to `file-name-handler-alist' during autoload." (add-to-list 'file-name-handler-alist (cons tramp-autoload-file-name-regexp #'tramp-autoload-file-name-handler)) (put #'tramp-autoload-file-name-handler 'safe-magic t)) +Add Tramp file name handlers to `file-name-handler-alist' during autoload." (unless (rassq #'tramp-file-name-handler file-name-handler-alist) (add-to-list 'file-name-handler-alist (cons tramp-autoload-file-name-regexp #'tramp-autoload-file-name-handler)) (put #'tramp-autoload-file-name-handler 'safe-magic t))) (tramp-register-autoload-file-name-handlers) (defun tramp-unload-file-name-handlers nil "\ @@ -34947,10 +34969,10 @@ It must be supported by libarchive(3).") Regular expression matching archive file names." '(concat "\\`" "\\(" ".+" "\\." (regexp-opt tramp-archive-suffixes) "\\(?:" "\\." (regexp-opt tramp-archive-compression-suffixes) "\\)*" "\\)" "\\(" "/" ".*" "\\)" "\\'")) (defun tramp-archive-autoload-file-name-handler (operation &rest args) "\ -Load Tramp archive file name handler, and perform OPERATION." (defvar tramp-archive-autoload) (when tramp-archive-enabled (let ((default-directory temporary-file-directory) (tramp-archive-autoload t)) (apply #'tramp-autoload-file-name-handler operation args)))) +Load Tramp archive file name handler, and perform OPERATION." (defvar tramp-archive-autoload) (let ((default-directory temporary-file-directory) (tramp-archive-autoload tramp-archive-enabled)) (apply #'tramp-autoload-file-name-handler operation args))) (defun tramp-register-archive-file-name-handler nil "\ -Add archive file name handler to `file-name-handler-alist'." (when tramp-archive-enabled (add-to-list 'file-name-handler-alist (cons (tramp-archive-autoload-file-name-regexp) #'tramp-archive-autoload-file-name-handler)) (put #'tramp-archive-autoload-file-name-handler 'safe-magic t))) +Add archive file name handler to `file-name-handler-alist'." (when (and tramp-archive-enabled (not (rassq #'tramp-archive-file-name-handler file-name-handler-alist))) (add-to-list 'file-name-handler-alist (cons (tramp-archive-autoload-file-name-regexp) #'tramp-archive-autoload-file-name-handler)) (put #'tramp-archive-autoload-file-name-handler 'safe-magic t))) (add-hook 'after-init-hook #'tramp-register-archive-file-name-handler) @@ -35064,7 +35086,7 @@ Add archive file name handler to `file-name-handler-alist'." (when tramp-archive ;;;### (autoloads nil "trampver" "net/trampver.el" (0 0 0 0)) ;;; Generated autoloads from net/trampver.el -(push (purecopy '(tramp 2 5 2 28 1)) package--builtin-versions) +(push (purecopy '(tramp 2 5 3)) package--builtin-versions) (register-definition-prefixes "trampver" '("tramp-")) @@ -39511,21 +39533,11 @@ Zone out, completely." t nil) ;;;;;; "eshell/em-term.el" "eshell/em-tramp.el" "eshell/em-unix.el" ;;;;;; "eshell/em-xtra.el" "faces.el" "files.el" "font-core.el" ;;;;;; "font-lock.el" "format.el" "frame.el" "help.el" "hfy-cmap.el" -;;;;;; "ibuf-ext.el" "indent.el" "international/characters.el" "international/charprop.el" -;;;;;; "international/charscript.el" "international/cp51932.el" -;;;;;; "international/emoji-zwj.el" "international/eucjp-ms.el" +;;;;;; "ibuf-ext.el" "indent.el" "international/characters.el" "international/charscript.el" +;;;;;; "international/cp51932.el" "international/emoji-zwj.el" "international/eucjp-ms.el" ;;;;;; "international/iso-transl.el" "international/mule-cmds.el" -;;;;;; "international/mule-conf.el" "international/mule.el" "international/uni-bidi.el" -;;;;;; "international/uni-brackets.el" "international/uni-category.el" -;;;;;; "international/uni-combining.el" "international/uni-comment.el" -;;;;;; "international/uni-decimal.el" "international/uni-decomposition.el" -;;;;;; "international/uni-digit.el" "international/uni-lowercase.el" -;;;;;; "international/uni-mirrored.el" "international/uni-name.el" -;;;;;; "international/uni-numeric.el" "international/uni-old-name.el" -;;;;;; "international/uni-special-lowercase.el" "international/uni-special-titlecase.el" -;;;;;; "international/uni-special-uppercase.el" "international/uni-titlecase.el" -;;;;;; "international/uni-uppercase.el" "isearch.el" "jit-lock.el" -;;;;;; "jka-cmpr-hook.el" "language/burmese.el" "language/cham.el" +;;;;;; "international/mule-conf.el" "international/mule.el" "isearch.el" +;;;;;; "jit-lock.el" "jka-cmpr-hook.el" "language/burmese.el" "language/cham.el" ;;;;;; "language/chinese.el" "language/cyrillic.el" "language/czech.el" ;;;;;; "language/english.el" "language/ethiopic.el" "language/european.el" ;;;;;; "language/georgian.el" "language/greek.el" "language/hebrew.el" commit f70e852ea63a602c2db0b0c61c09e7f86b26b505 Author: Po Lu Date: Wed Jun 29 20:16:44 2022 +0800 ; Fix build warnings * lisp/x-dnd.el (x-begin-drag): Add missing declarations. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 5820cae29b..b7a20d37ce 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -1128,6 +1128,8 @@ ACTION is the action given to `x-begin-drag'." ;;; XDS protocol support. (declare-function x-begin-drag "xfns.c") +(declare-function x-delete-window-property "xfns.c") +(defvar selection-converter-alist) (defvar x-dnd-xds-current-file nil "The file name for which a direct save is currently being performed.") commit b7d3231e80e5ac26dd824d9d3c7d7337ebc2f021 Author: Po Lu Date: Wed Jun 29 20:14:15 2022 +0800 Update dnd-tests.el to make sure remote files are removed when Emacs quits * test/lisp/dnd-tests.el (dnd-tests-begin-drag-files) (dnd-tests-begin-file-drag): Test value of `kill-emacs-hook'. diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index 18dd55c206..b6edbc3a2e 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -242,10 +242,17 @@ This function only tries to handle strings." ;; Test that the remote file was added to the list of files ;; to remove later. (should dnd-last-dragged-remote-file) + ;; Make sure the appropriate hook is added so the remote + ;; files are removed when Emacs exits. + (should (memq #'dnd-remove-last-dragged-remote-file + kill-emacs-hook)) ;; Test that the remote file was removed. (should (progn (dnd-begin-file-drag normal-temp-file) (not dnd-last-dragged-remote-file))) + ;; Make sure the remote file removal hook was deleted. + (should-not (memq #'dnd-remove-last-dragged-remote-file + kill-emacs-hook)) ;; Test that links to remote files can't be created. (should-error (dnd-begin-file-drag remote-temp-file nil 'link)) ;; Test dragging a file with a multibyte filename. @@ -298,12 +305,19 @@ This function only tries to handle strings." ;; Test that the remote file produced was added to the list ;; of files to remove upon the next call. (should dnd-last-dragged-remote-file) + ;; Make sure the appropriate hook is added so the remote + ;; files are removed when Emacs exits. + (should (memq #'dnd-remove-last-dragged-remote-file + kill-emacs-hook)) ;; Two local files at the same time. (should (eq (dnd-begin-drag-files (list normal-temp-file normal-temp-file-1)) 'copy)) ;; Test that the remote files were removed. (should-not dnd-last-dragged-remote-file) + ;; And so was the hook. + (should-not (memq #'dnd-remove-last-dragged-remote-file + kill-emacs-hook)) ;; Test the selection data is correct. (let ((uri-list-data (cdr (dnd-tests-verify-selection-data 'text/uri-list))) (username-data (dnd-tests-verify-selection-data 'text/x-xdnd-username)) @@ -347,6 +361,10 @@ This function only tries to handle strings." ;; Make sure exactly two valid remote files ;; were downloaded. (eq (length dnd-last-dragged-remote-file) 2))) + ;; Make sure the appropriate hook is added so the remote + ;; files are removed when Emacs exits. + (should (memq #'dnd-remove-last-dragged-remote-file + kill-emacs-hook)) ;; Make sure links can't be created to remote files. (should-error (dnd-begin-drag-files (list normal-temp-file remote-temp-file @@ -357,6 +375,9 @@ This function only tries to handle strings." normal-temp-file-1) nil 'link) 'link)) + ;; Make sure the remote file removal hook was deleted. + (should-not (memq #'dnd-remove-last-dragged-remote-file + kill-emacs-hook)) ;; Make sure you can't drag an empty list of files. (should-error (dnd-begin-drag-files nil)) ;; And when all remote files are inaccessible. commit d07063f69fab25da49c69e7790223511d61e9098 Author: Po Lu Date: Wed Jun 29 20:10:25 2022 +0800 Implement starting X Direct Save (XDS) drops * doc/lispref/frames.texi (Drag and Drop): Document new function `dnd-direct-save'. * etc/NEWS: Likewise. * lisp/dnd.el (dnd-direct-save-remote-files): New defcustom. (dnd-begin-file-drag): Implement defucstom. (dnd-begin-drag-files): Add kill-emacs-hook after saving remote file. (dnd-direct-save): New function. * lisp/x-dnd.el (x-dnd-known-types): Fix coding style. (x-dnd-handle-drag-n-drop-event): Handle local value with self-originating DND events. (x-dnd-xds-current-file, x-dnd-xds-source-frame): New defvars. (x-dnd-handle-direct-save, x-dnd-do-direct-save): New functions. * src/xfns.c (Fx_begin_drag): Allow any atom to be used as a DND action. * src/xselect.c (symbol_to_x_atom): Make public. * src/xterm.c (x_dnd_note_self_drop): Include selection local value. (x_ignore_errors_for_next_request): Don't assume x_error_message is set. * src/xterm.h: Update prototypes. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 16f7ad312a..860258a964 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4186,6 +4186,13 @@ This function is like @code{dnd-begin-file-drag}, except that dropping multiple files, then the first file will be used instead. @end defun +@defun dnd-direct-save file name &optional frame allow-same-frame +This function is similar to @code{dnd-begin-file-drag} (with the +default action of copy), but instead of specifying the action you +specify the name of the copy created by the target program in +@code{name}. +@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/etc/NEWS b/etc/NEWS index add7784ade..ce32542028 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2343,9 +2343,10 @@ list in reported motion events if there is no frame underneath the mouse pointer. +++ -** 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 functions for dragging items from Emacs to other programs. +The new functions 'x-begin-drag', 'dnd-begin-file-drag', +'dnd-begin-drag-files', and 'dnd-direct-save' allow dragging contents +(such as files and text) from Emacs to other programs. --- ** New function 'ietf-drums-parse-date-string'. diff --git a/lisp/dnd.el b/lisp/dnd.el index 9d72a4b595..29f4ca98ec 100644 --- a/lisp/dnd.el +++ b/lisp/dnd.el @@ -106,6 +106,18 @@ program." :version "29.1" :group 'dnd) +(defcustom dnd-direct-save-remote-files 'x + "Whether or not to perform a direct save of remote files. +This is compatible with less programs, but means dropped files +will be saved with their actual file names, and not a temporary +file name provided by TRAMP. + +This defaults to `x', which means only to drop that way on X +Windows." + :type '(choice (const :tag "Only use direct save on X Windows" x) + (const :tag "Use direct save everywhere" t) + (const :tag "Don't use direct save"))) + ;; Functions (defun dnd-handle-movement (posn) @@ -409,48 +421,58 @@ currently being held down. It should only be called upon a (dnd-remove-last-dragged-remote-file) (unless action (setq action 'copy)) - (let ((original-file file)) - (when (file-remote-p file) - (if (eq action 'link) - (error "Cannot create symbolic link to remote file") - (setq file (file-local-copy file)) - (setq dnd-last-dragged-remote-file file) - (add-hook 'kill-emacs-hook - #'dnd-remove-last-dragged-remote-file))) - (gui-set-selection 'XdndSelection - (propertize (expand-file-name file) 'text/uri-list - (concat "file://" - (expand-file-name file)))) - (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-xdnd-username" - ;; Traditional X selection targets used by - ;; programs supporting the Motif - ;; drag-and-drop protocols. Also used by NS - ;; and Haiku. - "FILE_NAME" "FILE" "HOST_NAME" - ;; ToolTalk filename. Mostly used by CDE - ;; programs. - "_DT_NETFILE") - (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. - (when (file-remote-p original-file) - (ignore-errors - (delete-file original-file))))) - ((eq return-value 'XdndActionLink) 'link) - ((not return-value) nil) - (t 'private))))) + (if (and (or (and (eq dnd-direct-save-remote-files 'x) + (eq (framep (or frame + (selected-frame))) + 'x)) + (and dnd-direct-save-remote-files + (not (eq dnd-direct-save-remote-files 'x)))) + (eq action 'copy) + (file-remote-p file)) + (dnd-direct-save file (file-name-nondirectory file) + frame allow-same-frame) + (let ((original-file file)) + (when (file-remote-p file) + (if (eq action 'link) + (error "Cannot create symbolic link to remote file") + (setq file (file-local-copy file)) + (setq dnd-last-dragged-remote-file file) + (add-hook 'kill-emacs-hook + #'dnd-remove-last-dragged-remote-file))) + (gui-set-selection 'XdndSelection + (propertize (expand-file-name file) 'text/uri-list + (concat "file://" + (expand-file-name file)))) + (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-xdnd-username" + ;; Traditional X selection targets used by + ;; programs supporting the Motif + ;; drag-and-drop protocols. Also used by NS + ;; and Haiku. + "FILE_NAME" "FILE" "HOST_NAME" + ;; ToolTalk filename. Mostly used by CDE + ;; programs. + "_DT_NETFILE") + (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. + (when (file-remote-p original-file) + (ignore-errors + (delete-file original-file))))) + ((eq return-value 'XdndActionLink) 'link) + ((not return-value) nil) + (t 'private)))))) (defun dnd-begin-drag-files (files &optional frame action allow-same-frame) "Begin dragging FILES from FRAME. @@ -477,6 +499,9 @@ FILES will be dragged." (error (message "Failed to download file: %s" error) (setcar tem nil)))) (setq tem (cdr tem))) + (when dnd-last-dragged-remote-file + (add-hook 'kill-emacs-hook + #'dnd-remove-last-dragged-remote-file)) ;; Remove any files that failed to download from a remote host. (setq new-files (delq nil new-files)) (unless new-files @@ -520,6 +545,27 @@ FILES will be dragged." ((not return-value) nil) (t 'private))))) +(declare-function x-dnd-do-direct-save "x-dnd.el") + +(defun dnd-direct-save (file name &optional frame allow-same-frame) + "Drag FILE from FRAME, but do not treat it as an actual file. +Instead, ask the target window to insert the file with NAME. +File managers will create a file in the displayed directory with +the contents of FILE and the name NAME, while text editors will +insert the contents of FILE in a new document named +NAME. + +ALLOW-SAME-FRAME means the same as in `dnd-begin-file-drag'. +Return `copy' if the drop was successful, else nil." + (setq file (expand-file-name file)) + (cond ((eq window-system 'x) + (when (x-dnd-do-direct-save file name frame + allow-same-frame) + 'copy)) + ;; Avoid infinite recursion. + (t (let ((dnd-direct-save-remote-files nil)) + (dnd-begin-file-drag file frame nil allow-same-frame))))) + (provide 'dnd) ;;; dnd.el ends here diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 5c6d25ba68..5820cae29b 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -84,20 +84,20 @@ if drop is successful, nil if not." (defcustom x-dnd-known-types (mapcar 'purecopy - '("text/uri-list" - "text/x-moz-url" - "_NETSCAPE_URL" - "FILE_NAME" - "UTF8_STRING" - "text/plain;charset=UTF-8" - "text/plain;charset=utf-8" - "text/unicode" - "text/plain" - "COMPOUND_TEXT" - "STRING" - "TEXT" - "DndTypeFile" - "DndTypeText")) + '("text/uri-list" + "text/x-moz-url" + "_NETSCAPE_URL" + "FILE_NAME" + "UTF8_STRING" + "text/plain;charset=UTF-8" + "text/plain;charset=utf-8" + "text/unicode" + "text/plain" + "COMPOUND_TEXT" + "STRING" + "TEXT" + "DndTypeFile" + "DndTypeText")) "The types accepted by default for dropped data. The types are chosen in the order they appear in the list." :version "22.1" @@ -380,7 +380,8 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." (progn (let ((action (cdr (assoc (symbol-name (cadr client-message)) x-dnd-xdnd-to-action))) - (targets (cddr client-message))) + (targets (cddr client-message)) + (local-value (nth 2 client-message))) (x-dnd-save-state window nil nil (apply #'vector targets)) (x-dnd-maybe-call-test-function window action) @@ -388,8 +389,8 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." (x-dnd-drop-data event (if (framep window) window (window-frame window)) window - (x-get-selection-internal - 'XdndSelection + (x-get-local-selection + local-value (intern (x-dnd-current-type window))) (x-dnd-current-type window)) (x-dnd-forget-drop window)))) @@ -1124,6 +1125,81 @@ ACTION is the action given to `x-begin-drag'." (setq x-dnd-native-test-function #'x-dnd-handle-native-drop) +;;; XDS protocol support. + +(declare-function x-begin-drag "xfns.c") + +(defvar x-dnd-xds-current-file nil + "The file name for which a direct save is currently being performed.") + +(defvar x-dnd-xds-source-frame nil + "The frame from which a direct save is currently being performed.") + +(defun x-dnd-handle-direct-save (_selection _type _value) + "Handle a selection request for `XdndDirectSave'." + (let* ((uri (x-window-property "XdndDirectSave0" + x-dnd-xds-source-frame + "AnyPropertyType" nil t)) + (local-name (dnd-get-local-file-name uri nil))) + (if (not local-name) + '(STRING . "F") + (condition-case nil + (progn + (rename-file x-dnd-xds-current-file + local-name t) + (when (equal x-dnd-xds-current-file + dnd-last-dragged-remote-file) + (dnd-remove-last-dragged-remote-file))) + (:success '(STRING . "S")) + (error '(STRING . "F")))))) + +(defun x-dnd-do-direct-save (file name frame allow-same-frame) + "Perform a direct save operation on FILE, from FRAME. +FILE is the file containing the contents to drop. +NAME is the name that should be given to the file after dropping. +FRAME is the frame from which the drop will originate. +ALLOW-SAME-FRAME means whether or not dropping will be allowed +on FRAME. + +Return the action taken by the drop target, or nil." + (dnd-remove-last-dragged-remote-file) + (let ((file-name file) + (original-file-name file) + (selection-converter-alist + (cons (cons 'XdndDirectSave0 + #'x-dnd-handle-direct-save) + selection-converter-alist)) + (x-dnd-xds-current-file nil) + (x-dnd-xds-source-frame frame) + encoded-name) + (unwind-protect + (progn + (when (file-remote-p file) + (setq file-name (file-local-copy file)) + (setq dnd-last-dragged-remote-file file-name) + (add-hook 'kill-emacs-hook + #'dnd-remove-last-dragged-remote-file)) + (setq encoded-name + (encode-coding-string name + (or file-name-coding-system + default-file-name-coding-system))) + (setq x-dnd-xds-current-file file-name) + (x-change-window-property "XdndDirectSave0" encoded-name + frame "text/plain" 8 nil) + (gui-set-selection 'XdndSelection (concat "file://" file-name)) + ;; FIXME: this does not work with GTK file managers, since + ;; they always reach for `text/uri-list' first, contrary to + ;; the spec. + (x-begin-drag '("XdndDirectSave0" "text/uri-list") + 'XdndActionDirectSave + frame nil allow-same-frame)) + ;; TODO: check for failure and implement selection-based file + ;; transfer. + (x-delete-window-property "XdndDirectSave0" frame) + ;; Delete any remote copy that was made. + (when (not (equal file-name original-file-name)) + (delete-file file-name))))) + (provide 'x-dnd) ;;; x-dnd.el ends here diff --git a/src/xfns.c b/src/xfns.c index 36920035d7..9dcf73da1c 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6936,6 +6936,11 @@ that mouse buttons are being held down, such as immediately after a xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate; else if (EQ (action, QXdndActionAsk)) xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk; + else if (SYMBOLP (action)) + /* This is to accommodate non-standard DND protocols such as XDS + that are explictly implemented by Emacs, and is not documented + for that reason. */ + xaction = symbol_to_x_atom (FRAME_DISPLAY_INFO (f), action); else if (CONSP (action)) { xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk; diff --git a/src/xselect.c b/src/xselect.c index a1f590632f..7993899b2c 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -121,7 +121,7 @@ selection_quantum (Display *display) /* This converts a Lisp symbol to a server Atom, avoiding a server roundtrip whenever possible. */ -static Atom +Atom symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) { Atom val; diff --git a/src/xterm.c b/src/xterm.c index 33c8d4199e..76da1064eb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4699,6 +4699,9 @@ x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target, XFree (atom_names[i - 1]); } + lval = Fcons (assq_no_quit (QXdndSelection, + FRAME_TERMINAL (f)->Vselection_alist), + lval); lval = Fcons (intern (name), lval); lval = Fcons (QXdndSelection, lval); ie.arg = lval; @@ -23030,8 +23033,8 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) { /* There is no point in making this extra sync if all requests are known to have been fully processed. */ - if ((LastKnownRequestProcessed (x_error_message->dpy) - != NextRequest (x_error_message->dpy) - 1)) + if ((LastKnownRequestProcessed (dpyinfo->display) + != NextRequest (dpyinfo->display) - 1)) XSync (dpyinfo->display, False); x_clean_failable_requests (dpyinfo); diff --git a/src/xterm.h b/src/xterm.h index ff81babc33..f7b93529cb 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1576,6 +1576,7 @@ extern void x_handle_selection_notify (const XSelectionEvent *); extern void x_handle_selection_event (struct selection_input_event *); extern void x_clear_frame_selections (struct frame *); extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom); +extern Atom symbol_to_x_atom (struct x_display_info *, Lisp_Object); extern bool x_handle_dnd_message (struct frame *, const XClientMessageEvent *, commit bf137fdbd2865773a34ec2c74d608cdd586d5a2c Author: Stefan Kangas Date: Wed Jun 29 14:07:36 2022 +0200 ; * admin/make-tarball.txt: Small clarification. diff --git a/admin/make-tarball.txt b/admin/make-tarball.txt index 02b4f318e2..98001e24e7 100644 --- a/admin/make-tarball.txt +++ b/admin/make-tarball.txt @@ -158,13 +158,15 @@ General steps (for each step, check for possible errors): 5. Copy lisp/loaddefs.el to lisp/ldefs-boot.el. - Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the - files changed by M-x set-version. The easiest way of doing that - is "C-x v d ROOT-DIR RET", then go to the first modified file, - press 'M' to mark all modified files, and finally 'v' to commit - them. Make sure the commit log message mentions all the changes - in all modified files, as by default 'v' doesn't necessarily do - so. + Commit ChangeLog.N, etc/AUTHORS, lisp/ldefs-boot.el, and the files + changed by M-x set-version. Note that the set-version changes + should be committed separately, as described in step 3 above. + + The easiest way of doing that is "C-x v d ROOT-DIR RET", then go + to the first modified file, press 'M' to mark all modified files, + and finally 'v' to commit them. Make sure the commit log message + mentions all the changes in all modified files, as by default 'v' + doesn't necessarily do so. If someone else made a commit between step 1 and now, you need to repeat from step 4 onwards. (You can commit the files commit 3c0b18facd0b7e733ec33913da02896b662742c2 Author: Stefan Kangas Date: Wed Jun 29 13:29:27 2022 +0200 Make two text-property-search tests easier to read * test/lisp/emacs-lisp/text-property-search-tests.el (text-property-search-forward/point-at-beginning) (text-property-search-backward/point-at-end): Rewrite to make tests easier to read. diff --git a/test/lisp/emacs-lisp/text-property-search-tests.el b/test/lisp/emacs-lisp/text-property-search-tests.el index d137572f30..98fdd55e85 100644 --- a/test/lisp/emacs-lisp/text-property-search-tests.el +++ b/test/lisp/emacs-lisp/text-property-search-tests.el @@ -156,20 +156,19 @@ ;;;; Position after search. -(defun text-property-search--pos-test (fun pos &optional reverse) +(ert-deftest text-property-search-forward/point-at-beginning () (with-temp-buffer - (insert (concat "foo " - (propertize "bar" 'x t) - " baz")) - (goto-char (if reverse (point-max) (point-min))) - (funcall fun 'x t) - (should (= (point) pos)))) - -(ert-deftest text-property-search-forward-point-at-beginning () - (text-property-search--pos-test #'text-property-search-forward 5)) - -(ert-deftest text-property-search-backward-point-at-end () - (text-property-search--pos-test #'text-property-search-backward 8 t)) + (insert (concat "1234" (propertize "567" 'x t) "890")) + (goto-char (point-min)) + (text-property-search-forward 'x t) + (should (= (point) 5)))) + +(ert-deftest text-property-search-backward/point-at-end () + (with-temp-buffer + (insert (concat "1234" (propertize "567" 'x t) "890")) + (goto-char (point-max)) + (text-property-search-backward 'x t) + (should (= (point) 8)))) (provide 'text-property-search-tests) commit f9d35afea37eb3a22ac1301dda431a79b3a34a02 Author: Stefan Kangas Date: Mon Jun 27 16:08:10 2022 +0200 Minor cleanup in dired-x-bind-find-file * lisp/dired-x.el (dired-x-bind-find-file): Use 'format-message' and 'keymap-set'. diff --git a/lisp/dired-x.el b/lisp/dired-x.el index b4b647f1b0..ed7f71e006 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -1515,12 +1515,13 @@ Binding direction based on `dired-x-hands-off-my-keys'." (interactive) (if (called-interactively-p 'interactive) (setq dired-x-hands-off-my-keys - (not (y-or-n-p "Bind dired-x-find-file over find-file? ")))) + (not (y-or-n-p (format-message + "Bind `dired-x-find-file' over `find-file'?"))))) (unless dired-x-hands-off-my-keys - (define-key (current-global-map) [remap find-file] - 'dired-x-find-file) - (define-key (current-global-map) [remap find-file-other-window] - 'dired-x-find-file-other-window))) + (keymap-set (current-global-map) " " + #'dired-x-find-file) + (keymap-set (current-global-map) " " + #'dired-x-find-file-other-window))) ;; Now call it so binding is correct. This could go in the :initialize ;; slot, but then dired-x-bind-find-file has to be defined before the commit 4d41bb7847348009f8102625ce080a2ea94984a4 Author: Lars Ingebrigtsen Date: Wed Jun 29 13:05:46 2022 +0200 Improve the eval-defun doc string * lisp/progmodes/elisp-mode.el (eval-defun): Document what the command actually does w.r.t. finding a form to evaluate (bug#47747). diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index fc25767934..0bf13a0e09 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1679,7 +1679,10 @@ Return the result of evaluation." elisp--eval-defun-result)) (defun eval-defun (edebug-it) - "Evaluate the top-level form containing point, or after point. + "Evaluate the top-level form containing point. +If point isn't in a top-level form, evaluate the first top-level +form after point. If there is no top-level form after point, +eval the first preceeding top-level form. If the current defun is actually a call to `defvar' or `defcustom', evaluating it this way resets the variable using its initial value commit 446d5b14a90e35cd0d67cd22592cde7a6d2891f9 Author: Lars Ingebrigtsen Date: Wed Jun 29 13:00:25 2022 +0200 Ensure that In-Reply-To is saved in drafts in Message * lisp/gnus/message.el (message-hidden-headers): Hide In-Reply-To now that we pre-generate it. (message-setup-1): Pre-generate In-Reply-To so that it'll be saved in drafts (bug#47639). diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 6973d8a86b..48115a4165 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -1468,11 +1468,11 @@ candidates: (memq feature message-shoot-gnksa-feet))) (defcustom message-hidden-headers '("^References:" "^Face:" "^X-Face:" - "^X-Draft-From:") + "^X-Draft-From:" "^In-Reply-To:") "Regexp of headers to be hidden when composing new messages. This can also be a list of regexps to match headers. Or a list starting with `not' and followed by regexps." - :version "22.1" + :version "29.1" :group 'message :link '(custom-manual "(message)Message Headers") :type '(choice @@ -6881,13 +6881,14 @@ are not included." (or (bolp) (insert ?\n))) (insert (concat mail-header-separator "\n")) (forward-line -1) - ;; If a crash happens while replying, the auto-save file would *not* have a - ;; `References:' header if `message-generate-headers-first' was nil. - ;; Therefore, always generate it first. + ;; If a crash happens while replying, the auto-save file would *not* + ;; have a `References:' header if `message-generate-headers-first' + ;; was nil. Therefore, always generate it first. (And why not + ;; include the `In-Reply-To' header as well.) (let ((message-generate-headers-first (if (eq message-generate-headers-first t) t - (append message-generate-headers-first '(References))))) + (append message-generate-headers-first '(References In-Reply-To))))) (when (message-news-p) (when message-default-news-headers (insert message-default-news-headers) commit 9c9e34e9b683b6b548d92dc7c1ed57f06f62eefb Author: Tom Gillespie Date: Tue Jun 28 19:55:31 2022 -0700 test/lisp/progmodes/python-tests.el: add test for nav end of block Add test for python-nav-end-of-block to prevent regression of bug#56271. diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index e17bc0df92..c59a2e7953 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -2565,6 +2565,18 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3): (python-tests-look-at "print 'After f(*args)'") (line-end-position)))))) +(ert-deftest python-nav-end-of-block-2 () + "Ensure that `python-nav-end-of-block' does not enter an infinite loop." + (python-tests-with-temp-buffer + "def + ='' + ' +\"\"\"\"\"\" + # +'' +" + (python-nav-end-of-block))) + (ert-deftest python-nav-forward-block-1 () "This also accounts as a test for `python-nav-backward-block'." (python-tests-with-temp-buffer commit bf1dbdd87bb87eb9f18f7677d6d254b249b4c251 Author: Tom Gillespie Date: Tue Jun 28 19:28:05 2022 -0700 lisp/progmodes/python.el (python-nav-end-of-block): prevent infinite loop lisp/progmodes/python.el (python-nav-end-of-block): Fix a bad assumption that python-nav-end-of-statement always makes forward progress by testing that it actually does. If this check is not made then it is possible for python-nav-end-of-block to enter an infinite loop. (bug#56271) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index e0c937d7ce..16cdf58611 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1636,11 +1636,15 @@ of the statement." (while (and (or noend (goto-char (line-end-position))) (not (eobp)) (cond ((setq string-start (python-syntax-context 'string)) - ;; The assertion can only fail if syntax table + ;; The condition can be nil if syntax table ;; text properties and the `syntax-ppss' cache ;; are somehow out of whack. This has been ;; observed when using `syntax-ppss' during ;; narrowing. + ;; It can also fail in cases where the buffer is in + ;; the process of being modified, e.g. when creating + ;; a string with `electric-pair-mode' disabled such + ;; that there can be an unmatched single quote (when (>= string-start last-string-end) (goto-char string-start) (if (python-syntax-context 'paren) @@ -1723,7 +1727,10 @@ backward to previous statement." (while (and (forward-line 1) (not (eobp)) (or (and (> (current-indentation) block-indentation) - (or (python-nav-end-of-statement) t)) + (let ((start (point))) + (python-nav-end-of-statement) + ;; must move forward otherwise infinite loop + (> (point) start))) (python-info-current-line-comment-p) (python-info-current-line-empty-p)))) (python-util-forward-comment -1) commit e73dbcf26d9de114b3ba228edaf946418b476052 Author: Lars Ingebrigtsen Date: Wed Jun 29 11:53:16 2022 +0200 Fix compilation-mode parsing of file names in Gradle errors * lisp/progmodes/compile.el (compilation-error-regexp-alist-alist): Fix parsing of file names in Gradle output (bug#56249). diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index d28fce9dbd..28a49fc0dd 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -365,9 +365,10 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1)) ;; PROGRAM:SOURCE-FILE-NAME:LINENO: MESSAGE ;; which is used for non-interactive programs other than ;; compilers (e.g. the "jade:" entry in compilation.txt). - (? (| (: alpha (+ (in ?. ?- alnum)) ":" (? " ")) - ;; Skip indentation generated by GCC's -fanalyzer. - (: (+ " ") "|"))) + (? (: (* " ") ; Allow space to precede the program name. + (| (: alpha (+ (in ?. ?- alnum)) ":" (? " ")) + ;; Skip indentation generated by GCC's -fanalyzer. + (: (+ " ") "|")))) ;; File name group. (group-n 1 @@ -387,13 +388,13 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1)) ;; Line number group. (group-n 2 (regexp "[0-9]+")) (? (| (: "-" - (group-n 4 (regexp "[0-9]+")) ; ending line - (? "." (group-n 5 (regexp "[0-9]+")))) ; ending column + (group-n 4 (regexp "[0-9]+")) ; ending line + (? "." (group-n 5 (regexp "[0-9]+")))) ; ending column (: (in ".:") - (group-n 3 (regexp "[0-9]+")) ; starting column + (group-n 3 (regexp "[0-9]+")) ; starting column (? "-" (? (group-n 4 (regexp "[0-9]+")) ".") ; ending line - (group-n 5 (regexp "[0-9]+")))))) ; ending column + (group-n 5 (regexp "[0-9]+")))))) ; ending column ":" (| (: (* " ") (group-n 6 (| "FutureWarning" @@ -1243,7 +1244,7 @@ POS and RES.") ;; Return a property list with all meta information on this error location. (defun compilation-error-properties (file line end-line col end-col type fmt - rule) + rule) (unless (text-property-not-all (match-beginning 0) (point) 'compilation-message nil) (if file commit 3d91d55432f42bc063439d74fbccfe805fbc0034 Author: Michael Albinus Date: Wed Jun 29 11:08:44 2022 +0200 Update Tramp version (don't merge with master) * doc/misc/trampver.texi: * lisp/net/trampver.el: Change version to "2.5.3". diff --git a/doc/misc/trampver.texi b/doc/misc/trampver.texi index a6914a58d0..580d9ba69e 100644 --- a/doc/misc/trampver.texi +++ b/doc/misc/trampver.texi @@ -8,7 +8,7 @@ @c In the Tramp GIT, the version numbers are auto-frobbed from @c tramp.el, and the bug report address is auto-frobbed from @c configure.ac. -@set trampver 2.5.3-pre +@set trampver 2.5.3 @set trampurl https://www.gnu.org/software/tramp/ @set tramp-bug-report-address tramp-devel@@gnu.org @set emacsver 25.1 diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el index 5863beb295..c1d58a45f4 100644 --- a/lisp/net/trampver.el +++ b/lisp/net/trampver.el @@ -7,7 +7,7 @@ ;; Maintainer: Michael Albinus ;; Keywords: comm, processes ;; Package: tramp -;; Version: 2.5.3-pre +;; Version: 2.5.3 ;; Package-Requires: ((emacs "25.1")) ;; Package-Type: multi ;; URL: https://www.gnu.org/software/tramp/ @@ -40,7 +40,7 @@ ;; ./configure" to change them. ;;;###tramp-autoload -(defconst tramp-version "2.5.3-pre" +(defconst tramp-version "2.5.3" "This version of Tramp.") ;;;###tramp-autoload @@ -78,7 +78,7 @@ ;; Check for Emacs version. (let ((x (if (not (string-lessp emacs-version "25.1")) "ok" - (format "Tramp 2.5.3-pre is not fit for %s" + (format "Tramp 2.5.3 is not fit for %s" (replace-regexp-in-string "\n" "" (emacs-version)))))) (unless (string-equal "ok" x) (error "%s" x))) commit 0ebad14f208e9ebdc0eab0e1c6ad558d0db76a3b Author: Po Lu Date: Wed Jun 29 15:59:56 2022 +0800 * lisp/pgtk-dnd.el (pgtk-dnd-use-offix-drop): Remove extra variable. diff --git a/lisp/pgtk-dnd.el b/lisp/pgtk-dnd.el index df267549d7..f9532269d6 100644 --- a/lisp/pgtk-dnd.el +++ b/lisp/pgtk-dnd.el @@ -92,22 +92,6 @@ The types are chosen in the order they appear in the list." :type '(repeat string) :group 'pgtk) -(defcustom pgtk-dnd-use-offix-drop 'files - "If non-nil, use the OffiX protocol to drop files and text. -This allows dropping (via `dired-mouse-drag-files' or -`mouse-drag-and-drop-region-cross-program') on some old Java -applets and old KDE programs. Turning this off allows dropping -only text on some other programs such as xterm and urxvt. - -If the symbol `files', use the OffiX protocol when dropping -files, and the fallback drop method (which is used with programs -like xterm) for text." - :version "29.1" - :type '(choice (const :tag "Don't use the OffiX protocol for drag-and-drop" nil) - (const :tag "Only use the OffiX protocol to drop files" files) - (const :tag "Use the OffiX protocol for both files and text" t)) - :group 'pgtk) - ;; Internal variables (defvar pgtk-dnd-current-state nil commit 60af986f38e98fde3e17005e49d175c061a1a29a Author: Po Lu Date: Wed Jun 29 15:09:17 2022 +0800 Clean up failable requests in more places * lisp/term/haiku-win.el (haiku-get-numeric-enum): Fix build. * src/xterm.c (x_clean_failable_requests): Avoid redundant memcpy if first == last. (x_ignore_errors_for_next_request): Fix check for last request. (x_check_errors, x_had_errors_p): Clean up failable requests here. diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index f73c8b7125..f6e4829cad 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -174,25 +174,26 @@ VALUE as a unibyte string, or nil if VALUE was not a string." (insert "\n"))) (buffer-string)))))) -(defun haiku-get-numeric-enum (name) - "Return the numeric value of the system enumerator NAME." - (or (get name 'haiku-numeric-enum) - (let ((value 0) - (offset 0) - (string (symbol-name name))) - (cl-loop for octet across string - do (progn - (when (or (< octet 0) - (> octet 255)) - (error "Out of range octet: %d" octet)) - (setq value - (logior value - (lsh octet - (- (* (1- (length string)) 8) - offset)))) - (setq offset (+ offset 8)))) - (prog1 value - (put name 'haiku-enumerator-id value))))) +(eval-and-compile + (defun haiku-get-numeric-enum (name) + "Return the numeric value of the system enumerator NAME." + (or (get name 'haiku-numeric-enum) + (let ((value 0) + (offset 0) + (string (symbol-name name))) + (cl-loop for octet across string + do (progn + (when (or (< octet 0) + (> octet 255)) + (error "Out of range octet: %d" octet)) + (setq value + (logior value + (lsh octet + (- (* (1- (length string)) 8) + offset)))) + (setq offset (+ offset 8)))) + (prog1 value + (put name 'haiku-enumerator-id value)))))) (defmacro haiku-numeric-enum (name) "Expand to the numeric value NAME as a system identifier." diff --git a/src/xterm.c b/src/xterm.c index 7298feb43a..33c8d4199e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -23010,8 +23010,9 @@ x_clean_failable_requests (struct x_display_info *dpyinfo) break; } - memmove (&dpyinfo->failable_requests, first, - sizeof *first * (last - first)); + if (first != last) + memmove (&dpyinfo->failable_requests, first, + sizeof *first * (last - first)); dpyinfo->next_failable_request = (dpyinfo->failable_requests + (last - first)); @@ -23025,7 +23026,7 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) request = dpyinfo->next_failable_request; max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS; - if (request > max) + if (request >= max) { /* There is no point in making this extra sync if all requests are known to have been fully processed. */ @@ -23119,6 +23120,7 @@ x_uncatch_errors (void) void x_check_errors (Display *dpy, const char *format) { + struct x_display_info *dpyinfo; char *string; /* This shouldn't happen, since x_check_errors should be called @@ -23134,6 +23136,12 @@ x_check_errors (Display *dpy, const char *format) > x_error_message->first_request)) XSync (dpy, False); + dpyinfo = x_display_info_for_display (dpy); + + /* Clean the array of failable requests, since a sync happened. */ + if (dpyinfo) + x_clean_failable_requests (dpyinfo); + if (x_error_message->string) { string = alloca (strlen (x_error_message->string) + 1); @@ -23149,6 +23157,8 @@ x_check_errors (Display *dpy, const char *format) bool x_had_errors_p (Display *dpy) { + struct x_display_info *dpyinfo; + /* This shouldn't happen, since x_check_errors should be called immediately inside an x_catch_errors block. */ if (dpy != x_error_message->dpy) @@ -23161,6 +23171,12 @@ x_had_errors_p (Display *dpy) > x_error_message->first_request)) XSync (dpy, False); + dpyinfo = x_display_info_for_display (dpy); + + /* Clean the array of failable requests, since a sync happened. */ + if (dpyinfo) + x_clean_failable_requests (dpyinfo); + return !!x_error_message->string; } commit 7fa37d7a1439bf8cd76b336ea95d3a1982b3ae03 Author: Po Lu Date: Wed Jun 29 06:05:25 2022 +0000 Handle be:actions field in Haiku DND messages * lisp/term/haiku-win.el (haiku-get-numeric-enum): New function. (haiku-numeric-enum): New macro. (haiku-select-encode-xstring, haiku-select-encode-utf-8-string): Replace hard-coded numeric enumerators. (haiku-parse-drag-actions): New function. (haiku-drag-and-drop): Use action returned by that function. (x-begin-drag): Replace hard-coded enumerator. diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 024459e647..f73c8b7125 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -174,6 +174,30 @@ VALUE as a unibyte string, or nil if VALUE was not a string." (insert "\n"))) (buffer-string)))))) +(defun haiku-get-numeric-enum (name) + "Return the numeric value of the system enumerator NAME." + (or (get name 'haiku-numeric-enum) + (let ((value 0) + (offset 0) + (string (symbol-name name))) + (cl-loop for octet across string + do (progn + (when (or (< octet 0) + (> octet 255)) + (error "Out of range octet: %d" octet)) + (setq value + (logior value + (lsh octet + (- (* (1- (length string)) 8) + offset)))) + (setq offset (+ offset 8)))) + (prog1 value + (put name 'haiku-enumerator-id value))))) + +(defmacro haiku-numeric-enum (name) + "Expand to the numeric value NAME as a system identifier." + (haiku-get-numeric-enum name)) + (declare-function x-open-connection "haikufns.c") (declare-function x-handle-args "common-win") (declare-function haiku-selection-data "haikuselect.c") @@ -237,7 +261,7 @@ under the type `text/plain;charset=iso-8859-1'." (buffer-substring (nth 0 bounds) (nth 1 bounds))))))) (when (and (stringp value) (not (string-empty-p value))) - (list "text/plain;charset=iso-8859-1" 1296649541 + (list "text/plain;charset=iso-8859-1" (haiku-numeric-enum MIME) (encode-coding-string value 'iso-latin-1)))) (defun haiku-select-encode-utf-8-string (_selection value) @@ -251,7 +275,7 @@ VALUE will be encoded as UTF-8 and stored under the type (buffer-substring (nth 0 bounds) (nth 1 bounds))))))) (when (and (stringp value) (not (string-empty-p value))) - (list "text/plain" 1296649541 + (list "text/plain" (haiku-numeric-enum MIME) (encode-coding-string value 'utf-8-unix)))) (defun haiku-select-encode-file-name (_selection value) @@ -304,6 +328,21 @@ or a pair of markers) and turns it into a file system reference." (file-name-nondirectory default-filename))) (error "x-file-dialog on a tty frame"))) +(defun haiku-parse-drag-actions (message) + "Given the drag-and-drop message MESSAGE, retrieve the desired action." + (let ((actions (cddr (assoc "be:actions" message))) + (sorted nil)) + (dolist (action (list (haiku-numeric-enum DDCP) + (haiku-numeric-enum DDMV) + (haiku-numeric-enum DDLN))) + (when (member action actions) + (push sorted action))) + (cond + ((eql (car sorted) (haiku-numeric-enum DDCP)) 'copy) + ((eql (car sorted) (haiku-numeric-enum DDMV)) 'move) + ((eql (car sorted) (haiku-numeric-enum DDLN)) 'link) + (t 'private)))) + (defun haiku-drag-and-drop (event) "Handle specified drag-n-drop EVENT." (interactive "e") @@ -311,34 +350,35 @@ or a pair of markers) and turns it into a file system reference." (window (posn-window (event-start event)))) (if (eq string 'lambda) ; This means the mouse moved. (dnd-handle-movement (event-start event)) - (cond - ;; Don't allow dropping on something other than the text area. - ;; It does nothing and doesn't work with text anyway. - ((posn-area (event-start event))) - ((assoc "refs" string) - (with-selected-window window - (dolist (filename (cddr (assoc "refs" string))) - (dnd-handle-one-url window 'private - (concat "file:" filename))))) - ((assoc "text/uri-list" string) - (dolist (text (cddr (assoc "text/uri-list" string))) - (let ((uri-list (split-string text "[\0\r\n]" t))) - (dolist (bf uri-list) - (dnd-handle-one-url window 'private bf))))) - ((assoc "text/plain" string) - (with-selected-window window - (dolist (text (cddr (assoc "text/plain" string))) - (unless mouse-yank-at-point - (goto-char (posn-point (event-start event)))) - (dnd-insert-text window 'private - (if (multibyte-string-p text) - text - (decode-coding-string text 'undecided)))))) - ((not (eq (cdr (assq 'type string)) - 3003)) ; Type of the placeholder message Emacs uses - ; to cancel a drop on C-g. - (message "Don't know how to drop any of: %s" - (mapcar #'car string))))))) + (let ((action (haiku-parse-drag-actions string))) + (cond + ;; Don't allow dropping on something other than the text area. + ;; It does nothing and doesn't work with text anyway. + ((posn-area (event-start event))) + ((assoc "refs" string) + (with-selected-window window + (dolist (filename (cddr (assoc "refs" string))) + (dnd-handle-one-url window action + (concat "file:" filename))))) + ((assoc "text/uri-list" string) + (dolist (text (cddr (assoc "text/uri-list" string))) + (let ((uri-list (split-string text "[\0\r\n]" t))) + (dolist (bf uri-list) + (dnd-handle-one-url window action bf))))) + ((assoc "text/plain" string) + (with-selected-window window + (dolist (text (cddr (assoc "text/plain" string))) + (unless mouse-yank-at-point + (goto-char (posn-point (event-start event)))) + (dnd-insert-text window action + (if (multibyte-string-p text) + text + (decode-coding-string text 'undecided)))))) + ((not (eq (cdr (assq 'type string)) + 3003)) ; Type of the placeholder message Emacs uses + ; to cancel a drop on C-g. + (message "Don't know how to drop any of: %s" + (mapcar #'car string)))))))) (define-key special-event-map [drag-n-drop] 'haiku-drag-and-drop) @@ -393,7 +433,7 @@ take effect on menu items until the menu bar is updated again." ;; 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 maybe-string) - 1296649541) + (haiku-numeric-enum MIME)) (alist-get (car selection-result) message nil nil #'equal)))) (if (not (consp (cadr selection-result))) commit 9c2b1d37e729f7af9e9661be7ece8348bae70ffa Author: Gerd Möllmann Date: Wed Jun 29 07:53:35 2022 +0200 Ensure correct toggle menu item display * lisp/menu-bar.el (menu-bar-make-toggle-command): Call force-mode-line-update. (Bug#56155) diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 4a943d2528..92989fcfb2 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -749,7 +749,11 @@ by \"Save Options\" in Custom buffers.") ;; interactively, because the purpose is to mark the variable as a ;; candidate for `Save Options', and we do not want to save options that ;; the user has already set explicitly in the init file. - (when interactively (customize-mark-as-set ',variable))) + (when interactively + (customize-mark-as-set ',variable)) + ;; Toggle menu items must make sure that the menu is updated so + ;; that toggle marks are drawn in the right state. + (force-mode-line-update t)) '(menu-item ,item-name ,command :help ,help :button (:toggle . (and (default-boundp ',variable) (default-value ',variable))) commit a0d7caf865269ce8aa3cad85cabda4e5cbffd9c2 Merge: 0e6516a1f0 2eba8cad20 Author: Stefan Kangas Date: Wed Jun 29 06:31:15 2022 +0200 Merge from origin/emacs-28 2eba8cad20 Tramp shall not trap unrelated D-Bus errors a8e72eb0e2 ; * etc/NEWS: Fix file name quotations. 091b22cb12 Fix hash table function return values in manual # Conflicts: # etc/NEWS commit 0e6516a1f022e18f4e32848331954deb0e850d4e Author: Po Lu Date: Wed Jun 29 10:24:14 2022 +0800 Fix reported problem with drag-and-drop inside VirtualBox * lisp/x-dnd.el (x-dnd-handle-old-kde, x-dnd-handle-offix) (x-dnd-handle-motif): Select window before handling drop, like on Xdnd. (x-dnd-convert-to-offix, x-dnd-do-offix-drop) (x-dnd-handle-unsupported-drop): Accept local selection data and use that instead. * src/keyboard.c (kbd_buffer_get_event): Call unsupported drop function with local selection data as 8th arg. * src/xselect.c (x_get_local_selection): Accept new arg `local_value'. All callers changed. (Fx_get_local_selection): New function. (syms_of_xselect): Update defsubrs. * src/xterm.c (x_dnd_lose_ownership): New function. (x_dnd_begin_drag_and_drop): Unless new variable is true, disown XdndSelection after returning. This supposedly makes drag-and-drop from guest to host work in VirtualBox without causing pointer motion to become choppy afterwards. (syms_of_xterm): New variable `x_dnd_preserve_selection_data' and update doc string of `x-dnd-unsupported-drop-function'. * test/lisp/dnd-tests.el (dnd-tests-begin-text-drag) (dnd-tests-begin-file-drag, dnd-tests-begin-drag-files): Set new variable to nil during tests. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 22277033f5..5c6d25ba68 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -443,6 +443,8 @@ EVENT, FRAME, WINDOW and DATA mean the same thing they do in ;; Now call the test function to decide what action to perform. (x-dnd-maybe-call-test-function window 'private) (unwind-protect + (when (windowp window) + (select-window window)) (x-dnd-drop-data event frame window data (symbol-name type)) (x-dnd-forget-drop window)))))) @@ -500,6 +502,8 @@ message (format 32) that caused EVENT to be generated." ;; Now call the test function to decide what action to perform. (x-dnd-maybe-call-test-function window 'private) (unwind-protect + (when (windowp window) + (select-window window)) (x-dnd-drop-data event frame window data (symbol-name type)) (x-dnd-forget-drop window)))) @@ -926,6 +930,8 @@ Return a vector of atoms containing the selection targets." reply))) ((eq message-type 'XmDROP_START) + (when (windowp window) + (select-window window)) (let* ((x (x-dnd-motif-value-to-list (x-dnd-get-motif-value data 8 2 source-byteorder) 2 my-byteorder)) @@ -1014,19 +1020,22 @@ Return a vector of atoms containing the selection targets." ;;; Handling drops. (defvar x-treat-local-requests-remotely) +(declare-function x-get-local-selection "xfns.c") -(defun x-dnd-convert-to-offix (targets) - "Convert the contents of `XdndSelection' to OffiX data. +(defun x-dnd-convert-to-offix (targets local-selection) + "Convert local selection data to OffiX data. TARGETS should be the list of targets currently available in `XdndSelection'. Return a list of an OffiX type, and data suitable for passing to `x-change-window-property', or nil if the -data could not be converted." +data could not be converted. +LOCAL-SELECTION should be the local selection data describing the +selection data to convert." (let ((x-treat-local-requests-remotely t) file-name-data string-data) (cond ((and (member "FILE_NAME" targets) (setq file-name-data - (gui-get-selection 'XdndSelection 'FILE_NAME))) + (x-get-local-selection local-selection 'FILE_NAME))) (if (string-match-p "\0" file-name-data) ;; This means there are multiple file names in ;; XdndSelection. Convert the file name data to a format @@ -1035,19 +1044,23 @@ data could not be converted." (cons 'DndTypeFile (concat file-name-data "\0")))) ((and (member "STRING" targets) (setq string-data - (gui-get-selection 'XdndSelection 'STRING))) + (x-get-local-selection local-selection 'STRING))) (cons 'DndTypeText (encode-coding-string string-data 'latin-1)))))) -(defun x-dnd-do-offix-drop (targets x y frame window-id) - "Perform an OffiX drop on WINDOW-ID with the contents of `XdndSelection'. +(defun x-dnd-do-offix-drop (targets x y frame window-id contents) + "Perform an OffiX drop on WINDOW-ID with the given selection contents. Return non-nil if the drop succeeded, or nil if it did not happen, which can happen if TARGETS didn't contain anything that the OffiX protocol can represent. X and Y are the root window coordinates of the drop. TARGETS is -the list of targets `XdndSelection' can be converted to." - (if-let* ((data (x-dnd-convert-to-offix targets)) +the list of targets CONTENTS can be converted to, and CONTENTS is +the local selection data to drop onto the target window. + +FRAME is the frame that will act as a source window for the +drop." + (if-let* ((data (x-dnd-convert-to-offix targets contents)) (type-id (car (rassq (car data) x-dnd-offix-id-to-name))) (source-id (string-to-number @@ -1074,18 +1087,20 @@ the list of targets `XdndSelection' can be converted to." frame "_DND_PROTOCOL" 32 message-data)))) -(defun x-dnd-handle-unsupported-drop (targets x y action window-id frame _time) +(defun x-dnd-handle-unsupported-drop (targets x y action window-id frame _time local-selection-data) "Return non-nil if the drop described by TARGETS and ACTION should not proceed. X and Y are the root window coordinates of the drop. FRAME is the frame the drop originated on. -WINDOW-ID is the X window the drop should happen to." +WINDOW-ID is the X window the drop should happen to. +LOCAL-SELECTION-DATA is the local selection data of the drop." (not (and (or (eq action 'XdndActionCopy) (eq action 'XdndActionMove)) - (not (and x-dnd-use-offix-drop + (not (and x-dnd-use-offix-drop local-selection-data (or (not (eq x-dnd-use-offix-drop 'files)) (member "FILE_NAME" targets)) (x-dnd-do-offix-drop targets x - y frame window-id))) + y frame window-id + local-selection-data))) (or (member "STRING" targets) (member "UTF8_STRING" targets) diff --git a/src/keyboard.c b/src/keyboard.c index e5708c06d9..8b8d348c41 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4056,12 +4056,13 @@ kbd_buffer_get_event (KBOARD **kbp, if (!NILP (Vx_dnd_unsupported_drop_function)) { - if (!NILP (call7 (Vx_dnd_unsupported_drop_function, + if (!NILP (call8 (Vx_dnd_unsupported_drop_function, XCAR (XCDR (event->ie.arg)), event->ie.x, event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))), make_uint (event->ie.code), event->ie.frame_or_window, - make_int (event->ie.timestamp)))) + make_int (event->ie.timestamp), + Fcopy_sequence (XCAR (event->ie.arg))))) break; } diff --git a/src/xselect.c b/src/xselect.c index d90916c6b6..a1f590632f 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -307,18 +307,30 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, This function is used both for remote requests (LOCAL_REQUEST is zero) and for local x-get-selection-internal (LOCAL_REQUEST is nonzero). + If LOCAL_VALUE is non-nil, use it as the local copy. Also allow + quitting in that case, and let DPYINFO be NULL. + This calls random Lisp code, and may signal or gc. */ static Lisp_Object x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, - bool local_request, struct x_display_info *dpyinfo) + bool local_request, struct x_display_info *dpyinfo, + Lisp_Object local_value) { - Lisp_Object local_value, tem; + Lisp_Object tem; Lisp_Object handler_fn, value, check; + bool may_quit; + specpdl_ref count; + + may_quit = false; - local_value = LOCAL_SELECTION (selection_symbol, dpyinfo); + if (NILP (local_value)) + local_value = LOCAL_SELECTION (selection_symbol, dpyinfo); + else + may_quit = true; - if (NILP (local_value)) return Qnil; + if (NILP (local_value)) + return Qnil; /* TIMESTAMP is a special case. */ if (EQ (target_type, QTIMESTAMP)) @@ -331,8 +343,10 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, /* Don't allow a quit within the converter. When the user types C-g, he would be surprised if by luck it came during a converter. */ - specpdl_ref count = SPECPDL_INDEX (); - specbind (Qinhibit_quit, Qt); + count = SPECPDL_INDEX (); + + if (!may_quit) + specbind (Qinhibit_quit, Qt); CHECK_SYMBOL (target_type); handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); @@ -804,7 +818,9 @@ x_handle_selection_request (struct selection_input_event *event) target that doesn't support XDND. */ if (SELECTION_EVENT_TIME (event) == pending_dnd_time + 1 || SELECTION_EVENT_TIME (event) == pending_dnd_time + 2) - selection_symbol = QXdndSelection; + /* Always reply with the contents of PRIMARY, since that's where + the selection data is. */ + selection_symbol = QPRIMARY; local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo); @@ -915,7 +931,7 @@ x_convert_selection (Lisp_Object selection_symbol, lisp_selection = x_get_local_selection (selection_symbol, target_symbol, - false, dpyinfo); + false, dpyinfo, Qnil); frame = selection_request_stack; @@ -2131,7 +2147,7 @@ On Nextstep, TIME-STAMP and TERMINAL are unused. */) } val = x_get_local_selection (selection_symbol, target_type, true, - FRAME_DISPLAY_INFO (f)); + FRAME_DISPLAY_INFO (f), Qnil); if (NILP (val) && FRAME_LIVE_P (f)) { @@ -2273,6 +2289,45 @@ On Nextstep, TERMINAL is unused. */) return (owner ? Qt : Qnil); } +DEFUN ("x-get-local-selection", Fx_get_local_selection, Sx_get_local_selection, + 0, 2, 0, + doc: /* Run selection converters for VALUE, and return the result. +TARGET is the selection target that is used to find a suitable +converter. VALUE is a list of 4 values NAME, SELECTION-VALUE, +TIMESTAMP and FRAME. NAME is the name of the selection that will be +passed to selection converters, SELECTION-VALUE is the value of the +selection used by the converter, TIMESTAMP is not meaningful (but must +be a number that fits in an X timestamp), and FRAME is the frame +describing the terminal for which the selection converter will be +run. */) + (Lisp_Object value, Lisp_Object target) +{ + Time time; + Lisp_Object name, timestamp, frame, result; + + CHECK_SYMBOL (target); + name = Fnth (make_fixnum (0), value); + timestamp = Fnth (make_fixnum (2), value); + frame = Fnth (make_fixnum (3), value); + + CHECK_SYMBOL (name); + CONS_TO_INTEGER (timestamp, Time, time); + check_window_system (decode_live_frame (frame)); + + result = x_get_local_selection (name, target, true, + NULL, value); + + if (CONSP (result) && SYMBOLP (XCAR (result))) + { + result = XCDR (result); + + if (CONSP (result) && NILP (XCDR (result))) + result = XCAR (result); + } + + return clean_local_selection_data (result); +} + /* Send clipboard manager a SAVE_TARGETS request with a UTF8_STRING property (https://www.freedesktop.org/wiki/ClipboardManager/). */ @@ -2809,6 +2864,7 @@ syms_of_xselect (void) defsubr (&Sx_get_atom_name); defsubr (&Sx_send_client_message); defsubr (&Sx_register_dnd_atom); + defsubr (&Sx_get_local_selection); reading_selection_reply = Fcons (Qnil, Qnil); staticpro (&reading_selection_reply); diff --git a/src/xterm.c b/src/xterm.c index d7c3bfa7af..7298feb43a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11234,6 +11234,19 @@ x_dnd_delete_action_list (Lisp_Object frame) unblock_input (); } +static void +x_dnd_lose_ownership (Lisp_Object timestamp_and_frame) +{ + struct frame *f; + + f = XFRAME (XCDR (timestamp_and_frame)); + + if (FRAME_LIVE_P (f)) + Fx_disown_selection_internal (QXdndSelection, + XCAR (timestamp_and_frame), + XCDR (timestamp_and_frame)); +} + /* This function is defined far away from the rest of the XDND code so it can utilize `x_any_window_to_frame'. */ @@ -11324,12 +11337,13 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (!NILP (Vx_dnd_unsupported_drop_function)) { - if (!NILP (call7 (Vx_dnd_unsupported_drop_function, + if (!NILP (call8 (Vx_dnd_unsupported_drop_function, XCAR (XCDR (event->ie.arg)), event->ie.x, event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))), make_uint (event->ie.code), event->ie.frame_or_window, - make_int (event->ie.timestamp)))) + make_int (event->ie.timestamp), + Fcopy_sequence (XCAR (event->ie.arg))))) continue; } @@ -11364,12 +11378,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* If local_value is nil, then we lost ownership of XdndSelection. Signal a more informative error than args-out-of-range. */ if (NILP (local_value)) - error ("Lost ownership of XdndSelection"); - - if (CONSP (local_value)) - x_own_selection (QXdndSelection, - Fnth (make_fixnum (1), local_value), frame); - else error ("No local value for XdndSelection"); if (popup_activated ()) @@ -11387,6 +11395,14 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, else x_dnd_selection_timestamp = XFIXNUM (ltimestamp); + /* Release ownership of XdndSelection after this function returns. + VirtualBox uses the owner of XdndSelection to determine whether + or not mouse motion is part of a drag-and-drop operation. */ + + if (!x_dnd_preserve_selection_data) + record_unwind_protect (x_dnd_lose_ownership, + Fcons (ltimestamp, frame)); + x_dnd_motif_operations = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), xaction); @@ -27959,17 +27975,21 @@ mouse position list. */); DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function, doc: /* Function called when trying to drop on an unsupported window. + This function is called whenever the user tries to drop something on a window that does not support either the XDND or Motif protocols for drag-and-drop. It should return a non-nil value if the drop was handled by the function, and nil if it was not. It should accept -several arguments TARGETS, X, Y, ACTION, WINDOW-ID, FRAME and TIME, -where TARGETS is the list of targets that was passed to -`x-begin-drag', WINDOW-ID is the numeric XID of the window that is +several arguments TARGETS, X, Y, ACTION, WINDOW-ID, FRAME, TIME and +LOCAL-SELECTION, where TARGETS is the list of targets that was passed +to `x-begin-drag', WINDOW-ID is the numeric XID of the window that is being dropped on, X and Y are the root window-relative coordinates where the drop happened, ACTION is the action that was passed to `x-begin-drag', FRAME is the frame which initiated the drag-and-drop -operation, and TIME is the X server time when the drop happened. */); +operation, TIME is the X server time when the drop happened, and +LOCAL-SELECTION is the contents of the `XdndSelection' when +`x-begin-drag' was run, which can be passed to +`x-get-local-selection'. */); Vx_dnd_unsupported_drop_function = Qnil; DEFVAR_INT ("x-color-cache-bucket-size", x_color_cache_bucket_size, @@ -27996,4 +28016,11 @@ should return a symbol describing what to return from If the value is nil, or the function returns a value that is not a symbol, a drop on an Emacs frame will be canceled. */); Vx_dnd_native_test_function = Qnil; + + DEFVAR_BOOL ("x-dnd-preserve-selection-data", x_dnd_preserve_selection_data, + doc: /* Preserve selection data after `x-begin-drag' returns. +This lets you inspect the contents of `XdndSelection' after a +drag-and-drop operation, which is useful when writing tests for +drag-and-drop code. */); + x_dnd_preserve_selection_data = false; } diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index aae9c80273..18dd55c206 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -38,6 +38,7 @@ "Alist of selection names to their values.") (defvar x-treat-local-requests-remotely) +(defvar x-dnd-preserve-selection-data) ;; Define some replacements for functions used by the drag-and-drop ;; code on X when running under something else. @@ -152,7 +153,8 @@ This function only tries to handle strings." ;; program with reasonably correct behavior, such as dtpad, gedit, ;; or Mozilla. ;; ASCII Latin-1 UTF-8 - (let ((test-text "hello, everyone! sæl öllsömul! всем привет")) + (let ((test-text "hello, everyone! sæl öllsömul! всем привет") + (x-dnd-preserve-selection-data t)) ;; Verify that dragging works. (should (eq (dnd-begin-text-drag test-text) 'copy)) (should (eq (dnd-begin-text-drag test-text nil 'move) 'move)) @@ -187,7 +189,8 @@ This function only tries to handle strings." (normal-multibyte-file (expand-file-name (make-temp-name "тест-на-перетаскивание") temporary-file-directory)) - (remote-temp-file (dnd-tests-make-temp-name))) + (remote-temp-file (dnd-tests-make-temp-name)) + (x-dnd-preserve-selection-data t)) ;; Touch those files if they don't exist. (unless (file-exists-p normal-temp-file) (write-region "" 0 normal-temp-file)) @@ -273,7 +276,8 @@ This function only tries to handle strings." (expand-file-name (make-temp-name "dnd-test") temporary-file-directory)) (nonexistent-remote-file (dnd-tests-make-temp-name)) - (nonexistent-remote-file-1 (dnd-tests-make-temp-name))) + (nonexistent-remote-file-1 (dnd-tests-make-temp-name)) + (x-dnd-preserve-selection-data t)) ;; Touch those files if they don't exist. (unless (file-exists-p normal-temp-file) (write-region "" 0 normal-temp-file)) commit 9705609c0ef5e426606300da95fed4bec54923fb Author: Lars Ingebrigtsen Date: Tue Jun 28 22:04:30 2022 +0200 Fix typo in previous maintaining.texi change * doc/emacs/maintaining.texi (Looking Up Identifiers): Fix typo. diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 8929f6d5c1..60169d8d8c 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -2223,7 +2223,7 @@ where you were with @kbd{M-,}. @kindex C-M-, @findex xref-go-forward If you previously went back too far with @kbd{M-,}, @kbd{C-M-,} -(@code{xref-go-forward} can be used to go forward again. +(@code{xref-go-forward}) can be used to go forward again. @findex xref-etags-mode Some major modes install @code{xref} support facilities that might commit b10a6fd5bb04675d531578accbd3609e29e8ad51 Author: Juri Linkov Date: Tue Jun 28 20:20:21 2022 +0300 * lisp/isearch.el (isearch-delete-char): Improve fix for bug#52248. When reaching the top of the stack where isearch-other-end is nil, still close unnecessary overlays for the previous position. (isearch-close-unnecessary-overlays): Rename arg BEG for consistency. diff --git a/lisp/isearch.el b/lisp/isearch.el index 0624858993..34c3665bd8 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -2522,11 +2522,12 @@ If no input items have been entered yet, just beep." (if (null (cdr isearch-cmds)) (ding) (isearch-pop-state)) - ;; When going back to the hidden match, reopen it. - (when (and (eq search-invisible 'open) isearch-hide-immediately - isearch-other-end) - (isearch-range-invisible (min (point) isearch-other-end) - (max (point) isearch-other-end))) + ;; When going back to the hidden match, reopen it and close other overlays. + (when (and (eq search-invisible 'open) isearch-hide-immediately) + (if isearch-other-end + (isearch-range-invisible (min (point) isearch-other-end) + (max (point) isearch-other-end)) + (isearch-close-unnecessary-overlays (point) (point)))) (isearch-update)) (defun isearch-del-char (&optional arg) @@ -3756,11 +3757,11 @@ Optional third argument, if t, means if fail just return nil (no error). ;; Verify if the current match is outside of each element of ;; `isearch-opened-overlays', if so close that overlay. -(defun isearch-close-unnecessary-overlays (begin end) +(defun isearch-close-unnecessary-overlays (beg end) (let ((overlays isearch-opened-overlays)) (setq isearch-opened-overlays nil) (dolist (ov overlays) - (if (isearch-intersects-p begin end (overlay-start ov) (overlay-end ov)) + (if (isearch-intersects-p beg end (overlay-start ov) (overlay-end ov)) (push ov isearch-opened-overlays) (let ((fct-temp (overlay-get ov 'isearch-open-invisible-temporary))) (if fct-temp commit 7580f3f4875921b6d88e6ea7ed34c2493af305d1 Author: Visuwesh Date: Tue Jun 28 17:41:32 2022 +0200 trouble.texi (Long Lines): Fix typo. * doc/emacs/trouble.texi (Long Lines): Fix typo (bug#56283). diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi index 5dc9fe0068..f06b93759d 100644 --- a/doc/emacs/trouble.texi +++ b/doc/emacs/trouble.texi @@ -480,7 +480,7 @@ variable. The display of the offending window will then remain outdated, and possibly incomplete, on the screen, but Emacs should otherwise be responsive, and you could then switch to another buffer, or kill the problematic buffer, or turn on @code{so-long-mode} or -@code{sol-long-minor-mode} in that buffer. When the display of a +@code{so-long-minor-mode} in that buffer. When the display of a window is aborted due to this reason, the buffer shown in that window will not have any of its windows redisplayed until the buffer is modified or until you type @kbd{C-l} (@pxref{Recentering}) in one of commit fb0d95984b522687eb10aebbc1b1cef7cca7c5ec Author: Lars Ingebrigtsen Date: Tue Jun 28 15:22:13 2022 +0200 Put the obsoletion earlier in the *Help* buffer * lisp/help-fns.el (help-fns--obsolete): Remove indentation and fill. (help-fns--var-obsolete): Ditto. (describe-function-1): Output the obsoletion info first since it's vital information. (describe-variable): Ditto (bug#56251). diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 364fce4ea6..705f92b37b 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -725,19 +725,22 @@ the C sources, too." ;; Ignore lambda constructs, keyboard macros, etc. (let* ((obsolete (and (symbolp function) (get function 'byte-obsolete-info))) - (use (car obsolete))) + (use (car obsolete)) + (start (point))) (when obsolete - (insert " This " + (insert "This " (if (eq (car-safe (symbol-function function)) 'macro) "macro" "function") " is obsolete") (when (nth 2 obsolete) (insert (format " since %s" (nth 2 obsolete)))) - (insert (cond ((stringp use) (concat ";\n " use)) - (use (format-message ";\n use `%s' instead." use)) + (insert (cond ((stringp use) (concat "; " use)) + (use (format-message "; use `%s' instead." use)) (t ".")) - "\n")))) + "\n") + (fill-region-as-paragraph start (point)) + (ensure-empty-lines)))) (add-hook 'help-fns-describe-function-functions #'help-fns--globalized-minor-mode) @@ -1044,6 +1047,8 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." nil t) (ensure-empty-lines)))) + (help-fns--obsolete function) + (pcase-let* ((`(,real-function ,def ,_aliased ,real-def) (help-fns--analyze-function function)) (doc-raw (condition-case nil @@ -1082,7 +1087,6 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." (set-buffer-file-coding-system 'utf-8))))) ;; Add defaults to `help-fns-describe-function-functions'. -(add-hook 'help-fns-describe-function-functions #'help-fns--obsolete) (add-hook 'help-fns-describe-function-functions #'help-fns--interactive-only) (add-hook 'help-fns-describe-function-functions #'help-fns--parent-mode) (add-hook 'help-fns-describe-function-functions #'help-fns--compiler-macro 100) @@ -1338,6 +1342,7 @@ it is displayed along with the global value." alias 'variable-documentation)))) (with-current-buffer standard-output + (help-fns--var-obsolete variable) (insert (or doc "Not documented as a variable."))) ;; Output the indented administrative bits. @@ -1531,19 +1536,21 @@ variable.\n"))) (princ watchpoints) (terpri)))) -(add-hook 'help-fns-describe-variable-functions #'help-fns--var-obsolete) (defun help-fns--var-obsolete (variable) (let* ((obsolete (get variable 'byte-obsolete-variable)) - (use (car obsolete))) + (use (car obsolete)) + (start (point))) (when obsolete - (princ " This variable is obsolete") + (insert "This variable is obsolete") (if (nth 2 obsolete) - (princ (format " since %s" (nth 2 obsolete)))) - (princ (cond ((stringp use) (concat ";\n " use)) - (use (format-message ";\n use `%s' instead." - (car obsolete))) - (t "."))) - (terpri)))) + (insert (format " since %s" (nth 2 obsolete)))) + (insert (cond ((stringp use) (concat "; " use)) + (use (format-message "; use `%s' instead." + (car obsolete))) + (t ".")) + "\n") + (fill-region-as-paragraph start (point)) + (ensure-empty-lines)))) (add-hook 'help-fns-describe-variable-functions #'help-fns--var-alias) (defun help-fns--var-alias (variable) commit c23a49d256771739d78eca1f371f69c46979d90c Author: Lars Ingebrigtsen Date: Tue Jun 28 14:58:20 2022 +0200 Improve sxhash-equal documentation * doc/lispref/hash.texi (Defining Hash): Explain more about what sxhash-equal is for and what the caveats are. * src/fns.c (Fsxhash_eql, Fsxhash_equal): Clarify doc string. diff --git a/doc/lispref/hash.texi b/doc/lispref/hash.texi index a566d89824..6264945521 100644 --- a/doc/lispref/hash.texi +++ b/doc/lispref/hash.texi @@ -289,9 +289,13 @@ If two objects @var{obj1} and @var{obj2} are @code{equal}, then are the same integer. If the two objects are not @code{equal}, the values returned by -@code{sxhash-equal} are usually different, but not always; once in a -rare while, by luck, you will encounter two distinct-looking objects -that give the same result from @code{sxhash-equal}. +@code{sxhash-equal} are usually different, but not always. +@code{sxhash-equal} is designed to be reasonably fast (since it's used +for indexing hash tables) so it won't recurse deeply into nested +structures. In addition; once in a rare while, by luck, you will +encounter two distinct-looking simple objects that give the same +result from @code{sxhash-equal}. So you can't, in general, use +@code{sxhash-equal} to check whether an object has changed. @b{Common Lisp note:} In Common Lisp a similar function is called @code{sxhash}. Emacs provides this name as a compatibility alias for diff --git a/src/fns.c b/src/fns.c index 6be6b6d616..7553a09446 100644 --- a/src/fns.c +++ b/src/fns.c @@ -4923,7 +4923,8 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */) DEFUN ("sxhash-eql", Fsxhash_eql, Ssxhash_eql, 1, 1, 0, doc: /* Return an integer hash code for OBJ suitable for `eql'. -If (eql A B), then (= (sxhash-eql A) (sxhash-eql B)). +If (eql A B), then (= (sxhash-eql A) (sxhash-eql B)), but the opposite +isn't necessarily true. Hash codes are not guaranteed to be preserved across Emacs sessions. */) (Lisp_Object obj) @@ -4933,7 +4934,8 @@ Hash codes are not guaranteed to be preserved across Emacs sessions. */) DEFUN ("sxhash-equal", Fsxhash_equal, Ssxhash_equal, 1, 1, 0, doc: /* Return an integer hash code for OBJ suitable for `equal'. -If (equal A B), then (= (sxhash-equal A) (sxhash-equal B)). +If (equal A B), then (= (sxhash-equal A) (sxhash-equal B)), but the +opposite isn't necessarily true. Hash codes are not guaranteed to be preserved across Emacs sessions. */) (Lisp_Object obj) commit 98c9105f059085da8ebbbf4d50fc43abcb7a2d32 Author: Lars Ingebrigtsen Date: Tue Jun 28 14:41:32 2022 +0200 Allow using define-short-documentation-group without loading shortdoc * lisp/emacs-lisp/shortdoc.el (define-short-documentation-group): Allow using without loading shortdoc.el (bug#56260). diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index d0f0635887..c82aa3365c 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -41,10 +41,12 @@ '((t :inherit variable-pitch)) "Face used for a section.") -(defvar shortdoc--groups nil) +;;;###autoload +(progn + (defvar shortdoc--groups nil) -(defmacro define-short-documentation-group (group &rest functions) - "Add GROUP to the list of defined documentation groups. + (defmacro define-short-documentation-group (group &rest functions) + "Add GROUP to the list of defined documentation groups. FUNCTIONS is a list of elements on the form: (FUNC @@ -88,8 +90,7 @@ string will be `read' and evaluated. (FUNC :no-eval EXAMPLE-FORM - :result RESULT-FORM ;Use `:result-string' if value is in string form - ) + :result RESULT-FORM) ;Use `:result-string' if value is in string form Using `:no-value' is the same as using `:no-eval'. @@ -102,17 +103,16 @@ execution of the documented form depends on some conditions. (FUNC :no-eval EXAMPLE-FORM - :eg-result RESULT-FORM ;Use `:eg-result-string' if value is in string form - ) + :eg-result RESULT-FORM) ;Use `:eg-result-string' if value is in string form A FUNC form can have any number of `:no-eval' (or `:no-value'), `:no-eval*', `:result', `:result-string', `:eg-result' and `:eg-result-string' properties." - (declare (indent defun)) - `(progn - (setq shortdoc--groups (delq (assq ',group shortdoc--groups) - shortdoc--groups)) - (push (cons ',group ',functions) shortdoc--groups))) + (declare (indent defun)) + `(progn + (setq shortdoc--groups (delq (assq ',group shortdoc--groups) + shortdoc--groups)) + (push (cons ',group ',functions) shortdoc--groups)))) (define-short-documentation-group alist "Alist Basics" commit 2eba8cad204e4b663809235941d91671d2d8e6da Author: Michael Albinus Date: Tue Jun 28 14:41:45 2022 +0200 Tramp shall not trap unrelated D-Bus errors * lisp/net/tramp-gvfs.el (tramp-gvfs-dbus-event-vector): Declare. (tramp-gvfs-file-name-handler): Let-bind it. (tramp-gvfs-dbus-event-vector): Fix docstring. (tramp-gvfs-maybe-open-connection): Do not set it globally. (Bug#56162) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 3a5041c491..4adc35bcb6 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -841,6 +841,8 @@ Operations not mentioned here will be handled by the default Emacs primitives.") (tramp-file-name-method (tramp-dissect-file-name filename)))) (and (stringp method) (member method tramp-gvfs-methods))))) +(defvar tramp-gvfs-dbus-event-vector) + ;;;###tramp-autoload (defun tramp-gvfs-file-name-handler (operation &rest args) "Invoke the GVFS related OPERATION and ARGS. @@ -848,7 +850,11 @@ First arg specifies the OPERATION, second arg is a list of arguments to pass to the OPERATION." (unless tramp-gvfs-enabled (tramp-user-error nil "Package `tramp-gvfs' not supported")) - (if-let ((fn (assoc operation tramp-gvfs-file-name-handler-alist))) + (if-let ((filename (apply #'tramp-file-name-for-operation operation args)) + (tramp-gvfs-dbus-event-vector + (and (tramp-tramp-file-p filename) + (tramp-dissect-file-name filename))) + (fn (assoc operation tramp-gvfs-file-name-handler-alist))) (save-match-data (apply (cdr fn) args)) (tramp-run-real-handler operation args))) @@ -942,7 +948,8 @@ The call will be traced by Tramp with trace level 6." (defvar tramp-gvfs-dbus-event-vector nil "Current Tramp file name to be used, as vector. It is needed when D-Bus signals or errors arrive, because there -is no information where to trace the message.") +is no information where to trace the message. +Globally, the value shall always be nil; it is bound where needed.") (defun tramp-gvfs-dbus-event-error (event err) "Called when a D-Bus error message arrives, see `dbus-event-error-functions'." @@ -2121,10 +2128,6 @@ connection if a previous connection has died for some reason." (unless (tramp-connectable-p vec) (throw 'non-essential 'non-essential)) - ;; We set the file name, in case there are incoming D-Bus signals or - ;; D-Bus errors. - (setq tramp-gvfs-dbus-event-vector vec) - ;; For password handling, we need a process bound to the connection ;; buffer. Therefore, we create a dummy process. Maybe there is a ;; better solution? commit a8e72eb0e26b6671df4ef8585da38e675b15745f Author: Michael Albinus Date: Tue Jun 28 14:40:52 2022 +0200 ; * etc/NEWS: Fix file name quotations. diff --git a/etc/NEWS b/etc/NEWS index 962cfe58d1..722b0da696 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -20,19 +20,19 @@ with a prefix argument or by typing 'C-u C-h C-n'. ** To install the Emacs binary in a non-standard directory, use '--bindir='. If you install Emacs in a way that places the Emacs executable file in -a directory other than ${prefix}/bin, you will now need to specify +a directory other than "${prefix}/bin", you will now need to specify that at configure time, if you build Emacs with native-compilation support. To this end, add the '--bindir=DIRECTORY' switch to the command line of the 'configure' script, where DIRECTORY is the -directory in which you will install the executable file 'emacs'. This -is required even if you place a symlink under ${prefix}/bin that +directory in which you will install the executable file "emacs". This +is required even if you place a symlink under "${prefix}/bin" that points to the real executable file in some other DIRECTORY. It is no longer enough to specify 'bindir=DIRECTORY' on the command line of the "make install" command. The reason for this new requirement is that Emacs needs to locate at -startup the directory with its '*.eln' natively-compiled files for the +startup the directory with its "*.eln" natively-compiled files for the preloaded Lisp packages, and the relative name of that directory needs therefore to be recorded in the executable as part of the build. commit 1dfd8a10af953cf3f4ad6a52800991eb3c53a312 Merge: 9151cc9386 55c5def19b Author: Eli Zaretskii Date: Tue Jun 28 15:38:39 2022 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 9151cc9386c0beec48f6be9e4fe44dd60a67ee08 Author: Eli Zaretskii Date: Tue Jun 28 15:37:55 2022 +0300 ; Fix documentation of 'rename-visited-file' * etc/NEWS: Move to proper place and mark as documented. * doc/emacs/files.texi (Save Commands): Fix typo. diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 2296bacada..fa02d264f9 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -422,7 +422,7 @@ Save the current buffer with a specified file name (@code{write-file}). Change the file name under which the current buffer will be saved. @item M-x rename-visited-file The same as @kbd{M-x set-visited-file-name}, but also rename the file -the buffer if visiting (if any). +the buffer is visiting (if any). @end table @kindex C-x C-s diff --git a/etc/NEWS b/etc/NEWS index c7e0d03d6e..add7784ade 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -350,12 +350,13 @@ This should be a regexp or a list of regexps; buffers whose names match those regexps will be ignored by 'switch-to-prev-buffer' and 'switch-to-next-buffer'. -** Menus - ++++ ** New command 'rename-visited-file'. This command renames the file visited by the current buffer by moving it to a new location, and also makes the buffer visit this new file. +** Menus + --- *** The entries following the buffers in the "Buffers" menu can now be altered. Change the 'menu-bar-buffers-menu-command-entries' variable to alter commit 55c5def19b760ea20a110c0443b301ba8a90d7cd Author: Lars Ingebrigtsen Date: Tue Jun 28 14:33:23 2022 +0200 Clarify Looking Up Identifiers in the manual * doc/emacs/maintaining.texi (Looking Up Identifiers): Clarify the text about C-M-, (bug#56261). diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index e5b3664a4c..8929f6d5c1 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -2222,8 +2222,8 @@ where you were with @kbd{M-,}. @kindex C-M-, @findex xref-go-forward - Go forward to a place from where you previously went back using @kbd{M-,}. -This is useful if you find that you went back too far. + If you previously went back too far with @kbd{M-,}, @kbd{C-M-,} +(@code{xref-go-forward} can be used to go forward again. @findex xref-etags-mode Some major modes install @code{xref} support facilities that might commit 772b189143453745a8e014e21d4b6b78f855bba3 Author: Zachary Kanfer Date: Tue Jun 28 14:13:58 2022 +0200 Add new command `rename-visited-file' * doc/emacs/files.texi (Save Commands): Document it. * lisp/files.el (rename-visited-file): New command (bug#56229). diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 5c80cfe190..2296bacada 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -420,6 +420,9 @@ With prefix argument (@kbd{C-u}), mark the current buffer as changed. Save the current buffer with a specified file name (@code{write-file}). @item M-x set-visited-file-name Change the file name under which the current buffer will be saved. +@item M-x rename-visited-file +The same as @kbd{M-x set-visited-file-name}, but also rename the file +the buffer if visiting (if any). @end table @kindex C-x C-s diff --git a/etc/NEWS b/etc/NEWS index 831486bb79..c7e0d03d6e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -352,6 +352,10 @@ match those regexps will be ignored by 'switch-to-prev-buffer' and ** Menus +** New command 'rename-visited-file'. +This command renames the file visited by the current buffer by moving +it to a new location, and also makes the buffer visit this new file. + --- *** The entries following the buffers in the "Buffers" menu can now be altered. Change the 'menu-bar-buffers-menu-command-entries' variable to alter diff --git a/lisp/files.el b/lisp/files.el index cc38f4e921..1295c24c93 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -4824,6 +4824,26 @@ Interactively, confirmation is required unless you supply a prefix argument." ;; It's likely that the VC status at the new location is different from ;; the one at the old location. (vc-refresh-state))) + +(defun rename-visited-file (new-location) + "Rename the file visited by the current buffer to NEW-LOCATION. +This command also sets the visited file name. If the buffer +isn't visiting any file, that's all it does. + +Interactively, this prompts for NEW-LOCATION." + (interactive + (list (if buffer-file-name + (read-file-name "Rename visited file to: ") + (read-file-name "Set visited file name: " + default-directory + (expand-file-name + (file-name-nondirectory (buffer-name)) + default-directory))))) + (when (and buffer-file-name + (file-exists-p buffer-file-name)) + (rename-file buffer-file-name new-location)) + (set-visited-file-name new-location nil t)) + (defun file-extended-attributes (filename) "Return an alist of extended attributes of file FILENAME. commit 0b62ad2f3a57845c664965658da82ffc93cb6e26 Author: Jim Meyering Date: Sun Jun 26 21:26:01 2022 -0700 Fix configure.ac quoting of AC_CHECK_LIB's 2nd arg Running an autoconf-head-generated configure, would fail like this: /emacs/configure: line 18002: syntax error near unexpected token `;;' /emacs/configure: line 18002: ` ;;' That is due to under-quoting of AC_CHECK_LIB's second argument, which led to the comma in an embedded string being interpreted as paramater-delimiting. * configure.ac: Quote the second arg of each AC_CHECK_LIB invocation. (Bug#56272) Copyright-paperwork-exempt: yes diff --git a/configure.ac b/configure.ac index c91b7de322..17f86627a7 100644 --- a/configure.ac +++ b/configure.ac @@ -3622,7 +3622,7 @@ if test "${HAVE_X11}" = "yes"; then CFLAGS="$CFLAGS $XFT_CFLAGS" LIBS="$XFT_LIBS $LIBS" AC_CHECK_HEADER(X11/Xft/Xft.h, - AC_CHECK_LIB(Xft, XftFontOpen, HAVE_XFT=yes, , $XFT_LIBS) , , + [AC_CHECK_LIB(Xft, XftFontOpen, HAVE_XFT=yes, , $XFT_LIBS)] , , [[#include ]]) if test "${HAVE_XFT}" = "yes"; then @@ -3818,7 +3818,7 @@ AC_SUBST(M17N_FLT_LIBS) XCB_LIBS= if test "${HAVE_X11}" = "yes"; then AC_CHECK_HEADER(X11/Xlib-xcb.h, - AC_CHECK_LIB(xcb, xcb_translate_coordinates, HAVE_XCB=yes)) + [AC_CHECK_LIB(xcb, xcb_translate_coordinates, HAVE_XCB=yes)]) if test "${HAVE_XCB}" = "yes"; then AC_CHECK_LIB(X11-xcb, XGetXCBConnection, HAVE_X11_XCB=yes) if test "${HAVE_X11_XCB}" = "yes"; then @@ -4597,7 +4597,7 @@ XSYNC_CFLAGS= HAVE_XSYNC=no if test "${HAVE_X11}" = "yes"; then AC_CHECK_HEADER(X11/extensions/sync.h, - AC_CHECK_LIB(Xext, XSyncQueryExtension, HAVE_XSYNC=yes), + [AC_CHECK_LIB(Xext, XSyncQueryExtension, HAVE_XSYNC=yes)], [], [#include ]) if test "${HAVE_XSYNC}" = "yes"; then commit f5293b336478ca48052b6a4b1538de45446317f4 Author: Po Lu Date: Tue Jun 28 18:25:50 2022 +0800 Adjust x-clipboard-yank for recent selection ownership changes * lisp/term/x-win.el (x-clipboard-yank): Don't own CLIPBOARD inside kill-new. diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 32675a07b1..7c88c85cef 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1182,8 +1182,12 @@ as returned by `x-server-vendor'." (interactive "*") (let ((clipboard-text (gui--selection-value-internal 'CLIPBOARD)) (select-enable-clipboard t)) - (if (and clipboard-text (> (length clipboard-text) 0)) - (kill-new clipboard-text)) + (when (and clipboard-text (> (length clipboard-text) 0)) + ;; Avoid asserting ownership of CLIPBOARD, which will cause + ;; `gui-selection-value' to return nil in the future. + ;; (bug#56273) + (let ((select-enable-clipboard nil)) + (kill-new clipboard-text))) (yank))) (declare-function accelerate-menu "xmenu.c" (&optional frame) t) commit baec3c4974e3a3f31dc4c3cb58db780746bbe691 Author: Po Lu Date: Tue Jun 28 15:31:09 2022 +0800 Clean up Fx_begin_drag * src/xfns.c (Fx_begin_drag): Use FOR_EACH_TAIL instead of iterating manually. diff --git a/src/xfns.c b/src/xfns.c index 1372809da6..36920035d7 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6910,10 +6910,9 @@ that mouse buttons are being held down, such as immediately after a original = targets; targets_arg = targets; - for (; CONSP (targets); targets = XCDR (targets)) + FOR_EACH_TAIL (targets) { CHECK_STRING (XCAR (targets)); - maybe_quit (); if (ntargets < 2048) { @@ -6943,9 +6942,8 @@ that mouse buttons are being held down, such as immediately after a original = action; CHECK_LIST (action); - for (; CONSP (action); action = XCDR (action)) + FOR_EACH_TAIL (action) { - maybe_quit (); tem = XCAR (action); CHECK_CONS (tem); t1 = XCAR (tem); commit 748e6c1e80e7c34cf255e1e8e030dd5414afb5da Author: Po Lu Date: Tue Jun 28 05:43:13 2022 +0000 Automatically detect cyclic lists in some Haiku functions * src/haikuselect.c (haiku_lisp_to_message): Use FOR_EACH_TAIL to iterate over message data. diff --git a/src/haikuselect.c b/src/haikuselect.c index 96223902f8..fe76e09810 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -441,10 +441,10 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) int rc; specpdl_ref ref; - CHECK_LIST (obj); - for (tem = obj; CONSP (tem); tem = XCDR (tem)) + tem = obj; + + FOR_EACH_TAIL (tem) { - maybe_quit (); t1 = XCAR (tem); CHECK_CONS (t1); @@ -490,9 +490,9 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) signal_error ("Unknown data type", type_sym); CHECK_LIST (t1); - for (t2 = XCDR (t1); CONSP (t2); t2 = XCDR (t2)) + t2 = XCDR (t1); + FOR_EACH_TAIL (t2) { - maybe_quit (); data = XCAR (t2); if (FIXNUMP (type_sym) || BIGNUMP (type_sym)) commit 091b22cb123c437324bd64c5b7d9d2596da4264c Author: Basil L. Contovounesios Date: Sat May 21 23:11:33 2022 +0300 Fix hash table function return values in manual * doc/lispref/hash.texi (Hash Access): Reconcile documented return values of puthash and clrhash with their respective docstrings (bug#55562). diff --git a/doc/lispref/hash.texi b/doc/lispref/hash.texi index a566d89824..34eda45b23 100644 --- a/doc/lispref/hash.texi +++ b/doc/lispref/hash.texi @@ -203,7 +203,8 @@ association in @var{table}. @defun puthash key value table This function enters an association for @var{key} in @var{table}, with value @var{value}. If @var{key} already has an association in -@var{table}, @var{value} replaces the old associated value. +@var{table}, @var{value} replaces the old associated value. This +function always returns @var{value}. @end defun @defun remhash key table @@ -219,10 +220,7 @@ otherwise. In Emacs Lisp, @code{remhash} always returns @code{nil}. @defun clrhash table This function removes all the associations from hash table @var{table}, so that it becomes empty. This is also called @dfn{clearing} the hash -table. - -@b{Common Lisp note:} In Common Lisp, @code{clrhash} returns the empty -@var{table}. In Emacs Lisp, it returns @code{nil}. +table. @code{clrhash} returns the empty @var{table}. @end defun @defun maphash function table commit b78508696b1997ba0eef4288219071994c88e575 Merge: 9c268510cf a280df4cab Author: Stefan Kangas Date: Tue Jun 28 06:30:31 2022 +0200 Merge from origin/emacs-28 a280df4cab ; Mention in NEWS the need to use --bindir # Conflicts: # etc/NEWS commit 9c268510cf4ce02e46d3884215a4d016914d35f0 Author: Po Lu Date: Tue Jun 28 09:42:40 2022 +0800 Fix handling "C-S-u" and such when using XKB * src/xterm.c (handle_one_xevent): Don't rely on XKB for consumed modifiers. diff --git a/src/xterm.c b/src/xterm.c index 3a64297258..d7c3bfa7af 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -17635,7 +17635,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, &consumed, &keysym)) goto done_keysym; - modifiers &= ~consumed; overflow = 0; nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym, @@ -20791,10 +20790,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #endif -#ifdef HAVE_XKB - mods_rtrn = 0; -#endif - x_display_set_last_user_time (dpyinfo, xev->time, xev->send_event); ignore_next_mouse_click_timeout = 0; @@ -21029,12 +21024,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } -#ifndef HAVE_XKB inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state); -#else - inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, - state & ~mods_rtrn); -#endif #ifdef XK_F1 if (x_dnd_in_progress && keysym == XK_F1) commit dea5c528bd8263b57a8619eac3e66e04f9ab31a4 Author: Po Lu Date: Tue Jun 28 09:40:22 2022 +0800 Always use XKB to translate keysyms when no input method is available * src/xterm.c (handle_one_xevent) [HAVE_XKB]: Also use XKB to handle core KeyPress events. diff --git a/src/xterm.c b/src/xterm.c index 98ceae6ac1..3a64297258 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -17622,14 +17622,50 @@ handle_one_xevent (struct x_display_info *dpyinfo, emacs_abort (); } else - nbytes = XLookupString (&xkey, (char *) copy_bufptr, - copy_bufsiz, &keysym, - &compose_status); -#else - nbytes = XLookupString (&xkey, (char *) copy_bufptr, - copy_bufsiz, &keysym, - &compose_status); #endif + { +#ifdef HAVE_XKB + int overflow; + unsigned int consumed; + + if (dpyinfo->xkb_desc) + { + if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, + xkey.keycode, xkey.state, + &consumed, &keysym)) + goto done_keysym; + + modifiers &= ~consumed; + overflow = 0; + + nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym, + xkey.state & ~consumed, + (char *) copy_bufptr, + copy_bufsiz, &overflow); + + if (overflow) + { + copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow) + * sizeof *copy_bufptr); + overflow = 0; + nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym, + xkey.state & ~consumed, + (char *) copy_bufptr, + copy_bufsiz, &overflow); + + if (overflow) + nbytes = 0; + } + + if (nbytes) + coding = Qnil; + } + else +#endif + nbytes = XLookupString (&xkey, (char *) copy_bufptr, + copy_bufsiz, &keysym, + &compose_status); + } #ifdef XK_F1 if (x_dnd_in_progress && keysym == XK_F1) @@ -20755,6 +20791,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #endif +#ifdef HAVE_XKB + mods_rtrn = 0; +#endif + x_display_set_last_user_time (dpyinfo, xev->time, xev->send_event); ignore_next_mouse_click_timeout = 0; @@ -20911,7 +20951,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif XSETFRAME (inev.ie.frame_or_window, f); - inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state); inev.ie.timestamp = xev->time; #ifdef HAVE_X_I18N @@ -20990,6 +21029,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } +#ifndef HAVE_XKB + inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state); +#else + inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, + state & ~mods_rtrn); +#endif + #ifdef XK_F1 if (x_dnd_in_progress && keysym == XK_F1) { commit 7565dfd268671c8d5388e8b9fe823367c206c131 Author: Basil L. Contovounesios Date: Mon Jun 27 23:20:55 2022 +0300 * lisp/subr.el (plistp): Simplify (bug#47427). diff --git a/lisp/subr.el b/lisp/subr.el index 69cff23cba..4e4eac32d9 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4008,9 +4008,8 @@ Otherwise, return nil." (defun plistp (object) "Non-nil if and only if OBJECT is a valid plist." - (and (listp object) - (proper-list-p object) - (zerop (mod (length object) 2)))) + (let ((len (proper-list-p object))) + (and len (zerop (% len 2))))) (defun macrop (object) "Non-nil if and only if OBJECT is a macro." commit 05fe0faed4f281c113aecb6524a14324a856671f Author: Paul Eggert Date: Mon Jun 27 08:29:32 2022 -0500 "make clean" etc. problem now fixed on Solaris. diff --git a/etc/PROBLEMS b/etc/PROBLEMS index c924f5f394..14c1df25b1 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -2548,12 +2548,6 @@ Emacs so that it isn't compiled with '-O5'. We list bugs in current versions here. See also the section on legacy systems. -*** On Solaris 10, 'make clean' and 'make check' do not work. -The Emacs build procedure uses ’find ... -path ...', which Solaris 10 -'find' does not support. You can work around the problem by -installing GNU 'find' in your PATH. This problem should be fixed in -Emacs 29. - *** On Solaris 10 sparc, Emacs crashes during the build while saving state. This was observed for Emacs 28.1 on Solaris 10 32-bit sparc, with Oracle Developer Studio 12.6 (Sun C 5.15). The failure was intermittent, commit 1e58dc46b89da4cdb537c6966e6cba8f6df4a106 Author: Gerd Möllmann Date: Fri Jun 24 10:44:17 2022 +0200 Prevent regexp cache entries from being GC'ed in more cases * src/search.c (string_match_1, fast_string_match_internal) (fast_c_string_match_ignore_case): Use freeze_pattern. (Bug#56108) diff --git a/src/search.c b/src/search.c index 816a757c18..9d6bd074e1 100644 --- a/src/search.c +++ b/src/search.c @@ -370,7 +370,6 @@ string_match_1 (Lisp_Object regexp, Lisp_Object string, Lisp_Object start, bool posix, bool modify_data) { ptrdiff_t val; - struct re_pattern_buffer *bufp; EMACS_INT pos; ptrdiff_t pos_byte, i; bool modify_match_data = NILP (Vinhibit_changing_match_data) && modify_data; @@ -401,17 +400,22 @@ string_match_1 (Lisp_Object regexp, Lisp_Object string, Lisp_Object start, set_char_table_extras (BVAR (current_buffer, case_canon_table), 2, BVAR (current_buffer, case_eqv_table)); - bufp = &compile_pattern (regexp, - (modify_match_data ? &search_regs : NULL), - (!NILP (BVAR (current_buffer, case_fold_search)) - ? BVAR (current_buffer, case_canon_table) : Qnil), - posix, - STRING_MULTIBYTE (string))->buf; + specpdl_ref count = SPECPDL_INDEX (); + struct regexp_cache *cache_entry + = compile_pattern (regexp, + modify_match_data ? &search_regs : NULL, + (!NILP (BVAR (current_buffer, case_fold_search)) + ? BVAR (current_buffer, case_canon_table) + : Qnil), + posix, + STRING_MULTIBYTE (string)); + freeze_pattern (cache_entry); re_match_object = string; - val = re_search (bufp, SSDATA (string), + val = re_search (&cache_entry->buf, SSDATA (string), SBYTES (string), pos_byte, SBYTES (string) - pos_byte, (modify_match_data ? &search_regs : NULL)); + unbind_to (count, Qnil); /* Set last_thing_searched only when match data is changed. */ if (modify_match_data) @@ -480,15 +484,15 @@ ptrdiff_t fast_string_match_internal (Lisp_Object regexp, Lisp_Object string, Lisp_Object table) { - ptrdiff_t val; - struct re_pattern_buffer *bufp; - - bufp = &compile_pattern (regexp, 0, table, - 0, STRING_MULTIBYTE (string))->buf; re_match_object = string; - val = re_search (bufp, SSDATA (string), - SBYTES (string), 0, - SBYTES (string), 0); + specpdl_ref count = SPECPDL_INDEX (); + struct regexp_cache *cache_entry + = compile_pattern (regexp, 0, table, 0, STRING_MULTIBYTE (string)); + freeze_pattern (cache_entry); + ptrdiff_t val = re_search (&cache_entry->buf, SSDATA (string), + SBYTES (string), 0, + SBYTES (string), 0); + unbind_to (count, Qnil); return val; } @@ -501,15 +505,14 @@ ptrdiff_t fast_c_string_match_ignore_case (Lisp_Object regexp, const char *string, ptrdiff_t len) { - ptrdiff_t val; - struct re_pattern_buffer *bufp; - regexp = string_make_unibyte (regexp); - bufp = &compile_pattern (regexp, 0, - Vascii_canon_table, 0, - 0)->buf; + specpdl_ref count = SPECPDL_INDEX (); + struct regexp_cache *cache_entry + = compile_pattern (regexp, 0, Vascii_canon_table, 0, 0); + freeze_pattern (cache_entry); re_match_object = Qt; - val = re_search (bufp, string, len, 0, len, 0); + ptrdiff_t val = re_search (&cache_entry->buf, string, len, 0, len, 0); + unbind_to (count, Qnil); return val; } commit a280df4cab8e492123ded9e236c671b275183d53 Author: Eli Zaretskii Date: Mon Jun 27 15:57:36 2022 +0300 ; Mention in NEWS the need to use --bindir * etc/NEWS: Mention the need to use --bindir= at configure time when installing outside of the ${prefix} tree. (Bug#46790) diff --git a/etc/NEWS b/etc/NEWS index 770c96b07b..962cfe58d1 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -18,6 +18,24 @@ with a prefix argument or by typing 'C-u C-h C-n'. * Installation Changes in Emacs 28.2 +** To install the Emacs binary in a non-standard directory, use '--bindir='. +If you install Emacs in a way that places the Emacs executable file in +a directory other than ${prefix}/bin, you will now need to specify +that at configure time, if you build Emacs with native-compilation +support. To this end, add the '--bindir=DIRECTORY' switch to the +command line of the 'configure' script, where DIRECTORY is the +directory in which you will install the executable file 'emacs'. This +is required even if you place a symlink under ${prefix}/bin that +points to the real executable file in some other DIRECTORY. + +It is no longer enough to specify 'bindir=DIRECTORY' on the command +line of the "make install" command. + +The reason for this new requirement is that Emacs needs to locate at +startup the directory with its '*.eln' natively-compiled files for the +preloaded Lisp packages, and the relative name of that directory needs +therefore to be recorded in the executable as part of the build. + * Startup Changes in Emacs 28.2 commit 0190dff96ac15e48ad57f33d69f5900b3851b9e0 Author: Eli Zaretskii Date: Mon Jun 27 15:32:53 2022 +0300 Fix deletion of composed text * lisp/composite.el (lgstring-glyph-boundary): New function. * lisp/simple.el (delete-forward-char): Call 'lgstring-glyph-boundary' to find where to end the deletion inside an automatic composition. (Bug#56237) diff --git a/lisp/composite.el b/lisp/composite.el index d7ac75708c..6fcf637584 100644 --- a/lisp/composite.el +++ b/lisp/composite.el @@ -474,6 +474,25 @@ after a sequence of character events." (aset gstring (1- len) nil)) gstring) +(defun lgstring-glyph-boundary (gstring startpos endpos) + "Return buffer position at or after ENDPOS where grapheme from GSTRING ends. +STARTPOS is the position where the grapheme cluster starts; it is returned +by `find-composition'." + (let ((nglyphs (lgstring-glyph-len gstring)) + (idx 0) + glyph found) + (while (and (not found) (< idx nglyphs)) + (setq glyph (lgstring-glyph gstring idx)) + (cond + ((or (null glyph) + (= (+ startpos (lglyph-from glyph)) endpos)) + (setq found endpos)) + ((>= (+ startpos (lglyph-to glyph)) endpos) + (setq found (+ startpos (lglyph-to glyph) 1))) + (t + (setq idx (1+ idx))))) + (or found endpos))) + (defun compose-glyph-string (gstring from to) (let ((glyph (lgstring-glyph gstring from)) from-pos to-pos) diff --git a/lisp/simple.el b/lisp/simple.el index 83185c4e1a..ea94727b3a 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1507,12 +1507,22 @@ the actual saved text might be different from what was killed." (while (> n 0) ;; 'find-composition' will return (FROM TO ....) or nil. (setq cmp (find-composition pos)) - (if cmp - ;; TO can be at POS, in which case we want to make - ;; sure we advance at least by 1 character. - (let ((cmp-end (cadr cmp))) - (setq pos (max (1+ pos) cmp-end))) - (setq pos (1+ pos))) + (setq pos + (if cmp + (let ((from (car cmp)) + (to (cadr cmp))) + (cond + ((= (length cmp) 2) ; static composition + to) + ;; TO can be at POS, in which case we want + ;; to make sure we advance at least by 1 + ;; character. + ((<= to pos) + (1+ pos)) + (t + (lgstring-glyph-boundary (nth 2 cmp) + from (1+ pos))))) + (1+ pos))) (setq n (1- n))) (delete-char (- pos start) killflag))) commit f9f41c586a31ad5ba326834c9f4dddfcf78f69e9 Author: Lars Ingebrigtsen Date: Mon Jun 27 12:39:42 2022 +0200 Fix some missed Fplist_put adjustments in src/w32.c * src/w32.c (serial_configure): Adjust some missed Fplist_put renames. diff --git a/src/w32.c b/src/w32.c index c1e4118e9b..e4c6d00766 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10959,7 +10959,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) tem = plist_get (p->childp, QCspeed); CHECK_FIXNUM (tem); dcb.BaudRate = XFIXNUM (tem); - childp2 = Fplist_put (childp2, QCspeed, tem); + childp2 = plist_put (childp2, QCspeed, tem); /* Configure bytesize. */ if (!NILP (plist_member (contact, QCbytesize))) @@ -10973,7 +10973,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) error (":bytesize must be nil (8), 7, or 8"); dcb.ByteSize = XFIXNUM (tem); summary[0] = XFIXNUM (tem) + '0'; - childp2 = Fplist_put (childp2, QCbytesize, tem); + childp2 = plist_put (childp2, QCbytesize, tem); /* Configure parity. */ if (!NILP (plist_member (contact, QCparity))) @@ -11003,7 +11003,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) dcb.Parity = ODDPARITY; dcb.fErrorChar = TRUE; } - childp2 = Fplist_put (childp2, QCparity, tem); + childp2 = plist_put (childp2, QCparity, tem); /* Configure stopbits. */ if (!NILP (plist_member (contact, QCstopbits))) @@ -11020,7 +11020,7 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) dcb.StopBits = ONESTOPBIT; else if (XFIXNUM (tem) == 2) dcb.StopBits = TWOSTOPBITS; - childp2 = Fplist_put (childp2, QCstopbits, tem); + childp2 = plist_put (childp2, QCstopbits, tem); /* Configure flowcontrol. */ if (!NILP (plist_member (contact, QCflowcontrol))) @@ -11053,13 +11053,13 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) dcb.fOutX = TRUE; dcb.fInX = TRUE; } - childp2 = Fplist_put (childp2, QCflowcontrol, tem); + childp2 = plist_put (childp2, QCflowcontrol, tem); /* Activate configuration. */ if (!SetCommState (hnd, &dcb)) error ("SetCommState() failed"); - childp2 = Fplist_put (childp2, QCsummary, build_string (summary)); + childp2 = plist_put (childp2, QCsummary, build_string (summary)); pset_childp (p, childp2); } commit dedd19a2f5cbf16c8ac8a122b0c39ee4e178b9e8 Author: Lars Ingebrigtsen Date: Mon Jun 27 12:36:37 2022 +0200 Add new type predicate plistp * lisp/subr.el (plistp): New type predicate (bug#47427). This referred to in the error message from plist-put: "Debugger entered--Lisp error: (wrong-type-argument plistp (a b c))". diff --git a/lisp/subr.el b/lisp/subr.el index b05471f0c3..69cff23cba 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -4006,6 +4006,12 @@ Otherwise, return nil." (setq object (indirect-function object))) (and (subrp object) (eq (cdr (subr-arity object)) 'unevalled))) +(defun plistp (object) + "Non-nil if and only if OBJECT is a valid plist." + (and (listp object) + (proper-list-p object) + (zerop (mod (length object) 2)))) + (defun macrop (object) "Non-nil if and only if OBJECT is a macro." (let ((def (indirect-function object))) diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index 45dd2d7160..ced2bc5c4e 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -1081,5 +1081,14 @@ final or penultimate step during initialization.")) (dolist (c (list ?a ?b ?α ?β)) (should-not (char-uppercase-p c)))) +(ert-deftest test-plistp () + (should (plistp nil)) + (should-not (plistp 1)) + (should (plistp '(1 2))) + (should-not (plistp '(1 . 2))) + (should (plistp '(1 2 3 4))) + (should-not (plistp '(1 2 3))) + (should-not (plistp '(1 2 3 . 4)))) + (provide 'subr-tests) ;;; subr-tests.el ends here commit abdf35fac66ca51419ec39056df0429790ec9db9 Author: Lars Ingebrigtsen Date: Mon Jun 27 12:26:19 2022 +0200 Adjust plist calls in .m files * src/nsterm.m (mod_of_kind): * src/nsimage.m (ns_load_image): Adjust plist calls in .m files. diff --git a/src/nsimage.m b/src/nsimage.m index 2fff987f9f..9cb5090dd0 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -142,7 +142,7 @@ Updated by Christian Limpach (chris@nice.ch) eassert (valid_image_p (img->spec)); - lisp_index = Fplist_get (XCDR (img->spec), QCindex); + lisp_index = plist_get (XCDR (img->spec), QCindex); index = FIXNUMP (lisp_index) ? XFIXNAT (lisp_index) : 0; if (STRINGP (spec_file)) diff --git a/src/nsterm.m b/src/nsterm.m index ae44f80845..7f232e7292 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -358,7 +358,7 @@ - (unsigned long)unsignedLong return modifier; else { - Lisp_Object val = Fplist_get (modifier, kind); + Lisp_Object val = plist_get (modifier, kind); return SYMBOLP (val) ? val : Qnil; } } commit 513acdc9b4495c5273c55447c47d21534deffc7f Author: Lars Ingebrigtsen Date: Mon Jun 27 12:22:05 2022 +0200 Allow plist-get/plist-put/plist-member to take a comparison function * doc/lispref/lists.texi (Plist Access): Document it. * lisp/filesets.el (filesets-reset-fileset) (filesets-ingroup-cache-get): (filesets-ingroup-cache-put): (filesets-build-menu-now): Don't use lax-plist functions. * lisp/simple.el (lax-plist-put, lax-plist-get): Moved here from fns.c and make obsolete. * lisp/emacs-lisp/byte-opt.el (side-effect-free-fns): Don't mark plist functions as side-effect-free or pure. * lisp/emacs-lisp/comp.el (comp-known-type-specifiers): Adjust type. * lisp/emacs-lisp/shortdoc.el (list): Don't document deprecated functions. * src/xdisp.c (build_desired_tool_bar_string): (display_mode_element): (store_mode_line_string): (display_string): (produce_stretch_glyph): (note_mode_line_or_margin_highlight): (note_mouse_highlight): * src/w32.c (serial_configure): * src/sysdep.c (serial_configure): * src/sound.c (parse_sound): * src/process.c (Fset_process_buffer): (Fset_process_sentinel): (Fprocess_contact): (Fmake_process): (Fmake_pipe_process): (Fset_network_process_option): (Fserial_process_configure): (Fmake_serial_process): (set_network_socket_coding_system): (finish_after_tls_connection): (connect_network_socket): (Fmake_network_process): (server_accept_connection): * src/lread.c (ADDPARAM): (hash_table_from_plist): * src/keyboard.c (make_lispy_position): * src/indent.c (check_display_width): * src/image.c (postprocess_image): * src/gnutls.c (gnutls_verify_boot): (Fgnutls_boot): (gnutls_symmetric): (Fgnutls_hash_mac): (Fgnutls_hash_digest): * src/dired.c (filter): * src/data.c (add_to_function_history): * src/coding.c (Fcoding_system_put): Adjust callers from Fplist_put (etc) to plist_put. * src/fns.c (plist_get): (plist_put): (plist_member): New functions (without optional third parameter) to be used in C code. * src/fns.c (Fplist_get, Fplist_put, Fplist_member): Take an optional predicate parameter (bug#47425). * src/lisp.h: Declare new plist_put, plist_get and plist_member functions. * test/lisp/json-tests.el (test-json-add-to-plist): Use plist-get. * test/src/fns-tests.el (test-cycle-lax-plist-get): (test-cycle-lax-plist-put): (lax-plist-get/odd-number-of-elements): (test-plist): Remove lax-plist tests, since semantics have changed (they no longer error out on cycles). diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index 4a862ab0de..a4f0ba815b 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi @@ -1925,9 +1925,10 @@ and later discarded; this is not possible with a property list. The following functions can be used to manipulate property lists. They all compare property names using @code{eq}. -@defun plist-get plist property +@defun plist-get plist property &optional predicate This returns the value of the @var{property} property stored in the -property list @var{plist}. It accepts a malformed @var{plist} +property list @var{plist}. Comparisons are done with @var{predicate}, +and defaults to @code{eq}. It accepts a malformed @var{plist} argument. If @var{property} is not found in the @var{plist}, it returns @code{nil}. For example, @@ -1943,9 +1944,10 @@ returns @code{nil}. For example, @end example @end defun -@defun plist-put plist property value +@defun plist-put plist property value &optional predicate This stores @var{value} as the value of the @var{property} property in -the property list @var{plist}. It may modify @var{plist} destructively, +the property list @var{plist}. Comparisons are done with @var{predicate}, +and defaults to @code{eq}. It may modify @var{plist} destructively, or it may construct a new list structure without altering the old. The function returns the modified property list, so you can store that back in the place where you got @var{plist}. For example, @@ -1961,19 +1963,20 @@ in the place where you got @var{plist}. For example, @end defun @defun lax-plist-get plist property -Like @code{plist-get} except that it compares properties -using @code{equal} instead of @code{eq}. +This obsolete function is like @code{plist-get} except that it +compares properties using @code{equal} instead of @code{eq}. @end defun @defun lax-plist-put plist property value -Like @code{plist-put} except that it compares properties -using @code{equal} instead of @code{eq}. +This obsolete function is like @code{plist-put} except that it +compares properties using @code{equal} instead of @code{eq}. @end defun -@defun plist-member plist property +@defun plist-member plist property &optional predicate This returns non-@code{nil} if @var{plist} contains the given -@var{property}. Unlike @code{plist-get}, this allows you to distinguish -between a missing property and a property with the value @code{nil}. -The value is actually the tail of @var{plist} whose @code{car} is -@var{property}. +@var{property}. Comparisons are done with @var{predicate}, and +defaults to @code{eq}. Unlike @code{plist-get}, this allows you to +distinguish between a missing property and a property with the value +@code{nil}. The value is actually the tail of @var{plist} whose +@code{car} is @var{property}. @end defun diff --git a/etc/NEWS b/etc/NEWS index 57b72dc846..831486bb79 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2150,6 +2150,10 @@ patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el. * Lisp Changes in Emacs 29.1 ++++ +** 'plist-get', 'plist-put' and 'plist-member' are no longer limited to 'eq'. +These function now take an optional comparison predicate argument. + +++ ** 'read-multiple-choice' can now use long-form answers. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index a8741c53bb..352ac40663 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1361,7 +1361,7 @@ See Info node `(elisp) Integer Basics'." match-beginning match-end member memq memql min minibuffer-selected-window minibuffer-window mod multibyte-char-to-unibyte next-window nth nthcdr number-to-string - parse-colon-path plist-get plist-member + parse-colon-path prefix-numeric-value previous-window prin1-to-string propertize degrees-to-radians radians-to-degrees rassq rassoc read-from-string regexp-opt @@ -1483,7 +1483,7 @@ See Info node `(elisp) Integer Basics'." ;; `assoc' and `assoc-default' are excluded since they are ;; impure if the test function is (consider `string-match'). assq rassq rassoc - plist-get lax-plist-get plist-member + lax-plist-get aref elt base64-decode-string base64-encode-string base64url-encode-string bool-vector-subsetp diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 53803b3818..4ce2ce75e1 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -475,8 +475,8 @@ Useful to hook into pass checkers.") (one-window-p (function (&optional t t) boolean)) (overlayp (function (t) boolean)) (parse-colon-path (function (string) cons)) - (plist-get (function (list t) t)) - (plist-member (function (list t) list)) + (plist-get (function (list t &optional t) t)) + (plist-member (function (list t &optional t) list)) (point (function () integer)) (point-marker (function () marker)) (point-max (function () integer)) diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index a1256ce1b8..d0f0635887 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -691,11 +691,6 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), (plist-put :no-eval (setq plist (plist-put plist 'd 4)) :eq-result (a 1 b 2 c 3 d 4)) - (lax-plist-get - :eval (lax-plist-get '("a" 1 "b" 2 "c" 3) "b")) - (lax-plist-put - :no-eval (setq plist (lax-plist-put plist "d" 4)) - :eq-result '("a" 1 "b" 2 "c" 3 "d" 4)) (plist-member :eval (plist-member '(a 1 b 2 c 3) 'b)) "Data About Lists" diff --git a/lisp/filesets.el b/lisp/filesets.el index 83a914d58c..b97dda3cd6 100644 --- a/lisp/filesets.el +++ b/lisp/filesets.el @@ -208,7 +208,7 @@ COND-FN takes one argument: the current element." (defun filesets-reset-fileset (&optional fileset no-cache) "Reset the cached values for one or all filesets." (setq filesets-submenus (if fileset - (lax-plist-put filesets-submenus fileset nil) + (plist-put filesets-submenus fileset nil #'equal) nil)) (setq filesets-has-changed-flag t) (setq filesets-update-cache-file-flag (or filesets-update-cache-file-flag @@ -1999,7 +1999,7 @@ LOOKUP-NAME is used as lookup name for retrieving fileset specific settings." (defun filesets-ingroup-cache-get (master) "Access to `filesets-ingroup-cache'." - (lax-plist-get filesets-ingroup-cache master)) + (plist-get filesets-ingroup-cache master #'equal)) (defun filesets-ingroup-cache-put (master file) "Access to `filesets-ingroup-cache'." @@ -2008,7 +2008,7 @@ LOOKUP-NAME is used as lookup name for retrieving fileset specific settings." (cons file (filesets-ingroup-cache-get emaster)) nil))) (setq filesets-ingroup-cache - (lax-plist-put filesets-ingroup-cache emaster this)))) + (plist-put filesets-ingroup-cache emaster this #'equal)))) (defun filesets-ingroup-collect-files (fs &optional remdupl-flag master depth) "Helper function for `filesets-ingroup-collect'. Collect file names." @@ -2305,12 +2305,12 @@ bottom up, set `filesets-submenus' to nil, first.)" ((null data)) (let* ((this (car data)) (name (filesets-data-get-name this)) - (cached (lax-plist-get filesets-submenus name)) + (cached (plist-get filesets-submenus name #'equal)) (submenu (or cached (filesets-build-submenu count name this)))) (unless cached (setq filesets-submenus - (lax-plist-put filesets-submenus name submenu))) + (plist-put filesets-submenus name submenu #'equal))) (unless (filesets-entry-get-dormant-flag this) (setq filesets-menu-cache (append filesets-menu-cache (list submenu)))))) diff --git a/lisp/simple.el b/lisp/simple.el index 6d62c02865..83185c4e1a 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -10640,6 +10640,15 @@ If the buffer doesn't exist, create it first." (string-to-number value) (intern (concat "sig" (downcase value)))))) +(defun lax-plist-get (plist prop) + "Extract a value from a property list, comparing with `equal'." + (declare (obsolete plist-get "29.1")) + (plist-get plist prop #'equal)) + +(defun lax-plist-put (plist prop val) + "Change value in PLIST of PROP to VAL, comparing with `equal'." + (declare (obsolete plist-put "29.1")) + (plist-put plist prop val #'equal)) (provide 'simple) diff --git a/src/coding.c b/src/coding.c index 68f3201de8..3fb4f148b1 100644 --- a/src/coding.c +++ b/src/coding.c @@ -11499,7 +11499,7 @@ DEFUN ("coding-system-put", Fcoding_system_put, Scoding_system_put, } ASET (attrs, coding_attr_plist, - Fplist_put (CODING_ATTR_PLIST (attrs), prop, val)); + plist_put (CODING_ATTR_PLIST (attrs), prop, val)); return val; } diff --git a/src/data.c b/src/data.c index d665da04da..1dbec4687b 100644 --- a/src/data.c +++ b/src/data.c @@ -874,7 +874,7 @@ add_to_function_history (Lisp_Object symbol, Lisp_Object olddef) if (NILP (XCDR (tail)) && STRINGP (XCAR (tail))) file = XCAR (tail); - Lisp_Object tem = Fplist_member (past, file); + Lisp_Object tem = plist_member (past, file); if (!NILP (tem)) { /* New def from a file used before. Overwrite the previous record associated with this file. */ diff --git a/src/dired.c b/src/dired.c index e31ad9121c..6bb8c2fcb9 100644 --- a/src/dired.c +++ b/src/dired.c @@ -482,8 +482,8 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, decoded names in order to filter false positives, such as "a" falsely matching "a-ring". */ if (!NILP (file_encoding) - && !NILP (Fplist_get (Fcoding_system_plist (file_encoding), - Qdecomposed_characters))) + && !NILP (plist_get (Fcoding_system_plist (file_encoding), + Qdecomposed_characters))) { check_decoded = true; if (STRING_MULTIBYTE (file)) diff --git a/src/fns.c b/src/fns.c index 5ee8482d00..6be6b6d616 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2276,24 +2276,27 @@ merge_c (Lisp_Object org_l1, Lisp_Object org_l2, bool (*less) (Lisp_Object, Lisp /* This does not check for quits. That is safe since it must terminate. */ -DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0, +DEFUN ("plist-get", Fplist_get, Splist_get, 2, 3, 0, doc: /* Extract a value from a property list. PLIST is a property list, which is a list of the form \(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value corresponding to the given PROP, or nil if PROP is not one of the properties on the list. The comparison -with PROP is done using `eq'. +with PROP is done using PREDICATE, which defaults to `eq'. -This function never signals an error. */) - (Lisp_Object plist, Lisp_Object prop) +This function doesn't signal an error if PLIST is invalid. */) + (Lisp_Object plist, Lisp_Object prop, Lisp_Object predicate) { Lisp_Object tail = plist; + if (NILP (predicate)) + return plist_get (plist, prop); + FOR_EACH_TAIL_SAFE (tail) { if (! CONSP (XCDR (tail))) break; - if (EQ (prop, XCAR (tail))) + if (!NILP (call2 (predicate, prop, XCAR (tail)))) return XCAR (XCDR (tail)); tail = XCDR (tail); } @@ -2301,39 +2304,58 @@ This function never signals an error. */) return Qnil; } +/* Faster version of the above that works with EQ only */ +Lisp_Object +plist_get (Lisp_Object plist, Lisp_Object prop) +{ + Lisp_Object tail = plist; + FOR_EACH_TAIL_SAFE (tail) + { + if (! CONSP (XCDR (tail))) + break; + if (EQ (prop, XCAR (tail))) + return XCAR (XCDR (tail)); + tail = XCDR (tail); + } + return Qnil; +} + DEFUN ("get", Fget, Sget, 2, 2, 0, doc: /* Return the value of SYMBOL's PROPNAME property. This is the last value stored with `(put SYMBOL PROPNAME VALUE)'. */) (Lisp_Object symbol, Lisp_Object propname) { CHECK_SYMBOL (symbol); - Lisp_Object propval = Fplist_get (CDR (Fassq (symbol, Voverriding_plist_environment)), - propname); + Lisp_Object propval = plist_get (CDR (Fassq (symbol, + Voverriding_plist_environment)), + propname); if (!NILP (propval)) return propval; - return Fplist_get (XSYMBOL (symbol)->u.s.plist, propname); + return plist_get (XSYMBOL (symbol)->u.s.plist, propname); } -DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0, +DEFUN ("plist-put", Fplist_put, Splist_put, 3, 4, 0, doc: /* Change value in PLIST of PROP to VAL. PLIST is a property list, which is a list of the form \(PROP1 VALUE1 PROP2 VALUE2 ...). -The comparison with PROP is done using `eq'. +The comparison with PROP is done using PREDICATE, which defaults to `eq'. If PROP is already a property on the list, its value is set to VAL, otherwise the new PROP VAL pair is added. The new plist is returned; use `(setq x (plist-put x prop val))' to be sure to use the new value. The PLIST is modified by side effects. */) - (Lisp_Object plist, Lisp_Object prop, Lisp_Object val) + (Lisp_Object plist, Lisp_Object prop, Lisp_Object val, Lisp_Object predicate) { Lisp_Object prev = Qnil, tail = plist; + if (NILP (predicate)) + return plist_put (plist, prop, val); FOR_EACH_TAIL (tail) { if (! CONSP (XCDR (tail))) break; - if (EQ (prop, XCAR (tail))) + if (!NILP (call2 (predicate, prop, XCAR (tail)))) { Fsetcar (XCDR (tail), val); return plist; @@ -2351,47 +2373,8 @@ The PLIST is modified by side effects. */) return plist; } -DEFUN ("put", Fput, Sput, 3, 3, 0, - doc: /* Store SYMBOL's PROPNAME property with value VALUE. -It can be retrieved with `(get SYMBOL PROPNAME)'. */) - (Lisp_Object symbol, Lisp_Object propname, Lisp_Object value) -{ - CHECK_SYMBOL (symbol); - set_symbol_plist - (symbol, Fplist_put (XSYMBOL (symbol)->u.s.plist, propname, value)); - return value; -} - -DEFUN ("lax-plist-get", Flax_plist_get, Slax_plist_get, 2, 2, 0, - doc: /* Extract a value from a property list, comparing with `equal'. -This function is otherwise like `plist-get', but may signal an error -if PLIST isn't a valid plist. */) - (Lisp_Object plist, Lisp_Object prop) -{ - Lisp_Object tail = plist; - FOR_EACH_TAIL (tail) - { - if (! CONSP (XCDR (tail))) - break; - if (! NILP (Fequal (prop, XCAR (tail)))) - return XCAR (XCDR (tail)); - tail = XCDR (tail); - } - - CHECK_TYPE (NILP (tail), Qplistp, plist); - - return Qnil; -} - -DEFUN ("lax-plist-put", Flax_plist_put, Slax_plist_put, 3, 3, 0, - doc: /* Change value in PLIST of PROP to VAL, comparing with `equal'. -PLIST is a property list, which is a list of the form -\(PROP1 VALUE1 PROP2 VALUE2 ...). PROP and VAL are any objects. -If PROP is already a property on the list, its value is set to VAL, -otherwise the new PROP VAL pair is added. The new plist is returned; -use `(setq x (lax-plist-put x prop val))' to be sure to use the new value. -The PLIST is modified by side effects. */) - (Lisp_Object plist, Lisp_Object prop, Lisp_Object val) +Lisp_Object +plist_put (Lisp_Object plist, Lisp_Object prop, Lisp_Object val) { Lisp_Object prev = Qnil, tail = plist; FOR_EACH_TAIL (tail) @@ -2399,7 +2382,7 @@ The PLIST is modified by side effects. */) if (! CONSP (XCDR (tail))) break; - if (! NILP (Fequal (prop, XCAR (tail)))) + if (EQ (prop, XCAR (tail))) { Fsetcar (XCDR (tail), val); return plist; @@ -2409,12 +2392,24 @@ The PLIST is modified by side effects. */) tail = XCDR (tail); } CHECK_TYPE (NILP (tail), Qplistp, plist); - Lisp_Object newcell = list2 (prop, val); + Lisp_Object newcell + = Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev)))); if (NILP (prev)) return newcell; Fsetcdr (XCDR (prev), newcell); return plist; } + +DEFUN ("put", Fput, Sput, 3, 3, 0, + doc: /* Store SYMBOL's PROPNAME property with value VALUE. +It can be retrieved with `(get SYMBOL PROPNAME)'. */) + (Lisp_Object symbol, Lisp_Object propname, Lisp_Object value) +{ + CHECK_SYMBOL (symbol); + set_symbol_plist + (symbol, plist_put (XSYMBOL (symbol)->u.s.plist, propname, value)); + return value; +} DEFUN ("eql", Feql, Seql, 2, 2, 0, doc: /* Return t if the two args are `eq' or are indistinguishable numbers. @@ -3183,22 +3178,25 @@ FILENAME are suppressed. */) bottleneck of Widget operation. Here is their translation to C, for the sole reason of efficiency. */ -DEFUN ("plist-member", Fplist_member, Splist_member, 2, 2, 0, +DEFUN ("plist-member", Fplist_member, Splist_member, 2, 3, 0, doc: /* Return non-nil if PLIST has the property PROP. PLIST is a property list, which is a list of the form \(PROP1 VALUE1 PROP2 VALUE2 ...). -The comparison with PROP is done using `eq'. +The comparison with PROP is done using PREDICATE, which defaults to +`eq'. Unlike `plist-get', this allows you to distinguish between a missing property and a property with the value nil. The value is actually the tail of PLIST whose car is PROP. */) - (Lisp_Object plist, Lisp_Object prop) + (Lisp_Object plist, Lisp_Object prop, Lisp_Object predicate) { Lisp_Object tail = plist; + if (NILP (predicate)) + predicate = Qeq; FOR_EACH_TAIL (tail) { - if (EQ (XCAR (tail), prop)) + if (!NILP (call2 (predicate, XCAR (tail), prop))) return tail; tail = XCDR (tail); if (! CONSP (tail)) @@ -3208,13 +3206,22 @@ The value is actually the tail of PLIST whose car is PROP. */) return Qnil; } +/* plist_member isn't used much in the Emacs sources, so just provide + a shim so that the function name follows the same pattern as + plist_get/plist_put. */ +Lisp_Object +plist_member (Lisp_Object plist, Lisp_Object prop) +{ + return Fplist_member (plist, prop, Qnil); +} + DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0, doc: /* In WIDGET, set PROPERTY to VALUE. The value can later be retrieved with `widget-get'. */) (Lisp_Object widget, Lisp_Object property, Lisp_Object value) { CHECK_CONS (widget); - XSETCDR (widget, Fplist_put (XCDR (widget), property, value)); + XSETCDR (widget, plist_put (XCDR (widget), property, value)); return value; } @@ -3231,7 +3238,7 @@ later with `widget-put'. */) if (NILP (widget)) return Qnil; CHECK_CONS (widget); - tmp = Fplist_member (XCDR (widget), property); + tmp = plist_member (XCDR (widget), property); if (CONSP (tmp)) { tmp = XCDR (tmp); @@ -6064,8 +6071,6 @@ The same variable also affects the function `read-answer'. */); defsubr (&Sget); defsubr (&Splist_put); defsubr (&Sput); - defsubr (&Slax_plist_get); - defsubr (&Slax_plist_put); defsubr (&Seql); defsubr (&Sequal); defsubr (&Sequal_including_properties); diff --git a/src/gnutls.c b/src/gnutls.c index 0e1e63e157..a0de0238c4 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -1635,10 +1635,10 @@ gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist) char *c_hostname; if (NILP (proplist)) - proplist = Fcdr (Fplist_get (p->childp, QCtls_parameters)); + proplist = Fcdr (plist_get (p->childp, QCtls_parameters)); - verify_error = Fplist_get (proplist, QCverify_error); - hostname = Fplist_get (proplist, QChostname); + verify_error = plist_get (proplist, QCverify_error); + hostname = plist_get (proplist, QChostname); if (EQ (verify_error, Qt)) verify_error_all = true; @@ -1668,7 +1668,7 @@ gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist) p->gnutls_peer_verification = peer_verification; - warnings = Fplist_get (Fgnutls_peer_status (proc), intern (":warnings")); + warnings = plist_get (Fgnutls_peer_status (proc), intern (":warnings")); if (!NILP (warnings)) { for (Lisp_Object tail = warnings; CONSP (tail); tail = XCDR (tail)) @@ -1870,13 +1870,13 @@ one trustfile (usually a CA bundle). */) return Qnil; } - hostname = Fplist_get (proplist, QChostname); - priority_string = Fplist_get (proplist, QCpriority); - trustfiles = Fplist_get (proplist, QCtrustfiles); - keylist = Fplist_get (proplist, QCkeylist); - crlfiles = Fplist_get (proplist, QCcrlfiles); - loglevel = Fplist_get (proplist, QCloglevel); - prime_bits = Fplist_get (proplist, QCmin_prime_bits); + hostname = plist_get (proplist, QChostname); + priority_string = plist_get (proplist, QCpriority); + trustfiles = plist_get (proplist, QCtrustfiles); + keylist = plist_get (proplist, QCkeylist); + crlfiles = plist_get (proplist, QCcrlfiles); + loglevel = plist_get (proplist, QCloglevel); + prime_bits = plist_get (proplist, QCmin_prime_bits); if (!STRINGP (hostname)) { @@ -1929,7 +1929,7 @@ one trustfile (usually a CA bundle). */) check_memory_full (gnutls_certificate_allocate_credentials (&x509_cred)); XPROCESS (proc)->gnutls_x509_cred = x509_cred; - verify_flags = Fplist_get (proplist, QCverify_flags); + verify_flags = plist_get (proplist, QCverify_flags); if (TYPE_RANGED_FIXNUMP (unsigned int, verify_flags)) { gnutls_verify_flags = XFIXNAT (verify_flags); @@ -2109,7 +2109,7 @@ one trustfile (usually a CA bundle). */) } XPROCESS (proc)->gnutls_complete_negotiation_p = - !NILP (Fplist_get (proplist, QCcomplete_negotiation)); + !NILP (plist_get (proplist, QCcomplete_negotiation)); GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_CRED_SET; ret = emacs_gnutls_handshake (XPROCESS (proc)); if (ret < GNUTLS_E_SUCCESS) @@ -2348,7 +2348,7 @@ gnutls_symmetric (bool encrypting, Lisp_Object cipher, if (!NILP (info) && CONSP (info)) { - Lisp_Object v = Fplist_get (info, QCcipher_id); + Lisp_Object v = plist_get (info, QCcipher_id); if (TYPE_RANGED_FIXNUMP (gnutls_cipher_algorithm_t, v)) gca = XFIXNUM (v); } @@ -2625,7 +2625,7 @@ itself. */) if (!NILP (info) && CONSP (info)) { - Lisp_Object v = Fplist_get (info, QCmac_algorithm_id); + Lisp_Object v = plist_get (info, QCmac_algorithm_id); if (TYPE_RANGED_FIXNUMP (gnutls_mac_algorithm_t, v)) gma = XFIXNUM (v); } @@ -2715,7 +2715,7 @@ the number itself. */) if (!NILP (info) && CONSP (info)) { - Lisp_Object v = Fplist_get (info, QCdigest_algorithm_id); + Lisp_Object v = plist_get (info, QCdigest_algorithm_id); if (TYPE_RANGED_FIXNUMP (gnutls_digest_algorithm_t, v)) gda = XFIXNUM (v); } diff --git a/src/image.c b/src/image.c index fcf5e97b0b..c0a7b85cb3 100644 --- a/src/image.c +++ b/src/image.c @@ -2309,8 +2309,8 @@ postprocess_image (struct frame *f, struct image *img) tem = XCDR (conversion); if (CONSP (tem)) image_edge_detection (f, img, - Fplist_get (tem, QCmatrix), - Fplist_get (tem, QCcolor_adjustment)); + plist_get (tem, QCmatrix), + plist_get (tem, QCcolor_adjustment)); } } } diff --git a/src/indent.c b/src/indent.c index c3d78518c4..d4ef075f00 100644 --- a/src/indent.c +++ b/src/indent.c @@ -484,15 +484,15 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos) : MOST_POSITIVE_FIXNUM); plist = XCDR (val); - if ((prop = Fplist_get (plist, QCwidth), + if ((prop = plist_get (plist, QCwidth), RANGED_FIXNUMP (0, prop, INT_MAX)) - || (prop = Fplist_get (plist, QCrelative_width), + || (prop = plist_get (plist, QCrelative_width), RANGED_FIXNUMP (0, prop, INT_MAX))) width = XFIXNUM (prop); else if (FLOATP (prop) && 0 <= XFLOAT_DATA (prop) && XFLOAT_DATA (prop) <= INT_MAX) width = (int)(XFLOAT_DATA (prop) + 0.5); - else if ((prop = Fplist_get (plist, QCalign_to), + else if ((prop = plist_get (plist, QCalign_to), RANGED_FIXNUMP (col, prop, align_to_max))) width = XFIXNUM (prop) - col; else if (FLOATP (prop) && col <= XFLOAT_DATA (prop) @@ -514,7 +514,7 @@ check_display_width (ptrdiff_t pos, ptrdiff_t col, ptrdiff_t *endpos) /* For :relative-width, we need to multiply by the column width of the character at POS, if it is greater than 1. */ if (!NILP (plist) - && !NILP (Fplist_get (plist, QCrelative_width)) + && !NILP (plist_get (plist, QCrelative_width)) && !NILP (BVAR (current_buffer, enable_multibyte_characters))) { int b, wd; diff --git a/src/intervals.c b/src/intervals.c index 9e28637d6b..85152c58a5 100644 --- a/src/intervals.c +++ b/src/intervals.c @@ -1737,11 +1737,11 @@ lookup_char_property (Lisp_Object plist, Lisp_Object prop, bool textprop) { tail = XCDR (tail); for (; NILP (fallback) && CONSP (tail); tail = XCDR (tail)) - fallback = Fplist_get (plist, XCAR (tail)); + fallback = plist_get (plist, XCAR (tail)); } if (textprop && NILP (fallback) && CONSP (Vdefault_text_properties)) - fallback = Fplist_get (Vdefault_text_properties, prop); + fallback = plist_get (Vdefault_text_properties, prop); return fallback; } diff --git a/src/keyboard.c b/src/keyboard.c index 5b5972ceee..e5708c06d9 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -5601,7 +5601,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y, if (IMAGEP (object)) { Lisp_Object image_map, hotspot; - if ((image_map = Fplist_get (XCDR (object), QCmap), + if ((image_map = plist_get (XCDR (object), QCmap), !NILP (image_map)) && (hotspot = find_hot_spot (image_map, dx, dy), CONSP (hotspot)) diff --git a/src/lisp.h b/src/lisp.h index 05b0754ff6..7a7d2e7997 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4034,6 +4034,10 @@ extern ptrdiff_t string_char_to_byte (Lisp_Object, ptrdiff_t); extern ptrdiff_t string_byte_to_char (Lisp_Object, ptrdiff_t); extern Lisp_Object string_to_multibyte (Lisp_Object); extern Lisp_Object string_make_unibyte (Lisp_Object); +extern Lisp_Object plist_get (Lisp_Object plist, Lisp_Object prop); +extern Lisp_Object plist_put (Lisp_Object plist, Lisp_Object prop, + Lisp_Object val); +extern Lisp_Object plist_member (Lisp_Object plist, Lisp_Object prop); extern void syms_of_fns (void); /* Defined in sort.c */ diff --git a/src/lread.c b/src/lread.c index a00590e466..66b1391646 100644 --- a/src/lread.c +++ b/src/lread.c @@ -3175,7 +3175,7 @@ hash_table_from_plist (Lisp_Object plist) /* This is repetitive but fast and simple. */ #define ADDPARAM(name) \ do { \ - Lisp_Object val = Fplist_get (plist, Q ## name); \ + Lisp_Object val = plist_get (plist, Q ## name); \ if (!NILP (val)) \ { \ *par++ = QC ## name; \ @@ -3190,7 +3190,7 @@ hash_table_from_plist (Lisp_Object plist) ADDPARAM (rehash_threshold); ADDPARAM (purecopy); - Lisp_Object data = Fplist_get (plist, Qdata); + Lisp_Object data = plist_get (plist, Qdata); /* Now use params to make a new hash table and fill it. */ Lisp_Object ht = Fmake_hash_table (par - params, params); diff --git a/src/process.c b/src/process.c index f9a32e0d6a..af402c8edb 100644 --- a/src/process.c +++ b/src/process.c @@ -1281,7 +1281,7 @@ Return BUFFER. */) update_process_mark (p); } if (NETCONN1_P (p) || SERIALCONN1_P (p) || PIPECONN1_P (p)) - pset_childp (p, Fplist_put (p->childp, QCbuffer, buffer)); + pset_childp (p, plist_put (p->childp, QCbuffer, buffer)); setup_process_coding_systems (process); return buffer; } @@ -1360,7 +1360,7 @@ The string argument is normally a multibyte string, except: pset_filter (p, filter); if (NETCONN1_P (p) || SERIALCONN1_P (p) || PIPECONN1_P (p)) - pset_childp (p, Fplist_put (p->childp, QCfilter, filter)); + pset_childp (p, plist_put (p->childp, QCfilter, filter)); setup_process_coding_systems (process); return filter; } @@ -1392,7 +1392,7 @@ It gets two arguments: the process, and a string describing the change. */) pset_sentinel (p, sentinel); if (NETCONN1_P (p) || SERIALCONN1_P (p) || PIPECONN1_P (p)) - pset_childp (p, Fplist_put (p->childp, QCsentinel, sentinel)); + pset_childp (p, plist_put (p->childp, QCsentinel, sentinel)); return sentinel; } @@ -1553,25 +1553,25 @@ waiting for the process to be fully set up.*/) if (DATAGRAM_CONN_P (process) && (EQ (key, Qt) || EQ (key, QCremote))) - contact = Fplist_put (contact, QCremote, - Fprocess_datagram_address (process)); + contact = plist_put (contact, QCremote, + Fprocess_datagram_address (process)); #endif if ((!NETCONN_P (process) && !SERIALCONN_P (process) && !PIPECONN_P (process)) || EQ (key, Qt)) return contact; if (NILP (key) && NETCONN_P (process)) - return list2 (Fplist_get (contact, QChost), - Fplist_get (contact, QCservice)); + return list2 (plist_get (contact, QChost), + plist_get (contact, QCservice)); if (NILP (key) && SERIALCONN_P (process)) - return list2 (Fplist_get (contact, QCport), - Fplist_get (contact, QCspeed)); + return list2 (plist_get (contact, QCport), + plist_get (contact, QCspeed)); /* FIXME: Return a meaningful value (e.g., the child end of the pipe) if the pipe process is useful for purposes other than receiving stderr. */ if (NILP (key) && PIPECONN_P (process)) return Qt; - return Fplist_get (contact, key); + return plist_get (contact, key); } DEFUN ("process-plist", Fprocess_plist, Sprocess_plist, @@ -1773,7 +1773,7 @@ usage: (make-process &rest ARGS) */) /* Save arguments for process-contact and clone-process. */ contact = Flist (nargs, args); - if (!NILP (Fplist_get (contact, QCfile_handler))) + if (!NILP (plist_get (contact, QCfile_handler))) { Lisp_Object file_handler = Ffind_file_name_handler (BVAR (current_buffer, directory), @@ -1782,7 +1782,7 @@ usage: (make-process &rest ARGS) */) return CALLN (Fapply, file_handler, Qmake_process, contact); } - buffer = Fplist_get (contact, QCbuffer); + buffer = plist_get (contact, QCbuffer); if (!NILP (buffer)) buffer = Fget_buffer_create (buffer, Qnil); @@ -1792,10 +1792,10 @@ usage: (make-process &rest ARGS) */) chdir, since it's in a vfork. */ current_dir = get_current_directory (true); - name = Fplist_get (contact, QCname); + name = plist_get (contact, QCname); CHECK_STRING (name); - command = Fplist_get (contact, QCcommand); + command = plist_get (contact, QCcommand); if (CONSP (command)) program = XCAR (command); else @@ -1804,10 +1804,10 @@ usage: (make-process &rest ARGS) */) if (!NILP (program)) CHECK_STRING (program); - bool query_on_exit = NILP (Fplist_get (contact, QCnoquery)); + bool query_on_exit = NILP (plist_get (contact, QCnoquery)); stderrproc = Qnil; - xstderr = Fplist_get (contact, QCstderr); + xstderr = plist_get (contact, QCstderr); if (PROCESSP (xstderr)) { if (!PIPECONN_P (xstderr)) @@ -1833,18 +1833,18 @@ usage: (make-process &rest ARGS) */) eassert (NILP (XPROCESS (proc)->plist)); pset_type (XPROCESS (proc), Qreal); pset_buffer (XPROCESS (proc), buffer); - pset_sentinel (XPROCESS (proc), Fplist_get (contact, QCsentinel)); - pset_filter (XPROCESS (proc), Fplist_get (contact, QCfilter)); + pset_sentinel (XPROCESS (proc), plist_get (contact, QCsentinel)); + pset_filter (XPROCESS (proc), plist_get (contact, QCfilter)); pset_command (XPROCESS (proc), Fcopy_sequence (command)); if (!query_on_exit) XPROCESS (proc)->kill_without_query = 1; - tem = Fplist_get (contact, QCstop); + tem = plist_get (contact, QCstop); /* Normal processes can't be started in a stopped state, see Bug#30460. */ CHECK_TYPE (NILP (tem), Qnull, tem); - tem = Fplist_get (contact, QCconnection_type); + tem = plist_get (contact, QCconnection_type); if (EQ (tem, Qpty)) XPROCESS (proc)->pty_flag = true; else if (EQ (tem, Qpipe)) @@ -1886,7 +1886,7 @@ usage: (make-process &rest ARGS) */) Lisp_Object coding_systems = Qt; Lisp_Object val, *args2; - tem = Fplist_get (contact, QCcoding); + tem = plist_get (contact, QCcoding); if (!NILP (tem)) { val = tem; @@ -2364,7 +2364,7 @@ usage: (make-pipe-process &rest ARGS) */) contact = Flist (nargs, args); - name = Fplist_get (contact, QCname); + name = plist_get (contact, QCname); CHECK_STRING (name); proc = make_process (name); specpdl_ref specpdl_count = SPECPDL_INDEX (); @@ -2396,21 +2396,21 @@ usage: (make-pipe-process &rest ARGS) */) if (inchannel > max_desc) max_desc = inchannel; - buffer = Fplist_get (contact, QCbuffer); + buffer = plist_get (contact, QCbuffer); if (NILP (buffer)) buffer = name; buffer = Fget_buffer_create (buffer, Qnil); pset_buffer (p, buffer); pset_childp (p, contact); - pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist))); + pset_plist (p, Fcopy_sequence (plist_get (contact, QCplist))); pset_type (p, Qpipe); - pset_sentinel (p, Fplist_get (contact, QCsentinel)); - pset_filter (p, Fplist_get (contact, QCfilter)); + pset_sentinel (p, plist_get (contact, QCsentinel)); + pset_filter (p, plist_get (contact, QCfilter)); eassert (NILP (p->log)); - if (tem = Fplist_get (contact, QCnoquery), !NILP (tem)) + if (tem = plist_get (contact, QCnoquery), !NILP (tem)) p->kill_without_query = 1; - if (tem = Fplist_get (contact, QCstop), !NILP (tem)) + if (tem = plist_get (contact, QCstop), !NILP (tem)) pset_command (p, Qt); eassert (! p->pty_flag); @@ -2431,7 +2431,7 @@ usage: (make-pipe-process &rest ARGS) */) Lisp_Object coding_systems = Qt; Lisp_Object val; - tem = Fplist_get (contact, QCcoding); + tem = plist_get (contact, QCcoding); val = Qnil; if (!NILP (tem)) { @@ -2918,7 +2918,7 @@ set up yet, this function will block until socket setup has completed. */) if (set_socket_option (s, option, value)) { - pset_childp (p, Fplist_put (p->childp, option, value)); + pset_childp (p, plist_put (p->childp, option, value)); return Qt; } @@ -2996,19 +2996,19 @@ usage: (serial-process-configure &rest ARGS) */) contact = Flist (nargs, args); - proc = Fplist_get (contact, QCprocess); + proc = plist_get (contact, QCprocess); if (NILP (proc)) - proc = Fplist_get (contact, QCname); + proc = plist_get (contact, QCname); if (NILP (proc)) - proc = Fplist_get (contact, QCbuffer); + proc = plist_get (contact, QCbuffer); if (NILP (proc)) - proc = Fplist_get (contact, QCport); + proc = plist_get (contact, QCport); proc = get_process (proc); p = XPROCESS (proc); if (!EQ (p->type, Qserial)) error ("Not a serial process"); - if (NILP (Fplist_get (p->childp, QCspeed))) + if (NILP (plist_get (p->childp, QCspeed))) return Qnil; serial_configure (p, contact); @@ -3101,17 +3101,17 @@ usage: (make-serial-process &rest ARGS) */) contact = Flist (nargs, args); - port = Fplist_get (contact, QCport); + port = plist_get (contact, QCport); if (NILP (port)) error ("No port specified"); CHECK_STRING (port); - if (NILP (Fplist_member (contact, QCspeed))) + if (NILP (plist_member (contact, QCspeed))) error (":speed not specified"); - if (!NILP (Fplist_get (contact, QCspeed))) - CHECK_FIXNUM (Fplist_get (contact, QCspeed)); + if (!NILP (plist_get (contact, QCspeed))) + CHECK_FIXNUM (plist_get (contact, QCspeed)); - name = Fplist_get (contact, QCname); + name = plist_get (contact, QCname); if (NILP (name)) name = port; CHECK_STRING (name); @@ -3131,21 +3131,21 @@ usage: (make-serial-process &rest ARGS) */) eassert (0 <= fd && fd < FD_SETSIZE); chan_process[fd] = proc; - buffer = Fplist_get (contact, QCbuffer); + buffer = plist_get (contact, QCbuffer); if (NILP (buffer)) buffer = name; buffer = Fget_buffer_create (buffer, Qnil); pset_buffer (p, buffer); pset_childp (p, contact); - pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist))); + pset_plist (p, Fcopy_sequence (plist_get (contact, QCplist))); pset_type (p, Qserial); - pset_sentinel (p, Fplist_get (contact, QCsentinel)); - pset_filter (p, Fplist_get (contact, QCfilter)); + pset_sentinel (p, plist_get (contact, QCsentinel)); + pset_filter (p, plist_get (contact, QCfilter)); eassert (NILP (p->log)); - if (tem = Fplist_get (contact, QCnoquery), !NILP (tem)) + if (tem = plist_get (contact, QCnoquery), !NILP (tem)) p->kill_without_query = 1; - if (tem = Fplist_get (contact, QCstop), !NILP (tem)) + if (tem = plist_get (contact, QCstop), !NILP (tem)) pset_command (p, Qt); eassert (! p->pty_flag); @@ -3155,7 +3155,7 @@ usage: (make-serial-process &rest ARGS) */) update_process_mark (p); - tem = Fplist_get (contact, QCcoding); + tem = plist_get (contact, QCcoding); val = Qnil; if (!NILP (tem)) @@ -3209,7 +3209,7 @@ set_network_socket_coding_system (Lisp_Object proc, Lisp_Object host, Lisp_Object coding_systems = Qt; Lisp_Object val; - tem = Fplist_get (contact, QCcoding); + tem = plist_get (contact, QCcoding); /* Setup coding systems for communicating with the network stream. */ /* Qt denotes we have not yet called Ffind_operation_coding_system. */ @@ -3297,8 +3297,8 @@ finish_after_tls_connection (Lisp_Object proc) if (!NILP (Ffboundp (Qnsm_verify_connection))) result = call3 (Qnsm_verify_connection, proc, - Fplist_get (contact, QChost), - Fplist_get (contact, QCservice)); + plist_get (contact, QChost), + plist_get (contact, QCservice)); eassert (p->outfd < FD_SETSIZE); if (NILP (result)) @@ -3479,7 +3479,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, if (getsockname (s, psa1, &len1) == 0) { Lisp_Object service = make_fixnum (ntohs (sa1.sin_port)); - contact = Fplist_put (contact, QCservice, service); + contact = plist_put (contact, QCservice, service); /* Save the port number so that we can stash it in the process object later. */ DECLARE_POINTER_ALIAS (psa, struct sockaddr_in, sa); @@ -3570,7 +3570,7 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, { Lisp_Object remote; memset (datagram_address[s].sa, 0, addrlen); - if (remote = Fplist_get (contact, QCremote), !NILP (remote)) + if (remote = plist_get (contact, QCremote), !NILP (remote)) { int rfamily; ptrdiff_t rlen = get_lisp_to_sockaddr_size (remote, &rfamily); @@ -3585,8 +3585,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, } #endif - contact = Fplist_put (contact, p->is_server? QClocal: QCremote, - conv_sockaddr_to_lisp (sa, addrlen)); + contact = plist_put (contact, p->is_server? QClocal: QCremote, + conv_sockaddr_to_lisp (sa, addrlen)); #ifdef HAVE_GETSOCKNAME if (!p->is_server) { @@ -3594,8 +3594,8 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos, socklen_t len1 = sizeof (sa1); DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1); if (getsockname (s, psa1, &len1) == 0) - contact = Fplist_put (contact, QClocal, - conv_sockaddr_to_lisp (psa1, len1)); + contact = plist_put (contact, QClocal, + conv_sockaddr_to_lisp (psa1, len1)); } #endif } @@ -3908,7 +3908,7 @@ usage: (make-network-process &rest ARGS) */) #endif /* :type TYPE (nil: stream, datagram */ - tem = Fplist_get (contact, QCtype); + tem = plist_get (contact, QCtype); if (NILP (tem)) socktype = SOCK_STREAM; #ifdef DATAGRAM_SOCKETS @@ -3922,13 +3922,13 @@ usage: (make-network-process &rest ARGS) */) else error ("Unsupported connection type"); - name = Fplist_get (contact, QCname); - buffer = Fplist_get (contact, QCbuffer); - filter = Fplist_get (contact, QCfilter); - sentinel = Fplist_get (contact, QCsentinel); - use_external_socket_p = Fplist_get (contact, QCuse_external_socket); - Lisp_Object server = Fplist_get (contact, QCserver); - bool nowait = !NILP (Fplist_get (contact, QCnowait)); + name = plist_get (contact, QCname); + buffer = plist_get (contact, QCbuffer); + filter = plist_get (contact, QCfilter); + sentinel = plist_get (contact, QCsentinel); + use_external_socket_p = plist_get (contact, QCuse_external_socket); + Lisp_Object server = plist_get (contact, QCserver); + bool nowait = !NILP (plist_get (contact, QCnowait)); if (!NILP (server) && nowait) error ("`:server' is incompatible with `:nowait'"); @@ -3936,9 +3936,9 @@ usage: (make-network-process &rest ARGS) */) /* :local ADDRESS or :remote ADDRESS */ if (NILP (server)) - address = Fplist_get (contact, QCremote); + address = plist_get (contact, QCremote); else - address = Fplist_get (contact, QClocal); + address = plist_get (contact, QClocal); if (!NILP (address)) { host = service = Qnil; @@ -3951,7 +3951,7 @@ usage: (make-network-process &rest ARGS) */) } /* :family FAMILY -- nil (for Inet), local, or integer. */ - tem = Fplist_get (contact, QCfamily); + tem = plist_get (contact, QCfamily); if (NILP (tem)) { #ifdef AF_INET6 @@ -3976,10 +3976,10 @@ usage: (make-network-process &rest ARGS) */) error ("Unknown address family"); /* :service SERVICE -- string, integer (port number), or t (random port). */ - service = Fplist_get (contact, QCservice); + service = plist_get (contact, QCservice); /* :host HOST -- hostname, ip address, or 'local for localhost. */ - host = Fplist_get (contact, QChost); + host = plist_get (contact, QChost); if (NILP (host)) { /* The "connection" function gets it bind info from the address we're @@ -4018,7 +4018,7 @@ usage: (make-network-process &rest ARGS) */) if (!NILP (host)) { message (":family local ignores the :host property"); - contact = Fplist_put (contact, QChost, Qnil); + contact = plist_put (contact, QChost, Qnil); host = Qnil; } CHECK_STRING (service); @@ -4172,16 +4172,16 @@ usage: (make-network-process &rest ARGS) */) record_unwind_protect (remove_process, proc); p = XPROCESS (proc); pset_childp (p, contact); - pset_plist (p, Fcopy_sequence (Fplist_get (contact, QCplist))); + pset_plist (p, Fcopy_sequence (plist_get (contact, QCplist))); pset_type (p, Qnetwork); pset_buffer (p, buffer); pset_sentinel (p, sentinel); pset_filter (p, filter); - pset_log (p, Fplist_get (contact, QClog)); - if (tem = Fplist_get (contact, QCnoquery), !NILP (tem)) + pset_log (p, plist_get (contact, QClog)); + if (tem = plist_get (contact, QCnoquery), !NILP (tem)) p->kill_without_query = 1; - if ((tem = Fplist_get (contact, QCstop), !NILP (tem))) + if ((tem = plist_get (contact, QCstop), !NILP (tem))) pset_command (p, Qt); eassert (p->pid == 0); p->backlog = 5; @@ -4193,7 +4193,7 @@ usage: (make-network-process &rest ARGS) */) eassert (! p->dns_request); #endif #ifdef HAVE_GNUTLS - tem = Fplist_get (contact, QCtls_parameters); + tem = plist_get (contact, QCtls_parameters); CHECK_LIST (tem); p->gnutls_boot_parameters = tem; #endif @@ -4969,17 +4969,17 @@ server_accept_connection (Lisp_Object server, int channel) /* Build new contact information for this setup. */ contact = Fcopy_sequence (ps->childp); - contact = Fplist_put (contact, QCserver, Qnil); - contact = Fplist_put (contact, QChost, host); + contact = plist_put (contact, QCserver, Qnil); + contact = plist_put (contact, QChost, host); if (!NILP (service)) - contact = Fplist_put (contact, QCservice, service); - contact = Fplist_put (contact, QCremote, - conv_sockaddr_to_lisp (&saddr.sa, len)); + contact = plist_put (contact, QCservice, service); + contact = plist_put (contact, QCremote, + conv_sockaddr_to_lisp (&saddr.sa, len)); #ifdef HAVE_GETSOCKNAME len = sizeof saddr; if (getsockname (s, &saddr.sa, &len) == 0) - contact = Fplist_put (contact, QClocal, - conv_sockaddr_to_lisp (&saddr.sa, len)); + contact = plist_put (contact, QClocal, + conv_sockaddr_to_lisp (&saddr.sa, len)); #endif pset_childp (p, contact); diff --git a/src/sound.c b/src/sound.c index 93c84a03b1..0a30782800 100644 --- a/src/sound.c +++ b/src/sound.c @@ -361,10 +361,10 @@ parse_sound (Lisp_Object sound, Lisp_Object *attrs) return 0; sound = XCDR (sound); - attrs[SOUND_FILE] = Fplist_get (sound, QCfile); - attrs[SOUND_DATA] = Fplist_get (sound, QCdata); - attrs[SOUND_DEVICE] = Fplist_get (sound, QCdevice); - attrs[SOUND_VOLUME] = Fplist_get (sound, QCvolume); + attrs[SOUND_FILE] = plist_get (sound, QCfile); + attrs[SOUND_DATA] = plist_get (sound, QCdata); + attrs[SOUND_DEVICE] = plist_get (sound, QCdevice); + attrs[SOUND_VOLUME] = plist_get (sound, QCvolume); #ifndef WINDOWSNT /* File name or data must be specified. */ diff --git a/src/sysdep.c b/src/sysdep.c index 28ab8189c3..c1545622df 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -2939,21 +2939,21 @@ serial_configure (struct Lisp_Process *p, #endif /* Configure speed. */ - if (!NILP (Fplist_member (contact, QCspeed))) - tem = Fplist_get (contact, QCspeed); + if (!NILP (plist_member (contact, QCspeed))) + tem = plist_get (contact, QCspeed); else - tem = Fplist_get (p->childp, QCspeed); + tem = plist_get (p->childp, QCspeed); CHECK_FIXNUM (tem); err = cfsetspeed (&attr, convert_speed (XFIXNUM (tem))); if (err != 0) report_file_error ("Failed cfsetspeed", tem); - childp2 = Fplist_put (childp2, QCspeed, tem); + childp2 = plist_put (childp2, QCspeed, tem); /* Configure bytesize. */ - if (!NILP (Fplist_member (contact, QCbytesize))) - tem = Fplist_get (contact, QCbytesize); + if (!NILP (plist_member (contact, QCbytesize))) + tem = plist_get (contact, QCbytesize); else - tem = Fplist_get (p->childp, QCbytesize); + tem = plist_get (p->childp, QCbytesize); if (NILP (tem)) tem = make_fixnum (8); CHECK_FIXNUM (tem); @@ -2968,13 +2968,13 @@ serial_configure (struct Lisp_Process *p, if (XFIXNUM (tem) != 8) error ("Bytesize cannot be changed"); #endif - childp2 = Fplist_put (childp2, QCbytesize, tem); + childp2 = plist_put (childp2, QCbytesize, tem); /* Configure parity. */ - if (!NILP (Fplist_member (contact, QCparity))) - tem = Fplist_get (contact, QCparity); + if (!NILP (plist_member (contact, QCparity))) + tem = plist_get (contact, QCparity); else - tem = Fplist_get (p->childp, QCparity); + tem = plist_get (p->childp, QCparity); if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd)) error (":parity must be nil (no parity), `even', or `odd'"); #if defined (PARENB) && defined (PARODD) && defined (IGNPAR) && defined (INPCK) @@ -3001,13 +3001,13 @@ serial_configure (struct Lisp_Process *p, if (!NILP (tem)) error ("Parity cannot be configured"); #endif - childp2 = Fplist_put (childp2, QCparity, tem); + childp2 = plist_put (childp2, QCparity, tem); /* Configure stopbits. */ - if (!NILP (Fplist_member (contact, QCstopbits))) - tem = Fplist_get (contact, QCstopbits); + if (!NILP (plist_member (contact, QCstopbits))) + tem = plist_get (contact, QCstopbits); else - tem = Fplist_get (p->childp, QCstopbits); + tem = plist_get (p->childp, QCstopbits); if (NILP (tem)) tem = make_fixnum (1); CHECK_FIXNUM (tem); @@ -3023,13 +3023,13 @@ serial_configure (struct Lisp_Process *p, if (XFIXNUM (tem) != 1) error ("Stopbits cannot be configured"); #endif - childp2 = Fplist_put (childp2, QCstopbits, tem); + childp2 = plist_put (childp2, QCstopbits, tem); /* Configure flowcontrol. */ - if (!NILP (Fplist_member (contact, QCflowcontrol))) - tem = Fplist_get (contact, QCflowcontrol); + if (!NILP (plist_member (contact, QCflowcontrol))) + tem = plist_get (contact, QCflowcontrol); else - tem = Fplist_get (p->childp, QCflowcontrol); + tem = plist_get (p->childp, QCflowcontrol); if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw)) error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'"); #if defined (CRTSCTS) @@ -3063,14 +3063,14 @@ serial_configure (struct Lisp_Process *p, error ("Software flowcontrol (XON/XOFF) not supported"); #endif } - childp2 = Fplist_put (childp2, QCflowcontrol, tem); + childp2 = plist_put (childp2, QCflowcontrol, tem); /* Activate configuration. */ err = tcsetattr (p->outfd, TCSANOW, &attr); if (err != 0) report_file_error ("Failed tcsetattr", Qnil); - childp2 = Fplist_put (childp2, QCsummary, build_string (summary)); + childp2 = plist_put (childp2, QCsummary, build_string (summary)); pset_childp (p, childp2); } #endif /* not DOS_NT */ diff --git a/src/textprop.c b/src/textprop.c index d69682d3ea..96d07b44be 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -2249,7 +2249,7 @@ verify_interval_modification (struct buffer *buf, tem = textget (i->plist, Qfront_sticky); if (TMEM (Qread_only, tem) - || (NILP (Fplist_get (i->plist, Qread_only)) + || (NILP (plist_get (i->plist, Qread_only)) && TMEM (Qcategory, tem))) text_read_only (after); } @@ -2269,7 +2269,7 @@ verify_interval_modification (struct buffer *buf, tem = textget (prev->plist, Qrear_nonsticky); if (! TMEM (Qread_only, tem) - && (! NILP (Fplist_get (prev->plist,Qread_only)) + && (! NILP (plist_get (prev->plist,Qread_only)) || ! TMEM (Qcategory, tem))) text_read_only (before); } @@ -2288,13 +2288,13 @@ verify_interval_modification (struct buffer *buf, tem = textget (i->plist, Qfront_sticky); if (TMEM (Qread_only, tem) - || (NILP (Fplist_get (i->plist, Qread_only)) + || (NILP (plist_get (i->plist, Qread_only)) && TMEM (Qcategory, tem))) text_read_only (after); tem = textget (prev->plist, Qrear_nonsticky); if (! TMEM (Qread_only, tem) - && (! NILP (Fplist_get (prev->plist, Qread_only)) + && (! NILP (plist_get (prev->plist, Qread_only)) || ! TMEM (Qcategory, tem))) text_read_only (after); } diff --git a/src/w32.c b/src/w32.c index 590d9e85d9..c1e4118e9b 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10953,19 +10953,19 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) dcb.EvtChar = 0; /* Configure speed. */ - if (!NILP (Fplist_member (contact, QCspeed))) - tem = Fplist_get (contact, QCspeed); + if (!NILP (plist_member (contact, QCspeed))) + tem = plist_get (contact, QCspeed); else - tem = Fplist_get (p->childp, QCspeed); + tem = plist_get (p->childp, QCspeed); CHECK_FIXNUM (tem); dcb.BaudRate = XFIXNUM (tem); childp2 = Fplist_put (childp2, QCspeed, tem); /* Configure bytesize. */ - if (!NILP (Fplist_member (contact, QCbytesize))) - tem = Fplist_get (contact, QCbytesize); + if (!NILP (plist_member (contact, QCbytesize))) + tem = plist_get (contact, QCbytesize); else - tem = Fplist_get (p->childp, QCbytesize); + tem = plist_get (p->childp, QCbytesize); if (NILP (tem)) tem = make_fixnum (8); CHECK_FIXNUM (tem); @@ -10976,10 +10976,10 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) childp2 = Fplist_put (childp2, QCbytesize, tem); /* Configure parity. */ - if (!NILP (Fplist_member (contact, QCparity))) - tem = Fplist_get (contact, QCparity); + if (!NILP (plist_member (contact, QCparity))) + tem = plist_get (contact, QCparity); else - tem = Fplist_get (p->childp, QCparity); + tem = plist_get (p->childp, QCparity); if (!NILP (tem) && !EQ (tem, Qeven) && !EQ (tem, Qodd)) error (":parity must be nil (no parity), `even', or `odd'"); dcb.fParity = FALSE; @@ -11006,10 +11006,10 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) childp2 = Fplist_put (childp2, QCparity, tem); /* Configure stopbits. */ - if (!NILP (Fplist_member (contact, QCstopbits))) - tem = Fplist_get (contact, QCstopbits); + if (!NILP (plist_member (contact, QCstopbits))) + tem = plist_get (contact, QCstopbits); else - tem = Fplist_get (p->childp, QCstopbits); + tem = plist_get (p->childp, QCstopbits); if (NILP (tem)) tem = make_fixnum (1); CHECK_FIXNUM (tem); @@ -11023,10 +11023,10 @@ serial_configure (struct Lisp_Process *p, Lisp_Object contact) childp2 = Fplist_put (childp2, QCstopbits, tem); /* Configure flowcontrol. */ - if (!NILP (Fplist_member (contact, QCflowcontrol))) - tem = Fplist_get (contact, QCflowcontrol); + if (!NILP (plist_member (contact, QCflowcontrol))) + tem = plist_get (contact, QCflowcontrol); else - tem = Fplist_get (p->childp, QCflowcontrol); + tem = plist_get (p->childp, QCflowcontrol); if (!NILP (tem) && !EQ (tem, Qhw) && !EQ (tem, Qsw)) error (":flowcontrol must be nil (no flowcontrol), `hw', or `sw'"); dcb.fOutxCtsFlow = FALSE; diff --git a/src/w32fns.c b/src/w32fns.c index b093d3c32e..468073c917 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -10212,21 +10212,21 @@ usage: (w32-notification-notify &rest PARAMS) */) arg_plist = Flist (nargs, args); /* Icon. */ - lres = Fplist_get (arg_plist, QCicon); + lres = plist_get (arg_plist, QCicon); if (STRINGP (lres)) icon = SSDATA (ENCODE_FILE (Fexpand_file_name (lres, Qnil))); else icon = (char *)""; /* Tip. */ - lres = Fplist_get (arg_plist, QCtip); + lres = plist_get (arg_plist, QCtip); if (STRINGP (lres)) tip = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1)); else tip = (char *)"Emacs notification"; /* Severity. */ - lres = Fplist_get (arg_plist, QClevel); + lres = plist_get (arg_plist, QClevel); if (NILP (lres)) severity = Ni_None; else if (EQ (lres, Qinfo)) @@ -10239,14 +10239,14 @@ usage: (w32-notification-notify &rest PARAMS) */) severity = Ni_Info; /* Title. */ - lres = Fplist_get (arg_plist, QCtitle); + lres = plist_get (arg_plist, QCtitle); if (STRINGP (lres)) title = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1)); else title = (char *)""; /* Notification body text. */ - lres = Fplist_get (arg_plist, QCbody); + lres = plist_get (arg_plist, QCbody); if (STRINGP (lres)) msg = SSDATA (code_convert_string_norecord (lres, Qutf_8, 1)); else diff --git a/src/w32image.c b/src/w32image.c index 1f7c4921b3..da748b8dab 100644 --- a/src/w32image.c +++ b/src/w32image.c @@ -382,7 +382,7 @@ w32_select_active_frame (GpBitmap *pBitmap, int frame, int *nframes, static ARGB w32_image_bg_color (struct frame *f, struct image *img) { - Lisp_Object specified_bg = Fplist_get (XCDR (img->spec), QCbackground); + Lisp_Object specified_bg = plist_get (XCDR (img->spec), QCbackground); Emacs_Color color; /* If the user specified a color, try to use it; if not, use the @@ -435,7 +435,7 @@ w32_load_image (struct frame *f, struct image *img, if (status == Ok) { /* In multiframe pictures, select the first frame. */ - Lisp_Object lisp_index = Fplist_get (XCDR (img->spec), QCindex); + Lisp_Object lisp_index = plist_get (XCDR (img->spec), QCindex); int index = FIXNATP (lisp_index) ? XFIXNAT (lisp_index) : 0; int nframes; double delay; diff --git a/src/xdisp.c b/src/xdisp.c index dec3176047..a46fe99830 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -14694,7 +14694,7 @@ build_desired_tool_bar_string (struct frame *f) selected. */ if (selected_p) { - plist = Fplist_put (plist, QCrelief, make_fixnum (-relief)); + plist = plist_put (plist, QCrelief, make_fixnum (-relief)); hmargin -= relief; vmargin -= relief; } @@ -14704,10 +14704,10 @@ build_desired_tool_bar_string (struct frame *f) /* If image is selected, display it pressed, i.e. with a negative relief. If it's not selected, display it with a raised relief. */ - plist = Fplist_put (plist, QCrelief, - (selected_p - ? make_fixnum (-relief) - : make_fixnum (relief))); + plist = plist_put (plist, QCrelief, + (selected_p + ? make_fixnum (-relief) + : make_fixnum (relief))); hmargin -= relief; vmargin -= relief; } @@ -14716,18 +14716,18 @@ build_desired_tool_bar_string (struct frame *f) if (hmargin || vmargin) { if (hmargin == vmargin) - plist = Fplist_put (plist, QCmargin, make_fixnum (hmargin)); + plist = plist_put (plist, QCmargin, make_fixnum (hmargin)); else - plist = Fplist_put (plist, QCmargin, - Fcons (make_fixnum (hmargin), - make_fixnum (vmargin))); + plist = plist_put (plist, QCmargin, + Fcons (make_fixnum (hmargin), + make_fixnum (vmargin))); } /* If button is not enabled, and we don't have special images for the disabled state, make the image appear disabled by applying an appropriate algorithm to it. */ if (!enabled_p && idx < 0) - plist = Fplist_put (plist, QCconversion, Qdisabled); + plist = plist_put (plist, QCconversion, Qdisabled); /* Put a `display' text property on the string for the image to display. Put a `menu-item' property on the string that gives @@ -26510,8 +26510,8 @@ display_mode_element (struct it *it, int depth, int field_width, int precision, tem = props; while (CONSP (tem)) { - oprops = Fplist_put (oprops, XCAR (tem), - XCAR (XCDR (tem))); + oprops = plist_put (oprops, XCAR (tem), + XCAR (XCDR (tem))); tem = XCDR (XCDR (tem)); } props = oprops; @@ -26962,13 +26962,13 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string, props = mode_line_string_face_prop; else if (!NILP (mode_line_string_face)) { - Lisp_Object face = Fplist_get (props, Qface); + Lisp_Object face = plist_get (props, Qface); props = Fcopy_sequence (props); if (NILP (face)) face = mode_line_string_face; else face = list2 (face, mode_line_string_face); - props = Fplist_put (props, Qface, face); + props = plist_put (props, Qface, face); } Fadd_text_properties (make_fixnum (0), make_fixnum (len), props, lisp_string); @@ -26987,7 +26987,7 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string, Lisp_Object face; if (NILP (props)) props = Ftext_properties_at (make_fixnum (0), lisp_string); - face = Fplist_get (props, Qface); + face = plist_get (props, Qface); if (NILP (face)) face = mode_line_string_face; else @@ -28037,7 +28037,7 @@ display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_st face_string); if (!NILP (display)) { - Lisp_Object min_width = Fplist_get (display, Qmin_width); + Lisp_Object min_width = plist_get (display, Qmin_width); if (!NILP (min_width)) display_min_width (it, 0, face_string, min_width); } @@ -30730,14 +30730,14 @@ produce_stretch_glyph (struct it *it) plist = XCDR (it->object); /* Compute the width of the stretch. */ - if ((prop = Fplist_get (plist, QCwidth), !NILP (prop)) + if ((prop = plist_get (plist, QCwidth), !NILP (prop)) && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL)) { /* Absolute width `:width WIDTH' specified and valid. */ zero_width_ok_p = true; width = (int)tem; } - else if (prop = Fplist_get (plist, QCrelative_width), NUMVAL (prop) > 0) + else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0) { /* Relative width `:relative-width FACTOR' specified and valid. Compute the width of the characters having this `display' @@ -30774,7 +30774,7 @@ produce_stretch_glyph (struct it *it) PRODUCE_GLYPHS (&it2); width = NUMVAL (prop) * it2.pixel_width; } - else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop)) + else if ((prop = plist_get (plist, QCalign_to), !NILP (prop)) && calc_pixel_width_or_height (&tem, it, prop, font, true, &align_to)) { @@ -30800,13 +30800,13 @@ produce_stretch_glyph (struct it *it) { int default_height = normal_char_height (font, ' '); - if ((prop = Fplist_get (plist, QCheight), !NILP (prop)) + if ((prop = plist_get (plist, QCheight), !NILP (prop)) && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL)) { height = (int)tem; zero_height_ok_p = true; } - else if (prop = Fplist_get (plist, QCrelative_height), + else if (prop = plist_get (plist, QCrelative_height), NUMVAL (prop) > 0) height = default_height * NUMVAL (prop); else @@ -30818,7 +30818,7 @@ produce_stretch_glyph (struct it *it) /* Compute percentage of height used for ascent. If `:ascent ASCENT' is present and valid, use that. Otherwise, derive the ascent from the font in use. */ - if (prop = Fplist_get (plist, QCascent), + if (prop = plist_get (plist, QCascent), NUMVAL (prop) > 0 && NUMVAL (prop) <= 100) ascent = height * NUMVAL (prop) / 100.0; else if (!NILP (prop) @@ -34165,7 +34165,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, if (IMAGEP (object)) { Lisp_Object image_map, hotspot; - if ((image_map = Fplist_get (XCDR (object), QCmap), + if ((image_map = plist_get (XCDR (object), QCmap), !NILP (image_map)) && (hotspot = find_hot_spot (image_map, dx, dy), CONSP (hotspot)) @@ -34180,10 +34180,10 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, if (CONSP (hotspot) && (plist = XCAR (hotspot), CONSP (plist))) { - pointer = Fplist_get (plist, Qpointer); + pointer = plist_get (plist, Qpointer); if (NILP (pointer)) pointer = Qhand; - help = Fplist_get (plist, Qhelp_echo); + help = plist_get (plist, Qhelp_echo); if (!NILP (help)) { help_echo_string = help; @@ -34194,7 +34194,7 @@ note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y, } } if (NILP (pointer)) - pointer = Fplist_get (XCDR (object), QCpointer); + pointer = plist_get (XCDR (object), QCpointer); } #endif /* HAVE_WINDOW_SYSTEM */ @@ -34680,7 +34680,7 @@ note_mouse_highlight (struct frame *f, int x, int y) if (img != NULL && IMAGEP (img->spec)) { Lisp_Object image_map, hotspot; - if ((image_map = Fplist_get (XCDR (img->spec), QCmap), + if ((image_map = plist_get (XCDR (img->spec), QCmap), !NILP (image_map)) && (hotspot = find_hot_spot (image_map, glyph->slice.img.x + dx, @@ -34698,10 +34698,10 @@ note_mouse_highlight (struct frame *f, int x, int y) if (CONSP (hotspot) && (plist = XCAR (hotspot), CONSP (plist))) { - pointer = Fplist_get (plist, Qpointer); + pointer = plist_get (plist, Qpointer); if (NILP (pointer)) pointer = Qhand; - help_echo_string = Fplist_get (plist, Qhelp_echo); + help_echo_string = plist_get (plist, Qhelp_echo); if (!NILP (help_echo_string)) { help_echo_window = window; @@ -34711,7 +34711,7 @@ note_mouse_highlight (struct frame *f, int x, int y) } } if (NILP (pointer)) - pointer = Fplist_get (XCDR (img->spec), QCpointer); + pointer = plist_get (XCDR (img->spec), QCpointer); } } #endif /* HAVE_WINDOW_SYSTEM */ diff --git a/test/lisp/json-tests.el b/test/lisp/json-tests.el index ef7805a341..ab1f19fb6e 100644 --- a/test/lisp/json-tests.el +++ b/test/lisp/json-tests.el @@ -510,8 +510,8 @@ Point is moved to beginning of the buffer." (let ((json-key-type 'string)) (setq obj (json-add-to-object obj "g" 7)) (setq obj (json-add-to-object obj "h" 8)) - (should (= (lax-plist-get obj "g") 7)) - (should (= (lax-plist-get obj "h") 8))))) + (should (= (plist-get obj "g" #'equal) 7)) + (should (= (plist-get obj "h" #'equal) 8))))) (ert-deftest test-json-add-to-hash-table () (let* ((json-object-type 'hash-table) diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 39bcc5ee38..ba56019d4c 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -852,24 +852,6 @@ (should-not (plist-get d1 3)) (should-not (plist-get d2 3)))) -(ert-deftest test-cycle-lax-plist-get () - (let ((c1 (cyc1 1)) - (c2 (cyc2 1 2)) - (d1 (dot1 1)) - (d2 (dot2 1 2))) - (should (lax-plist-get c1 1)) - (should (lax-plist-get c2 1)) - (should (lax-plist-get d1 1)) - (should (lax-plist-get d2 1)) - (should-error (lax-plist-get c1 2) :type 'circular-list) - (should (lax-plist-get c2 2)) - (should-error (lax-plist-get d1 2) :type 'wrong-type-argument) - (should (lax-plist-get d2 2)) - (should-error (lax-plist-get c1 3) :type 'circular-list) - (should-error (lax-plist-get c2 3) :type 'circular-list) - (should-error (lax-plist-get d1 3) :type 'wrong-type-argument) - (should-error (lax-plist-get d2 3) :type 'wrong-type-argument))) - (ert-deftest test-cycle-plist-member () (let ((c1 (cyc1 1)) (c2 (cyc2 1 2)) @@ -906,24 +888,6 @@ (should-error (plist-put d1 3 3) :type 'wrong-type-argument) (should-error (plist-put d2 3 3) :type 'wrong-type-argument))) -(ert-deftest test-cycle-lax-plist-put () - (let ((c1 (cyc1 1)) - (c2 (cyc2 1 2)) - (d1 (dot1 1)) - (d2 (dot2 1 2))) - (should (lax-plist-put c1 1 1)) - (should (lax-plist-put c2 1 1)) - (should (lax-plist-put d1 1 1)) - (should (lax-plist-put d2 1 1)) - (should-error (lax-plist-put c1 2 2) :type 'circular-list) - (should (lax-plist-put c2 2 2)) - (should-error (lax-plist-put d1 2 2) :type 'wrong-type-argument) - (should (lax-plist-put d2 2 2)) - (should-error (lax-plist-put c1 3 3) :type 'circular-list) - (should-error (lax-plist-put c2 3 3) :type 'circular-list) - (should-error (lax-plist-put d1 3 3) :type 'wrong-type-argument) - (should-error (lax-plist-put d2 3 3) :type 'wrong-type-argument))) - (ert-deftest test-cycle-equal () (should-error (equal (cyc1 1) (cyc1 1))) (should-error (equal (cyc2 1 2) (cyc2 1 2)))) @@ -936,24 +900,12 @@ "Test that `plist-get' doesn't signal an error on degenerate plists." (should-not (plist-get '(:foo 1 :bar) :bar))) -(ert-deftest lax-plist-get/odd-number-of-elements () - "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726." - (should (equal (should-error (lax-plist-get '(:foo 1 :bar) :bar) - :type 'wrong-type-argument) - '(wrong-type-argument plistp (:foo 1 :bar))))) - (ert-deftest plist-put/odd-number-of-elements () "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726." (should (equal (should-error (plist-put '(:foo 1 :bar) :zot 2) :type 'wrong-type-argument) '(wrong-type-argument plistp (:foo 1 :bar))))) -(ert-deftest lax-plist-put/odd-number-of-elements () - "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726." - (should (equal (should-error (lax-plist-put '(:foo 1 :bar) :zot 2) - :type 'wrong-type-argument) - '(wrong-type-argument plistp (:foo 1 :bar))))) - (ert-deftest plist-member/improper-list () "Check for https://debbugs.gnu.org/cgi/bugreport.cgi?bug=27726." (should (equal (should-error (plist-member '(:foo 1 . :bar) :qux) @@ -1375,4 +1327,21 @@ (should-error (append loop '(end)) :type 'circular-list))) +(ert-deftest test-plist () + (let ((plist '(:a "b"))) + (setq plist (plist-put plist :b "c")) + (should (equal (plist-get plist :b) "c")) + (should (equal (plist-member plist :b) '(:b "c")))) + + (let ((plist '("1" "2" "a" "b"))) + (setq plist (plist-put plist (copy-sequence "a") "c")) + (should-not (equal (plist-get plist (copy-sequence "a")) "c")) + (should-not (equal (plist-member plist (copy-sequence "a")) '("a" "c")))) + + (let ((plist '("1" "2" "a" "b"))) + (setq plist (plist-put plist (copy-sequence "a") "c" #'equal)) + (should (equal (plist-get plist (copy-sequence "a") #'equal) "c")) + (should (equal (plist-member plist (copy-sequence "a") #'equal) + '("a" "c"))))) + ;;; fns-tests.el ends here commit 5b1bb1af030597aab7f7895b6e3da9b430f9438a Author: Lars Ingebrigtsen Date: Mon Jun 27 10:11:06 2022 +0200 Add NEWS entry about C-h v font locking diff --git a/etc/NEWS b/etc/NEWS index 257b32a5b0..57b72dc846 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -609,6 +609,10 @@ or ':scream:'. ** Help +--- +*** Variable values displayed by 'C-h v' in *Help* are now font-locked. + ++++ *** New user option 'help-clean-buttons'. If non-nil, link buttons in *Help* will have any surrounding quotes removed. commit c21487b2bed3bb986f0dcbdca5e4561f87a77ca8 Author: hokomo Date: Mon Jun 27 10:03:30 2022 +0200 Fix detecting dotted pairs in icalendar-export-region * lisp/calendar/icalendar.el (icalendar-export-region): Fix detecting dotted pairs (bug#56241). Copyright-paperwork-exempt: yes diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el index 1a5a071e20..cf54293989 100644 --- a/lisp/calendar/icalendar.el +++ b/lisp/calendar/icalendar.el @@ -1144,7 +1144,8 @@ FExport diary data into iCalendar file: ") (cdr contents-n-summary)))) (setq result (concat result header contents alarm "\nEND:VEVENT"))) - (if (consp cns-cons-or-list) + (if (and (consp cns-cons-or-list) + (not (listp (cdr cns-cons-or-list)))) (list cns-cons-or-list) cns-cons-or-list))) ;; handle errors commit bc3b20b44164aad1b196518516ecf3645219ac72 Author: Allen Li Date: Mon Jun 27 09:46:27 2022 +0200 find-dired: Add find-dired-with-command Add a command that runs and sets up the find-dired buffer with an arbitrary find command. Also rewrite the existing find-dired commands using it. The set of commands possible with find-dired is limited; the new command allows users to run the full set of commands, but also leaves the responsibility to the user to construct the command manually. * lisp/find-dired.el (find-command-history): New var. (find-dired-with-command): New command. (find-dired): Rewritten with new command. diff --git a/etc/NEWS b/etc/NEWS index c85e8e0256..257b32a5b0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1381,6 +1381,13 @@ doesn't work on other systems. Also see etc/PROBLEMS. These are used to alter an URL before using it. By default it removes the common "utm_" trackers from URLs. +** Find-Dired + +*** New command 'find-dired-with-command'. +This enables users to run 'find-dired' with an arbitrary command, +enabling running commands previously unsupported and also enabling new +commands to be built on top. + ** Gnus +++ diff --git a/lisp/find-dired.el b/lisp/find-dired.el index 998ddbc721..2f3f6b689a 100644 --- a/lisp/find-dired.el +++ b/lisp/find-dired.el @@ -154,6 +154,9 @@ output of `find' (one file per line) when this function is called." ;; History of find-args values entered in the minibuffer. (defvar find-args-history nil) +(defvar find-command-history nil + "History of commands passed interactively to `find-dired-with-command'.") + (defvar dired-sort-inhibit) ;;;###autoload @@ -171,6 +174,38 @@ it finishes, type \\[kill-find]." (interactive (list (read-directory-name "Run find in directory: " nil "" t) (read-string "Run find (with args): " find-args '(find-args-history . 1)))) + (setq find-args args ; save for next interactive call + args (concat find-program " . " + (if (string= args "") + "" + (concat + (shell-quote-argument "(") + " " args " " + (shell-quote-argument ")") + " ")) + (find-dired--escaped-ls-option))) + (find-dired-with-command dir args)) + +;;;###autoload +(defun find-dired-with-command (dir command) + "Run `find' and go into Dired mode on a buffer of the output. +The user-supplied COMMAND is run after changing into DIR and should look like + + find . GLOBALARGS \\( ARGS \\) -ls + +The car of the variable `find-ls-option' specifies what to +use in place of \"-ls\" as the starting input. + +Collect output in the \"*Find*\" buffer. To kill the job before +it finishes, type \\[kill-find]." + (interactive + (list (read-directory-name "Run find in directory: " nil "" t) + (read-string "Run find command: " + (cons (concat find-program + " . \\( \\) " + (find-dired--escaped-ls-option)) + (+ 1 (length find-program) (length " . \\( "))) + find-command-history))) (let ((dired-buffers dired-buffers)) ;; Expand DIR ("" means default-directory), and make sure it has a ;; trailing slash. @@ -199,19 +234,9 @@ it finishes, type \\[kill-find]." (kill-all-local-variables) (setq buffer-read-only nil) (erase-buffer) - (setq default-directory dir - find-args args ; save for next interactive call - args (concat find-program " . " - (if (string= args "") - "" - (concat - (shell-quote-argument "(") - " " args " " - (shell-quote-argument ")") - " ")) - (find-dired--escaped-ls-option))) + (setq default-directory dir) ;; Start the find process. - (shell-command (concat args "&") (current-buffer)) + (shell-command (concat command "&") (current-buffer)) (dired-mode dir (cdr find-ls-option)) (let ((map (make-sparse-keymap))) (set-keymap-parent map (current-local-map)) @@ -220,7 +245,7 @@ it finishes, type \\[kill-find]." (setq-local dired-sort-inhibit t) (setq-local revert-buffer-function (lambda (_ignore-auto _noconfirm) - (find-dired dir find-args))) + (find-dired-with-command dir command))) ;; Set subdir-alist so that Tree Dired will work: (if (fboundp 'dired-simple-subdir-alist) ;; will work even with nested dired format (dired-nstd.el,v 1.15 @@ -240,7 +265,7 @@ it finishes, type \\[kill-find]." ;; Make second line a ``find'' line in analogy to the ``total'' or ;; ``wildcard'' line. (let ((point (point))) - (insert " " args "\n") + (insert " " command "\n") (dired-insert-set-properties point (point))) (setq buffer-read-only t) (let ((proc (get-buffer-process (current-buffer)))) commit 995fb1677d640784f1ca58ef99a71314a3ac9d30 Author: Allen Li Date: Mon Jun 27 09:44:29 2022 +0200 find-dired: Factor out find-dired--escaped-ls-option Deduplicate this logic for other future find-dired commands. * lisp/find-dired.el (find-dired--escaped-ls-option): New function. (find-dired): Use find-dired--escaped-ls-option. diff --git a/lisp/find-dired.el b/lisp/find-dired.el index 61e626080e..998ddbc721 100644 --- a/lisp/find-dired.el +++ b/lisp/find-dired.el @@ -209,13 +209,7 @@ it finishes, type \\[kill-find]." " " args " " (shell-quote-argument ")") " ")) - (if (string-match "\\`\\(.*\\) {} \\(\\\\;\\|\\+\\)\\'" - (car find-ls-option)) - (format "%s %s %s" - (match-string 1 (car find-ls-option)) - (shell-quote-argument "{}") - find-exec-terminator) - (car find-ls-option)))) + (find-dired--escaped-ls-option))) ;; Start the find process. (shell-command (concat args "&") (current-buffer)) (dired-mode dir (cdr find-ls-option)) @@ -256,6 +250,16 @@ it finishes, type \\[kill-find]." (move-marker (process-mark proc) (point) (current-buffer))) (setq mode-line-process '(":%s")))) +(defun find-dired--escaped-ls-option () + "Return the car of `find-ls-option' escaped for a shell command." + (if (string-match "\\`\\(.*\\) {} \\(\\\\;\\|\\+\\)\\'" + (car find-ls-option)) + (format "%s %s %s" + (match-string 1 (car find-ls-option)) + (shell-quote-argument "{}") + find-exec-terminator) + (car find-ls-option))) + (defun kill-find () "Kill the `find' process running in the current buffer." (interactive) commit f7149f73b125ba56494a89e8053f090a215b842e Author: Lars Ingebrigtsen Date: Mon Jun 27 09:02:26 2022 +0200 Fix off-by-one error in Fsignal_names * src/process.c (Fsignal_names): Fix off-by-one error. diff --git a/src/process.c b/src/process.c index 531ad677fe..f9a32e0d6a 100644 --- a/src/process.c +++ b/src/process.c @@ -8323,7 +8323,7 @@ DEFUN ("signal-names", Fsignal_names, Ssignal_names, 0, 0, 0, { char name[SIG2STR_MAX]; Lisp_Object names = Qnil; - for (int i = 0; i < 255; ++i) + for (int i = 0; i < 256; ++i) { if (!sig2str (i, name)) names = Fcons (build_string (name), names); commit 0c01f3fa180aad18c4f63c783e3ebef2312e72f9 Author: Po Lu Date: Mon Jun 27 06:21:16 2022 +0000 Use correct background for image mask color on Haiku * src/haikuterm.c (haiku_draw_image_glyph_string): Use adjusted background for image mask. diff --git a/src/haikuterm.c b/src/haikuterm.c index 9e84dec159..9f8aceae64 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -1749,7 +1749,7 @@ haiku_draw_image_glyph_string (struct glyph_string *s) 0, 0, s->img->original_width, s->img->original_height, - face->background); + background); } else /* In order to make sure the stipple background remains commit d1f63b2b0683a18d9b39faf7a825b89459754a8f Author: Po Lu Date: Mon Jun 27 06:16:52 2022 +0000 Implement stipples for images on Haiku * src/haiku_draw_support.cc (be_draw_bitmap_with_mask): New function. * src/haiku_support.h: Add prototype. * src/haikuterm.c (haiku_draw_image_glyph_string): Draw stipple correctly. (haiku_draw_glyph_string): Fix conditions under which row->stipple_p is set. diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc index e2025ed68d..8e911dd184 100644 --- a/src/haiku_draw_support.cc +++ b/src/haiku_draw_support.cc @@ -475,3 +475,62 @@ be_draw_cross_on_pixmap (void *bitmap, int x, int y, int width, be_draw_cross_on_pixmap_1 (target, x, y, width, height, color); } + +void +be_draw_bitmap_with_mask (void *view, void *bitmap, void *mask, + int dx, int dy, int width, int height, + int vx, int vy, int vwidth, int vheight, + bool use_bilinear_filtering) +{ + BBitmap *source ((BBitmap *) bitmap); + BBitmap combined (source->Bounds (), B_RGBA32); + BRect bounds; + int x, y, bit; + BView *vw; + uint32_t source_mask; + unsigned long pixel; + + if (combined.InitCheck () != B_OK) + return; + + if (combined.ImportBits (source) != B_OK) + return; + + bounds = source->Bounds (); + + if (source->ColorSpace () == B_RGB32) + source_mask = 255u << 24; + else + source_mask = 0; + + for (y = 0; y < BE_RECT_HEIGHT (bounds); ++y) + { + for (x = 0; x < BE_RECT_WIDTH (bounds); ++x) + { + bit = haiku_get_pixel (mask, x, y); + + if (bit) + { + pixel = haiku_get_pixel (bitmap, x, y); + haiku_put_pixel ((void *) &combined, x, y, + source_mask | pixel); + } + else + haiku_put_pixel ((void *) &combined, x, y, 0); + } + } + + vw = get_view (view); + + vw->SetDrawingMode (B_OP_OVER); + if (!use_bilinear_filtering) + vw->DrawBitmap (&combined, + BRect (dx, dy, dx + width - 1, dy + height - 1), + BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); + else + vw->DrawBitmap (&combined, + BRect (dx, dy, dx + width - 1, dy + height - 1), + BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1), + B_FILTER_BITMAP_BILINEAR); + vw->SetDrawingMode (B_OP_COPY); +} diff --git a/src/haiku_support.h b/src/haiku_support.h index 7585b62a06..6260b35cbc 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -575,6 +575,8 @@ extern void be_apply_affine_transform (void *, double, double, double, extern void be_apply_inverse_transform (double (*)[3], int, int, int *, int *); extern void be_draw_image_mask (void *, void *, int, int, int, int, int, int, int, int, uint32_t); +extern void be_draw_bitmap_with_mask (void *, void *, void *, int, int, int, + int, int, int, int, int, bool); extern void be_get_display_resolution (double *, double *); extern void be_get_screen_dimensions (int *, int *); diff --git a/src/haikuterm.c b/src/haikuterm.c index f50f6b34bd..9e84dec159 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -1672,7 +1672,6 @@ haiku_draw_image_glyph_string (struct glyph_string *s) view = FRAME_HAIKU_VIEW (s->f); bitmap = s->img->pixmap; - /* TODO: implement stipples for images with masks. */ s->stippled_p = face->stipple != 0; if (s->hl == DRAW_CURSOR) @@ -1680,8 +1679,8 @@ haiku_draw_image_glyph_string (struct glyph_string *s) else background = face->background; - BView_SetHighColor (view, background); - BView_FillRectangle (view, x, y, width, height); + haiku_draw_background_rect (s, face, x, y, + width, height); if (bitmap) { @@ -1733,22 +1732,36 @@ haiku_draw_image_glyph_string (struct glyph_string *s) image_transform[1][1], image_transform[1][2]); - BView_DrawBitmap (view, bitmap, 0, 0, - s->img->original_width, - s->img->original_height, - 0, 0, - s->img->original_width, - s->img->original_height, - s->img->use_bilinear_filtering); - - if (mask) - be_draw_image_mask (mask, view, 0, 0, + if (!s->stippled_p || !mask) + { + BView_DrawBitmap (view, bitmap, 0, 0, s->img->original_width, s->img->original_height, 0, 0, s->img->original_width, s->img->original_height, - face->background); + s->img->use_bilinear_filtering); + + if (mask) + be_draw_image_mask (mask, view, 0, 0, + s->img->original_width, + s->img->original_height, + 0, 0, + s->img->original_width, + s->img->original_height, + face->background); + } + else + /* In order to make sure the stipple background remains + visible, use the mask for the alpha channel of BITMAP + and composite it onto the view instead. */ + be_draw_bitmap_with_mask (view, bitmap, mask, 0, 0, + s->img->original_width, + s->img->original_height, + 0, 0, + s->img->original_width, + s->img->original_height, + s->img->use_bilinear_filtering); if (s->slice.x != x || s->slice.y != y || s->slice.width != s->img->width @@ -1949,10 +1962,8 @@ haiku_draw_glyph_string (struct glyph_string *s) /* Set the stipple_p flag indicating whether or not a stipple was drawn in s->row. That is the case either when s is a stretch glyph string and s->face->stipple is not NULL, or when - s->face->stipple exists and s->hl is not DRAW_CURSOR, and s is - not an image. This is different from X. */ - if (s->first_glyph->type != IMAGE_GLYPH - && s->face->stipple + s->face->stipple exists and s->hl is not DRAW_CURSOR. */ + if (s->face->stipple && (s->first_glyph->type == STRETCH_GLYPH || s->hl != DRAW_CURSOR)) s->row->stipple_p = true; commit 087476bce183a404b2a7e62b15b5033504cb4819 Merge: 677d740e14 48bda83d35 Author: Stefan Kangas Date: Mon Jun 27 06:30:25 2022 +0200 Merge from origin/emacs-28 48bda83d35 Update to Org 9.5.4-3-g6dc785 c66b90a534 Mention Solaris 10 'make clean' and 'make check' ade34cf821 Mention further crashes on Solaris 10 commit 677d740e14adc30a8544220b9c49ea9c1527182b Merge: 9533676302 fd04009d16 Author: Stefan Kangas Date: Mon Jun 27 06:30:25 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: fd04009d16 Port distribution tarball to Solaris 10 commit 953367630242d25228f22b0a210db8fb44e0ab30 Merge: 363821344d a9d338818a Author: Stefan Kangas Date: Mon Jun 27 06:30:24 2022 +0200 Merge from origin/emacs-28 a9d338818a ; elec-pair: Fix docstring typo (bug#56233) commit 48bda83d3591d33c5bb8292d9edb06ef3c3f93bd Author: Kyle Meyer Date: Sun Jun 26 23:00:38 2022 -0400 Update to Org 9.5.4-3-g6dc785 diff --git a/lisp/org/oc-basic.el b/lisp/org/oc-basic.el index 775690f176..9ed1b810fa 100644 --- a/lisp/org/oc-basic.el +++ b/lisp/org/oc-basic.el @@ -189,7 +189,14 @@ Return a hash table with citation references as keys and fields alist as values. (cons 'year (cond ((consp date) - (caar date)) + (let ((year (caar date))) + (cond + ((numberp year) (number-to-string year)) + ((stringp year) year) + (t + (error + "First element of CSL-JSON date-parts should be a number or string, got %s: %S" + (type-of year) year))))) ((stringp date) (replace-regexp-in-string (rx diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 6bdcb0afff..2a500fe510 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made." (defun org-git-version () "The Git version of Org mode. Inserted by installing Org or when a release is made." - (let ((org-git-version "release_9.5.4")) + (let ((org-git-version "release_9.5.4-3-g6dc785")) org-git-version)) (provide 'org-version) commit 363821344d17b1bac37e509fc3606be913859831 Author: Po Lu Date: Mon Jun 27 09:13:33 2022 +0800 Correctly convert event state in more places * src/xterm.c (handle_one_xevent): Use `xi_convert_event_state' to handle synthetic and xwidget button events. diff --git a/src/xterm.c b/src/xterm.c index 34fbbfb81c..98ceae6ac1 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -20424,7 +20424,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, { xwidget_button (xvw, xev->evtype == XI_ButtonPress, lrint (xev->event_x), lrint (xev->event_y), - xev->detail, xev->mods.effective, xev->time); + xev->detail, xi_convert_event_state (xev), + xev->time); if (!EQ (selected_window, xvw->w) && (xev->detail < 4)) { @@ -20450,7 +20451,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, bv.x = lrint (xev->event_x); bv.y = lrint (xev->event_y); bv.window = xev->event; - bv.state = xev->mods.effective; + bv.state = xi_convert_event_state (xev); bv.time = xev->time; dpyinfo->last_mouse_glyph_frame = NULL; commit c66b90a534ed08762d57f8f78224dbd6dd6a1b68 Author: Paul Eggert Date: Sun Jun 26 17:36:22 2022 -0500 Mention Solaris 10 'make clean' and 'make check' diff --git a/etc/PROBLEMS b/etc/PROBLEMS index c2164094d7..f935b9c930 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -2400,6 +2400,12 @@ Definitions" to make them defined. We list bugs in current versions here. See also the section on legacy systems. +*** On Solaris 10, 'make clean' and 'make check' do not work. +The Emacs build procedure uses ’find ... -path ...', which Solaris 10 +'find' does not support. You can work around the problem by +installing GNU 'find' in your PATH. This problem should be fixed in +Emacs 29. + *** On Solaris 10 sparc, Emacs crashes during the build while saving state. This was observed for Emacs 28.1 on Solaris 10 32-bit sparc, with Oracle Developer Studio 12.6 (Sun C 5.15). The failure was intermittent, commit ade34cf8217e40ea27cde7c12ad6071cee283bb1 Author: Paul Eggert Date: Sun Jun 26 17:23:20 2022 -0500 Mention further crashes on Solaris 10 diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 8a260c3177..c2164094d7 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -2400,6 +2400,11 @@ Definitions" to make them defined. We list bugs in current versions here. See also the section on legacy systems. +*** On Solaris 10 sparc, Emacs crashes during the build while saving state. +This was observed for Emacs 28.1 on Solaris 10 32-bit sparc, with +Oracle Developer Studio 12.6 (Sun C 5.15). The failure was intermittent, +and running GNU Make a second time would typically finish the build. + *** On Solaris 10, Emacs crashes during the build process. (This applies only with './configure --with-unexec=yes', which is rare.) This was reported for Emacs 25.2 on i386-pc-solaris2.10 with Sun commit 7865b516c8dbff0e7872c746c7afca968ee2348a Author: Lars Ingebrigtsen Date: Sun Jun 26 22:50:50 2022 +0200 Minor clean up of previous Fsignal_names patch * src/process.c (Fsignal_names): Clean up code slightly. diff --git a/src/process.c b/src/process.c index 5cb5d95222..531ad677fe 100644 --- a/src/process.c +++ b/src/process.c @@ -8326,9 +8326,7 @@ DEFUN ("signal-names", Fsignal_names, Ssignal_names, 0, 0, 0, for (int i = 0; i < 255; ++i) { if (!sig2str (i, name)) - { - names = Fcons (build_string (name), names); - } + names = Fcons (build_string (name), names); } return names; } commit ed84f24a215a65dcf2ef49d343eebdbd4be178ee Author: Lars Ingebrigtsen Date: Sun Jun 26 22:45:39 2022 +0200 Make `signal-process' allow completing over signal names * lisp/simple.el (read-signal-name): New function. * src/process.c (Fsignal_process): Use it to allow completing over the signal names (bug#56239). (Fsignal_names): New function. diff --git a/lisp/simple.el b/lisp/simple.el index a750eed72b..6d62c02865 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -10627,6 +10627,19 @@ If the buffer doesn't exist, create it first." "Check whether STRING is empty." (string= string "")) +(defun read-signal-name () + "Read a signal number or name." + (let ((value + (completing-read "Signal code or name: " + (signal-names) + nil + (lambda (value) + (or (string-match "\\`[0-9]+\\'" value) + (member value (signal-names))))))) + (if (string-match "\\`[0-9]+\\'" value) + (string-to-number value) + (intern (concat "sig" (downcase value)))))) + (provide 'simple) diff --git a/src/process.c b/src/process.c index b2847ee172..5cb5d95222 100644 --- a/src/process.c +++ b/src/process.c @@ -7109,7 +7109,7 @@ See function `signal-process' for more details on usage. */) } DEFUN ("signal-process", Fsignal_process, Ssignal_process, - 2, 3, "sProcess (name or number): \nnSignal code: ", + 2, 3, "(list (read-string \"Process (name or number): \") (read-signal-name))", doc: /* Send PROCESS the signal with code SIGCODE. PROCESS may also be a number specifying the process id of the process to signal; in this case, the process need not be a child of @@ -8317,6 +8317,22 @@ If QUERY is `all', also count processors not available. */) #endif } +DEFUN ("signal-names", Fsignal_names, Ssignal_names, 0, 0, 0, + doc: /* Return a list of known signal names on this system. */) + (void) +{ + char name[SIG2STR_MAX]; + Lisp_Object names = Qnil; + for (int i = 0; i < 255; ++i) + { + if (!sig2str (i, name)) + { + names = Fcons (build_string (name), names); + } + } + return names; +} + #ifdef subprocesses /* Arrange to catch SIGCHLD if this hasn't already been arranged. Invoke this after init_process_emacs, and after glib and/or GNUstep @@ -8770,4 +8786,5 @@ sentinel or a process filter function has an error. */); defsubr (&Slist_system_processes); defsubr (&Sprocess_attributes); defsubr (&Snum_processors); + defsubr (&Ssignal_names); } commit 19c44e2be30a2549db446308a128acdff4686c28 Author: Lars Ingebrigtsen Date: Sun Jun 26 21:41:42 2022 +0200 Font-lock variable values in *Help* * lisp/help-fns.el (describe-variable): Font-lock the variable value (bug#47363). diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 43855cd6d7..364fce4ea6 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1239,10 +1239,11 @@ it is displayed along with the global value." (terpri) (let ((buf (current-buffer))) (with-temp-buffer - (lisp-mode-variables nil) + (lisp-data-mode) (set-syntax-table emacs-lisp-mode-syntax-table) (insert print-rep) (pp-buffer) + (font-lock-ensure) (let ((pp-buffer (current-buffer))) (with-current-buffer buf (insert-buffer-substring pp-buffer))))) commit f2a5d48e89bc5611c9cc9aeb978faacee32de6c8 Author: Mattias Engdegård Date: Sun Jun 26 18:46:13 2022 +0200 Optimise away functions in for-effect context * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): Turn functions into nil when compiled for-effect since they have no side-effects on their own. This may enable further improvements such as the elimination of variable bindings. `unwind-protect` forms can be treated as plain function call at this point. In particular, their unwind function argument should be not optimised for effect since it's a function. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 1a50c5a43a..a8741c53bb 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -406,7 +406,7 @@ for speeding up processing.") (`(function . ,_) ;; This forms is compiled as constant or by breaking out ;; all the subexpressions and compiling them separately. - form) + (and (not for-effect) form)) (`(condition-case ,var ,exp . ,clauses) `(,fn ,var ;Not evaluated. @@ -422,15 +422,13 @@ for speeding up processing.") (byte-optimize-body (cdr clause) for-effect)))) clauses))) - (`(unwind-protect ,exp :fun-body ,f) - ;; The unwinding part of an unwind-protect is compiled (and thus - ;; optimized) as a top-level form, but run the optimizer for it here - ;; anyway for lexical variable usage and substitution. But the - ;; protected part has the same for-effect status as the - ;; unwind-protect itself. (The unwinding part is always for effect, - ;; but that isn't handled properly yet.) - (let ((bodyform (byte-optimize-form exp for-effect))) - `(,fn ,bodyform :fun-body ,(byte-optimize-form f nil)))) + ;; `unwind-protect' is a special form which here takes the shape + ;; (unwind-protect EXPR :fun-body UNWIND-FUN). + ;; We can treat it as if it were a plain function at this point, + ;; although there are specific optimisations possible. + ;; In particular, the return value of UNWIND-FUN is never used + ;; so its body should really be compiled for-effect, but we + ;; don't do that right now. (`(catch ,tag . ,exps) `(,fn ,(byte-optimize-form tag nil) @@ -438,13 +436,15 @@ for speeding up processing.") ;; Needed as long as we run byte-optimize-form after cconv. (`(internal-make-closure . ,_) - ;; Look up free vars and mark them to be kept, so that they - ;; won't be optimised away. - (dolist (var (caddr form)) - (let ((lexvar (assq var byte-optimize--lexvars))) - (when lexvar - (setcar (cdr lexvar) t)))) - form) + (and (not for-effect) + (progn + ;; Look up free vars and mark them to be kept, so that they + ;; won't be optimised away. + (dolist (var (caddr form)) + (let ((lexvar (assq var byte-optimize--lexvars))) + (when lexvar + (setcar (cdr lexvar) t)))) + form))) (`((lambda . ,_) . ,_) (let ((newform (macroexp--unfold-lambda form))) commit d3893d7e8e20b392e531f00981191138e26d8bff Author: Stefan Monnier Date: Sun Jun 26 13:15:15 2022 -0400 (oclosure-test-limits): Fix test failure when interpreted * test/lisp/emacs-lisp/oclosure-tests.el (oclosure-test-limits): Make sure we bind `byte-compile-debug` dynamically. diff --git a/test/lisp/emacs-lisp/oclosure-tests.el b/test/lisp/emacs-lisp/oclosure-tests.el index b3a921826b..00b008845c 100644 --- a/test/lisp/emacs-lisp/oclosure-tests.el +++ b/test/lisp/emacs-lisp/oclosure-tests.el @@ -69,6 +69,7 @@ )) (ert-deftest oclosure-test-limits () + (defvar byte-compile-debug) (should (condition-case err (let ((lexical-binding t) commit e6e818f6cfff580461d59e93402291892a731a15 Author: Eli Zaretskii Date: Sun Jun 26 19:55:13 2022 +0300 Fix re-composition under 'composition-break-at-point' * src/xdisp.c (try_window_id): Disable this optimization if 'composition-break-at-point' is non-nil. diff --git a/src/xdisp.c b/src/xdisp.c index cbe6feeae4..dec3176047 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -21192,6 +21192,12 @@ try_window_id (struct window *w) w->frame)))) GIVE_UP (24); + /* composition-break-at-point is incompatible with the optimizations + in this function, because we need to recompose characters when + point moves off their positions. */ + if (composition_break_at_point) + GIVE_UP (27); + /* Make sure beg_unchanged and end_unchanged are up to date. Do it only if buffer has really changed. The reason is that the gap is initially at Z for freshly visited files. The code below would commit da5ef57fe475dbbe68c9eaad48f24ca3f46867b0 Author: Eli Zaretskii Date: Sun Jun 26 19:35:57 2022 +0300 * lisp/simple.el (delete-forward-char): Fix bug #56237. diff --git a/lisp/simple.el b/lisp/simple.el index 2b11a6362f..a750eed72b 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1508,7 +1508,10 @@ the actual saved text might be different from what was killed." ;; 'find-composition' will return (FROM TO ....) or nil. (setq cmp (find-composition pos)) (if cmp - (setq pos (cadr cmp)) + ;; TO can be at POS, in which case we want to make + ;; sure we advance at least by 1 character. + (let ((cmp-end (cadr cmp))) + (setq pos (max (1+ pos) cmp-end))) (setq pos (1+ pos))) (setq n (1- n))) (delete-char (- pos start) killflag))) commit 7faea4a15ead8307f59b055cfecba0928a9110c8 Author: Jim Porter Date: Sun Jun 26 18:27:20 2022 +0200 When closing an Eshell process target, send EOF three times * lisp/eshell/esh-io.el (eshell-close-target): Send EOF 3 times. * test/lisp/eshell/em-extpipe-tests.el (em-extpipe-tests--deftest): Re-enable these tests on EMBA. This patch is adapted by one from Ken Brown, who uncovered the reason for this bug (bug#56025). diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el index 3644c1a18b..c035890ddf 100644 --- a/lisp/eshell/esh-io.el +++ b/lisp/eshell/esh-io.el @@ -276,8 +276,20 @@ STATUS should be non-nil on successful termination of the output." ;; If we're redirecting to a process (via a pipe, or process ;; redirection), send it EOF so that it knows we're finished. ((eshell-processp target) - (if (eq (process-status target) 'run) - (process-send-eof target))) + ;; According to POSIX.1-2017, section 11.1.9, sending EOF causes + ;; all bytes waiting to be read to be sent to the process + ;; immediately. Thus, if there are any bytes waiting, we need to + ;; send EOF twice: once to flush the buffer, and a second time to + ;; cause the next read() to return a size of 0, indicating + ;; end-of-file to the reading process. However, some platforms + ;; (e.g. Solaris) actually require sending a *third* EOF. Since + ;; sending extra EOFs while the process is running shouldn't break + ;; anything, we'll just send the maximum we'd ever need. See + ;; bug#56025 for further details. + (let ((i 0)) + (while (and (<= (cl-incf i) 3) + (eq (process-status target) 'run)) + (process-send-eof target)))) ;; A plain function redirection needs no additional arguments ;; passed. diff --git a/test/lisp/eshell/em-extpipe-tests.el b/test/lisp/eshell/em-extpipe-tests.el index 3b84d763ac..29f5dc0551 100644 --- a/test/lisp/eshell/em-extpipe-tests.el +++ b/test/lisp/eshell/em-extpipe-tests.el @@ -71,7 +71,6 @@ (skip-unless shell-file-name) (skip-unless shell-command-switch) (skip-unless (executable-find shell-file-name)) - (skip-unless (not (getenv "EMACS_EMBA_CI"))) (let ((input ,input)) (with-temp-eshell ,@body))))) commit 51f24fe2f418f2b7c4fa6732384bdd198f67f24f Author: Kjartan Óli Ágústsson Date: Sun Jun 26 17:52:29 2022 +0200 Reconvert EPUB buffers when user CSS is changed * lisp/doc-view.el (doc-view-epub-user-stylesheet): Add `doc-view-custom-set-mutool-user-stylesheet' as setter, change name. (doc-view-custom-set-epub-font-size): Factor reconvert logic out (doc-view--epub-reconvert): Add defun (doc-view--epub-stylesheet-watcher): Add defvar (doc-view-custom-set-epub-user-stylesheet): Add defun (bug#55825). diff --git a/lisp/doc-view.el b/lisp/doc-view.el index c167ead1c8..63be1b16f3 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -144,6 +144,7 @@ (require 'dired) (require 'image-mode) (require 'jka-compr) +(require 'filenotify) (eval-when-compile (require 'subr-x)) ;;;; Customization Options @@ -226,17 +227,49 @@ are available (see Info node `(emacs)Document View')" Higher values result in larger images." :type 'number) -(defcustom doc-view-mutool-user-stylesheet nil - "User stylesheet to use when converting EPUB documents to PDF." - :type '(choice (const nil) - (file :must-match t)) - :version "29.1") - (defvar doc-view-doc-type nil "The type of document in the current buffer. Can be `dvi', `pdf', `ps', `djvu', `odf', `epub', `cbz', `fb2', `xps' or `oxps'.") +(defvar doc-view--epub-stylesheet-watcher nil + "File watcher for `doc-view-epub-user-stylesheet'.") + +(defun doc-view--epub-reconvert (&optional _event) + "Reconvert all epub buffers. + +EVENT is unused, but neccesary to work with the filenotify API" + (dolist (x (buffer-list)) + (with-current-buffer x + (when (eq doc-view-doc-type 'epub) + (doc-view-reconvert-doc))))) + +(defun doc-view-custom-set-epub-user-stylesheet (option-name new-value) + "Setter for `doc-view-epub-user-stylesheet'. + +Reconverts existing epub buffers when the file used as a user +stylesheet is switched, or its contents modified." + (set-default option-name new-value) + (file-notify-rm-watch doc-view--epub-stylesheet-watcher) + (doc-view--epub-reconvert) + (setq doc-view--epub-stylesheet-watcher + (when new-value + (file-notify-add-watch new-value '(change) #'doc-view--epub-reconvert)))) + +(defcustom doc-view-epub-user-stylesheet nil + "User stylesheet to use when converting EPUB documents to PDF." + :type '(choice (const nil) + (file :must-match t)) + :version "29.1" + :set #'doc-view-custom-set-epub-user-stylesheet) + +(defvar-local doc-view--current-cache-dir nil + "Only used internally.") + +(defun doc-view-custom-set-epub-font-size (option-name new-value) + (set-default option-name new-value) + (doc-view--epub-reconvert)) + ;; FIXME: The doc-view-current-* definitions below are macros because they ;; map to accessors which we want to use via `setf' as well! (defmacro doc-view-current-page (&optional win) @@ -249,15 +282,6 @@ Can be `dvi', `pdf', `ps', `djvu', `odf', `epub', `cbz', `fb2', (defvar-local doc-view--current-cache-dir nil "Only used internally.") -(defun doc-view-custom-set-epub-font-size (option-name new-value) - (set-default option-name new-value) - (dolist (x (buffer-list)) - (with-current-buffer x - (when (eq doc-view-doc-type 'epub) - (delete-directory doc-view--current-cache-dir t) - (doc-view-initiate-display) - (doc-view-goto-page (doc-view-current-page)))))) - (defcustom doc-view-epub-font-size nil "Font size in points for EPUB layout." :type '(choice (const nil) integer) @@ -1178,12 +1202,12 @@ The test is performed using `doc-view-pdfdraw-program'." (when doc-view-epub-font-size (setq options (append options (list (format "-S%s" doc-view-epub-font-size))))) - (when doc-view-mutool-user-stylesheet + (when doc-view-epub-user-stylesheet (setq options (append options (list (format "-U%s" (expand-file-name - doc-view-mutool-user-stylesheet))))))) + doc-view-epub-user-stylesheet))))))) (doc-view-start-process "pdf->png" doc-view-pdfdraw-program `(,@(doc-view-pdfdraw-program-subcommand) commit 9e08c04798e994abc929f52e15b9ecb7e0ad53be Author: Visuwesh Date: Sun Jun 26 17:45:45 2022 +0200 Make in mode line more careful as well * lisp/mouse.el (mouse-delete-other-windows): Only delete other windows if the user didn't move the cursor off the mode-line (bug#56198). diff --git a/lisp/mouse.el b/lisp/mouse.el index 3b33ba817b..98e49c3598 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -687,10 +687,13 @@ This command must be bound to a mouse click." (switch-to-buffer buf) (delete-window window))) -(defun mouse-delete-other-windows () +(defun mouse-delete-other-windows (click) "Delete all windows except the one you click on." - (interactive "@") - (delete-other-windows)) + (interactive "e") + (when (and (eq (posn-area (event-end click)) 'mode-line) + (eq (posn-window (event-start click)) + (posn-window (event-end click)))) + (delete-other-windows (posn-window (event-start click))))) (defun mouse-split-window-vertically (click) "Select Emacs window mouse is on, then split it vertically in half. commit cd6ce7e546e6d2ed1918a1d20341c1e4c9050a9a Author: Visuwesh Date: Sun Jun 26 17:30:04 2022 +0200 Make in the mode line more careful * lisp/mouse.el (mouse-delete-window): Only delete the window if the user hasn't moved point out of the mode line before releasing the button (bug#56198). diff --git a/lisp/mouse.el b/lisp/mouse.el index 82c8a14693..3b33ba817b 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -655,7 +655,13 @@ This command must be bound to a mouse click." (interactive "e") (unless (one-window-p t) (mouse-minibuffer-check click) - (delete-window (posn-window (event-start click))))) + ;; Only delete the window if the user hasn't moved point out of + ;; the mode line before releasing the button. + (when (and (eq (posn-area (event-end click)) + 'mode-line) + (eq (posn-window (event-end click)) + (posn-window (event-start click)))) + (delete-window (posn-window (event-start click)))))) (defun mouse-select-window (click) "Select the window clicked on; don't move point." commit 7fc3f1b0d14ad390ca361a40ecf02eaa9f1b202a Author: Jim Porter Date: Sat Jun 25 18:19:01 2022 -0700 Make Eshell globs ending in "/" match directories only * lisp/eshell/em-glob.el (eshell-glob-convert): Return whether to match directories only. (eshell-glob-entries): Add ONLY-DIRS argument. * test/lisp/eshell/em-glob-tests.el (em-glob-test/match-any-directory): New test. (em-glob-test/match-recursive) (em-glob-test/match-recursive-follow-symlinks): Add test cases for when "**/" or "***/" are the last components in a glob. * etc/NEWS: Announce this change (bug#56227). diff --git a/etc/NEWS b/etc/NEWS index 4e091e5a14..c85e8e0256 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1849,6 +1849,12 @@ values passed as a single token, such as '-oVALUE' or 'eshell-eval-using-options' macro. See "Defining new built-in commands" in the "(eshell) Built-ins" node of the Eshell manual. +--- +*** Eshell globs ending with '/' now match only directories. +Additionally, globs ending with '**/' or '***/' no longer raise an +error, and now expand to all directories recursively (following +symlinks in the latter case). + ** Shell --- diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el index 8acdaee233..58b7a83c09 100644 --- a/lisp/eshell/em-glob.el +++ b/lisp/eshell/em-glob.el @@ -273,17 +273,23 @@ include, and the second for ones to exclude." (defun eshell-glob-convert (glob) "Convert an Eshell glob-pattern GLOB to regexps. -The result is a list, where the first element is the base -directory to search in, and the second is a list containing -elements of the following forms: +The result is a list of three elements: -* Regexp pairs as generated by `eshell-glob-convert-1'. +1. The base directory to search in. -* `recurse', indicating that searches should recurse into - subdirectories. +2. A list containing elements of the following forms: -* `recurse-symlink', like `recurse', but also following symlinks." + * Regexp pairs as generated by `eshell-glob-convert-1'. + + * `recurse', indicating that searches should recurse into + subdirectories. + + * `recurse-symlink', like `recurse', but also following + symlinks. + +3. A boolean indicating whether to match directories only." (let ((globs (eshell-split-path glob)) + (isdir (eq (aref glob (1- (length glob))) ?/)) start-dir result last-saw-recursion) (if (and (cdr globs) (file-name-absolute-p (car globs))) @@ -302,7 +308,8 @@ elements of the following forms: (setq last-saw-recursion nil)) (setq globs (cdr globs))) (list (file-name-as-directory start-dir) - (nreverse result)))) + (nreverse result) + isdir))) (defun eshell-extended-glob (glob) "Return a list of files matched by GLOB. @@ -331,17 +338,21 @@ regular expressions, and these cannot support the above constructs." glob)))) ;; FIXME does this really need to abuse eshell-glob-matches, message-shown? -(defun eshell-glob-entries (path globs) +(defun eshell-glob-entries (path globs only-dirs) "Match the entries in PATH against GLOBS. GLOBS is a list of globs as converted by `eshell-glob-convert', -which see." +which see. + +If ONLY-DIRS is non-nil, only match directories; otherwise, match +directories and files." (let* ((entries (ignore-errors (file-name-all-completions "" path))) (case-fold-search eshell-glob-case-insensitive) glob glob-remainder recurse-p) (if (rassq (car globs) eshell-glob-recursive-alist) (setq recurse-p (car globs) - glob (cadr globs) + glob (or (cadr globs) + (eshell-glob-convert-1 "*" t)) glob-remainder (cddr globs)) (setq glob (car globs) glob-remainder (cdr globs))) @@ -363,7 +374,13 @@ which see." (if glob-remainder (when isdir (push (concat path name) dirs)) - (push (concat path name) eshell-glob-matches))) + (when (or (not only-dirs) + (and isdir + (not (and (eq recurse-p 'recurse) + (file-symlink-p + (directory-file-name + (concat path name))))))) + (push (concat path name) eshell-glob-matches)))) (when (and recurse-p isdir (not (member name '("./" "../"))) (setq pathname (concat path name)) @@ -372,9 +389,9 @@ which see." (directory-file-name pathname))))) (push pathname rdirs)))) (dolist (dir (nreverse dirs)) - (eshell-glob-entries dir glob-remainder)) + (eshell-glob-entries dir glob-remainder only-dirs)) (dolist (rdir (nreverse rdirs)) - (eshell-glob-entries rdir globs))))) + (eshell-glob-entries rdir globs only-dirs))))) (provide 'em-glob) diff --git a/test/lisp/eshell/em-glob-tests.el b/test/lisp/eshell/em-glob-tests.el index 65f340a8da..b733be35d9 100644 --- a/test/lisp/eshell/em-glob-tests.el +++ b/test/lisp/eshell/em-glob-tests.el @@ -60,6 +60,12 @@ component ending in \"symlink\" is treated as a symbolic link." (should (equal (eshell-extended-glob "*.el") '("a.el" "b.el"))))) +(ert-deftest em-glob-test/match-any-directory () + "Test that \"*/\" pattern matches any directory." + (with-fake-files '("a.el" "b.el" "dir/a.el" "dir/sub/a.el" "symlink/") + (should (equal (eshell-extended-glob "*/") + '("dir/" "symlink/"))))) + (ert-deftest em-glob-test/match-any-character () "Test that \"?\" pattern matches any character." (with-fake-files '("a.el" "b.el" "ccc.el" "d.txt" "dir/a.el") @@ -71,7 +77,9 @@ component ending in \"symlink\" is treated as a symbolic link." (with-fake-files '("a.el" "b.el" "ccc.el" "d.txt" "dir/a.el" "dir/sub/a.el" "dir/symlink/a.el" "symlink/a.el" "symlink/sub/a.el") (should (equal (eshell-extended-glob "**/a.el") - '("a.el" "dir/a.el" "dir/sub/a.el"))))) + '("a.el" "dir/a.el" "dir/sub/a.el"))) + (should (equal (eshell-extended-glob "**/") + '("dir/" "dir/sub/"))))) (ert-deftest em-glob-test/match-recursive-follow-symlinks () "Test that \"***/\" recursively matches directories, following symlinks." @@ -79,7 +87,10 @@ component ending in \"symlink\" is treated as a symbolic link." "dir/symlink/a.el" "symlink/a.el" "symlink/sub/a.el") (should (equal (eshell-extended-glob "***/a.el") '("a.el" "dir/a.el" "dir/sub/a.el" "dir/symlink/a.el" - "symlink/a.el" "symlink/sub/a.el"))))) + "symlink/a.el" "symlink/sub/a.el"))) + (should (equal (eshell-extended-glob "***/") + '("dir/" "dir/sub/" "dir/symlink/" "symlink/" + "symlink/sub/"))))) (ert-deftest em-glob-test/match-recursive-mixed () "Test combination of \"**/\" and \"***/\"." commit ea3681575f24ab6766931d0c86f080c52f2ce2d7 Author: Jim Porter Date: Fri Jun 24 08:39:42 2022 -0700 Convert Eshell globs ahead of time instead of doing it repeatedly * lisp/eshell/em-glob.el (eshell-glob-recursive): New variable. (eshell-glob-convert-1, eshell-glob-convert): New functions. (eshell-extended-glob): Use 'eshell-glob-convert'. (eshell-glob-entries): Adapt function to use pre-converted globs. * test/lisp/eshell-em-glob-tests.el (em-glob-test/match-dot-files): New test. diff --git a/lisp/eshell/em-glob.el b/lisp/eshell/em-glob.el index 52531ff893..8acdaee233 100644 --- a/lisp/eshell/em-glob.el +++ b/lisp/eshell/em-glob.el @@ -183,6 +183,10 @@ interpretation." (defvar eshell-glob-matches) (defvar message-shown) +(defvar eshell-glob-recursive-alist + '(("**/" . recurse) + ("***/" . recurse-symlink))) + (defun eshell-glob-regexp (pattern) "Convert glob-pattern PATTERN to a regular expression. The basic syntax is: @@ -232,6 +236,74 @@ resulting regular expression." (regexp-quote (substring pattern matched-in-pattern)) "\\'"))) +(defun eshell-glob-convert-1 (glob &optional last) + "Convert a GLOB matching a single element of a file name to regexps. +If LAST is non-nil, this glob is the last element of a file name. + +The result is a pair of regexps, the first for file names to +include, and the second for ones to exclude." + (let ((len (length glob)) (index 1) (incl glob) excl) + ;; We can't use `directory-file-name' because it strips away text + ;; properties in the string. + (let ((last (1- (length incl)))) + (when (eq (aref incl last) ?/) + (setq incl (substring incl 0 last)))) + ;; Split the glob if it contains a negation like x~y. + (while (and (eq incl glob) + (setq index (string-search "~" glob index))) + (if (or (get-text-property index 'escaped glob) + (or (= (1+ index) len))) + (setq index (1+ index)) + (setq incl (substring glob 0 index) + excl (substring glob (1+ index))))) + (setq incl (eshell-glob-regexp incl) + excl (and excl (eshell-glob-regexp excl))) + ;; Exclude dot files if requested. + (if (or eshell-glob-include-dot-files + (eq (aref glob 0) ?.)) + (unless (or eshell-glob-include-dot-dot + (not last)) + (setq excl (if excl + (concat "\\(\\`\\.\\.?\\'\\|" excl "\\)") + "\\`\\.\\.?\\'"))) + (setq excl (if excl + (concat "\\(\\`\\.\\|" excl "\\)") + "\\`\\."))) + (cons incl excl))) + +(defun eshell-glob-convert (glob) + "Convert an Eshell glob-pattern GLOB to regexps. +The result is a list, where the first element is the base +directory to search in, and the second is a list containing +elements of the following forms: + +* Regexp pairs as generated by `eshell-glob-convert-1'. + +* `recurse', indicating that searches should recurse into + subdirectories. + +* `recurse-symlink', like `recurse', but also following symlinks." + (let ((globs (eshell-split-path glob)) + start-dir result last-saw-recursion) + (if (and (cdr globs) + (file-name-absolute-p (car globs))) + (setq start-dir (car globs) + globs (cdr globs)) + (setq start-dir ".")) + (while globs + (if-let ((recurse (cdr (assoc (car globs) + eshell-glob-recursive-alist)))) + (if last-saw-recursion + (setcar result recurse) + (push recurse result) + (setq last-saw-recursion t)) + (push (eshell-glob-convert-1 (car globs) (null (cdr globs))) + result) + (setq last-saw-recursion nil)) + (setq globs (cdr globs))) + (list (file-name-as-directory start-dir) + (nreverse result)))) + (defun eshell-extended-glob (glob) "Return a list of files matched by GLOB. If no files match, signal an error (if `eshell-error-if-no-glob' @@ -247,14 +319,10 @@ syntax. Things that are not supported are: Mainly they are not supported because file matching is done with Emacs regular expressions, and these cannot support the above constructs." - (let ((paths (eshell-split-path glob)) + (let ((globs (eshell-glob-convert glob)) eshell-glob-matches message-shown) (unwind-protect - (if (and (cdr paths) - (file-name-absolute-p (car paths))) - (eshell-glob-entries (file-name-as-directory (car paths)) - (cdr paths)) - (eshell-glob-entries (file-name-as-directory ".") paths)) + (apply #'eshell-glob-entries globs) (if message-shown (message nil))) (or (and eshell-glob-matches (sort eshell-glob-matches #'string<)) @@ -263,94 +331,50 @@ regular expressions, and these cannot support the above constructs." glob)))) ;; FIXME does this really need to abuse eshell-glob-matches, message-shown? -(defun eshell-glob-entries (path globs &optional recurse-p) - "Glob the entries in PATH, possibly recursing if RECURSE-P is non-nil." +(defun eshell-glob-entries (path globs) + "Match the entries in PATH against GLOBS. +GLOBS is a list of globs as converted by `eshell-glob-convert', +which see." (let* ((entries (ignore-errors - (file-name-all-completions "" path))) - (case-fold-search eshell-glob-case-insensitive) - (glob (car globs)) - (len (length glob)) - dirs rdirs - incl excl - name isdir pathname) - (while (cond - ((and (= len 3) (equal glob "**/")) - (setq recurse-p 2 - globs (cdr globs) - glob (car globs) - len (length glob))) - ((and (= len 4) (equal glob "***/")) - (setq recurse-p 3 - globs (cdr globs) - glob (car globs) - len (length glob))))) - (if (and recurse-p (not glob)) - (error "`**/' cannot end a globbing pattern")) - (let ((index 1)) - (setq incl glob) - (while (and (eq incl glob) - (setq index (string-search "~" glob index))) - (if (or (get-text-property index 'escaped glob) - (or (= (1+ index) len))) - (setq index (1+ index)) - (setq incl (substring glob 0 index) - excl (substring glob (1+ index)))))) - ;; can't use `directory-file-name' because it strips away text - ;; properties in the string - (let ((len (1- (length incl)))) - (if (eq (aref incl len) ?/) - (setq incl (substring incl 0 len))) - (when excl - (setq len (1- (length excl))) - (if (eq (aref excl len) ?/) - (setq excl (substring excl 0 len))))) - (setq incl (eshell-glob-regexp incl) - excl (and excl (eshell-glob-regexp excl))) - (if (or eshell-glob-include-dot-files - (eq (aref glob 0) ?.)) - (unless (or eshell-glob-include-dot-dot - (cdr globs)) - (setq excl (if excl - (concat "\\(\\`\\.\\.?\\'\\|" excl "\\)") - "\\`\\.\\.?\\'"))) - (setq excl (if excl - (concat "\\(\\`\\.\\|" excl "\\)") - "\\`\\."))) + (file-name-all-completions "" path))) + (case-fold-search eshell-glob-case-insensitive) + glob glob-remainder recurse-p) + (if (rassq (car globs) eshell-glob-recursive-alist) + (setq recurse-p (car globs) + glob (cadr globs) + glob-remainder (cddr globs)) + (setq glob (car globs) + glob-remainder (cdr globs))) (when (and recurse-p eshell-glob-show-progress) (message "Building file list...%d so far: %s" - (length eshell-glob-matches) path) + (length eshell-glob-matches) path) (setq message-shown t)) - (if (equal path "./") (setq path "")) - (while entries - (setq name (car entries) - len (length name) - isdir (eq (aref name (1- len)) ?/)) - (if (let ((fname (directory-file-name name))) - (and (not (and excl (string-match excl fname))) - (string-match incl fname))) - (if (cdr globs) - (if isdir - (setq dirs (cons (concat path name) dirs))) - (setq eshell-glob-matches - (cons (concat path name) eshell-glob-matches)))) - (if (and recurse-p isdir - (or (> len 3) - (not (or (and (= len 2) (equal name "./")) - (and (= len 3) (equal name "../"))))) - (setq pathname (concat path name)) - (not (and (= recurse-p 2) - (file-symlink-p - (directory-file-name pathname))))) - (setq rdirs (cons pathname rdirs))) - (setq entries (cdr entries))) - (setq dirs (nreverse dirs) - rdirs (nreverse rdirs)) - (while dirs - (eshell-glob-entries (car dirs) (cdr globs)) - (setq dirs (cdr dirs))) - (while rdirs - (eshell-glob-entries (car rdirs) globs recurse-p) - (setq rdirs (cdr rdirs))))) + (when (equal path "./") (setq path "")) + (let ((incl (car glob)) + (excl (cdr glob)) + dirs rdirs) + (dolist (name entries) + (let* ((len (length name)) + (isdir (eq (aref name (1- len)) ?/)) + pathname) + (when (let ((fname (directory-file-name name))) + (and (not (and excl (string-match excl fname))) + (string-match incl fname))) + (if glob-remainder + (when isdir + (push (concat path name) dirs)) + (push (concat path name) eshell-glob-matches))) + (when (and recurse-p isdir + (not (member name '("./" "../"))) + (setq pathname (concat path name)) + (not (and (eq recurse-p 'recurse) + (file-symlink-p + (directory-file-name pathname))))) + (push pathname rdirs)))) + (dolist (dir (nreverse dirs)) + (eshell-glob-entries dir glob-remainder)) + (dolist (rdir (nreverse rdirs)) + (eshell-glob-entries rdir globs))))) (provide 'em-glob) diff --git a/test/lisp/eshell/em-glob-tests.el b/test/lisp/eshell/em-glob-tests.el index 9976b32ffe..65f340a8da 100644 --- a/test/lisp/eshell/em-glob-tests.el +++ b/test/lisp/eshell/em-glob-tests.el @@ -160,6 +160,21 @@ component ending in \"symlink\" is treated as a symbolic link." (should (equal (eshell-extended-glob "[[:digit:]]##~4?") '("1" "12" "123"))))) +(ert-deftest em-glob-test/match-dot-files () + "Test that dot files are matched correctly." + (with-fake-files '("foo.el" ".emacs") + (should (equal (eshell-extended-glob ".*") + '("../" "./" ".emacs"))) + (let (eshell-glob-include-dot-dot) + (should (equal (eshell-extended-glob ".*") + '(".emacs")))) + (let ((eshell-glob-include-dot-files t)) + (should (equal (eshell-extended-glob "*") + '("../" "./" ".emacs" "foo.el"))) + (let (eshell-glob-include-dot-dot) + (should (equal (eshell-extended-glob "*") + '(".emacs" "foo.el"))))))) + (ert-deftest em-glob-test/no-matches () "Test behavior when a glob fails to match any files." (with-fake-files '("foo.el" "bar.el") commit 598d7c5d1c10bfb161cb53aa76d480864414487c Author: Jim Porter Date: Sat Jun 25 20:05:57 2022 -0700 Optionally signal an error if an Eshell predicate fails to match anything * lisp/eshell/em-pred.el (eshell-error-if-no-glob): Declare it. (eshell-apply-modifiers): Add STRING-DESC argument and signal an error if there are no matches and 'eshell-error-if-no-glob' is set. (eshell-parse-arg-modifier): Pass modifier string to 'eshell-apply-modifiers'. * test/lisp/eshell/em-pred-tests.el (eshell-eval-predicate): Simplify. (em-pred-test/no-matches): New test. * doc/misc/eshell.texi (Bugs and ideas): Remove todo entry about this change. diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index 85e5a4933f..2e3ba4c273 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -1902,11 +1902,6 @@ glob match. At the moment, this is not supported. -@item Error if a glob doesn't expand due to a predicate - -An error should be generated only if @code{eshell-error-if-no-glob} is -non-@code{nil}. - @item @samp{(+ @key{RET} @key{SPC} @key{TAB}} does not cause @code{indent-according-to-mode} to occur @item Create @code{eshell-auto-accumulate-list} diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el index d73976d346..b4ef154f8c 100644 --- a/lisp/eshell/em-pred.el +++ b/lisp/eshell/em-pred.el @@ -233,6 +233,8 @@ Each element is of the form (OPEN . CLOSE), where OPEN and CLOSE are characters representing the opening and closing delimiter, respectively.") +(defvar eshell-error-if-no-glob) ; Defined in em-glob.el. + (defvar-keymap eshell-pred-mode-map "C-c M-q" #'eshell-display-predicate-help "C-c M-m" #'eshell-display-modifier-help) @@ -263,14 +265,19 @@ respectively.") #'eshell-parse-arg-modifier t t) (eshell-pred-mode)) -(defun eshell-apply-modifiers (lst predicates modifiers) - "Apply to list LST a series of PREDICATES and MODIFIERS." +(defun eshell-apply-modifiers (lst predicates modifiers string-desc) + "Apply to list LST a series of PREDICATES and MODIFIERS. +STRING-DESC is the original string defining these predicates and +modifiers." (let (stringified) (if (stringp lst) (setq lst (list lst) stringified t)) (when (listp lst) - (setq lst (eshell-winnow-list lst nil predicates)) + (when lst + (setq lst (or (eshell-winnow-list lst nil predicates) + (when eshell-error-if-no-glob + (error "No matches found: (%s)" string-desc))))) (while modifiers (setq lst (funcall (car modifiers) lst) modifiers (cdr modifiers))) @@ -290,7 +297,8 @@ This function is specially for adding onto `eshell-parse-argument-hook'." (when (eshell-arg-delimiter (1+ end)) (save-restriction (narrow-to-region (point) end) - (let* ((modifiers (eshell-parse-modifiers)) + (let* ((modifier-string (buffer-string)) + (modifiers (eshell-parse-modifiers)) (preds (car modifiers)) (mods (cdr modifiers))) (if (or preds mods) @@ -302,7 +310,7 @@ This function is specially for adding onto `eshell-parse-argument-hook'." (list (lambda (lst) (eshell-apply-modifiers - lst preds mods)))))))) + lst preds mods modifier-string)))))))) (goto-char (1+ end)) (eshell-finish-arg)))))) diff --git a/test/lisp/eshell/em-pred-tests.el b/test/lisp/eshell/em-pred-tests.el index 3b50543d69..c8c1a6a931 100644 --- a/test/lisp/eshell/em-pred-tests.el +++ b/test/lisp/eshell/em-pred-tests.el @@ -26,6 +26,7 @@ (require 'ert) (require 'esh-mode) (require 'eshell) +(require 'em-glob) (require 'em-pred) (require 'eshell-tests-helpers @@ -39,10 +40,9 @@ "Evaluate PREDICATE on INITIAL-VALUE, returning the result. PREDICATE is an Eshell argument predicate/modifier." (let ((eshell-test-value initial-value)) - (with-temp-eshell - (eshell-insert-command - (format "setq eshell-test-value $eshell-test-value(%s)" predicate))) - eshell-test-value)) + (ignore-errors + (eshell-test-command-result + (format "echo $eshell-test-value(%s)" predicate))))) (defun eshell-parse-file-name-attributes (file) "Parse a fake FILE name to determine its attributes. @@ -545,4 +545,22 @@ PREDICATE is the predicate used to query that attribute." (should (equal (eshell-eval-predicate '("foo" "bar" "baz") ":j'\\\"'") "foo\\\"bar\\\"baz"))) +(ert-deftest em-pred-test/no-matches () + "Test behavior when a predicate fails to match any files." + (eshell-with-file-attributes-from-name + (let ((files '("/fake/modes=0666" "/fake/type=d,modes=0777" + "/fake/type=l,modes=0777"))) + (should (equal (eshell-eval-predicate files "*") nil)) + (let ((eshell-error-if-no-glob t)) + ;; Don't signal an error if the original list is empty. + (should (equal (eshell-eval-predicate nil "*") nil)) + ;; Ensure this signals an error. This test case is a bit + ;; clumsy, since `eshell-do-eval' makes it hard to catch + ;; errors otherwise. + (let ((modifiers (with-temp-eshell + (eshell-with-temp-command "*" + (eshell-parse-modifiers))))) + (should-error (eshell-apply-modifiers files (car modifiers) + (cdr modifiers) "*"))))))) + ;; em-pred-tests.el ends here commit b637d9c0750fde8810058a153d964b6c70e0f577 Author: Daniel Martín Date: Sun Jun 26 12:27:55 2022 +0200 Fix typo in signal-process-functions * doc/lispref/processes.texi (Signals to Processes): Update reference to correct default variable in the ELisp manual. * etc/NEWS: The same for the NEWS entry (bug#56234). diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 9e0bd98a54..14856b9e05 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -1512,7 +1512,7 @@ This variable is a list of functions to be called for for @code{signal-process}. These functions are called in the order of the list, until one of them returns non-@code{nil}. The default function, which shall always be the last in this list, is -@code{signal-default-interrupt-process}. +@code{internal-default-signal-process}. This is the mechanism, how Tramp implements @code{signal-process}. @end defvar diff --git a/etc/NEWS b/etc/NEWS index 01354a65f0..4e091e5a14 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2880,7 +2880,7 @@ invocation. Such shells are POSIX conformant by default. This is to determine which function has to be called in order to deliver the signal. This allows Tramp to send the signal to remote asynchronous processes. The hitherto existing implementation has been -moved to 'signal-default-interrupt-process'. +moved to 'internal-default-signal-process'. +++ ** 'list-system-processes' now returns remote process IDs. commit e12f5ca9a5be854f0b57fea1a5dfc3b75549f283 Author: Lars Ingebrigtsen Date: Sun Jun 26 16:45:09 2022 +0200 Update term-char-mode doc string * lisp/term.el (term-char-mode): Update doc string. diff --git a/lisp/term.el b/lisp/term.el index a8e44b4c34..3bf1531fcd 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -1445,10 +1445,7 @@ Entry to this mode runs the hooks on `term-mode-hook'." (defun term-char-mode () "Switch to char (\"raw\") sub-mode of term mode. Each character you type is sent directly to the inferior without -intervention from Emacs, except for the escape character (usually C-c). - -This command will send existing partial lines to the terminal -process." +intervention from Emacs, except for the escape character (usually C-c)." (interactive) ;; FIXME: Emit message? Cfr ilisp-raw-message (when (term-in-line-mode) commit edf6f5d0cae97de10c914c6e94dc5b35f06ec33c Author: Michael Heerdegen Date: Tue Jun 21 13:41:51 2022 +0200 Fix Bug#56110 (switching from line-mode to char-mode) * lisp/term.el (term-char-mode): Make `add-function' override the correct place (the buffer local variable `term-input-sender'). diff --git a/lisp/term.el b/lisp/term.el index 94bf13e973..a8e44b4c34 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -1467,10 +1467,10 @@ process." (when (> (point) pmark) (unwind-protect (progn - (add-function :override term-input-sender #'term-send-string) + (add-function :override (local 'term-input-sender) #'term-send-string) (end-of-line) (term-send-input)) - (remove-function term-input-sender #'term-send-string)))) + (remove-function (local 'term-input-sender) #'term-send-string)))) (term-update-mode-line))) (defun term-line-mode () commit 8f5d9d0abd0f5078646bc85c7a4d480b32057a47 Author: Lars Ingebrigtsen Date: Sun Jun 26 16:31:33 2022 +0200 Fix a recent Lisp mode filling test failure * lisp/emacs-lisp/lisp-mode.el (lisp-fill-paragraph): Restore the "fill first line separately" logic. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 781c80fd5a..6d5391d1e9 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -1426,6 +1426,9 @@ and initial semicolons." ;; a comment: Point is on a program line; we are interested ;; particularly in docstring lines. ;; + ;; FIXME: The below bindings are probably mostly irrelevant + ;; since we're now narrowing to a region before filling. + ;; ;; We bind `paragraph-start' and `paragraph-separate' temporarily. They ;; are buffer-local, but we avoid changing them so that they can be set ;; to make `forward-paragraph' and friends do something the user wants. @@ -1485,6 +1488,15 @@ and initial semicolons." (1- (point))))) ;; Move back to where we were. (goto-char start) + ;; We should fill the first line of a string + ;; separately (since it's usually a doc string). + (if (= (line-number-at-pos) 1) + (narrow-to-region (line-beginning-position) + (line-beginning-position 2)) + (save-excursion + (goto-char (point-min)) + (forward-line 1) + (narrow-to-region (point) (point-max)))) (fill-paragraph justify))))))) ;; Never return nil. t) commit fd04009d167a620513fa948155c2e30040a142c2 Author: Paul Eggert Date: Sat Jun 25 14:51:28 2022 -0500 Port distribution tarball to Solaris 10 * make-dist (taropt): Use 'tar -H ustar' to generate a portable tar file format instead of a GNU-specific format. Needed now that Emacs tarballs contain file names longer than 100 bytes, e.g.: emacs-28.1/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C072AF82DCCCB9A7F1B85FFA10B802DC4ED16703.key emacs-28.1/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-success.el Without this patch, extracting a tarball on Solaris 10 fails with many diagnostics like “tar: ././@LongLink: typeflag 'L' not recognized, converting to regular file”. (cherry picked from commit 4410f5d86997b6b238ff05c2ece338b28e1163b1) diff --git a/make-dist b/make-dist index 447e90f018..67e49382d0 100755 --- a/make-dist +++ b/make-dist @@ -485,6 +485,8 @@ if [ "${make_tar}" = yes ]; then esac echo "Creating tar file" taropt='--numeric-owner --owner=0 --group=0 --mode=go+u,go-w' + tar -H ustar -cf /dev/null $tempdir/src/lisp.h 2>/dev/null && + taropt="$taropt -H ustar" tar --sort=name -cf /dev/null $tempdir/src/lisp.h 2>/dev/null && taropt="$taropt --sort=name" [ "$verbose" = "yes" ] && taropt="$taropt --verbose" commit 6a96d1773469e671a3d5710bedf68c21929b5183 Author: Stefan Monnier Date: Sun Jun 26 08:59:38 2022 -0400 * lisp/emacs-lisp/syntax.el: Rework the handling of nested calls. Nested calls to `syntax-ppss` and `syntax-propertize` can easily happen unexpectedly via ondemand propertizing or `forward-sexp`. Refine the handling of nested calls so we detect them more reliably (e.g. also within `syntax-propertize-extend-region-functions`) and so that the `syntax-ppss` cache is automatically flushed in case it might have been filled with data that's become obsolete since. (syntax-propertize--inhibit-flush): Delete var. (syntax-propertize--in-process-p): New function to replace it. (syntax-ppss-flush-cache): Use it. (syntax-ppss--updated-cache): New var. (syntax-propertize): Make `syntax-propertize--done` binding apply to `syntax-propertize-extend-region-functions` as well, as intended (fixes bug#46713). Use `syntax-ppss--updated-cache` to flush syntax-ppss cache at the end when needed. Don't bind `syntax-propertize--inhibit-flush` any more. (syntax-ppss): Set `syntax-ppss--updated-cache` when applicable. diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el index a4d7beade1..36b0c56e95 100644 --- a/lisp/emacs-lisp/syntax.el +++ b/lisp/emacs-lisp/syntax.el @@ -345,10 +345,16 @@ END) suitable for `syntax-propertize-function'." (defvar-local syntax-ppss-table nil "Syntax-table to use during `syntax-ppss', if any.") -(defvar-local syntax-propertize--inhibit-flush nil - "If non-nil, `syntax-ppss-flush-cache' only flushes the ppss cache. -Otherwise it flushes both the ppss cache and the properties -set by `syntax-propertize'") +(defun syntax-propertize--in-process-p () + "Non-nil if we're inside `syntax-propertize'. +This is used to avoid infinite recursion as well as to handle cases where +`syntax-ppss' is called when the final `syntax-table' properties have not +yet been setup, in which case we may end up putting invalid info into the cache. +It's also used so that `syntax-ppss-flush-cache' can be used from within +`syntax-propertize' without ruining the `syntax-table' already set." + (eq syntax-propertize--done most-positive-fixnum)) + +(defvar-local syntax-ppss--updated-cache nil) (defun syntax-propertize (pos) "Ensure that syntax-table properties are set until POS (a buffer point)." @@ -370,21 +376,24 @@ set by `syntax-propertize'") (with-silent-modifications (with-syntax-table (or syntax-ppss-table (syntax-table)) (make-local-variable 'syntax-propertize--done) ;Just in case! + ;; Make sure we let-bind it only buffer-locally. + (make-local-variable 'syntax-ppss--updated-cache) (let* ((start (max (min syntax-propertize--done (point-max)) (point-min))) (end (max pos (min (point-max) (+ start syntax-propertize-chunk-size)))) (first t) - (repeat t)) + (repeat t) + (syntax-ppss--updated-cache nil)) (while repeat (setq repeat nil) (run-hook-wrapped 'syntax-propertize-extend-region-functions (lambda (f) - (let ((new (funcall f start end)) - ;; Avoid recursion! - (syntax-propertize--done most-positive-fixnum)) + ;; Bind `syntax-propertize--done' to avoid recursion! + (let* ((syntax-propertize--done most-positive-fixnum) + (new (funcall f start end))) (if (or (null new) (and (>= (car new) start) (<= (cdr new) end))) nil @@ -399,20 +408,26 @@ set by `syntax-propertize'") ;; Flush ppss cache between the original value of `start' and that ;; set above by syntax-propertize-extend-region-functions. (syntax-ppss-flush-cache start) - ;; Move the limit before calling the function, so the function - ;; can use syntax-ppss. + ;; Move the limit before calling the function, so it's + ;; done in case of errors. (setq syntax-propertize--done end) ;; (message "syntax-propertizing from %s to %s" start end) (remove-text-properties start end '(syntax-table nil syntax-multiline nil)) - ;; Make sure we only let-bind it buffer-locally. - (make-local-variable 'syntax-propertize--inhibit-flush) - ;; Let-bind `syntax-propertize--done' to avoid infinite recursion! - (let ((syntax-propertize--done most-positive-fixnum) - ;; Let `syntax-propertize-function' call - ;; `syntax-ppss-flush-cache' without worries. - (syntax-propertize--inhibit-flush t)) - (funcall syntax-propertize-function start end))))))))) + ;; Bind `syntax-propertize--done' to avoid recursion! + (let ((syntax-propertize--done most-positive-fixnum)) + (funcall syntax-propertize-function start end) + (when syntax-ppss--updated-cache + ;; `syntax-ppss' was called and updated the cache while we + ;; were propertizing so we need to flush the part of the + ;; cache that may have been rendered out-of-date by the new + ;; properties. + ;; We used to require syntax-propertize-functions to do that + ;; manually when applicable, but nowadays the `syntax-ppss' + ;; cache can be updated by too many functions, so the author + ;; of the syntax-propertize-function may not be aware it + ;; can happen. + (syntax-ppss-flush-cache start)))))))))) ;;; Link syntax-propertize with syntax.c. @@ -487,10 +502,10 @@ These are valid when the buffer has no restriction.") (define-obsolete-function-alias 'syntax-ppss-after-change-function #'syntax-ppss-flush-cache "27.1") -(defun syntax-ppss-flush-cache (beg &rest ignored) +(defun syntax-ppss-flush-cache (beg &rest _ignored) "Flush the cache of `syntax-ppss' starting at position BEG." ;; Set syntax-propertize to refontify anything past beg. - (unless syntax-propertize--inhibit-flush + (unless (syntax-propertize--in-process-p) (setq syntax-propertize--done (min beg syntax-propertize--done))) ;; Flush invalid cache entries. (dolist (cell (list syntax-ppss-wide syntax-ppss-narrow)) @@ -517,10 +532,16 @@ These are valid when the buffer has no restriction.") (setcdr cell cache))) )) -;;; FIXME: Explain this variable. Currently only its last (5th) slot is used. -;;; Perhaps the other slots should be removed? +;; FIXME: Explain this variable. Currently only its last (5th) slot is used. +;; Perhaps the other slots should be removed? +;; This variable is only used when `syntax-begin-function' is used and +;; will hence be removed together with `syntax-begin-function'. (defvar syntax-ppss-stats - [(0 . 0) (0 . 0) (0 . 0) (0 . 0) (0 . 0) (2 . 2500)]) + [(0 . 0) (0 . 0) (0 . 0) (0 . 0) (0 . 0) (2 . 2500)] + "Statistics about which case is more/less frequent in `syntax-ppss'. +The 5th slot drives the heuristic to use `syntax-begin-function'. +The rest is only useful if you're interested in tweaking the algorithm.") + (defun syntax-ppss-stats () (mapcar (lambda (x) (condition-case nil @@ -658,6 +679,7 @@ running the hook." ;; populate the cache so we won't need to do it again soon. (t (syntax-ppss--update-stats 3 pt-min pos) + (setq syntax-ppss--updated-cache t) ;; If `pt-min' is too far, add a few intermediate entries. (while (> (- pos pt-min) (* 2 syntax-ppss-max-span)) @@ -692,6 +714,7 @@ running the hook." (push pair ppss-cache) (setcar ppss-cache pair))))))))) + (setq syntax-ppss--updated-cache t) (setq ppss-last (cons pos ppss)) (setcar cell ppss-last) (setcdr cell ppss-cache) commit 502e861af75e32152346f17f034c92a0550ccea3 Author: Lars Ingebrigtsen Date: Sat Jun 25 17:28:12 2022 +0200 Don't create HOME if it doesn't exist * lisp/files.el (locate-user-emacs-file): Don't create HOME if it doesn't exist (bug#47298). This returns us to Emacs 26.3 behaviour here. diff --git a/lisp/files.el b/lisp/files.el index a804f0088e..cc38f4e921 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -1115,10 +1115,17 @@ directory if it does not exist." (if (file-directory-p user-emacs-directory) (or (file-accessible-directory-p user-emacs-directory) (setq errtype "access")) - (with-file-modes ?\700 - (condition-case nil - (make-directory user-emacs-directory t) - (error (setq errtype "create"))))) + ;; We don't want to create HOME if it doesn't exist. + (if (and (not (file-exists-p "~")) + (string-prefix-p + (expand-file-name "~") + (expand-file-name user-emacs-directory))) + (setq errtype "create") + ;; Create `user-emacs-directory'. + (with-file-modes ?\700 + (condition-case nil + (make-directory user-emacs-directory t) + (error (setq errtype "create")))))) (when (and errtype user-emacs-directory-warning (not (get 'user-emacs-directory-warning 'this-session))) commit 0808da91e3c227d802baaeac66592ecca3e64c35 Author: Basil L. Contovounesios Date: Sun Jun 26 15:08:57 2022 +0300 ; Pacify unknown fun warning in mh-utils-tests.el. diff --git a/test/lisp/mh-e/mh-utils-tests.el b/test/lisp/mh-e/mh-utils-tests.el index 0708617259..72ee2fc474 100644 --- a/test/lisp/mh-e/mh-utils-tests.el +++ b/test/lisp/mh-e/mh-utils-tests.el @@ -48,8 +48,10 @@ ;;; Code: (require 'ert) -(eval-when-compile (require 'cl-lib)) (require 'mh-utils) +(eval-when-compile + (require 'cl-lib) + (require 'subr-x)) (ert-deftest mh-quote-pick-expr () "Test `mh-quote-pick-expr'." commit 05ee87d4233d0bbb64cf24af93d3d074a5d5a3eb Author: Po Lu Date: Sun Jun 26 18:14:17 2022 +0800 ; Minor cosmetics adjustment to xterm.c * src/xterm.c: Rename xIOErrorHandler & friends to "Emacs_XIOErrorHandler" so they don't look like X protocol header types. diff --git a/src/xterm.c b/src/xterm.c index 6afb2a3312..34fbbfb81c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -720,10 +720,10 @@ along with GNU Emacs. If not, see . */ #endif /* Although X11/Xlib.h commonly defines the types XErrorHandler and - XIOErrorHandler, they are not in the Xlib spec so for portability - define and use names with a leading lower-case 'x' instead. */ -typedef int (*xErrorHandler) (Display *, XErrorEvent *); -typedef int (*xIOErrorHandler) (Display *); + XIOErrorHandler, they are not in the Xlib spec, so for portability + define and use names with an Emacs_ prefix instead. */ +typedef int (*Emacs_XErrorHandler) (Display *, XErrorEvent *); +typedef int (*Emacs_XIOErrorHandler) (Display *); #if defined USE_XCB && defined USE_CAIRO_XCB #define USE_CAIRO_XCB_SURFACE @@ -1838,8 +1838,8 @@ xm_get_drag_window_1 (struct x_display_info *dpyinfo) Window drag_window; XSetWindowAttributes attrs; Display *temp_display; - xErrorHandler old_handler; - xIOErrorHandler old_io_handler; + Emacs_XErrorHandler old_handler; + Emacs_XIOErrorHandler old_io_handler; /* These are volatile because GCC mistakenly warns about them being clobbered by longjmp. */ @@ -23168,7 +23168,7 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) struct x_display_info *dpyinfo; Lisp_Object frame, tail; specpdl_ref idx = SPECPDL_INDEX (); - xIOErrorHandler io_error_handler; + Emacs_XIOErrorHandler io_error_handler; xm_drop_start_message dmsg; struct frame *f; commit 3b7d8dd3b3ee2b28ea5aa86e84f5a355698b29a8 Author: Michael Albinus Date: Sun Jun 26 10:57:00 2022 +0200 Fix narrowing problem in tramp-debug-buffer-command-completion-p * lisp/net/tramp.el (tramp-debug-buffer-command-completion-p): Respect narrowing. (Bug#56225) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index c6665c2792..9d5a02456e 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1955,7 +1955,8 @@ The outline level is equal to the verbosity of the Tramp message." "A predicate for Tramp interactive commands. They are completed by \"M-x TAB\" only in Tramp debug buffers." (with-current-buffer buffer - (string-equal (buffer-substring 1 (min 10 (point-max))) ";; Emacs:"))) + (string-equal + (buffer-substring (point-min) (min 10 (point-max))) ";; Emacs:"))) (put #'tramp-debug-buffer-command-completion-p 'tramp-suppress-trace t) commit a9d338818ae9ec789b90f1b3d5700d25fcdbbab6 Author: Allen Li Date: Sun Jun 26 00:37:07 2022 -0700 ; elec-pair: Fix docstring typo (bug#56233) * lisp/elec-pair.el (electric-pair-post-self-insert-function): Fix typo. diff --git a/lisp/elec-pair.el b/lisp/elec-pair.el index 964d21f11c..bbed955a39 100644 --- a/lisp/elec-pair.el +++ b/lisp/elec-pair.el @@ -498,7 +498,7 @@ The decision is taken by order of preference: corresponding delimiter for C; * According to C alone, by looking C up in the tables - `electric-pair-paris' or `electric-pair-text-pairs' (which + `electric-pair-pairs' or `electric-pair-text-pairs' (which see); * According to C's syntax and the syntactic state of the buffer commit a399eeac156ec782aca5e298d846a1ca905d2fdb Merge: f3b876fa75 afcec5f0a5 Author: Eli Zaretskii Date: Sun Jun 26 11:11:28 2022 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit afcec5f0a50665660d4a7bf8526b201101fa33e2 Author: Po Lu Date: Sun Jun 26 15:36:43 2022 +0800 Add some more common predefined atoms * src/xterm.c (x_intern_cached_atom, x_get_atom_name): Add DRAWABLE, BITMAP, COLORMAP, CURSOR and FONT. diff --git a/src/xterm.c b/src/xterm.c index 8aeaca230f..6afb2a3312 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -25631,11 +25631,26 @@ x_intern_cached_atom (struct x_display_info *dpyinfo, if (!strcmp (name, "ATOM")) return XA_ATOM; + if (!strcmp (name, "WINDOW")) + return XA_WINDOW; + + if (!strcmp (name, "DRAWABLE")) + return XA_DRAWABLE; + + if (!strcmp (name, "BITMAP")) + return XA_BITMAP; + if (!strcmp (name, "CARDINAL")) return XA_CARDINAL; - if (!strcmp (name, "WINDOW")) - return XA_WINDOW; + if (!strcmp (name, "COLORMAP")) + return XA_COLORMAP; + + if (!strcmp (name, "CURSOR")) + return XA_CURSOR; + + if (!strcmp (name, "FONT")) + return XA_FONT; if (dpyinfo->motif_drag_atom != None && !strcmp (name, dpyinfo->motif_drag_atom_name)) @@ -25698,6 +25713,18 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom, case XA_WINDOW: return xstrdup ("WINDOW"); + case XA_DRAWABLE: + return xstrdup ("DRAWABLE"); + + case XA_BITMAP: + return xstrdup ("BITMAP"); + + case XA_COLORMAP: + return xstrdup ("COLORMAP"); + + case XA_FONT: + return xstrdup ("FONT"); + default: if (dpyinfo->motif_drag_atom && atom == dpyinfo->motif_drag_atom) commit f3b876fa75042a1c00886e07d8491ac11824a892 Author: Eli Zaretskii Date: Sun Jun 26 10:22:20 2022 +0300 Fix ispell-word on colorless TTY frames * lisp/textmodes/ispell.el (ispell-highlight-spelling-error-generic): Keep marker position of END intact, deletion of text notwithstanding. (Bug#56219) diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index 1810d7bcae..8c8522a6e5 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -2615,15 +2615,18 @@ Optional REFRESH will unhighlighted then highlight, using block cursor (text (buffer-substring-no-properties start end)) ; Save highlight region. (inhibit-quit t) ; inhibit interrupt processing here. - (buffer-undo-list t)) ; don't clutter the undo list. + (buffer-undo-list t) ; don't clutter the undo list. + (end1 (if (markerp end) (marker-position end) end))) (goto-char end) (delete-region start end) - (insert-char ? (- end start)) ; minimize amount of redisplay + (insert-char ? (- end1 start)) ; minimize amount of redisplay (sit-for 0) ; update display (if highlight (setq inverse-video (not inverse-video))) ; toggle video - (delete-region start end) ; delete whitespace + (delete-region start end1) ; delete whitespace (insert text) ; insert text in inverse video. (sit-for 0) ; update display showing inverse video. + (if (markerp end) + (set-marker end end1)) ; restore marker position (if (not highlight) (goto-char end) (setq inverse-video (not inverse-video)) ; toggle video commit 1c4cd5e7d92ff0be14e07c02c2fd06eed81f3338 Author: Po Lu Date: Sun Jun 26 13:34:43 2022 +0800 Stop catching errors for some requests * src/xterm.c (x_dnd_compute_toplevels) (frame_set_mouse_pixel_position, x_focus_frame): Use `x_ignore_errors_for_next_request'. This results in a healthy ~30% speedup for the involved requests. diff --git a/src/xterm.c b/src/xterm.c index 8a42b77f51..8aeaca230f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3184,11 +3184,10 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo) if (dpyinfo->xshape_supported_p) { - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XShapeSelectInput (dpyinfo->display, toplevels[i], ShapeNotifyMask); - x_uncatch_errors (); #ifndef HAVE_XCB_SHAPE x_catch_errors (dpyinfo->display); @@ -24770,12 +24769,12 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) FRAME_X_WINDOW (f), &deviceid)) { - x_catch_errors (FRAME_X_DISPLAY (f)); + x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f)); + XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None, FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y); - x_uncatch_errors (); } } else @@ -24889,7 +24888,7 @@ x_get_focus_frame (struct frame *f) /* In certain situations, when the window manager follows a click-to-focus policy, there seems to be no way around calling - XSetInputFocus to give another frame the input focus . + XSetInputFocus to give another frame the input focus. In an ideal world, XSetInputFocus should generally be avoided so that applications don't interfere with the window manager's focus @@ -24899,28 +24898,25 @@ x_get_focus_frame (struct frame *f) static void x_focus_frame (struct frame *f, bool noactivate) { - Display *dpy = FRAME_X_DISPLAY (f); + struct x_display_info *dpyinfo; - block_input (); - x_catch_errors (dpy); + dpyinfo = FRAME_DISPLAY_INFO (f); if (FRAME_X_EMBEDDED_P (f)) - { - /* For Xembedded frames, normally the embedder forwards key - events. See XEmbed Protocol Specification at - https://freedesktop.org/wiki/Specifications/xembed-spec/ */ - xembed_request_focus (f); - } + /* For Xembedded frames, normally the embedder forwards key + events. See XEmbed Protocol Specification at + https://freedesktop.org/wiki/Specifications/xembed-spec/ */ + xembed_request_focus (f); else { + /* Ignore any BadMatch error this request might result in. */ + x_ignore_errors_for_next_request (dpyinfo); XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), RevertToParent, CurrentTime); + if (!noactivate) x_ewmh_activate_frame (f); } - - x_uncatch_errors (); - unblock_input (); } commit c2e07f2258a157718ee868c7f3d3c30de56cd9f7 Author: Po Lu Date: Sun Jun 26 10:20:35 2022 +0800 Handle errors while sending client events asynchronously * src/xterm.c (xm_send_drop_message) (xm_send_top_level_enter_message, xm_send_drag_motion_message) (xm_send_top_level_leave_message, x_dnd_send_enter) (x_dnd_send_position, x_dnd_send_leave, x_dnd_send_drop): Avoid sync to check for errors while sending client events. (x_dnd_begin_drag_and_drop, handle_one_xevent, XTread_socket): Clean up failable requests. (x_request_can_fail): New functions. (x_clean_failable_requests, x_ignore_errors_for_next_request) (x_uncatch_errors): Clean up failable requests. (x_error_handler): If a request is allowed to fail, just return. (x_term_init): Set up new pointer. * src/xterm.h (N_FAILABLE_REQUESTS): New macro. (struct x_display_info): New field `failable_requests' and associated next pointer. diff --git a/src/xterm.c b/src/xterm.c index cd9645af07..8a42b77f51 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1116,6 +1116,8 @@ static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar #ifdef HAVE_X_I18N static int x_filter_event (struct x_display_info *, XEvent *); #endif +static void x_ignore_errors_for_next_request (struct x_display_info *); +static void x_clean_failable_requests (struct x_display_info *); static struct frame *x_tooltip_window_to_frame (struct x_display_info *, Window, bool *); @@ -2417,9 +2419,8 @@ xm_send_drop_message (struct x_display_info *dpyinfo, Window source, *((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom; *((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window; - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); - x_uncatch_errors (); } static void @@ -2444,9 +2445,8 @@ xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source, msg.xclient.data.b[18] = 0; msg.xclient.data.b[19] = 0; - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); - x_uncatch_errors (); } static void @@ -2475,9 +2475,8 @@ xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source, msg.xclient.data.b[18] = 0; msg.xclient.data.b[19] = 0; - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); - x_uncatch_errors (); } static void @@ -2534,9 +2533,8 @@ xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source, msg.xclient.data.b[18] = 0; msg.xclient.data.b[19] = 0; - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg); - x_uncatch_errors (); } static int @@ -4353,9 +4351,8 @@ x_dnd_send_enter (struct frame *f, Window target, int supported) so we don't have to set it again. */ x_dnd_init_type_lists = true; - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); - x_uncatch_errors (); } static void @@ -4416,9 +4413,8 @@ x_dnd_send_position (struct frame *f, Window target, int supported, x_dnd_pending_send_position = msg; else { - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); - x_uncatch_errors (); x_dnd_waiting_for_status_window = target; } @@ -4442,9 +4438,8 @@ x_dnd_send_leave (struct frame *f, Window target) x_dnd_waiting_for_status_window = None; - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); - x_uncatch_errors (); } static bool @@ -4475,9 +4470,8 @@ x_dnd_send_drop (struct frame *f, Window target, Time timestamp, if (supported >= 1) msg.xclient.data.l[2] = timestamp; - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); - x_uncatch_errors (); return true; } @@ -11625,6 +11619,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #endif x_dnd_inside_handle_one_xevent = false; + /* Clean up any event handlers that are now out of date. */ + x_clean_failable_requests (FRAME_DISPLAY_INFO (f)); + /* The unblock_input below might try to read input, but XTread_socket does nothing inside a drag-and-drop event loop, so don't let it clear the pending_signals flag. */ @@ -16405,11 +16402,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, { if (x_dnd_pending_send_position.type != 0) { - x_catch_errors (dpyinfo->display); + x_ignore_errors_for_next_request (dpyinfo); XSendEvent (dpyinfo->display, target, False, NoEventMask, &x_dnd_pending_send_position); - x_uncatch_errors (); } x_dnd_pending_send_position.type = 0; @@ -22274,6 +22270,8 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit) && dpyinfo->display == x_dnd_finish_display))) return 0; + x_clean_failable_requests (dpyinfo); + block_input (); /* For debugging, this gives a way to fake an I/O error. */ @@ -22896,7 +22894,12 @@ x_error_catcher (Display *display, XErrorEvent *event, always skips an XSync to the server, and should be used only immediately after x_had_errors_p or x_check_errors, or when it is known that no requests have been made since the last x_catch_errors - call for DPY. */ + call for DPY. + + There is no need to use this mechanism for ignoring errors from + single asynchronous requests, such as sending a ClientMessage to a + window that might no longer exist. Use + x_ignore_errors_for_next_request instead. */ void x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler, @@ -22921,6 +22924,76 @@ x_catch_errors (Display *dpy) x_catch_errors_with_handler (dpy, NULL, NULL); } +/* Return if errors for REQUEST should be ignored even if there is no + error handler applied. */ +static unsigned long * +x_request_can_fail (struct x_display_info *dpyinfo, + unsigned long request) +{ + unsigned long *failable_requests; + + for (failable_requests = dpyinfo->failable_requests; + failable_requests < dpyinfo->next_failable_request; + failable_requests++) + { + if (*failable_requests == request) + return failable_requests; + } + + return NULL; +} + +/* Remove outdated request serials from + dpyinfo->failable_requests. */ +static void +x_clean_failable_requests (struct x_display_info *dpyinfo) +{ + unsigned long *first, *last; + + last = dpyinfo->next_failable_request; + + for (first = dpyinfo->failable_requests; first < last; first++) + { + if (*first > LastKnownRequestProcessed (dpyinfo->display)) + break; + } + + memmove (&dpyinfo->failable_requests, first, + sizeof *first * (last - first)); + + dpyinfo->next_failable_request = (dpyinfo->failable_requests + + (last - first)); +} + +static void +x_ignore_errors_for_next_request (struct x_display_info *dpyinfo) +{ + unsigned long *request, *max; + + request = dpyinfo->next_failable_request; + max = dpyinfo->failable_requests + N_FAILABLE_REQUESTS; + + if (request > max) + { + /* There is no point in making this extra sync if all requests + are known to have been fully processed. */ + if ((LastKnownRequestProcessed (x_error_message->dpy) + != NextRequest (x_error_message->dpy) - 1)) + XSync (dpyinfo->display, False); + + x_clean_failable_requests (dpyinfo); + request = dpyinfo->next_failable_request; + } + + if (request >= max) + /* A request should always be made immediately after calling this + function. */ + emacs_abort (); + + *request = NextRequest (dpyinfo->display); + dpyinfo->next_failable_request++; +} + /* Undo the last x_catch_errors call. DPY should be the display that was passed to x_catch_errors. @@ -22949,6 +23022,7 @@ void x_uncatch_errors (void) { struct x_error_message_stack *tmp; + struct x_display_info *dpyinfo; /* In rare situations when running Emacs run in daemon mode, shutting down an emacsclient via delete-frame can cause @@ -22959,9 +23033,11 @@ x_uncatch_errors (void) block_input (); + dpyinfo = x_display_info_for_display (x_error_message->dpy); + /* The display may have been closed before this function is called. Check if it is still open before calling XSync. */ - if (x_display_info_for_display (x_error_message->dpy) != 0 + if (dpyinfo != 0 /* There is no point in making this extra sync if all requests are known to have been fully processed. */ && (LastKnownRequestProcessed (x_error_message->dpy) @@ -22970,7 +23046,10 @@ x_uncatch_errors (void) installed. */ && (NextRequest (x_error_message->dpy) > x_error_message->first_request)) - XSync (x_error_message->dpy, False); + { + XSync (x_error_message->dpy, False); + x_clean_failable_requests (dpyinfo); + } tmp = x_error_message; x_error_message = x_error_message->prev; @@ -23280,9 +23359,8 @@ static int x_error_handler (Display *display, XErrorEvent *event) { struct x_error_message_stack *stack; -#ifdef HAVE_XINPUT2 struct x_display_info *dpyinfo; -#endif + unsigned long *fail, *last; #if defined USE_GTK && defined HAVE_GTK3 if ((event->error_code == BadMatch @@ -23291,12 +23369,30 @@ x_error_handler (Display *display, XErrorEvent *event) return 0; #endif + dpyinfo = x_display_info_for_display (display); + + if (dpyinfo) + { + fail = x_request_can_fail (dpyinfo, event->serial); + + if (fail) + { + /* Now that this request has been handled, remove it from + the list of requests that can fail. */ + last = dpyinfo->next_failable_request; + memmove (&dpyinfo->failable_requests, fail, + sizeof *fail * (last - fail)); + dpyinfo->next_failable_request = (dpyinfo->failable_requests + + (last - fail)); + + return 0; + } + } + /* If we try to ungrab or grab a device that doesn't exist anymore (that happens a lot in xmenu.c), just ignore the error. */ #ifdef HAVE_XINPUT2 - dpyinfo = x_display_info_for_display (display); - /* 51 is X_XIGrabDevice and 52 is X_XIUngrabDevice. 53 is X_XIAllowEvents. We handle errors from that here to avoid @@ -26272,6 +26368,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) dpyinfo = xzalloc (sizeof *dpyinfo); terminal = x_create_terminal (dpyinfo); + dpyinfo->next_failable_request = dpyinfo->failable_requests; + { struct x_display_info *share; diff --git a/src/xterm.h b/src/xterm.h index f136b6b97f..ff81babc33 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -75,6 +75,9 @@ typedef GtkWidget *xt_or_gtk_widget; #endif #endif /* USE_GTK */ +/* Number of "failable requests" to store. */ +#define N_FAILABLE_REQUESTS 128 + #ifdef USE_CAIRO #include #ifdef CAIRO_HAS_PDF_SURFACE @@ -742,6 +745,13 @@ struct x_display_info RRScreenChangeNotify. */ int screen_mm_width; int screen_mm_height; + + /* Circular buffer of request serials to ignore inside an error + handler in increasing order. */ + unsigned long failable_requests[N_FAILABLE_REQUESTS]; + + /* Pointer to the next request in `failable_requests'. */ + unsigned long *next_failable_request; }; #ifdef HAVE_X_I18N commit 78c0c8673bba086842ef9ea57f44f446558e5ebf Author: Paul Eggert Date: Sat Jun 25 16:45:28 2022 -0500 Port ‘make clean’ to Solaris 10 * test/Makefile.in (CLEAN_XML_FILES): New macro. (clean): Use it. diff --git a/test/Makefile.in b/test/Makefile.in index 67162c4883..0be5842512 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -341,9 +341,17 @@ mostlyclean: -@for f in ${LOGFILES}; do test ! -f $$f || mv $$f $$f~; done rm -f ./*.tmp +# If 'find' supports -delete, it also supports -path. Otherwise, use +# -prune and $(FIND_DELETE) instead. -prune is incompatible with -delete. +ifeq ($(FIND_DELETE),-delete) +CLEAN_XML_FILES = '(' -name '*.xml' -a ! -path '*resources*' ')' -delete +else +CLEAN_XML_FILES = -name '*resources*' -prune -o -name '*.xml' $(FIND_DELETE) +endif + clean: find . '(' -name '*.log' -o -name '*.log~' ')' $(FIND_DELETE) - find . '(' -name '*.xml' -a ! -path '*resources*' ')' $(FIND_DELETE) + find . $(CLEAN_XML_FILES) rm -f ${srcdir}/lisp/gnus/mml-sec-resources/random_seed rm -f $(test_module_dir)/*.o $(test_module_dir)/*.so \ $(test_module_dir)/*.dll gmp.h commit 4410f5d86997b6b238ff05c2ece338b28e1163b1 Author: Paul Eggert Date: Sat Jun 25 14:51:28 2022 -0500 Port distribution tarball to Solaris 10 * make-dist (taropt): Use 'tar -H ustar' to generate a portable tar file format instead of a GNU-specific format. Needed now that Emacs tarballs contain file names longer than 100 bytes, e.g.: emacs-28.1/test/lisp/gnus/mml-sec-resources/private-keys-v1.d/C072AF82DCCCB9A7F1B85FFA10B802DC4ED16703.key emacs-28.1/test/lisp/emacs-lisp/bytecomp-resources/error-lexical-var-with-run-hook-with-args-until-success.el Without this patch, extracting a tarball on Solaris 10 fails with many diagnostics like “tar: ././@LongLink: typeflag 'L' not recognized, converting to regular file”. diff --git a/make-dist b/make-dist index 447e90f018..67e49382d0 100755 --- a/make-dist +++ b/make-dist @@ -485,6 +485,8 @@ if [ "${make_tar}" = yes ]; then esac echo "Creating tar file" taropt='--numeric-owner --owner=0 --group=0 --mode=go+u,go-w' + tar -H ustar -cf /dev/null $tempdir/src/lisp.h 2>/dev/null && + taropt="$taropt -H ustar" tar --sort=name -cf /dev/null $tempdir/src/lisp.h 2>/dev/null && taropt="$taropt --sort=name" [ "$verbose" = "yes" ] && taropt="$taropt --verbose" commit b0ed2d1f46d27885a19ae6941b6ea5276f0050e0 Author: Paul Eggert Date: Sat Jun 25 13:09:22 2022 -0500 Port test SUBDIRS to Solaris 10 * test/Makefile.in (SUBDIRS): Port to traditional ‘find’, which lacks -path. diff --git a/test/Makefile.in b/test/Makefile.in index 3b6e116e65..67162c4883 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -240,7 +240,8 @@ $(foreach test,${TESTS},$(eval $(call test_template,${test}))) ## Get the tests for only a specific directory. SUBDIRS = $(sort $(shell cd ${srcdir} && find lib-src lisp misc src -type d \ - ! \( -path "*resources*" -o -path "*auto-save-list" \) -print)) + \( -name '*resources*' -prune \ + -o ! -name '*auto-save-list' -print \))) SUBDIR_TARGETS = define subdir_template commit 250a5e8bdde09c7e7d67bc006c469964de7474bb Author: Paul Eggert Date: Sat Jun 25 13:00:28 2022 -0500 Pacify Oracle Studio re xterm.c * src/xterm.c (xErrorHandler, xIOErrorHandler): New typedefs. (xm_get_drag_window_1, x_connection_closed): Use them instead of void *, since the C standard frowns on converting function pointers to and from void *. This pacifies Oracle Studio diagnostics like “warning: assignment type mismatch: pointer to void "=" pointer to function(pointer to struct _XDisplay {})\ returning int”. (x_detect_pending_selection_requests, x_had_errors_p): Do not rely on implicit conversion of a pointer to a bool return value; use !! instead. This pacifies Oracle Studio’s “warning: improper pointer/integer combination: op "="”. (xim_open_dpy) [HAVE_X11R6 && !HAVE_X11R6_XIM]: Do not use xim_destroy_callback; configure.ac says “inoue@ainet.or.jp says Solaris has a bug related to X11R6-style ## XIM support” and Oracle Studio complains “warning: assignment type mismatch: pointer to function(pointer to struct _XIC {}, pointer to char, pointer\ to char) returning void "=" pointer to function(pointer to struct _XIM {}, pointer to char, pointer to char) returning void”. diff --git a/src/xterm.c b/src/xterm.c index 7d5794bdd7..cd9645af07 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -719,6 +719,12 @@ along with GNU Emacs. If not, see . */ #include #endif +/* Although X11/Xlib.h commonly defines the types XErrorHandler and + XIOErrorHandler, they are not in the Xlib spec so for portability + define and use names with a leading lower-case 'x' instead. */ +typedef int (*xErrorHandler) (Display *, XErrorEvent *); +typedef int (*xIOErrorHandler) (Display *); + #if defined USE_XCB && defined USE_CAIRO_XCB #define USE_CAIRO_XCB_SURFACE #endif @@ -1830,7 +1836,9 @@ xm_get_drag_window_1 (struct x_display_info *dpyinfo) Window drag_window; XSetWindowAttributes attrs; Display *temp_display; - void *old_handler, *old_io_handler; + xErrorHandler old_handler; + xIOErrorHandler old_io_handler; + /* These are volatile because GCC mistakenly warns about them being clobbered by longjmp. */ volatile bool error, created; @@ -1893,9 +1901,7 @@ xm_get_drag_window_1 (struct x_display_info *dpyinfo) XGrabServer (temp_display); XSetCloseDownMode (temp_display, RetainPermanent); - /* We can't use XErrorHandler since it's not in the Xlib - specification, and Emacs tries to be portable. */ - old_handler = (void *) XSetErrorHandler (xm_drag_window_error_handler); + old_handler = XSetErrorHandler (xm_drag_window_error_handler); _MOTIF_DRAG_WINDOW = XInternAtom (temp_display, "_MOTIF_DRAG_WINDOW", False); @@ -11202,7 +11208,7 @@ x_push_selection_request (struct selection_input_event *se) bool x_detect_pending_selection_requests (void) { - return pending_selection_requests; + return !!pending_selection_requests; } static void @@ -23024,7 +23030,7 @@ x_had_errors_p (Display *dpy) > x_error_message->first_request)) XSync (dpy, False); - return x_error_message->string; + return !!x_error_message->string; } /* Forget about any errors we have had, since we did x_catch_errors on @@ -23084,7 +23090,7 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) struct x_display_info *dpyinfo; Lisp_Object frame, tail; specpdl_ref idx = SPECPDL_INDEX (); - void *io_error_handler; + xIOErrorHandler io_error_handler; xm_drop_start_message dmsg; struct frame *f; @@ -23479,14 +23485,14 @@ xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name) if (xim) { -#ifdef HAVE_X11R6 +#ifdef HAVE_X11R6_XIM XIMCallback destroy; #endif /* Get supported styles and XIM values. */ XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL); -#ifdef HAVE_X11R6 +#ifdef HAVE_X11R6_XIM destroy.callback = xim_destroy_callback; destroy.client_data = (XPointer)dpyinfo; XSetIMValues (xim, XNDestroyCallback, &destroy, NULL); commit bdedfd927c493aab9c2c2f55a2a261137ad75cc2 Author: Paul Eggert Date: Sat Jun 25 11:44:33 2022 -0500 Pacify Oracle Studio re print_vectorlike * src/print.c (print_vectorlike): Use explicit cast of function pointer to void *, to pacify Oracle Studio 12.6’s “warning: assignment type mismatch: pointer to void "=" pointer to function(pointer to void) returning void”. Admittedly this is not strictly conforming C code even with the cast. diff --git a/src/print.c b/src/print.c index 8f829ba684..d562500b61 100644 --- a/src/print.c +++ b/src/print.c @@ -1727,10 +1727,10 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, case PVEC_USER_PTR: { - void *finalizer = XUSER_PTR (obj)->finalizer; print_c_string ("#p, finalizer); + XUSER_PTR (obj)->p, + (void *) XUSER_PTR (obj)->finalizer); strout (buf, i, i, printcharfun); printchar ('>', printcharfun); } commit 728968a2e6985b31956340199221da6f4bee3ce2 Author: Paul Eggert Date: Sat Jun 25 11:41:07 2022 -0500 Pacify Oracle Studio re Time_to_position * src/keyboard.c (Time_to_position): Use no-op position_to_Time to pacify Oracle Studio 12.6’s “warning: initializer will be sign-extended”. diff --git a/src/keyboard.c b/src/keyboard.c index ecc5a2169c..5b5972ceee 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -3738,7 +3738,7 @@ Time_to_position (Time encoded_pos) { if (encoded_pos <= INPUT_EVENT_POS_MAX) return encoded_pos; - Time encoded_pos_min = INPUT_EVENT_POS_MIN; + Time encoded_pos_min = position_to_Time (INPUT_EVENT_POS_MIN); eassert (encoded_pos_min <= encoded_pos); ptrdiff_t notpos = -1 - encoded_pos; return -1 - notpos; commit 040c03cae2db361d2e014a52d969a6b0ebc48f1c Author: Lars Ingebrigtsen Date: Sat Jun 25 14:58:01 2022 +0200 Make `M-q' work on the first line of a multi-line string again * lisp/emacs-lisp/lisp-mode.el (lisp-fill-paragraph): Exclude the quote marks from the region so that filling works (bug#56197). diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index aaec13d1af..781c80fd5a 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -1481,8 +1481,8 @@ and initial semicolons." (progn (forward-sexp 1) t)) - (narrow-to-region (ppss-comment-or-string-start ppss) - (point)))) + (narrow-to-region (1+ (ppss-comment-or-string-start ppss)) + (1- (point))))) ;; Move back to where we were. (goto-char start) (fill-paragraph justify))))))) commit bdf495f25fe38a151b96c4061fc0dffc121fcc14 Author: Po Lu Date: Sat Jun 25 20:07:35 2022 +0800 Update input_pending after deferring selection requests * src/xterm.c (x_defer_selection_requests): If kbd_fetch_ptr moved, update input_pending. Bug found calling `input-pending-p' inside the DND movement function. diff --git a/src/xterm.c b/src/xterm.c index 7f43e21e88..7d5794bdd7 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -842,7 +842,13 @@ x_defer_selection_requests (void) avoids exhausting the keyboard buffer with some over-enthusiastic clipboard managers. */ if (!between) - kbd_fetch_ptr = X_NEXT_KBD_EVENT (event); + { + kbd_fetch_ptr = X_NEXT_KBD_EVENT (event); + + /* `detect_input_pending' will then recompute + whether or not pending input events exist. */ + input_pending = false; + } } else between = true; commit 3d3029353b95360e374fc673339b7c8cd5568db1 Author: Stefan Kangas Date: Sat Jun 25 12:55:15 2022 +0200 New command recentf-open * lisp/recentf.el (recentf-open): New command. (Bug#56148) (recentf): New alias. (recentf, recentf-mode): Update documentation to focus more on the list of recently opened files and ways of accessing it, instead of focusing on the menu bar only. (recentf-list, recentf-enabled-p): Minor doc fixes. * doc/emacs/files.texi (File Conveniences): Update documentation. diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 062185fb4a..5c80cfe190 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -2222,13 +2222,16 @@ recently-opened files, reading file names from a buffer. @findex recentf-mode @vindex recentf-mode +@findex recentf-open @findex recentf-save-list @findex recentf-edit-list - If you enable Recentf mode, with @kbd{M-x recentf-mode}, the -@samp{File} menu includes a submenu containing a list of recently -opened files. @kbd{M-x recentf-save-list} saves the current -@code{recentf-list} to a file, and @kbd{M-x recentf-edit-list} edits -it. + If you enable Recentf mode, with @kbd{M-x recentf-mode}, Emacs +maintains a list of recently opened files. To open a file from this +list, use the @kbd{M-x recentf-open} command. When this mode is +enabled, the @samp{File} menu will include a submenu that you can use +to visit one of these files. @kbd{M-x recentf-save-list} saves the +current @code{recentf-list} to a file, and @kbd{M-x recentf-edit-list} +edits it. @c FIXME partial-completion-mode (complete.el) is obsolete. The @kbd{M-x ffap} command generalizes @code{find-file} with more diff --git a/etc/NEWS b/etc/NEWS index 5e81cc0fe8..01354a65f0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1893,6 +1893,11 @@ This means that e.g. "/home/foo/bar" is now displayed as "~/bar". Customize the user option 'recentf-filename-handlers' to nil to get back the old behavior. +--- +*** New command 'recentf-open'. +This command prompts for a recently opened file in the minibuffer, and +visits it. + --- ** The autoarg.el library is now marked obsolete. This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor diff --git a/lisp/recentf.el b/lisp/recentf.el index d8016077eb..601b2642f7 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -1,4 +1,4 @@ -;;; recentf.el --- setup a menu of recently opened files -*- lexical-binding: t -*- +;;; recentf.el --- keep track of recently opened files -*- lexical-binding: t -*- ;; Copyright (C) 1999-2022 Free Software Foundation, Inc. @@ -23,10 +23,19 @@ ;;; Commentary: -;; This package maintains a menu for visiting files that were operated -;; on recently. When enabled a new "Open Recent" submenu is -;; displayed in the "File" menu. The recent files list is -;; automatically saved across Emacs sessions. +;; This package maintains a list of recently opened files and makes it +;; easy to visit them. The recent files list is automatically saved +;; across Emacs sessions. + +;; There are three ways to access recent files: +;; +;; (1) `M-x recentf-open' prompts for a recently opened file. +;; +;; (2) When this mode is enabled, a new "Open Recent" submenu is +;; displayed in the "File" menu. +;; +;; (3) `M-x recentf-open-files' lists recently visited files in a +;; buffer. ;; You can customize the number of recent files displayed, the ;; location of the menu and other options. Type: @@ -45,17 +54,17 @@ ;;; Internal data ;; (defvar recentf-list nil - "List of recently opened files.") + "List of recently opened files for `recentf-mode'.") (defun recentf-enabled-p () - "Return non-nil if recentf mode is currently enabled." + "Return non-nil if `recentf-mode' is currently enabled." (memq 'recentf-save-list kill-emacs-hook)) ;;; Customization ;; (defgroup recentf nil - "Maintain a menu of recently opened files." + "Maintain a list of recently opened files." :version "21.1" :group 'files) @@ -465,6 +474,26 @@ Return non-nil if F1 is less than F2." (recentf-string-lessp (file-name-nondirectory f1) (file-name-nondirectory f2)) (recentf-string-lessp d1 d2)))) + + +;;; Open files +;; + +;;;###autoload +(defun recentf-open (file) + "Prompt for FILE in `recentf-list' and visit it. +Enable `recentf-mode' if it isn't already." + (interactive + (list + (progn (unless recentf-mode (recentf-mode 1)) + (completing-read (format-prompt "Open recent file" nil) + recentf-list nil t)))) + (when file + (funcall recentf-menu-action file))) + +;;;###autoload +(defalias 'recentf 'recentf-open) + ;;; Menu building ;; @@ -1344,7 +1373,13 @@ That is, remove duplicates, non-kept, and excluded files." ;;;###autoload (define-minor-mode recentf-mode - "Toggle \"Open Recent\" menu (Recentf mode). + "Toggle keeping track of opened files (Recentf mode). +This mode maintains a list of recently opened files and makes it +easy to visit them. The recent files list is automatically saved +across Emacs sessions. + +You can use `recentf-open' or `recentf-open-files' to visit +files. When Recentf mode is enabled, a \"Open Recent\" submenu is displayed in the \"File\" menu, containing a list of files that commit a2c25d5b2f34522d14fd9dc105d942b74698078a Author: Lars Ingebrigtsen Date: Sat Jun 25 12:45:32 2022 +0200 Fix subr-x fix that was missed when re-reverting * lisp/replace.el (require): Fix subr-x build warning. diff --git a/lisp/replace.el b/lisp/replace.el index c5c24c7a36..34c3d5299e 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -30,6 +30,7 @@ (require 'text-mode) (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) (defcustom case-replace t "Non-nil means `query-replace' should preserve case in replacements." commit 37315f9895406e7ba4c7dce3a5fe179fa658c04c Author: Stefan Kangas Date: Sat Jun 25 12:25:58 2022 +0200 Don't error out on invalid literal key substitutions It would be backwards-incompatible to error out on invalid literal key substitutions. Consider this docstring fragment, where "\\`" should have been escaped but wasn't: "Example value: \"\\(?:\\`[#.]\\)\\|\\(?:[#~]\\'\\)\"." If we error out, we can't display this docstring at all. However, it is clearly better to display something in such cases, even if suboptimal, than refusing to display anything at all. * lisp/help.el (substitute-command-keys): Don't error out on invalid literal key substitutions: just ignore them instead. * test/lisp/help-tests.el (help-tests-substitute-command-keys/literal-key-sequence-errors): Delete test. (help-tests-substitute-command-keys/literal-key-sequence-ignore-invalid): New test. diff --git a/lisp/help.el b/lisp/help.el index f14617b437..fbcf8461e6 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1165,26 +1165,24 @@ Otherwise, return a new string." (delete-char 2) (ignore-errors (forward-char 1))) + ;; 1C. \`f' is replaced with a fontified f. ((and (= (following-char) ?`) (save-excursion (prog1 (search-forward "'" nil t) - (setq end-point (- (point) 2))))) - (goto-char orig-point) - (delete-char 2) - (goto-char (1- end-point)) - (delete-char 1) - ;; (backward-char 1) - (let ((k (buffer-substring-no-properties orig-point (point)))) - (cond ((= (length k) 0) - (error "Empty key sequence in substitution")) - ((and (not (string-match-p "\\`M-x " k)) - (not (key-valid-p k))) - (error "Invalid key sequence in substitution: `%s'" k)))) - (unless no-face - (add-text-properties orig-point (point) - '( face help-key-binding - font-lock-face help-key-binding)))) - ;; 1C. \[foo] is replaced with the keybinding. + (setq end-point (1- (point)))))) + (let ((k (buffer-substring-no-properties (+ orig-point 2) + end-point))) + (when (or (key-valid-p k) + (string-match-p "\\`M-x " k)) + (goto-char orig-point) + (delete-char 2) + (goto-char (- end-point 2)) ; nb. take deletion into account + (delete-char 1) + (unless no-face + (add-text-properties orig-point (point) + '( face help-key-binding + font-lock-face help-key-binding)))))) + ;; 1D. \[foo] is replaced with the keybinding. ((and (= (following-char) ?\[) (save-excursion (prog1 (search-forward "]" nil t) @@ -1228,7 +1226,7 @@ Otherwise, return a new string." (help-mode--add-function-link key fun) key) key))))))) - ;; 1D. \{foo} is replaced with a summary of the keymap + ;; 1E. \{foo} is replaced with a summary of the keymap ;; (symbol-value foo). ;; \ just sets the keymap used for \[cmd]. ((and (or (and (= (following-char) ?{) diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el index 14a1fb49ae..5c935965f7 100644 --- a/test/lisp/help-tests.el +++ b/test/lisp/help-tests.el @@ -95,10 +95,12 @@ (test "\\`C-m'\\`C-j'" "C-mC-j") (test "foo\\`C-m'bar\\`C-j'baz" "fooC-mbarC-jbaz"))) -(ert-deftest help-tests-substitute-command-keys/literal-key-sequence-errors () - (should-error (substitute-command-keys "\\`'")) - (should-error (substitute-command-keys "\\`c-c'")) - (should-error (substitute-command-keys "\\`'"))) +(ert-deftest help-tests-substitute-command-keys/literal-key-sequence-ignore-invalid () + "Ignore any invalid literal key sequence." + (with-substitute-command-keys-test + (test-re "ab\\`'cd" "ab\\\\[`'‘]['’]cd") + (test-re "\\`c-c'" "\\\\[`'‘]c-c['’]") + (test-re "\\`'" "\\\\[`'‘]['’]"))) (ert-deftest help-tests-substitute-key-bindings/help-key-binding-face () (let ((A (substitute-command-keys "\\[next-line]")) commit 2f346b0ab10a8777ff5629af30a224b4f0ea16a6 Author: Lars Ingebrigtsen Date: Sat Jun 25 12:20:05 2022 +0200 Re-fix build warnings about subr-x defsubsts * lisp/term/haiku-win.el (require): * lisp/progmodes/elisp-mode.el (require): * lisp/isearch.el (require): Require subr-x at compile time, since these use defsubsts/macros from there. * lisp/emacs-lisp/subr-x.el (string-empty-p): Move from here... * lisp/simple.el (string-empty-p): ... to here. This is to help with a build problem where files.el is using the defsubst, but requiring subr-x.el at compile time leads to load errors. diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index b0de5d155a..390e505f00 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -97,10 +97,6 @@ threading." (maphash (lambda (_ v) (push v values)) hash-table) values)) -(defsubst string-empty-p (string) - "Check whether STRING is empty." - (string= string "")) - (defsubst string-join (strings &optional separator) "Join all STRINGS using SEPARATOR. Optional argument SEPARATOR must be a string, a vector, or a list of diff --git a/lisp/isearch.el b/lisp/isearch.el index 7650ebcfce..0624858993 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -54,6 +54,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) ;; Some additional options and constants. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 332488e6d4..fc25767934 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -31,6 +31,7 @@ (require 'cl-generic) (require 'lisp-mode) (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) (define-abbrev-table 'emacs-lisp-mode-abbrev-table () "Abbrev table for Emacs Lisp mode. diff --git a/lisp/simple.el b/lisp/simple.el index 8f82ff3a8e..2b11a6362f 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -10620,6 +10620,10 @@ If the buffer doesn't exist, create it first." (save-buffer))) t))) +(defsubst string-empty-p (string) + "Check whether STRING is empty." + (string= string "")) + (provide 'simple) diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 5443904a73..024459e647 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -24,6 +24,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) (unless (featurep 'haiku) (error "%s: Loading haiku-win without having Haiku" invocation-name)) commit 376ecd5346496a4f11a3bc93814b03d7a884b841 Author: Eli Zaretskii Date: Sat Jun 25 12:33:45 2022 +0300 ; Fix last change regarding 'record-all-keys' * src/keyboard.c (syms_of_keyboard): * etc/NEWS: Minor fixes of documentation of 'record-all-keys'. diff --git a/etc/NEWS b/etc/NEWS index afd0725a69..5e81cc0fe8 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -400,9 +400,10 @@ dragging items from another program. +++ ** New user option 'record-all-keys'. -If non-nil, this option will force recording of all input keys -including in passwords prompt (this was the previous behaviour). It -now defaults to NIL and inhibits recording of passwords. +If non-nil, this option will force recording of all input keys, +including those typed in response to passwords prompt (this was the +previous behavior). The default is nil, which inhibits recording of +passwords. +++ ** New function 'command-query'. diff --git a/src/keyboard.c b/src/keyboard.c index 0d52378a93..ecc5a2169c 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -13040,8 +13040,10 @@ Internal use only. */); inhibit_record_char = false; DEFVAR_BOOL ("record-all-keys", record_all_keys, - doc: /* Non-nil means to record all typed keys. When -nil, only passwords' keys are not recorded. */); + doc: /* Non-nil means record all keys you type. +When nil, the default, characters typed as part of passwords are +not recorded. The non-nil value countermands `inhibit--record-char', +which see. */); record_all_keys = false; pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper); commit f01024b94d1b2af9ebb14a2d1faaddce23314811 Author: Manuel Giraud Date: Tue Jun 14 11:14:02 2022 +0200 Avoid recording passwords' chars * lisp/cus-start.el (standard): New user custom `record-all-keys'. * src/keyboard.c (syms_of_keyboard): Un-obsolete `inhibit--record-char'. * lisp/subr.el (read-passwd): Use `inhibit--record-char' to inhibit passwords recording. diff --git a/etc/NEWS b/etc/NEWS index e3b4df227e..afd0725a69 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -398,6 +398,12 @@ This inhibits putting empty strings onto the kill ring. These options allow adjusting point and scrolling a window when dragging items from another program. ++++ +** New user option 'record-all-keys'. +If non-nil, this option will force recording of all input keys +including in passwords prompt (this was the previous behaviour). It +now defaults to NIL and inhibits recording of passwords. + +++ ** New function 'command-query'. This function makes its argument command prompt the user for diff --git a/lisp/cus-start.el b/lisp/cus-start.el index d8c4b48035..ca2fca4eb7 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -398,6 +398,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of ;; (const :tag " current dir" nil) ;; (directory :format "%v")))) (load-prefer-newer lisp boolean "24.4") + (record-all-keys keyboard boolean) ;; minibuf.c (minibuffer-follows-selected-frame minibuffer (choice (const :tag "Always" t) diff --git a/lisp/subr.el b/lisp/subr.el index 075bfb95b7..b05471f0c3 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1883,12 +1883,6 @@ be a list of the form returned by `event-start' and `event-end'." (make-obsolete-variable 'load-dangerous-libraries "no longer used." "27.1") -(defvar inhibit--record-char nil - "Obsolete variable. -This was used internally by quail.el and keyboard.c in Emacs 27. -It does nothing in Emacs 28.") -(make-obsolete-variable 'inhibit--record-char nil "28.1") - (define-obsolete-function-alias 'compare-window-configurations #'window-configuration-equal-p "29.1") @@ -3048,6 +3042,7 @@ by doing (clear-string STRING)." (use-local-map read-passwd-map) (setq-local inhibit-modification-hooks nil) ;bug#15501. (setq-local show-paren-mode nil) ;bug#16091. + (setq-local inhibit--record-char t) (add-hook 'post-command-hook #'read-password--hide-password nil t)) (unwind-protect (let ((enable-recursive-minibuffers t) diff --git a/src/keyboard.c b/src/keyboard.c index 7fb7afca87..0d52378a93 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -3320,6 +3320,11 @@ help_char_p (Lisp_Object c) static void record_char (Lisp_Object c) { + /* subr.el/read-passwd binds inhibit_record_char to avoid recording + passwords. */ + if (!record_all_keys && inhibit_record_char) + return; + int recorded = 0; if (CONSP (c) && (EQ (XCAR (c), Qhelp_echo) || EQ (XCAR (c), Qmouse_movement))) @@ -13026,6 +13031,19 @@ argument, which is the terminal on which the monitor configuration changed. */); Vdisplay_monitors_changed_functions = Qnil; + DEFVAR_BOOL ("inhibit--record-char", + inhibit_record_char, + doc: /* If non-nil, don't record input events. +This inhibits recording input events for the purposes of keyboard +macros, dribble file, and `recent-keys'. +Internal use only. */); + inhibit_record_char = false; + + DEFVAR_BOOL ("record-all-keys", record_all_keys, + doc: /* Non-nil means to record all typed keys. When +nil, only passwords' keys are not recorded. */); + record_all_keys = false; + pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper); } commit ab5de9e3eee2e9ae9fb284da7f2ab26f5adb1a48 Author: Eli Zaretskii Date: Sat Jun 25 12:17:46 2022 +0300 ; * CONTRIBUTE: Mention checks performed by commit hooks. (Bug#56108) diff --git a/CONTRIBUTE b/CONTRIBUTE index 614afa27db..d624fe8524 100644 --- a/CONTRIBUTE +++ b/CONTRIBUTE @@ -314,11 +314,42 @@ them right the first time, so here are guidelines for formatting them: with Emacs commands like 'C-x 4 a', and commit the change using the shell command 'vc-dwim --commit'. Type 'vc-dwim --help' for more. +** Committing your changes. + +When you commit changes, Git invokes several scripts that test the +commit for validity, and may abort the commit of some of the tests +fail. These scripts live in the '.git/hooks/' subdirectory of the +top-level directory of the repository, and they perform the following +tests: + +- commit log message must not be empty; +- the first line of the commit log message doesn't start with + whitespace characters; +- the second line of the commit log message must be empty; +- commit log message should include only valid printable ASCII and + UTF-8 characters; +- commit log message lines must be shorter than 79 characters, unless + a line consists of a single long word, in which case that word can + be up to 140 characters long; +- there shouldn't be any "Signed-off-by:" tags in the commit log + message, and "git commit" should not be invoked with the '-s' option + (which automatically adds "Signed-off-by:"); +- if the commit adds new files, the file names must not begin with + '-' and must consist of ASCII letters, digits, and characters of the + set [-+./_]; +- the changes don't include unresolved merge conflict markers; +- the changes don't introduce whitespace errors: trailing whitespace, + lines that include nothing but whitespace characters, and indented + lines where a SPC character is immediately followed by a TAB in the + line's initial indentation + ** Committing changes by others If committing changes written by someone else, commit in their name, not yours. You can use 'git commit --author="AUTHOR"' to specify a -change's author. +change's author. Note that the validity checks described in the +previous section are still applied, so you will have to correct any +problems they uncover in the changes submitted by others. ** Branches commit 473affe5c6f44973725dd5bfb6990e089657e81e Author: Eli Zaretskii Date: Sat Jun 25 10:46:10 2022 +0300 Minor optimization of the "abort redisplay" feature * src/xdisp.c (init_iterator, set_iterator_to_next) (redisplay_internal): * src/syntax.c (scan_sexps_forward): * src/regex-emacs.c (re_match_2_internal): * src/bidi.c (bidi_fetch_char, bidi_paragraph_init) (bidi_find_bracket_pairs, bidi_find_other_level_edge): Don't call 'update_redisplay_ticks' if aborting too-long redisplay is disabled. (Bug#45898) diff --git a/src/bidi.c b/src/bidi.c index 267b62fb0b..c4d04136e9 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -1281,7 +1281,7 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos, tuned. It means we consider 100 buffer positions examined by the above call roughly equivalent to the display engine iterating over a single buffer position. */ - if (*disp_pos > charpos) + if (max_redisplay_ticks > 0 && *disp_pos > charpos) update_redisplay_ticks ((*disp_pos - charpos) / 100 + 1, w); } @@ -1391,7 +1391,7 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos, SET_TEXT_POS (pos, charpos + *nchars, bytepos + *ch_len); *disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p, disp_prop); - if (*disp_pos > charpos + *nchars) + if (max_redisplay_ticks > 0 && *disp_pos > charpos + *nchars) update_redisplay_ticks ((*disp_pos - charpos - *nchars) / 100 + 1, w); } @@ -1822,7 +1822,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) roughly equivalent to the display engine iterating over a single buffer position. */ ptrdiff_t nexamined = bidi_it->charpos - pos + nsearch_for_strong; - if (nexamined > 0) + if (max_redisplay_ticks > 0 && nexamined > 0) update_redisplay_ticks (nexamined / 50, bidi_it->w); } @@ -2825,7 +2825,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) means we consider 20 buffer positions examined by this function roughly equivalent to the display engine iterating over a single buffer position. */ - if (n > 0) + if (max_redisplay_ticks > 0 && n > 0) update_redisplay_ticks (n / 20 + 1, bidi_it->w); return retval; } @@ -3436,7 +3436,7 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag) tuned. It means we consider 50 buffer positions examined by the above call roughly equivalent to the display engine iterating over a single buffer position. */ - if (bidi_it->charpos > pos0) + if (max_redisplay_ticks > 0 && bidi_it->charpos > pos0) update_redisplay_ticks ((bidi_it->charpos - pos0) / 50 + 1, bidi_it->w); } } diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 4d87418eea..9b2c14c413 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c @@ -4217,7 +4217,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, means we consider 50 buffer positions examined by this function roughly equivalent to the display engine iterating over a single buffer position. */ - if (nchars > 0) + if (max_redisplay_ticks > 0 && nchars > 0) update_redisplay_ticks (nchars / 50 + 1, NULL); return dcnt; } @@ -5087,7 +5087,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, unbind_to (count, Qnil); SAFE_FREE (); - if (nchars > 0) + if (max_redisplay_ticks > 0 && nchars > 0) update_redisplay_ticks (nchars / 50 + 1, NULL); return -1; /* Failure to match. */ diff --git a/src/syntax.c b/src/syntax.c index c13a8179ee..15625b4d0e 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -3481,7 +3481,7 @@ do { prev_from = from; \ means we consider 10 buffer positions examined by this function roughly equivalent to the display engine iterating over a single buffer position. */ - if (from > started_from) + if (max_redisplay_ticks > 0 && from > started_from) update_redisplay_ticks ((from - started_from) / 10 + 1, NULL); } diff --git a/src/xdisp.c b/src/xdisp.c index 886c3f4ecb..cbe6feeae4 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3231,7 +3231,8 @@ init_iterator (struct it *it, struct window *w, it->cmp_it.id = -1; - update_redisplay_ticks (0, w); + if (max_redisplay_ticks > 0) + update_redisplay_ticks (0, w); /* Extra space between lines (on window systems only). */ if (base_face_id == DEFAULT_FACE_ID @@ -8186,7 +8187,8 @@ void set_iterator_to_next (struct it *it, bool reseat_p) { - update_redisplay_ticks (1, it->w); + if (max_redisplay_ticks > 0) + update_redisplay_ticks (1, it->w); switch (it->method) { @@ -16925,7 +16927,8 @@ redisplay_internal (void) /* We're done with this redisplay cycle, so reset the tick count in preparation for the next redisplay cycle. */ - update_redisplay_ticks (0, NULL); + if (max_redisplay_ticks > 0) + update_redisplay_ticks (0, NULL); unbind_to (count, Qnil); RESUME_POLLING; commit 230891d9f33644146cf1e962824618256374eadc Author: Po Lu Date: Sat Jun 25 07:34:43 2022 +0000 Implement image transform smoothing on Haiku * src/dispextern.h (struct image): New field `use_bilinear_filtering'. * src/haiku_draw_support.cc (BView_DrawBitmap): Accept it. * src/haiku_support.h: Update prototypes. * src/haikuterm.c (haiku_draw_image_glyph_string): * src/image.c (image_set_transform): Set it. diff --git a/src/dispextern.h b/src/dispextern.h index 170641f1ba..9dec8b7d12 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3090,6 +3090,10 @@ struct image /* The original width and height of the image. */ int original_width, original_height; + + /* Whether or not bilinear filtering should be used to "smooth" the + image. */ + bool use_bilinear_filtering; #endif /* Colors allocated for this image, if any. Allocated via xmalloc. */ diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc index 768ffdabf8..e2025ed68d 100644 --- a/src/haiku_draw_support.cc +++ b/src/haiku_draw_support.cc @@ -280,14 +280,19 @@ hsl_color_rgb (double h, double s, double l, uint32_t *rgb) void BView_DrawBitmap (void *view, void *bitmap, int x, int y, int width, int height, int vx, int vy, int vwidth, - int vheight) + int vheight, bool use_bilinear_filtering) { BView *vw = get_view (view); BBitmap *bm = (BBitmap *) bitmap; vw->SetDrawingMode (B_OP_OVER); - vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1), - BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); + if (!use_bilinear_filtering) + vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1), + BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); + else + vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1), + BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1), + B_FILTER_BITMAP_BILINEAR); vw->SetDrawingMode (B_OP_COPY); } diff --git a/src/haiku_support.h b/src/haiku_support.h index fcdf6bcb15..7585b62a06 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -558,7 +558,7 @@ extern void BView_StrokeLine (void *, int, int, int, int); extern void BView_CopyBits (void *, int, int, int, int, int, int, int, int); extern void BView_InvertRect (void *, int, int, int, int); extern void BView_DrawBitmap (void *, void *, int, int, int, int, int, int, - int, int); + int, int, bool); extern void BView_DrawBitmapWithEraseOp (void *, void *, int, int, int, int); extern void BView_DrawBitmapTiled (void *, void *, int, int, int, int, int, int, int, int); diff --git a/src/haikuterm.c b/src/haikuterm.c index 7c307afa32..f50f6b34bd 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -1738,7 +1738,8 @@ haiku_draw_image_glyph_string (struct glyph_string *s) s->img->original_height, 0, 0, s->img->original_width, - s->img->original_height); + s->img->original_height, + s->img->use_bilinear_filtering); if (mask) be_draw_image_mask (mask, view, 0, 0, diff --git a/src/image.c b/src/image.c index 5e98945df5..fcf5e97b0b 100644 --- a/src/image.c +++ b/src/image.c @@ -2563,6 +2563,7 @@ image_set_transform (struct frame *f, struct image *img) img->original_width = img->width; img->original_height = img->height; + img->use_bilinear_filtering = false; memcpy (&img->transform, identity, sizeof identity); #endif @@ -2604,7 +2605,7 @@ image_set_transform (struct frame *f, struct image *img) /* Determine flipping. */ flip = !NILP (image_spec_value (img->spec, QCflip, NULL)); -# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS +# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_HAIKU /* We want scale up operations to use a nearest neighbor filter to show real pixels instead of munging them, but scale down operations to use a blended filter, to avoid aliasing and the like. @@ -2618,6 +2619,10 @@ image_set_transform (struct frame *f, struct image *img) smoothing = !NILP (s); # endif +#ifdef HAVE_HAIKU + img->use_bilinear_filtering = smoothing; +#endif + /* Perform scale transformation. */ matrix3x3 matrix commit 1754b0df75701cadb264b2c3ae829893f1a04327 Author: Eli Zaretskii Date: Sat Jun 25 10:14:11 2022 +0300 Fix false positive due to 'max-redisplay-ticks' feature * src/xdisp.c (redisplay_internal): Reset the tick count at end of redisplay cycle. (Bug#45898) diff --git a/src/xdisp.c b/src/xdisp.c index c37a58ab4e..886c3f4ecb 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -16923,6 +16923,10 @@ redisplay_internal (void) if (interrupt_input && interrupts_deferred) request_sigio (); + /* We're done with this redisplay cycle, so reset the tick count in + preparation for the next redisplay cycle. */ + update_redisplay_ticks (0, NULL); + unbind_to (count, Qnil); RESUME_POLLING; } commit d392ad7c5c914db7edc59b86bfe00c4fe0a7e3a5 Author: Po Lu Date: Sat Jun 25 14:38:54 2022 +0800 Fix non-XI2 build * src/xterm.c (handle_one_xevent): Don't make `event' const when passing it to RandR functions. Also, update out of date comment. diff --git a/src/xterm.c b/src/xterm.c index d03b9a6d61..7f43e21e88 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -16806,9 +16806,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property; SELECTION_EVENT_TIME (&inev.sie) = eventp->time; - /* If drag-and-drop is in progress, handle SelectionRequest - events immediately, by setting hold_quit to the input - event. */ + /* If drag-and-drop or another modal dialog/menu is in + progress, handle SelectionRequest events immediately, by + pushing it onto the selecction queue. */ if (x_use_pending_selection_requests) { @@ -22064,7 +22064,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (event->type == (dpyinfo->xrandr_event_base + RRScreenChangeNotify)) - XRRUpdateConfiguration (event); + XRRUpdateConfiguration ((XEvent *) event); if (event->type == (dpyinfo->xrandr_event_base + RRScreenChangeNotify)) commit a70f731e412f4393211f132ea989102c98d17b78 Author: Po Lu Date: Sat Jun 25 14:24:18 2022 +0800 ; Fix typo in last change ; * src/dispextern.h (struct image): Fix typo. diff --git a/src/dispextern.h b/src/dispextern.h index 797b4730cd..170641f1ba 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3070,7 +3070,7 @@ struct image Non-NULL means it and its Pixmap counterpart may be out of sync and the latter is outdated. NULL means the X image has been synchronized to Pixmap. */ -v XImage *ximg, *mask_img; + XImage *ximg, *mask_img; # if !defined USE_CAIRO && defined HAVE_XRENDER /* Picture versions of pixmap and mask for compositing. */ commit b257a7894b6b8536ee16e6b334207c8f5c887280 Author: Po Lu Date: Sat Jun 25 06:20:57 2022 +0000 Implement "flip" image transforms on Haiku * src/dispextern.h (struct image): New field `transform', `original_width' and `original_height'. * src/haiku_draw_support.cc (BView_DrawMask): Rename to `be_draw_image_mask' and fix coding style. (rotate_bitmap_270, BBitmap_transform_bitmap, rotate_bitmap_90): Delete functions. (be_apply_affine_transform): New function. (be_apply_inverse_transform): New function. * src/haiku_support.h: Update prototypes. * src/haikuterm.c (haiku_translate_transform): New function. (haiku_draw_image_glyph_string): Use affine transforms to implement images. * src/image.c (image_set_transform): Implement using affine transforms on Haiku too. diff --git a/src/dispextern.h b/src/dispextern.h index 8bcd13dbb6..797b4730cd 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3070,7 +3070,7 @@ struct image Non-NULL means it and its Pixmap counterpart may be out of sync and the latter is outdated. NULL means the X image has been synchronized to Pixmap. */ - XImage *ximg, *mask_img; +v XImage *ximg, *mask_img; # if !defined USE_CAIRO && defined HAVE_XRENDER /* Picture versions of pixmap and mask for compositing. */ @@ -3085,12 +3085,11 @@ struct image XFORM xform; #endif #ifdef HAVE_HAIKU - /* Non-zero if the image has not yet been transformed for display. */ - int have_be_transforms_p; + /* The affine transformation to apply to this image. */ + double transform[3][3]; - double be_rotate; - double be_scale_x; - double be_scale_y; + /* The original width and height of the image. */ + int original_width, original_height; #endif /* Colors allocated for this image, if any. Allocated via xmalloc. */ diff --git a/src/haiku_draw_support.cc b/src/haiku_draw_support.cc index f0cc084bb3..768ffdabf8 100644 --- a/src/haiku_draw_support.cc +++ b/src/haiku_draw_support.cc @@ -357,134 +357,64 @@ BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x, } void -BView_DrawMask (void *src, void *view, - int x, int y, int width, int height, - int vx, int vy, int vwidth, int vheight, - uint32_t color) +be_draw_image_mask (void *src, void *view, int x, int y, int width, + int height, int vx, int vy, int vwidth, int vheight, + uint32_t color) { BBitmap *source = (BBitmap *) src; BBitmap bm (source->Bounds (), B_RGBA32); BRect bounds = bm.Bounds (); + int bx, by, bit; + BView *vw; if (bm.InitCheck () != B_OK) return; - for (int y = 0; y < BE_RECT_HEIGHT (bounds); ++y) + + /* Fill the background color or transparency into the bitmap, + depending on the value of the mask. */ + for (by = 0; by < BE_RECT_HEIGHT (bounds); ++by) { - for (int x = 0; x < BE_RECT_WIDTH (bounds); ++x) + for (bx = 0; bx < BE_RECT_WIDTH (bounds); ++bx) { - int bit = haiku_get_pixel ((void *) source, x, y); + bit = haiku_get_pixel ((void *) source, bx, by); if (!bit) - haiku_put_pixel ((void *) &bm, x, y, ((uint32_t) 255 << 24) | color); + haiku_put_pixel ((void *) &bm, bx, by, + ((uint32_t) 255 << 24) | color); else - haiku_put_pixel ((void *) &bm, x, y, 0); + haiku_put_pixel ((void *) &bm, bx, by, 0); } } - BView *vw = get_view (view); + + vw = get_view (view); vw->SetDrawingMode (B_OP_OVER); vw->DrawBitmap (&bm, BRect (x, y, x + width - 1, y + height - 1), BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1)); vw->SetDrawingMode (B_OP_COPY); } -static BBitmap * -rotate_bitmap_270 (BBitmap *bmp) -{ - BRect r = bmp->Bounds (); - BBitmap *bm = new BBitmap (BRect (r.top, r.left, r.bottom, r.right), - bmp->ColorSpace (), true); - if (bm->InitCheck () != B_OK) - gui_abort ("Failed to init bitmap for rotate"); - int w = BE_RECT_WIDTH (r); - int h = BE_RECT_HEIGHT (r); - - for (int y = 0; y < h; ++y) - for (int x = 0; x < w; ++x) - haiku_put_pixel ((void *) bm, y, w - x - 1, - haiku_get_pixel ((void *) bmp, x, y)); - - return bm; -} - -static BBitmap * -rotate_bitmap_90 (BBitmap *bmp) +void +be_apply_affine_transform (void *view, double m0, double m1, double tx, + double m2, double m3, double ty) { - BRect r = bmp->Bounds (); - BBitmap *bm = new BBitmap (BRect (r.top, r.left, r.bottom, r.right), - bmp->ColorSpace (), true); - if (bm->InitCheck () != B_OK) - gui_abort ("Failed to init bitmap for rotate"); - int w = BE_RECT_WIDTH (r); - int h = BE_RECT_HEIGHT (r); + BAffineTransform transform (m0, m2, m1, m3, tx, ty); - for (int y = 0; y < h; ++y) - for (int x = 0; x < w; ++x) - haiku_put_pixel ((void *) bm, h - y - 1, x, - haiku_get_pixel ((void *) bmp, x, y)); - - return bm; + get_view (view)->SetTransform (transform); } -void * -BBitmap_transform_bitmap (void *bitmap, void *mask, uint32_t m_color, - double rot, int desw, int desh) +void +be_apply_inverse_transform (double (*matrix3x3)[3], int x, int y, + int *x_out, int *y_out) { - BBitmap *bm = (BBitmap *) bitmap; - BBitmap *mk = (BBitmap *) mask; - int copied_p = 0; + BAffineTransform transform (matrix3x3[0][0], matrix3x3[1][0], + matrix3x3[0][1], matrix3x3[1][1], + matrix3x3[0][2], matrix3x3[1][2]); + BPoint point (x, y); - if (rot == 90) - { - copied_p = 1; - bm = rotate_bitmap_90 (bm); - if (mk) - mk = rotate_bitmap_90 (mk); - } - - if (rot == 270) - { - copied_p = 1; - bm = rotate_bitmap_270 (bm); - if (mk) - mk = rotate_bitmap_270 (mk); - } - - BRect n = BRect (0, 0, desw - 1, desh - 1); - BView vw (n, NULL, B_FOLLOW_NONE, 0); - BBitmap *dst = new BBitmap (n, bm->ColorSpace (), true); - if (dst->InitCheck () != B_OK) - if (bm->InitCheck () != B_OK) - gui_abort ("Failed to init bitmap for scale"); - dst->AddChild (&vw); + transform.ApplyInverse (&point); - if (!vw.LockLooper ()) - gui_abort ("Failed to lock offscreen view for scale"); - - if (rot != 90 && rot != 270) - { - BAffineTransform tr; - tr.RotateBy (BPoint (desw / 2, desh / 2), rot * M_PI / 180.0); - vw.SetTransform (tr); - } - - vw.MovePenTo (0, 0); - vw.DrawBitmap (bm, n); - if (mk) - { - BRect k = mk->Bounds (); - BView_DrawMask ((void *) mk, (void *) &vw, - 0, 0, BE_RECT_WIDTH (k), - BE_RECT_HEIGHT (k), - 0, 0, desw, desh, m_color); - } - vw.Sync (); - vw.RemoveSelf (); - - if (copied_p) - delete bm; - if (copied_p && mk) - delete mk; - return dst; + *x_out = std::floor (point.x); + *y_out = std::floor (point.y); } void diff --git a/src/haiku_support.h b/src/haiku_support.h index 3484fe0bbe..fcdf6bcb15 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -560,8 +560,6 @@ extern void BView_InvertRect (void *, int, int, int, int); extern void BView_DrawBitmap (void *, void *, int, int, int, int, int, int, int, int); extern void BView_DrawBitmapWithEraseOp (void *, void *, int, int, int, int); -extern void BView_DrawMask (void *, void *, int, int, int, int, int, int, - int, int, uint32_t); extern void BView_DrawBitmapTiled (void *, void *, int, int, int, int, int, int, int, int); @@ -570,8 +568,13 @@ extern void BView_set_view_cursor (void *, void *); extern void BView_move_frame (void *, int, int, int, int); extern void BView_scroll_bar_update (void *, int, int, int, int, bool); -extern void *BBitmap_transform_bitmap (void *, void *, uint32_t, double, - int, int); +extern void *be_transform_bitmap (void *, void *, uint32_t, double, + int, int, bool); +extern void be_apply_affine_transform (void *, double, double, double, + double, double, double); +extern void be_apply_inverse_transform (double (*)[3], int, int, int *, int *); +extern void be_draw_image_mask (void *, void *, int, int, int, int, int, int, + int, int, uint32_t); extern void be_get_display_resolution (double *, double *); extern void be_get_screen_dimensions (int *, int *); diff --git a/src/haikuterm.c b/src/haikuterm.c index a90955ebe7..7c307afa32 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -1629,6 +1629,14 @@ haiku_draw_image_relief (struct glyph_string *s) top_p, bot_p, left_p, right_p, &r); } +static void +haiku_translate_transform (double (*transform)[3], double dx, + double dy) +{ + transform[0][2] += dx; + transform[1][2] += dy; +} + static void haiku_draw_image_glyph_string (struct glyph_string *s) { @@ -1640,6 +1648,7 @@ haiku_draw_image_glyph_string (struct glyph_string *s) struct haiku_rect nr; Emacs_Rectangle cr, ir, r; unsigned long background; + double image_transform[3][3]; height = s->height; if (s->slice.y == 0) @@ -1701,34 +1710,51 @@ haiku_draw_image_glyph_string (struct glyph_string *s) if (gui_intersect_rectangles (&cr, &ir, &r)) { - if (s->img->have_be_transforms_p) - { - bitmap = BBitmap_transform_bitmap (bitmap, - s->img->mask, - face->background, - s->img->be_rotate, - s->img->width, - s->img->height); - mask = NULL; - } + memcpy (&image_transform, &s->img->transform, + sizeof image_transform); - BView_DrawBitmap (view, bitmap, - s->slice.x + r.x - x, - s->slice.y + r.y - y, - r.width, r.height, - r.x, r.y, r.width, r.height); - if (mask) + if (s->slice.x != x || s->slice.y != y + || s->slice.width != s->img->width + || s->slice.height != s->img->height) { - BView_DrawMask (mask, view, - s->slice.x + r.x - x, - s->slice.y + r.y - y, - r.width, r.height, - r.x, r.y, r.width, r.height, - face->background); + BView_StartClip (view); + BView_ClipToRect (view, r.x, r.y, r.width, r.height); } - if (s->img->have_be_transforms_p) - BBitmap_free (bitmap); + haiku_translate_transform (image_transform, + x - s->slice.x, + y - s->slice.y); + + be_apply_affine_transform (view, + image_transform[0][0], + image_transform[0][1], + image_transform[0][2], + image_transform[1][0], + image_transform[1][1], + image_transform[1][2]); + + BView_DrawBitmap (view, bitmap, 0, 0, + s->img->original_width, + s->img->original_height, + 0, 0, + s->img->original_width, + s->img->original_height); + + if (mask) + be_draw_image_mask (mask, view, 0, 0, + s->img->original_width, + s->img->original_height, + 0, 0, + s->img->original_width, + s->img->original_height, + face->background); + + if (s->slice.x != x || s->slice.y != y + || s->slice.width != s->img->width + || s->slice.height != s->img->height) + BView_EndClip (view); + + be_apply_affine_transform (view, 1, 0, 0, 0, 1, 0); } if (!s->img->mask) diff --git a/src/image.c b/src/image.c index 0e4b2e0f62..5e98945df5 100644 --- a/src/image.c +++ b/src/image.c @@ -2503,17 +2503,17 @@ compute_image_size (double width, double height, finally move the origin back to the top left of the image, which may now be a different corner. - Note that different GUI backends (X, Cairo, w32, NS) want the - transform matrix defined as transform from the original image to - the transformed image, while others want the matrix to describe the - transform of the space, which boils down to inverting the matrix. + Note that different GUI backends (X, Cairo, w32, NS, Haiku) want + the transform matrix defined as transform from the original image + to the transformed image, while others want the matrix to describe + the transform of the space, which boils down to inverting the + matrix. It's possible to pre-calculate the matrix multiplications and just generate one transform matrix that will do everything we need in a single step, but the maths for each element is much more complex and performing the steps separately makes for more readable code. */ -#ifndef HAVE_HAIKU typedef double matrix3x3[3][3]; static void @@ -2528,7 +2528,6 @@ matrix3x3_mult (matrix3x3 a, matrix3x3 b, matrix3x3 result) result[i][j] = sum; } } -#endif /* not HAVE_HAIKU */ static void compute_image_rotation (struct image *img, double *rotation) @@ -2553,6 +2552,21 @@ compute_image_rotation (struct image *img, double *rotation) static void image_set_transform (struct frame *f, struct image *img) { + bool flip; + +#if defined HAVE_HAIKU + matrix3x3 identity = { + { 1, 0, 0 }, + { 0, 1, 0 }, + { 0, 0, 1 }, + }; + + img->original_width = img->width; + img->original_height = img->height; + + memcpy (&img->transform, identity, sizeof identity); +#endif + # if (defined HAVE_IMAGEMAGICK \ && !defined DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE) /* ImageMagick images already have the correct transform. */ @@ -2588,11 +2602,8 @@ image_set_transform (struct frame *f, struct image *img) compute_image_rotation (img, &rotation); /* Determine flipping. */ - bool flip; - Lisp_Object m = image_spec_value (img->spec, QCflip, NULL); - flip = !NILP (m); + flip = !NILP (image_spec_value (img->spec, QCflip, NULL)); -#ifndef HAVE_HAIKU # if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS /* We want scale up operations to use a nearest neighbor filter to show real pixels instead of munging them, but scale down @@ -2616,7 +2627,7 @@ image_set_transform (struct frame *f, struct image *img) : img->width / (double) width), [1][1] = (!IEEE_FLOATING_POINT && height == 0 ? DBL_MAX : img->height / (double) height), -# elif defined HAVE_NTGUI || defined HAVE_NS +# elif defined HAVE_NTGUI || defined HAVE_NS || defined HAVE_HAIKU [0][0] = (!IEEE_FLOATING_POINT && img->width == 0 ? DBL_MAX : width / (double) img->width), [1][1] = (!IEEE_FLOATING_POINT && img->height == 0 ? DBL_MAX @@ -2631,12 +2642,23 @@ image_set_transform (struct frame *f, struct image *img) /* Perform rotation transformation. */ int rotate_flag = -1; + + /* Haiku needs this, since the transformation is done on the basis + of the view, and not the image. */ +#ifdef HAVE_HAIKU + int extra_tx, extra_ty; + + extra_tx = 0; + extra_ty = 0; +#endif + if (rotation == 0 && !flip) rotate_flag = 0; else { # if (defined USE_CAIRO || defined HAVE_XRENDER \ - || defined HAVE_NTGUI || defined HAVE_NS) + || defined HAVE_NTGUI || defined HAVE_NS \ + || defined HAVE_HAIKU) int cos_r, sin_r; if (rotation == 0) { @@ -2648,6 +2670,11 @@ image_set_transform (struct frame *f, struct image *img) cos_r = 1; sin_r = 0; rotate_flag = 1; + +#ifdef HAVE_HAIKU + extra_tx = width; + extra_ty = 0; +#endif } else if (rotation == 90) { @@ -2656,12 +2683,24 @@ image_set_transform (struct frame *f, struct image *img) cos_r = 0; sin_r = 1; rotate_flag = 1; + +#ifdef HAVE_HAIKU + if (!flip) + extra_ty = height; + extra_tx = 0; +#endif } else if (rotation == 180) { cos_r = -1; sin_r = 0; rotate_flag = 1; + +#ifdef HAVE_HAIKU + if (!flip) + extra_tx = width; + extra_ty = height; +#endif } else if (rotation == 270) { @@ -2670,6 +2709,13 @@ image_set_transform (struct frame *f, struct image *img) cos_r = 0; sin_r = -1; rotate_flag = 1; + +#ifdef HAVE_HAIKU + extra_tx = width; + + if (flip) + extra_ty = height; +#endif } if (0 < rotate_flag) @@ -2779,35 +2825,17 @@ image_set_transform (struct frame *f, struct image *img) img->xform.eM22 = matrix[1][1]; img->xform.eDx = matrix[2][0]; img->xform.eDy = matrix[2][1]; -# endif -#else - if (rotation != 0 && - rotation != 90 && - rotation != 180 && - rotation != 270 && - rotation != 360) - { - image_error ("No native support for rotation by %g degrees", - make_float (rotation)); - return; - } - - rotation = fmod (rotation, 360.0); +# elif defined HAVE_HAIKU + /* Store the transform in the struct image for later. */ + memcpy (&img->transform, &matrix, sizeof matrix); - if (rotation == 90 || rotation == 270) + /* Also add the extra translations. */ + if (rotate_flag) { - int w = width; - width = height; - height = w; + img->transform[0][2] = extra_tx; + img->transform[1][2] = extra_ty; } - - img->have_be_transforms_p = rotation != 0 || (img->width != width) || (img->height != height); - img->be_rotate = rotation; - img->be_scale_x = 1.0 / (img->width / (double) width); - img->be_scale_y = 1.0 / (img->height / (double) height); - img->width = width; - img->height = height; -#endif /* not HAVE_HAIKU */ +#endif } #endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_TRANSFORMS */ commit fc46552dc8273e41e40b395b554eb0e3cfa386b9 Merge: b6238a26c9 1f6750b53a Author: Stefan Kangas Date: Sat Jun 25 06:30:26 2022 +0200 Merge from origin/emacs-28 1f6750b53a Avoid treating number as an enum in the org manual commit b6238a26c97341cf2c34c12cf25c580f64d06a78 Author: Lars Ingebrigtsen Date: Sat Jun 25 00:19:23 2022 +0200 Revert "Fix some byte-compilation warnings about subr-x" This reverts commit cd479aa8bd498da4d7980a7fe7a37e238761482f. This led to build failures when doing bootstraps. diff --git a/lisp/files.el b/lisp/files.el index c205407f99..a804f0088e 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -30,8 +30,7 @@ (eval-when-compile (require 'pcase) - (require 'easy-mmode) ; For `define-minor-mode'. - (require 'subr-x)) + (require 'easy-mmode)) ; For `define-minor-mode'. (defvar font-lock-keywords) diff --git a/lisp/isearch.el b/lisp/isearch.el index 0624858993..7650ebcfce 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -54,7 +54,6 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) -(eval-when-compile (require 'subr-x)) ;; Some additional options and constants. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index fc25767934..332488e6d4 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -31,7 +31,6 @@ (require 'cl-generic) (require 'lisp-mode) (eval-when-compile (require 'cl-lib)) -(eval-when-compile (require 'subr-x)) (define-abbrev-table 'emacs-lisp-mode-abbrev-table () "Abbrev table for Emacs Lisp mode. diff --git a/lisp/replace.el b/lisp/replace.el index 34c3d5299e..c5c24c7a36 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -30,7 +30,6 @@ (require 'text-mode) (eval-when-compile (require 'cl-lib)) -(eval-when-compile (require 'subr-x)) (defcustom case-replace t "Non-nil means `query-replace' should preserve case in replacements." diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 024459e647..5443904a73 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -24,7 +24,6 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) -(eval-when-compile (require 'subr-x)) (unless (featurep 'haiku) (error "%s: Loading haiku-win without having Haiku" invocation-name)) commit cdbb02a597298b7812b456fca3d61e223dc40b7c Author: Lars Ingebrigtsen Date: Fri Jun 24 20:16:51 2022 +0200 Allow toggling completion modes for `M-x' with `M-X' * doc/lispref/commands.texi (Interactive Call): Document it. * lisp/minibuffer.el (minibuffer-local-must-match-map): Bind 'M-X'. * lisp/simple.el (execute-extended-command-cycle): New command. (read-extended-command): Use it to allow toggling (bug#47215). (read-extended-command-1): Renamed from `read-extended-command'. (execute-extended-command-for-buffer): Factored out most of the code... (command-completion--command-for-this-buffer-function): ... to here. (extended-command-versions): New variable. This code is based on a patch by Felician Nemeth . diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 6f02218333..ed32814329 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -897,6 +897,10 @@ keymaps. This command is the normal definition of @kbd{M-S-x} (that's ``meta shift x''). @end deffn +Both these commands prompt for a command name, but with different +completion rules. You can toggle between these two modes by using the +@kbd{M-S-x} command while being prompted. + @node Distinguish Interactive @section Distinguish Interactive Calls @cindex distinguish interactive calls diff --git a/etc/NEWS b/etc/NEWS index cb9e7417b6..e3b4df227e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -314,6 +314,16 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 ++++ +** New key binding after 'M-x' or 'M-X': 'M-X'. +Emacs allows different completion predicates to be used with 'M-x' +(i.e., 'execute-extended-command') via the +'read-extended-command-predicate' user option. Emacs also has the +'M-X' (note upper case) command, which only displays commands +especially relevant to the current buffer. Emacs now allows toggling +between these modes while the user is inputting a command by hitting +'M-X' while in the minibuffer. + --- ** Interactively, 'kill-buffer' will now offer to save the buffer if unsaved. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index e42d83af34..9ffaff7c8e 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2780,6 +2780,7 @@ The completion method is determined by `completion-at-point-functions'." (defvar-keymap minibuffer-local-must-match-map :doc "Local keymap for minibuffer input with completion, for exact match." :parent minibuffer-local-completion-map + "M-X" #'execute-extended-command-cycle "RET" #'minibuffer-complete-and-exit "C-j" #'minibuffer-complete-and-exit) diff --git a/lisp/simple.el b/lisp/simple.el index 653cffae62..8f82ff3a8e 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2207,9 +2207,53 @@ in that buffer." command-completion-default-include-p) (function :tag "Other function"))) -(defun read-extended-command () +(defun execute-extended-command-cycle () + "Choose the next version of the extended command predicates. +See `extended-command-versions'." + (interactive) + (throw 'cycle + (cons (minibuffer-contents) + (- (point) (minibuffer-prompt-end))))) + +(defvar extended-command-versions + (list (list "M-x " (lambda () read-extended-command-predicate)) + (list "M-X " #'command-completion--command-for-this-buffer-function)) + "Alist of prompts and what the extended command predicate should be. +This is used by the \\\\[execute-extended-command-cycle] command when reading an extended command.") + +(defun read-extended-command (&optional prompt) "Read command name to invoke in `execute-extended-command'. This function uses the `read-extended-command-predicate' user option." + (let ((default-predicate read-extended-command-predicate) + (read-extended-command-predicate read-extended-command-predicate) + already-typed ret) + ;; If we have a prompt (which is the name of the version of the + ;; command), then set up the predicate from + ;; `extended-command-versions'. + (if (not prompt) + (setq prompt (caar extended-command-versions)) + (setq read-extended-command-predicate + (funcall (cadr (assoc prompt extended-command-versions))))) + ;; Normally this will only execute once. + (while (not (stringp ret)) + (when (consp (setq ret (catch 'cycle + (read-extended-command-1 prompt + already-typed)))) + ;; But if the user hit `M-X', then we `throw'ed out to that + ;; `catch', and we cycle to the next setting. + (let ((next (or (cadr (memq (assoc prompt extended-command-versions) + extended-command-versions)) + ;; Last one; cycle back to the first. + (car extended-command-versions)))) + ;; Restore the user's default predicate. + (setq read-extended-command-predicate default-predicate) + ;; Then calculate the next. + (setq prompt (car next) + read-extended-command-predicate (funcall (cadr next)) + already-typed ret)))) + ret)) + +(defun read-extended-command-1 (prompt initial-input) (let ((buffer (current-buffer))) (minibuffer-with-setup-hook (lambda () @@ -2234,8 +2278,8 @@ This function uses the `read-extended-command-predicate' user option." (cons def (delete def all)) all))))) ;; Read a string, completing from and restricting to the set of - ;; all defined commands. Don't provide any initial input. - ;; Save the command read on the extended-command history list. + ;; all defined commands. Save the command read on the + ;; extended-command history list. (completing-read (concat (cond ((eq current-prefix-arg '-) "- ") @@ -2253,9 +2297,7 @@ This function uses the `read-extended-command-predicate' user option." ;; but actually a prompt other than "M-x" would be confusing, ;; because "M-x" is a well-known prompt to read a command ;; and it serves as a shorthand for "Extended command: ". - (if (memq 'shift (event-modifiers last-command-event)) - "M-X " - "M-x ")) + (or prompt "M-x ")) (lambda (string pred action) (if (and suggest-key-bindings (eq action 'metadata)) '(metadata @@ -2294,7 +2336,7 @@ This function uses the `read-extended-command-predicate' user option." (funcall read-extended-command-predicate sym buffer) (error (message "read-extended-command-predicate: %s: %s" sym (error-message-string err)))))))) - t nil 'extended-command-history)))) + t initial-input 'extended-command-history)))) (defun command-completion-using-modes-p (symbol buffer) "Say whether SYMBOL has been marked as a mode-specific command in BUFFER." @@ -2525,36 +2567,37 @@ minor modes), as well as commands bound in the active local key maps." (declare (interactive-only command-execute)) (interactive - (let* ((execute-extended-command--last-typed nil) - (keymaps - ;; The major mode's keymap and any active minor modes. - (nconc - (and (current-local-map) (list (current-local-map))) - (mapcar - #'cdr - (seq-filter - (lambda (elem) - (symbol-value (car elem))) - minor-mode-map-alist)))) - (read-extended-command-predicate - (lambda (symbol buffer) - (or (command-completion-using-modes-p symbol buffer) - ;; Include commands that are bound in a keymap in the - ;; current buffer. - (and (where-is-internal symbol keymaps) - ;; But not if they have a command predicate that - ;; says that they shouldn't. (This is the case - ;; for `ignore' and `undefined' and similar - ;; commands commonly found in keymaps.) - (or (null (get symbol 'completion-predicate)) - (funcall (get symbol 'completion-predicate) - symbol buffer))))))) + (let ((execute-extended-command--last-typed nil)) (list current-prefix-arg - (read-extended-command) + (read-extended-command "M-X ") execute-extended-command--last-typed))) (with-suppressed-warnings ((interactive-only execute-extended-command)) (execute-extended-command prefixarg command-name typed))) +(defun command-completion--command-for-this-buffer-function () + (let ((keymaps + ;; The major mode's keymap and any active minor modes. + (nconc + (and (current-local-map) (list (current-local-map))) + (mapcar + #'cdr + (seq-filter + (lambda (elem) + (symbol-value (car elem))) + minor-mode-map-alist))))) + (lambda (symbol buffer) + (or (command-completion-using-modes-p symbol buffer) + ;; Include commands that are bound in a keymap in the + ;; current buffer. + (and (where-is-internal symbol keymaps) + ;; But not if they have a command predicate that + ;; says that they shouldn't. (This is the case + ;; for `ignore' and `undefined' and similar + ;; commands commonly found in keymaps.) + (or (null (get symbol 'completion-predicate)) + (funcall (get symbol 'completion-predicate) + symbol buffer))))))) + (cl-defgeneric function-documentation (function) "Extract the raw docstring info from FUNCTION. FUNCTION is expected to be a function value rather than, say, a mere symbol. commit 41c09d347feb94b9070a9aa2c78ccf65be7fd268 Author: Lars Ingebrigtsen Date: Fri Jun 24 14:54:43 2022 +0200 Make ido sorting respect ido-case-fold * lisp/ido.el (ido-file-lessp): (ido-file-extension-lessp): Respect ido-case-fold (bug#47127). diff --git a/lisp/ido.el b/lisp/ido.el index f970fce1ed..b3365059d2 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -3205,12 +3205,18 @@ instead removed from the current item list." ;; File list sorting (defun ido-file-lessp (a b) - ;; Simple compare two file names. + "Simple compare two file names." + (when ido-case-fold + (setq a (downcase a) + b (downcase b))) (string-lessp (ido-no-final-slash a) (ido-no-final-slash b))) (defun ido-file-extension-lessp (a b) - ;; Compare file names according to ido-file-extensions-order list. + "Compare file names according to ido-file-extensions-order list." + (when ido-case-fold + (setq a (downcase a) + b (downcase b))) (let ((n (compare-strings a 0 nil b 0 nil nil)) lessp p) (if (eq n t) commit 1f6750b53a872a5747dff92b8f61cfede0c5a6a6 Author: Stefan Kangas Date: Fri Jun 24 19:18:22 2022 +0200 Avoid treating number as an enum in the org manual * doc/misc/org.org (The Agenda Dispatcher): Avoid treating number as enum. diff --git a/doc/misc/org.org b/doc/misc/org.org index baab2efeda..b1dc708498 100644 --- a/doc/misc/org.org +++ b/doc/misc/org.org @@ -8544,8 +8544,8 @@ commands: Search for a regular expression in all agenda files and additionally in the files listed in ~org-agenda-text-search-extra-files~. This uses the Emacs command ~multi-occur~. A prefix argument can be used - to specify the number of context lines for each match, default is - 1. + to specify the number of context lines for each match, the default + is 1. - {{{kbd(#)}}} :: commit c7f141d67829ccef64a5e4e961f098f09774afe2 Author: Michael Albinus Date: Fri Jun 24 18:05:54 2022 +0200 Make url-tramp-convert-tramp-to-url more robust * lisp/url/url-tramp.el (url-tramp-convert-tramp-to-url): Prevent errors from not existing Tramp methods. diff --git a/lisp/url/url-tramp.el b/lisp/url/url-tramp.el index 2918192a45..c414a025a1 100644 --- a/lisp/url/url-tramp.el +++ b/lisp/url/url-tramp.el @@ -62,7 +62,8 @@ In case URL is not convertible, nil is returned." (defun url-tramp-convert-tramp-to-url (file) "Convert FILE, a Tramp file name, to a URL. In case FILE is not convertible, nil is returned." - (let* ((obj (and (tramp-tramp-file-p file) (tramp-dissect-file-name file))) + (let* ((obj (and (tramp-tramp-file-p file) + (ignore-errors (tramp-dissect-file-name file)))) (port (and obj (stringp (tramp-file-name-port obj)) (string-to-number (tramp-file-name-port obj))))) commit de0b7af169345442852622bb337483398c583a9e Author: Platon Pronko Date: Fri Jun 24 17:18:19 2022 +0200 Fix logic error in Tramp, setting file ownership * lisp/net/tramp.el (tramp-skeleton-write-region): Fix logic in changing file ownership. (Bug#56180) Copyright-paperwork-exempt: yes diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 59a2710e00..c6665c2792 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -3462,8 +3462,8 @@ BODY is the backend specific code." ;; `file-precious-flag' is set. (or (file-attribute-modification-time file-attr) (current-time))) - (unless (and (= (file-attribute-user-id file-attr) uid) - (= (file-attribute-group-id file-attr) gid)) + (when (and (= (file-attribute-user-id file-attr) uid) + (= (file-attribute-group-id file-attr) gid)) (setq need-chown nil)))) ;; Set the ownership. commit 6fbea946bfd0119cf517211d058ea277c9209a87 Author: Timo Taipalus Date: Fri Jun 24 14:44:02 2022 +0200 Add support for image flipping * lisp/image.el (image-map): Keybindings for flipping functions. (image-flip-horizontally): New function that toggles image flipping property. (image-flip-vertically): New function that toggles image flipping property and rotates image 180 degrees. * src/image.c (syms_of_image): Add property. (image_set_transform): Modify image rotation code to also horizontally flip the image when the property is set. * etc/NEWS: Add description. * doc/lispref/display.texi (Image Descriptors): Document :flip (bug#47095). diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 3d1d9e24dd..e85d492bbb 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5717,6 +5717,12 @@ are supported, unless the image type is @code{imagemagick}. Positive values rotate clockwise, negative values counter-clockwise. Rotation is performed after scaling and cropping. +@item :flip @var{flip} +If this is @code{t}, the image will be horizontally flipped. +Currently it has no effect if the image type is @code{imagemagick}. +Vertical flipping can be achieved by rotating the image 180 degrees +and toggling this value. + @item :transform-smoothing @var{smooth} If this is @code{t}, any image transform will have smoothing applied; if @code{nil}, no smoothing will be applied. The exact algorithm used diff --git a/etc/NEWS b/etc/NEWS index 552c8d1d49..cb9e7417b6 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1545,6 +1545,10 @@ This controls whether or not to show a message when opening certain image formats saying how to edit it as text. The default is to show this message for SVG and XPM. ++++ +*** New commands: 'image-flip-horizontally' and 'image-flip-vertically'. +These commands horizontally and vertically flip the image under point. + ** Image-Dired +++ diff --git a/lisp/image.el b/lisp/image.el index 8c5cfa7c0b..e90cccaa09 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -177,6 +177,8 @@ or \"ffmpeg\") is installed." "+" #'image-increase-size "r" #'image-rotate "o" #'image-save + "h" #'image-flip-horizontally + "v" #'image-flip-vertically "C-" #'image-mouse-decrease-size "C-" #'image-mouse-decrease-size "C-" #'image-mouse-increase-size @@ -1288,6 +1290,22 @@ changing the displayed image size does not affect the saved image." (write-region (point-min) (point-max) (read-file-name "Write image to file: "))))) +(defun image-flip-horizontally () + "Horizontally flip the image under point." + (interactive) + (let ((image (image--get-image))) + (image-flush image) + (setf (image-property image :flip) + (not (image-property image :flip))))) + +(defun image-flip-vertically () + "Vertically flip the image under point." + (interactive) + (let ((image (image--get-image))) + (image-rotate 180) + (setf (image-property image :flip) + (not (image-property image :flip))))) + (provide 'image) ;;; image.el ends here diff --git a/src/image.c b/src/image.c index 2e2f8fe364..0e4b2e0f62 100644 --- a/src/image.c +++ b/src/image.c @@ -2587,6 +2587,11 @@ image_set_transform (struct frame *f, struct image *img) double rotation = 0.0; compute_image_rotation (img, &rotation); + /* Determine flipping. */ + bool flip; + Lisp_Object m = image_spec_value (img->spec, QCflip, NULL); + flip = !NILP (m); + #ifndef HAVE_HAIKU # if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS /* We want scale up operations to use a nearest neighbor filter to @@ -2626,14 +2631,25 @@ image_set_transform (struct frame *f, struct image *img) /* Perform rotation transformation. */ int rotate_flag = -1; - if (rotation == 0) + if (rotation == 0 && !flip) rotate_flag = 0; else { # if (defined USE_CAIRO || defined HAVE_XRENDER \ || defined HAVE_NTGUI || defined HAVE_NS) int cos_r, sin_r; - if (rotation == 90) + if (rotation == 0) + { + /* FLIP is always true here. As this will rotate by 0 + degrees, it has no visible effect. Applying only + translation matrix to the image would be sufficient for + horizontal flipping, but writing special handling for + this case would increase code complexity somewhat. */ + cos_r = 1; + sin_r = 0; + rotate_flag = 1; + } + else if (rotation == 90) { width = img->height; height = img->width; @@ -2674,9 +2690,14 @@ image_set_transform (struct frame *f, struct image *img) matrix3x3 v; matrix3x3_mult (rot, u, v); - /* 3. Translate back. */ + /* 3. Translate back. Flip horizontally if requested. */ t[2][0] = width * -.5; t[2][1] = height * -.5; + if (flip) + { + t[0][0] = -t[0][0]; + t[2][0] = -t[2][0]; + } matrix3x3_mult (t, v, matrix); # else /* 1. Translate so (0, 0) is in the center of the image. */ @@ -2694,9 +2715,10 @@ image_set_transform (struct frame *f, struct image *img) matrix3x3 v; matrix3x3_mult (u, rot, v); - /* 3. Translate back. */ + /* 3. Translate back. Flip horizontally if requested. */ t[2][0] = width * .5; t[2][1] = height * .5; + if (flip) t[0][0] = -t[0][0]; matrix3x3_mult (v, t, matrix); # endif img->width = width; @@ -11940,6 +11962,7 @@ non-numeric, there is no explicit limit on the size of images. */); DEFSYM (QCtransform_smoothing, ":transform-smoothing"); DEFSYM (QCcolor_adjustment, ":color-adjustment"); DEFSYM (QCmask, ":mask"); + DEFSYM (QCflip, ":flip"); /* Other symbols. */ DEFSYM (Qlaplace, "laplace"); commit cd479aa8bd498da4d7980a7fe7a37e238761482f Author: Lars Ingebrigtsen Date: Fri Jun 24 14:35:23 2022 +0200 Fix some byte-compilation warnings about subr-x * lisp/term/haiku-win.el (require): * lisp/replace.el (require): * lisp/progmodes/elisp-mode.el (require): * lisp/isearch.el (require): * lisp/files.el (require): Require subr-x when compiling. diff --git a/lisp/files.el b/lisp/files.el index a804f0088e..c205407f99 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -30,7 +30,8 @@ (eval-when-compile (require 'pcase) - (require 'easy-mmode)) ; For `define-minor-mode'. + (require 'easy-mmode) ; For `define-minor-mode'. + (require 'subr-x)) (defvar font-lock-keywords) diff --git a/lisp/isearch.el b/lisp/isearch.el index 7650ebcfce..0624858993 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -54,6 +54,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) ;; Some additional options and constants. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 332488e6d4..fc25767934 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -31,6 +31,7 @@ (require 'cl-generic) (require 'lisp-mode) (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) (define-abbrev-table 'emacs-lisp-mode-abbrev-table () "Abbrev table for Emacs Lisp mode. diff --git a/lisp/replace.el b/lisp/replace.el index c5c24c7a36..34c3d5299e 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -30,6 +30,7 @@ (require 'text-mode) (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) (defcustom case-replace t "Non-nil means `query-replace' should preserve case in replacements." diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 5443904a73..024459e647 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -24,6 +24,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) (unless (featurep 'haiku) (error "%s: Loading haiku-win without having Haiku" invocation-name)) commit 4ca11a99b3658333e49d59ef2989d21783f537df Author: Lars Ingebrigtsen Date: Fri Jun 24 14:11:45 2022 +0200 Fix imenu popup syntax * lisp/imenu.el (imenu--create-keymap): Fix menu syntax (bug#56185). diff --git a/lisp/imenu.el b/lisp/imenu.el index 2636e77d08..4393c6ed6c 100644 --- a/lisp/imenu.el +++ b/lisp/imenu.el @@ -464,7 +464,7 @@ Non-nil arguments are in recursive calls." `(keymap ,title ,@(mapcar (lambda (item) - `(,(car item) ,(car item) + `(,(intern (car item)) ,(car item) ,@(cond ((imenu--subalist-p item) (imenu--create-keymap (car item) (cdr item) cmd)) commit 81e58d1ce5a16fbe4cad543b1b011fe52da5d70c Merge: 391acd9134 a772c0b852 Author: Stefan Kangas Date: Fri Jun 24 13:52:51 2022 +0200 Merge from origin/emacs-28 a772c0b852 ; Fix typos: prefer US spelling. # Conflicts: # doc/misc/modus-themes.org commit 391acd91344c833d94d89b2862b272d08643c068 Author: Eli Zaretskii Date: Fri Jun 24 14:14:41 2022 +0300 Fix assertion violation when 'max-redisplay-ticks' is set too low * src/xdisp.c (update_redisplay_ticks): Disable 'scrolling_window' optimization in 'update_window' when redisplay of a window is aborted. (Bug#56184) diff --git a/src/xdisp.c b/src/xdisp.c index 2e3711a20d..c37a58ab4e 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -17250,6 +17250,11 @@ update_redisplay_ticks (int ticks, struct window *w) : (char *) ""); windows_or_buffers_changed = 177; + /* scrolling_window depends too much on the glyph matrices being + correct, and we cannot guarantee that if we abort the + redisplay of this window. */ + if (w && w->desired_matrix) + w->desired_matrix->no_scrolling_p = true; error ("Window showing buffer %s takes too long to redisplay", bufname); } } commit 66669c5c200d00f7fc4b112f3c418a3796915fee Author: Lars Ingebrigtsen Date: Fri Jun 24 11:57:02 2022 +0200 Add NEWS entry about kill-buffer change diff --git a/etc/NEWS b/etc/NEWS index 3ed7aae220..552c8d1d49 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -314,6 +314,9 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 +--- +** Interactively, 'kill-buffer' will now offer to save the buffer if unsaved. + --- ** New command 'duplicate-line'. This command duplicates the current line the specified number of times. commit 253a4a2c689d757cb798cfb9f51b2110283d7146 Author: Mattias Engdegård Date: Fri Jun 24 11:48:42 2022 +0200 Bytecode opcode comments update This is a cosmetic change only; there is no change in behaviour. * lisp/emacs-lisp/bytecomp.el: * src/bytecode.c (BYTE_CODES, exec_byte_code): Update and/or remove incorrect, outdated or useless comments. Clarify. Reorder where appropriate. Rename Bsave_current_buffer to Bsave_current_buffer_OBSOLETE and Bsave_current_buffer_1 to Bsave_current_buffer, reflecting the state since 1996. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index a8c68f8153..bd3db85c14 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -681,10 +681,13 @@ Each element is (INDEX . VALUE)") (put 'byte-stack+-info 'tmp-compile-time-value nil))) -;; These opcodes are special in that they pack their argument into the -;; opcode word. -;; +;; The following opcodes (1-47) use the 3 lowest bits for an immediate +;; argument. + (byte-defop 0 1 byte-stack-ref "for stack reference") +;; Code 0 is actually unused but reserved as invalid code for detecting +;; corrupted bytecode. Codes 1-7 are stack-ref. + (byte-defop 8 1 byte-varref "for variable reference") (byte-defop 16 -1 byte-varset "for setting a variable") (byte-defop 24 -1 byte-varbind "for binding a variable") @@ -692,11 +695,9 @@ Each element is (INDEX . VALUE)") (byte-defop 40 0 byte-unbind "for unbinding special bindings") ;; codes 8-47 are consumed by the preceding opcodes -;; New (in Emacs-24.4) bytecodes for more efficient handling of non-local exits -;; (especially useful in lexical-binding code). (byte-defop 48 0 byte-pophandler) -(byte-defop 50 -1 byte-pushcatch) (byte-defop 49 -1 byte-pushconditioncase) +(byte-defop 50 -1 byte-pushcatch) ;; unused: 51-55 @@ -719,9 +720,9 @@ Each element is (INDEX . VALUE)") (byte-defop 72 -1 byte-aref) (byte-defop 73 -2 byte-aset) (byte-defop 74 0 byte-symbol-value) -(byte-defop 75 0 byte-symbol-function) ; this was commented out +(byte-defop 75 0 byte-symbol-function) (byte-defop 76 -1 byte-set) -(byte-defop 77 -1 byte-fset) ; this was commented out +(byte-defop 77 -1 byte-fset) (byte-defop 78 -1 byte-get) (byte-defop 79 -2 byte-substring) (byte-defop 80 -1 byte-concat2) @@ -739,8 +740,9 @@ Each element is (INDEX . VALUE)") (byte-defop 92 -1 byte-plus) (byte-defop 93 -1 byte-max) (byte-defop 94 -1 byte-min) -(byte-defop 95 -1 byte-mult) ; v19 only +(byte-defop 95 -1 byte-mult) (byte-defop 96 1 byte-point) +(byte-defop 97 0 byte-save-current-buffer-OBSOLETE) ; unused since v20 (byte-defop 98 0 byte-goto-char) (byte-defop 99 0 byte-insert) (byte-defop 100 1 byte-point-max) @@ -762,7 +764,6 @@ Each element is (INDEX . VALUE)") (byte-defop 115 0 byte-set-mark-OBSOLETE) (byte-defop 116 1 byte-interactive-p-OBSOLETE) -;; These ops are new to v19 (byte-defop 117 0 byte-forward-char) (byte-defop 118 0 byte-forward-word) (byte-defop 119 -1 byte-skip-chars-forward) @@ -819,7 +820,6 @@ the unwind-action") ;; unused: 146 -;; these ops are new to v19 (byte-defop 147 -2 byte-set-marker) (byte-defop 148 0 byte-match-beginning) (byte-defop 149 0 byte-match-end) @@ -866,10 +866,11 @@ the unwind-action") "to take a hash table and a value from the stack, and jump to the address the value maps to, if any.") -;; unused: 182-191 +;; unused: 184-191 (byte-defop 192 1 byte-constant "for reference to a constant") -;; codes 193-255 are consumed by byte-constant. +;; Codes 193-255 are consumed by `byte-constant', which uses the 6 +;; lowest bits for an immediate argument. (defconst byte-constant-limit 64 "Exclusive maximum index usable in the `byte-constant' opcode.") diff --git a/src/bytecode.c b/src/bytecode.c index fa068e1ec6..d75767bb0c 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -176,8 +176,8 @@ DEFINE (Bmin, 0136) \ DEFINE (Bmult, 0137) \ \ DEFINE (Bpoint, 0140) \ -/* Was Bmark in v17. */ \ -DEFINE (Bsave_current_buffer, 0141) /* Obsolete. */ \ +/* 0141 was Bmark in v17, Bsave_current_buffer in 18-19. */ \ +DEFINE (Bsave_current_buffer_OBSOLETE, 0141) /* Obsolete since 20. */ \ DEFINE (Bgoto_char, 0142) \ DEFINE (Binsert, 0143) \ DEFINE (Bpoint_max, 0144) \ @@ -194,7 +194,7 @@ DEFINE (Bbolp, 0156) \ DEFINE (Bbobp, 0157) \ DEFINE (Bcurrent_buffer, 0160) \ DEFINE (Bset_buffer, 0161) \ -DEFINE (Bsave_current_buffer_1, 0162) /* Replacing Bsave_current_buffer. */ \ +DEFINE (Bsave_current_buffer, 0162) \ /* 0163 was Bset_mark in v17. */ \ DEFINE (Binteractive_p, 0164) /* Obsolete since Emacs-24.1. */ \ \ @@ -924,8 +924,8 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, record_unwind_protect_excursion (); NEXT; - CASE (Bsave_current_buffer): /* Obsolete since ??. */ - CASE (Bsave_current_buffer_1): + CASE (Bsave_current_buffer_OBSOLETE): /* Obsolete since 20. */ + CASE (Bsave_current_buffer): record_unwind_current_buffer (); NEXT; @@ -1678,6 +1678,12 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, /* TODO: Perhaps introduce another byte-code for switch when the number of cases is less, which uses a simple vector for linear search as the jump table. */ + + /* TODO: Instead of pushing the table in a separate + Bconstant op, use an immediate argument (maybe separate + switch opcodes for 1-byte and 2-byte constant indices). + This would also get rid of some hacks that assume each + Bswitch to be preceded by a Bconstant. */ Lisp_Object jmp_table = POP; if (BYTE_CODE_SAFE && !HASH_TABLE_P (jmp_table)) emacs_abort (); commit 0c784a483f98d6bea4d955a99bbf5ea6faf80acf Author: Lars Ingebrigtsen Date: Fri Jun 24 11:15:19 2022 +0200 Update seq.el comment * lisp/emacs-lisp/seq.el: Update comment. diff --git a/lisp/emacs-lisp/seq.el b/lisp/emacs-lisp/seq.el index 133d3c9e11..947b64e868 100644 --- a/lisp/emacs-lisp/seq.el +++ b/lisp/emacs-lisp/seq.el @@ -59,8 +59,8 @@ (eval-when-compile (require 'cl-generic)) ;; We used to use some sequence functions from cl-lib, but this -;; dependency was swapped around so that it will be easier to make -;; seq.el preloaded in the future. See also Bug#39761#26. +;; dependency was swapped around so that it's easier to make seq.el +;; preloaded. See also Bug#39761#26. (defmacro seq-doseq (spec &rest body) "Loop over a sequence. commit e193ea3c34b01a09806cffbca2d3b5657881419b Author: Lars Ingebrigtsen Date: Fri Jun 24 11:04:03 2022 +0200 Allow `kill-buffer' query to save the buffer first * lisp/loadup.el ("emacs-lisp/rmc"): Preload. * lisp/simple.el (kill-buffer--possibly-save): New function to offer to save the buffer before killing (bug#47075). * src/buffer.c (Fkill_buffer): Call the new function to query the user. (syms_of_buffer): Define symbol. diff --git a/lisp/loadup.el b/lisp/loadup.el index 1d834da5b2..21a87dbd77 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -397,6 +397,9 @@ (message "Warning: Change in load-path due to site-load will be \ lost after dumping"))) +;; Used by `kill-buffer', for instance. +(load "emacs-lisp/rmc") + ;; Make sure default-directory is unibyte when dumping. This is ;; because we cannot decode and encode it correctly (since the locale ;; environment is not, and should not be, set up). default-directory diff --git a/lisp/simple.el b/lisp/simple.el index f2b3d82a7a..653cffae62 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -10560,6 +10560,23 @@ If the buffer doesn't exist, create it first." (interactive) (pop-to-buffer-same-window (get-scratch-buffer-create))) +(defun kill-buffer--possibly-save (buffer) + (let ((response + (cadr + (read-multiple-choice + (format "Buffer %s modified; kill anyway?" + (buffer-name)) + '((?y "yes" "kill buffer without saving") + (?n "no" "exit without doing anything") + (?s "save and then kill" "save the buffer and then kill it")) + nil nil (not use-short-answers))))) + (if (equal response "no") + nil + (unless (equal response "yes") + (with-current-buffer buffer + (save-buffer))) + t))) + (provide 'simple) diff --git a/src/buffer.c b/src/buffer.c index 7adcd22d88..509ce51b55 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1809,10 +1809,12 @@ cleaning up all windows currently displaying the buffer to be killed. */) /* Query if the buffer is still modified. */ if (INTERACTIVE && modified) { - AUTO_STRING (format, "Buffer %s modified; kill anyway? "); - tem = do_yes_or_no_p (CALLN (Fformat, format, BVAR (b, name))); - if (NILP (tem)) + /* Ask whether to kill the buffer, and exit if the user says + "no". */ + if (NILP (call1 (Qkill_buffer__possibly_save, buffer))) return unbind_to (count, Qnil); + /* Recheck modified. */ + modified = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b); } /* Delete the autosave file, if requested. */ @@ -6474,5 +6476,7 @@ will run for `clone-indirect-buffer' calls as well. */); DEFSYM (Qautosaved, "autosaved"); + DEFSYM (Qkill_buffer__possibly_save, "kill-buffer--possibly-save"); + Fput (intern_c_string ("erase-buffer"), Qdisabled, Qt); } commit f2b7525e3875cdf5a9b01ca21bc393367ec1f703 Author: Lars Ingebrigtsen Date: Fri Jun 24 11:02:14 2022 +0200 Preload seq * lisp/loadup.el ("emacs-lisp/seq"): Preload seq since it's now almost impossible to do anything in Emacs that doesn't result in seq being loaded -- for instance, visiting a .txt file or an .el file, so this will speed up Emacs usage for basically everybody. diff --git a/lisp/loadup.el b/lisp/loadup.el index f076b8b289..1d834da5b2 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -253,6 +253,7 @@ ;; A particularly demanding file to load; 1600 does not seem to be enough. (load "emacs-lisp/cl-generic")) (load "simple") +(load "emacs-lisp/seq") (load "emacs-lisp/nadvice") (load "minibuffer") ;Needs cl-generic (and define-minor-mode). (load "frame") commit bed9fd41efc72526a7fddcbe73c2ad9a97495356 Author: Lars Ingebrigtsen Date: Fri Jun 24 11:00:06 2022 +0200 Allow read-multiple-choice to do long-form answers * doc/lispref/commands.texi (Reading One Event): Document it. * lisp/emacs-lisp/rmc.el (read-multiple-choice): Allow using long-form answers instead of single character ones. (read-multiple-choice--long-answers): New function. (read-multiple-choice--short-answers): Refactored out from the main function. diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 0a82bba3bc..6f02218333 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -3198,7 +3198,7 @@ causes it to evaluate @code{help-form} and display the result. It then continues to wait for a valid input character, or keyboard-quit. @end defun -@defun read-multiple-choice prompt choices &optional help-string show-help +@defun read-multiple-choice prompt choices &optional help-string show-help long-form Ask user a multiple choice question. @var{prompt} should be a string that will be displayed as the prompt. @@ -3217,6 +3217,11 @@ If optional argument @var{show-help} is non-@code{nil}, the help buffer will be displayed immediately, before any user input. If it is a string, use it as the name of the help buffer. +If optional argument @var{long-form} is non-@code{nil}, the user +will have to type in long-form answers (using @code{completing-read}) +instead of hitting a single key. The answers must be among the second +elements of the values in the @var{choices} list. + The return value is the matching value from @var{choices}. @lisp diff --git a/etc/NEWS b/etc/NEWS index 7ef7109274..3ed7aae220 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2104,6 +2104,9 @@ patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el. * Lisp Changes in Emacs 29.1 ++++ +** 'read-multiple-choice' can now use long-form answers. + +++ ** 'read-regexp' now allows the user to indicate whether to use case folding. diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el index 195035e6be..dae6590b9b 100644 --- a/lisp/emacs-lisp/rmc.el +++ b/lisp/emacs-lisp/rmc.el @@ -23,8 +23,6 @@ ;;; Code: -(require 'seq) - (defun rmc--add-key-description (elem) (let* ((char (car elem)) (name (cadr elem)) @@ -125,7 +123,8 @@ buf)) ;;;###autoload -(defun read-multiple-choice (prompt choices &optional help-string show-help) +(defun read-multiple-choice (prompt choices &optional help-string show-help + long-form) "Ask user to select an entry from CHOICES, promting with PROMPT. This function allows to ask the user a multiple-choice question. @@ -163,12 +162,21 @@ dialogs. Otherwise, the function will always use text-mode dialogs. The return value is the matching entry from the CHOICES list. +If LONG-FORM, do a `completing-read' over the NAME elements in +CHOICES instead. + Usage example: \(read-multiple-choice \"Continue connecting?\" \\='((?a \"always\") (?s \"session only\") (?n \"no\")))" + (if long-form + (read-multiple-choice--long-answers prompt choices) + (read-multiple-choice--short-answers + prompt choices help-string show-help))) + +(defun read-multiple-choice--short-answers (prompt choices help-string show-help) (let* ((prompt-choices (if show-help choices (append choices '((?? "?"))))) (altered-names (mapcar #'rmc--add-key-description prompt-choices)) @@ -244,6 +252,17 @@ Usage example: (kill-buffer buf)) (assq tchar choices))) +(defun read-multiple-choice--long-answers (prompt choices) + (let ((answer + (completing-read + (concat prompt " (" + (mapconcat #'identity (mapcar #'cadr choices) "/") + ") ") + (mapcar #'cadr choices) nil t))) + (seq-find (lambda (elem) + (equal (cadr elem) answer)) + choices))) + (provide 'rmc) ;;; rmc.el ends here commit 49910adf872a98d9c144d34478a53ecb3e01856f Author: Lars Ingebrigtsen Date: Fri Jun 24 10:54:01 2022 +0200 Fix cl-generic bootstrap problems * lisp/sqlite-mode.el (require): * lisp/net/eudc.el (require): * lisp/arc-mode.el (require): Require subr-x, since these files are using macros from there. * lisp/emacs-lisp/subr-x.el (with-memoization): Move from here... * lisp/subr.el (with-memoization): ... to here, as it's used from the preloaded cl-generic.el file. * lisp/emacs-lisp/cl-generic.el (cl--generic-compiler): Don't use the autoloaded `byte-compile' function during bootstrap. (cl--generic-get-dispatcher): Don't require subr-x, either. cl-generic has been preloaded since 2015, and most usages of it (in preloaded files) work fine. In particular, using `cl-defgeneric' is unproblematic. However, `cl-defmethod' would end up pulling in the byte compiler (at load time), which would make it impossible to use `cl-defmethod' in pre-loaded files, and this change fixes that (but possibly not in the most self-evidently correct way). diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el index 1c5faa1152..c52f2a4432 100644 --- a/lisp/arc-mode.el +++ b/lisp/arc-mode.el @@ -101,6 +101,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) ;; ------------------------------------------------------------------------- ;;; Section: Configuration. diff --git a/lisp/emacs-lisp/cl-generic.el b/lisp/emacs-lisp/cl-generic.el index 200af057cd..6c5813959f 100644 --- a/lisp/emacs-lisp/cl-generic.el +++ b/lisp/emacs-lisp/cl-generic.el @@ -658,8 +658,10 @@ The set of acceptable TYPEs (also called \"specializers\") is defined ;; compiled. Otherwise the byte-compiler and all the code on ;; which it depends needs to be usable before cl-generic is loaded, ;; which imposes a significant burden on the bootstrap. - (if (consp (lambda (x) (+ x 1))) - (lambda (exp) (eval exp t)) #'byte-compile)) + (if (or (consp (lambda (x) (+ x 1))) + (not (featurep 'bytecomp))) + (lambda (exp) (eval exp t)) + #'byte-compile)) (defun cl--generic-get-dispatcher (dispatch) (with-memoization @@ -708,9 +710,6 @@ The set of acceptable TYPEs (also called \"specializers\") is defined (funcall cl--generic-compiler `(lambda (generic dispatches-left methods) - ;; FIXME: We should find a way to expand `with-memoize' once - ;; and forall so we don't need `subr-x' when we get here. - (eval-when-compile (require 'subr-x)) (let ((method-cache (make-hash-table :test #'eql))) (lambda (,@fixedargs &rest args) (let ,bindings diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 5c3dff62c8..b0de5d155a 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -290,19 +290,6 @@ as the new values of the bound variables in the recursive invocation." (cl-labels ((,name ,fargs . ,body)) #',name) . ,aargs))) -(defmacro with-memoization (place &rest code) - "Return the value of CODE and stash it in PLACE. -If PLACE's value is non-nil, then don't bother evaluating CODE -and return the value found in PLACE instead." - (declare (indent 1) (debug (gv-place body))) - (gv-letplace (getter setter) place - `(or ,getter - ,(macroexp-let2 nil val (macroexp-progn code) - `(progn - ,(funcall setter val) - ,val))))) - - ;;;###autoload (defun string-pixel-width (string) "Return the width of STRING in pixels." diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el index 808d2ca509..1d9dbbeb75 100644 --- a/lisp/net/eudc.el +++ b/lisp/net/eudc.el @@ -48,6 +48,7 @@ (require 'wid-edit) (require 'cl-lib) (require 'eudc-vars) +(eval-when-compile (require 'subr-x)) ;;{{{ Internal cooking diff --git a/lisp/sqlite-mode.el b/lisp/sqlite-mode.el index 66e2e487d9..fb2ceab383 100644 --- a/lisp/sqlite-mode.el +++ b/lisp/sqlite-mode.el @@ -24,6 +24,7 @@ ;;; Code: (require 'cl-lib) +(eval-when-compile (require 'subr-x)) (declare-function sqlite-execute "sqlite.c") (declare-function sqlite-more-p "sqlite.c") diff --git a/lisp/subr.el b/lisp/subr.el index 04eec977bb..075bfb95b7 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -6912,4 +6912,16 @@ CONDITION." (push buf bufs))) bufs)) +(defmacro with-memoization (place &rest code) + "Return the value of CODE and stash it in PLACE. +If PLACE's value is non-nil, then don't bother evaluating CODE +and return the value found in PLACE instead." + (declare (indent 1) (debug (gv-place body))) + (gv-letplace (getter setter) place + `(or ,getter + ,(macroexp-let2 nil val (macroexp-progn code) + `(progn + ,(funcall setter val) + ,val))))) + ;;; subr.el ends here diff --git a/test/lisp/custom-tests.el b/test/lisp/custom-tests.el index 77bb337d6a..d1effaa72a 100644 --- a/test/lisp/custom-tests.el +++ b/test/lisp/custom-tests.el @@ -24,6 +24,7 @@ (require 'wid-edit) (require 'cus-edit) +(require 'bytecomp) (ert-deftest custom-theme--load-path () "Test `custom-theme--load-path' behavior." diff --git a/test/lisp/emacs-lisp/cconv-tests.el b/test/lisp/emacs-lisp/cconv-tests.el index 0668e44ba5..9904c6a969 100644 --- a/test/lisp/emacs-lisp/cconv-tests.el +++ b/test/lisp/emacs-lisp/cconv-tests.el @@ -24,6 +24,7 @@ (require 'ert) (require 'cl-lib) (require 'generator) +(require 'bytecomp) (ert-deftest cconv-tests-lambda-:documentation () "Docstring for lambda can be specified with :documentation." commit 2ff5cb4cb4420e2b18ea8451ad0b29f1a69bdb6c Author: Lars Ingebrigtsen Date: Fri Jun 24 10:45:34 2022 +0200 Make warning about require/autoload while bootstrapping not error out * src/fns.c (Frequire): * src/eval.c (Fautoload_do_load): Avoid further errors while outputting the error about not being able to autoload/require while bootstrapping. diff --git a/src/eval.c b/src/eval.c index 346dff8bdc..141d2546f0 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2273,8 +2273,13 @@ it defines a macro. */) /* This is to make sure that loadup.el gives a clear picture of what files are preloaded and when. */ if (will_dump_p () && !will_bootstrap_p ()) - error ("Attempt to autoload %s while preparing to dump", - SDATA (SYMBOL_NAME (funname))); + { + /* Avoid landing here recursively while outputting the + backtrace from the error. */ + gflags.will_dump_ = false; + error ("Attempt to autoload %s while preparing to dump", + SDATA (SYMBOL_NAME (funname))); + } CHECK_SYMBOL (funname); diff --git a/src/fns.c b/src/fns.c index 4a9954ce90..5ee8482d00 100644 --- a/src/fns.c +++ b/src/fns.c @@ -3121,8 +3121,13 @@ FILENAME are suppressed. */) /* This is to make sure that loadup.el gives a clear picture of what files are preloaded and when. */ if (will_dump_p () && !will_bootstrap_p ()) - error ("(require %s) while preparing to dump", - SDATA (SYMBOL_NAME (feature))); + { + /* Avoid landing here recursively while outputting the + backtrace from the error. */ + gflags.will_dump_ = false; + error ("(require %s) while preparing to dump", + SDATA (SYMBOL_NAME (feature))); + } /* A certain amount of recursive `require' is legitimate, but if we require the same feature recursively 3 times, commit bd1f20eea199d61a8b1db602392d8e17af624ff2 Author: Lars Ingebrigtsen Date: Fri Jun 24 10:43:41 2022 +0200 Make debug-early-backtrace more resilient * lisp/emacs-lisp/debug-early.el (debug-early-backtrace): Allow outputting backtraces during bootstrap. diff --git a/lisp/emacs-lisp/debug-early.el b/lisp/emacs-lisp/debug-early.el index 4f1f4b8155..a301c73017 100644 --- a/lisp/emacs-lisp/debug-early.el +++ b/lisp/emacs-lisp/debug-early.el @@ -45,7 +45,13 @@ of the build process." (let ((print-escape-newlines t) (print-escape-control-characters t) (print-escape-nonascii t) - (prin1 (if (fboundp 'cl-prin1) #'cl-prin1 #'prin1))) + (prin1 (if (and (fboundp 'cl-prin1) + ;; If we're being called while + ;; bootstrapping, we won't be able to load + ;; cl-print. + (require 'cl-print nil t)) + #'cl-prin1 + #'prin1))) (mapbacktrace #'(lambda (evald func args _flags) (let ((args args)) commit c148bfc229e4d305a8e45595b1b0aa8ae21ef7de Author: Po Lu Date: Fri Jun 24 16:41:12 2022 +0800 Fix handling of mouse motion across screens during drag-and-drop * src/xterm.c (x_dnd_fill_empty_target): New function. (handle_one_xevent): Fill empty target if the event didn't come from the same screen. diff --git a/src/xterm.c b/src/xterm.c index 414a9c0ebe..d03b9a6d61 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3893,6 +3893,18 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo kbd_buffer_store_event (&ie); } +static Window +x_dnd_fill_empty_target (int *proto_out, int *motif_out, + Window *toplevel_out, bool *was_frame) +{ + *proto_out = -1; + *motif_out = XM_DRAG_STYLE_NONE; + *toplevel_out = None; + *was_frame = false; + + return None; +} + static Window x_dnd_get_target_window (struct x_display_info *dpyinfo, int root_x, int root_y, int *proto_out, @@ -18111,12 +18123,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } - target = x_dnd_get_target_window (dpyinfo, - event->xmotion.x_root, - event->xmotion.y_root, - &target_proto, - &motif_style, &toplevel, - &was_frame); + if (event->xmotion.same_screen) + target = x_dnd_get_target_window (dpyinfo, + event->xmotion.x_root, + event->xmotion.y_root, + &target_proto, + &motif_style, &toplevel, + &was_frame); + else + target = x_dnd_fill_empty_target (&target_proto, &motif_style, + &toplevel, &was_frame); if (toplevel != x_dnd_last_seen_toplevel) { @@ -19837,13 +19853,19 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } - target = x_dnd_get_target_window (dpyinfo, - xev->root_x, - xev->root_y, - &target_proto, - &motif_style, - &toplevel, - &was_frame); + if (xev->root == dpyinfo->root_window) + target = x_dnd_get_target_window (dpyinfo, + xev->root_x, + xev->root_y, + &target_proto, + &motif_style, + &toplevel, + &was_frame); + else + target = x_dnd_fill_empty_target (&target_proto, + &motif_style, + &toplevel, + &was_frame); if (toplevel != x_dnd_last_seen_toplevel) { commit 9f3ce27e56f5fa1053f2abcbcbd375cc0a75f283 Author: Po Lu Date: Fri Jun 24 16:31:45 2022 +0800 ; * etc/PROBLEMS: Fix errors in last change. diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 20b417f205..88382f93d0 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -1770,9 +1770,9 @@ restart the X server after the monitor configuration has been changed. *** Touchpad gestures don't work and/or emit warning messages. -Support for touch gestures in Emacs requires version 21.1.0 or later -of the X.Org server, and it requires that Emacs be built with the -xf86-input-libinput library that is new enough +Support for touch gestures in Emacs requires a sufficiently new X +server. We currently know of only one: version 21.1.0 or later of the +X.Org server, coupled with the xf86-input-libinput input driver. Type 'M-: (x-server-input-extension-version) RET'; if that doesn't return '(2 4)' (version 2.4) or later, your version of the X server commit 4266871467ebcd67ea978e28a9b9ebfccd9b4d6d Author: Lars Ingebrigtsen Date: Fri Jun 24 08:57:30 2022 +0200 Fix previous nnimap header fetching change * lisp/gnus/nnimap.el (nnimap-retrieve-headers): Ensure that the splitting works. diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index c158367b73..a69b5c7727 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -239,7 +239,7 @@ during splitting, which may be slow." (when (nnimap-change-group group server) (with-current-buffer (nnimap-buffer) (erase-buffer) - (let ((ranges (gnus-compress-sequence articles)) + (let ((ranges (gnus-compress-sequence articles t)) sequence) ;; If we have a lot of ranges, split them up to avoid ;; generating too-long lines. (The limit is 8192 octects, commit 289b457cac1439ac5f9bb6ce1143d91b8d52da91 Merge: fbb703f60a 6fcd8ca743 Author: Eli Zaretskii Date: Fri Jun 24 10:44:44 2022 +0300 Merge branch 'abort-redisplay' This allows abandoning the redisplay of a window that takes too long to complete. Bug#45898 * src/xdisp.c (update_redisplay_ticks): New function. (init_iterator, set_iterator_to_next): Call 'update_redisplay_ticks'. (syms_of_xdisp) : New variable. : Remove 'void-variable': it is no longer needed, since 'calc_pixel_width_or_height' can no longer signal a void-variable error, and it gets in the way of aborting redisplay via 'redisplay_window_error'. * src/keyboard.c (command_loop_1): Reinitialize the tick count before executing each command in the loop. * src/syntax.c (scan_sexps_forward): Call 'update_redisplay_ticks' after finishing the loop. * src/dispnew.c (make_current): Make sure enabled rows of the current matrix have a valid hash, even if redisplay of a window was aborted due to slowness. This avoids assertion violations in 'scrolling_window' due to the wrong hash value. * src/xdisp.c (display_working_on_window_p): New global variable. (unwind_display_working_on_window): New function. * src/keyboard.c (command_loop_1): Reset 'display_working_on_window_p' before and after executing commands. * src/window.c (Frecenter, window_scroll, displayed_window_lines): * src/indent.c (Fvertical_motion): Set 'display_working_on_window_p' before calling 'start_display'. * src/syntax.c (scan_sexps_forward): Call 'update_redisplay_ticks' after finishing the loop. * src/regex-emacs.c (re_match_2_internal): * src/bidi.c (bidi_find_bracket_pairs, bidi_fetch_char) (bidi_paragraph_init, bidi_find_other_level_edge): Update the redisplay tick count as appropriate, when moving the iterator by one character position actually requires to examine many more positions. * src/xdisp.c (redisplay_window_error): Show messages about aborted redisplay of a window as delayed-warnings. * doc/emacs/trouble.texi (DEL Does Not Delete): Move to the end of the chapter. This issue is no longer frequent or important as it was back in Emacs 20 days. (Long Lines): Document 'max-redisplay-ticks'. * doc/emacs/emacs.texi (Top): Update the detailed menu. * etc/NEWS: Announce 'max-redisplay-ticks'. commit 6fcd8ca743c35566e9216fd0681914fde05761b3 Author: Eli Zaretskii Date: Fri Jun 24 10:23:16 2022 +0300 ; * etc/NEWS: Minor update of description of 'max-redisplay-ticks'. diff --git a/etc/NEWS b/etc/NEWS index fa54d68a10..a8582e6270 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -749,7 +749,7 @@ Use it if you want Imenu to forget the buffer's index alist and recreate it anew next time 'imenu' is invoked. +++ -** Emacs is now capable of aborting too-long redisplay processing. +** Emacs is now capable of abandoning a window's redisplay that takes too long. This is controlled by the new variable 'max-redisplay-ticks'. If that variable is set to a non-zero value, display of a window will be aborted after that many low-level redisplay operations, thus commit fbb703f60aa9bbe3a0c60ee6e52d60d58126999f Author: Eli Zaretskii Date: Fri Jun 24 10:09:39 2022 +0300 ; * etc/PROBLEMS: Update the touch-gestures section. diff --git a/etc/PROBLEMS b/etc/PROBLEMS index 018efcf302..20b417f205 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -1768,7 +1768,15 @@ This happens on the proprietary X server ASTEC-X when the number of monitors is changed after the server has started. A workaround is to restart the X server after the monitor configuration has been changed. -*** Touchpad gestures don't work and emit warning messages. +*** Touchpad gestures don't work and/or emit warning messages. + +Support for touch gestures in Emacs requires version 21.1.0 or later +of the X.Org server, and it requires that Emacs be built with the +xf86-input-libinput library that is new enough + +Type 'M-: (x-server-input-extension-version) RET'; if that doesn't +return '(2 4)' (version 2.4) or later, your version of the X server +and libraries are too old and need to be upgraded. When pinching or swiping on your touchpad, you might see a warning message that looks like: commit bf5c75465f37ad45934f58287660f18ec0bcf7bf Author: Po Lu Date: Fri Jun 24 10:57:35 2022 +0800 Improve grabbing detection with multiple master devices (MPX) * src/frame.c (gui_mouse_grabbed): Respect any_grab_hook. * src/termhooks.h (GCALIGNED_STRUCT): New hook `any_grab_hook'. * src/xterm.c (x_have_any_grab): New function. (x_create_terminal): Define hook on XI2 builds. diff --git a/src/frame.c b/src/frame.c index c2f2f8e464..02c90ea651 100644 --- a/src/frame.c +++ b/src/frame.c @@ -5130,7 +5130,9 @@ gui_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object o bool gui_mouse_grabbed (Display_Info *dpyinfo) { - return (dpyinfo->grabbed + return ((dpyinfo->grabbed + || (dpyinfo->terminal->any_grab_hook + && dpyinfo->terminal->any_grab_hook (dpyinfo))) && dpyinfo->last_mouse_frame && FRAME_LIVE_P (dpyinfo->last_mouse_frame)); } diff --git a/src/termhooks.h b/src/termhooks.h index d7190e7736..a1e3e2cde9 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -877,6 +877,13 @@ struct terminal MENU_BAR_P if X and Y are in FRAME's toolkit menu bar, and true into TOOL_BAR_P if X and Y are in FRAME's toolkit tool bar. */ void (*toolkit_position_hook) (struct frame *, int, int, bool *, bool *); + +#ifdef HAVE_WINDOW_SYSTEM + /* Called to determine if the mouse is grabbed on the given display. + If either dpyinfo->grabbed or this returns true, then the display + will be considered as grabbed. */ + bool (*any_grab_hook) (Display_Info *); +#endif } GCALIGNED_STRUCT; INLINE bool diff --git a/src/xterm.c b/src/xterm.c index 6375b71666..414a9c0ebe 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -27320,6 +27320,25 @@ x_delete_terminal (struct terminal *terminal) unblock_input (); } +#ifdef HAVE_XINPUT2 +static bool +x_have_any_grab (struct x_display_info *dpyinfo) +{ + int i; + + if (!dpyinfo->supports_xi2) + return false; + + for (i = 0; i < dpyinfo->num_devices; ++i) + { + if (dpyinfo->devices[i].grab) + return true; + } + + return false; +} +#endif + /* Create a struct terminal, initialize it with the X11 specific functions and make DISPLAY->TERMINAL point to it. */ @@ -27387,6 +27406,9 @@ x_create_terminal (struct x_display_info *dpyinfo) terminal->delete_frame_hook = x_destroy_window; terminal->delete_terminal_hook = x_delete_terminal; terminal->toolkit_position_hook = x_toolkit_position; +#ifdef HAVE_XINPUT2 + terminal->any_grab_hook = x_have_any_grab; +#endif /* Other hooks are NULL by default. */ return terminal; commit ab203b0ce26f4989c7fc80185207c6c40bbfa5fe Author: Po Lu Date: Fri Jun 24 09:49:14 2022 +0800 Simplify XI event state conversion * src/xterm.c (xi_convert_button_state, xi_convert_event_state): New functions. (handle_one_xevent): Reduce duplicate code for converting XI state and button state into X state. diff --git a/src/xterm.c b/src/xterm.c index 23cee3c547..6375b71666 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4960,7 +4960,38 @@ x_extension_initialize (struct x_display_info *dpyinfo) #ifdef HAVE_XINPUT2 -/* Free all XI2 devices on dpyinfo. */ +/* Convert XI2 button state IN to a standard X button modifier + mask, and place it in OUT. */ +static void +xi_convert_button_state (XIButtonState *in, unsigned int *out) +{ + int i; + + if (in->mask_len) + { + for (i = 1; i <= 8; ++i) + { + if (XIMaskIsSet (in->mask, i)) + *out |= (Button1Mask << (i - 1)); + } + } +} + +/* Return the modifier state in XEV as a standard X modifier mask. */ +static unsigned int +xi_convert_event_state (XIDeviceEvent *xev) +{ + unsigned int mods, buttons; + + mods = xev->mods.effective; + buttons = 0; + + xi_convert_button_state (&xev->buttons, &buttons); + + return mods | buttons; +} + +/* Free all XI2 devices on DPYINFO. */ static void x_free_xi_devices (struct x_display_info *dpyinfo) { @@ -19462,7 +19493,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xm_top_level_leave_message lmsg; xm_top_level_enter_message emsg; xm_drag_motion_message dmsg; - int dnd_state; + unsigned int dnd_state; source = xi_device_from_id (dpyinfo, xev->sourceid); @@ -19628,20 +19659,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, #ifdef HAVE_XWIDGETS if (xv) { - uint state = xev->mods.effective; + unsigned int state; + + state = xi_convert_event_state (xev); x_display_set_last_user_time (dpyinfo, xev->time, xev->send_event); - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - state |= Button3Mask; - } - if (found_valuator) xwidget_scroll (xv, xev->event_x, xev->event_y, -xv_total_x, -xv_total_y, state, @@ -19748,17 +19771,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, copy.xmotion.y = lrint (xev->event_y); copy.xmotion.x_root = lrint (xev->root_x); copy.xmotion.y_root = lrint (xev->root_y); - copy.xmotion.state = 0; - - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - copy.xmotion.state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - copy.xmotion.state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - copy.xmotion.state |= Button3Mask; - } + copy.xmotion.state = xi_convert_event_state (xev); copy.xmotion.is_hint = False; copy.xmotion.same_screen = True; @@ -19962,17 +19975,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xev->root_x, xev->root_y); else if (x_dnd_last_protocol_version != -1 && target != None) { - dnd_state = xev->mods.effective; - - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - dnd_state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - dnd_state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - dnd_state |= Button3Mask; - } + dnd_state = xi_convert_event_state (xev); x_dnd_send_position (x_dnd_frame, target, x_dnd_last_protocol_version, @@ -20156,17 +20159,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, && x_dnd_last_seen_window != None && x_dnd_last_protocol_version != -1) { - dnd_state = xev->mods.effective; - - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - dnd_state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - dnd_state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - dnd_state |= Button3Mask; - } + dnd_state = xi_convert_event_state (xev); x_dnd_send_position (x_dnd_frame, x_dnd_last_seen_window, x_dnd_last_protocol_version, xev->root_x, @@ -20339,19 +20332,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, copy.xbutton.y = lrint (xev->event_y); copy.xbutton.x_root = lrint (xev->root_x); copy.xbutton.y_root = lrint (xev->root_y); - copy.xbutton.state = xev->mods.effective; + copy.xbutton.state = xi_convert_event_state (xev); copy.xbutton.button = xev->detail; copy.xbutton.same_screen = True; - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - copy.xbutton.state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - copy.xbutton.state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - copy.xbutton.state |= Button3Mask; - } #elif defined USE_GTK && !defined HAVE_GTK3 copy = gdk_event_new (xev->evtype == XI_ButtonPress ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE); @@ -20363,19 +20347,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, copy->button.y = xev->event_y; copy->button.x_root = xev->root_x; copy->button.y_root = xev->root_y; - copy->button.state = xev->mods.effective; + copy->button.state = xi_convert_event_state (xev); copy->button.button = xev->detail; - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - copy->button.state |= GDK_BUTTON1_MASK; - if (XIMaskIsSet (xev->buttons.mask, 2)) - copy->button.state |= GDK_BUTTON2_MASK; - if (XIMaskIsSet (xev->buttons.mask, 3)) - copy->button.state |= GDK_BUTTON3_MASK; - } - if (!copy->button.window) emacs_abort (); @@ -20738,22 +20712,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, copy.xkey.time = xev->time; copy.xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 << 14)) | (xev->group.effective << 13)); + xi_convert_button_state (&xev->buttons, ©.xkey.state); copy.xkey.x = lrint (xev->event_x); copy.xkey.y = lrint (xev->event_y); copy.xkey.x_root = lrint (xev->root_x); copy.xkey.y_root = lrint (xev->root_y); - - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - copy.xkey.state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - copy.xkey.state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - copy.xkey.state |= Button3Mask; - } - copy.xkey.keycode = xev->detail; copy.xkey.same_screen = True; #endif @@ -20789,15 +20753,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, /* Some input methods react differently depending on the buttons that are pressed. */ - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - xkey.state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - xkey.state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - xkey.state |= Button3Mask; - } + xi_convert_button_state (&xev->buttons, &xkey.state); xkey.keycode = xev->detail; xkey.same_screen = True; @@ -21228,15 +21184,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, /* Some input methods react differently depending on the buttons that are pressed. */ - if (xev->buttons.mask_len) - { - if (XIMaskIsSet (xev->buttons.mask, 1)) - xkey.state |= Button1Mask; - if (XIMaskIsSet (xev->buttons.mask, 2)) - xkey.state |= Button2Mask; - if (XIMaskIsSet (xev->buttons.mask, 3)) - xkey.state |= Button3Mask; - } + xi_convert_button_state (&xev->buttons, &xkey.state); xkey.keycode = xev->detail; xkey.same_screen = True; commit a772c0b85272bc20858a35af5f619983cfcb0084 Author: Stefan Kangas Date: Thu Jun 23 22:03:50 2022 +0200 ; Fix typos: prefer US spelling. diff --git a/doc/misc/modus-themes.org b/doc/misc/modus-themes.org index 2c49cbdd72..6b1d91c396 100644 --- a/doc/misc/modus-themes.org +++ b/doc/misc/modus-themes.org @@ -481,7 +481,7 @@ By default, customizing a theme-related user option through the Custom interfaces or with {{{kbd(M-x customize-set-variable)}}} will not reload the currently active Modus theme. -Enable this behaviour by setting this variable to ~nil~. +Enable this behavior by setting this variable to ~nil~. ** Option for color-coding success state :properties: @@ -649,7 +649,7 @@ tables and code blocks to always inherit from the ~fixed-pitch~ face. This is to ensure that those constructs remain monospaced even when users opt for a mode that remaps typeface families, such as the built-in {{{kbd(M-x variable-pitch-mode)}}}. Otherwise the layout would appear -broken, due to how spacing is done. To disable this behaviour, set the +broken, due to how spacing is done. To disable this behavior, set the option to ~t~. Users may prefer to use another package for handling mixed typeface @@ -2069,7 +2069,7 @@ contrast on an on-demand basis. One way to achieve this is to design a command that cycles through three distinct levels of intensity, though the following can be adapted to any -kind of cyclic behaviour, such as to switch between red, green, and +kind of cyclic behavior, such as to switch between red, green, and blue. In the following example, we employ the ~modus-themes-color~ function diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex index 0d86b25dc4..e798ae1c2c 100644 --- a/doc/misc/texinfo.tex +++ b/doc/misc/texinfo.tex @@ -7660,7 +7660,7 @@ % If SUBTOPIC is present, precede it with a space, and call \doind. % (At some time during the 20th century, this made a two-level entry in an % index such as the operation index. Nobody seemed to notice the change in -% behaviour though.) +% behavior though.) \def\dosubind#1#2#3{% \def\thirdarg{#3}% \ifx\thirdarg\empty diff --git a/etc/themes/modus-themes.el b/etc/themes/modus-themes.el index 6068bf47ce..f49a809e49 100644 --- a/etc/themes/modus-themes.el +++ b/etc/themes/modus-themes.el @@ -1679,7 +1679,7 @@ By default, customizing a theme-related user option through the Custom interfaces or with `customize-set-variable' will not reload the currently active Modus theme. -Enable this behaviour by setting this variable to nil." +Enable this behavior by setting this variable to nil." :group 'modus-themes :package-version '(modus-themes . "1.5.0") :version "28.1" diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 7b7cc5b8bd..9617257470 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -587,7 +587,7 @@ Usually run by inclusion in `minibuffer-setup-hook'." ;; select it -- again, as desired. ;; ;; FIXME: it's arguable that this second - ;; behaviour should be a property of the + ;; behavior should be a property of the ;; completion table and not the completion ;; frontend such as we have done ;; here. However, it seems generically diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index 8feef6beeb..b23b0d64ae 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -3437,7 +3437,7 @@ form \"PARAMETER\" to enable a feature, \"PARAMETER=VALUE\" to configure a specific option or \"-PARAMETER\" to disable a previously specified feature. SENDER is passed on to `rcirc-handler-generic'. PROCESS is the process object for the -current connection. Note that this is not the behaviour as +current connection. Note that this is not the behavior as specified in RFC2812, where 005 stood for RPL_BOUNCE." (rcirc-handler-generic process "005" sender args text) (with-rcirc-process-buffer process diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 101c323b13..bdd7751fc0 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1710,7 +1710,7 @@ which see." (defalias 'elisp-eldoc-documentation-function 'elisp--documentation-one-liner "Return Elisp documentation for the thing at point as one-line string. This is meant as a backward compatibility aide to the \"old\" -Elisp eldoc behaviour. Consider variable docstrings and function +Elisp eldoc behavior. Consider variable docstrings and function signatures only, in this order. If none applies, returns nil. Changes to `eldoc-documentation-functions' and `eldoc-documentation-strategy' are _not_ reflected here. As such diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el index 68b085d42f..f6a4711e24 100644 --- a/lisp/progmodes/hideif.el +++ b/lisp/progmodes/hideif.el @@ -109,7 +109,7 @@ ;; ;; Extensively modified by Luke Lee in 2013 to support complete C expression ;; evaluation and argumented macro expansion; C++11, C++14, C++17, GCC -;; extension literals and gcc/clang matching behaviours are supported in 2021. +;; extension literals and gcc/clang matching behaviors are supported in 2021. ;; Various floating point types and operations are also supported but the ;; actual precision is limited by the Emacs internal floating representation, ;; which is the C data type "double" or IEEE binary64 format. diff --git a/lisp/so-long.el b/lisp/so-long.el index f4ae71d905..17af532249 100644 --- a/lisp/so-long.el +++ b/lisp/so-long.el @@ -90,7 +90,7 @@ ;; * Overview of modes and commands ;; -------------------------------- ;; - `global-so-long-mode' - A global minor mode which enables the automated -;; behaviour, causing the user's preferred action to be invoked whenever a +;; behavior, causing the user's preferred action to be invoked whenever a ;; newly-visited file contains excessively long lines. ;; - `so-long-mode' - A major mode, and the default action. ;; - `so-long-minor-mode' - A minor mode version of the major mode, and an @@ -111,7 +111,7 @@ ;; ;; On rare occasions you may choose to manually invoke the `so-long' command, ;; which invokes your preferred `so-long-action' (exactly as the automatic -;; behaviour would do if it had detected long lines). You might use this if a +;; behavior would do if it had detected long lines). You might use this if a ;; problematic file did not meet your configured criteria, and you wished to ;; trigger the performance improvements manually. ;; @@ -120,7 +120,7 @@ ;; available to `so-long' but, like any other mode, they can be invoked directly ;; if you have a need to do that (see also "Other ways of using so-long" below). ;; -;; If the behaviour ever triggers when you did not want it to, you can use the +;; If the behavior ever triggers when you did not want it to, you can use the ;; `so-long-revert' command to restore the buffer to its original state. ;; * Basic configuration @@ -199,7 +199,7 @@ ;; ;; Note that `so-long-minor-modes' is not useful for other global minor modes ;; (as distinguished from globalized minor modes), but in some cases it will be -;; possible to inhibit or otherwise counter-act the behaviour of a global mode +;; possible to inhibit or otherwise counter-act the behavior of a global mode ;; by overriding variables, or by employing hooks (see below). You would need ;; to inspect the code for a given global mode (on a case by case basis) to ;; determine whether it's possible to inhibit it for a single buffer -- and if @@ -211,7 +211,7 @@ ;; If `so-long-action' is set to either `so-long-mode' or `so-long-minor-mode', ;; the buffer-local value for each variable in the list is set to the associated ;; value in the alist. Use this to enforce values which will improve -;; performance or otherwise avoid undesirable behaviours. If `so-long-revert' +;; performance or otherwise avoid undesirable behaviors. If `so-long-revert' ;; is called, then the original values are restored. ;; * Retaining minor modes and settings when switching to `so-long-mode' @@ -273,7 +273,7 @@ ;; `so-long-mode', completely bypassing the automated decision process. ;; Refer to M-: (info "(emacs) Specifying File Variables") RET ;; -;; If so-long itself causes problems, disable the automated behaviour with +;; If so-long itself causes problems, disable the automated behavior with ;; M-- M-x global-so-long-mode, or M-: (global-so-long-mode 0) ;; * Example configuration @@ -313,7 +313,7 @@ ;; (add-hook 'js-mode-hook 'my-js-mode-hook) ;; ;; (defun my-js-mode-hook () -;; "Custom `js-mode' behaviours." +;; "Custom `js-mode' behaviors." ;; (setq-local so-long-max-lines 100) ;; (setq-local so-long-threshold 1000)) ;; @@ -327,7 +327,7 @@ ;; (add-hook 'nxml-mode-hook 'my-nxml-mode-hook) ;; ;; (defun my-nxml-mode-hook () -;; "Custom `nxml-mode' behaviours." +;; "Custom `nxml-mode' behaviors." ;; (require 'so-long) ;; (setq-local so-long-variable-overrides ;; (remove '(bidi-inhibit-bpa . t) so-long-variable-overrides))) @@ -380,7 +380,7 @@ ;; meaning you would need to add to `safe-local-variable-values' in order to ;; avoid being queried about them. ;; -;; Finally, the `so-long-predicate' user option enables the automated behaviour +;; Finally, the `so-long-predicate' user option enables the automated behavior ;; to be determined by a custom function, if greater control is needed. ;; * Implementation notes @@ -397,7 +397,7 @@ ;; * Caveats ;; --------- -;; The variables affecting the automated behaviour of this library (such as +;; The variables affecting the automated behavior of this library (such as ;; `so-long-action') can be used as file- or dir-local values in Emacs 26+, but ;; not in previous versions of Emacs. This is on account of improvements made ;; to `normal-mode' in 26.1, which altered the execution order with respect to @@ -462,7 +462,7 @@ ;; 0.6 - Added `so-long-minor-modes' and `so-long-hook'. ;; 0.5 - Renamed library to "so-long.el". ;; - Added explicit `so-long-enable' command to activate our advice. -;; 0.4 - Amended/documented behaviour with file-local 'mode' variables. +;; 0.4 - Amended/documented behavior with file-local 'mode' variables. ;; 0.3 - Defer to a file-local 'mode' variable. ;; 0.2 - Initial release to EmacsWiki. ;; 0.1 - Experimental. @@ -490,7 +490,7 @@ ;; automatically."; however `so-long--ensure-enabled' may forcibly re-enable ;; it contrary to the user's expectations, so for the present this should be ;; considered internal-use only (with `global-so-long-mode' the interface - ;; for enabling or disabling the automated behaviour). FIXME: Establish a + ;; for enabling or disabling the automated behavior). FIXME: Establish a ;; way to support the original use-case, or rename to `so-long--enabled'. "Internal use. Non-nil when any `so-long' functionality has been used.") @@ -586,7 +586,7 @@ files would prevent Emacs from handling them correctly." (defcustom so-long-invisible-buffer-function #'so-long-deferred "Function called in place of `so-long' when the buffer is not displayed. -This affects the behaviour of `global-so-long-mode'. +This affects the behavior of `global-so-long-mode'. We treat invisible buffers differently from displayed buffers because, in cases where a library is using a buffer for behind-the-scenes processing, @@ -618,7 +618,7 @@ the mentioned options might interfere with some intended processing." 'so-long-detected-long-line-p) "Function called after `set-auto-mode' to decide whether action is needed. -This affects the behaviour of `global-so-long-mode'. +This affects the behavior of `global-so-long-mode'. Only called if the major mode is a member of `so-long-target-modes'. @@ -703,7 +703,7 @@ will be automatically processed; but custom actions can also do these things. The value `longlines-mode' causes that minor mode to be enabled. See longlines.el for more details. -Each action likewise determines the behaviour of `so-long-revert'. +Each action likewise determines the behavior of `so-long-revert'. If the value is nil, or not defined in `so-long-action-alist', then no action will be taken." @@ -753,7 +753,7 @@ If ACTION-ARG is provided, it is used in place of `so-long-action'." (defcustom so-long-file-local-mode-function 'so-long-mode-downgrade "Function to call during `set-auto-mode' when a file-local mode is set. -This affects the behaviour of `global-so-long-mode'. +This affects the behavior of `global-so-long-mode'. The specified function will be called with a single argument, being the file-local mode which was established. @@ -855,7 +855,7 @@ By default this happens if `so-long-action' is set to either `so-long-mode' or `so-long-minor-mode'. If `so-long-revert' is subsequently invoked, then the disabled modes are re-enabled by calling them with the numeric argument 1. -`so-long-hook' can be used where more custom behaviour is desired. +`so-long-hook' can be used where more custom behavior is desired. Please submit bug reports to recommend additional modes for this list, whether they are in Emacs core, GNU ELPA, or elsewhere." @@ -1312,7 +1312,7 @@ This minor mode is a standard `so-long-action' option." (if so-long-minor-mode ;; We are enabling the mode. (progn ;; Housekeeping. `so-long-minor-mode' might be invoked directly rather - ;; than via `so-long', so replicate the necessary behaviours. The minor + ;; than via `so-long', so replicate the necessary behaviors. The minor ;; mode also cares about whether `so-long' was already active, as we do ;; not want to remember values which were (potentially) overridden ;; already. @@ -1387,9 +1387,9 @@ values), despite potential performance issues, type \\[so-long-revert]. Use \\[so-long-commentary] for more information. Use \\[so-long-customize] to open the customization group `so-long' to -configure the behaviour." +configure the behavior." ;; Housekeeping. `so-long-mode' might be invoked directly rather than via - ;; `so-long', so replicate the necessary behaviours. We could use this same + ;; `so-long', so replicate the necessary behaviors. We could use this same ;; test in `so-long-after-change-major-mode' to run `so-long-hook', but that's ;; not so obviously the right thing to do, so I've omitted it for now. (unless so-long--calling @@ -1435,7 +1435,7 @@ configure the behaviour." This advice acts before `so-long-mode', with the previous mode still active." (unless (derived-mode-p 'so-long-mode) ;; Housekeeping. `so-long-mode' might be invoked directly rather than - ;; via `so-long', so replicate the necessary behaviours. + ;; via `so-long', so replicate the necessary behaviors. (unless so-long--calling (so-long-remember-all :reset)) ;; Remember the original major mode, regardless. @@ -1549,7 +1549,7 @@ This is the `so-long-revert-function' for `so-long-mode'." ;; Emacs 26+ has already called `hack-local-variables' (during ;; `run-mode-hooks'; provided there was a `buffer-file-name'), but for older ;; versions we need to call it here. In Emacs 26+ the revised 'HANDLE-MODE' - ;; argument is set to `no-mode' (being the non-nil-and-non-t behaviour), + ;; argument is set to `no-mode' (being the non-nil-and-non-t behavior), ;; which we mimic here by binding `so-long--hack-local-variables-no-mode', ;; in order to prevent a local 'mode' variable from clobbering the major ;; mode we have just called. @@ -1590,7 +1590,7 @@ because we do not want to downgrade the major mode in that scenario." ;; Act only if `so-long-mode' would be enabled by the current action. (when (and (symbolp (so-long-function)) (provided-mode-derived-p (so-long-function) 'so-long-mode)) - ;; Downgrade from `so-long-mode' to the `so-long-minor-mode' behaviour. + ;; Downgrade from `so-long-mode' to the `so-long-minor-mode' behavior. (setq so-long-function 'turn-on-so-long-minor-mode so-long-revert-function 'turn-off-so-long-minor-mode)))) @@ -1610,7 +1610,7 @@ and cannot be conveniently intercepted, so we are forced to replicate it here. This special-case code will ultimately be removed from Emacs, as it exists to deal with a deprecated feature; but until then we need to replicate it in order -to inhibit our own behaviour in the presence of a header comment `mode' +to inhibit our own behavior in the presence of a header comment `mode' declaration. If a file-local mode is detected in the header comment, then we call the @@ -1747,7 +1747,7 @@ by testing the value against `major-mode'; but as we may have changed the major mode to `so-long-mode' by this point, that protection is insufficient and so we need to perform our own test. -We likewise need to support an equivalent of the `no-mode' behaviour in 26.1+ +We likewise need to support an equivalent of the `no-mode' behavior in 26.1+ to ensure that `so-long-mode-revert' will not restore a file-local mode again after it has already reverted to the original mode. @@ -1895,7 +1895,7 @@ When such files are detected by `so-long-predicate', we invoke the selected Use \\[so-long-commentary] for more information. Use \\[so-long-customize] to open the customization group `so-long' to -configure the behaviour." +configure the behavior." :global t :group 'so-long (if global-so-long-mode diff --git a/test/lisp/so-long-tests/so-long-tests.el b/test/lisp/so-long-tests/so-long-tests.el index 23a5660df5..670ab52cef 100644 --- a/test/lisp/so-long-tests/so-long-tests.el +++ b/test/lisp/so-long-tests/so-long-tests.el @@ -59,7 +59,7 @@ (declare-function so-long-tests-assert-and-revert "so-long-tests-helpers") (declare-function so-long-tests-predicates "so-long-tests-helpers") -;; Enable the automated behaviour for all tests. +;; Enable the automated behavior for all tests. (global-so-long-mode 1) (ert-deftest so-long-tests-threshold-under () @@ -210,7 +210,7 @@ ;; From Emacs 27 the `display-buffer' call is insufficient. ;; The various 'window change functions' are now invoked by the ;; redisplay, and redisplay does nothing at all in batch mode, - ;; so we cannot test under this revised behaviour. Refer to: + ;; so we cannot test under this revised behavior. Refer to: ;; https://lists.gnu.org/r/emacs-devel/2019-10/msg00971.html ;; For interactive (non-batch) test runs, calling `redisplay' ;; does do the trick; so do that first. diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 4d59f349ba..e27a40f644 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -788,7 +788,7 @@ (should (equal 1 (string-distance "ab" "a我b"))) (should (equal 1 (string-distance "我" "她"))) - ;; correct behaviour with empty strings + ;; correct behavior with empty strings (should (equal 0 (string-distance "" ""))) (should (equal 0 (string-distance "" "" t))) (should (equal 1 (string-distance "x" ""))) diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el index 1dbaf7ef2e..d7b9e8440e 100644 --- a/test/src/keymap-tests.el +++ b/test/src/keymap-tests.el @@ -125,7 +125,7 @@ ;; ...) (ert-deftest keymap-lookup-key/mixed-case () - "Backwards compatibility behaviour (Bug#50752)." + "Backwards compatibility behavior (Bug#50752)." (let ((map (make-keymap))) (define-key map [menu-bar foo bar] 'foo) (should (eq (lookup-key map [menu-bar foo bar]) 'foo)) commit f7e73716316d0256ac1584348009a79c81d11e56 Author: Stefan Kangas Date: Thu Jun 23 21:51:19 2022 +0200 * lisp/net/browse-url.el: Doc fix; recommend keymap-* functions. diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 5b58c8ed86..1cfe90895f 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -91,18 +91,18 @@ ;; Bind the browse-url commands to keys with the `C-c C-z' prefix ;; (as used by html-helper-mode): -;; (global-set-key "\C-c\C-z." 'browse-url-at-point) -;; (global-set-key "\C-c\C-zb" 'browse-url-of-buffer) -;; (global-set-key "\C-c\C-zr" 'browse-url-of-region) -;; (global-set-key "\C-c\C-zu" 'browse-url) -;; (global-set-key "\C-c\C-zv" 'browse-url-of-file) +;; (keymap-global-set "C-c C-z ." 'browse-url-at-point) +;; (keymap-global-set "C-c C-z b" 'browse-url-of-buffer) +;; (keymap-global-set "C-c C-z r" 'browse-url-of-region) +;; (keymap-global-set "C-c C-z u" 'browse-url) +;; (keymap-global-set "C-c C-z v" 'browse-url-of-file) ;; (add-hook 'dired-mode-hook ;; (lambda () -;; (local-set-key "\C-c\C-zf" 'browse-url-of-dired-file))) +;; (keymap-local-set "C-c C-z f" 'browse-url-of-dired-file))) ;; Browse URLs in mail messages under RMAIL by clicking mouse-2: ;; (add-hook 'rmail-mode-hook (lambda () ; rmail-mode startup -;; (define-key rmail-mode-map [mouse-2] 'browse-url-at-mouse))) +;; (keymap-set rmail-mode-map [mouse-2] 'browse-url-at-mouse))) ;; Alternatively, add `goto-address' to `rmail-show-message-hook'. ;; Gnus provides a standard feature to activate URLs in article commit 61c8a078cff572a29cb61b0c1c0554d5f09a1e83 Author: Stefan Kangas Date: Thu Jun 23 21:04:59 2022 +0200 * lisp/recentf.el (recentf-auto-cleanup): Clarify docstring. diff --git a/lisp/recentf.el b/lisp/recentf.el index 7ddf1efb9f..d8016077eb 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -238,6 +238,8 @@ This item will replace the \"More...\" item." (defcustom recentf-auto-cleanup 'mode "Define when to automatically cleanup the recent list. +That is, remove duplicates, non-kept, and excluded files. + The following values can be set: - `mode' commit 48248c901d0884c042345c3ae1ba8fdfeb195c74 Author: Mattias Engdegård Date: Thu Jun 23 14:33:46 2022 +0200 Remove unused function in bytecomp.el * lisp/emacs-lisp/bytecomp.el (byte-compile-delete-first): Remove. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 4fd65bb5d5..a8c68f8153 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1174,18 +1174,6 @@ message buffer `default-directory'." (t (insert (format "%s\n" string))))))) -;; copied from gnus-util.el -(defsubst byte-compile-delete-first (elt list) - (if (eq (car list) elt) - (cdr list) - (let ((total list)) - (while (and (cdr list) - (not (eq (cadr list) elt))) - (setq list (cdr list))) - (when (cdr list) - (setcdr list (cddr list))) - total))) - (defvar byte-compile-last-warned-form nil) (defvar byte-compile-last-logged-file nil) (defvar byte-compile-root-dir nil commit 89afd90bde9ff689ff62c6a5c170edf661b2fb8c Author: Stefan Kangas Date: Thu Jun 23 15:12:47 2022 +0200 ; * lisp/uniquify.el: Remove incorrect comment. diff --git a/lisp/uniquify.el b/lisp/uniquify.el index 2ef1f04f70..0b7db9b54f 100644 --- a/lisp/uniquify.el +++ b/lisp/uniquify.el @@ -128,7 +128,6 @@ you can set, browse the `uniquify' custom group." "If non-nil, rerationalize buffer names after a buffer has been killed." :type 'boolean) -;; The default value matches certain Gnus buffers. (defcustom uniquify-ignore-buffers-re nil "Regular expression matching buffer names that should not be uniquified. For instance, set this to \"^draft-[0-9]+$\" to avoid having uniquify rename commit 630a33f0a9e976601e43152815aafe3f22350cfc Author: Gerd Moellmann Date: Thu Jun 23 14:38:13 2022 +0200 Save desktop-save-mode when changed from menu * lisp/menu-bar.el (menu-bar-options-save): Save desktop-save-mode (bug#56156). diff --git a/lisp/menu-bar.el b/lisp/menu-bar.el index 488bf05f3a..4a943d2528 100644 --- a/lisp/menu-bar.el +++ b/lisp/menu-bar.el @@ -792,6 +792,7 @@ The selected font will be the default on both the existing and future frames." (dolist (elt '(scroll-bar-mode debug-on-quit debug-on-error ;; Somehow this works, when tool-bar and menu-bar don't. + desktop-save-mode tooltip-mode window-divider-mode save-place-mode uniquify-buffer-name-style fringe-mode indicate-empty-lines indicate-buffer-boundaries commit 097b63f2ef1851dfa3540cc94d4f756182e0d687 Author: Stefan Kangas Date: Thu Jun 23 13:41:07 2022 +0200 Tag shortcut commands for recentf-dialog-mode * lisp/recentf.el (recentf--shortcuts-keymap): Add interactive mode tags for 'recentf-dialog-mode' specific commands. diff --git a/lisp/recentf.el b/lisp/recentf.el index b31aafc9dc..7ddf1efb9f 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -478,7 +478,7 @@ See also the command `recentf-open-most-recent-file'." ;; Define a shortcut command. (defalias cmd `(lambda () - (interactive) + (interactive nil recentf-dialog-mode) (recentf-open-most-recent-file ,k))) ;; Bind it to a digit key. (keymap-set km (format "%d" k) cmd))) commit 3832e5360bd71c90eb0f7ad88f0daf001de8b3d3 Author: Stefan Kangas Date: Thu Jun 23 12:20:38 2022 +0200 Prefer defvar-keymap and keymap-set in recentf.el * lisp/recentf.el (recentf-mode-map): Prefer defvar-keymap. (recentf--shortcuts-keymap): Prefer keymap-set. diff --git a/lisp/recentf.el b/lisp/recentf.el index 6729ede167..b31aafc9dc 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -160,7 +160,7 @@ If nil add it at end of menu (see also `easy-menu-add-item')." (const :tag "Last" nil)) :set 'recentf-menu-customization-changed) -(defcustom recentf-menu-action 'find-file +(defcustom recentf-menu-action #'find-file "Function to invoke with a filename item of the recentf menu. The default is to call `find-file' to edit the selected file." :group 'recentf @@ -481,7 +481,7 @@ See also the command `recentf-open-most-recent-file'." (interactive) (recentf-open-most-recent-file ,k))) ;; Bind it to a digit key. - (define-key km (vector (+ k ?0)) cmd))) + (keymap-set km (format "%d" k) cmd))) km) "Digit shortcuts keymap.") @@ -1337,8 +1337,8 @@ That is, remove duplicates, non-kept, and excluded files." ;;; The minor mode ;; -(defvar recentf-mode-map (make-sparse-keymap) - "Keymap to use in recentf mode.") +(defvar-keymap recentf-mode-map + :doc "Keymap to use in `recentf-mode'.") ;;;###autoload (define-minor-mode recentf-mode commit c753e4cb2a2a5998626d48d85071c047cbab6c54 Author: Stefan Kangas Date: Thu Jun 23 11:00:19 2022 +0200 Use shortened filenames in recentf-mode * lisp/recentf.el (recentf-filename-handlers): Set to 'abbreviate-file-name' to get shortened names by default. (Bug#56123) diff --git a/etc/NEWS b/etc/NEWS index f21f482c29..6c04ae164c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1855,6 +1855,12 @@ Enabling this minor mode turns on hiding header material, like If non-nil, files untracked by a VCS are considered to be part of the project by a VC project based on that VCS. +--- +*** 'recentf-mode' now uses shortened filenames by default. +This means that e.g. "/home/foo/bar" is now displayed as "~/bar". +Customize the user option 'recentf-filename-handlers' to nil to get +back the old behavior. + --- ** The autoarg.el library is now marked obsolete. This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor diff --git a/lisp/recentf.el b/lisp/recentf.el index 8b05f48283..6729ede167 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -285,7 +285,7 @@ If `file-name-history' is not empty, do nothing." (make-obsolete-variable 'recentf-load-hook "use `with-eval-after-load' instead." "28.1") -(defcustom recentf-filename-handlers nil +(defcustom recentf-filename-handlers '(abbreviate-file-name) "Functions to post process recent file names. They are successively passed a file name to transform it." :group 'recentf @@ -295,7 +295,8 @@ They are successively passed a file name to transform it." (choice (const file-truename) (const abbreviate-file-name) - (function :tag "Other function"))))) + (function :tag "Other function")))) + :version "29.1") (defcustom recentf-show-file-shortcuts-flag t "Non-nil means to show \"[N]\" for the Nth item up to 10. commit 5f904e50c32197e636e521120384d3658f53c794 Author: Stefan Kangas Date: Thu Jun 23 10:55:45 2022 +0200 Revert "Allow shortening filenames in recentf-mode menu" This reverts commit 32906819addde1aa952d4718699d332d3a58b004. diff --git a/etc/NEWS b/etc/NEWS index 88ba721384..f21f482c29 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1855,11 +1855,6 @@ Enabling this minor mode turns on hiding header material, like 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 'recentf-mode' menu can now use shortened filenames. -Set the user option 'recentf-menu-filter' to -'recentf-show-abbreviated' to enable it. - --- ** The autoarg.el library is now marked obsolete. This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor diff --git a/lisp/recentf.el b/lisp/recentf.el index 05127cbf49..8b05f48283 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -187,8 +187,6 @@ A nil value means no filter. The following functions are predefined: Sort menu items by directories in ascending order. - `recentf-sort-directories-descending' Sort menu items by directories in descending order. -- `recentf-show-abbreviated' - Show shortened filenames. - `recentf-show-basenames' Show filenames sans directory in menu items. - `recentf-show-basenames-ascending' @@ -217,7 +215,6 @@ elements (see `recentf-make-menu-element' for menu element form)." (function-item recentf-sort-basenames-descending) (function-item recentf-sort-directories-ascending) (function-item recentf-sort-directories-descending) - (function-item recentf-show-abbreviated) (function-item recentf-show-basenames) (function-item recentf-show-basenames-ascending) (function-item recentf-show-basenames-descending) @@ -724,11 +721,14 @@ Compares directories then filenames to order the list." (recentf-menu-element-value e2) (recentf-menu-element-value e1))))) -(defun recentf--filter-names (l no-dir fun) +(defun recentf-show-basenames (l &optional no-dir) + "Filter the list of menu elements L to show filenames sans directory. +When a filename is duplicated, it is appended a sequence number if +optional argument NO-DIR is non-nil, or its directory otherwise." (let (filtered-names filtered-list full name counters sufx) (dolist (elt l (nreverse filtered-list)) (setq full (recentf-menu-element-value elt) - name (funcall fun full)) + name (file-name-nondirectory full)) (if (not (member name filtered-names)) (push name filtered-names) (if no-dir @@ -740,18 +740,6 @@ Compares directories then filenames to order the list." (setq name (format "%s(%s)" name sufx))) (push (recentf-make-menu-element name full) filtered-list)))) -(defun recentf-show-abbreviated (l &optional no-dir) - "Filter the list of menu elements L to show shortened filenames. -When a filename is duplicated, it is appended a sequence number if -optional argument NO-DIR is non-nil, or its directory otherwise." - (recentf--filter-names l no-dir #'abbreviate-file-name)) - -(defun recentf-show-basenames (l &optional no-dir) - "Filter the list of menu elements L to show filenames sans directory. -When a filename is duplicated, it is appended a sequence number if -optional argument NO-DIR is non-nil, or its directory otherwise." - (recentf--filter-names l no-dir #'file-name-nondirectory)) - (defun recentf-show-basenames-ascending (l) "Filter the list of menu elements L to show filenames sans directory. Filenames are sorted in ascending order. commit 2bd49c8204cc643965e761c4fbcf489b21bbca5d Author: Stefan Kangas Date: Thu Jun 23 10:55:04 2022 +0200 Revert "Use short file names by default in recentf menu" This reverts commit ec9228eb81c0a89b18480dfff18cc9afdc3d0884. diff --git a/etc/NEWS b/etc/NEWS index 40658559d7..88ba721384 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1856,9 +1856,9 @@ 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 'recentf-mode' menu now uses shortened filenames by default. -They are shortened with 'abbreviate-file-name'. Customize the user -option 'recentf-menu-filter' to nil to get unabbreviated file names. +*** The 'recentf-mode' menu can now use shortened filenames. +Set the user option 'recentf-menu-filter' to +'recentf-show-abbreviated' to enable it. --- ** The autoarg.el library is now marked obsolete. diff --git a/lisp/recentf.el b/lisp/recentf.el index b10f4d0ed0..05127cbf49 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -171,7 +171,7 @@ The default is to call `find-file' to edit the selected file." :group 'recentf :type 'integer) -(defcustom recentf-menu-filter #'recentf-show-abbreviated +(defcustom recentf-menu-filter nil "Function used to filter files displayed in the recentf menu. A nil value means no filter. The following functions are predefined: @@ -226,8 +226,7 @@ elements (see `recentf-make-menu-element' for menu element form)." (function-item recentf-arrange-by-mode) (function-item recentf-arrange-by-dir) (function-item recentf-filter-changer) - function) - :version "29.1") + function)) (defcustom recentf-menu-open-all-flag nil "Non-nil means to show an \"All...\" item in the menu. commit ea640581bad1c596f657ca405f6c97e1b4fc4b11 Author: Lars Ingebrigtsen Date: Thu Jun 23 11:22:29 2022 +0200 Ensure that nnimap doesn't send too long lines to the server * lisp/gnus/nnimap.el (nnimap-retrieve-headers): Don't send too-long lines to the server (bug#56138). diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index afd5418912..c158367b73 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -239,12 +239,21 @@ during splitting, which may be slow." (when (nnimap-change-group group server) (with-current-buffer (nnimap-buffer) (erase-buffer) - (nnimap-wait-for-response - (nnimap-send-command - "UID FETCH %s %s" - (nnimap-article-ranges (gnus-compress-sequence articles)) - (nnimap-header-parameters)) - t) + (let ((ranges (gnus-compress-sequence articles)) + sequence) + ;; If we have a lot of ranges, split them up to avoid + ;; generating too-long lines. (The limit is 8192 octects, + ;; and this should guarantee that it's (much) shorter than + ;; that.) + (while ranges + (setq sequence + (nnimap-send-command + "UID FETCH %s %s" + (nnimap-article-ranges (seq-take ranges 200)) + (nnimap-header-parameters))) + (setq ranges (nthcdr 200 ranges))) + ;; Wait for the final one. + (nnimap-wait-for-response sequence t)) (unless (process-live-p (get-buffer-process (current-buffer))) (error "IMAP server %S closed connection" nnimap-address)) (nnimap-transform-headers) commit 716a0f4025658490262d9a5f6d501775f1d59fb7 Author: Po Lu Date: Thu Jun 23 15:35:37 2022 +0800 ; * src/xterm.c (x_dnd_send_leave): Remove debugging code. diff --git a/src/xterm.c b/src/xterm.c index d3e6c5323b..23cee3c547 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4416,7 +4416,6 @@ x_dnd_send_leave (struct frame *f, Window target) msg.xclient.data.l[3] = 0; msg.xclient.data.l[4] = 0; - puts ("RESET PENDING"); x_dnd_waiting_for_status_window = None; x_catch_errors (dpyinfo->display); commit 1003f36febe91afe7381aac713d56335e555b22d Author: Po Lu Date: Thu Jun 23 13:58:16 2022 +0800 Minor fixes to last change * src/pgtkselect.c (pgtk_get_window_property): Add 1 to xdata when it is GdkAtom. * src/pgtkterm.c (drag_leave): Initialize inev.ie. diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 2a4f6adba4..fff163c92a 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -1108,7 +1108,7 @@ pgtk_get_window_property (GdkWindow *window, unsigned char **data_ret, eassert (actual_format == 32); length = length / sizeof (GdkAtom); - xdata = xmalloc (sizeof (GdkAtom) * length); + xdata = xmalloc (sizeof (GdkAtom) * length + 1); memcpy (xdata, data, 1 + length * sizeof (GdkAtom)); g_free (data); diff --git a/src/pgtkterm.c b/src/pgtkterm.c index a123311366..1eb4d378ad 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -6259,6 +6259,8 @@ drag_leave (GtkWidget *widget, GdkDragContext *context, g_object_unref); } + EVENT_INIT (inev.ie); + inev.ie.kind = DRAG_N_DROP_EVENT; inev.ie.modifiers = 0; inev.ie.arg = Qnil; commit 5cbe50a4fb9e13624ccd7082d20ab069558dca21 Author: Po Lu Date: Thu Jun 23 13:57:23 2022 +0800 Make DND from other GTK programs work on Wayland * lisp/pgtk-dnd.el (pgtk-dnd-handle-gdk): Try to keep the selection contents in extra-data during a motion event. diff --git a/lisp/pgtk-dnd.el b/lisp/pgtk-dnd.el index 2aaf4c4e97..df267549d7 100644 --- a/lisp/pgtk-dnd.el +++ b/lisp/pgtk-dnd.el @@ -373,15 +373,27 @@ message." (time (nth 2 client-message)) (action-type (pgtk-dnd-maybe-call-test-function window action))) + ;; Get the selection contents now. GdkWaylandSelection + ;; becomes unavailable immediately after `drag-drop' is sent. + (let* ((current-type (pgtk-dnd-current-type window)) + (current-action-type (car-safe (aref state 6)))) + (when (and current-type + (not (equal current-action-type action-type))) + (aset state 6 (cons action-type + (pgtk-get-selection-internal + (nth 1 client-message) + (intern current-type)))))) (pgtk-update-drop-status (car action-type) time) (dnd-handle-movement (event-start event))))) ((eq (car client-message) 'quote) ; drag-drop - (let* ((timestamp (nth 2 client-message)) + (let* ((state (pgtk-dnd-get-state-for-frame frame)) + (timestamp (nth 2 client-message)) (value (and (pgtk-dnd-current-type window) - (pgtk-get-selection-internal - (nth 1 client-message) - (intern (pgtk-dnd-current-type window)) - timestamp))) + (or (cdr-safe (aref state 6)) + (pgtk-get-selection-internal + (nth 1 client-message) + (intern (pgtk-dnd-current-type window)) + timestamp)))) action) (unwind-protect (setq action (when value commit 0b4db66a9deae682dc7d444f4ab8d0e49f15c3b9 Author: Po Lu Date: Thu Jun 23 13:38:30 2022 +0800 Allow dropping more data types on PGTK * lisp/loadup.el (featurep): Load `pgtk-dnd'. * lisp/pgtk-dnd.el: New file. (pgtk-dnd-test-function, pgtk-dnd-types-alist) (pgtk-dnd-known-types, pgtk-dnd-use-offix-drop) (pgtk-dnd-current-state, pgtk-get-selection-internal) (pgtk-register-dnd-targets, pgtk-dnd-empty-state) (pgtk-dnd-init-frame, pgtk-dnd-get-state-cons-for-frame) (pgtk-dnd-get-state-for-frame, pgtk-dnd-default-test-function) (pgtk-dnd-current-type, pgtk-dnd-forget-drop) (pgtk-dnd-maybe-call-test-function, pgtk-dnd-save-state) (pgtk-dnd-handle-moz-url, pgtk-dnd-insert-utf8-text) (pgtk-dnd-insert-utf16-text, pgtk-dnd-insert-ctext) (pgtk-dnd-handle-uri-list, pgtk-dnd-handle-file-name) (pgtk-dnd-choose-type, pgtk-dnd-drop-data) (pgtk-dnd-handle-drag-n-drop-event, pgtk-update-drop-status) (pgtk-drop-finish, pgtk-dnd-handle-gdk, pgtk-dnd): New variables and functions and library. * lisp/term/pgtk-win.el (special-event-map): Load `drag-n-drop-event'. (after-make-frame-functions): Register DND after make frame functions. * src/emacs.c (main): Stop calling empty init_pgtkterm function. * src/pgtkselect.c (Fpgtk_register_dnd_targets, Fpgtk_drop_finish) (Fpgtk_update_drop_status): New functions. (syms_of_pgtkselect): Register new functions. * src/pgtkterm.c (struct event_queue_t): Fix coding style of definition. (symbol_to_drag_action, drag_action_to_symbol) (pgtk_update_drop_status, pgtk_finish_drop): New functions. (drag_data_received): Delete function. (pgtk_set_event_handler): Register for DND correctly. (syms_of_pgtkterm): New defsyms for DND types. (init_pgtkterm): Delete function. * src/pgtkterm.h: Update prototypes, fix prototype coding style. diff --git a/lisp/loadup.el b/lisp/loadup.el index aa15a3bbe8..f076b8b289 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -346,10 +346,8 @@ (load "term/ns-win")))) (if (featurep 'pgtk) (progn + (load "pgtk-dnd") (load "term/common-win") - ;; Don't load ucs-normalize.el unless uni-*.el files were - ;; already produced, because it needs uni-*.el files that might - ;; not be built early enough during bootstrap. (load "term/pgtk-win"))) (if (fboundp 'x-create-frame) ;; Do it after loading term/foo-win.el since the value of the diff --git a/lisp/pgtk-dnd.el b/lisp/pgtk-dnd.el new file mode 100644 index 0000000000..2aaf4c4e97 --- /dev/null +++ b/lisp/pgtk-dnd.el @@ -0,0 +1,400 @@ +;;; pgtk-dnd.el --- drag and drop support for GDK -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; Maintainer: emacs-devel@gnu.org +;; Keywords: window, drag, drop +;; Package: emacs + +;; Significant portions taken from x-dnd.el. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; This file provides the receiving side of the GDK drag and drop +;; mechanism. + +;;; Code: + +(require 'dnd) + +;;; Customizable variables +(defcustom pgtk-dnd-test-function #'pgtk-dnd-default-test-function + "The function drag and drop uses to determine if to accept or reject a drop. +The function takes three arguments, WINDOW, ACTION and TYPES. +WINDOW is where the mouse is when the function is called. WINDOW +may be a frame if the mouse isn't over a real window (i.e. menu +bar, tool bar or scroll bar). ACTION is the suggested action +from the drag and drop source, one of the symbols move, copy, +link or ask. TYPES is a vector of available types for the drop. + +Each element of TYPE should either be a string (containing the +name of the type's X atom), or a symbol, whose name will be used. + +The function shall return nil to reject the drop or a cons with +two values, the wanted action as car and the wanted type as cdr. +The wanted action can be copy, move, link, ask or private. + +The default value for this variable is `pgtk-dnd-default-test-function'." + :version "22.1" + :type 'symbol + :group 'pgtk) + +(defcustom pgtk-dnd-types-alist + `((,(purecopy "text/uri-list") . pgtk-dnd-handle-uri-list) + (,(purecopy "FILE_NAME") . pgtk-dnd-handle-file-name) + (,(purecopy "UTF8_STRING") . pgtk-dnd-insert-utf8-text) + (,(purecopy "text/plain;charset=UTF-8") . pgtk-dnd-insert-utf8-text) + (,(purecopy "text/plain;charset=utf-8") . pgtk-dnd-insert-utf8-text) + (,(purecopy "text/plain") . dnd-insert-text) + (,(purecopy "COMPOUND_TEXT") . pgtk-dnd-insert-ctext) + (,(purecopy "STRING") . dnd-insert-text) + (,(purecopy "TEXT") . dnd-insert-text)) + "Which function to call to handle a drop of that type. +If the type for the drop is not present, or the function is nil, +the drop is rejected. The function takes three arguments, WINDOW, ACTION +and DATA. WINDOW is where the drop occurred, ACTION is the action for +this drop (copy, move, link, private or ask) as determined by a previous +call to `pgtk-dnd-test-function'. DATA is the drop data. +The function shall return the action used (copy, move, link or private) +if drop is successful, nil if not." + :version "22.1" + :type 'alist + :group 'pgtk) + +(defcustom pgtk-dnd-known-types + (mapcar 'purecopy '("text/uri-list" + "FILE_NAME" + "UTF8_STRING" + "text/plain;charset=UTF-8" + "text/plain;charset=utf-8" + "text/plain" + "COMPOUND_TEXT" + "STRING" + "TEXT")) + "The types accepted by default for dropped data. +The types are chosen in the order they appear in the list." + :version "22.1" + :type '(repeat string) + :group 'pgtk) + +(defcustom pgtk-dnd-use-offix-drop 'files + "If non-nil, use the OffiX protocol to drop files and text. +This allows dropping (via `dired-mouse-drag-files' or +`mouse-drag-and-drop-region-cross-program') on some old Java +applets and old KDE programs. Turning this off allows dropping +only text on some other programs such as xterm and urxvt. + +If the symbol `files', use the OffiX protocol when dropping +files, and the fallback drop method (which is used with programs +like xterm) for text." + :version "29.1" + :type '(choice (const :tag "Don't use the OffiX protocol for drag-and-drop" nil) + (const :tag "Only use the OffiX protocol to drop files" files) + (const :tag "Use the OffiX protocol for both files and text" t)) + :group 'pgtk) + +;; Internal variables + +(defvar pgtk-dnd-current-state nil + "The current state for a drop. +This is an alist with one entry for each display. The value for each display +is a vector that contains the state for drag and drop for that display. +Elements in the vector are: +Last buffer drag was in, +last window drag was in, +types available for drop, +the action suggested by the source, +the type we want for the drop, +the action we want for the drop, +any protocol specific data.") + +(declare-function pgtk-get-selection-internal "pgtkselect.c") +(declare-function pgtk-register-dnd-targets "pgtkselect.c") + +(defvar pgtk-dnd-empty-state [nil nil nil nil nil nil nil]) + +(defun pgtk-dnd-init-frame (&optional frame) + "Setup drag and drop for FRAME (i.e. create appropriate properties)." + (when (eq 'pgtk (window-system frame)) + (pgtk-register-dnd-targets frame pgtk-dnd-known-types))) + +(defun pgtk-dnd-get-state-cons-for-frame (frame-or-window) + "Return the entry in `pgtk-dnd-current-state' for a frame or window." + (let* ((frame (if (framep frame-or-window) frame-or-window + (window-frame frame-or-window))) + (display (frame-parameter frame 'display))) + (if (not (assoc display pgtk-dnd-current-state)) + (push (cons display (copy-sequence pgtk-dnd-empty-state)) + pgtk-dnd-current-state)) + (assoc display pgtk-dnd-current-state))) + +(defun pgtk-dnd-get-state-for-frame (frame-or-window) + "Return the state in `pgtk-dnd-current-state' for a frame or window." + (cdr (pgtk-dnd-get-state-cons-for-frame frame-or-window))) + +(defun pgtk-dnd-default-test-function (_window _action types) + "The default test function for drag and drop. +WINDOW is where the mouse is when this function is called. It may be +a frame if the mouse is over the menu bar, scroll bar or tool bar. +ACTION is the suggested action from the source, and TYPES are the +types the drop data can have. This function only accepts drops with +types in `pgtk-dnd-known-types'. It always returns the action `copy'." + (let ((type (pgtk-dnd-choose-type types))) + (when type (cons 'copy type)))) + +(defun pgtk-dnd-current-type (frame-or-window) + "Return the type we want the DND data to be in for the current drop. +FRAME-OR-WINDOW is the frame or window that the mouse is over." + (aref (pgtk-dnd-get-state-for-frame frame-or-window) 4)) + +(defun pgtk-dnd-forget-drop (frame-or-window) + "Remove all state for the last drop. +FRAME-OR-WINDOW is the frame or window that the mouse is over." + (setcdr (pgtk-dnd-get-state-cons-for-frame frame-or-window) + (copy-sequence pgtk-dnd-empty-state))) + +(defun pgtk-dnd-maybe-call-test-function (window action) + "Call `pgtk-dnd-test-function' if something has changed. +WINDOW is the window the mouse is over. ACTION is the suggested +action from the source. If nothing has changed, return the last +action and type we got from `pgtk-dnd-test-function'." + (let ((buffer (when (window-live-p window) + (window-buffer window))) + (current-state (pgtk-dnd-get-state-for-frame window))) + (unless (and (equal buffer (aref current-state 0)) + (equal window (aref current-state 1)) + (equal action (aref current-state 3))) + (save-current-buffer + (when buffer (set-buffer buffer)) + (let* ((action-type (funcall pgtk-dnd-test-function + window + action + (aref current-state 2))) + (handler (cdr (assoc (cdr action-type) pgtk-dnd-types-alist)))) + ;; Ignore action-type if we have no handler. + (setq current-state + (pgtk-dnd-save-state window + action + (when handler action-type))))))) + (let ((current-state (pgtk-dnd-get-state-for-frame window))) + (cons (aref current-state 5) + (aref current-state 4)))) + +(defun pgtk-dnd-save-state (window action action-type &optional types extra-data) + "Save the state of the current drag and drop. +WINDOW is the window the mouse is over. ACTION is the action suggested +by the source. ACTION-TYPE is the result of calling `pgtk-dnd-test-function'. +If given, TYPES are the types for the drop data that the source supports. +EXTRA-DATA is data needed for a specific protocol." + (let ((current-state (pgtk-dnd-get-state-for-frame window))) + (aset current-state 5 (car action-type)) + (aset current-state 4 (cdr action-type)) + (aset current-state 3 action) + (when types (aset current-state 2 types)) + (when extra-data (aset current-state 6 extra-data)) + (aset current-state 1 window) + (aset current-state 0 (and (window-live-p window) (window-buffer window))) + (setcdr (pgtk-dnd-get-state-cons-for-frame window) current-state))) + + +(defun pgtk-dnd-handle-moz-url (window action data) + "Handle one item of type text/x-moz-url. +WINDOW is the window where the drop happened. ACTION is ignored. +DATA is the moz-url, which is formatted as two strings separated by \\r\\n. +The first string is the URL, the second string is the title of that URL. +DATA is encoded in utf-16. Decode the URL and call `pgtk-dnd-handle-uri-list'." + ;; Mozilla and applications based on it use text/unicode, but it is + ;; impossible to tell if it is le or be. Use what the machine Emacs + ;; runs on uses. This loses if dropping between machines + ;; with different endian-ness, but it is the best we can do. + (let* ((coding (if (eq (byteorder) ?B) 'utf-16be 'utf-16le)) + (string (decode-coding-string data coding)) + (strings (split-string string "[\r\n]" t)) + ;; Can one drop more than one moz-url ?? Assume not. + (url (car strings))) + (pgtk-dnd-handle-uri-list window action url))) + +(defun pgtk-dnd-insert-utf8-text (window action text) + "Decode the UTF-8 text and insert it at point. +TEXT is the text as a string, WINDOW is the window where the drop happened." + (dnd-insert-text window action (decode-coding-string text 'utf-8))) + +(defun pgtk-dnd-insert-utf16-text (window action text) + "Decode the UTF-16 text and insert it at point. +TEXT is the text as a string, WINDOW is the window where the drop happened." + ;; See comment in pgtk-dnd-handle-moz-url about coding. + (let ((coding (if (eq (byteorder) ?B) 'utf-16be 'utf-16le))) + (dnd-insert-text window action (decode-coding-string text coding)))) + +(defun pgtk-dnd-insert-ctext (window action text) + "Decode the compound text and insert it at point. +TEXT is the text as a string, WINDOW is the window where the drop happened." + (dnd-insert-text window action + (decode-coding-string text + 'compound-text-with-extensions))) + +(defun pgtk-dnd-handle-uri-list (window action string) + "Split an uri-list into separate URIs and call `dnd-handle-one-url'. +WINDOW is the window where the drop happened. +STRING is the uri-list as a string. The URIs are separated by \\r\\n." + (let ((uri-list (split-string string "[\0\r\n]" t)) + retval) + (dolist (bf uri-list) + ;; If one URL is handled, treat as if the whole drop succeeded. + (let ((did-action (dnd-handle-one-url window action bf))) + (when did-action (setq retval did-action)))) + retval)) + +(defun pgtk-dnd-handle-file-name (window action string) + "Convert file names to URLs and call `dnd-handle-one-url'. +WINDOW is the window where the drop happened. +STRING is the file names as a string, separated by nulls." + (let ((uri-list (split-string string "[\0\r\n]" t)) + (coding (or file-name-coding-system + default-file-name-coding-system)) + retval) + (dolist (bf uri-list) + ;; If one URL is handled, treat as if the whole drop succeeded. + (if coding (setq bf (encode-coding-string bf coding))) + (let* ((file-uri (concat "file://" + (mapconcat 'url-hexify-string + (split-string bf "/") "/"))) + (did-action (dnd-handle-one-url window action file-uri))) + (when did-action (setq retval did-action)))) + retval)) + + +(defun pgtk-dnd-choose-type (types &optional known-types) + "Choose which type we want to receive for the drop. +TYPES are the types the source of the drop offers, a vector of type names +as strings or symbols. Select among the types in `pgtk-dnd-known-types' or +KNOWN-TYPES if given, and return that type name. +If no suitable type is found, return nil." + (let* ((known-list (or known-types pgtk-dnd-known-types)) + (first-known-type (car known-list)) + (types-array types) + (found (when first-known-type + (catch 'done + (dotimes (i (length types-array)) + (let* ((type (aref types-array i)) + (typename (if (symbolp type) + (symbol-name type) type))) + (when (equal first-known-type typename) + (throw 'done first-known-type)))) + nil)))) + + (if (and (not found) (cdr known-list)) + (pgtk-dnd-choose-type types (cdr known-list)) + found))) + +(defun pgtk-dnd-drop-data (event frame window data type) + "Drop one data item onto a frame. +EVENT is the client message for the drop, FRAME is the frame the drop +occurred on. WINDOW is the window of FRAME where the drop happened. +DATA is the data received from the source, and type is the type for DATA, +see `pgtk-dnd-types-alist'). + +Returns the action used (move, copy, link, private) if drop was successful, +nil if not." + (let* ((type-info (assoc type pgtk-dnd-types-alist)) + (handler (cdr type-info)) + (state (pgtk-dnd-get-state-for-frame frame)) + (action (aref state 5)) + (w (posn-window (event-start event)))) + (when handler + (if (and (window-live-p w) + (not (window-minibuffer-p w)) + (not (window-dedicated-p w))) + ;; If dropping in an ordinary window which we could use, + ;; let dnd-open-file-other-window specify what to do. + (progn + (when (and (not mouse-yank-at-point) + ;; If dropping on top of the mode line, insert + ;; the text at point instead. + (posn-point (event-start event))) + (goto-char (posn-point (event-start event)))) + (funcall handler window action data)) + ;; If we can't display the file here, + ;; make a new window for it. + (let ((dnd-open-file-other-window t)) + (select-frame frame) + (funcall handler window action data)))))) + +(defun pgtk-dnd-handle-drag-n-drop-event (event) + "Receive drag and drop events (X client messages). +Currently XDND, Motif and old KDE 1.x protocols are recognized." + (interactive "e") + (let* ((client-message (car (cdr (cdr event)))) + (window (posn-window (event-start event))) + (frame (if (framep window) + window + (window-frame window)))) + (pgtk-dnd-handle-gdk event frame window client-message))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; GDK protocol. + +(declare-function pgtk-update-drop-status "pgtkselect.c") +(declare-function pgtk-drop-finish "pgtkselect.c") + +(defun pgtk-dnd-handle-gdk (event frame window client-message) + "Handle drag-n-drop EVENT on FRAME. +WINDOW should be the window the event happened on top of. +CLIENT-MESSAGE is the detailed description of the drag-and-drop +message." + (cond + ;; We can't handle `drag-leave' here, since that signal is also + ;; sent right before `drag-drop', and there is no reliable way to + ;; distinguish the two. + ((eq (car client-message) 'lambda) ; drag-motion + (let ((state (pgtk-dnd-get-state-for-frame frame))) + (unless (aref state 0) ;; This is actually an entry. + (pgtk-dnd-save-state window nil nil + (pgtk-get-selection-internal + (nth 1 client-message) 'TARGETS) + t) + (setq state (pgtk-dnd-get-state-for-frame frame))) + (let* ((action (nth 3 client-message)) + (time (nth 2 client-message)) + (action-type (pgtk-dnd-maybe-call-test-function window + action))) + (pgtk-update-drop-status (car action-type) time) + (dnd-handle-movement (event-start event))))) + ((eq (car client-message) 'quote) ; drag-drop + (let* ((timestamp (nth 2 client-message)) + (value (and (pgtk-dnd-current-type window) + (pgtk-get-selection-internal + (nth 1 client-message) + (intern (pgtk-dnd-current-type window)) + timestamp))) + action) + (unwind-protect + (setq action (when value + (condition-case info + (pgtk-dnd-drop-data + event frame window value + (pgtk-dnd-current-type window)) + (error + (message "Error: %s" info) + nil)))) + (pgtk-drop-finish action timestamp (eq action 'move)) + (pgtk-dnd-forget-drop window)))))) + +(provide 'pgtk-dnd) + +;;; pgtk-dnd.el ends here diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 8abea3edba..ee1aad3d0e 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -38,6 +38,7 @@ (require 'menu-bar) (require 'fontset) (require 'dnd) +(require 'pgtk-dnd) (defvar x-invocation-args) (defvar x-command-line-resources) @@ -389,6 +390,10 @@ Users should not call this function; see `device-class' instead." (defvaralias 'x-gtk-use-system-tooltips 'use-system-tooltips) + +(define-key special-event-map [drag-n-drop] #'pgtk-dnd-handle-drag-n-drop-event) +(add-hook 'after-make-frame-functions #'pgtk-dnd-init-frame) + (provide 'pgtk-win) (provide 'term/pgtk-win) diff --git a/src/emacs.c b/src/emacs.c index 37c6c76e7a..3c76841281 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1930,9 +1930,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_bignum (); init_threads (); init_eval (); -#ifdef HAVE_PGTK - init_pgtkterm (); /* Must come before `init_atimer'. */ -#endif running_asynch_code = 0; init_random (); init_xfaces (); diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 122b5d8c07..2a4f6adba4 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -1762,6 +1762,86 @@ pgtk_handle_selection_notify (GdkEventSelection *event) (event->property != GDK_NONE ? Qt : Qlambda)); } + +/*********************************************************************** + Drag and drop support +***********************************************************************/ + +DEFUN ("pgtk-register-dnd-targets", Fpgtk_register_dnd_targets, + Spgtk_register_dnd_targets, 2, 2, 0, + doc: /* Register TARGETS on FRAME. +TARGETS should be a list of strings describing data types (selection +targets) that can be dropped on top of FRAME. */) + (Lisp_Object frame, Lisp_Object targets) +{ + struct frame *f; + GtkTargetEntry *entries; + GtkTargetList *list; + ptrdiff_t length, n; + Lisp_Object tem, t; + char *buf; + USE_SAFE_ALLOCA; + + f = decode_window_system_frame (frame); + CHECK_LIST (targets); + length = list_length (targets); + n = 0; + entries = SAFE_ALLOCA (sizeof *entries * length); + memset (entries, 0, sizeof *entries * length); + tem = targets; + + FOR_EACH_TAIL (tem) + { + if (!CONSP (tem)) + continue; + + t = XCAR (tem); + + CHECK_STRING (t); + SAFE_ALLOCA_STRING (buf, t); + + entries[n++].target = buf; + } + CHECK_LIST_END (tem, targets); + + if (n != length) + emacs_abort (); + + list = gtk_target_list_new (entries, n); + gtk_drag_dest_set_target_list (FRAME_GTK_WIDGET (f), list); + gtk_target_list_unref (list); + + SAFE_FREE (); + + return Qnil; +} + +DEFUN ("pgtk-drop-finish", Fpgtk_drop_finish, Spgtk_drop_finish, 3, 3, 0, + doc: /* Finish the drag-n-drop event that happened at TIMESTAMP. +SUCCESS is whether or not the drop was successful, i.e. the action +chosen in the last call to `pgtk-update-drop-status' was performed. +TIMESTAMP is the time associated with the drag-n-drop event that is +being finished. +DELETE is whether or not the action was `move'. */) + (Lisp_Object success, Lisp_Object timestamp, Lisp_Object delete) +{ + pgtk_finish_drop (success, timestamp, delete); + + return Qnil; +} + +DEFUN ("pgtk-update-drop-status", Fpgtk_update_drop_status, + Spgtk_update_drop_status, 2, 2, 0, + doc: /* Update the status of the current drag-and-drop operation. +ACTION is the action the drop source should take. +TIMESTAMP is the same as in `pgtk-drop-finish'. */) + (Lisp_Object action, Lisp_Object timestamp) +{ + pgtk_update_drop_status (action, timestamp); + + return Qnil; +} + void syms_of_pgtkselect (void) { @@ -1777,23 +1857,22 @@ syms_of_pgtkselect (void) DEFSYM (QNULL, "NULL"); DEFSYM (QATOM, "ATOM"); DEFSYM (QTARGETS, "TARGETS"); - - DEFSYM (Qpgtk_sent_selection_functions, - "pgtk-sent-selection-functions"); - DEFSYM (Qpgtk_lost_selection_functions, - "pgtk-lost-selection-functions"); - - DEFSYM (Qforeign_selection, "foreign-selection"); DEFSYM (QUTF8_STRING, "UTF8_STRING"); - DEFSYM (QSTRING, "STRING"); DEFSYM (QCOMPOUND_TEXT, "COMPOUND_TEXT"); - DEFSYM (Qtext_plain_charset_utf_8, "text/plain;charset=utf-8"); + + DEFSYM (Qforeign_selection, "foreign-selection"); + + DEFSYM (Qpgtk_sent_selection_functions, "pgtk-sent-selection-functions"); + DEFSYM (Qpgtk_lost_selection_functions, "pgtk-lost-selection-functions"); defsubr (&Spgtk_disown_selection_internal); defsubr (&Spgtk_get_selection_internal); defsubr (&Spgtk_own_selection_internal); defsubr (&Spgtk_selection_exists_p); defsubr (&Spgtk_selection_owner_p); + defsubr (&Spgtk_register_dnd_targets); + defsubr (&Spgtk_update_drop_status); + defsubr (&Spgtk_drop_finish); DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist, doc: /* SKIP: real doc in xselect.c. */); @@ -1817,7 +1896,7 @@ The functions are called with three arguments: We might have failed (and declined the request) for any number of reasons, including being asked for a selection that we no longer own, or being asked to convert into a type that we don't know about or that is inappropriate. -This hook doesn't let you change the behavior of Emacs's selection replies, +xThis hook doesn't let you change the behavior of Emacs's selection replies, it merely informs you that they have happened. */); Vpgtk_sent_selection_functions = Qnil; diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 91874ff58a..a123311366 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -76,25 +76,36 @@ along with GNU Emacs. If not, see . */ static bool any_help_event_p; -struct pgtk_display_info *x_display_list; /* Chain of existing displays */ -extern Lisp_Object tip_frame; +/* Chain of existing displays */ +struct pgtk_display_info *x_display_list; -static struct event_queue_t +struct event_queue_t { union buffered_input_event *q; int nr, cap; -} event_q = { - NULL, 0, 0, }; +/* A queue of events that will be read by the read_socket_hook. */ +static struct event_queue_t event_q; + /* Non-zero timeout value means ignore next mouse click if it arrives before that timeout elapses (i.e. as part of the same sequence of events resulting from clicking on a frame to select it). */ - static Time ignore_next_mouse_click_timeout; +/* The default Emacs icon . */ static Lisp_Object xg_default_icon_file; +/* The current GdkDragContext of a drop. */ +static GdkDragContext *current_drop_context; + +/* Whether or not current_drop_context was set from a drop + handler. */ +static bool current_drop_context_drop; + +/* The time of the last drop. */ +static guint32 current_drop_time; + static void pgtk_delete_display (struct pgtk_display_info *); static void pgtk_clear_frame_area (struct frame *, int, int, int, int); static void pgtk_fill_rectangle (struct frame *, unsigned long, int, int, @@ -6146,40 +6157,217 @@ scroll_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) return TRUE; } + + +/* C part of drop handling code. + The Lisp part is in pgtk-dnd.el. */ + +static GdkDragAction +symbol_to_drag_action (Lisp_Object act) +{ + if (EQ (act, Qcopy)) + return GDK_ACTION_COPY; + + if (EQ (act, Qmove)) + return GDK_ACTION_MOVE; + + if (EQ (act, Qlink)) + return GDK_ACTION_LINK; + + if (EQ (act, Qprivate)) + return GDK_ACTION_PRIVATE; + + if (NILP (act)) + return GDK_ACTION_DEFAULT; + + signal_error ("Invalid drag acction", act); +} + +static Lisp_Object +drag_action_to_symbol (GdkDragAction action) +{ + switch (action) + { + case GDK_ACTION_COPY: + return Qcopy; + + case GDK_ACTION_MOVE: + return Qmove; + + case GDK_ACTION_LINK: + return Qlink; + + case GDK_ACTION_PRIVATE: + return Qprivate; + + case GDK_ACTION_DEFAULT: + default: + return Qnil; + } +} + +void +pgtk_update_drop_status (Lisp_Object action, Lisp_Object event_time) +{ + guint32 time; + + CONS_TO_INTEGER (event_time, guint32, time); + + if (!current_drop_context || time < current_drop_time) + return; + + gdk_drag_status (current_drop_context, + symbol_to_drag_action (action), + time); +} + +void +pgtk_finish_drop (Lisp_Object success, Lisp_Object event_time, + Lisp_Object del) +{ + guint32 time; + + CONS_TO_INTEGER (event_time, guint32, time); + + if (!current_drop_context || time < current_drop_time) + return; + + gtk_drag_finish (current_drop_context, !NILP (success), + !NILP (del), time); + + if (current_drop_context_drop) + g_clear_pointer (¤t_drop_context, + g_object_unref); +} + static void -drag_data_received (GtkWidget *widget, GdkDragContext *context, - gint x, gint y, GtkSelectionData *data, - guint info, guint time, gpointer user_data) +drag_leave (GtkWidget *widget, GdkDragContext *context, + guint time, gpointer user_data) { - struct frame *f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); - gchar **uris = gtk_selection_data_get_uris (data); + struct frame *f; + union buffered_input_event inev; + + f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); - if (uris != NULL) + if (current_drop_context) { - for (int i = 0; uris[i] != NULL; i++) - { - union buffered_input_event inev; - Lisp_Object arg = Qnil; + if (current_drop_context_drop) + gtk_drag_finish (current_drop_context, + FALSE, FALSE, current_drop_time); - EVENT_INIT (inev.ie); - inev.ie.kind = NO_EVENT; - inev.ie.arg = Qnil; + g_clear_pointer (¤t_drop_context, + g_object_unref); + } - arg = list2 (Qurl, build_string (uris[i])); + inev.ie.kind = DRAG_N_DROP_EVENT; + inev.ie.modifiers = 0; + inev.ie.arg = Qnil; + inev.ie.timestamp = time; - inev.ie.kind = DRAG_N_DROP_EVENT; - inev.ie.modifiers = 0; - XSETINT (inev.ie.x, x); - XSETINT (inev.ie.y, y); - XSETFRAME (inev.ie.frame_or_window, f); - inev.ie.arg = arg; - inev.ie.timestamp = 0; + XSETINT (inev.ie.x, 0); + XSETINT (inev.ie.y, 0); + XSETFRAME (inev.ie.frame_or_window, f); - evq_enqueue (&inev); - } + evq_enqueue (&inev); +} + +static gboolean +drag_motion (GtkWidget *widget, GdkDragContext *context, + gint x, gint y, guint time) + +{ + struct frame *f; + union buffered_input_event inev; + GdkAtom name; + GdkDragAction suggestion; + + f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); + + if (!f) + return FALSE; + + if (current_drop_context) + { + if (current_drop_context_drop) + gtk_drag_finish (current_drop_context, + FALSE, FALSE, current_drop_time); + + g_clear_pointer (¤t_drop_context, + g_object_unref); } - gtk_drag_finish (context, TRUE, FALSE, time); + current_drop_context = g_object_ref (context); + current_drop_time = time; + current_drop_context_drop = false; + + name = gdk_drag_get_selection (context); + suggestion = gdk_drag_context_get_suggested_action (context); + + EVENT_INIT (inev.ie); + + inev.ie.kind = DRAG_N_DROP_EVENT; + inev.ie.modifiers = 0; + inev.ie.arg = list4 (Qlambda, intern (gdk_atom_name (name)), + make_uint (time), + drag_action_to_symbol (suggestion)); + inev.ie.timestamp = time; + + XSETINT (inev.ie.x, x); + XSETINT (inev.ie.y, y); + XSETFRAME (inev.ie.frame_or_window, f); + + evq_enqueue (&inev); + + return TRUE; +} + +static gboolean +drag_drop (GtkWidget *widget, GdkDragContext *context, + int x, int y, guint time, gpointer user_data) +{ + struct frame *f; + union buffered_input_event inev; + GdkAtom name; + GdkDragAction selected_action; + + f = pgtk_any_window_to_frame (gtk_widget_get_window (widget)); + + if (!f) + return FALSE; + + if (current_drop_context) + { + if (current_drop_context_drop) + gtk_drag_finish (current_drop_context, + FALSE, FALSE, current_drop_time); + + g_clear_pointer (¤t_drop_context, + g_object_unref); + } + + current_drop_context = g_object_ref (context); + current_drop_time = time; + current_drop_context_drop = true; + + name = gdk_drag_get_selection (context); + selected_action = gdk_drag_context_get_selected_action (context); + + EVENT_INIT (inev.ie); + + inev.ie.kind = DRAG_N_DROP_EVENT; + inev.ie.modifiers = 0; + inev.ie.arg = list4 (Qquote, intern (gdk_atom_name (name)), + make_uint (time), + drag_action_to_symbol (selected_action)); + inev.ie.timestamp = time; + + XSETINT (inev.ie.x, x); + XSETINT (inev.ie.y, y); + XSETFRAME (inev.ie.frame_or_window, f); + + evq_enqueue (&inev); + + return TRUE; } static void @@ -6208,9 +6396,9 @@ pgtk_set_event_handler (struct frame *f) return; } - gtk_drag_dest_set (FRAME_GTK_WIDGET (f), GTK_DEST_DEFAULT_ALL, NULL, 0, - GDK_ACTION_COPY); - gtk_drag_dest_add_uri_targets (FRAME_GTK_WIDGET (f)); + gtk_drag_dest_set (FRAME_GTK_WIDGET (f), 0, NULL, 0, + (GDK_ACTION_MOVE | GDK_ACTION_COPY + | GDK_ACTION_LINK | GDK_ACTION_PRIVATE)); if (FRAME_GTK_OUTER_WIDGET (f)) { @@ -6251,8 +6439,12 @@ pgtk_set_event_handler (struct frame *f) G_CALLBACK (scroll_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event", G_CALLBACK (configure_event), NULL); - g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received", - G_CALLBACK (drag_data_received), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-leave", + G_CALLBACK (drag_leave), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-motion", + G_CALLBACK (drag_motion), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-drop", + G_CALLBACK (drag_drop), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw", G_CALLBACK (pgtk_handle_draw), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event", @@ -6803,12 +6995,17 @@ syms_of_pgtkterm (void) DEFSYM (Qlatin_1, "latin-1"); - xg_default_icon_file = - build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); + xg_default_icon_file + = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); staticpro (&xg_default_icon_file); DEFSYM (Qx_gtk_map_stock, "x-gtk-map-stock"); + DEFSYM (Qcopy, "copy"); + DEFSYM (Qmove, "move"); + DEFSYM (Qlink, "link"); + DEFSYM (Qprivate, "private"); + Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); @@ -7093,8 +7290,3 @@ pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type) return CALLN (Fapply, intern ("concat"), Fnreverse (acc)); } - -void -init_pgtkterm (void) -{ -} diff --git a/src/pgtkterm.h b/src/pgtkterm.h index 86578be6b5..fcc6c5310e 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -448,9 +448,9 @@ enum #define FRAME_FONT(f) (FRAME_X_OUTPUT (f)->font) #define FRAME_GTK_OUTER_WIDGET(f) (FRAME_X_OUTPUT (f)->widget) #define FRAME_GTK_WIDGET(f) (FRAME_X_OUTPUT (f)->edit_widget) -#define FRAME_WIDGET(f) (FRAME_GTK_OUTER_WIDGET (f) ? \ - FRAME_GTK_OUTER_WIDGET (f) : \ - FRAME_GTK_WIDGET (f)) +#define FRAME_WIDGET(f) (FRAME_GTK_OUTER_WIDGET (f) \ + ? FRAME_GTK_OUTER_WIDGET (f) \ + : FRAME_GTK_WIDGET (f)) #define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET (f) #define FRAME_X_WINDOW(f) FRAME_GTK_OUTER_WIDGET (f) @@ -538,69 +538,57 @@ extern void pgtk_handle_property_notify (GdkEventProperty *); extern void pgtk_handle_selection_notify (GdkEventSelection *); /* Display init/shutdown functions implemented in pgtkterm.c */ -extern struct pgtk_display_info *pgtk_term_init (Lisp_Object display_name, - char *resource_name); -extern void pgtk_term_shutdown (int sig); +extern struct pgtk_display_info *pgtk_term_init (Lisp_Object, char *); +extern void pgtk_term_shutdown (int); /* Implemented in pgtkterm, published in or needed from pgtkfns. */ -extern void pgtk_clear_frame (struct frame *f); -extern char *pgtk_xlfd_to_fontname (const char *xlfd); +extern void pgtk_clear_frame (struct frame *); +extern char *pgtk_xlfd_to_fontname (const char *); /* Implemented in pgtkfns.c. */ extern void pgtk_set_doc_edited (void); -extern const char *pgtk_get_defaults_value (const char *key); -extern const char *pgtk_get_string_resource (XrmDatabase rdb, - const char *name, - const char *class); -extern void pgtk_implicitly_set_name (struct frame *f, Lisp_Object arg, - Lisp_Object oldval); +extern const char *pgtk_get_defaults_value (const char *); +extern const char *pgtk_get_string_resource (XrmDatabase, const char *, const char *); +extern void pgtk_implicitly_set_name (struct frame *, Lisp_Object, Lisp_Object); /* Color management implemented in pgtkterm. */ -extern bool pgtk_defined_color (struct frame *f, - const char *name, - Emacs_Color * color_def, bool alloc, - bool makeIndex); -extern void pgtk_query_color (struct frame *f, Emacs_Color * color); -extern void pgtk_query_colors (struct frame *f, Emacs_Color * colors, - int ncolors); -extern int pgtk_parse_color (struct frame *f, const char *color_name, - Emacs_Color * color); +extern bool pgtk_defined_color (struct frame *, const char *, + Emacs_Color *, bool, bool); +extern void pgtk_query_color (struct frame *, Emacs_Color *); +extern void pgtk_query_colors (struct frame *, Emacs_Color *, int); +extern int pgtk_parse_color (struct frame *, const char *, Emacs_Color *); /* Implemented in pgtkterm.c */ -extern void pgtk_clear_area (struct frame *f, int x, int y, int width, - int height); -extern int pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *dpyinfo, - int state); -extern void pgtk_clear_under_internal_border (struct frame *f); -extern void pgtk_set_event_handler (struct frame *f); +extern void pgtk_clear_area (struct frame *, int, int, int, int); +extern int pgtk_gtk_to_emacs_modifiers (struct pgtk_display_info *, int); +extern void pgtk_clear_under_internal_border (struct frame *); +extern void pgtk_set_event_handler (struct frame *); /* Implemented in pgtkterm.c */ extern int pgtk_display_pixel_height (struct pgtk_display_info *); extern int pgtk_display_pixel_width (struct pgtk_display_info *); -extern void pgtk_destroy_window (struct frame *f); -extern void pgtk_set_parent_frame (struct frame *f, Lisp_Object, Lisp_Object); +extern void pgtk_destroy_window (struct frame *); +extern void pgtk_set_parent_frame (struct frame *, Lisp_Object, Lisp_Object); extern void pgtk_set_no_focus_on_map (struct frame *, Lisp_Object, Lisp_Object); extern void pgtk_set_no_accept_focus (struct frame *, Lisp_Object, Lisp_Object); extern void pgtk_set_z_group (struct frame *, Lisp_Object, Lisp_Object); /* Cairo related functions implemented in pgtkterm.c */ extern void pgtk_cr_update_surface_desired_size (struct frame *, int, int, bool); -extern cairo_t *pgtk_begin_cr_clip (struct frame *f); -extern void pgtk_end_cr_clip (struct frame *f); +extern cairo_t *pgtk_begin_cr_clip (struct frame *); +extern void pgtk_end_cr_clip (struct frame *); extern void pgtk_set_cr_source_with_gc_foreground (struct frame *, Emacs_GC *, bool); extern void pgtk_set_cr_source_with_gc_background (struct frame *, Emacs_GC *, bool); extern void pgtk_set_cr_source_with_color (struct frame *, unsigned long, bool); -extern void pgtk_cr_draw_frame (cairo_t * cr, struct frame *f); -extern void pgtk_cr_destroy_frame_context (struct frame *f); -extern Lisp_Object pgtk_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type); +extern void pgtk_cr_draw_frame (cairo_t *, struct frame *); +extern void pgtk_cr_destroy_frame_context (struct frame *); +extern Lisp_Object pgtk_cr_export_frames (Lisp_Object , cairo_surface_type_t); /* Defined in pgtkmenu.c */ -extern Lisp_Object pgtk_popup_dialog (struct frame *f, Lisp_Object header, - Lisp_Object contents); -extern Lisp_Object pgtk_dialog_show (struct frame *f, Lisp_Object title, - Lisp_Object header, - const char **error_name); +extern Lisp_Object pgtk_popup_dialog (struct frame *, Lisp_Object, Lisp_Object); +extern Lisp_Object pgtk_dialog_show (struct frame *, Lisp_Object, Lisp_Object, + const char **); extern void initialize_frame_menubar (struct frame *); @@ -612,44 +600,46 @@ extern void syms_of_pgtkselect (void); extern void syms_of_pgtkim (void); /* Initialization and marking implemented in pgtkterm.c */ -extern void init_pgtkterm (void); extern void mark_pgtkterm (void); -extern void pgtk_delete_terminal (struct terminal *terminal); +extern void pgtk_delete_terminal (struct terminal *); -extern void pgtk_make_frame_visible (struct frame *f); -extern void pgtk_make_frame_invisible (struct frame *f); +extern void pgtk_make_frame_visible (struct frame *); +extern void pgtk_make_frame_invisible (struct frame *); extern void pgtk_free_frame_resources (struct frame *); -extern void pgtk_iconify_frame (struct frame *f); -extern void pgtk_focus_frame (struct frame *f, bool noactivate); -extern void pgtk_set_scroll_bar_default_width (struct frame *f); -extern void pgtk_set_scroll_bar_default_height (struct frame *f); -extern Lisp_Object pgtk_get_focus_frame (struct frame *frame); +extern void pgtk_iconify_frame (struct frame *); +extern void pgtk_focus_frame (struct frame *, bool); +extern void pgtk_set_scroll_bar_default_width (struct frame *); +extern void pgtk_set_scroll_bar_default_height (struct frame *); +extern Lisp_Object pgtk_get_focus_frame (struct frame *); -extern void pgtk_frame_rehighlight (struct pgtk_display_info *dpyinfo); +extern void pgtk_frame_rehighlight (struct pgtk_display_info *); extern void pgtk_change_tab_bar_height (struct frame *, int); -extern struct pgtk_display_info *check_pgtk_display_info (Lisp_Object object); +extern struct pgtk_display_info *check_pgtk_display_info (Lisp_Object); -extern void pgtk_default_font_parameter (struct frame *f, Lisp_Object parms); +extern void pgtk_default_font_parameter (struct frame *, Lisp_Object); -extern void pgtk_menu_set_in_use (bool in_use); +extern void pgtk_menu_set_in_use (bool); +/* Drag and drop functions used by Lisp. */ +extern void pgtk_update_drop_status (Lisp_Object, Lisp_Object); +extern void pgtk_finish_drop (Lisp_Object, Lisp_Object, Lisp_Object); -extern void pgtk_enqueue_string (struct frame *f, gchar * str); -extern void pgtk_enqueue_preedit (struct frame *f, Lisp_Object image_data); -extern void pgtk_im_focus_in (struct frame *f); -extern void pgtk_im_focus_out (struct frame *f); -extern bool pgtk_im_filter_keypress (struct frame *f, GdkEventKey * ev); -extern void pgtk_im_set_cursor_location (struct frame *f, int x, int y, - int width, int height); -extern void pgtk_im_init (struct pgtk_display_info *dpyinfo); -extern void pgtk_im_finish (struct pgtk_display_info *dpyinfo); +extern void pgtk_enqueue_string (struct frame *, gchar *); +extern void pgtk_enqueue_preedit (struct frame *, Lisp_Object); +extern void pgtk_im_focus_in (struct frame *); +extern void pgtk_im_focus_out (struct frame *); +extern bool pgtk_im_filter_keypress (struct frame *, GdkEventKey *); +extern void pgtk_im_set_cursor_location (struct frame *, int, int, + int, int); +extern void pgtk_im_init (struct pgtk_display_info *); +extern void pgtk_im_finish (struct pgtk_display_info *); extern bool xg_set_icon (struct frame *, Lisp_Object); -extern bool xg_set_icon_from_xpm_data (struct frame *f, const char **data); +extern bool xg_set_icon_from_xpm_data (struct frame *, const char **); -extern bool pgtk_text_icon (struct frame *f, const char *icon_name); +extern bool pgtk_text_icon (struct frame *, const char *); extern double pgtk_frame_scale_factor (struct frame *); extern int pgtk_emacs_to_gtk_modifiers (struct pgtk_display_info *, int); commit 00034ad2e635adc93cd1d6dcb1b500c10d990c74 Merge: 41540b9324 a3f294b37f Author: Stefan Kangas Date: Thu Jun 23 06:30:22 2022 +0200 Merge from origin/emacs-28 a3f294b37f Improve last change in autotype.texi commit 41540b9324283ec924d0f818e649b4b9d7679d10 Author: Po Lu Date: Thu Jun 23 11:31:10 2022 +0800 Don't send XdndPosition before XdndStatus arrives * src/xterm.c (x_dnd_send_position): Set pending DND message if target is right. (x_dnd_send_leave): Clear pending status target. (x_dnd_begin_drag_and_drop): Clear new flags. (handle_one_xevent): Respect those flags. diff --git a/src/xterm.c b/src/xterm.c index b6300f831f..d3e6c5323b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1235,6 +1235,14 @@ static Window x_dnd_mouse_rect_target; drop target if the mouse pointer lies within. */ static XRectangle x_dnd_mouse_rect; +/* If not None, Emacs is waiting for an XdndStatus event from this + window. */ +static Window x_dnd_waiting_for_status_window; + +/* If .type != 0, an event that should be sent to .xclient.window + upon receiving an XdndStatus event from said window. */ +static XEvent x_dnd_pending_send_position; + /* The action the drop target actually chose to perform. Under XDND, this is set upon receiving the XdndFinished or @@ -4380,9 +4388,16 @@ x_dnd_send_position (struct frame *f, Window target, int supported, if (supported >= 4) msg.xclient.data.l[4] = action; - x_catch_errors (dpyinfo->display); - XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); - x_uncatch_errors (); + if (x_dnd_waiting_for_status_window == target) + x_dnd_pending_send_position = msg; + else + { + x_catch_errors (dpyinfo->display); + XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); + x_uncatch_errors (); + + x_dnd_waiting_for_status_window = target; + } } static void @@ -4401,6 +4416,9 @@ x_dnd_send_leave (struct frame *f, Window target) msg.xclient.data.l[3] = 0; msg.xclient.data.l[4] = 0; + puts ("RESET PENDING"); + x_dnd_waiting_for_status_window = None; + x_catch_errors (dpyinfo->display); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); x_uncatch_errors (); @@ -11437,6 +11455,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_return_frame = 0; x_dnd_waiting_for_finish = false; x_dnd_waiting_for_motif_finish = 0; + x_dnd_waiting_for_status_window = None; + x_dnd_pending_send_position.type = 0; x_dnd_xm_use_help = false; x_dnd_motif_setup_p = false; x_dnd_end_window = None; @@ -16326,6 +16346,22 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_action = None; } + /* Send any pending XdndPosition message. */ + if (x_dnd_waiting_for_status_window == target) + { + if (x_dnd_pending_send_position.type != 0) + { + x_catch_errors (dpyinfo->display); + XSendEvent (dpyinfo->display, target, + False, NoEventMask, + &x_dnd_pending_send_position); + x_uncatch_errors (); + } + + x_dnd_pending_send_position.type = 0; + x_dnd_waiting_for_status_window = None; + } + goto done; } commit ee6e4bc525125c77d284039c0ab2e2ce4d70c7e3 Author: Po Lu Date: Thu Jun 23 08:53:55 2022 +0800 Update device-specific grab during drag-and-drop * src/xterm.c (x_detect_focus_change): Fix typo. (handle_one_xevent): Set device if DND is in progress and update device->grab. diff --git a/src/xterm.c b/src/xterm.c index cfe329ab0f..b6300f831f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11928,8 +11928,8 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame, really has focus, and these kinds of focus event don't correspond to real user input changes. GTK+ uses the same filtering. */ - if (event->xfocus.mode == NotifyGrab || - event->xfocus.mode == NotifyUngrab) + if (event->xfocus.mode == NotifyGrab + || event->xfocus.mode == NotifyUngrab) return; x_focus_changed (event->type, (event->xfocus.detail == NotifyPointer ? @@ -20081,6 +20081,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { f = mouse_or_wdesc_frame (dpyinfo, xev->event); + device = xi_device_from_id (dpyinfo, xev->deviceid); /* Don't track grab status for emulated pointer events, because they are ignored by the regular @@ -20096,6 +20097,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, dpyinfo->grabbed |= (1 << xev->detail); dpyinfo->last_mouse_frame = f; + + if (device) + device->grab |= (1 << xev->detail); + if (f && !tab_bar_p) f->last_tab_bar_item = -1; #if ! defined (USE_GTK) @@ -20104,7 +20109,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif /* not USE_GTK */ } else - dpyinfo->grabbed &= ~(1 << xev->detail); + { + dpyinfo->grabbed &= ~(1 << xev->detail); + device->grab &= ~(1 << xev->detail); + } #ifdef XIPointerEmulated } #endif commit 2bf96389f7e28a2a0ba74606e84fc0aafd3009e6 Author: Stefan Kangas Date: Thu Jun 23 01:12:05 2022 +0200 Make recentf-elements obsolete * lisp/recentf.el (recentf-elements): Make obsolete. Update callers. diff --git a/lisp/recentf.el b/lisp/recentf.el index fa467afa00..b10f4d0ed0 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -515,10 +515,6 @@ If non-nil it must contain a list of valid menu-items to be appended to the recent file list part of the menu. Before calling a menu filter function this variable is reset to nil.") -(defun recentf-elements (n) - "Return a list of the first N elements of the recent list." - (seq-take recentf-list n)) - (defsubst recentf-make-menu-element (menu-item menu-value) "Create a new menu-element. A menu element is a pair (MENU-ITEM . MENU-VALUE), where MENU-ITEM is @@ -558,7 +554,7 @@ This a menu element (FILE . FILE)." "Return a list of the first N default menu elements from the recent list. See also `recentf-make-default-menu-element'." (mapcar #'recentf-make-default-menu-element - (recentf-elements n))) + (seq-take recentf-list n))) (defun recentf-apply-menu-filter (filter l) "Apply function FILTER to the list of menu-elements L. @@ -1395,6 +1391,11 @@ buffers you switch to a lot, you can say something like the following: (define-obsolete-function-alias 'recentf-trunc-list #'seq-take "28.1") +(defun recentf-elements (n) + "Return a list of the first N elements of the recent list." + (declare (obsolete "use `(seq-take recentf-list n)'." "29.1")) + (seq-take recentf-list n)) + (provide 'recentf) (run-hooks 'recentf-load-hook) commit f5515fa8aa28271d43d1ed322518c6ace0534405 Author: Stefan Kangas Date: Thu Jun 23 01:00:54 2022 +0200 Convert several defsubst to defun in recentf.el * lisp/recentf.el (recentf-enabled-p, recentf-string-equal) (recentf-string-lessp, recentf-push, recentf-expand-file-name) (recentf-add-file, recentf-remove-if-non-kept) (recentf-digit-shortcut-command-name, recentf-elements) (recentf-menu-bar, recentf-sort-ascending) (recentf-sort-descending, recentf-sort-basenames-ascending) (recentf-sort-basenames-descending) (recentf-sort-directories-ascending) (recentf-sort-directories-descending) (recentf-show-basenames-ascending) (recentf-show-basenames-descending): Change from defsubst to defun. diff --git a/lisp/recentf.el b/lisp/recentf.el index 1005d4855f..fa467afa00 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -47,9 +47,10 @@ (defvar recentf-list nil "List of recently opened files.") -(defsubst recentf-enabled-p () +(defun recentf-enabled-p () "Return non-nil if recentf mode is currently enabled." (memq 'recentf-save-list kill-emacs-hook)) + ;;; Customization ;; @@ -313,14 +314,14 @@ used as shortcuts to open the Nth file." (memq system-type '(windows-nt cygwin)) "Non-nil if recentf searches and matches should ignore case.") -(defsubst recentf-string-equal (s1 s2) +(defun recentf-string-equal (s1 s2) "Return non-nil if strings S1 and S2 have identical contents. Ignore case if `recentf-case-fold-search' is non-nil." (if recentf-case-fold-search (string-equal (downcase s1) (downcase s2)) (string-equal s1 s2))) -(defsubst recentf-string-lessp (s1 s2) +(defun recentf-string-lessp (s1 s2) "Return non-nil if string S1 is less than S2 in lexicographic order. Ignore case if `recentf-case-fold-search' is non-nil." (if recentf-case-fold-search @@ -375,7 +376,7 @@ See also the option `recentf-auto-cleanup'.") ;;; File functions ;; -(defsubst recentf-push (filename) +(defun recentf-push (filename) "Push FILENAME into the recent list, if it isn't there yet. If it is there yet, move it at the beginning of the list. If `recentf-case-fold-search' is non-nil, ignore case when comparing @@ -398,7 +399,7 @@ returned nil." (error nil)) name)) -(defsubst recentf-expand-file-name (name) +(defun recentf-expand-file-name (name) "Convert file NAME to absolute, and canonicalize it. NAME is first passed to the function `expand-file-name', then to `recentf-filename-handlers' to post process it." @@ -439,7 +440,7 @@ That is, if it matches any of the `recentf-keep' checks." checks (cdr checks))) keepit)) -(defsubst recentf-add-file (filename) +(defun recentf-add-file (filename) "Add or move FILENAME at the beginning of the recent list. Does nothing if the name satisfies any of the `recentf-exclude' regexps or predicates." @@ -447,7 +448,7 @@ regexps or predicates." (when (recentf-include-p filename) (recentf-push filename))) -(defsubst recentf-remove-if-non-kept (filename) +(defun recentf-remove-if-non-kept (filename) "Remove FILENAME from the recent list, if file is not kept. Return non-nil if FILENAME has been removed." (unless (recentf-keep-p filename) @@ -468,7 +469,7 @@ Return non-nil if F1 is less than F2." ;;; Menu building ;; -(defsubst recentf-digit-shortcut-command-name (n) +(defun recentf-digit-shortcut-command-name (n) "Return a command name to open the Nth most recent file. See also the command `recentf-open-most-recent-file'." (intern (format "recentf-open-most-recent-file-%d" n))) @@ -514,7 +515,7 @@ If non-nil it must contain a list of valid menu-items to be appended to the recent file list part of the menu. Before calling a menu filter function this variable is reset to nil.") -(defsubst recentf-elements (n) +(defun recentf-elements (n) "Return a list of the first N elements of the recent list." (seq-take recentf-list n)) @@ -654,7 +655,7 @@ Return nil if file NAME is not one of the ten more recent." :help (concat "Open " value) :active t))))) -(defsubst recentf-menu-bar () +(defun recentf-menu-bar () "Return the keymap of the global menu bar." (lookup-key global-map [menu-bar])) @@ -674,7 +675,7 @@ Return nil if file NAME is not one of the ten more recent." ;;; Predefined menu filters ;; -(defsubst recentf-sort-ascending (l) +(defun recentf-sort-ascending (l) "Sort the list of menu elements L in ascending order. The MENU-ITEM part of each menu element is compared." (sort (copy-sequence l) @@ -683,7 +684,7 @@ The MENU-ITEM part of each menu element is compared." (recentf-menu-element-item e1) (recentf-menu-element-item e2))))) -(defsubst recentf-sort-descending (l) +(defun recentf-sort-descending (l) "Sort the list of menu elements L in descending order. The MENU-ITEM part of each menu element is compared." (sort (copy-sequence l) @@ -692,7 +693,7 @@ The MENU-ITEM part of each menu element is compared." (recentf-menu-element-item e2) (recentf-menu-element-item e1))))) -(defsubst recentf-sort-basenames-ascending (l) +(defun recentf-sort-basenames-ascending (l) "Sort the list of menu elements L in ascending order. Only filenames sans directory are compared." (sort (copy-sequence l) @@ -701,7 +702,7 @@ Only filenames sans directory are compared." (file-name-nondirectory (recentf-menu-element-value e1)) (file-name-nondirectory (recentf-menu-element-value e2)))))) -(defsubst recentf-sort-basenames-descending (l) +(defun recentf-sort-basenames-descending (l) "Sort the list of menu elements L in descending order. Only filenames sans directory are compared." (sort (copy-sequence l) @@ -710,7 +711,7 @@ Only filenames sans directory are compared." (file-name-nondirectory (recentf-menu-element-value e2)) (file-name-nondirectory (recentf-menu-element-value e1)))))) -(defsubst recentf-sort-directories-ascending (l) +(defun recentf-sort-directories-ascending (l) "Sort the list of menu elements L in ascending order. Compares directories then filenames to order the list." (sort (copy-sequence l) @@ -719,7 +720,7 @@ Compares directories then filenames to order the list." (recentf-menu-element-value e1) (recentf-menu-element-value e2))))) -(defsubst recentf-sort-directories-descending (l) +(defun recentf-sort-directories-descending (l) "Sort the list of menu elements L in descending order. Compares directories then filenames to order the list." (sort (copy-sequence l) @@ -756,14 +757,14 @@ When a filename is duplicated, it is appended a sequence number if optional argument NO-DIR is non-nil, or its directory otherwise." (recentf--filter-names l no-dir #'file-name-nondirectory)) -(defsubst recentf-show-basenames-ascending (l) +(defun recentf-show-basenames-ascending (l) "Filter the list of menu elements L to show filenames sans directory. Filenames are sorted in ascending order. This filter combines the `recentf-sort-basenames-ascending' and `recentf-show-basenames' filters." (recentf-show-basenames (recentf-sort-basenames-ascending l))) -(defsubst recentf-show-basenames-descending (l) +(defun recentf-show-basenames-descending (l) "Filter the list of menu elements L to show filenames sans directory. Filenames are sorted in descending order. This filter combines the `recentf-sort-basenames-descending' and commit feb88fa8abe94dbd39ed05dd68008a4eccbf56cd Author: Stefan Kangas Date: Wed Jun 22 13:36:19 2022 +0200 Bind C-c C-c and C-c C-k in recentf-dialog-mode * lisp/recentf.el (recentf-dialog-mode-map): Prefer defvar-keymap. Bind `C-c C-c' and `C-c C-k' to confirm/cancel the dialog. (recentf-cancel-dialog, recentf-edit-list-validate): Add interactive mode tags for 'recentf-dialog-mode'. (recentf-dialog-mode): Mark as non-interactive. (recentf-edit-list): Display key binding. diff --git a/lisp/recentf.el b/lisp/recentf.el index b3bb6482d4..1005d4855f 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -1050,7 +1050,7 @@ That is, remove a non kept file from the recent list." (defun recentf-cancel-dialog (&rest _ignore) "Cancel the current dialog. IGNORE arguments." - (interactive) + (interactive nil recentf-dialog-mode) (kill-buffer (current-buffer)) (message "Dialog canceled")) @@ -1068,19 +1068,20 @@ Go to the beginning of buffer if not found." (error (goto-char (point-min))))) -(defvar recentf-dialog-mode-map - (let ((km (copy-keymap recentf--shortcuts-keymap))) - (set-keymap-parent km widget-keymap) - (define-key km "q" #'recentf-cancel-dialog) - (define-key km "n" #'next-line) - (define-key km "p" #'previous-line) - km) - "Keymap used in recentf dialogs.") +(defvar-keymap recentf-dialog-mode-map + :doc "Keymap used in recentf dialogs." + :parent (make-composed-keymap recentf--shortcuts-keymap widget-keymap) + "q" #'recentf-cancel-dialog + "n" #'next-line + "p" #'previous-line + "C-c C-c" #'recentf-edit-list-validate + "C-c C-k" #'recentf-cancel-dialog) (define-derived-mode recentf-dialog-mode nil "recentf-dialog" "Major mode of recentf dialogs. \\{recentf-dialog-mode-map}" + :interactive nil :syntax-table nil :abbrev-table nil (setq truncate-lines t)) @@ -1117,6 +1118,7 @@ IGNORE other arguments." (defun recentf-edit-list-validate (&rest _ignore) "Process the recent list when the edit list dialog is committed. IGNORE arguments." + (interactive nil recentf-dialog-mode) (if recentf-edit-list (let ((i 0)) (dolist (e recentf-edit-list) @@ -1136,8 +1138,8 @@ IGNORE arguments." (widget-insert (format-message (substitute-command-keys - "Click on OK to delete selected files from the recent list. -Click on Cancel or type \\[recentf-cancel-dialog] to cancel.\n"))) + "Click on \"OK\" or type \\[recentf-edit-list-validate] to delete selected files from the recent list. +Click on \"Cancel\" or type \\[recentf-cancel-dialog] to cancel.\n"))) ;; Insert the list of files as checkboxes (dolist (item recentf-list) (widget-create 'checkbox commit ec1fffdeca9c87a92b8c35545121b4ee3eec3ece Author: Michael Albinus Date: Wed Jun 22 17:47:39 2022 +0200 Fix dnd-tests-open-remote-url on EMBA * test/lisp/dnd-tests.el (dnd-tests-open-remote-url): Check for ftp client. diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index 3ee92286f9..aae9c80273 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -375,6 +375,8 @@ This function only tries to handle strings." ;; Expensive test to make sure opening an FTP URL during ;; drag-and-drop works. :tags '(:expensive-test) + ;; Don't run if there is no ftp client. + (skip-unless (executable-find "ftp")) ;; Don't run this test if the FTP server isn't reachable. (skip-unless (and (fboundp 'network-lookup-address-info) (network-lookup-address-info "ftp.gnu.org"))) commit 47374d44167ce7a20d78c3c544434f389e0d726e Author: Mattias Engdegård Date: Wed Jun 22 15:55:19 2022 +0200 duplicate-line: fix optional argument and add test (bug#46621) The test assumes that the current semantics are intended and desired, which may or may not be true, but it's better than not having any at all. * lisp/misc.el (duplicate-line): Don't crash if called with no argument. * test/lisp/misc-tests.el (misc--duplicate-line): New test. diff --git a/lisp/misc.el b/lisp/misc.el index 3fb30e5372..8a01b51c6d 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -69,6 +69,8 @@ Also see the `duplicate-line' command." Interactively, N is the prefix numeric argument, and defaults to 1. Also see the `copy-from-above-command' command." (interactive "p") + (unless n + (setq n 1)) (let ((line (buffer-substring (line-beginning-position) (line-end-position)))) (save-excursion (forward-line 1) diff --git a/test/lisp/misc-tests.el b/test/lisp/misc-tests.el index 236223ef49..a56feaa049 100644 --- a/test/lisp/misc-tests.el +++ b/test/lisp/misc-tests.el @@ -80,5 +80,21 @@ (backward-to-word 3) (should (equal (point) 1)))) +(ert-deftest misc--duplicate-line () + ;; Duplicate a line (twice). + (with-temp-buffer + (insert "abc\ndefg\nh\n") + (goto-char 7) + (duplicate-line 2) + (should (equal (buffer-string) "abc\ndefg\ndefg\ndefg\nh\n")) + (should (equal (point) 7))) + ;; Duplicate a non-terminated line. + (with-temp-buffer + (insert "abc") + (goto-char 2) + (duplicate-line) + (should (equal (buffer-string) "abc\nabc\n")) + (should (equal (point) 2)))) + (provide 'misc-tests) ;;; misc-tests.el ends here commit 55c2102560751ae05c98fd04120abcf4595d2a57 Author: Richard Hansen Date: Thu Jun 16 15:21:57 2022 -0400 bindat (strz): Null terminate fixed-length strings if there is room * lisp/emacs-lisp/bindat.el (bindat--pack-strz): For fixed-length strz fields, explicitly write a null terminator after the packed string if there is room (bug#56048). * doc/lispref/processes.texi (Bindat Types): Update documentation. * test/lisp/emacs-lisp/bindat-tests.el (bindat-test--str-strz-prealloc): Update tests. diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index b9200aedde..9e0bd98a54 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3509,23 +3509,24 @@ packed; other multibyte strings signal an error. When unpacking a (but excluding) the null byte that terminated the input string. If @var{len} is provided, @code{strz} behaves the same as @code{str}, -but with one difference: when unpacking, the first null byte -encountered in the packed string is interpreted as the terminating -byte, and it and all subsequent bytes are excluded from the result of -the unpacking. +but with a couple of differences: -@quotation Caution -The packed output will not be null-terminated unless one of the -following is true: -@itemize +@itemize @bullet @item -The input string is shorter than @var{len} bytes and either no pre-allocated -string was provided to @code{bindat-pack} or the appropriate byte in -the pre-allocated string was already null. +When packing, a null terminator is written after the packed input +string if the number of characters in the input string is less than +@var{len}. + @item -The input string contains a null byte within the first @var{len} -bytes. +When unpacking, the first null byte encountered in the packed string +is interpreted as the terminating byte, and it and all subsequent +bytes are excluded from the result of the unpacking. @end itemize + +@quotation Caution +The packed output will not be null-terminated unless the input string +is shorter than @var{len} bytes or it contains a null byte within the +first @var{len} bytes. @end quotation @item vec @var{len} [@var{type}] diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 4a642bb9c5..0ecac3d52a 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -443,11 +443,14 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." (defun bindat--pack-strz (len v) (let* ((v (string-to-unibyte v)) (vlen (length v))) + ;; Explicitly write a null terminator (if there's room) in case + ;; the user provided a pre-allocated string to `bindat-pack' that + ;; wasn't already zeroed. + (when (or (null len) (< vlen len)) + (aset bindat-raw (+ bindat-idx vlen) 0)) (if len ;; When len is specified, behave the same as the str type - ;; since we don't actually add the terminating zero anyway - ;; (because we rely on the fact that `bindat-raw' was - ;; presumably initialized with all-zeroes before we started). + ;; (except for the null terminator possibly written above). (bindat--pack-str len v) (dotimes (i vlen) (when (= (aref v i) 0) @@ -456,10 +459,6 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." ;; need to scan the input string looking for a null byte. (error "Null byte encountered in input strz string")) (aset bindat-raw (+ bindat-idx i) (aref v i))) - ;; Explicitly write a null terminator in case the user provided - ;; a pre-allocated string to `bindat-pack' that wasn't already - ;; zeroed. - (aset bindat-raw (+ bindat-idx vlen) 0) (setq bindat-idx (+ bindat-idx vlen 1))))) (defun bindat--pack-bits (len v) diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el index cc223ad14e..0c03c51e2e 100644 --- a/test/lisp/emacs-lisp/bindat-tests.el +++ b/test/lisp/emacs-lisp/bindat-tests.el @@ -172,14 +172,14 @@ ((((x str 2)) ((x . "a"))) . "ax") ((((x str 2)) ((x . "ab"))) . "ab") ((((x str 2)) ((x . "abc"))) . "ab") - ((,(bindat-type strz 1) "") . "xx") - ((,(bindat-type strz 2) "") . "xx") - ((,(bindat-type strz 2) "a") . "ax") + ((,(bindat-type strz 1) "") . "\0x") + ((,(bindat-type strz 2) "") . "\0x") + ((,(bindat-type strz 2) "a") . "a\0") ((,(bindat-type strz 2) "ab") . "ab") ((,(bindat-type strz 2) "abc") . "ab") - ((((x strz 1)) ((x . ""))) . "xx") - ((((x strz 2)) ((x . ""))) . "xx") - ((((x strz 2)) ((x . "a"))) . "ax") + ((((x strz 1)) ((x . ""))) . "\0x") + ((((x strz 2)) ((x . ""))) . "\0x") + ((((x strz 2)) ((x . "a"))) . "a\0") ((((x strz 2)) ((x . "ab"))) . "ab") ((((x strz 2)) ((x . "abc"))) . "ab") ((,(bindat-type strz) "") . "\0x") commit eff42dc0af741cc56c52d7d9577d29fc16f9f665 Author: Richard Hansen Date: Sun May 29 21:23:57 2022 -0400 ; bindat (strz): Move all pack logic to pack function (bug#56048) Motivation/rationale: * Improve code readability. Now `bindat--pack-strz` is used for all `strz` packing, not just variable-length `strz` packing. * Make it easier to change the behavior of fixed-length `strz` packing without also affecting the behavior of `str` packing. (A future commit will modify `strz` to write a null terminator if there is room.) diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 46e2a4901c..4a642bb9c5 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -440,20 +440,27 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." (aset bindat-raw (+ bindat-idx i) (aref v i))) (setq bindat-idx (+ bindat-idx len)))) -(defun bindat--pack-strz (v) +(defun bindat--pack-strz (len v) (let* ((v (string-to-unibyte v)) - (len (length v))) - (dotimes (i len) - (when (= (aref v i) 0) - ;; Alternatively we could pretend that this was the end of - ;; the string and stop packing, but then bindat-length would - ;; need to scan the input string looking for a null byte. - (error "Null byte encountered in input strz string")) - (aset bindat-raw (+ bindat-idx i) (aref v i))) - ;; Explicitly write a null terminator in case the user provided a - ;; pre-allocated string to bindat-pack that wasn't zeroed first. - (aset bindat-raw (+ bindat-idx len) 0) - (setq bindat-idx (+ bindat-idx len 1)))) + (vlen (length v))) + (if len + ;; When len is specified, behave the same as the str type + ;; since we don't actually add the terminating zero anyway + ;; (because we rely on the fact that `bindat-raw' was + ;; presumably initialized with all-zeroes before we started). + (bindat--pack-str len v) + (dotimes (i vlen) + (when (= (aref v i) 0) + ;; Alternatively we could pretend that this was the end of + ;; the string and stop packing, but then bindat-length would + ;; need to scan the input string looking for a null byte. + (error "Null byte encountered in input strz string")) + (aset bindat-raw (+ bindat-idx i) (aref v i))) + ;; Explicitly write a null terminator in case the user provided + ;; a pre-allocated string to `bindat-pack' that wasn't already + ;; zeroed. + (aset bindat-raw (+ bindat-idx vlen) 0) + (setq bindat-idx (+ bindat-idx vlen 1))))) (defun bindat--pack-bits (len v) (let ((bnum (1- (* 8 len))) j m) @@ -482,7 +489,8 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." ('u24r (bindat--pack-u24r v)) ('u32r (bindat--pack-u32r v)) ('bits (bindat--pack-bits len v)) - ((or 'str 'strz) (bindat--pack-str len v)) + ('str (bindat--pack-str len v)) + ('strz (bindat--pack-strz len v)) ('vec (let ((l (length v)) (vlen 1)) (if (consp vectype) @@ -699,18 +707,7 @@ is the name of a variable that will hold the value we need to pack.") ((numberp len) len) ;; General expression support. (t `(or ,len (1+ (length ,val))))))) - (`(pack . ,args) - ;; When len is specified, behave the same as the str type since we don't - ;; actually add the terminating zero anyway (because we rely on the fact - ;; that `bindat-raw' was presumably initialized with all-zeroes before we - ;; started). - (cond ; Same optimizations as 'length above. - ((null len) `(bindat--pack-strz . ,args)) - ((numberp len) `(bindat--pack-str ,len . ,args)) - (t (macroexp-let2 nil len len - `(if ,len - (bindat--pack-str ,len . ,args) - (bindat--pack-strz . ,args)))))))) + (`(pack . ,args) `(bindat--pack-strz ,len . ,args)))) (cl-defmethod bindat--type (op (_ (eql 'bits)) len) (bindat--pcase op commit 5f1bd872478927ad4bc635502e74628d39885286 Author: Gerd Moellmann Date: Tue Jun 21 15:49:44 2022 +0200 Prevent GC of window referenced from EmacsScroller * src/nsterm.m (EmacsScroller.mark, mark_nsterm): New functions. * src/nsterm.h (EmacsScroller.mark, mark_nsterm): Declare. * src/alloc.c (garbage_collect) [MAVE_NS]: Call mark_nsterm. (Bug#56095) diff --git a/src/alloc.c b/src/alloc.c index 55e18ecd77..f115a3ceba 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -6204,6 +6204,10 @@ garbage_collect (void) mark_xterm (); #endif +#ifdef HAVE_NS + mark_nsterm (); +#endif + /* Everything is now marked, except for the data in font caches, undo lists, and finalizers. The first two are compacted by removing an items which aren't reachable otherwise. */ diff --git a/src/nsterm.h b/src/nsterm.h index c4fdc7054f..7a097b3248 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -724,6 +724,7 @@ enum ns_return_frame_mode int em_whole; } +- (void) mark; - (instancetype) initFrame: (NSRect )r window: (Lisp_Object)win; - (void)setFrame: (NSRect)r; @@ -1373,4 +1374,7 @@ enum NSWindowTabbingMode #define NSBezelStyleRounded NSRoundedBezelStyle #define NSButtonTypeMomentaryPushIn NSMomentaryPushInButton #endif + +extern void mark_nsterm (void); + #endif /* HAVE_NS */ diff --git a/src/nsterm.m b/src/nsterm.m index 891d52ea3f..ae44f80845 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -9924,6 +9924,16 @@ -(bool)judge return ret; } +- (void) mark +{ + if (window) + { + Lisp_Object win; + XSETWINDOW (win, window); + mark_object (win); + } +} + - (void)resetCursorRects { @@ -10665,6 +10675,26 @@ Convert an X font name (XLFD) to an NS font name. return ret; } +void +mark_nsterm (void) +{ + NSTRACE ("mark_nsterm"); + Lisp_Object tail, frame; + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_NS_P (f)) + { + NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews]; + for (int i = [subviews count] - 1; i >= 0; --i) + { + id scroller = [subviews objectAtIndex: i]; + if ([scroller isKindOfClass: [EmacsScroller class]]) + [scroller mark]; + } + } + } +} void syms_of_nsterm (void) commit a3f294b37f81ae3d5438ff32173726bddaa79496 Author: Eli Zaretskii Date: Wed Jun 22 16:46:25 2022 +0300 Improve last change in autotype.texi * doc/misc/autotype.texi (Autoinserting): Fix wording. Suggested by Richard Stallman . diff --git a/doc/misc/autotype.texi b/doc/misc/autotype.texi index a880642ac3..b005c9c34f 100644 --- a/doc/misc/autotype.texi +++ b/doc/misc/autotype.texi @@ -274,13 +274,13 @@ empty file is visited. This is accomplished by putting @vindex auto-insert-alist What gets inserted, if anything, is determined by the variable -@code{auto-insert-alist}. The @sc{car}s of this list are each either -a mode name, making an element applicable when a buffer is in that -mode, or they can be a string, which is a regexp matched against the -buffer's file name. In that way different kinds of files that have -the same mode in Emacs can be distinguished. The @sc{car}s may also -be cons cells consisting of mode name or regexp as above and an -additional descriptive string. +@code{auto-insert-alist}. The @sc{car} of each element of this list +is either a mode name, making the element applicable when a buffer is +in that mode, or a string, which is a regexp matched against a +buffer's file name (the latter allows to distinguish between different +kinds of files that have the same mode in Emacs). The @sc{car} of an +element may also be a cons cell, consisting of mode name or regexp, as +above, and an additional descriptive string. When a matching element is found, the @sc{cdr} says what to do. It may be a string, which is a file name, whose contents are to be inserted, if commit 38ae6cf3ce1a84f46739a788b8a2a832f8d08b2a Author: Stefan Kangas Date: Wed Jun 22 12:42:01 2022 +0200 Prefer Emacs mouse button event names to XEmacs names * lisp/mwheel.el: * lisp/vc/ediff-mult.el (ediff-meta-buffer-verbose-message) (ediff-draw-dir-diffs, ediff-redraw-registry-buffer): Prefer Emacs mouse button event names to XEmacs names. diff --git a/lisp/bs.el b/lisp/bs.el index 3b0c800866..00d8326115 100644 --- a/lisp/bs.el +++ b/lisp/bs.el @@ -1,6 +1,7 @@ ;;; bs.el --- menu for selecting and displaying buffers -*- lexical-binding: t -*- ;; Copyright (C) 1998-2022 Free Software Foundation, Inc. + ;; Author: Olaf Sylvester ;; Maintainer: emacs-devel@gnu.org ;; Keywords: convenience diff --git a/lisp/mwheel.el b/lisp/mwheel.el index 99ba9cb687..9a92d42cc0 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -1,6 +1,7 @@ ;;; mwheel.el --- Mouse wheel support -*- lexical-binding:t -*- -;; Copyright (C) 1998, 2000-2022 Free Software Foundation, Inc. +;; Copyright (C) 1998-2022 Free Software Foundation, Inc. + ;; Keywords: mouse ;; Package: emacs @@ -22,7 +23,7 @@ ;;; Commentary: ;; This enables the use of the mouse wheel (or scroll wheel) in Emacs. -;; Under X11/X.Org, the wheel events are sent as button4/button5 +;; Under X11/X.Org, the wheel events are sent as mouse-4/mouse-5 ;; events. ;; Mouse wheel support is already enabled by default on most graphical @@ -32,7 +33,7 @@ ;; Implementation note: ;; -;; I for one would prefer some way of converting the button4/button5 +;; I for one would prefer some way of converting the mouse-4/mouse-5 ;; events into different event types, like 'mwheel-up' or ;; 'mwheel-down', but I cannot find a way to do this very easily (or ;; portably), so for now I just live with it. diff --git a/lisp/vc/ediff-mult.el b/lisp/vc/ediff-mult.el index 4871690111..b7c349fc1c 100644 --- a/lisp/vc/ediff-mult.el +++ b/lisp/vc/ediff-mult.el @@ -128,7 +128,7 @@ (defconst ediff-meta-buffer-verbose-message "Ediff Session Group Panel: %s Useful commands (type ? to hide them and free up screen): - button2, v, or RET over session record: start that Ediff session + mouse-2, v, or RET over session record: start that Ediff session M:\tin sessions invoked from here, brings back this group panel R:\tdisplay the registry of active Ediff sessions h:\tmark session for hiding (toggle) @@ -1236,7 +1236,7 @@ behavior." (insert "\t\t*** Directory Differences ***\n") (insert " Useful commands: - C,button2: over file name -- copy this file to directory that doesn't have it + C,mouse-2: over file name -- copy this file to directory that doesn't have it q: hide this buffer n,SPC: next line p,DEL: previous line\n\n") @@ -1429,7 +1429,7 @@ Useful commands: This is a registry of all active Ediff sessions. Useful commands: - button2, `v', RET over a session record: switch to that session + mouse-2, `v', RET over a session record: switch to that session M over a session record: display the associated session group R in any Ediff session: display session registry n,SPC: next session commit cc06be904c5f1da950312c9c3640da42700a1f36 Author: Stefan Kangas Date: Wed Jun 22 12:34:05 2022 +0200 * lisp/bs.el (bs-mode-map): Prefer defvar-keymap. diff --git a/lisp/bs.el b/lisp/bs.el index cff19c81cb..3b0c800866 100644 --- a/lisp/bs.el +++ b/lisp/bs.el @@ -434,58 +434,61 @@ Used internally, only.") (defvar bs--marked-buffers nil "Currently marked buffers in Buffer Selection Menu.") -(defvar bs-mode-map - (let ((map (make-sparse-keymap))) - (define-key map " " 'bs-select) - (define-key map "f" 'bs-select) - (define-key map "v" 'bs-view) - (define-key map "!" 'bs-select-in-one-window) - (define-key map [mouse-2] 'bs-mouse-select) - (define-key map "F" 'bs-select-other-frame) - (let ((key ?1)) - (while (<= key ?9) - (define-key map (char-to-string key) 'digit-argument) - (setq key (1+ key)))) - (define-key map "-" 'negative-argument) - (define-key map "\e-" 'negative-argument) - (define-key map "o" 'bs-select-other-window) - (define-key map "\C-o" 'bs-tmp-select-other-window) - (define-key map [mouse-3] 'bs-mouse-select-other-frame) - (define-key map [up] 'bs-up) - (define-key map "n" 'bs-down) - (define-key map "p" 'bs-up) - (define-key map [down] 'bs-down) - (define-key map "\C-m" 'bs-select) - (define-key map "b" 'bs-bury-buffer) - (define-key map "s" 'bs-save) - (define-key map "S" 'bs-show-sorted) - (define-key map "a" 'bs-toggle-show-all) - (define-key map "d" 'bs-delete) - (define-key map "\C-d" 'bs-delete-backward) - (define-key map "k" 'bs-delete) - (define-key map "g" 'bs-refresh) - (define-key map "C" 'bs-set-configuration-and-refresh) - (define-key map "c" 'bs-select-next-configuration) - (define-key map "q" 'bs-kill) - ;; (define-key map "z" 'bs-kill) - (define-key map "\C-c\C-c" 'bs-kill) - (define-key map "\C-g" 'bs-abort) - (define-key map "\C-]" 'bs-abort) - (define-key map "%" 'bs-toggle-readonly) - (define-key map "~" 'bs-clear-modified) - (define-key map "M" 'bs-toggle-current-to-show) - (define-key map "+" 'bs-set-current-buffer-to-show-always) - ;;(define-key map "-" 'bs-set-current-buffer-to-show-never) - (define-key map "t" 'bs-visit-tags-table) - (define-key map "m" 'bs-mark-current) - (define-key map "u" 'bs-unmark-current) - (define-key map "U" 'bs-unmark-all) - (define-key map "\177" 'bs-unmark-previous) - (define-key map ">" 'scroll-right) - (define-key map "<" 'scroll-left) - (define-key map "?" 'bs-help) - map) - "Keymap of `bs-mode'.") +(defvar-keymap bs-mode-map + :doc "Keymap of `bs-mode'." + "SPC" #'bs-select + "f" #'bs-select + "v" #'bs-view + "!" #'bs-select-in-one-window + "F" #'bs-select-other-frame + "1" #'digit-argument + "2" #'digit-argument + "3" #'digit-argument + "4" #'digit-argument + "5" #'digit-argument + "6" #'digit-argument + "7" #'digit-argument + "8" #'digit-argument + "9" #'digit-argument + "-" #'negative-argument + "ESC -" #'negative-argument + "o" #'bs-select-other-window + "C-o" #'bs-tmp-select-other-window + "" #'bs-up + "n" #'bs-down + "p" #'bs-up + "" #'bs-down + "C-m" #'bs-select + "b" #'bs-bury-buffer + "s" #'bs-save + "S" #'bs-show-sorted + "a" #'bs-toggle-show-all + "d" #'bs-delete + "C-d" #'bs-delete-backward + "k" #'bs-delete + "g" #'bs-refresh + "C" #'bs-set-configuration-and-refresh + "c" #'bs-select-next-configuration + "q" #'bs-kill + ;; "z" #'bs-kill + "C-c C-c" #'bs-kill + "C-g" #'bs-abort + "C-]" #'bs-abort + "%" #'bs-toggle-readonly + "~" #'bs-clear-modified + "M" #'bs-toggle-current-to-show + "+" #'bs-set-current-buffer-to-show-always + ;; "-" #'bs-set-current-buffer-to-show-never + "t" #'bs-visit-tags-table + "m" #'bs-mark-current + "u" #'bs-unmark-current + "U" #'bs-unmark-all + "DEL" #'bs-unmark-previous + ">" #'scroll-right + "<" #'scroll-left + "?" #'bs-help + "" #'bs-mouse-select + "" #'bs-mouse-select-other-frame) ;; ---------------------------------------------------------------------- ;; Functions commit 18d412a5138f21be77f36e4f8036971d576ef25e Author: Po Lu Date: Wed Jun 22 18:37:32 2022 +0800 Fix non-system-malloc build * src/xterm.c (x_gc_free_ext_data_private): New function. (x_gc_get_ext_data): Set it as the private data free function. diff --git a/src/xterm.c b/src/xterm.c index 9e481c39af..cfe329ab0f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4888,6 +4888,14 @@ x_update_opaque_region (struct frame *f, XEvent *configure) #if defined USE_CAIRO || defined HAVE_XRENDER +static int +x_gc_free_ext_data_private (XExtData *extension) +{ + xfree (extension->private_data); + + return 0; +} + static struct x_gc_ext_data * x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p) { @@ -4907,6 +4915,7 @@ x_gc_get_ext_data (struct frame *f, GC gc, int create_if_not_found_p) ext_data = xzalloc (sizeof (*ext_data)); ext_data->number = dpyinfo->ext_codes->extension; ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data)); + ext_data->free_private = x_gc_free_ext_data_private; XAddToExtensionList (head, ext_data); } } commit f3c78c6ea7045734fa5e524d683d6cf6435b90bb Author: Stefan Kangas Date: Wed Jun 22 12:14:06 2022 +0200 Do interactive mode tagging in edmacro.el * lisp/edmacro.el (edmacro-finish-edit, edmacro-insert-key): Add interactive mode tag for edmacro-mode. diff --git a/lisp/edmacro.el b/lisp/edmacro.el index 2f5a8c137e..bdc50c5885 100644 --- a/lisp/edmacro.el +++ b/lisp/edmacro.el @@ -255,7 +255,7 @@ or nil, use a compact 80-column format." ;;; Commands for *Edit Macro* buffer. (defun edmacro-finish-edit () - (interactive) + (interactive nil edmacro-mode) (unless (eq major-mode 'edmacro-mode) (error "This command is valid only in buffers created by `edit-kbd-macro'")) @@ -366,7 +366,7 @@ or nil, use a compact 80-column format." (defun edmacro-insert-key (key) "Insert the written name of a KEY in the buffer." - (interactive "kKey to insert: ") + (interactive "kKey to insert: " edmacro-mode) (if (bolp) (insert (edmacro-format-keys key t) "\n") (insert (edmacro-format-keys key) " "))) commit ec9228eb81c0a89b18480dfff18cc9afdc3d0884 Author: Stefan Kangas Date: Wed Jun 22 11:47:30 2022 +0200 Use short file names by default in recentf menu * lisp/recentf.el (recentf-menu-filter): Set the default to 'recentf-show-abbreviated' to get short file names. (Bug#56123) diff --git a/etc/NEWS b/etc/NEWS index 88ba721384..40658559d7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1856,9 +1856,9 @@ 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 'recentf-mode' menu can now use shortened filenames. -Set the user option 'recentf-menu-filter' to -'recentf-show-abbreviated' to enable it. +*** The 'recentf-mode' menu now uses shortened filenames by default. +They are shortened with 'abbreviate-file-name'. Customize the user +option 'recentf-menu-filter' to nil to get unabbreviated file names. --- ** The autoarg.el library is now marked obsolete. diff --git a/lisp/recentf.el b/lisp/recentf.el index 09843a8956..b3bb6482d4 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -170,7 +170,7 @@ The default is to call `find-file' to edit the selected file." :group 'recentf :type 'integer) -(defcustom recentf-menu-filter nil +(defcustom recentf-menu-filter #'recentf-show-abbreviated "Function used to filter files displayed in the recentf menu. A nil value means no filter. The following functions are predefined: @@ -225,7 +225,8 @@ elements (see `recentf-make-menu-element' for menu element form)." (function-item recentf-arrange-by-mode) (function-item recentf-arrange-by-dir) (function-item recentf-filter-changer) - function)) + function) + :version "29.1") (defcustom recentf-menu-open-all-flag nil "Non-nil means to show an \"All...\" item in the menu. commit 5b1109394ca8f9d98b6b9cd0f7ef01c179a89351 Author: Stefan Kangas Date: Wed Jun 22 10:03:16 2022 +0200 ; * lisp/edmacro.el: Minor doc fixes. diff --git a/lisp/edmacro.el b/lisp/edmacro.el index c681f90141..2f5a8c137e 100644 --- a/lisp/edmacro.el +++ b/lisp/edmacro.el @@ -111,7 +111,7 @@ Default nil means to write characters above \\177 in octal notation." (defun edit-kbd-macro (keys &optional prefix finish-hook store-hook) "Edit a keyboard macro. At the prompt, type any key sequence which is bound to a keyboard macro. -Or, type `\\[kmacro-end-and-call-macro]' or RET to edit the last +Or, type `\\[kmacro-end-and-call-macro]' or \\`RET' to edit the last keyboard macro, `\\[view-lossage]' to edit the last 300 keystrokes as a keyboard macro, or `\\[execute-extended-command]' to edit a macro by its command name. @@ -374,7 +374,7 @@ or nil, use a compact 80-column format." (defun edmacro-mode () "\\Keyboard Macro Editing mode. Press \ \\[edmacro-finish-edit] to save and exit. -To abort the edit, just kill this buffer with \\[kill-buffer] RET. +To abort the edit, just kill this buffer with \\[kill-buffer] \\`RET'. Press \\[edmacro-insert-key] to insert the name of any key by typing the key. commit 0301b295bb89f63689c892665af0a57d23a27809 Author: Sean Whitton Date: Wed Jun 22 06:23:24 2022 +0200 Don't drop existing escape char in eshell * lisp/eshell/em-term.el (eshell-exec-visual): Don't drop existing escape char. diff --git a/lisp/eshell/em-term.el b/lisp/eshell/em-term.el index d150c07b03..9000e8c878 100644 --- a/lisp/eshell/em-term.el +++ b/lisp/eshell/em-term.el @@ -186,8 +186,10 @@ allowed." (set-process-sentinel proc #'eshell-term-sentinel) (error "Failed to invoke visual command"))) (term-char-mode) - (if eshell-escape-control-x - (term-set-escape-char ?\C-x)))) + (when eshell-escape-control-x + ;; Don't drop existing escape char. + (let (term-escape-char) + (term-set-escape-char ?\C-x))))) nil) ;; Process sentinels receive two arguments. commit 582356c45f86ef0e27e2e0e4c171b0c670148043 Author: Po Lu Date: Wed Jun 22 12:23:00 2022 +0800 * src/xterm.c (x_scroll_bar_note_movement): Fix no-toolkit build. diff --git a/src/xterm.c b/src/xterm.c index f97452a2e5..9e481c39af 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15078,7 +15078,7 @@ x_scroll_bar_note_movement (struct scroll_bar *bar, struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); dpyinfo->last_mouse_movement_time = event->time; - dpyinfo->last_mouse_movement_send_event = event->send_event; + dpyinfo->last_mouse_movement_time_send_event = event->send_event; dpyinfo->last_mouse_scroll_bar = bar; f->mouse_moved = true; commit fa6d9c1e848972e80b75d6c079e73ec9c398a93d Author: Lars Ingebrigtsen Date: Wed Jun 22 05:25:48 2022 +0200 Mention the new Tetris user option diff --git a/etc/NEWS b/etc/NEWS index cb59d166f7..88ba721384 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -941,6 +941,13 @@ so automatically. * Changes in Specialized Modes and Packages in Emacs 29.1 +** Games + +--- +*** New user option 'tetris-allow-repetitions'. +This controls how randomness is implemented (whether to use pure +randomness as before or whether to use a bag). + ** Battery +++ commit ff20b0192c6f20b44c2f58f9a46c9061f354adf0 Author: Po Lu Date: Wed Jun 22 10:02:09 2022 +0800 Port x-selection-timeout to PGTK * src/pgtkselect.c (pgtk_own_selection): Fix comment. (wait_for_property_change, pgtk_get_foreign_selection): Respect selection timeout. (syms_of_pgtkselect): New variable `pgtk-selection-timeout'. diff --git a/src/pgtkselect.c b/src/pgtkselect.c index a0168c9fad..122b5d8c07 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -154,8 +154,8 @@ pgtk_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, if (timestamp == GDK_CURRENT_TIME) timestamp = dpyinfo->last_user_time; - /* Assert ownership over the selection. Ideally we would use the - GDK selection API for this as well, but it just doesn't work on + /* Assert ownership over the selection. Ideally we would use only + the GDK selection API for this, but it just doesn't work on Wayland. */ if (!gdk_selection_owner_set_for_display (dpyinfo->display, @@ -911,7 +911,7 @@ wait_for_property_change (struct prop_location *location) property_change_reply, because property_change_reply_object says so. */ if (! location->arrived) { - intmax_t timeout = max (0, 5000); + intmax_t timeout = max (0, pgtk_selection_timeout); intmax_t secs = timeout / 1000; int nsecs = (timeout % 1000) * 1000000; @@ -1027,7 +1027,7 @@ pgtk_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_typ record_unwind_protect_ptr (pgtk_cancel_atimer, delayed_message); /* This allows quits. Also, don't wait forever. */ - intmax_t timeout = max (0, 5000); + intmax_t timeout = max (0, pgtk_selection_timeout); intmax_t secs = timeout / 1000; int nsecs = (timeout % 1000) * 1000000; @@ -1835,12 +1835,11 @@ This hook doesn't let you change the behavior of Emacs's selection replies, it merely informs you that they have happened. */); Vpgtk_sent_selection_hooks = Qnil; - DEFVAR_BOOL ("pgtk-enable-selection-on-multi-display", pgtk_enable_selection_on_multi_display, - doc: /* Enable selections when connected to multiple displays. -This may cause crashes due to a GTK bug, which assumes that clients -will connect to a single display. It might also cause selections to -not arrive at the correct display. */); - pgtk_enable_selection_on_multi_display = false; + DEFVAR_INT ("pgtk-selection-timeout", pgtk_selection_timeout, + doc: /* Number of milliseconds to wait for a selection reply. +If the selection owner doesn't reply in this time, we give up. +A value of 0 means wait as long as necessary. */); + pgtk_selection_timeout = 0; DEFVAR_LISP ("pgtk-selection-alias-alist", Vpgtk_selection_alias_alist, doc: /* List of selections to alias to another. commit d5a3fbe7c8b320cae26458ce353a5d933ded7bb9 Author: Po Lu Date: Wed Jun 22 09:49:16 2022 +0800 Fix setting user time for mouse movement events * src/xterm.c (x_note_mouse_movement, XTmouse_position) (x_scroll_bar_note_movement, handle_one_xevent): Record whether or not mouse movement was send_event before using the mouse movement time. * src/xterm.h (struct x_display_info): New field `last_mouse_movement_time_send_event'. diff --git a/src/xterm.c b/src/xterm.c index ee78da085e..f97452a2e5 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -12335,10 +12335,11 @@ x_construct_mouse_click (struct input_event *result, The XMotionEvent structure passed as EVENT might not come from the X server, and instead be artificially constructed from input extension events. In these special events, the only fields that - are initialized are `time', `window', and `x' and `y'. This - function should not access any other fields in EVENT without also - initializing the corresponding fields in `ev' under the XI_Motion, - XI_Enter and XI_Leave labels inside `handle_one_xevent'. */ + are initialized are `time', `window', `send_event', `x' and `y'. + This function should not access any other fields in EVENT without + also initializing the corresponding fields in `ev' under the + XI_Motion, XI_Enter and XI_Leave labels inside + `handle_one_xevent'. */ static bool x_note_mouse_movement (struct frame *frame, const XMotionEvent *event, @@ -12352,6 +12353,7 @@ x_note_mouse_movement (struct frame *frame, const XMotionEvent *event, dpyinfo = FRAME_DISPLAY_INFO (frame); dpyinfo->last_mouse_movement_time = event->time; + dpyinfo->last_mouse_movement_time_send_event = event->send_event; dpyinfo->last_mouse_motion_frame = frame; dpyinfo->last_mouse_motion_x = event->x; dpyinfo->last_mouse_motion_y = event->y; @@ -12667,7 +12669,8 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, && (dpyinfo->last_user_time < dpyinfo->last_mouse_movement_time)) x_display_set_last_user_time (dpyinfo, - dpyinfo->last_mouse_movement_time, false); + dpyinfo->last_mouse_movement_time, + dpyinfo->last_mouse_movement_time_send_event); if ((!f1 || FRAME_TOOLTIP_P (f1)) && (EQ (track_mouse, Qdropping) @@ -15075,6 +15078,7 @@ x_scroll_bar_note_movement (struct scroll_bar *bar, struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); dpyinfo->last_mouse_movement_time = event->time; + dpyinfo->last_mouse_movement_send_event = event->send_event; dpyinfo->last_mouse_scroll_bar = bar; f->mouse_moved = true; @@ -19168,10 +19172,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, any = x_top_window_to_frame (dpyinfo, enter->event); source = xi_device_from_id (dpyinfo, enter->sourceid); + ev.x = lrint (enter->event_x); ev.y = lrint (enter->event_y); ev.window = enter->event; ev.time = enter->time; + ev.send_event = enter->send_event; x_display_set_last_user_time (dpyinfo, enter->time, enter->send_event); @@ -19262,6 +19268,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, ev.y = lrint (leave->event_y); ev.window = leave->event; ev.time = leave->time; + ev.send_event = leave->send_event; #endif any = x_top_window_to_frame (dpyinfo, leave->event); @@ -19680,6 +19687,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, ev.y = lrint (xev->event_y); ev.window = xev->event; ev.time = xev->time; + ev.send_event = xev->send_event; #ifdef USE_MOTIF use_copy = true; diff --git a/src/xterm.h b/src/xterm.h index 3d243f3eab..f136b6b97f 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -515,6 +515,9 @@ struct x_display_info received, and return that in hopes that it's somewhat accurate. */ Time last_mouse_movement_time; + /* Whether or not the last mouse motion was synthetic. */ + bool last_mouse_movement_time_send_event; + /* The gray pixmap. */ Pixmap gray; commit 6f5f2ebfb4fe2652152bc0f69d6a1ffde3ec5c87 Author: Sam Steingold Date: Tue Jun 21 18:41:13 2022 -0400 A trivial optimization and a formatting fix * lisp/subr.el (internal--compiler-macro-cXXr): Re-use `head' for `n'. Fix indentation and line length. diff --git a/lisp/subr.el b/lisp/subr.el index d14efccd82..04eec977bb 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -540,12 +540,12 @@ i.e., subtract 2 * `most-negative-fixnum' from VALUE before shifting it." ;; you may want to amend the other, too. (defun internal--compiler-macro-cXXr (form x) (let* ((head (car form)) - (n (symbol-name (car form))) + (n (symbol-name head)) (i (- (length n) 2))) (if (not (string-match "c[ad]+r\\'" n)) (if (and (fboundp head) (symbolp (symbol-function head))) - (internal--compiler-macro-cXXr (cons (symbol-function head) (cdr form)) - x) + (internal--compiler-macro-cXXr + (cons (symbol-function head) (cdr form)) x) (error "Compiler macro for cXXr applied to non-cXXr form")) (while (> i (match-beginning 0)) (setq x (list (if (eq (aref n i) ?a) 'car 'cdr) x)) commit 5e40c5a3beaccdea956abf9d0be0631cb7d2e1d2 Merge: de30e8c0de f3acc09377 Author: Tassilo Horn Date: Tue Jun 21 21:53:57 2022 +0200 Merge from origin/emacs-28 f3acc09377 ; Revert "Use file-in-directory-p instead of obsolete dire... 5082d74cfd ; * lisp/recentf.el: Fix typo. 3f66e2a903 * lisp/repeat.el (repeat-mode): Fix message format. 137539c125 Clarify autotype.texi text slightly commit de30e8c0decf6b76beef332f19d3745ec162fc5b Author: Lars Ingebrigtsen Date: Tue Jun 21 21:52:11 2022 +0200 Fix logic in previous Tetris change * lisp/play/tetris.el (tetris-new-shape): Fix logic in previous change. diff --git a/lisp/play/tetris.el b/lisp/play/tetris.el index af1004e081..d9bc0dd020 100644 --- a/lisp/play/tetris.el +++ b/lisp/play/tetris.el @@ -364,8 +364,8 @@ each one of its four blocks.") (setq tetris-shape tetris-next-shape) (setq tetris-rot 0) (setq tetris-next-shape (if tetris-allow-repetitions - (tetris--seven-bag) - (random 7))) + (random 7) + (tetris--seven-bag))) (setq tetris-pos-x (/ (- tetris-width (tetris-shape-width)) 2)) (setq tetris-pos-y 0) (if (tetris-test-shape) commit ca6c8fc72c66c7ed997801e055e5fb25374d69b5 Author: Timothee Denizou Date: Tue Jun 21 21:50:15 2022 +0200 Allow different randomization of shapes in Tetris * lisp/play/tetris.el (tetris-allow-repetitions): New user option. (tetris--shuffle, tetris--seven-bag): New functions. (tetris-new-shape): Use the option. * Added 7 bag randomizer for tetris A piece is selected from the bag and removed each time we want a piece When the bag is empty, refill the bag with the seven piece and shuffle it Copyright-paperwork-exempt: yes diff --git a/lisp/play/tetris.el b/lisp/play/tetris.el index 8ce2453c75..af1004e081 100644 --- a/lisp/play/tetris.el +++ b/lisp/play/tetris.el @@ -117,6 +117,13 @@ If the return value is a number, it is used as the timer period." "Y position of top left of playing area." :type 'number) +(defcustom tetris-allow-repetitions t + "If non-nil, use a random selection for each shape. +If nil, put the shapes into a bag and select without putting +back (until empty, when the bag is repopulated." + :type 'boolean + :version "29.1") + (defvar tetris-next-x (+ (* 2 tetris-top-left-x) tetris-width) "X position of next shape.") @@ -233,6 +240,7 @@ each one of its four blocks.") (defvar-local tetris-pos-x 0) (defvar-local tetris-pos-y 0) (defvar-local tetris-paused nil) +(defvar-local tetris--bag nil) ;; ;;;;;;;;;;;;; keymaps ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -341,10 +349,23 @@ each one of its four blocks.") (let ((period (tetris-get-tick-period))) (if period (gamegrid-set-timer period)))) +(defun tetris--shuffle (sequence) + (cl-loop for i from (length sequence) downto 2 + do (cl-rotatef (elt sequence (random i)) + (elt sequence (1- i)))) + sequence) + +(defun tetris--seven-bag () + (when (not tetris--bag) + (setq tetris--bag (tetris--shuffle (list 0 1 2 3 4 5 6)))) + (pop tetris--bag)) + (defun tetris-new-shape () (setq tetris-shape tetris-next-shape) (setq tetris-rot 0) - (setq tetris-next-shape (random 7)) + (setq tetris-next-shape (if tetris-allow-repetitions + (tetris--seven-bag) + (random 7))) (setq tetris-pos-x (/ (- tetris-width (tetris-shape-width)) 2)) (setq tetris-pos-y 0) (if (tetris-test-shape) commit f3acc09377f98ae18653eb01c11c57b6449c83af Author: Tassilo Horn Date: Tue Jun 21 21:21:12 2022 +0200 ; Revert "Use file-in-directory-p instead of obsolete dired-in-this-tree-p" Fixes bug#56126. This reverts commit b425966b072792b7b22b845b5f2e39ff4f60b5ab. diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index d47bcf0427..b62e94fa77 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -1868,7 +1868,7 @@ unless OK-IF-ALREADY-EXISTS is non-nil." (while blist (with-current-buffer (car blist) (if (and buffer-file-name - (dired-in-this-tree-p buffer-file-name expanded-from-dir)) + (dired-in-this-tree-p buffer-file-name expanded-from-dir)) (let ((modflag (buffer-modified-p)) (to-file (replace-regexp-in-string (concat "^" (regexp-quote from-dir)) @@ -2727,7 +2727,7 @@ This function takes some pains to conform to `ls -lR' output." (setq switches (string-replace "R" "" switches)) (dolist (cur-ass dired-subdir-alist) (let ((cur-dir (car cur-ass))) - (and (file-in-directory-p cur-dir dirname) + (and (dired-in-this-tree-p cur-dir dirname) (let ((cur-cons (assoc-string cur-dir dired-switches-alist))) (if cur-cons (setcdr cur-cons switches) @@ -2739,7 +2739,7 @@ This function takes some pains to conform to `ls -lR' output." (defun dired-insert-subdir-validate (dirname &optional switches) ;; Check that it is valid to insert DIRNAME with SWITCHES. ;; Signal an error if invalid (e.g. user typed `i' on `..'). - (or (file-in-directory-p dirname (expand-file-name default-directory)) + (or (dired-in-this-tree-p dirname (expand-file-name default-directory)) (error "%s: Not in this directory tree" dirname)) (let ((real-switches (or switches dired-subdir-switches))) (when real-switches commit 3833ce16afe930a57554667afc16b20ce258983d Author: Lars Ingebrigtsen Date: Tue Jun 21 20:51:33 2022 +0200 Fix shr--set-target-ids test for empty buffer * lisp/net/shr.el (shr--set-target-ids): Fix the check for an empty buffer (which may be narrowed). diff --git a/lisp/net/shr.el b/lisp/net/shr.el index b269607e32..0645f4721a 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -399,7 +399,7 @@ DOM should be a parse tree as generated by (defun shr--set-target-ids (ids) ;; If the buffer is empty, there's no point in setting targets. - (unless (zerop (buffer-size)) + (unless (zerop (- (point-max) (point-min))) ;; We may have several targets in the same place (if you have ;; several things after one another). So group ;; them by position. commit 406fd979218321d887c4ca550bcc94f20f6c1713 Author: Michael Heerdegen Date: Sat Apr 2 00:56:09 2022 +0200 Fix autoload generation of iter-defun forms This fixes Bug#54648. * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--make-autoload): Add `iter-defun' and `cl-iter-defun' to the list of "complex cases" that are macro-expanded and recursed on. diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index a686de406a..7545ba1e5e 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -174,7 +174,7 @@ expression, in which case we want to handle forms differently." define-globalized-minor-mode defun defmacro easy-mmode-define-minor-mode define-minor-mode define-inline cl-defun cl-defmacro cl-defgeneric - cl-defstruct pcase-defmacro)) + cl-defstruct pcase-defmacro iter-defun cl-iter-defun)) (macrop car) (setq expand (let ((load-true-file-name file) (load-file-name file)) commit dbbf38d43f1f49a38efd260bda655e0b3cd2b6d5 Author: Philipp Stephani Date: Tue Jun 21 19:10:14 2022 +0200 Document and test 'no-byte-compile' behavior. * lisp/emacs-lisp/bytecomp.el (byte-compile-file): Document behavior if 'no-byte-compile' is set. * test/lisp/emacs-lisp/bytecomp-tests.el (byte-compile-file/no-byte-compile): New unit test. * test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el: New test file. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 04c107a7cf..4fd65bb5d5 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -2089,6 +2089,9 @@ If compilation is needed, this functions returns the result of The output file's name is generated by passing FILENAME to the function `byte-compile-dest-file' (which see). The value is non-nil if there were no errors, nil if errors. +If the file sets the file variable `no-byte-compile', it is not +compiled, any existing output file is removed, and the return +value is `no-byte-compile'. See also `emacs-lisp-byte-compile-and-load'." (declare (advertised-calling-convention (filename) "28.1")) diff --git a/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el b/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el new file mode 100644 index 0000000000..00ad194750 --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/no-byte-compile.el @@ -0,0 +1 @@ +;; -*- no-byte-compile: t; -*- diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index fbc00b30c5..9c5bef09a3 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -1642,6 +1642,13 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \ (setq actual (nreverse actual)) (should (equal actual expected))))))) +(ert-deftest byte-compile-file/no-byte-compile () + (let* ((src-file (ert-resource-file "no-byte-compile.el")) + (dest-file (make-temp-file "bytecomp-tests-" nil ".elc")) + (byte-compile-dest-file-function (lambda (_) dest-file))) + (should (eq (byte-compile-file src-file) 'no-byte-compile)) + (should-not (file-exists-p dest-file)))) + ;; Local Variables: ;; no-byte-compile: t commit 16d48cf8a0153917d5047b557860668acb461e15 Author: Lars Ingebrigtsen Date: Tue Jun 21 19:08:16 2022 +0200 Fix too-long ediff defface doc strings * lisp/vc/ediff-init.el (ediff-fine-diff-Ancestor): (ediff-even-diff-Ancestor): (ediff-odd-diff-Ancestor): Fix too-long doc strings. diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el index de0a4d71ed..273bad5d35 100644 --- a/lisp/vc/ediff-init.el +++ b/lisp/vc/ediff-init.el @@ -955,9 +955,9 @@ this variable represents.") (((class color)) (:foreground "red3" :background "green")) (t (:underline t :stipple "gray3"))) - "Face for highlighting the refinement of the selected diff in the ancestor buffer. -At present, this face is not used and no fine differences are computed for the -ancestor buffer." + "Face for highlighting refinement of the selected diff in the ancestor buffer. +At present, this face is not used and no fine differences are +computed for the ancestor buffer." :group 'ediff-highlighting) ;; An internal variable. Ediff takes the face from here. When unhighlighting, ;; this variable is set to nil, then again to the appropriate face. @@ -1055,7 +1055,7 @@ this variable represents.") (:foreground "cyan3" :background "light grey" :weight bold :extend t)) (t (:italic t :stipple ,stipple-pixmap :extend t))) - "Face for highlighting even-numbered non-current differences in the ancestor buffer." + "Face for highlighting even-numbered non-current differences in ancestor buffer." :group 'ediff-highlighting) ;; An internal variable. Ediff takes the face from here. When unhighlighting, ;; this variable is set to nil, then again to the appropriate face. @@ -1146,7 +1146,7 @@ this variable represents.") (((class color)) (:foreground "green3" :background "black" :weight bold :extend t)) (t (:italic t :stipple "gray1" :extend t))) - "Face for highlighting odd-numbered non-current differences in the ancestor buffer." + "Face for highlighting odd-numbered non-current differences in ancestor buffer." :group 'ediff-highlighting) ;; An internal variable. Ediff takes the face from here. When unhighlighting, ;; this variable is set to nil, then again to the appropriate face. commit acf9dcdc51280933eba9f249e41ab41d2896aa93 Author: Lars Ingebrigtsen Date: Tue Jun 21 19:07:46 2022 +0200 Check defface doc strings * lisp/emacs-lisp/bytecomp.el (byte-compile-file-form-custom-declare-variable): We already warn about missing groups from byte-compile-normal-call, so this would be a double warning. (custom-declare-face) (byte-compile-file-form-custom-declare-face): Add doc string checking for defface. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 198eb4df5c..04c107a7cf 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1756,7 +1756,8 @@ It is too wide if it has any lines longer than the largest of (pcase (car form) ((or 'autoload 'custom-declare-variable 'defalias 'defconst 'define-abbrev-table - 'defvar 'defvaralias) + 'defvar 'defvaralias + 'custom-declare-face) (setq kind (nth 0 form)) (setq name (nth 1 form)) (setq docs (nth 3 form))) @@ -2705,11 +2706,10 @@ list that represents a doc string reference. (byte-compile-keep-pending form)) (put 'custom-declare-variable 'byte-hunk-handler - 'byte-compile-file-form-custom-declare-variable) -(defun byte-compile-file-form-custom-declare-variable (form) - (when (byte-compile-warning-enabled-p 'callargs) - (byte-compile-nogroup-warn form)) - (byte-compile-file-form-defvar-function form)) + 'byte-compile-file-form-defvar-function) + +(put 'custom-declare-face 'byte-hunk-handler + 'byte-compile-docstring-style-warn) (put 'require 'byte-hunk-handler 'byte-compile-file-form-require) (defun byte-compile-file-form-require (form) commit 1883e532d1aabbf3bb4085824f777382dc190d9c Author: Lars Ingebrigtsen Date: Tue Jun 21 18:45:20 2022 +0200 Untabify doc strings before displaying in Customize * lisp/cus-edit.el (custom-variable-documentation): Untabify the doc string since we'll be indenting it when displaying it (which makes the tabs not align properly). diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 6dff9ec97a..1f496af7d5 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -2583,7 +2583,13 @@ If INITIAL-STRING is non-nil, use that rather than \"Parent groups:\"." Normally just return the docstring. But if VARIABLE automatically becomes buffer local when set, append a message to that effect. Also append any obsolescence information." - (format "%s%s%s" (documentation-property variable 'variable-documentation t) + (format "%s%s%s" + (with-temp-buffer + (insert + (or (documentation-property variable 'variable-documentation t) + "")) + (untabify (point-min) (point-max)) + (buffer-string)) (if (and (local-variable-if-set-p variable) (or (not (local-variable-p variable)) (with-temp-buffer commit 0008003c3e466269074001d637cda872d6fee9be Author: Manuel Giraud Date: Tue Jun 21 16:52:52 2022 +0200 Two typos captured on OpenBSD/clang ; * src/kqueue.c (kqueue_compare_dir_list): Indent typo. ; * src/sysdep.c (system_process_attributes): Unused variable on OpenBSD. diff --git a/src/kqueue.c b/src/kqueue.c index c3c4631784..99a9434cc2 100644 --- a/src/kqueue.c +++ b/src/kqueue.c @@ -159,8 +159,8 @@ kqueue_compare_dir_list (Lisp_Object watch_object) (watch_object, Fcons (Qwrite, Qnil), XCAR (XCDR (old_entry)), Qnil); /* Status change time has been changed, the file attributes have changed. */ - if (NILP (Fequal (Fnth (make_fixnum (3), old_entry), - Fnth (make_fixnum (3), new_entry)))) + if (NILP (Fequal (Fnth (make_fixnum (3), old_entry), + Fnth (make_fixnum (3), new_entry)))) kqueue_generate_event (watch_object, Fcons (Qattrib, Qnil), XCAR (XCDR (old_entry)), Qnil); diff --git a/src/sysdep.c b/src/sysdep.c index 95295e7e67..28ab8189c3 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -3869,7 +3869,7 @@ system_process_attributes (Lisp_Object pid) Lisp_Object system_process_attributes (Lisp_Object pid) { - int proc_id, nentries, fscale, i; + int proc_id, fscale, i; int pagesize = getpagesize (); int mib[6]; size_t len; commit a4dcc8b9a94466c792be3743760a4a45cf6e1e61 Author: Po Lu Date: Tue Jun 21 22:14:49 2022 +0800 Fix recent change to xlwmenu.c * lwlib/xlwmenu.c (ungrab_all): Ungrab keyboard if it was grabbed. This handles `lucid--menu-grab-keyboard' changing while the menu is open. (XlwMenuDestroy): (pop_up_menu): Record if the keyboard was grabbed. diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c index 3c7a493616..eba85631bd 100644 --- a/lwlib/xlwmenu.c +++ b/lwlib/xlwmenu.c @@ -48,6 +48,7 @@ along with GNU Emacs. If not, see . */ #endif /* not emacs */ static int pointer_grabbed; +static int keyboard_grabbed; static XEvent menu_post_event; static char @@ -254,7 +255,8 @@ static void ungrab_all (Widget w, Time ungrabtime) { XtUngrabPointer (w, ungrabtime); - if (lucid__menu_grab_keyboard) + + if (keyboard_grabbed) XtUngrabKeyboard (w, ungrabtime); } @@ -2100,6 +2102,7 @@ XlwMenuDestroy (Widget w) if (pointer_grabbed) ungrab_all ((Widget)w, CurrentTime); pointer_grabbed = 0; + keyboard_grabbed = 0; if (!XtIsShell (XtParent (w))) submenu_destroyed = 1; @@ -2717,15 +2720,22 @@ pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent *event) mw->menu.cursor_shape, event->time) == Success) { - if (!lucid__menu_grab_keyboard - || XtGrabKeyboard ((Widget)mw, False, GrabModeAsync, - GrabModeAsync, event->time) == Success) + if (true +#ifdef emacs + && lucid__menu_grab_keyboard +#endif + && XtGrabKeyboard ((Widget) mw, False, GrabModeAsync, + GrabModeAsync, event->time) == Success) { - XtSetKeyboardFocus((Widget)mw, None); + XtSetKeyboardFocus ((Widget) mw, None); pointer_grabbed = 1; + keyboard_grabbed = 1; } else - XtUngrabPointer ((Widget)mw, event->time); + { + XtUngrabPointer ((Widget) mw, event->time); + keyboard_grabbed = 0; + } } #ifdef emacs commit be35c92c90d455739a6ff9d4beefa2b35d044852 Author: Po Lu Date: Tue Jun 21 22:03:42 2022 +0800 Rewrite PGTK selection code from scratch * src/frame.c (delete_frame): Clear selections and swallow special events. * src/keyboard.c (kbd_buffer_get_event, process_special_events): Also handle selection events on PGTK. * src/keyboard.h (union buffered_input_event): Include selection events on PGTK. * src/pgtkselect.c (symbol_to_gtk_clipboard, LOCAL_SELECTION): New functions and macros. (selection_type_to_quarks, get_func, clear_func): Delete functions. (pgtk_selection_init, pgtk_selection_lost): (pgtk_selection_usable): New functions. (Fpgtk_own_selection_internal, Fpgtk_disown_selection_internal) (Fpgtk_selection_exists_p, Fpgtk_selection_owner_p) (Fpgtk_get_selection_internal): Complete rewrite. (syms_of_pgtkselect): Update defsyms and add more hooks. * src/pgtkselect.h: Delete file. * src/pgtkterm.c (evq_enqueue): Set last user time based on the event. (pgtk_any_window_to_frame, button_event): Fix coding style. (pgtk_set_event_handler): Add selection events. (pgtk_find_selection_owner, pgtk_selection_event): New functions. (pgtk_term_init): Remove call to `pgtk_selection_init'. * src/pgtkterm.h (struct pgtk_display_info): New field `display'. (enum selection_input_event): New struct. New macros for accessing its fields. diff --git a/src/frame.c b/src/frame.c index c21461d49f..c2f2f8e464 100644 --- a/src/frame.c +++ b/src/frame.c @@ -2176,6 +2176,17 @@ delete_frame (Lisp_Object frame, Lisp_Object force) x_clear_frame_selections (f); #endif +#ifdef HAVE_PGTK + if (FRAME_PGTK_P (f)) + { + /* Do special selection events now, in case the window gets + destroyed by this deletion. Does this run Lisp code? */ + swallow_events (false); + + pgtk_clear_frame_selections (f); + } +#endif + /* Free glyphs. This function must be called before the window tree of the frame is deleted because windows contain dynamically allocated diff --git a/src/keyboard.c b/src/keyboard.c index c41727d6c6..6bc2afd40a 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4003,14 +4003,19 @@ kbd_buffer_get_event (KBOARD **kbp, case SELECTION_REQUEST_EVENT: case SELECTION_CLEAR_EVENT: { -#ifdef HAVE_X11 +#if defined HAVE_X11 || HAVE_PGTK /* Remove it from the buffer before processing it, since otherwise swallow_events will see it and process it again. */ struct selection_input_event copy = event->sie; kbd_fetch_ptr = next_kbd_event (event); input_pending = readable_events (0); + +#ifdef HAVE_X11 x_handle_selection_event (©); +#else + pgtk_handle_selection_event (©); +#endif #else /* We're getting selection request events, but we don't have a window system. */ @@ -4381,7 +4386,7 @@ process_special_events (void) if (event->kind == SELECTION_REQUEST_EVENT || event->kind == SELECTION_CLEAR_EVENT) { -#ifdef HAVE_X11 +#if defined HAVE_X11 || defined HAVE_PGTK /* Remove the event from the fifo buffer before processing; otherwise swallow_events called recursively could see it @@ -4406,7 +4411,12 @@ process_special_events (void) moved_events * sizeof *kbd_fetch_ptr); kbd_fetch_ptr = next_kbd_event (kbd_fetch_ptr); input_pending = readable_events (0); + +#ifdef HAVE_X11 x_handle_selection_event (©); +#else + pgtk_handle_selection_event (©); +#endif #else /* We're getting selection request events, but we don't have a window system. */ diff --git a/src/keyboard.h b/src/keyboard.h index 6ae2dc9c4c..507d80c297 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -27,6 +27,10 @@ along with GNU Emacs. If not, see . */ # include "xterm.h" /* for struct selection_input_event */ #endif +#ifdef HAVE_PGTK +#include "pgtkterm.h" /* for struct selection_input_event */ +#endif + INLINE_HEADER_BEGIN /* Most code should use this macro to access Lisp fields in struct kboard. */ @@ -226,7 +230,7 @@ union buffered_input_event { ENUM_BF (event_kind) kind : EVENT_KIND_WIDTH; struct input_event ie; -#ifdef HAVE_X11 +#if defined HAVE_X11 || defined HAVE_PGTK struct selection_input_event sie; #endif }; diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 76901b9eb1..a0168c9fad 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -17,16 +17,6 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs. If not, see . */ -/* FIXME: this file needs a major rewrite to replace the use of GTK's - own high-level GtkClipboard API with the GDK selection API: - - https://developer-old.gnome.org/gdk3/stable/gdk3-Selections.html - - That way, most of the code can be shared with X, and non-text - targets along with drag-and-drop can be supported. GDK implements - selections according to the ICCCM, as on X, but its selection API - will work on any supported window system. */ - /* This should be the first include, as it may set up #defines affecting interpretation of even the system includes. */ #include @@ -35,21 +25,37 @@ along with GNU Emacs. If not, see . */ #include "pgtkterm.h" #include "termhooks.h" #include "keyboard.h" -#include "pgtkselect.h" -#include - -static GQuark quark_primary_data = 0; -static GQuark quark_primary_size = 0; -static GQuark quark_secondary_data = 0; -static GQuark quark_secondary_size = 0; -static GQuark quark_clipboard_data = 0; -static GQuark quark_clipboard_size = 0; - -/* ========================================================================== - - Internal utility functions - - ========================================================================== */ +#include "atimer.h" +#include "blockinput.h" + +/* This file deliberately does not implement INCR, since it adds a + bunch of extra code for no real gain, as PGTK isn't supposed to + support X11 anyway. */ + +/* Advance declaration of structs. */ +struct selection_data; +struct prop_location; + +static void pgtk_decline_selection_request (struct selection_input_event *); +static bool pgtk_convert_selection (Lisp_Object, Lisp_Object, GdkAtom, bool, + struct pgtk_display_info *); +static bool waiting_for_other_props_on_window (GdkDisplay *, GdkWindow *); +#if 0 +static struct prop_location *expect_property_change (GdkDisplay *, GdkWindow *, + GdkAtom, int); +#endif +static void unexpect_property_change (struct prop_location *); +static void wait_for_property_change (struct prop_location *); +static Lisp_Object pgtk_get_window_property_as_lisp_data (struct pgtk_display_info *, + GdkWindow *, GdkAtom, + Lisp_Object, GdkAtom, bool); +static Lisp_Object selection_data_to_lisp_data (struct pgtk_display_info *, + const unsigned char *, + ptrdiff_t, GdkAtom, int); +static void lisp_data_to_selection_data (struct pgtk_display_info *, Lisp_Object, + struct selection_data *); +static Lisp_Object pgtk_get_local_selection (Lisp_Object, Lisp_Object, + bool, struct pgtk_display_info *); /* From a Lisp_Object, return a suitable frame for selection operations. OBJECT may be a frame, a terminal object, or nil @@ -98,398 +104,1662 @@ frame_for_pgtk_selection (Lisp_Object object) return NULL; } -static GtkClipboard * -symbol_to_gtk_clipboard (GtkWidget * widget, Lisp_Object symbol) +#define LOCAL_SELECTION(selection_symbol, dpyinfo) \ + assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) + +static GdkAtom +symbol_to_gdk_atom (Lisp_Object sym) { - GdkAtom atom; + if (NILP (sym)) + return GDK_NONE; - CHECK_SYMBOL (symbol); - if (NILP (symbol)) - { - atom = GDK_SELECTION_PRIMARY; - } - else if (EQ (symbol, QCLIPBOARD)) + if (EQ (sym, QPRIMARY)) + return GDK_SELECTION_PRIMARY; + if (EQ (sym, QSECONDARY)) + return GDK_SELECTION_SECONDARY; + if (EQ (sym, QCLIPBOARD)) + return GDK_SELECTION_CLIPBOARD; + + if (!SYMBOLP (sym)) + emacs_abort (); + + return gdk_atom_intern (SSDATA (SYMBOL_NAME (sym)), FALSE); +} + +static Lisp_Object +gdk_atom_to_symbol (GdkAtom atom) +{ + return intern (gdk_atom_name (atom)); +} + + + +/* Do protocol to assert ourself as a selection owner. + FRAME shall be the owner; it must be a valid GDK frame. + Update the Vselection_alist so that we can reply to later requests for + our selection. */ + +static void +pgtk_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, + Lisp_Object frame) +{ + struct frame *f = XFRAME (frame); + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + guint32 timestamp = gtk_get_current_event_time (); + GdkAtom selection_atom = symbol_to_gdk_atom (selection_name); + Lisp_Object targets; + ptrdiff_t i, ntargets; + GtkTargetEntry *gtargets; + + if (timestamp == GDK_CURRENT_TIME) + timestamp = dpyinfo->last_user_time; + + /* Assert ownership over the selection. Ideally we would use the + GDK selection API for this as well, but it just doesn't work on + Wayland. */ + + if (!gdk_selection_owner_set_for_display (dpyinfo->display, + FRAME_GDK_WINDOW (f), + selection_atom, + timestamp, TRUE)) + signal_error ("Could not assert ownership over selection", selection_name); + + /* Update the local cache */ + { + Lisp_Object selection_data; + Lisp_Object prev_value; + + selection_data = list4 (selection_name, selection_value, + INT_TO_INTEGER (timestamp), frame); + prev_value = LOCAL_SELECTION (selection_name, dpyinfo); + + tset_selection_alist + (dpyinfo->terminal, + Fcons (selection_data, dpyinfo->terminal->Vselection_alist)); + + /* If we already owned the selection, remove the old selection + data. Don't use Fdelq as that may quit. */ + if (!NILP (prev_value)) + { + /* We know it's not the CAR, so it's easy. */ + Lisp_Object rest = dpyinfo->terminal->Vselection_alist; + for (; CONSP (rest); rest = XCDR (rest)) + if (EQ (prev_value, Fcar (XCDR (rest)))) + { + XSETCDR (rest, XCDR (XCDR (rest))); + break; + } + } + } + + /* Announce the targets to the display server. This isn't required + on X, but is on Wayland. */ + + targets = pgtk_get_local_selection (selection_name, QTARGETS, + true, dpyinfo); + + /* GC must not happen inside this segment. */ + block_input (); + gtk_selection_clear_targets (FRAME_GTK_WIDGET (f), selection_atom); + + if (VECTORP (targets)) { - atom = GDK_SELECTION_CLIPBOARD; + gtargets = xzalloc (sizeof *gtargets * ASIZE (targets)); + ntargets = 0; + + for (i = 0; i < ASIZE (targets); ++i) + { + if (SYMBOLP (AREF (targets, i))) + gtargets[ntargets++].target + = SSDATA (SYMBOL_NAME (AREF (targets, i))); + } + + gtk_selection_add_targets (FRAME_GTK_WIDGET (f), + selection_atom, gtargets, + ntargets); + + xfree (gtargets); } - else if (EQ (symbol, QPRIMARY)) + unblock_input (); +} + +static Lisp_Object +pgtk_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, + bool local_request, struct pgtk_display_info *dpyinfo) +{ + Lisp_Object local_value, tem; + Lisp_Object handler_fn, value, check; + + local_value = LOCAL_SELECTION (selection_symbol, dpyinfo); + + if (NILP (local_value)) return Qnil; + + /* TIMESTAMP is a special case. */ + if (EQ (target_type, QTIMESTAMP)) { - atom = GDK_SELECTION_PRIMARY; + handler_fn = Qnil; + value = XCAR (XCDR (XCDR (local_value))); } - else if (EQ (symbol, QSECONDARY)) + else { - atom = GDK_SELECTION_SECONDARY; + /* Don't allow a quit within the converter. + When the user types C-g, he would be surprised + if by luck it came during a converter. */ + specpdl_ref count = SPECPDL_INDEX (); + specbind (Qinhibit_quit, Qt); + + CHECK_SYMBOL (target_type); + handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); + + if (CONSP (handler_fn)) + handler_fn = XCDR (handler_fn); + + tem = XCAR (XCDR (local_value)); + + if (STRINGP (tem)) + { + local_value = Fget_text_property (make_fixnum (0), + target_type, tem); + + if (!NILP (local_value)) + tem = local_value; + } + + if (!NILP (handler_fn)) + value = call3 (handler_fn, selection_symbol, + (local_request + ? Qnil + : target_type), + tem); + else + value = Qnil; + value = unbind_to (count, value); } - else if (EQ (symbol, Qt)) + + /* Make sure this value is of a type that we could transmit + to another client. */ + + check = value; + if (CONSP (value) + && SYMBOLP (XCAR (value))) + check = XCDR (value); + + if (STRINGP (check) + || VECTORP (check) + || SYMBOLP (check) + || INTEGERP (check) + || NILP (value)) + return value; + /* Check for a value that CONS_TO_INTEGER could handle. */ + else if (CONSP (check) + && INTEGERP (XCAR (check)) + && (INTEGERP (XCDR (check)) + || + (CONSP (XCDR (check)) + && INTEGERP (XCAR (XCDR (check))) + && NILP (XCDR (XCDR (check)))))) + return value; + + signal_error ("Invalid data returned by selection-conversion function", + list2 (handler_fn, value)); +} + +static void +pgtk_decline_selection_request (struct selection_input_event *event) +{ + gdk_selection_send_notify (SELECTION_EVENT_REQUESTOR (event), + SELECTION_EVENT_SELECTION (event), + SELECTION_EVENT_TARGET (event), + GDK_NONE, SELECTION_EVENT_TIME (event)); +} + +struct selection_data +{ + unsigned char *data; + ptrdiff_t size; + int format; + GdkAtom type; + bool nofree; + GdkAtom property; + + /* This can be set to non-NULL during x_reply_selection_request, if + the selection is waiting for an INCR transfer to complete. Don't + free these; that's done by unexpect_property_change. */ + struct prop_location *wait_object; + struct selection_data *next; +}; + +struct pgtk_selection_request +{ + /* The last element in this stack. */ + struct pgtk_selection_request *last; + + /* Its display info. */ + struct pgtk_display_info *dpyinfo; + + /* Its selection input event. */ + struct selection_input_event *request; + + /* Linked list of the above (in support of MULTIPLE targets). */ + struct selection_data *converted_selections; + + /* "Data" to send a requestor for a failed MULTIPLE subtarget. */ + GdkAtom conversion_fail_tag; + + /* Whether or not conversion was successful. */ + bool converted; +}; + +/* Stack of selections currently being processed. + NULL if all requests have been fully processed. */ + +struct pgtk_selection_request *selection_request_stack; + +static void +pgtk_push_current_selection_request (struct selection_input_event *se, + struct pgtk_display_info *dpyinfo) +{ + struct pgtk_selection_request *frame; + + frame = xmalloc (sizeof *frame); + frame->converted = false; + frame->last = selection_request_stack; + frame->request = se; + frame->dpyinfo = dpyinfo; + frame->converted_selections = NULL; + frame->conversion_fail_tag = GDK_NONE; + + selection_request_stack = frame; +} + +static void +pgtk_pop_current_selection_request (void) +{ + struct pgtk_selection_request *tem; + + tem = selection_request_stack; + selection_request_stack = selection_request_stack->last; + + xfree (tem); +} + +/* Used as an unwind-protect clause so that, if a selection-converter signals + an error, we tell the requestor that we were unable to do what they wanted + before we throw to top-level or go into the debugger or whatever. */ + +static void +pgtk_selection_request_lisp_error (void) +{ + struct selection_data *cs, *next; + struct pgtk_selection_request *frame; + + frame = selection_request_stack; + + for (cs = frame->converted_selections; cs; cs = next) { - atom = GDK_SELECTION_SECONDARY; + next = cs->next; + if (! cs->nofree && cs->data) + xfree (cs->data); + xfree (cs); } - else + frame->converted_selections = NULL; + + if (!frame->converted && frame->dpyinfo->display) + pgtk_decline_selection_request (frame->request); +} + +/* This stuff is so that INCR selections are reentrant (that is, so we can + be servicing multiple INCR selection requests simultaneously.) I haven't + actually tested that yet. */ + +/* Keep a list of the property changes that are awaited. */ + +struct prop_location +{ + int identifier; + GdkDisplay *display; + GdkWindow *window; + GdkAtom property; + int desired_state; + bool arrived; + struct prop_location *next; +}; + +#if 0 + +static int prop_location_identifier; + +#endif + +static Lisp_Object property_change_reply; + +static struct prop_location *property_change_reply_object; + +static struct prop_location *property_change_wait_list; + +static void +set_property_change_object (struct prop_location *location) +{ + /* Input must be blocked so we don't get the event before we set these. */ + if (!input_blocked_p ()) + emacs_abort (); + + XSETCAR (property_change_reply, Qnil); + property_change_reply_object = location; +} + + +/* Send the reply to a selection request event EVENT. */ + +static void +pgtk_reply_selection_request (struct selection_input_event *event, + struct pgtk_display_info *dpyinfo) +{ + GdkDisplay *display = SELECTION_EVENT_DISPLAY (event); + GdkWindow *window = SELECTION_EVENT_REQUESTOR (event); + ptrdiff_t bytes_remaining; + struct selection_data *cs; + struct pgtk_selection_request *frame; + + frame = selection_request_stack; + + block_input (); + /* Loop over converted selections, storing them in the requested + properties. If data is large, only store the first N bytes + (section 2.7.2 of ICCCM). Note that we store the data for a + MULTIPLE request in the opposite order; the ICCM says only that + the conversion itself must be done in the same order. */ + for (cs = frame->converted_selections; cs; cs = cs->next) { - atom = 0; - error ("Bad selection"); + if (cs->property == GDK_NONE) + continue; + + bytes_remaining = cs->size; + bytes_remaining *= cs->format >> 3; + + gdk_property_change (window, cs->property, + cs->type, cs->format, + GDK_PROP_MODE_APPEND, + cs->data, cs->size); } - return gtk_widget_get_clipboard (widget, atom); + /* Now issue the SelectionNotify event. */ + gdk_selection_send_notify (window, + SELECTION_EVENT_SELECTION (event), + SELECTION_EVENT_TARGET (event), + SELECTION_EVENT_PROPERTY (event), + SELECTION_EVENT_TIME (event)); + gdk_display_flush (display); + + /* Finish sending the rest of each of the INCR values. This should + be improved; there's a chance of deadlock if more than one + subtarget in a MULTIPLE selection requires an INCR transfer, and + the requestor and Emacs loop waiting on different transfers. */ + for (cs = frame->converted_selections; cs; cs = cs->next) + if (cs->wait_object) + { + int format_bytes = cs->format / 8; + + /* Must set this inside block_input (). unblock_input may read + events and setting property_change_reply in + wait_for_property_change is then too late. */ + set_property_change_object (cs->wait_object); + unblock_input (); + + bytes_remaining = cs->size; + bytes_remaining *= format_bytes; + + /* Wait for the requestor to ack by deleting the property. + This can run Lisp code (process handlers) or signal. */ + wait_for_property_change (cs->wait_object); + + /* Now write a zero-length chunk to the property to tell the + requestor that we're done. */ + block_input (); + if (! waiting_for_other_props_on_window (display, window)) + gdk_window_set_events (window, 0); + gdk_property_change (window, cs->property, cs->type, cs->format, + GDK_PROP_MODE_REPLACE, cs->data, 0); + } + + gdk_display_sync (display); + unblock_input (); } + + +/* Handle a SelectionRequest event EVENT. + This is called from keyboard.c when such an event is found in the queue. */ + static void -selection_type_to_quarks (GdkAtom type, GQuark * quark_data, - GQuark * quark_size) +pgtk_handle_selection_request (struct selection_input_event *event) { - if (type == GDK_SELECTION_PRIMARY) + guint32 local_selection_time; + struct pgtk_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event); + GdkAtom selection = SELECTION_EVENT_SELECTION (event); + Lisp_Object selection_symbol = gdk_atom_to_symbol (selection); + GdkAtom target = SELECTION_EVENT_TARGET (event); + Lisp_Object target_symbol = gdk_atom_to_symbol (target); + GdkAtom property = SELECTION_EVENT_PROPERTY (event); + Lisp_Object local_selection_data; + bool success = false; + specpdl_ref count = SPECPDL_INDEX (); + bool pushed; + Lisp_Object alias, tem; + + alias = Vpgtk_selection_alias_alist; + + FOR_EACH_TAIL_SAFE (alias) { - *quark_data = quark_primary_data; - *quark_size = quark_primary_size; + tem = Qnil; + + if (CONSP (alias)) + tem = XCAR (alias); + + if (CONSP (tem) + && EQ (XCAR (tem), selection_symbol) + && SYMBOLP (XCDR (tem))) + { + selection_symbol = XCDR (tem); + break; + } } - else if (type == GDK_SELECTION_SECONDARY) + + pushed = false; + + if (!dpyinfo) + goto DONE; + + local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo); + + /* Decline if we don't own any selections. */ + if (NILP (local_selection_data)) goto DONE; + + /* Decline requests issued prior to our acquiring the selection. */ + CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))), + guint32, local_selection_time); + if (SELECTION_EVENT_TIME (event) != GDK_CURRENT_TIME + && local_selection_time > SELECTION_EVENT_TIME (event)) + goto DONE; + + block_input (); + pushed = true; + pgtk_push_current_selection_request (event, dpyinfo); + record_unwind_protect_void (pgtk_pop_current_selection_request); + record_unwind_protect_void (pgtk_selection_request_lisp_error); + unblock_input (); + + if (EQ (target_symbol, QMULTIPLE)) { - *quark_data = quark_secondary_data; - *quark_size = quark_secondary_size; + /* For MULTIPLE targets, the event property names a list of atom + pairs; the first atom names a target and the second names a + non-GDK_NONE property. */ + GdkWindow *requestor = SELECTION_EVENT_REQUESTOR (event); + Lisp_Object multprop; + ptrdiff_t j, nselections; + struct selection_data cs; + + if (property == GDK_NONE) + goto DONE; + + multprop = pgtk_get_window_property_as_lisp_data (dpyinfo, + requestor, + property, + QMULTIPLE, + selection, + true); + + if (!VECTORP (multprop) || ASIZE (multprop) % 2) + goto DONE; + + nselections = ASIZE (multprop) / 2; + /* Perform conversions. This can signal. */ + for (j = 0; j < nselections; j++) + { + Lisp_Object subtarget = AREF (multprop, 2*j); + GdkAtom subproperty = symbol_to_gdk_atom (AREF (multprop, 2 * j + 1)); + bool subsuccess = false; + + if (subproperty != GDK_NONE) + subsuccess = pgtk_convert_selection (selection_symbol, subtarget, + subproperty, true, dpyinfo); + if (!subsuccess) + ASET (multprop, 2*j+1, Qnil); + } + /* Save conversion results */ + lisp_data_to_selection_data (dpyinfo, multprop, &cs); + gdk_property_change (requestor, property, + cs.type, cs.format, + GDK_PROP_MODE_REPLACE, + cs.data, cs.size); + success = true; } - else if (type == GDK_SELECTION_CLIPBOARD) + else { - *quark_data = quark_clipboard_data; - *quark_size = quark_clipboard_size; + if (property == GDK_NONE) + property = SELECTION_EVENT_TARGET (event); + + success = pgtk_convert_selection (selection_symbol, + target_symbol, property, + false, dpyinfo); } + + DONE: + + if (pushed) + selection_request_stack->converted = true; + + if (success) + pgtk_reply_selection_request (event, dpyinfo); else - /* FIXME: Is it safe to use 'error' here? */ - error ("Unknown selection type."); + pgtk_decline_selection_request (event); + + /* Run the `pgtk-sent-selection-functions' abnormal hook. */ + if (!NILP (Vpgtk_sent_selection_functions) + && !BASE_EQ (Vpgtk_sent_selection_functions, Qunbound)) + CALLN (Frun_hook_with_args, Qpgtk_sent_selection_functions, + selection_symbol, target_symbol, success ? Qt : Qnil); + + unbind_to (count, Qnil); } -static void -get_func (GtkClipboard * cb, GtkSelectionData * data, guint info, - gpointer user_data_or_owner) +/* Perform the requested selection conversion, and write the data to + the converted_selections linked list, where it can be accessed by + x_reply_selection_request. If FOR_MULTIPLE, write out + the data even if conversion fails, using conversion_fail_tag. + + Return true if (and only if) successful. */ + +static bool +pgtk_convert_selection (Lisp_Object selection_symbol, + Lisp_Object target_symbol, GdkAtom property, + bool for_multiple, struct pgtk_display_info *dpyinfo) { - GObject *obj = G_OBJECT (user_data_or_owner); - const char *str; - int size; - GQuark quark_data, quark_size; + Lisp_Object lisp_selection; + struct selection_data *cs; + struct pgtk_selection_request *frame; + + lisp_selection + = pgtk_get_local_selection (selection_symbol, target_symbol, + false, dpyinfo); - selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data, - &quark_size); + frame = selection_request_stack; - str = g_object_get_qdata (obj, quark_data); - size = GPOINTER_TO_SIZE (g_object_get_qdata (obj, quark_size)); - gtk_selection_data_set_text (data, str, size); + /* A nil return value means we can't perform the conversion. */ + if (NILP (lisp_selection) + || (CONSP (lisp_selection) && NILP (XCDR (lisp_selection)))) + { + if (for_multiple) + { + cs = xmalloc (sizeof *cs); + cs->data = ((unsigned char *) + &selection_request_stack->conversion_fail_tag); + cs->size = 1; + cs->format = 32; + cs->type = GDK_SELECTION_TYPE_ATOM; + cs->nofree = true; + cs->property = property; + cs->wait_object = NULL; + cs->next = frame->converted_selections; + frame->converted_selections = cs; + } + + return false; + } + + /* Otherwise, record the converted selection to binary. */ + cs = xmalloc (sizeof *cs); + cs->data = NULL; + cs->nofree = true; + cs->property = property; + cs->wait_object = NULL; + cs->next = frame->converted_selections; + frame->converted_selections = cs; + lisp_data_to_selection_data (dpyinfo, lisp_selection, cs); + return true; } + + +/* Handle a SelectionClear event EVENT, which indicates that some + client cleared out our previously asserted selection. + This is called from keyboard.c when such an event is found in the queue. */ + static void -clear_func (GtkClipboard * cb, gpointer user_data_or_owner) +pgtk_handle_selection_clear (struct selection_input_event *event) { - GObject *obj = G_OBJECT (user_data_or_owner); - GQuark quark_data, quark_size; + GdkAtom selection = SELECTION_EVENT_SELECTION (event); + guint32 changed_owner_time = SELECTION_EVENT_TIME (event); - selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data, - &quark_size); + Lisp_Object selection_symbol, local_selection_data; + guint32 local_selection_time; + struct pgtk_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event); + Lisp_Object Vselection_alist; - g_object_set_qdata (obj, quark_data, NULL); - g_object_set_qdata (obj, quark_size, 0); -} + if (!dpyinfo) return; + selection_symbol = gdk_atom_to_symbol (selection); + local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo); -/* ========================================================================== + /* Well, we already believe that we don't own it, so that's just fine. */ + if (NILP (local_selection_data)) return; - Functions used externally + CONS_TO_INTEGER (XCAR (XCDR (XCDR (local_selection_data))), + guint32, local_selection_time); - ========================================================================== */ + /* We have reasserted the selection since this SelectionClear was + generated, so we can disregard it. */ + if (changed_owner_time != GDK_CURRENT_TIME + && local_selection_time > changed_owner_time) + return; + + /* Otherwise, really clear. Don't use Fdelq as that may quit. */ + Vselection_alist = dpyinfo->terminal->Vselection_alist; + if (EQ (local_selection_data, CAR (Vselection_alist))) + Vselection_alist = XCDR (Vselection_alist); + else + { + Lisp_Object rest; + for (rest = Vselection_alist; CONSP (rest); rest = XCDR (rest)) + if (EQ (local_selection_data, CAR (XCDR (rest)))) + { + XSETCDR (rest, XCDR (XCDR (rest))); + break; + } + } + tset_selection_alist (dpyinfo->terminal, Vselection_alist); + + /* Run the `pgtk-lost-selection-functions' abnormal hook. */ + CALLN (Frun_hook_with_args, Qpgtk_lost_selection_functions, selection_symbol); + + redisplay_preserve_echo_area (20); +} + +void +pgtk_handle_selection_event (struct selection_input_event *event) +{ + if (event->kind != SELECTION_REQUEST_EVENT) + pgtk_handle_selection_clear (event); + else + pgtk_handle_selection_request (event); +} + +/* Clear all selections that were made from frame F. + We do this when about to delete a frame. */ void -pgtk_selection_init (void) +pgtk_clear_frame_selections (struct frame *f) +{ + Lisp_Object frame; + Lisp_Object rest; + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + struct terminal *t = dpyinfo->terminal; + + XSETFRAME (frame, f); + + /* Delete elements from the beginning of Vselection_alist. */ + while (CONSP (t->Vselection_alist) + && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist))))))) + { + /* Run the `pgtk-lost-selection-functions' abnormal hook. */ + CALLN (Frun_hook_with_args, Qpgtk_lost_selection_functions, + Fcar (Fcar (t->Vselection_alist))); + + tset_selection_alist (t, XCDR (t->Vselection_alist)); + } + + /* Delete elements after the beginning of Vselection_alist. */ + for (rest = t->Vselection_alist; CONSP (rest); rest = XCDR (rest)) + if (CONSP (XCDR (rest)) + && EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest)))))))) + { + CALLN (Frun_hook_with_args, Qpgtk_lost_selection_functions, + XCAR (XCAR (XCDR (rest)))); + XSETCDR (rest, XCDR (XCDR (rest))); + break; + } +} + +/* True if any properties for DISPLAY and WINDOW + are on the list of what we are waiting for. */ + +static bool +waiting_for_other_props_on_window (GdkDisplay *display, GdkWindow *window) +{ + for (struct prop_location *p = property_change_wait_list; p; p = p->next) + if (p->display == display && p->window == window) + return true; + return false; +} + +/* Add an entry to the list of property changes we are waiting for. + DISPLAY, WINDOW, PROPERTY, STATE describe what we will wait for. + The return value is a number that uniquely identifies + this awaited property change. */ + +/* Currently unused -- uncomment later if we decide to implement INCR + transfer for X. */ + +#if 0 + +static struct prop_location * +expect_property_change (GdkDisplay *display, GdkWindow *window, + GdkAtom property, int state) +{ + struct prop_location *pl = xmalloc (sizeof *pl); + pl->identifier = ++prop_location_identifier; + pl->display = display; + pl->window = window; + pl->property = property; + pl->desired_state = state; + pl->next = property_change_wait_list; + pl->arrived = false; + property_change_wait_list = pl; + return pl; +} + +#endif + +/* Delete an entry from the list of property changes we are waiting for. + IDENTIFIER is the number that uniquely identifies the entry. */ + +static void +unexpect_property_change (struct prop_location *location) { - if (quark_primary_data == 0) + struct prop_location *prop, **pprev = &property_change_wait_list; + + for (prop = property_change_wait_list; prop; prop = *pprev) { - quark_primary_data = g_quark_from_static_string ("pgtk-primary-data"); - quark_primary_size = g_quark_from_static_string ("pgtk-primary-size"); - quark_secondary_data = - g_quark_from_static_string ("pgtk-secondary-data"); - quark_secondary_size = - g_quark_from_static_string ("pgtk-secondary-size"); - quark_clipboard_data = - g_quark_from_static_string ("pgtk-clipboard-data"); - quark_clipboard_size = - g_quark_from_static_string ("pgtk-clipboard-size"); + if (prop == location) + { + *pprev = prop->next; + xfree (prop); + break; + } + else + pprev = &prop->next; } } +/* Remove the property change expectation element for IDENTIFIER. */ + +static void +wait_for_property_change_unwind (void *loc) +{ + struct prop_location *location = loc; + + unexpect_property_change (location); + if (location == property_change_reply_object) + property_change_reply_object = 0; +} + +/* Actually wait for a property change. + IDENTIFIER should be the value that expect_property_change returned. */ + +static void +wait_for_property_change (struct prop_location *location) +{ + specpdl_ref count = SPECPDL_INDEX (); + + /* Make sure to do unexpect_property_change if we quit or err. */ + record_unwind_protect_ptr (wait_for_property_change_unwind, location); + + /* See comment in x_reply_selection_request about setting + property_change_reply. Do not do it here. */ + + /* If the event we are waiting for arrives beyond here, it will set + property_change_reply, because property_change_reply_object says so. */ + if (! location->arrived) + { + intmax_t timeout = max (0, 5000); + intmax_t secs = timeout / 1000; + int nsecs = (timeout % 1000) * 1000000; + + wait_reading_process_output (secs, nsecs, 0, false, + property_change_reply, NULL, 0); + + if (NILP (XCAR (property_change_reply))) + error ("Timed out waiting for property-notify event"); + } + + unbind_to (count, Qnil); +} + +/* Called from the big filter in response to a PropertyNotify + event. */ + void -pgtk_selection_lost (GtkWidget * widget, GdkEventSelection * event, - gpointer user_data) +pgtk_handle_property_notify (GdkEventProperty *event) { - GQuark quark_data, quark_size; + struct prop_location *rest; + GdkDisplay *dpy; + + dpy = gdk_window_get_display (event->window); - selection_type_to_quarks (event->selection, &quark_data, &quark_size); + for (rest = property_change_wait_list; rest; rest = rest->next) + { + if (!rest->arrived + && rest->property == event->atom + && rest->window == event->window + && rest->display == dpy + && rest->desired_state == event->state) + { + rest->arrived = true; - g_object_set_qdata (G_OBJECT (widget), quark_data, NULL); - g_object_set_qdata (G_OBJECT (widget), quark_size, 0); + /* If this is the one wait_for_property_change is waiting for, + tell it to wake up. */ + if (rest == property_change_reply_object) + XSETCAR (property_change_reply, Qt); + + return; + } + } } -static bool -pgtk_selection_usable (void) +static void +pgtk_display_selection_waiting_message (struct atimer *timer) { - if (pgtk_enable_selection_on_multi_display) - return true; + Lisp_Object val; - /* Gdk uses `gdk_display_get_default' when handling selections, so - selections don't work properly when Emacs is connected to - multiple displays. */ + val = build_string ("Waiting for reply from selection owner..."); + message3_nolog (val); +} - GdkDisplayManager *dpyman = gdk_display_manager_get (); - GSList *list = gdk_display_manager_list_displays (dpyman); - int len = g_slist_length (list); - g_slist_free (list); - return len < 2; +static void +pgtk_cancel_atimer (void *atimer) +{ + cancel_atimer (atimer); } -/* ========================================================================== + +/* Variables for communication with pgtk_handle_selection_notify. */ +static GdkAtom reading_which_selection; +static Lisp_Object reading_selection_reply; +static GdkWindow *reading_selection_window; - Lisp Defuns +/* Do protocol to read selection-data from the window server. + Converts this to Lisp data and returns it. + FRAME is the frame whose window shall request the selection. */ - ========================================================================== */ +static Lisp_Object +pgtk_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, + Lisp_Object time_stamp, Lisp_Object frame) +{ + struct frame *f = XFRAME (frame); + struct pgtk_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + GdkWindow *requestor_window = FRAME_GDK_WINDOW (f); + guint32 requestor_time = dpyinfo->last_user_time; + GdkAtom selection_atom = symbol_to_gdk_atom (selection_symbol); + GdkAtom type_atom = (CONSP (target_type) + ? symbol_to_gdk_atom (XCAR (target_type)) + : symbol_to_gdk_atom (target_type)); + struct atimer *delayed_message; + struct timespec message_interval; + specpdl_ref count; + + count = SPECPDL_INDEX (); + + if (!FRAME_LIVE_P (f)) + return unbind_to (count, Qnil); + + if (!NILP (time_stamp)) + CONS_TO_INTEGER (time_stamp, guint32, requestor_time); + + block_input (); + /* Prepare to block until the reply has been read. */ + reading_selection_window = requestor_window; + reading_which_selection = selection_atom; + XSETCAR (reading_selection_reply, Qnil); + + gdk_selection_convert (requestor_window, selection_atom, + type_atom, requestor_time); + unblock_input (); + + /* It should not be necessary to stop handling selection requests + during this time. In fact, the SAVE_TARGETS mechanism requires + us to handle a clipboard manager's requests before it returns + GDK_SELECTION_NOTIFY. */ + + message_interval = make_timespec (1, 0); + delayed_message = start_atimer (ATIMER_RELATIVE, message_interval, + pgtk_display_selection_waiting_message, + NULL); + record_unwind_protect_ptr (pgtk_cancel_atimer, delayed_message); + + /* This allows quits. Also, don't wait forever. */ + intmax_t timeout = max (0, 5000); + intmax_t secs = timeout / 1000; + int nsecs = (timeout % 1000) * 1000000; + + wait_reading_process_output (secs, nsecs, 0, false, + reading_selection_reply, NULL, 0); + + if (NILP (XCAR (reading_selection_reply))) + error ("Timed out waiting for reply from selection owner"); + if (EQ (XCAR (reading_selection_reply), Qlambda)) + return unbind_to (count, Qnil); + + /* Otherwise, the selection is waiting for us on the requested property. */ + return unbind_to (count, + pgtk_get_window_property_as_lisp_data (dpyinfo, + requestor_window, + GDK_NONE, + target_type, + selection_atom, + false)); +} +/* Subroutines of pgtk_get_window_property_as_lisp_data */ -DEFUN ("pgtk-own-selection-internal", Fpgtk_own_selection_internal, Spgtk_own_selection_internal, 2, 3, 0, - doc: /* Assert an X selection of type SELECTION and value VALUE. -SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. -\(Those are literal upper-case symbol names, since that's what X expects.) -VALUE is typically a string, or a cons of two markers, but may be -anything that the functions on `selection-converter-alist' know about. +static ptrdiff_t +pgtk_size_for_format (gint format) +{ + switch (format) + { + case 8: + return sizeof (unsigned char); + case 16: + return sizeof (unsigned short); + case 32: + return sizeof (unsigned long); + + default: + emacs_abort (); + } +} -FRAME should be a frame that should own the selection. If omitted or -nil, it defaults to the selected frame. */) - (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) +/* Use xfree, not g_free, to free the data obtained with this function. */ + +static void +pgtk_get_window_property (GdkWindow *window, unsigned char **data_ret, + ptrdiff_t *bytes_ret, GdkAtom *actual_type_ret, + int *actual_format_ret, unsigned long *actual_size_ret) { - Lisp_Object successful_p = Qnil; - Lisp_Object target_symbol, rest; - GtkClipboard *cb; - struct frame *f; - GQuark quark_data, quark_size; + gint length, actual_format; + unsigned char *data; + ptrdiff_t element_size; + void *xdata; + GdkAtom actual_type; + unsigned long i; + unsigned int *idata; + unsigned long *ldata; + + data = NULL; + + length = gdk_selection_property_get (window, &data, + &actual_type, + &actual_format); + + if (!data) + { + *data_ret = NULL; + *actual_type_ret = GDK_NONE; + *bytes_ret = 0; + *actual_format_ret = 8; + *actual_size_ret = 0; - check_window_system (NULL); + return; + } - if (!pgtk_selection_usable ()) - return Qnil; + if (actual_type == GDK_SELECTION_TYPE_ATOM + || actual_type == gdk_atom_intern_static_string ("ATOM_PAIR")) + { + /* GDK should not allow anything else. */ + eassert (actual_format == 32); - if (NILP (frame)) - frame = selected_frame; - if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame))) - error ("pgtk selection unavailable for this frame"); - f = XFRAME (frame); + length = length / sizeof (GdkAtom); + xdata = xmalloc (sizeof (GdkAtom) * length); + memcpy (xdata, data, 1 + length * sizeof (GdkAtom)); + + g_free (data); + + *data_ret = xdata; + *actual_type_ret = actual_type; + *bytes_ret = length * sizeof (GdkAtom); + *actual_format_ret = 32; + *actual_size_ret = length; - cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection); - selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data, - &quark_size); + return; + } + + element_size = pgtk_size_for_format (actual_format); + length = length / element_size; - /* We only support copy of text. */ - target_symbol = QTEXT; - if (STRINGP (value)) + /* Add an extra byte on the end. GDK guarantees that it is + NULL. */ + xdata = xmalloc (1 + element_size * length); + memcpy (xdata, data, 1 + element_size * length); + + if (actual_format == 32 && LONG_WIDTH > 32) { - GtkTargetList *list; - GtkTargetEntry *targets; - gint n_targets; - GtkWidget *widget; + ldata = (typeof (ldata)) data; + idata = xdata; - list = gtk_target_list_new (NULL, 0); - gtk_target_list_add_text_targets (list, 0); + for (i = 0; i < length; ++i) + idata[i] = ldata[i]; - { - /* text/plain: Strings encoded by Gtk are not correctly decoded by Chromium(Wayland). */ - GdkAtom atom_text_plain = gdk_atom_intern ("text/plain", false); - gtk_target_list_remove (list, atom_text_plain); - } + /* There is always enough space in idata. */ + idata[length] = 0; + *bytes_ret = sizeof *idata * length; + } + else + /* I think GDK itself prevents element_size from exceeding the + length at which this computation fails. */ + *bytes_ret = element_size * length; + + /* Now free the original `data' allocated by GDK. */ + g_free (data); + + *data_ret = xdata; + *actual_type_ret = GDK_NONE; + *actual_size_ret = length; + *actual_format_ret = actual_format; + *actual_type_ret = actual_type; +} + +static Lisp_Object +pgtk_get_window_property_as_lisp_data (struct pgtk_display_info *dpyinfo, + GdkWindow *window, GdkAtom property, + Lisp_Object target_type, GdkAtom selection_atom, + bool for_multiple) +{ + GdkAtom actual_type; + int actual_format; + unsigned long actual_size; + unsigned char *data = 0; + ptrdiff_t bytes = 0; + Lisp_Object val; + GdkDisplay *display = dpyinfo->display; + + pgtk_get_window_property (window, &data, &bytes, + &actual_type, &actual_format, + &actual_size); + + if (!data) + { + if (for_multiple) + return Qnil; + + if (gdk_selection_owner_get_for_display (display, selection_atom)) + { + AUTO_STRING (format, "Selection owner couldn't convert: %s"); + CALLN (Fmessage, format, + actual_type + ? list2 (target_type, + gdk_atom_to_symbol (actual_type)) + : target_type); + return Qnil; + } + else + { + AUTO_STRING (format, "No selection: %s"); + CALLN (Fmessage, format, + gdk_atom_to_symbol (selection_atom)); + return Qnil; + } + } - targets = gtk_target_table_new_from_list (list, &n_targets); + if (!for_multiple && property != GDK_NONE) + gdk_property_delete (window, property); - int size = SBYTES (value); - gchar *str = xmalloc (size + 1); - memcpy (str, SSDATA (value), size); - str[size] = '\0'; + /* It's been read. Now convert it to a lisp object in some semi-rational + manner. */ + val = selection_data_to_lisp_data (dpyinfo, data, bytes, + actual_type, actual_format); - widget = FRAME_GTK_WIDGET (f); - g_object_set_qdata_full (G_OBJECT (widget), quark_data, str, xfree); - g_object_set_qdata_full (G_OBJECT (widget), quark_size, - GSIZE_TO_POINTER (size), NULL); + /* Use xfree, not g_free, because pgtk_get_window_property calls + xmalloc itself. */ + xfree (data); + return val; +} + + + +/* These functions convert from the selection data read from the + server into something that we can use from Lisp, and vice versa. + + Type: Format: Size: Lisp Type: + ----- ------- ----- ----------- + * 8 * String + ATOM 32 1 Symbol + ATOM 32 > 1 Vector of Symbols + * 16 1 Integer + * 16 > 1 Vector of Integers + * 32 1 if small enough: fixnum + otherwise: bignum + * 32 > 1 Vector of the above + + When converting an object to C, it may be of the form (SYMBOL + . ) where SYMBOL is what we should claim that the type is. + Format and representation are as above. + + Important: When format is 32, data should contain an array of int, + not an array of long as GDK returns. Unless TYPE is also + GDK_SELECTION_TYPE_ATOM, in which case data should be an array of + GdkAtom. This makes a difference when sizeof (long) != sizeof + (int). */ + +static Lisp_Object +selection_data_to_lisp_data (struct pgtk_display_info *dpyinfo, + const unsigned char *data, + ptrdiff_t size, GdkAtom type, int format) +{ + if (type == gdk_atom_intern_static_string ("NULL")) + return QNULL; + /* Convert any 8-bit data to a string, for compactness. */ + else if (format == 8) + { + Lisp_Object str, lispy_type; + + str = make_unibyte_string ((char *) data, size); + /* Indicate that this string is from foreign selection by a text + property `foreign-selection' so that the caller of + x-get-selection-internal (usually x-get-selection) can know + that the string must be decode. */ + if (type == gdk_atom_intern_static_string ("COMPOUND_TEXT")) + lispy_type = QCOMPOUND_TEXT; + else if (type == gdk_atom_intern_static_string ("UTF8_STRING")) + lispy_type = QUTF8_STRING; + else + lispy_type = QSTRING; + + Fput_text_property (make_fixnum (0), make_fixnum (size), + Qforeign_selection, lispy_type, str); + return str; + } + /* Convert a single atom to a Lisp_Symbol. Convert a set of atoms to + a vector of symbols. */ + else if (format == 32 + && (type == GDK_SELECTION_TYPE_ATOM + /* Treat ATOM_PAIR type similar to list of atoms. */ + || type == gdk_atom_intern_static_string ("ATOM_PAIR"))) + { + ptrdiff_t i; + GdkAtom *idata = (GdkAtom *) data; - if (gtk_clipboard_set_with_owner (cb, - targets, n_targets, - get_func, clear_func, - G_OBJECT (FRAME_GTK_WIDGET (f)))) + if (size == sizeof (GdkAtom)) + return gdk_atom_to_symbol (idata[0]); + else { - successful_p = Qt; + Lisp_Object v = make_nil_vector (size / sizeof (GdkAtom)); + + for (i = 0; i < size / sizeof (GdkAtom); i++) + ASET (v, i, gdk_atom_to_symbol (idata[i])); + return v; } - gtk_clipboard_set_can_store (cb, NULL, 0); + } + + /* Convert a single 16-bit number or a small 32-bit number to a Lisp_Int. + If the number is 32 bits and won't fit in a Lisp_Int, convert it + to a bignum. - gtk_target_table_free (targets, n_targets); - gtk_target_list_unref (list); + INTEGER is a signed type, CARDINAL is unsigned. + Assume any other types are unsigned as well. + */ + else if (format == 32 && size == sizeof (int)) + { + if (type == GDK_SELECTION_TYPE_INTEGER) + return INT_TO_INTEGER (((int *) data) [0]); + else + return INT_TO_INTEGER (((unsigned int *) data) [0]); + } + else if (format == 16 && size == sizeof (short)) + { + if (type == GDK_SELECTION_TYPE_INTEGER) + return make_fixnum (((short *) data) [0]); + else + return make_fixnum (((unsigned short *) data) [0]); + } + /* Convert any other kind of data to a vector of numbers, represented + as above (as an integer, or a cons of two 16 bit integers.) + */ + else if (format == 16) + { + ptrdiff_t i; + Lisp_Object v = make_uninit_vector (size / 2); + + if (type == GDK_SELECTION_TYPE_INTEGER) + { + for (i = 0; i < size / 2; i++) + { + short j = ((short *) data) [i]; + ASET (v, i, make_fixnum (j)); + } + } + else + { + for (i = 0; i < size / 2; i++) + { + unsigned short j = ((unsigned short *) data) [i]; + ASET (v, i, make_fixnum (j)); + } + } + return v; } + else + { + ptrdiff_t i; + Lisp_Object v = make_nil_vector (size / sizeof (gint)); + + if (type == GDK_SELECTION_TYPE_INTEGER) + { + for (i = 0; i < size / sizeof (gint); i++) + { + int j = ((gint *) data) [i]; + ASET (v, i, INT_TO_INTEGER (j)); + } + } + else + { + for (i = 0; i < size / sizeof (gint); i++) + { + unsigned int j = ((unsigned int *) data) [i]; + ASET (v, i, INT_TO_INTEGER (j)); + } + } + return v; + } +} + +/* Convert OBJ to an X long value, and return it as unsigned long. + OBJ should be an integer or a cons representing an integer. + Treat values in the range X_LONG_MAX + 1 .. X_ULONG_MAX as X + unsigned long values: in theory these values are supposed to be + signed but in practice unsigned 32-bit data are communicated via X + selections and we need to support that. */ +static unsigned long +cons_to_gdk_long (Lisp_Object obj) +{ + if (G_MAXUINT32 <= INTMAX_MAX + || NILP (Fnatnump (CONSP (obj) ? XCAR (obj) : obj))) + return cons_to_signed (obj, 0, min (G_MAXUINT32, INTMAX_MAX)); + else + return cons_to_unsigned (obj, G_MAXUINT32); +} + +/* Use xfree, not XFree, to free the data obtained with this function. */ + +static void +lisp_data_to_selection_data (struct pgtk_display_info *dpyinfo, + Lisp_Object obj, struct selection_data *cs) +{ + Lisp_Object type = Qnil; - if (!BASE_EQ (Vpgtk_sent_selection_hooks, Qunbound)) + eassert (cs != NULL); + cs->nofree = false; + + if (CONSP (obj) && SYMBOLP (XCAR (obj))) { - /* FIXME: Use run-hook-with-args! */ - for (rest = Vpgtk_sent_selection_hooks; CONSP (rest); - rest = Fcdr (rest)) - call3 (Fcar (rest), selection, target_symbol, successful_p); + type = XCAR (obj); + obj = XCDR (obj); + if (CONSP (obj) && NILP (XCDR (obj))) + obj = XCAR (obj); } + if (EQ (obj, QNULL) || (EQ (type, QNULL))) + { /* This is not the same as declining */ + cs->format = 32; + cs->size = 0; + cs->data = NULL; + type = QNULL; + } + else if (STRINGP (obj)) + { + if (SCHARS (obj) < SBYTES (obj)) + /* OBJ is a multibyte string containing a non-ASCII char. */ + signal_error ("Non-ASCII string must be encoded in advance", obj); + if (NILP (type)) + type = QSTRING; + cs->format = 8; + cs->size = SBYTES (obj); + cs->data = SDATA (obj); + cs->nofree = true; + } + else if (SYMBOLP (obj)) + { + void *data = xmalloc (sizeof (GdkAtom) + 1); + GdkAtom *x_atom_ptr = data; + cs->data = data; + cs->format = 32; + cs->size = 1; + cs->data[sizeof (GdkAtom)] = 0; + *x_atom_ptr = symbol_to_gdk_atom (obj); + if (NILP (type)) type = QATOM; + } + else if (RANGED_FIXNUMP (SHRT_MIN, obj, SHRT_MAX)) + { + void *data = xmalloc (sizeof (short) + 1); + short *short_ptr = data; + cs->data = data; + cs->format = 16; + cs->size = 1; + cs->data[sizeof (short)] = 0; + *short_ptr = XFIXNUM (obj); + if (NILP (type)) type = QINTEGER; + } + else if (INTEGERP (obj) + || (CONSP (obj) && INTEGERP (XCAR (obj)) + && (FIXNUMP (XCDR (obj)) + || (CONSP (XCDR (obj)) + && FIXNUMP (XCAR (XCDR (obj))))))) + { + void *data = xmalloc (sizeof (unsigned long) + 1); + unsigned long *x_long_ptr = data; + cs->data = data; + cs->format = 32; + cs->size = 1; + cs->data[sizeof (unsigned long)] = 0; + *x_long_ptr = cons_to_gdk_long (obj); + if (NILP (type)) type = QINTEGER; + } + else if (VECTORP (obj)) + { + /* Lisp_Vectors may represent a set of ATOMs; + a set of 16 or 32 bit INTEGERs; + or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...] + */ + ptrdiff_t i; + ptrdiff_t size = ASIZE (obj); + + if (SYMBOLP (AREF (obj, 0))) + /* This vector is an ATOM set */ + { + void *data; + GdkAtom *x_atoms; + if (NILP (type)) type = QATOM; + for (i = 0; i < size; i++) + if (!SYMBOLP (AREF (obj, i))) + signal_error ("All elements of selection vector must have same type", obj); + + cs->data = data = xnmalloc (size, sizeof *x_atoms); + x_atoms = data; + cs->format = 32; + cs->size = size; + for (i = 0; i < size; i++) + x_atoms[i] = symbol_to_gdk_atom (AREF (obj, i)); + } + else + /* This vector is an INTEGER set, or something like it */ + { + int format = 16; + int data_size = sizeof (short); + void *data; + unsigned long *x_atoms; + short *shorts; + if (NILP (type)) type = QINTEGER; + for (i = 0; i < size; i++) + { + if (! RANGED_FIXNUMP (SHRT_MIN, AREF (obj, i), SHRT_MAX)) + { + /* Use sizeof (long) even if it is more than 32 bits. + See comment in x_get_window_property and + x_fill_property_data. */ + data_size = sizeof (long); + format = 32; + break; + } + } + cs->data = data = xnmalloc (size, data_size); + x_atoms = data; + shorts = data; + cs->format = format; + cs->size = size; + for (i = 0; i < size; i++) + { + if (format == 32) + x_atoms[i] = cons_to_gdk_long (AREF (obj, i)); + else + shorts[i] = XFIXNUM (AREF (obj, i)); + } + } + } + else + signal_error (/* Qselection_error */ "Unrecognized selection data", obj); + + cs->type = symbol_to_gdk_atom (type); +} + +static Lisp_Object +clean_local_selection_data (Lisp_Object obj) +{ + if (CONSP (obj) + && INTEGERP (XCAR (obj)) + && CONSP (XCDR (obj)) + && FIXNUMP (XCAR (XCDR (obj))) + && NILP (XCDR (XCDR (obj)))) + obj = Fcons (XCAR (obj), XCDR (obj)); + + if (CONSP (obj) + && INTEGERP (XCAR (obj)) + && FIXNUMP (XCDR (obj))) + { + if (BASE_EQ (XCAR (obj), make_fixnum (0))) + return XCDR (obj); + if (BASE_EQ (XCAR (obj), make_fixnum (-1))) + return make_fixnum (- XFIXNUM (XCDR (obj))); + } + if (VECTORP (obj)) + { + ptrdiff_t i; + ptrdiff_t size = ASIZE (obj); + Lisp_Object copy; + if (size == 1) + return clean_local_selection_data (AREF (obj, 0)); + copy = make_nil_vector (size); + for (i = 0; i < size; i++) + ASET (copy, i, clean_local_selection_data (AREF (obj, i))); + return copy; + } + return obj; +} + +DEFUN ("pgtk-own-selection-internal", Fpgtk_own_selection_internal, + Spgtk_own_selection_internal, 2, 3, 0, + doc: /* Assert a selection of type SELECTION and value VALUE. +SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. +\(Those are literal upper-case symbol names, since that's what GDK expects.) +VALUE is typically a string, or a cons of two markers, but may be +anything that the functions on `selection-converter-alist' know about. + +FRAME should be a frame that should own the selection. If omitted or +nil, it defaults to the selected frame. */) + (Lisp_Object selection, Lisp_Object value, Lisp_Object frame) +{ + if (NILP (frame)) frame = selected_frame; + if (!FRAME_LIVE_P (XFRAME (frame)) || !FRAME_PGTK_P (XFRAME (frame))) + error ("GDK selection unavailable for this frame"); + + CHECK_SYMBOL (selection); + if (NILP (value)) error ("VALUE may not be nil"); + pgtk_own_selection (selection, value, frame); return value; } +/* Request the selection value from the owner. If we are the owner, + simply return our selection value. If we are not the owner, this + will block until all of the data has arrived. */ -DEFUN ("pgtk-disown-selection-internal", Fpgtk_disown_selection_internal, - Spgtk_disown_selection_internal, 1, 2, 0, - doc: /* If we own the selection SELECTION, disown it. -Disowning it means there is no such selection. +DEFUN ("pgtk-get-selection-internal", Fpgtk_get_selection_internal, + Spgtk_get_selection_internal, 2, 4, 0, + doc: /* Return text selected from some X window. +SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. +\(Those are literal upper-case symbol names, since that's what X expects.) +TARGET-TYPE is the type of data desired, typically `STRING'. + +TIME-STAMP is the time to use in the XConvertSelection call for foreign +selections. If omitted, defaults to the time for the last event. TERMINAL should be a terminal object or a frame specifying the X server to query. If omitted or nil, that stands for the selected frame's display, or the first available X display. */) - (Lisp_Object selection, Lisp_Object terminal) + (Lisp_Object selection_symbol, Lisp_Object target_type, + Lisp_Object time_stamp, Lisp_Object terminal) { + Lisp_Object val = Qnil; + Lisp_Object maybe_alias; struct frame *f = frame_for_pgtk_selection (terminal); - GtkClipboard *cb; - if (!pgtk_selection_usable ()) - return Qnil; + CHECK_SYMBOL (selection_symbol); + CHECK_SYMBOL (target_type); + if (EQ (target_type, QMULTIPLE)) + error ("Retrieving MULTIPLE selections is currently unimplemented"); if (!f) - return Qnil; + error ("GDK selection unavailable for this frame"); - cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection); + /* Quitting inside this function is okay, so we don't have to use + FOR_EACH_TAIL_SAFE. */ + maybe_alias = Fassq (selection_symbol, Vpgtk_selection_alias_alist); - gtk_clipboard_clear (cb); + if (!NILP (maybe_alias)) + { + selection_symbol = XCDR (maybe_alias); + CHECK_SYMBOL (selection_symbol); + } - return Qt; + val = pgtk_get_local_selection (selection_symbol, target_type, true, + FRAME_DISPLAY_INFO (f)); + + if (NILP (val) && FRAME_LIVE_P (f)) + { + Lisp_Object frame; + XSETFRAME (frame, f); + return pgtk_get_foreign_selection (selection_symbol, target_type, + time_stamp, frame); + } + + if (CONSP (val) && SYMBOLP (XCAR (val))) + { + val = XCDR (val); + if (CONSP (val) && NILP (XCDR (val))) + val = XCAR (val); + } + return clean_local_selection_data (val); } +DEFUN ("pgtk-disown-selection-internal", Fpgtk_disown_selection_internal, + Spgtk_disown_selection_internal, 1, 3, 0, + doc: /* If we own the selection SELECTION, disown it. +Disowning it means there is no such selection. -DEFUN ("pgtk-selection-exists-p", Fpgtk_selection_exists_p, Spgtk_selection_exists_p, 0, 2, 0, - doc: /* Whether there is an owner for the given X selection. -SELECTION should be the name of the selection in question, typically -one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. (X expects -these literal upper-case names.) The symbol nil is the same as -`PRIMARY', and t is the same as `SECONDARY'. +Sets the last-change time for the selection to TIME-OBJECT (by default +the time of the last event). TERMINAL should be a terminal object or a frame specifying the X server to query. If omitted or nil, that stands for the selected -frame's display, or the first available X display. - -On Nextstep, TERMINAL is unused. */) - (Lisp_Object selection, Lisp_Object terminal) +frame's display, or the first available X display. */) + (Lisp_Object selection, Lisp_Object time_object, Lisp_Object terminal) { + guint32 timestamp; + GdkAtom selection_atom; struct frame *f = frame_for_pgtk_selection (terminal); - GtkClipboard *cb; + struct pgtk_display_info *dpyinfo; - if (!pgtk_selection_usable ()) + if (!f) return Qnil; - if (!f) + dpyinfo = FRAME_DISPLAY_INFO (f); + CHECK_SYMBOL (selection); + + /* Don't disown the selection when we're not the owner. */ + if (NILP (LOCAL_SELECTION (selection, dpyinfo))) return Qnil; - cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection); + selection_atom = symbol_to_gdk_atom (selection); - return gtk_clipboard_wait_is_text_available (cb) ? Qt : Qnil; -} + block_input (); + if (NILP (time_object)) + timestamp = dpyinfo->last_user_time; + else + CONS_TO_INTEGER (time_object, guint32, timestamp); + gdk_selection_owner_set_for_display (dpyinfo->display, NULL, + selection_atom, timestamp, + TRUE); + unblock_input (); + return Qt; +} -DEFUN ("pgtk-selection-owner-p", Fpgtk_selection_owner_p, Spgtk_selection_owner_p, 0, 2, 0, - doc: /* Whether the current Emacs process owns the given X Selection. +DEFUN ("pgtk-selection-owner-p", Fpgtk_selection_owner_p, Spgtk_selection_owner_p, + 0, 2, 0, + doc: /* Whether the current Emacs process owns the given selection. The arg should be the name of the selection in question, typically one of the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'. -\(Those are literal upper-case symbol names, since that's what X expects.) +\(Those are literal upper-case symbol names, since that's what GDK expects.) For convenience, the symbol nil is the same as `PRIMARY', and t is the same as `SECONDARY'. -TERMINAL should be a terminal object or a frame specifying the X +TERMINAL should be a terminal object or a frame specifying the GDK server to query. If omitted or nil, that stands for the selected -frame's display, or the first available X display. - -On Nextstep, TERMINAL is unused. */) +frame's display, or the first available X display. */) (Lisp_Object selection, Lisp_Object terminal) { struct frame *f = frame_for_pgtk_selection (terminal); - GtkClipboard *cb; - GObject *obj; - GQuark quark_data, quark_size; - - if (!pgtk_selection_usable ()) - return Qnil; - cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection); - selection_type_to_quarks (gtk_clipboard_get_selection (cb), &quark_data, - &quark_size); + CHECK_SYMBOL (selection); + if (NILP (selection)) selection = QPRIMARY; + if (EQ (selection, Qt)) selection = QSECONDARY; - obj = gtk_clipboard_get_owner (cb); - - return obj && g_object_get_qdata (obj, quark_data) != NULL ? Qt : Qnil; + if (f && !NILP (LOCAL_SELECTION (selection, FRAME_DISPLAY_INFO (f)))) + return Qt; + else + return Qnil; } +DEFUN ("pgtk-selection-exists-p", Fpgtk_selection_exists_p, Spgtk_selection_exists_p, + 0, 2, 0, + doc: /* Whether there is an owner for the given selection. +SELECTION should be the name of the selection in question, typically +one of the symbols `PRIMARY', `SECONDARY', `CLIPBOARD', or +`CLIPBOARD_MANAGER' (GDK expects these literal upper-case names.) The +symbol nil is the same as `PRIMARY', and t is the same as `SECONDARY'. -DEFUN ("pgtk-get-selection-internal", Fpgtk_get_selection_internal, - Spgtk_get_selection_internal, 2, 3, 0, - doc: /* Return text selected from some program. -SELECTION-SYMBOL is typically `PRIMARY', `SECONDARY', or `CLIPBOARD'. -\(Those are literal upper-case symbol names, since that's what X expects.) -TARGET-TYPE is the type of data desired, typically `STRING'. - -TERMINAL should be a terminal object or a frame specifying the X +TERMINAL should be a terminal object or a frame specifying the GDK server to query. If omitted or nil, that stands for the selected -frame's display, or the first available display. */) - (Lisp_Object selection_symbol, Lisp_Object target_type, - Lisp_Object terminal) +frame's display, or the first available X display. */) + (Lisp_Object selection, Lisp_Object terminal) { + GdkWindow *owner; + GdkAtom atom; struct frame *f = frame_for_pgtk_selection (terminal); - GtkClipboard *cb; + struct pgtk_display_info *dpyinfo; - CHECK_SYMBOL (selection_symbol); - CHECK_SYMBOL (target_type); + CHECK_SYMBOL (selection); + if (NILP (selection)) selection = QPRIMARY; + if (EQ (selection, Qt)) selection = QSECONDARY; - if (EQ (target_type, QMULTIPLE)) - error ("Retrieving MULTIPLE selections is currently unimplemented"); if (!f) - error ("PGTK selection unavailable for this frame"); - - if (!pgtk_selection_usable ()) return Qnil; - cb = symbol_to_gtk_clipboard (FRAME_GTK_WIDGET (f), selection_symbol); - - GdkAtom target_atom = gdk_atom_intern (SSDATA (SYMBOL_NAME (target_type)), false); - GtkSelectionData *seldata = gtk_clipboard_wait_for_contents (cb, target_atom); + dpyinfo = FRAME_DISPLAY_INFO (f); - if (seldata == NULL) - return Qnil; + if (!NILP (LOCAL_SELECTION (selection, dpyinfo))) + return Qt; - const guchar *sd_data = gtk_selection_data_get_data (seldata); - int sd_len = gtk_selection_data_get_length (seldata); - int sd_format = gtk_selection_data_get_format (seldata); - GdkAtom sd_type = gtk_selection_data_get_data_type (seldata); + atom = symbol_to_gdk_atom (selection); + if (atom == 0) return Qnil; + block_input (); + owner = gdk_selection_owner_get_for_display (dpyinfo->display, atom); + unblock_input (); + return (owner ? Qt : Qnil); +} - if (sd_format == 8) - { - Lisp_Object str, lispy_type; +/* Called to handle GDK_SELECTION_NOTIFY events. + If it's the selection we are waiting for, stop waiting + by setting the car of reading_selection_reply to non-nil. + We store t there if the reply is successful, lambda if not. */ - str = make_unibyte_string ((char *) sd_data, sd_len); - /* Indicate that this string is from foreign selection by a text - property `foreign-selection' so that the caller of - x-get-selection-internal (usually x-get-selection) can know - that the string must be decode. */ - if (sd_type == gdk_atom_intern ("COMPOUND_TEXT", false)) - lispy_type = QCOMPOUND_TEXT; - else if (sd_type == gdk_atom_intern ("UTF8_STRING", false)) - lispy_type = QUTF8_STRING; - else if (sd_type == gdk_atom_intern ("text/plain;charset=utf-8", false)) - lispy_type = Qtext_plain_charset_utf_8; - else - lispy_type = QSTRING; - Fput_text_property (make_fixnum (0), make_fixnum (sd_len), - Qforeign_selection, lispy_type, str); +void +pgtk_handle_selection_notify (GdkEventSelection *event) +{ + /* GDK doesn't populate event->requestor, contrary to what the ICCCM + says should be done with SelectionNotify events. */ - gtk_selection_data_free (seldata); - return str; - } + if (event->selection != reading_which_selection) + return; - gtk_selection_data_free (seldata); - return Qnil; + XSETCAR (reading_selection_reply, + (event->property != GDK_NONE ? Qt : Qlambda)); } void @@ -499,7 +1769,19 @@ syms_of_pgtkselect (void) DEFSYM (QSECONDARY, "SECONDARY"); DEFSYM (QTEXT, "TEXT"); DEFSYM (QFILE_NAME, "FILE_NAME"); + DEFSYM (QSTRING, "STRING"); + DEFSYM (QINTEGER, "INTEGER"); + DEFSYM (QTIMESTAMP, "TIMESTAMP"); + DEFSYM (QTEXT, "TEXT"); DEFSYM (QMULTIPLE, "MULTIPLE"); + DEFSYM (QNULL, "NULL"); + DEFSYM (QATOM, "ATOM"); + DEFSYM (QTARGETS, "TARGETS"); + + DEFSYM (Qpgtk_sent_selection_functions, + "pgtk-sent-selection-functions"); + DEFSYM (Qpgtk_lost_selection_functions, + "pgtk-lost-selection-functions"); DEFSYM (Qforeign_selection, "foreign-selection"); DEFSYM (QUTF8_STRING, "UTF8_STRING"); @@ -513,6 +1795,32 @@ syms_of_pgtkselect (void) defsubr (&Spgtk_selection_exists_p); defsubr (&Spgtk_selection_owner_p); + DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist, + doc: /* SKIP: real doc in xselect.c. */); + Vselection_converter_alist = Qnil; + + DEFVAR_LISP ("pgtk-lost-selection-functions", Vpgtk_lost_selection_functions, + doc: /* A list of functions to be called when Emacs loses a selection. +\(This happens when some other client makes its own selection +or when a Lisp program explicitly clears the selection.) +The functions are called with one argument, the selection type +\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'). */); + Vpgtk_lost_selection_functions = Qnil; + + DEFVAR_LISP ("pgtk-sent-selection-functions", Vpgtk_sent_selection_functions, + doc: /* A list of functions to be called when Emacs answers a selection request. +The functions are called with three arguments: + - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD'); + - the selection-type which Emacs was asked to convert the + selection into before sending (for example, `STRING' or `LENGTH'); + - a flag indicating success or failure for responding to the request. +We might have failed (and declined the request) for any number of reasons, +including being asked for a selection that we no longer own, or being asked +to convert into a type that we don't know about or that is inappropriate. +This hook doesn't let you change the behavior of Emacs's selection replies, +it merely informs you that they have happened. */); + Vpgtk_sent_selection_functions = Qnil; + DEFVAR_LISP ("pgtk-sent-selection-hooks", Vpgtk_sent_selection_hooks, doc: /* A list of functions to be called when Emacs answers a selection request The functions are called with four arguments: @@ -533,4 +1841,19 @@ This may cause crashes due to a GTK bug, which assumes that clients will connect to a single display. It might also cause selections to not arrive at the correct display. */); pgtk_enable_selection_on_multi_display = false; + + DEFVAR_LISP ("pgtk-selection-alias-alist", Vpgtk_selection_alias_alist, + doc: /* List of selections to alias to another. +It should be an alist of a selection name to another. When a +selection request arrives for the first selection, Emacs will respond +as if the request was meant for the other. + +Note that this does not affect setting or owning selections. */); + Vpgtk_selection_alias_alist = Qnil; + + reading_selection_reply = Fcons (Qnil, Qnil); + staticpro (&reading_selection_reply); + + property_change_reply = Fcons (Qnil, Qnil); + staticpro (&property_change_reply); } diff --git a/src/pgtkselect.h b/src/pgtkselect.h deleted file mode 100644 index fd9910b2d1..0000000000 --- a/src/pgtkselect.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Definitions and headers for selection of pure Gtk+3. - Copyright (C) 1989, 1993, 2005, 2008-2022 Free Software Foundation, - Inc. - -This file is part of GNU Emacs. - -GNU Emacs is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or (at -your option) any later version. - -GNU Emacs is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Emacs. If not, see . */ - - -#include "dispextern.h" -#include "frame.h" - -#ifdef HAVE_PGTK - -#include - -extern void pgtk_selection_init (void); -extern void pgtk_selection_lost (GtkWidget *, GdkEventSelection *, gpointer); - -#endif /* HAVE_PGTK */ diff --git a/src/pgtkterm.c b/src/pgtkterm.c index da958a6664..91874ff58a 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -61,7 +61,6 @@ along with GNU Emacs. If not, see . */ #include "buffer.h" #include "font.h" #include "xsettings.h" -#include "pgtkselect.h" #include "emacsgtkfixed.h" #ifdef GDK_WINDOWING_WAYLAND @@ -290,6 +289,9 @@ static void evq_enqueue (union buffered_input_event *ev) { struct event_queue_t *evq = &event_q; + struct frame *frame; + struct pgtk_display_info *dpyinfo; + if (evq->cap == 0) { evq->cap = 4; @@ -303,6 +305,27 @@ evq_enqueue (union buffered_input_event *ev) } evq->q[evq->nr++] = *ev; + + if (ev->ie.kind != SELECTION_REQUEST_EVENT + && ev->ie.kind != SELECTION_CLEAR_EVENT) + { + frame = NULL; + + if (WINDOWP (ev->ie.frame_or_window)) + frame = WINDOW_XFRAME (XWINDOW (ev->ie.frame_or_window)); + + if (FRAMEP (ev->ie.frame_or_window)) + frame = XFRAME (ev->ie.frame_or_window); + + if (frame) + { + dpyinfo = FRAME_DISPLAY_INFO (frame); + + if (dpyinfo->last_user_time < ev->ie.timestamp) + dpyinfo->last_user_time = ev->ie.timestamp; + } + } + raise (SIGIO); } @@ -4809,16 +4832,16 @@ pgtk_any_window_to_frame (GdkWindow *window) return NULL; FOR_EACH_FRAME (tail, frame) - { - if (found) - break; - f = XFRAME (frame); - if (FRAME_PGTK_P (f)) - { - if (pgtk_window_is_of_frame (f, window)) - found = f; - } - } + { + if (found) + break; + f = XFRAME (frame); + if (FRAME_PGTK_P (f)) + { + if (pgtk_window_is_of_frame (f, window)) + found = f; + } + } return found; } @@ -5868,8 +5891,7 @@ construct_mouse_click (struct input_event *result, } static gboolean -button_event (GtkWidget *widget, - GdkEvent *event, +button_event (GtkWidget *widget, GdkEvent *event, gpointer *user_data) { union buffered_input_event inev; @@ -6174,6 +6196,8 @@ pgtk_monitors_changed_cb (GdkScreen *screen, gpointer user_data) evq_enqueue (&inev); } +static gboolean pgtk_selection_event (GtkWidget *, GdkEvent *, gpointer); + void pgtk_set_event_handler (struct frame *f) { @@ -6225,14 +6249,20 @@ pgtk_set_event_handler (struct frame *f) G_CALLBACK (button_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "scroll-event", G_CALLBACK (scroll_event), NULL); - g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event", - G_CALLBACK (pgtk_selection_lost), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "configure-event", G_CALLBACK (configure_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "drag-data-received", G_CALLBACK (drag_data_received), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "draw", G_CALLBACK (pgtk_handle_draw), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "property-notify-event", + G_CALLBACK (pgtk_selection_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-clear-event", + G_CALLBACK (pgtk_selection_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-request-event", + G_CALLBACK (pgtk_selection_event), NULL); + g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "selection-notify-event", + G_CALLBACK (pgtk_selection_event), NULL); g_signal_connect (G_OBJECT (FRAME_GTK_WIDGET (f)), "event", G_CALLBACK (pgtk_handle_event), NULL); } @@ -6292,6 +6322,73 @@ same_x_server (const char *name1, const char *name2) && (*name2 == '.' || *name2 == '\0')); } +static struct frame * +pgtk_find_selection_owner (GdkWindow *window) +{ + Lisp_Object tail, tem; + struct frame *f; + + FOR_EACH_FRAME (tail, tem) + { + f = XFRAME (tem); + + if (FRAME_PGTK_P (f) + && (FRAME_GDK_WINDOW (f) == window)) + return f; + } + + return NULL; +} + +static gboolean +pgtk_selection_event (GtkWidget *widget, GdkEvent *event, + gpointer user_data) +{ + struct frame *f; + union buffered_input_event inev; + + if (event->type == GDK_PROPERTY_NOTIFY) + pgtk_handle_property_notify (&event->property); + else if (event->type == GDK_SELECTION_CLEAR + || event->type == GDK_SELECTION_REQUEST) + { + f = pgtk_find_selection_owner (event->selection.window); + + if (f) + { + EVENT_INIT (inev.ie); + + inev.sie.kind = (event->type == GDK_SELECTION_CLEAR + ? SELECTION_CLEAR_EVENT + : SELECTION_REQUEST_EVENT); + + SELECTION_EVENT_DPYINFO (&inev.sie) = FRAME_DISPLAY_INFO (f); + SELECTION_EVENT_SELECTION (&inev.sie) = event->selection.selection; + SELECTION_EVENT_TIME (&inev.sie) = event->selection.time; + + if (event->type == GDK_SELECTION_REQUEST) + { + /* FIXME: when does GDK destroy the requestor GdkWindow + object? + + It would make sense to wait for the transfer to + complete. But I don't know if GDK actually does + that. */ + SELECTION_EVENT_REQUESTOR (&inev.sie) = event->selection.requestor; + SELECTION_EVENT_TARGET (&inev.sie) = event->selection.target; + SELECTION_EVENT_PROPERTY (&inev.sie) = event->selection.property; + } + + evq_enqueue (&inev); + return TRUE; + } + } + else if (event->type == GDK_SELECTION_NOTIFY) + pgtk_handle_selection_notify (&event->selection); + + return FALSE; +} + /* Open a connection to X display DISPLAY_NAME, and return the structure that describes the open display. If we cannot contact the display, return null. */ @@ -6525,8 +6622,6 @@ pgtk_term_init (Lisp_Object display_name, char *resource_name) xsettings_initialize (dpyinfo); - pgtk_selection_init (); - pgtk_im_init (dpyinfo); g_signal_connect (G_OBJECT (dpyinfo->gdpy), "seat-added", diff --git a/src/pgtkterm.h b/src/pgtkterm.h index e31e62ae19..86578be6b5 100644 --- a/src/pgtkterm.h +++ b/src/pgtkterm.h @@ -127,8 +127,14 @@ struct pgtk_display_info /* The generic display parameters corresponding to this PGTK display. */ struct terminal *terminal; - /* This says how to access this display in Gdk. */ - GdkDisplay *gdpy; + union + { + /* This says how to access this display through GDK. */ + GdkDisplay *gdpy; + + /* An alias defined to make porting X code easier. */ + GdkDisplay *display; + }; /* This is a cons cell of the form (NAME . FONT-LIST-CACHE). */ Lisp_Object name_list_element; @@ -210,6 +216,9 @@ struct pgtk_display_info /* Time of last mouse movement. */ Time last_mouse_movement_time; + /* Time of last user interaction. */ + guint32 last_user_time; + /* The scroll bar in which the last motion event occurred. */ void *last_mouse_scroll_bar; @@ -443,10 +452,11 @@ enum FRAME_GTK_OUTER_WIDGET (f) : \ FRAME_GTK_WIDGET (f)) -/* aliases */ #define FRAME_PGTK_VIEW(f) FRAME_GTK_WIDGET (f) #define FRAME_X_WINDOW(f) FRAME_GTK_OUTER_WIDGET (f) #define FRAME_NATIVE_WINDOW(f) GTK_WINDOW (FRAME_X_WINDOW (f)) +#define FRAME_GDK_WINDOW(f) \ + (gtk_widget_get_window (FRAME_GTK_WIDGET (f))) #define FRAME_X_DISPLAY(f) (FRAME_DISPLAY_INFO (f)->gdpy) @@ -484,6 +494,49 @@ enum #define FRAME_CR_SURFACE_DESIRED_HEIGHT(f) \ ((f)->output_data.pgtk->cr_surface_desired_height) + +/* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT + or SELECTION_CLEAR_EVENT, then its contents are really described + by this structure. */ + +/* For an event of kind SELECTION_REQUEST_EVENT, + this structure really describes the contents. */ + +struct selection_input_event +{ + ENUM_BF (event_kind) kind : EVENT_KIND_WIDTH; + struct pgtk_display_info *dpyinfo; + /* We spell it with an "o" here because X does. */ + GdkWindow *requestor; + GdkAtom selection, target, property; + guint32 time; +}; + +/* Unlike macros below, this can't be used as an lvalue. */ +INLINE GdkDisplay * +SELECTION_EVENT_DISPLAY (struct selection_input_event *ev) +{ + return ev->dpyinfo->display; +} +#define SELECTION_EVENT_DPYINFO(eventp) \ + ((eventp)->dpyinfo) +/* We spell it with an "o" here because X does. */ +#define SELECTION_EVENT_REQUESTOR(eventp) \ + ((eventp)->requestor) +#define SELECTION_EVENT_SELECTION(eventp) \ + ((eventp)->selection) +#define SELECTION_EVENT_TARGET(eventp) \ + ((eventp)->target) +#define SELECTION_EVENT_PROPERTY(eventp) \ + ((eventp)->property) +#define SELECTION_EVENT_TIME(eventp) \ + ((eventp)->time) + +extern void pgtk_handle_selection_event (struct selection_input_event *); +extern void pgtk_clear_frame_selections (struct frame *); +extern void pgtk_handle_property_notify (GdkEventProperty *); +extern void pgtk_handle_selection_notify (GdkEventSelection *); + /* Display init/shutdown functions implemented in pgtkterm.c */ extern struct pgtk_display_info *pgtk_term_init (Lisp_Object display_name, char *resource_name); @@ -493,7 +546,7 @@ extern void pgtk_term_shutdown (int sig); extern void pgtk_clear_frame (struct frame *f); extern char *pgtk_xlfd_to_fontname (const char *xlfd); -/* Implemented in pgtkfns. */ +/* Implemented in pgtkfns.c. */ extern void pgtk_set_doc_edited (void); extern const char *pgtk_get_defaults_value (const char *key); extern const char *pgtk_get_string_resource (XrmDatabase rdb, commit b1af8c2c00aefe6aa554a468e65b6e07c9f14722 Author: Eli Zaretskii Date: Tue Jun 21 16:21:53 2022 +0300 ; * doc/lispref/os.texi (Batch Mode): Fix typo and wording. diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 262ef8bbfd..2b49818ed3 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -2738,11 +2738,12 @@ if it is non-@code{nil}; this can be overridden by binding @code{coding-system-for-write} to a coding system of you choice (@pxref{Explicit Encoding}). -In batch mode, Emacs will adjust the @code{gc-cons-threshold} variable -up from a default of @samp{0.1} to @samp{1.0}. Batch jobs that are -supposed to run for a long time should adjust the limit back down -again, because this means that less garbage collection will be -performed by default (and more memory consumed). +In batch mode, Emacs will enlarge the value of the +@code{gc-cons-percentage} variable from the default of @samp{0.1} up to +@samp{1.0}. Batch jobs that are supposed to run for a long time +should adjust the limit back down again, because this means that less +garbage collection will be performed by default (and more memory +consumed). @defvar noninteractive This variable is non-@code{nil} when Emacs is running in batch mode. commit 49137311a432a0c3c4afef1ae7d463cd4c3613ae Author: Lars Ingebrigtsen Date: Tue Jun 21 15:11:28 2022 +0200 Fix previous -batch change for gc-cons-percentage * src/emacs.c (main): Reset the default for gc-cons-percentage in interactive Emacs. diff --git a/src/emacs.c b/src/emacs.c index c602157da1..37c6c76e7a 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1947,8 +1947,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem /* Do less garbage collection in batch mode (since these tend to be more short-lived, and the memory is returned to the OS on exit anyway). */ - if (noninteractive) - Vgc_cons_percentage = make_float (1.0); + Vgc_cons_percentage = make_float (noninteractive? 1.0: 0.1); no_loadup = argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args); commit 73a384a98698ae1ef655c41a2b76a31b3f2c80fc Author: Lars Ingebrigtsen Date: Tue Jun 21 15:04:27 2022 +0200 Increase gc-cons-percentage in -batch Emacs * doc/lispref/os.texi (Batch Mode): Document it. * src/emacs.c (main): Use a gc-cons-percentage of 1.0 in noninteractive Emacsen. diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index bc5374f10f..262ef8bbfd 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -2738,6 +2738,12 @@ if it is non-@code{nil}; this can be overridden by binding @code{coding-system-for-write} to a coding system of you choice (@pxref{Explicit Encoding}). +In batch mode, Emacs will adjust the @code{gc-cons-threshold} variable +up from a default of @samp{0.1} to @samp{1.0}. Batch jobs that are +supposed to run for a long time should adjust the limit back down +again, because this means that less garbage collection will be +performed by default (and more memory consumed). + @defvar noninteractive This variable is non-@code{nil} when Emacs is running in batch mode. @end defvar diff --git a/etc/NEWS b/etc/NEWS index fdc2e99ca4..cb59d166f7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -116,6 +116,14 @@ Emacs Sessions" node in the Emacs manual for more details. * Startup Changes in Emacs 29.1 ++++ +** -batch and -script now adjusts the garbage collection levels. +These switches now set 'gc-cons-percentage' to 1.0 (up from the +default of 0.1). This means that batch processes will typically use +more memory than before, but use less time doing garbage collection. +Batch jobs that are supposed to run for a long time should adjust the +limit back down again. + +++ ** Emacs can now be used more easily in an executable script. If you start an executable script with diff --git a/src/emacs.c b/src/emacs.c index 5098acd722..c602157da1 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1944,6 +1944,12 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem if (!initialized) syms_of_comp (); + /* Do less garbage collection in batch mode (since these tend to be + more short-lived, and the memory is returned to the OS on exit + anyway). */ + if (noninteractive) + Vgc_cons_percentage = make_float (1.0); + no_loadup = argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args); commit 0939465300f7c80f110c8596c0388f555619ea62 Author: Michael Albinus Date: Tue Jun 21 14:59:46 2022 +0200 Tramp code cleanup * lisp/net/tramp-adb.el (tramp-adb-handle-make-process): * lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Improve handling of "process-name" and "process-buffer" connection properties. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index ebcdf00c48..9981cc3c13 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -1048,8 +1048,7 @@ implementation will be used." ;; Save exit. (if (string-prefix-p tramp-temp-buffer-name (buffer-name)) (ignore-errors - (set-process-buffer - (tramp-get-connection-process v) nil) + (set-process-buffer p nil) (kill-buffer (current-buffer))) (set-buffer-modified-p bmp)))))))))))) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index eccc15efe7..f2e91a1977 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -2977,13 +2977,13 @@ implementation will be used." name1 (format "%s<%d>" name i))) (setq name name1) - (with-current-buffer (tramp-get-connection-buffer v) - (unwind-protect - (with-tramp-saved-connection-property v "process-name" - (with-tramp-saved-connection-property v "process-buffer" - ;; Set the new process properties. - (tramp-set-connection-property v "process-name" name) - (tramp-set-connection-property v "process-buffer" buffer) + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + ;; Set the new process properties. + (tramp-set-connection-property v "process-name" name) + (tramp-set-connection-property v "process-buffer" buffer) + (with-current-buffer (tramp-get-connection-buffer v) + (unwind-protect ;; We catch this event. Otherwise, ;; `make-process' could be called on the local ;; host. @@ -3049,6 +3049,10 @@ implementation will be used." (ignore-errors (set-process-query-on-exit-flag p (null noquery)) (set-marker (process-mark p) (point))) + ;; We must flush them here already; + ;; otherwise `delete-file' will fail. + (tramp-flush-connection-property v "process-name") + (tramp-flush-connection-property v "process-buffer") ;; Kill stderr process and delete named pipe. (when (bufferp stderr) (add-function @@ -3061,14 +3065,14 @@ implementation will be used." (ignore-errors (delete-file remote-tmpstderr))))) ;; Return process. - p))))) - - ;; Save exit. - (if (string-prefix-p tramp-temp-buffer-name (buffer-name)) - (ignore-errors - (set-process-buffer p nil) - (kill-buffer (current-buffer))) - (set-buffer-modified-p bmp)))))))))) + p))) + + ;; Save exit. + (if (string-prefix-p tramp-temp-buffer-name (buffer-name)) + (ignore-errors + (set-process-buffer p nil) + (kill-buffer (current-buffer))) + (set-buffer-modified-p bmp)))))))))))) (defun tramp-sh-get-signal-strings (vec) "Strings to return by `process-file' in case of signals." commit 32906819addde1aa952d4718699d332d3a58b004 Author: Stefan Kangas Date: Tue Jun 21 14:27:51 2022 +0200 Allow shortening filenames in recentf-mode menu * lisp/recentf.el (recentf-show-abbreviated): New function. (recentf--filter-names): New helper function. (recentf-show-basenames): Use above new helper function. (recentf-menu-filter): Allow setting user option to new value 'recentf-show-abbreviated'. diff --git a/etc/NEWS b/etc/NEWS index c54a1cc42a..fdc2e99ca4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1840,6 +1840,11 @@ Enabling this minor mode turns on hiding header material, like 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 'recentf-mode' menu can now use shortened filenames. +Set the user option 'recentf-menu-filter' to +'recentf-show-abbreviated' to enable it. + --- ** The autoarg.el library is now marked obsolete. This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor diff --git a/lisp/recentf.el b/lisp/recentf.el index 2de9831154..28aee0f17f 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -186,6 +186,8 @@ A nil value means no filter. The following functions are predefined: Sort menu items by directories in ascending order. - `recentf-sort-directories-descending' Sort menu items by directories in descending order. +- `recentf-show-abbreviated' + Show shortened filenames. - `recentf-show-basenames' Show filenames sans directory in menu items. - `recentf-show-basenames-ascending' @@ -214,6 +216,7 @@ elements (see `recentf-make-menu-element' for menu element form)." (function-item recentf-sort-basenames-descending) (function-item recentf-sort-directories-ascending) (function-item recentf-sort-directories-descending) + (function-item recentf-show-abbreviated) (function-item recentf-show-basenames) (function-item recentf-show-basenames-ascending) (function-item recentf-show-basenames-descending) @@ -724,14 +727,11 @@ Compares directories then filenames to order the list." (recentf-menu-element-value e2) (recentf-menu-element-value e1))))) -(defun recentf-show-basenames (l &optional no-dir) - "Filter the list of menu elements L to show filenames sans directory. -When a filename is duplicated, it is appended a sequence number if -optional argument NO-DIR is non-nil, or its directory otherwise." +(defun recentf--filter-names (l no-dir fun) (let (filtered-names filtered-list full name counters sufx) (dolist (elt l (nreverse filtered-list)) (setq full (recentf-menu-element-value elt) - name (file-name-nondirectory full)) + name (funcall fun full)) (if (not (member name filtered-names)) (push name filtered-names) (if no-dir @@ -743,6 +743,18 @@ optional argument NO-DIR is non-nil, or its directory otherwise." (setq name (format "%s(%s)" name sufx))) (push (recentf-make-menu-element name full) filtered-list)))) +(defun recentf-show-abbreviated (l &optional no-dir) + "Filter the list of menu elements L to show shortened filenames. +When a filename is duplicated, it is appended a sequence number if +optional argument NO-DIR is non-nil, or its directory otherwise." + (recentf--filter-names l no-dir #'abbreviate-file-name)) + +(defun recentf-show-basenames (l &optional no-dir) + "Filter the list of menu elements L to show filenames sans directory. +When a filename is duplicated, it is appended a sequence number if +optional argument NO-DIR is non-nil, or its directory otherwise." + (recentf--filter-names l no-dir #'file-name-nondirectory)) + (defsubst recentf-show-basenames-ascending (l) "Filter the list of menu elements L to show filenames sans directory. Filenames are sorted in ascending order. commit 3518ab51d1f08165c2eb74517873877a998e38a5 Author: Eli Zaretskii Date: Tue Jun 21 15:35:22 2022 +0300 ; * lwlib/xlwmenu.c (ungrab_all): Fix typo. diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c index f0625982cf..3c7a493616 100644 --- a/lwlib/xlwmenu.c +++ b/lwlib/xlwmenu.c @@ -254,7 +254,7 @@ static void ungrab_all (Widget w, Time ungrabtime) { XtUngrabPointer (w, ungrabtime); - if (!lucid__menu_grab_keyboard) + if (lucid__menu_grab_keyboard) XtUngrabKeyboard (w, ungrabtime); } commit 5082d74cfd512cf9c707ee22b85db3e94569fcd4 Author: Stefan Kangas Date: Tue Jun 21 14:20:22 2022 +0200 ; * lisp/recentf.el: Fix typo. diff --git a/lisp/recentf.el b/lisp/recentf.el index 2ee9717f4d..7a4b589e45 100644 --- a/lisp/recentf.el +++ b/lisp/recentf.el @@ -29,7 +29,7 @@ ;; automatically saved across Emacs sessions. ;; You can customize the number of recent files displayed, the -;; location of the menu and others options. Type: +;; location of the menu and other options. Type: ;; ;; M-x customize-group RET recentf RET commit 3f66e2a90392933e110a1a04f271c86b6eb179d5 Author: Stefan Kangas Date: Tue Jun 21 13:56:58 2022 +0200 * lisp/repeat.el (repeat-mode): Fix message format. diff --git a/lisp/repeat.el b/lisp/repeat.el index 040ce818a2..4d04f5ae95 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -418,7 +418,7 @@ See `describe-repeat-maps' for a list of all repeatable commands." (and (commandp s) (get s 'repeat-map) (push (get s 'repeat-map) keymaps)))))) - (message "Repeat mode is enabled for %d commands and %d keymaps; see `describe-repeat-maps'." + (message "Repeat mode is enabled for %d commands and %d keymaps; see `describe-repeat-maps'" (length commands) (length (delete-dups keymaps)))))) commit 3491c7a322dd3d7b67f52a90605181c51fbe5881 Author: kobarity Date: Tue Jun 21 13:37:08 2022 +0200 Fix nested defuns handling in `python-nav-beginning-of-defun' * lisp/progmodes/python.el (python-nav--beginning-of-defun): Fix handling of nested defuns (bug#56105). diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index c2483436fe..e0c937d7ce 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1455,11 +1455,17 @@ With positive ARG search backwards, else search forwards." (line-beg-pos (line-beginning-position)) (line-content-start (+ line-beg-pos (current-indentation))) (pos (point-marker)) + (min-indentation (+ (current-indentation) + (if (python-info-looking-at-beginning-of-defun) + python-indent-offset 0))) (body-indentation (and (> arg 0) (save-excursion (while (and - (not (python-info-looking-at-beginning-of-defun)) + (or (not (python-info-looking-at-beginning-of-defun)) + (>= (current-indentation) min-indentation)) + (setq min-indentation + (min min-indentation (current-indentation))) (python-nav-backward-block))) (or (and (python-info-looking-at-beginning-of-defun) (+ (current-indentation) python-indent-offset)) diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el index 8db0a07170..e17bc0df92 100644 --- a/test/lisp/progmodes/python-tests.el +++ b/test/lisp/progmodes/python-tests.el @@ -1736,6 +1736,27 @@ class C: (should (= (marker-position (mark-marker)) expected-mark-end-position))))) +(ert-deftest python-mark-defun-4 () + "Test `python-mark-defun' with nested functions." + (python-tests-with-temp-buffer + " +def foo(x): + def bar(): + return x + if True: + return bar +" + (let ((expected-mark-beginning-position + (progn + (python-tests-look-at "def foo(x):") + (1- (line-beginning-position)))) + (expected-mark-end-position (point-max))) + (python-tests-look-at "return bar") + (python-mark-defun 1) + (should (= (point) expected-mark-beginning-position)) + (should (= (marker-position (mark-marker)) + expected-mark-end-position))))) + ;;; Navigation @@ -1762,12 +1783,20 @@ def decoratorFunctionWithArguments(arg1, arg2, arg3): return wrapped_f return wwrap " - (python-tests-look-at "return wrap") + (python-tests-look-at "return wwrap") (should (= (save-excursion (python-nav-beginning-of-defun) (point)) (save-excursion - (python-tests-look-at "def wrapped_f(*args):" -1) + (python-tests-look-at "def decoratorFunctionWithArguments" -1) + (beginning-of-line) + (point)))) + (python-tests-look-at "return wrap" -1) + (should (= (save-excursion + (python-nav-beginning-of-defun) + (point)) + (save-excursion + (python-tests-look-at "def wwrap(f):" -1) (beginning-of-line) (point)))) (python-tests-look-at "def wrapped_f(*args):" -1) @@ -1801,11 +1830,23 @@ class C(object): def a(): pass + if True: + return a + def c(self): pass " ;; Nested defuns, are handled with care. (python-tests-look-at "def c(self):") + (should (= (save-excursion + (python-nav-beginning-of-defun) + (point)) + (save-excursion + (python-tests-look-at "def m(self):" -1) + (beginning-of-line) + (point)))) + ;; Nested defuns shuld be skipped. + (python-tests-look-at "return a" -1) (should (= (save-excursion (python-nav-beginning-of-defun) (point)) commit a5387dec4eb12ff668e531f323efd8b28540c9a2 Author: Lars Ingebrigtsen Date: Tue Jun 21 13:34:54 2022 +0200 Fix previous describe-key change * lisp/help.el (describe-function-orig-buffer): Ensure we bind dynamically. diff --git a/lisp/help.el b/lisp/help.el index 94747ff4b0..f14617b437 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -903,6 +903,9 @@ Describe the following key, mouse click, or menu item: " (setq yank-menu (copy-sequence saved-yank-menu)) (fset 'yank-menu (cons 'keymap yank-menu)))))) +;; Defined in help-fns.el. +(defvar describe-function-orig-buffer) + (defun describe-key (&optional key-list buffer up-event) "Display documentation of the function invoked by KEY-LIST. KEY-LIST can be any kind of a key sequence; it can include keyboard events, commit ef03c8852d064da127a1deea263b2dcec5ea5bf8 Author: Lars Ingebrigtsen Date: Tue Jun 21 13:33:02 2022 +0200 Make describe-key do doc string command key substitution again * lisp/help.el (describe-key): Do doc string command key substitution (bug#56106). diff --git a/lisp/help.el b/lisp/help.el index 1c46f25338..94747ff4b0 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -933,6 +933,7 @@ current buffer." (setq buffer nil)) (let* ((help-buffer-under-preparation t) (buf (or buffer (current-buffer))) + (describe-function-orig-buffer buf) (on-link (mapcar (lambda (kr) (let ((raw (cdr kr))) commit 7934bad23b248fb7be4669e486cdcb9cb2d6d73e Author: Lars Ingebrigtsen Date: Tue Jun 21 13:25:19 2022 +0200 Fix fontification in describe-key * lisp/help.el (describe-key): Use insert instead of princ so that text properties on the key descriptions survive. diff --git a/lisp/help.el b/lisp/help.el index 2d02b22e52..1c46f25338 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -966,16 +966,16 @@ current buffer." (with-help-window (help-buffer) (when (> (length info-list) 1) ;; FIXME: Make this into clickable hyperlinks. - (princ "There were several key-sequences:\n\n") - (princ (mapconcat (lambda (info) - (pcase-let ((`(,_seq ,brief-desc ,_defn ,_locus) - info)) - (concat " " brief-desc))) - info-list - "\n")) + (insert "There were several key-sequences:\n\n") + (insert (mapconcat (lambda (info) + (pcase-let ((`(,_seq ,brief-desc ,_defn ,_locus) + info)) + (concat " " brief-desc))) + info-list + "\n")) (when (delq nil on-link) - (princ "\n\nThose are influenced by `mouse-1-click-follows-link'")) - (princ "\n\nThey're all described below.")) + (insert "\n\nThose are influenced by `mouse-1-click-follows-link'")) + (insert "\n\nThey're all described below.")) (pcase-dolist (`(,_seq ,brief-desc ,defn ,locus) info-list) (when defn @@ -983,10 +983,10 @@ current buffer." (with-current-buffer standard-output (insert "\n\n" (make-separator-line) "\n"))) - (princ brief-desc) + (insert brief-desc) (when locus - (princ (format " (found in %s)" locus))) - (princ ", which is ") + (insert (format " (found in %s)" locus))) + (insert ", which is ") (describe-function-1 defn))))))) (defun search-forward-help-for-help () commit 97950f2bc4cda476d540037b59cf1f90fcb9bc0a Author: Kevin Brubeck Unhammer Date: Tue Jun 21 13:02:05 2022 +0200 Speed up mail-extr in some configurations * lisp/mail/mail-extr.el (mail-extract-address-components): (mail-extract-address-components): The buffer is already in fundamental-mode, so don't re-enable it (bug#56113). diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el index 50ba04ccc1..c87ea2b46e 100644 --- a/lisp/mail/mail-extr.el +++ b/lisp/mail/mail-extr.el @@ -716,7 +716,6 @@ to the results." value-list) (with-current-buffer (get-buffer-create extraction-buffer) - (fundamental-mode) (buffer-disable-undo extraction-buffer) (set-syntax-table mail-extr-address-syntax-table) (widen) @@ -738,7 +737,6 @@ to the results." (set-text-properties (point-min) (point-max) nil) (with-current-buffer (get-buffer-create canonicalization-buffer) - (fundamental-mode) (buffer-disable-undo canonicalization-buffer) (setq case-fold-search nil)) commit 137539c1250a62dd9952a3fd5451d00d76ab42a9 Author: Earl Hyatt Date: Tue Jun 21 12:52:28 2022 +0200 Clarify autotype.texi text slightly * doc/misc/autotype.texi (Autoinserting): Make text slightly clearer (bug#56118). diff --git a/doc/misc/autotype.texi b/doc/misc/autotype.texi index a3b0f16df9..a880642ac3 100644 --- a/doc/misc/autotype.texi +++ b/doc/misc/autotype.texi @@ -276,7 +276,7 @@ empty file is visited. This is accomplished by putting What gets inserted, if anything, is determined by the variable @code{auto-insert-alist}. The @sc{car}s of this list are each either a mode name, making an element applicable when a buffer is in that -mode. Or they can be a string, which is a regexp matched against the +mode, or they can be a string, which is a regexp matched against the buffer's file name. In that way different kinds of files that have the same mode in Emacs can be distinguished. The @sc{car}s may also be cons cells consisting of mode name or regexp as above and an commit 3d4b389f3247d0158ba8572caf89331cb6f04a6d Author: Lars Ingebrigtsen Date: Tue Jun 21 12:44:00 2022 +0200 Rename recently-introduced dired-omit-line-regexp user option * lisp/dired-x.el (dired-omit-lines, dired-omit-mode): Rename dired-omit-line-regexp to dired-omit-lines for consistency. diff --git a/etc/NEWS b/etc/NEWS index f10573b86b..c54a1cc42a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1623,7 +1623,7 @@ the thumbnail file. ** Dired --- -*** New user option 'dired-omit-line-regexp'. +*** New user option 'dired-omit-lines'. This is used by 'dired-omit-mode', and now allows you to hide based on other things than just the file names. diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 6eb0f63ee5..b4b647f1b0 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -125,7 +125,7 @@ folding to be used on case-insensitive filesystems only." (file-name-case-insensitive-p dir) dired-omit-case-fold)) -(defcustom dired-omit-line-regexp nil +(defcustom dired-omit-lines nil "Regexp matching lines to be omitted by `dired-omit-mode'. The value can also be a variable whose value is such a regexp. The value can also be nil, which means do no line matching. @@ -167,7 +167,7 @@ Dired-Omit mode is a buffer-local minor mode. When enabled in a Dired buffer, Dired does not list files whose filenames match regexp `dired-omit-files', files ending with extensions in `dired-omit-extensions', or files listed on lines -matching `dired-omit-line-regexp'. +matching `dired-omit-lines'. To enable omitting in every Dired buffer, you can put this in your init file: @@ -184,8 +184,8 @@ See Info node `(dired-x) Omitting Variables' for more information." ;; Use count of file-name match as INIT-COUNT for line match. ;; Return total count. (Return value is not used anywhere, so far). (setq file-count (dired-omit-expunge)) - (when dired-omit-line-regexp - (dired-omit-expunge dired-omit-line-regexp 'LINEP file-count))))) + (when dired-omit-lines + (dired-omit-expunge dired-omit-lines 'LINEP file-count))))) (put 'dired-omit-mode 'safe-local-variable 'booleanp) commit 649b43d20cf75e61fab289f99d20e98b035d5a9a Author: Lars Ingebrigtsen Date: Tue Jun 21 12:15:11 2022 +0200 Make Lucid menus work from the keyboard also when uninstalled * lwlib/xlwmenu.c (ungrab_all, pop_up_menu): Use it. * src/keyboard.c (syms_of_keyboard): New variable (bug#46990). diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c index ace5141cdb..f0625982cf 100644 --- a/lwlib/xlwmenu.c +++ b/lwlib/xlwmenu.c @@ -245,11 +245,6 @@ WidgetClass xlwMenuWidgetClass = (WidgetClass) &xlwMenuClassRec; int submenu_destroyed; -/* For debug, if installation-directory is non-nil this is not an installed - Emacs. In that case we do not grab the keyboard to make it easier to - debug. */ -#define GRAB_KEYBOARD (EQ (Vinstallation_directory, Qnil)) - static int next_release_must_exit; /* Utilities */ @@ -259,7 +254,8 @@ static void ungrab_all (Widget w, Time ungrabtime) { XtUngrabPointer (w, ungrabtime); - if (GRAB_KEYBOARD) XtUngrabKeyboard (w, ungrabtime); + if (!lucid__menu_grab_keyboard) + XtUngrabKeyboard (w, ungrabtime); } /* Like abort, but remove grabs from widget W before. */ @@ -2721,7 +2717,7 @@ pop_up_menu (XlwMenuWidget mw, XButtonPressedEvent *event) mw->menu.cursor_shape, event->time) == Success) { - if (! GRAB_KEYBOARD + if (!lucid__menu_grab_keyboard || XtGrabKeyboard ((Widget)mw, False, GrabModeAsync, GrabModeAsync, event->time) == Success) { diff --git a/src/keyboard.c b/src/keyboard.c index e62b2e56d3..c41727d6c6 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -12648,6 +12648,15 @@ See also `pre-command-hook'. */); doc: /* Non-nil means menu bar, specified Lucid style, needs to be recomputed. */); Vlucid_menu_bar_dirty_flag = Qnil; +#ifdef USE_LUCID + DEFVAR_BOOL ("lucid--menu-grab-keyboard", + lucid__menu_grab_keyboard, + doc: /* If non-nil, grab keyboard during menu operations. +This is only relevant when using the Lucid X toolkit. It can be +convenient to disable this for debugging purposes. */); + lucid__menu_grab_keyboard = true; +#endif + DEFVAR_LISP ("menu-bar-final-items", Vmenu_bar_final_items, doc: /* List of menu bar items to move to the end of the menu bar. The elements of the list are event types that may have menu bar commit 8cf3c3203b07b781ed34627fce0283d2b1b03fd7 Author: Po Lu Date: Tue Jun 21 05:04:24 2022 +0000 Allow toggling antialiasing inside the Haiku font dialog * src/haiku_support.cc (struct font_selection_dialog_message): New field `disable_antialias'. (MessageReceived): Handle new message SET_DISABLE_ANTIALIASING. (class DualLayoutView): Rename to `TripleLayoutView'. (class TripleLayoutView): Rename from `DualLayoutView'. (MinSize): Update computations for three views. (class EmacsFontSelectionDialog, UpdatePreview) (EmacsFontSelectionDialog): Add an antialiasing checkbox to control antialiasing. (be_select_font): New arguments `initial_antialias' and `disable_antialias'. * src/haiku_support.h: Update prototypes. * src/haikufont.c (haikufont_pattern_from_object): Set FSPEC_ANTIALIAS. (Fx_select_font): Update accordingly. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index e09f886990..7819cef568 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -92,22 +92,23 @@ along with GNU Emacs. If not, see . */ /* Some messages that Emacs sends to itself. */ enum { - SCROLL_BAR_UPDATE = 3000, - WAIT_FOR_RELEASE = 3001, - RELEASE_NOW = 3002, - CANCEL_DROP = 3003, - SHOW_MENU_BAR = 3004, - BE_MENU_BAR_OPEN = 3005, - QUIT_APPLICATION = 3006, - REPLAY_MENU_BAR = 3007, - FONT_FAMILY_SELECTED = 3008, - FONT_STYLE_SELECTED = 3009, - FILE_PANEL_SELECTION = 3010, - QUIT_PREVIEW_DIALOG = 3011, - SET_FONT_INDICES = 3012, - SET_PREVIEW_DIALOG = 3013, - UPDATE_PREVIEW_DIALOG = 3014, - SEND_MOVE_FRAME_EVENT = 3015, + SCROLL_BAR_UPDATE = 3000, + WAIT_FOR_RELEASE = 3001, + RELEASE_NOW = 3002, + CANCEL_DROP = 3003, + SHOW_MENU_BAR = 3004, + BE_MENU_BAR_OPEN = 3005, + QUIT_APPLICATION = 3006, + REPLAY_MENU_BAR = 3007, + FONT_FAMILY_SELECTED = 3008, + FONT_STYLE_SELECTED = 3009, + FILE_PANEL_SELECTION = 3010, + QUIT_PREVIEW_DIALOG = 3011, + SET_FONT_INDICES = 3012, + SET_PREVIEW_DIALOG = 3013, + UPDATE_PREVIEW_DIALOG = 3014, + SEND_MOVE_FRAME_EVENT = 3015, + SET_DISABLE_ANTIALIASING = 3016, }; /* X11 keysyms that we use. */ @@ -146,6 +147,9 @@ struct font_selection_dialog_message /* Whether or not a size was explicitly specified. */ bool_bf size_specified : 1; + /* Whether or not antialiasing should be disabled. */ + bool_bf disable_antialias : 1; + /* The index of the selected font family. */ int family_idx; @@ -2574,6 +2578,9 @@ class EmacsFontPreviewDialog : public BWindow current_font = new BFont; current_font->SetFamilyAndStyle (name, sname); + if (message->GetBool ("emacs:disable_antialiasing", false)) + current_font->SetFlags (B_DISABLE_ANTIALIASING); + if (size_name && strlen (size_name)) { size = atoi (size_name); @@ -2615,26 +2622,32 @@ class EmacsFontPreviewDialog : public BWindow } }; -class DualLayoutView : public BView +class TripleLayoutView : public BView { BScrollView *view_1; - BView *view_2; + BView *view_2, *view_3; void FrameResized (float new_width, float new_height) { BRect frame; - float width, height; + float width, height, height_1, width_1; + float basic_height; frame = Frame (); view_2->GetPreferredSize (&width, &height); + view_3->GetPreferredSize (&width_1, &height_1); + + basic_height = height + height_1; view_1->MoveTo (0, 0); view_1->ResizeTo (BE_RECT_WIDTH (frame), - BE_RECT_HEIGHT (frame) - height); - view_2->MoveTo (2, BE_RECT_HEIGHT (frame) - height); + BE_RECT_HEIGHT (frame) - basic_height); + view_2->MoveTo (2, BE_RECT_HEIGHT (frame) - basic_height); view_2->ResizeTo (BE_RECT_WIDTH (frame) - 4, height); + view_3->MoveTo (2, BE_RECT_HEIGHT (frame) - height_1); + view_3->ResizeTo (BE_RECT_WIDTH (frame) - 4, height_1); BView::FrameResized (new_width, new_height); } @@ -2644,19 +2657,24 @@ class DualLayoutView : public BView MinSize (void) { float width, height; + float width_1, height_1; BSize size_1; size_1 = view_1->MinSize (); view_2->GetPreferredSize (&width, &height); + view_3->GetPreferredSize (&width_1, &height_1); - return BSize (std::max (size_1.width, width), - std::max (size_1.height, height)); + return BSize (std::max (size_1.width, + std::max (width_1, width)), + std::max (size_1.height, height + height_1)); } public: - DualLayoutView (BScrollView *first, BView *second) : BView (NULL, B_FRAME_EVENTS), - view_1 (first), - view_2 (second) + TripleLayoutView (BScrollView *first, BView *second, + BView *third) : BView (NULL, B_FRAME_EVENTS), + view_1 (first), + view_2 (second), + view_3 (third) { FrameResized (801, 801); } @@ -2665,13 +2683,14 @@ class DualLayoutView : public BView class EmacsFontSelectionDialog : public BWindow { BView basic_view; + BCheckBox antialias_checkbox; BCheckBox preview_checkbox; BSplitView split_view; BListView font_family_pane; BListView font_style_pane; BScrollView font_family_scroller; BScrollView font_style_scroller; - DualLayoutView style_view; + TripleLayoutView style_view; BObjectList all_families; BObjectList all_styles; BButton cancel_button, ok_button; @@ -2707,6 +2726,9 @@ class EmacsFontSelectionDialog : public BWindow message.AddInt32 ("emacs:family", family); message.AddInt32 ("emacs:style", style); + if (antialias_checkbox.Value () == B_CONTROL_ON) + message.AddBool ("emacs:disable_antialiasing", true); + message.AddString ("emacs:size", size_entry.Text ()); @@ -2834,6 +2856,11 @@ class EmacsFontSelectionDialog : public BWindow rq.size = atoi (text); rq.size_specified = rq.size > 0 || strlen (text); + if (antialias_checkbox.Value () == B_CONTROL_ON) + rq.disable_antialias = true; + else + rq.disable_antialias = false; + write_port (comm_port, 0, &rq, sizeof rq); } else if (msg->what == B_CANCEL) @@ -2859,6 +2886,11 @@ class EmacsFontSelectionDialog : public BWindow if (preview) UpdatePreview (); } + else if (msg->what == SET_DISABLE_ANTIALIASING) + { + if (preview) + UpdatePreview (); + } BWindow::MessageReceived (msg); } @@ -2881,6 +2913,7 @@ class EmacsFontSelectionDialog : public BWindow font_family_pane.RemoveSelf (); font_style_pane.RemoveSelf (); + antialias_checkbox.RemoveSelf (); preview_checkbox.RemoveSelf (); style_view.RemoveSelf (); font_family_scroller.RemoveSelf (); @@ -2897,12 +2930,15 @@ class EmacsFontSelectionDialog : public BWindow EmacsFontSelectionDialog (bool monospace_only, int initial_family_idx, int initial_style_idx, - int initial_size) + int initial_size, + bool initial_antialias) : BWindow (BRect (0, 0, 500, 500), "Select font from list", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, 0), basic_view (NULL, 0), + antialias_checkbox ("Disable antialiasing", "Disable antialiasing", + new BMessage (SET_DISABLE_ANTIALIASING)), preview_checkbox ("Show preview", "Show preview", new BMessage (SET_PREVIEW_DIALOG)), font_family_pane (BRect (0, 0, 0, 0), NULL, @@ -2917,7 +2953,8 @@ class EmacsFontSelectionDialog : public BWindow font_style_scroller (NULL, &font_style_pane, B_FOLLOW_ALL_SIDES, B_SUPPORTS_LAYOUT, false, true), - style_view (&font_style_scroller, &preview_checkbox), + style_view (&font_style_scroller, &antialias_checkbox, + &preview_checkbox), all_families (20, true), all_styles (20, true), cancel_button ("Cancel", "Cancel", @@ -2946,6 +2983,7 @@ class EmacsFontSelectionDialog : public BWindow split_view.AddChild (&font_family_scroller, 0.7); split_view.AddChild (&style_view, 0.3); style_view.AddChild (&font_style_scroller); + style_view.AddChild (&antialias_checkbox); style_view.AddChild (&preview_checkbox); basic_view.SetViewUIColor (B_PANEL_BACKGROUND_COLOR); @@ -3007,6 +3045,9 @@ class EmacsFontSelectionDialog : public BWindow sprintf (format_buffer, "%d", initial_size); size_entry.SetText (format_buffer); } + + if (!initial_antialias) + antialias_checkbox.SetValue (B_CONTROL_ON); } void @@ -5096,7 +5137,8 @@ be_select_font (void (*process_pending_signals_function) (void), haiku_font_family_or_style *style, int *size, bool allow_monospace_only, int initial_family, int initial_style, - int initial_size) + int initial_size, bool initial_antialias, + bool *disable_antialias) { EmacsFontSelectionDialog *dialog; struct font_selection_dialog_message msg; @@ -5106,7 +5148,7 @@ be_select_font (void (*process_pending_signals_function) (void), dialog = new EmacsFontSelectionDialog (allow_monospace_only, initial_family, initial_style, - initial_size); + initial_size, initial_antialias); dialog->CenterOnScreen (); if (dialog->InitCheck () < B_OK) @@ -5135,6 +5177,7 @@ be_select_font (void (*process_pending_signals_function) (void), memcpy (family, family_buffer, sizeof *family); memcpy (style, style_buffer, sizeof *style); *size = msg.size_specified ? msg.size : -1; + *disable_antialias = msg.disable_antialias; return true; } diff --git a/src/haiku_support.h b/src/haiku_support.h index 97c2b6904a..3484fe0bbe 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -703,7 +703,8 @@ extern bool be_replay_menu_bar_event (void *, struct haiku_menu_bar_click_event extern bool be_select_font (void (*) (void), bool (*) (void), haiku_font_family_or_style *, haiku_font_family_or_style *, - int *, bool, int, int, int); + int *, bool, int, int, int, + bool, bool *); extern int be_find_font_indices (struct haiku_font_pattern *, int *, int *); extern status_t be_roster_launch (const char *, const char *, char **, diff --git a/src/haikufont.c b/src/haikufont.c index e9a25c0d58..3e7f6f86dc 100644 --- a/src/haikufont.c +++ b/src/haikufont.c @@ -492,6 +492,14 @@ haikufont_pattern_from_object (struct haiku_font_pattern *pattern, pattern->specified |= FSPEC_WIDTH; pattern->width = haikufont_lisp_to_width (val); } + + val = assq_no_quit (QCantialias, + AREF (font_object, FONT_EXTRA_INDEX)); + if (CONSP (val)) + { + pattern->specified |= FSPEC_ANTIALIAS; + pattern->use_antialiasing = !NILP (XCDR (val)); + } } static void @@ -1232,6 +1240,7 @@ in the font selection dialog. */) int rc, size, initial_family, initial_style, initial_size; struct haiku_font_pattern pattern; Lisp_Object lfamily, lweight, lslant, lwidth, ladstyle, lsize; + bool disable_antialiasing, initial_antialias; f = decode_window_system_frame (frame); @@ -1241,6 +1250,7 @@ in the font selection dialog. */) initial_style = -1; initial_family = -1; initial_size = -1; + initial_antialias = true; font = FRAME_FONT (f); @@ -1254,6 +1264,11 @@ in the font selection dialog. */) haikufont_done_with_query_pattern (&pattern); initial_size = font->pixel_size; + + /* This field is safe to access even after + haikufont_done_with_query_pattern. */ + if (pattern.specified & FSPEC_ANTIALIAS) + initial_antialias = pattern.use_antialiasing; } popup_activated_p++; @@ -1263,7 +1278,8 @@ in the font selection dialog. */) &family, &style, &size, !NILP (exclude_proportional), initial_family, initial_style, - initial_size); + initial_size, initial_antialias, + &disable_antialiasing); request_sigio (); popup_activated_p--; @@ -1280,9 +1296,15 @@ in the font selection dialog. */) lwidth = (pattern.specified & FSPEC_WIDTH ? haikufont_width_to_lisp (pattern.width) : Qnil); ladstyle = (pattern.specified & FSPEC_STYLE - ? intern (pattern.style) : Qnil); + ? intern (pattern.style) : Qnil); lsize = (size >= 0 ? make_fixnum (size) : Qnil); + if (disable_antialiasing) + return CALLN (Ffont_spec, QCfamily, lfamily, + QCweight, lweight, QCslant, lslant, + QCwidth, lwidth, QCadstyle, ladstyle, + QCsize, lsize, QCantialias, Qnil); + return CALLN (Ffont_spec, QCfamily, lfamily, QCweight, lweight, QCslant, lslant, QCwidth, lwidth, QCadstyle, ladstyle, commit c175984e2c909979da915ac46b0c92de67f4b249 Merge: 1d681a5700 2eb738f2b8 Author: Stefan Kangas Date: Tue Jun 21 06:30:25 2022 +0200 Merge from origin/emacs-28 2eb738f2b8 Support builds configured with a separate --bindir cf4c204df8 * doc/misc/eww.texi (Overview, Basics): Fix typos. commit 1d681a57005c837a58c9b3a365bc59f7293c4df5 Author: Po Lu Date: Tue Jun 21 10:12:00 2022 +0800 Add test for bug#56078 fix * test/lisp/dnd-tests.el (dnd-tests-open-remote-url): New test. diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index dfd441b56d..3ee92286f9 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -371,5 +371,18 @@ This function only tries to handle strings." (should-not (dnd-get-local-file-uri "file://some-remote-host/path/to/foo")) (should-not (dnd-get-local-file-uri "file:///path/to/foo"))) +(ert-deftest dnd-tests-open-remote-url () + ;; Expensive test to make sure opening an FTP URL during + ;; drag-and-drop works. + :tags '(:expensive-test) + ;; Don't run this test if the FTP server isn't reachable. + (skip-unless (and (fboundp 'network-lookup-address-info) + (network-lookup-address-info "ftp.gnu.org"))) + ;; Make sure bug#56078 doesn't happen again. + (let ((url "ftp://anonymous@ftp.gnu.org/") + ;; This prints a bunch of annoying spaces to stdout. + (inhibit-message t)) + (should (prog1 t (dnd-open-remote-url url 'private))))) + (provide 'dnd-tests) ;;; dnd-tests.el ends here commit 01834ba0c9c1ed5d6b25a1463b79b00e2fc7266b Author: Po Lu Date: Tue Jun 21 09:52:47 2022 +0800 Remove selection requests on the keyboard buffer when closing display * src/xterm.c (X_NEXT_KBD_EVENT): New macro. (x_defer_selection_requests): Set input_pending if the kbd buffer was modified. (x_delete_selection_requests): New function. (x_delete_display): Call that. Bug found when a display died while the clipboard manager was sending an unreasonably high number of requests. diff --git a/src/xterm.c b/src/xterm.c index b5543b873c..ee78da085e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -802,6 +802,10 @@ static struct input_event *current_hold_quit; than 0. */ static int x_use_pending_selection_requests; +/* Like `next_kbd_event', but for use in X code. */ +#define X_NEXT_KBD_EVENT(ptr) \ + ((ptr) == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : (ptr) + 1) + static void x_push_selection_request (struct selection_input_event *); /* Defer selection requests. Between this and @@ -838,14 +842,12 @@ x_defer_selection_requests (void) avoids exhausting the keyboard buffer with some over-enthusiastic clipboard managers. */ if (!between) - kbd_fetch_ptr = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 - ? kbd_buffer : event + 1); + kbd_fetch_ptr = X_NEXT_KBD_EVENT (event); } else between = true; - event = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 - ? kbd_buffer : event + 1); + event = X_NEXT_KBD_EVENT (event); } } @@ -26969,7 +26971,54 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) return dpyinfo; } + + +/* Remove all the selection input events on the keyboard buffer + intended for DPYINFO. */ + +static void +x_delete_selection_requests (struct x_display_info *dpyinfo) +{ + union buffered_input_event *event; + int moved_events; + + for (event = kbd_fetch_ptr; event != kbd_store_ptr; + event = X_NEXT_KBD_EVENT (event)) + { + if (event->kind == SELECTION_REQUEST_EVENT + || event->kind == SELECTION_CLEAR_EVENT) + { + if (SELECTION_EVENT_DPYINFO (&event->sie) != dpyinfo) + continue; + + /* Remove the event from the fifo buffer before processing; + otherwise swallow_events called recursively could see it + and process it again. To do this, we move the events + between kbd_fetch_ptr and EVENT one slot to the right, + cyclically. */ + + if (event < kbd_fetch_ptr) + { + memmove (kbd_buffer + 1, kbd_buffer, + (event - kbd_buffer) * sizeof *kbd_buffer); + kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1]; + moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr; + } + else + moved_events = event - kbd_fetch_ptr; + + memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr, + moved_events * sizeof *kbd_fetch_ptr); + kbd_fetch_ptr = X_NEXT_KBD_EVENT (kbd_fetch_ptr); + + /* `detect_input_pending' will then recompute whether or not + pending input events exist. */ + input_pending = false; + } + } +} + /* Get rid of display DPYINFO, deleting all frames on it, and without sending any more commands to the X server. */ @@ -27019,6 +27068,8 @@ x_delete_display (struct x_display_info *dpyinfo) last = ie; } + x_delete_selection_requests (dpyinfo); + if (next_noop_dpyinfo == dpyinfo) next_noop_dpyinfo = dpyinfo->next; commit 32a6d52d43b4c3452687a11b01dfb51ba111fee2 Author: Po Lu Date: Tue Jun 21 09:35:07 2022 +0800 Move selection delayed message to a better location * lisp/term/x-win.el (gui-backend-get-selection): Remove `with-delayed-message' here. * src/xselect.c (x_display_selection_waiting_message) (x_cancel_atimer): New functions. (x_get_foreign_selection): Add an atimer that displays the message after a while. diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 6e083499df..32675a07b1 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1366,9 +1366,8 @@ This returns an error if any Emacs frames are X frames." (cl-defmethod gui-backend-get-selection (selection-symbol target-type &context (window-system x) &optional time-stamp terminal) - (with-delayed-message (1 "Waiting for selection") - (x-get-selection-internal selection-symbol target-type - time-stamp terminal))) + (x-get-selection-internal selection-symbol target-type + time-stamp terminal)) ;; Initiate drag and drop (add-hook 'after-make-frame-functions 'x-dnd-init-frame) diff --git a/src/xselect.c b/src/xselect.c index fcf0ee944e..d90916c6b6 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -36,6 +36,7 @@ along with GNU Emacs. If not, see . */ #include "termhooks.h" #include "keyboard.h" #include "pdumper.h" +#include "atimer.h" #include @@ -1198,6 +1199,20 @@ x_handle_property_notify (const XPropertyEvent *event) } } +static void +x_display_selection_waiting_message (struct atimer *timer) +{ + Lisp_Object val; + + val = build_string ("Waiting for reply from selection owner..."); + message3_nolog (val); +} + +static void +x_cancel_atimer (void *atimer) +{ + cancel_atimer (atimer); +} /* Variables for communication with x_handle_selection_notify. */ @@ -1223,9 +1238,14 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, Atom type_atom = (CONSP (target_type) ? symbol_to_x_atom (dpyinfo, XCAR (target_type)) : symbol_to_x_atom (dpyinfo, target_type)); + struct atimer *delayed_message; + struct timespec message_interval; + specpdl_ref count; + + count = SPECPDL_INDEX (); if (!FRAME_LIVE_P (f)) - return Qnil; + return unbind_to (count, Qnil); if (! NILP (time_stamp)) CONS_TO_INTEGER (time_stamp, Time, requestor_time); @@ -1257,6 +1277,12 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, unblock_input (); + message_interval = make_timespec (1, 0); + delayed_message = start_atimer (ATIMER_RELATIVE, message_interval, + x_display_selection_waiting_message, + NULL); + record_unwind_protect_ptr (x_cancel_atimer, delayed_message); + /* This allows quits. Also, don't wait forever. */ intmax_t timeout = max (0, x_selection_timeout); intmax_t secs = timeout / 1000; @@ -1288,13 +1314,16 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, if (NILP (XCAR (reading_selection_reply))) error ("Timed out waiting for reply from selection owner"); if (EQ (XCAR (reading_selection_reply), Qlambda)) - return Qnil; + return unbind_to (count, Qnil); /* Otherwise, the selection is waiting for us on the requested property. */ - return - x_get_window_property_as_lisp_data (dpyinfo, requestor_window, - target_property, target_type, - selection_atom, false); + return unbind_to (count, + x_get_window_property_as_lisp_data (dpyinfo, + requestor_window, + target_property, + target_type, + selection_atom, + false)); } /* Subroutines of x_get_window_property_as_lisp_data */ commit 256fac4886579ec164a1baf84f6059687296b1dd Author: Sean Whitton Date: Mon Jun 20 17:43:27 2022 -0700 * lisp/edmacro.el: Add missing (require 'seq). diff --git a/lisp/edmacro.el b/lisp/edmacro.el index debd76c43a..c681f90141 100644 --- a/lisp/edmacro.el +++ b/lisp/edmacro.el @@ -62,6 +62,7 @@ ;;; Code: (require 'cl-lib) +(require 'seq) (require 'kmacro) ;;; The user-level commands for editing macros. commit 25e69968b05df4116ff669277386c1529c545d6b Author: Sean Whitton Date: Mon Jun 20 14:33:51 2022 -0700 term-set-escape-char: Remove old binding from term-raw-escape-map * lisp/term.el (term-set-escape-char): When replacing the escape char, remove the binding of the old escape char in term-raw-escape-map. diff --git a/lisp/term.el b/lisp/term.el index f81cbf7293..94bf13e973 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -1052,11 +1052,10 @@ underlying shell." "Change `term-escape-char' and keymaps that depend on it." (when term-escape-char ;; Undo previous term-set-escape-char. - (define-key term-raw-map term-escape-char 'term-send-raw)) + (define-key term-raw-map term-escape-char 'term-send-raw) + (define-key term-raw-escape-map term-escape-char nil t)) (setq term-escape-char (if (vectorp key) key (vector key))) (define-key term-raw-map term-escape-char term-raw-escape-map) - ;; FIXME: If we later call term-set-escape-char again with another key, - ;; we should undo this binding. (define-key term-raw-escape-map term-escape-char 'term-send-raw)) (term-set-escape-char (or term-escape-char ?\C-c)) commit 4ae315f7c3b5bc370d9d66eab5428685a6097606 Author: Alan Mackenzie Date: Mon Jun 20 18:31:05 2022 +0000 Fix potential (goto-char nil) in byte-compile-warning-prefix * lisp/emacs-lisp/bytecomp.el (byte-compile-warning-prefix): Replace a wrong 'or' form involving OFFSET with simply OFFSET. This prevents OFFSET from possibly being nil in the first branch of the containing `if' form. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 2ae9aa13bb..198eb4df5c 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -1246,8 +1246,7 @@ Order is by depth-first search." load-file-name dir))) (t ""))) (offset (byte-compile--warning-source-offset)) - (pos (if (and byte-compile-current-file - (or offset (not symbols-with-pos-enabled))) + (pos (if (and byte-compile-current-file offset) (with-current-buffer byte-compile-current-buffer (let (new-l new-c) (save-excursion commit 2eb738f2b8a3948b590ac7a6640f317a5cb12918 Author: Eli Zaretskii Date: Mon Jun 20 19:04:06 2022 +0300 Support builds configured with a separate --bindir * src/emacs.c (load_pdump): Don't overwrite the leading directories of the Emacs executable just because the pdumper file was not found in the expected directory relative to the binary. This is needed to support builds with a separate --bindir configure-time option and native-compilation. (Bug#55741) diff --git a/src/emacs.c b/src/emacs.c index ccc0dd269f..0a90b0913b 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -940,20 +940,24 @@ load_pdump (int argc, char **argv) sprintf (dump_file, "%s%c%s%s", path_exec, DIRECTORY_SEP, argv0_base, suffix); #if !defined (NS_SELF_CONTAINED) - /* Assume the Emacs binary lives in a sibling directory as set up by - the default installation configuration. */ - const char *go_up = "../../../../bin/"; - needed += (strip_suffix ? strlen (strip_suffix) : 0) - - strlen (suffix) + strlen (go_up); - if (exec_bufsize < needed) - { - xfree (emacs_executable); - emacs_executable = xpalloc (NULL, &exec_bufsize, needed - exec_bufsize, - -1, 1); - } - sprintf (emacs_executable, "%s%c%s%s%s", - path_exec, DIRECTORY_SEP, go_up, argv0_base, - strip_suffix ? strip_suffix : ""); + if (!(emacs_executable && *emacs_executable)) + { + /* If we didn't find the Emacs binary, assume that it lives in a + sibling directory as set up by the default installation + configuration. */ + const char *go_up = "../../../../bin/"; + needed += (strip_suffix ? strlen (strip_suffix) : 0) + - strlen (suffix) + strlen (go_up); + if (exec_bufsize < needed) + { + xfree (emacs_executable); + emacs_executable = xpalloc (NULL, &exec_bufsize, + needed - exec_bufsize, -1, 1); + } + sprintf (emacs_executable, "%s%c%s%s%s", + path_exec, DIRECTORY_SEP, go_up, argv0_base, + strip_suffix ? strip_suffix : ""); + } #endif result = pdumper_load (dump_file, emacs_executable); commit 54e350977148df1c2e26d83492ee3c6668c047d1 Author: Lars Ingebrigtsen Date: Mon Jun 20 17:34:33 2022 +0200 Issue a message if getting a selection takes a long time * lisp/term/x-win.el (gui-backend-get-selection): If getting the selection takes a long time, issue a message after one second (bug#46935). diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 31fc3ba534..6e083499df 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1366,7 +1366,9 @@ This returns an error if any Emacs frames are X frames." (cl-defmethod gui-backend-get-selection (selection-symbol target-type &context (window-system x) &optional time-stamp terminal) - (x-get-selection-internal selection-symbol target-type time-stamp terminal)) + (with-delayed-message (1 "Waiting for selection") + (x-get-selection-internal selection-symbol target-type + time-stamp terminal))) ;; Initiate drag and drop (add-hook 'after-make-frame-functions 'x-dnd-init-frame) commit c6ff592663e93c43ee36ba441ada5639305fee75 Author: Michael Albinus Date: Mon Jun 20 15:45:46 2022 +0200 Adapt url-tramp-tests * test/lisp/url/url-tramp-tests.el (url-tramp-test-convert-url-to-tramp) (url-tramp-test-convert-tramp-to-url): Adapt tests. diff --git a/test/lisp/url/url-tramp-tests.el b/test/lisp/url/url-tramp-tests.el index 033c17444d..369de0e245 100644 --- a/test/lisp/url/url-tramp-tests.el +++ b/test/lisp/url/url-tramp-tests.el @@ -55,8 +55,12 @@ (password-cache-remove key) (should-not (password-in-cache-p key))) - ;; "http" does not belong to `url-tramp-protocols'. - (should-not (url-tramp-convert-url-to-tramp "http://www.gnu.org"))) + ;; "http" does not belong to `url-tramp-protocols'. The string + ;; isn't changed, therefore. + (should + (string-equal + (url-tramp-convert-url-to-tramp "http://www.gnu.org") + "http://www.gnu.org"))) (ert-deftest url-tramp-test-convert-tramp-to-url () "Test that Tramp file names are converted into proper URLs." @@ -75,8 +79,12 @@ (url-tramp-convert-tramp-to-url "/telnet:user@remotehost#42:") "telnet://user@remotehost:42")) - ;; "sftp" does not belong to `url-tramp-protocols'. - (should-not (url-tramp-convert-tramp-to-url "/sftp:user@localhost:"))) + ;; "sftp" does not belong to `url-tramp-protocols'. The string + ;; isn't changed, therefore. + (should + (string-equal + (url-tramp-convert-tramp-to-url "/sftp:user@localhost:") + "/sftp:user@localhost:"))) (provide 'url-tramp-tests) commit 5e7a0873c5f4160948cdd98922d198836f1c6fd1 Author: Eli Zaretskii Date: Mon Jun 20 16:08:46 2022 +0300 ; * src/process.c (wait_reading_process_output): Fix typo. diff --git a/src/process.c b/src/process.c index 8f65496148..b2847ee172 100644 --- a/src/process.c +++ b/src/process.c @@ -5494,7 +5494,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, no_avail = 0; if ((read_kbd /* The following code doesn't make any sense for just the - wait_or_cell case, because detect_input_pending returns + wait_for_cell case, because detect_input_pending returns whether or not the keyboard buffer isn't empty or there is mouse movement. Any keyboard input that arrives while waiting for a cell will cause the select call to commit 0c8bc8e6d93d901c96770f798f41cb6aaafdb678 Author: Eli Zaretskii Date: Mon Jun 20 16:05:05 2022 +0300 ; Fix recent change of documentation of face-remap * lisp/face-remap.el (text-scale-adjust): * doc/emacs/display.texi (Text Scale): Fix wording of recent changes to documentation. diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index e065155845..fbff1d4eb6 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -855,7 +855,7 @@ would be selected if you click a mouse or press @key{RET}. @section Text Scale @cindex adjust buffer font size -@cindex font size, increase or decrease +@cindex font size of @code{default} face, increase or decrease @findex text-scale-adjust @kindex C-x C-+ @kindex C-x C-- @@ -863,21 +863,27 @@ would be selected if you click a mouse or press @key{RET}. @kindex C-x C-0 @kindex C-wheel-down @kindex C-wheel-up - To increase the font size in the current buffer, type @kbd{C-x C-+} -or @kbd{C-x C-=}. To decrease it, type @kbd{C-x C--}. To restore the -default (global) font size, type @kbd{C-x C-0}. These keys are all -bound to the same command, @code{text-scale-adjust}, which looks at -the last key typed to determine which action to take and adjusts the -font size accordingly by changing the height of the default face. - - Most faces are affected by these font size changes, but not faces -that have an explicit @code{:height} setting. The two exceptions to -this are the @code{default} and @code{header} faces: They will both be -scaled even if they have an explicit @code{:height} setting. + To increase the font size of the @code{default} face in the current +buffer, type @kbd{C-x C-+} or @kbd{C-x C-=}. To decrease it, type +@kbd{C-x C--}. To restore the default (global) font size, type +@kbd{C-x C-0}. These keys are all bound to the same command, +@code{text-scale-adjust}, which looks at the last key typed to +determine which action to take and adjusts the font size accordingly +by changing the height of the default face. + + Most faces don't have an explicit setting of the @code{:height} +attribute, and thus inherit the height from the @code{default} face. +Those faces are also scaled by the above commands. + + Faces other than @code{default} that have an explicit setting of the +@code{:height} attribute are not affected by these font size changes. +The @code{header-line} face is an exception: it will be scaled even if +it has an explicit setting of the @code{:height} attribute. Similarly, scrolling the mouse wheel with the @kbd{Ctrl} modifier pressed, when the mouse pointer is above buffer text, will increase or -decrease the font size, depending on the direction of the scrolling. +decrease the font size of the affected faces, depending on the +direction of the scrolling. The final key of these commands may be repeated without the leading @kbd{C-x}. For instance, @kbd{C-x C-= C-= C-=} increases the face diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 75d7333f8a..d611671408 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -393,7 +393,7 @@ a top-level keymap, `text-scale-increase' or Most faces are affected by these font size changes, but not faces that have an explicit `:height' setting. The two exceptions to -this are the `default' and `header' faces: They will both be +this are the `default' and `header-line' faces: they will both be scaled even if they have an explicit `:height' setting." (interactive "p") (let ((ev last-command-event) commit 4cc2f820b500ed2f8fad9baa2cf4a057f271a006 Author: Po Lu Date: Mon Jun 20 20:56:49 2022 +0800 Fix x-selection-timeout if some keyboard input arrives while waiting * src/process.c (wait_reading_process_output): Don't allow skipping calls to select if detect_input_pending when just waiting for a cell. (bug#46935) * src/xselect.c (x_get_foreign_selection): Add more debugging code. diff --git a/src/process.c b/src/process.c index 0cbac172fe..8f65496148 100644 --- a/src/process.c +++ b/src/process.c @@ -5492,7 +5492,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, triggered by processing X events). In the latter case, set nfds to 1 to avoid breaking the loop. */ no_avail = 0; - if ((read_kbd || !NILP (wait_for_cell)) + if ((read_kbd + /* The following code doesn't make any sense for just the + wait_or_cell case, because detect_input_pending returns + whether or not the keyboard buffer isn't empty or there + is mouse movement. Any keyboard input that arrives + while waiting for a cell will cause the select call to + be skipped, and gobble_input to be called even when + there is no input available from the terminal itself. + Skipping the call to select also causes the timeout to + be ignored. (bug#46935) */ + /* || !NILP (wait_for_cell) */) && detect_input_pending ()) { nfds = read_kbd ? 0 : 1; diff --git a/src/xselect.c b/src/xselect.c index dd82a906af..fcf0ee944e 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -1261,7 +1261,13 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, intmax_t timeout = max (0, x_selection_timeout); intmax_t secs = timeout / 1000; int nsecs = (timeout % 1000) * 1000000; - TRACE1 (" Start waiting %"PRIdMAX" secs for SelectionNotify", secs); + TRACE1 (" Start waiting %"PRIdMAX" secs for SelectionNotify.", secs); + + if (input_blocked_p ()) + TRACE0 (" Input is blocked."); + else + TRACE1 (" Waiting for %d nsecs in addition.", nsecs); + /* This function can be called with input blocked inside Xt or GTK timeouts run inside popup menus, so use a function that works when input is blocked. Prefer wait_reading_process_output commit a7aeef934be65ed86993181f3ad3b4b074a6afaa Author: Eli Zaretskii Date: Mon Jun 20 15:49:11 2022 +0300 ; * lisp/help-mode.el (help-xref-button): Doc fix. diff --git a/lisp/help-mode.el b/lisp/help-mode.el index a1b03700db..219e3c7b86 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -699,8 +699,8 @@ regexp. TYPE is the type of button to use. Any remaining arguments are passed to the button's help-function when it is invoked. See `help-make-xrefs'. -This function heeds the `help-clean-buttons' variable and will -remove quotes surrounding the match if non-nil." +This function removes quotes surrounding the match if the +variable `help-clean-buttons' is non-nil." ;; Don't mung properties we've added specially in some instances. (let ((beg (match-beginning match-number)) (end (match-end match-number))) commit 3642f3787279c05288f4f0d295fd9238f206ed15 Author: Eli Zaretskii Date: Mon Jun 20 15:42:48 2022 +0300 ; * lisp/image.el (find-image): Fix typos. diff --git a/lisp/image.el b/lisp/image.el index 24d1c2d169..8c5cfa7c0b 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -764,13 +764,13 @@ SPECS is a list of image specifications. Each image specification in SPECS is a property list. The contents of a specification are image type dependent. All specifications must at -least contain the either the property `:file FILE' or `:data DATA', +least contain either the property `:file FILE' or `:data DATA', where FILE is the file to load the image from, and DATA is a string containing the actual image data. If the property `:type TYPE' is omitted or nil, try to determine the image type from its first few -bytes of image data. If that doesn’t work, and the property `:file -FILE' provide a file name, use its file extension as image type. If -the property `:type TYPE' is provided, it must match the actual type +bytes of image data. If that doesn't work, and the property `:file +FILE' provide a file name, use its file extension as image type. +If `:type TYPE' is provided, it must match the actual type determined for FILE or DATA by `create-image'. Return nil if no specification is satisfied. commit e2ec4b844337794a4b95475481fecdd7a5ad28e9 Author: Stefan Kangas Date: Mon Jun 20 13:23:24 2022 +0200 Prefer defvar-keymap in hi-lock.el * lisp/hi-lock.el: Prefer keymap-set in documentation. (hi-lock-map): Prefer defvar-keymap. diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index 0934eef8ed..8cddd64482 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -69,12 +69,12 @@ ;; You might also want to bind the hi-lock commands to more ;; finger-friendly sequences: -;; (define-key hi-lock-map "\C-z\C-h" 'highlight-lines-matching-regexp) -;; (define-key hi-lock-map "\C-zi" 'hi-lock-find-patterns) -;; (define-key hi-lock-map "\C-zh" 'highlight-regexp) -;; (define-key hi-lock-map "\C-zp" 'highlight-phrase) -;; (define-key hi-lock-map "\C-zr" 'unhighlight-regexp) -;; (define-key hi-lock-map "\C-zb" 'hi-lock-write-interactive-patterns)) +;; (keymap-set hi-lock-map "C-z C-h" 'highlight-lines-matching-regexp) +;; (keymap-set hi-lock-map "C-z i" 'hi-lock-find-patterns) +;; (keymap-set hi-lock-map "C-z h" 'highlight-regexp) +;; (keymap-set hi-lock-map "C-z p" 'highlight-phrase) +;; (keymap-set hi-lock-map "C-z r" 'unhighlight-regexp) +;; (keymap-set hi-lock-map "C-z b" 'hi-lock-write-interactive-patterns)) ;; See the documentation for hi-lock-mode `C-h f hi-lock-mode' for ;; additional instructions. @@ -276,17 +276,16 @@ a library is being loaded.") ["Patterns from Buffer" hi-lock-find-patterns :help "Use patterns (if any) near top of buffer."])) -(defvar hi-lock-map - (let ((map (make-sparse-keymap "Hi Lock"))) - (define-key map "\C-xwi" 'hi-lock-find-patterns) - (define-key map "\C-xwl" 'highlight-lines-matching-regexp) - (define-key map "\C-xwp" 'highlight-phrase) - (define-key map "\C-xwh" 'highlight-regexp) - (define-key map "\C-xw." 'highlight-symbol-at-point) - (define-key map "\C-xwr" 'unhighlight-regexp) - (define-key map "\C-xwb" 'hi-lock-write-interactive-patterns) - map) - "Key map for hi-lock.") +(defvar-keymap hi-lock-map + :doc "Keymap for `hi-lock-mode'." + :name "Hi Lock" + "C-x w i" #'hi-lock-find-patterns + "C-x w l" #'highlight-lines-matching-regexp + "C-x w p" #'highlight-phrase + "C-x w h" #'highlight-regexp + "C-x w ." #'highlight-symbol-at-point + "C-x w r" #'unhighlight-regexp + "C-x w b" #'hi-lock-write-interactive-patterns) ;; Visible Functions commit 45dc99dcb91f0de5b9ea30141e1dd5a53368e38b Author: Po Lu Date: Mon Jun 20 19:11:38 2022 +0800 Fix ns-reg-to-script definition * src/nsfont.m (syms_of_nsfont): Fix definition. diff --git a/src/nsfont.m b/src/nsfont.m index ae5e134e15..b54118afe5 100644 --- a/src/nsfont.m +++ b/src/nsfont.m @@ -1763,8 +1763,11 @@ is false when (FROM > 0 || TO < S->nchars). */ DEFSYM (Qcondensed, "condensed"); DEFSYM (Qexpanded, "expanded"); DEFSYM (Qmedium, "medium"); + DEFVAR_LISP ("ns-reg-to-script", Vns_reg_to_script, - doc: /* Internal use: maps font registry to Unicode script. */); + doc: /* Internal map of font registry to Unicode script. */); + Vns_reg_to_script = Qnil; + pdumper_do_now_and_after_load (syms_of_nsfont_for_pdumper); } commit f120db63a34e7e9085d815c872049c9cacbbe971 Author: Po Lu Date: Mon Jun 20 11:02:14 2022 +0000 Fix running temacs on Haiku * src/emacs.c (main): Run init_haiku_select at the right place. diff --git a/src/emacs.c b/src/emacs.c index 43b9901e08..236add1157 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -2412,11 +2412,11 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #if defined WINDOWSNT || defined HAVE_NTGUI globals_of_w32select (); #endif + } #ifdef HAVE_HAIKU - init_haiku_select (); + init_haiku_select (); #endif - } init_charset (); commit b5dd337ada80ec89651677cfd8630380afca6f91 Author: Po Lu Date: Mon Jun 20 10:57:17 2022 +0000 Fix initialization of Haiku font driver * src/font.c (register_font_driver): Fix comment. * src/haikufont.c (haikufont_booleans): New list. (haikufont_filter_properties): New function. (haikufont_driver): Register new hook. (syms_of_haikufont_for_pdumper): Register font driver globally. (syms_of_haikufont): Call it in a pdumper hook. diff --git a/src/font.c b/src/font.c index 702536c1ca..3846cfc107 100644 --- a/src/font.c +++ b/src/font.c @@ -3589,8 +3589,8 @@ font_open_by_name (struct frame *f, Lisp_Object name) The second is with frame F NULL. In this case, DRIVER is globally registered in the variable `font_driver_list'. All font-driver - implementations must call this function in its syms_of_XXXX - (e.g. syms_of_xfont). */ + implementations must call this function in its + syms_of_XXXX_for_pdumper (e.g. syms_of_xfont_for_pdumper). */ void register_font_driver (struct font_driver const *driver, struct frame *f) diff --git a/src/haikufont.c b/src/haikufont.c index 77aa400631..e9a25c0d58 100644 --- a/src/haikufont.c +++ b/src/haikufont.c @@ -1173,6 +1173,24 @@ haikufont_list_family (struct frame *f) return list; } +/* List of boolean properties in font names accepted by this font + driver. */ +static const char *const haikufont_booleans[] = + { + ":antialias", + NULL, + }; + +/* List of non-boolean properties. Currently empty. */ +static const char *const haikufont_non_booleans[1]; + +static void +haikufont_filter_properties (Lisp_Object font, Lisp_Object alist) +{ + font_filter_properties (font, alist, haikufont_booleans, + haikufont_non_booleans); +} + struct font_driver const haikufont_driver = { .type = LISPSYM_INITIALLY (Qhaiku), @@ -1187,7 +1205,8 @@ struct font_driver const haikufont_driver = .encode_char = haikufont_encode_char, .text_extents = haikufont_text_extents, .shape = haikufont_shape, - .list_family = haikufont_list_family + .list_family = haikufont_list_family, + .filter_properties = haikufont_filter_properties, }; static bool @@ -1270,6 +1289,12 @@ in the font selection dialog. */) QCsize, lsize); } +static void +syms_of_haikufont_for_pdumper (void) +{ + register_font_driver (&haikufont_driver, NULL); +} + void syms_of_haikufont (void) { @@ -1299,6 +1324,7 @@ syms_of_haikufont (void) #ifdef USE_BE_CAIRO Fput (Qhaiku, Qfont_driver_superseded_by, Qftcr); #endif + pdumper_do_now_and_after_load (syms_of_haikufont_for_pdumper); font_cache = list (Qnil); staticpro (&font_cache); commit 8400c59358c69574f3eeb2751b517f94abb28274 Author: Michael Albinus Date: Mon Jun 20 12:47:27 2022 +0200 Fix problems with Tramp FTP and URL handler mode * lisp/net/tramp-archive.el (tramp-archive-run-real-handler): Add ;;;###tramp-autoload cookie. * lisp/net/tramp-ftp.el (tramp-ftp-file-name-handler): Prevent invocation of `tramp-archive-file-name-handler'. (Bug#56078) * lisp/url/url-tramp.el (url-tramp-convert-url-to-tramp) (url-tramp-convert-tramp-to-url): Make them more robust. diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el index f30aa021b6..119ac54dd2 100644 --- a/lisp/net/tramp-archive.el +++ b/lisp/net/tramp-archive.el @@ -309,7 +309,8 @@ Operations not mentioned here will be handled by the default Emacs primitives.") #'tramp-archive-file-name-p)) (apply #'tramp-file-name-for-operation operation args))) -(defun tramp-archive-run-real-handler (operation args) +;;;###tramp-autoload +(progn (defun tramp-archive-run-real-handler (operation args) "Invoke normal file name handler for OPERATION. First arg specifies the OPERATION, second arg ARGS is a list of arguments to pass to the OPERATION." @@ -319,7 +320,7 @@ arguments to pass to the OPERATION." ,(and (eq inhibit-file-name-operation operation) inhibit-file-name-handlers))) (inhibit-file-name-operation operation)) - (apply operation args))) + (apply operation args)))) ;;;###tramp-autoload (defun tramp-archive-file-name-handler (operation &rest args) diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el index ff8caa570c..7a13760ffc 100644 --- a/lisp/net/tramp-ftp.el +++ b/lisp/net/tramp-ftp.el @@ -135,12 +135,21 @@ pass to the OPERATION." ;; completion. We don't use `with-parsed-tramp-file-name', ;; because this returns another user but the one declared in ;; "~/.netrc". + ;; For file names which look like Tramp archive files like + ;; "/ftp:anonymous@ftp.gnu.org:/gnu/tramp/tramp-2.0.39.tar.gz", + ;; we must disable tramp-archive.el, because in + ;; `ange-ftp-get-files' this is "normalized" by + ;; `file-name-as-directory' with unwelcome side side-effects. + ;; This disables the file archive functionality, perhaps we + ;; could fix this otherwise. (Bug#56078) ((memq operation '(file-directory-p file-exists-p)) - (if (apply #'ange-ftp-hook-function operation args) + (cl-letf (((symbol-function #'tramp-archive-file-name-handler) + (lambda (operation &rest args) + (tramp-archive-run-real-handler operation args)))) + (prog1 (apply #'ange-ftp-hook-function operation args) (let ((v (tramp-dissect-file-name (car args) t))) (setf (tramp-file-name-method v) tramp-ftp-method) - (tramp-set-connection-property v "started" t)) - nil)) + (tramp-set-connection-property v "started" t))))) ;; If the second argument of `copy-file' or `rename-file' is a ;; remote file name but via FTP, ange-ftp doesn't check this. diff --git a/lisp/url/url-tramp.el b/lisp/url/url-tramp.el index 30c1961407..2918192a45 100644 --- a/lisp/url/url-tramp.el +++ b/lisp/url/url-tramp.el @@ -44,36 +44,39 @@ In case URL is not convertible, nil is returned." (port (and obj (natnump (url-portspec obj)) (number-to-string (url-portspec obj))))) - (when (and obj (member (url-type obj) url-tramp-protocols)) - (when (url-password obj) - (password-cache-add - (tramp-make-tramp-file-name - (make-tramp-file-name - :method (url-type obj) :user (url-user obj) - :host (url-host obj))) - (url-password obj))) - (tramp-make-tramp-file-name - (make-tramp-file-name - :method (url-type obj) :user (url-user obj) - :host (url-host obj) :port port :localname (url-filename obj)))))) + (if (and obj (member (url-type obj) url-tramp-protocols)) + (progn + (when (url-password obj) + (password-cache-add + (tramp-make-tramp-file-name + (make-tramp-file-name + :method (url-type obj) :user (url-user obj) + :host (url-host obj))) + (url-password obj))) + (tramp-make-tramp-file-name + (make-tramp-file-name + :method (url-type obj) :user (url-user obj) + :host (url-host obj) :port port :localname (url-filename obj)))) + url))) (defun url-tramp-convert-tramp-to-url (file) "Convert FILE, a Tramp file name, to a URL. In case FILE is not convertible, nil is returned." - (let* ((obj (ignore-errors (tramp-dissect-file-name file))) + (let* ((obj (and (tramp-tramp-file-p file) (tramp-dissect-file-name file))) (port (and obj (stringp (tramp-file-name-port obj)) (string-to-number (tramp-file-name-port obj))))) - (when (and obj (member (tramp-file-name-method obj) url-tramp-protocols)) - (url-recreate-url - (url-parse-make-urlobj - (tramp-file-name-method obj) - (tramp-file-name-user obj) - nil ; password. - (tramp-file-name-host obj) - port - (tramp-file-name-localname obj) - nil nil t))))) ; target attributes fullness. + (if (and obj (member (tramp-file-name-method obj) url-tramp-protocols)) + (url-recreate-url + (url-parse-make-urlobj + (tramp-file-name-method obj) + (tramp-file-name-user obj) + nil ; password. + (tramp-file-name-host obj) + port + (tramp-file-name-localname obj) + nil nil t)) ; target attributes fullness. + file))) ;;;###autoload (defun url-tramp-file-handler (operation &rest args) commit 854714efb47d3365c41a84443fa56e7e275bfb4c Author: Po Lu Date: Mon Jun 20 18:13:51 2022 +0800 Ignore pinch events from the wrong window * src/xterm.c (handle_one_xevent): Use x_window_to_frame to find frames for pinch events. diff --git a/src/xterm.c b/src/xterm.c index 12d091c1d9..b5543b873c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -21685,7 +21685,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #endif - any = x_any_window_to_frame (dpyinfo, pev->event); + any = x_window_to_frame (dpyinfo, pev->event); if (any) { inev.ie.kind = PINCH_EVENT; commit c1453cd6f6b79e050db976bcdcfe68235e45e0a7 Author: David Ponce Date: Mon Jun 20 11:39:56 2022 +0200 Make images found through `find-image' be handled like `create-image' * lisp/image.el (find-image): Use `create-image' so that we get auto-scaling of images (bug#40978). diff --git a/etc/NEWS b/etc/NEWS index dab42d83cc..f10573b86b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1880,6 +1880,12 @@ Emacs buffers, like indentation and the like. The new ert function * Incompatible Lisp Changes in Emacs 29.1 +--- +** 'find-image' now uses 'create-image'. +This means that images found through 'find-image' also has +auto-scaling applied. (This only makes a difference on HiDPI +displays.) + +++ ** Changes to "raw" in-memory xbm images are specified. Some years back Emacs gained the ability to scale images, and you diff --git a/lisp/image.el b/lisp/image.el index 1b684d5c57..24d1c2d169 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -764,13 +764,15 @@ SPECS is a list of image specifications. Each image specification in SPECS is a property list. The contents of a specification are image type dependent. All specifications must at -least contain the properties `:type TYPE' and either `:file FILE' or -`:data DATA', where TYPE is a symbol specifying the image type, -e.g. `xbm', FILE is the file to load the image from, and DATA is a -string containing the actual image data. The specification whose TYPE -is supported, and FILE exists, is used to construct the image -specification to be returned. Return nil if no specification is -satisfied. +least contain the either the property `:file FILE' or `:data DATA', +where FILE is the file to load the image from, and DATA is a string +containing the actual image data. If the property `:type TYPE' is +omitted or nil, try to determine the image type from its first few +bytes of image data. If that doesn’t work, and the property `:file +FILE' provide a file name, use its file extension as image type. If +the property `:type TYPE' is provided, it must match the actual type +determined for FILE or DATA by `create-image'. Return nil if no +specification is satisfied. If CACHE is non-nil, results are cached and returned on subsequent calls. @@ -785,22 +787,44 @@ Image files should not be larger than specified by `max-image-size'." (let* ((spec (car specs)) (type (plist-get spec :type)) (data (plist-get spec :data)) - (file (plist-get spec :file)) - found) - (when (image-type-available-p type) - (cond ((stringp file) - (if (setq found (image-search-load-path file)) - (setq image - (cons 'image (plist-put (copy-sequence spec) - :file found))))) - ((not (null data)) - (setq image (cons 'image spec))))) + (file (plist-get spec :file))) + (cond + ((stringp file) + (when (setq file (image-search-load-path file)) + ;; At this point, remove the :type and :file properties. + ;; `create-image' will set them depending on image file. + (setq image (cons 'image (copy-sequence spec))) + (setf (image-property image :type) nil) + (setf (image-property image :file) nil) + (and (setq image (ignore-errors + (apply #'create-image file nil nil + (cdr image)))) + ;; Ensure, if a type has been provided, it is + ;; consistent with the type returned by + ;; `create-image'. If not, return nil. + (not (null type)) + (not (eq type (image-property image :type))) + (setq image nil)))) + ((not (null data)) + ;; At this point, remove the :type and :data properties. + ;; `create-image' will set them depending on image data. + (setq image (cons 'image (copy-sequence spec))) + (setf (image-property image :type) nil) + (setf (image-property image :data) nil) + (and (setq image (ignore-errors + (apply #'create-image data nil t + (cdr image)))) + ;; Ensure, if a type has been provided, it is + ;; consistent with the type returned by + ;; `create-image'. If not, return nil. + (not (null type)) + (not (eq type (image-property image :type))) + (setq image nil)))) (setq specs (cdr specs)))) (when cache (setf (gethash orig-specs find-image--cache) image)) image))) - ;;;###autoload (defmacro defimage (symbol specs &optional doc) "Define SYMBOL as an image, and return SYMBOL. commit bd0b96d25295c1d29186d4a96a2215ab0239c64c Author: Lars Ingebrigtsen Date: Mon Jun 20 11:18:31 2022 +0200 Allow using :width/:height as normal with xbm images * doc/lispref/display.texi (XBM Images): Adjust the documentation. * src/image.c (enum xbm_keyword_index): Add :data-width and :data-height. (xbm_format): Ditto. (xbm_image_p): Allow passing in :width/:height for display. (xbm_load): Use :data-width/:data-height. diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 958eede977..3d1d9e24dd 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5930,13 +5930,10 @@ There are three formats you can use for @var{data}: @itemize @bullet @item A vector of strings or bool-vectors, each specifying one line of the -image. Do specify @code{:height} and @code{:width}. +image. Do specify @code{:data-height} and @code{:data-width}. @item A string containing the same byte sequence as an XBM file would contain. -You must not specify @code{:height} and @code{:width} in this case, -because omitting them is what indicates the data has the format of an -XBM file. The file contents specify the height and width of the image. @item A string or a bool-vector containing the bits of the image (plus @@ -5944,26 +5941,11 @@ perhaps some extra bits at the end that will not be used). It should contain at least @w{@code{@var{stride} * @var{height}}} bits, where @var{stride} is the smallest multiple of 8 greater than or equal to the width of the image. In this case, you should specify -@code{:height}, @code{:width} and @code{:stride}, both to indicate -that the string contains just the bits rather than a whole XBM file, -and to specify the size of the image. +@code{:data-height}, @code{:data-width} and @code{:stride}, both to +indicate that the string contains just the bits rather than a whole +XBM file, and to specify the size of the image. @end itemize -@item :width @var{width} -The value, @var{width}, specifies the width of the image, in pixels. - -@item :height @var{height} -The value, @var{height}, specifies the height of the image, in pixels. - -Note that @code{:width} and @code{:height} can only be used if passing -in data that doesn't specify the width and height (e.g., a string or a -vector containing the bits of the image). @acronym{XBM} files usually -specify this themselves, and it's an error to use these two properties -on these files. Also note that @code{:width} and @code{:height} are -used by most other image formats to specify what the displayed image -is supposed to be, which usually means performing some sort of -scaling. This isn't supported for @acronym{XBM} images. - @item :stride @var{stride} The number of bool vector entries stored for each row; the smallest multiple of 8 greater than or equal to @var{width}. diff --git a/etc/NEWS b/etc/NEWS index bf154b4b9e..dab42d83cc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1880,6 +1880,18 @@ Emacs buffers, like indentation and the like. The new ert function * Incompatible Lisp Changes in Emacs 29.1 ++++ +** Changes to "raw" in-memory xbm images are specified. +Some years back Emacs gained the ability to scale images, and you +could then specify :width and :height when using 'create-image' on all +image types -- except xbm images, because this format already used the +:width and :height arguments to specify the width/height of the "raw" +in-memory format. This meant that if you used these specifications +on, for instance, xbm files, Emacs would refuse to display them. This +has been changed, and :width/:height now works as with all other image +formats, and the way to specify the width/height of the "raw" +in-memory format is now by using :data-width and :data-height. + +++ ** loaddefs.el generation has been reimplemented. The various loaddefs.el files in the Emacs tree (which contain diff --git a/src/image.c b/src/image.c index 058c175570..2e2f8fe364 100644 --- a/src/image.c +++ b/src/image.c @@ -3723,6 +3723,8 @@ enum xbm_keyword_index XBM_ALGORITHM, XBM_HEURISTIC_MASK, XBM_MASK, + XBM_DATA_WIDTH, + XBM_DATA_HEIGHT, XBM_LAST }; @@ -3744,7 +3746,9 @@ static const struct image_keyword xbm_format[XBM_LAST] = {":relief", IMAGE_INTEGER_VALUE, 0}, {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, - {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0} + {":mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}, + {":data-width", IMAGE_POSITIVE_INTEGER_VALUE, 0}, + {":data-height", IMAGE_POSITIVE_INTEGER_VALUE, 0} }; /* Tokens returned from xbm_scan. */ @@ -3766,8 +3770,8 @@ enum xbm_token an entry `:file FILENAME' where FILENAME is a string. If the specification is for a bitmap loaded from memory it must - contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where - WIDTH and HEIGHT are integers > 0. DATA may be: + contain `:data-width WIDTH', `:data-height HEIGHT', and `:data DATA', + where WIDTH and HEIGHT are integers > 0. DATA may be: 1. a string large enough to hold the bitmap data, i.e. it must have a size >= (WIDTH + 7) / 8 * HEIGHT @@ -3777,9 +3781,7 @@ enum xbm_token 3. a vector of strings or bool-vectors, one for each line of the bitmap. - 4. a string containing an in-memory XBM file. WIDTH and HEIGHT - may not be specified in this case because they are defined in the - XBM file. + 4. a string containing an in-memory XBM file. Both the file and data forms may contain the additional entries `:background COLOR' and `:foreground COLOR'. If not present, @@ -3799,13 +3801,13 @@ xbm_image_p (Lisp_Object object) if (kw[XBM_FILE].count) { - if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count) + if (kw[XBM_DATA].count) return 0; } else if (kw[XBM_DATA].count && xbm_file_p (kw[XBM_DATA].value)) { /* In-memory XBM file. */ - if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_FILE].count) + if (kw[XBM_FILE].count) return 0; } else @@ -3814,14 +3816,14 @@ xbm_image_p (Lisp_Object object) int width, height, stride; /* Entries for `:width', `:height' and `:data' must be present. */ - if (!kw[XBM_WIDTH].count - || !kw[XBM_HEIGHT].count + if (!kw[XBM_DATA_WIDTH].count + || !kw[XBM_DATA_HEIGHT].count || !kw[XBM_DATA].count) return 0; data = kw[XBM_DATA].value; - width = XFIXNAT (kw[XBM_WIDTH].value); - height = XFIXNAT (kw[XBM_HEIGHT].value); + width = XFIXNAT (kw[XBM_DATA_WIDTH].value); + height = XFIXNAT (kw[XBM_DATA_HEIGHT].value); if (!kw[XBM_STRIDE].count) stride = width; @@ -4445,8 +4447,8 @@ xbm_load (struct frame *f, struct image *img) /* Get specified width, and height. */ if (!in_memory_file_p) { - img->width = XFIXNAT (fmt[XBM_WIDTH].value); - img->height = XFIXNAT (fmt[XBM_HEIGHT].value); + img->width = XFIXNAT (fmt[XBM_DATA_WIDTH].value); + img->height = XFIXNAT (fmt[XBM_DATA_HEIGHT].value); eassert (img->width > 0 && img->height > 0); if (!check_image_size (f, img->width, img->height)) { diff --git a/test/manual/image-circular-tests.el b/test/manual/image-circular-tests.el index edc65eee9b..1299970f82 100644 --- a/test/manual/image-circular-tests.el +++ b/test/manual/image-circular-tests.el @@ -29,22 +29,25 @@ (ert-deftest image-test-duplicate-keywords () "Test that duplicate keywords in an image spec lead to rejection." - (should-error (image-size `(image :type xbm :type xbm :width 1 :height 1 + (should-error (image-size `(image :type xbm :type xbm + :data-width 1 :data-height 1 :data ,(bool-vector t)) t))) (ert-deftest image-test-circular-plist () "Test that a circular image spec is rejected." (should-error - (let ((l `(image :type xbm :width 1 :height 1 :data ,(bool-vector t)))) + (let ((l `(image :type xbm :data-width 1 :data-height 1 + :data ,(bool-vector t)))) (setcdr (last l) '#1=(:invalid . #1#)) (image-size l t)))) (ert-deftest image-test-:type-property-value () "Test that :type is allowed as a property value in an image spec." - (should (equal (image-size `(image :dummy :type :type xbm :width 1 :height 1 - :data ,(bool-vector t)) - t) + (should (equal (image-size `(image :dummy :type :type xbm + :data-width 1 :data-height 1 + :data ,(bool-vector t)) + t) (cons 1 1)))) (ert-deftest image-test-circular-specs () @@ -52,9 +55,9 @@ (should (let* ((circ1 (cons :dummy nil)) (circ2 (cons :dummy nil)) - (spec1 `(image :type xbm :width 1 :height 1 + (spec1 `(image :type xbm :data-width 1 :data-height 1 :data ,(bool-vector 1) :ignored ,circ1)) - (spec2 `(image :type xbm :width 1 :height 1 + (spec2 `(image :type xbm :data-width 1 :data-height 1 :data ,(bool-vector 1) :ignored ,circ2))) (setcdr circ1 circ1) (setcdr circ2 circ2) commit cf4c204df8c4b01b1745452492164deca82bfcca Author: Stefan Kangas Date: Mon Jun 20 11:08:08 2022 +0200 * doc/misc/eww.texi (Overview, Basics): Fix typos. diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi index df1eb53c9d..b3ec52f7ab 100644 --- a/doc/misc/eww.texi +++ b/doc/misc/eww.texi @@ -69,7 +69,7 @@ Indices @chapter Overview @dfn{EWW}, the Emacs Web Wowser, is a web browser for GNU Emacs. It can load, parse, and display various web pages using @dfn{shr.el}. -However a GNU Emacs with @code{libxml2} support is required. +However, a GNU Emacs with @code{libxml2} support is required. @node Basics @chapter Basic Usage @@ -213,7 +213,7 @@ switch EWW buffers through a minibuffer prompt, press @kbd{s} @cindex External Browser Although EWW and shr.el do their best to render webpages in GNU Emacs some websites use features which can not be properly represented -or are not implemented (E.g., JavaScript). If you have trouble +or are not implemented (e.g., JavaScript). If you have trouble viewing a website with EWW then hit @kbd{&} (@code{eww-browse-with-external-browser}) inside the EWW buffer to open the website in the external browser specified by commit 1172c7303dbce015d12424739a56bfce00e195b1 Author: Richard Hansen Date: Mon Jun 20 09:40:38 2022 +0200 whitespace: Redraw if indentation or line length changes * lisp/whitespace.el (whitespace-color-on): Convert the indentation matcher from a static regular expression to a function so that changes to `indent-tabs-mode' and `tab-width' are picked up the next time `font-lock-flush' runs. (whitespace--indentation-matcher): The new function matcher. (whitespace--variable-watcher): New variable watcher that calls `font-lock-flush' if `whitespace-mode' is enabled for the buffer. (whitespace--watched-vars): List of variables to watch. (whitespace-unload-function): Un-watch the variables. (bug#56103). diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 7ee8a46cec..98f21ce9a5 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -2112,16 +2112,7 @@ resultant list will be returned." ,@(when (or (memq 'indentation whitespace-active-style) (memq 'indentation::tab whitespace-active-style) (memq 'indentation::space whitespace-active-style)) - `((,(cond - ((memq 'indentation whitespace-active-style) - ;; Show indentation SPACEs (indent-tabs-mode). - (whitespace-indentation-regexp)) - ((memq 'indentation::tab whitespace-active-style) - ;; Show indentation SPACEs (SPACEs). - (whitespace-indentation-regexp 'tab)) - ((memq 'indentation::space whitespace-active-style) - ;; Show indentation SPACEs (TABs). - (whitespace-indentation-regexp 'space))) + `((,#'whitespace--indentation-matcher 1 whitespace-indentation t))) ,@(when (memq 'big-indent whitespace-active-style) ;; Show big indentation. @@ -2356,6 +2347,26 @@ Also refontify when necessary." (font-lock-flush ostart (overlay-end whitespace-point--used)) (delete-overlay whitespace-point--used)))))) +(defun whitespace--indentation-matcher (limit) + "Indentation matcher for `font-lock-keywords'. +This matcher is a function instead of a static regular expression +so that the next call to `font-lock-flush' picks up any changes +to `indent-tabs-mode' and `tab-width'." + (re-search-forward + (whitespace-indentation-regexp + (cond + ((memq 'indentation whitespace-active-style) nil) + ((memq 'indentation::tab whitespace-active-style) 'tab) + ((memq 'indentation::space whitespace-active-style) 'space))) + limit t)) + +(defun whitespace--variable-watcher (_symbol _newval _op buffer) + "Variable watcher that calls `font-lock-flush' for BUFFER." + (when buffer + (with-current-buffer buffer + (when whitespace-mode + (font-lock-flush))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; Hacked from visws.el (Miles Bader ) @@ -2468,9 +2479,16 @@ It should be added buffer-locally to `write-file-functions'." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar whitespace--watched-vars + '(fill-column indent-tabs-mode tab-width whitespace-line-column)) + +(dolist (var whitespace--watched-vars) + (add-variable-watcher var #'whitespace--variable-watcher)) (defun whitespace-unload-function () "Unload the whitespace library." + (dolist (var whitespace--watched-vars) + (remove-variable-watcher var #'whitespace--variable-watcher)) (global-whitespace-mode -1) ;; be sure all local whitespace mode is turned off (save-current-buffer commit 382f7920abcf7df46b5b44462c6c71de54454b0e Author: Po Lu Date: Mon Jun 20 02:16:34 2022 +0000 Respect `:antialias' on Haiku * src/haiku_font_support.cc (BFont_find): Pass through FSPEC_ANTIALIAS. (be_set_font_antialiasing): New function. * src/haiku_support.h (enum haiku_font_specification): New enum FSPEC_ANTIALIAS. (struct haiku_font_pattern): New field `use_antialiasing'. * src/haikufont.c (haikufont_pattern_to_entity) (haikufont_spec_or_entity_to_pattern, haikufont_open): Respect antialiasing. (syms_of_haikufont): New defsym `:indices'. diff --git a/src/haiku_font_support.cc b/src/haiku_font_support.cc index ca6aaf7120..d824cc59ae 100644 --- a/src/haiku_font_support.cc +++ b/src/haiku_font_support.cc @@ -598,6 +598,12 @@ BFont_find (struct haiku_font_pattern *pt) p->last = NULL; p->next_family = r; r = p; + + if (pt->specified & FSPEC_ANTIALIAS) + { + p->specified |= FSPEC_ANTIALIAS; + p->use_antialiasing = pt->use_antialiasing; + } } else if (sty_count) { @@ -623,6 +629,12 @@ BFont_find (struct haiku_font_pattern *pt) p->family_index = fi; p->style_index = si; + if (pt->specified & FSPEC_ANTIALIAS) + { + p->specified |= FSPEC_ANTIALIAS; + p->use_antialiasing = pt->use_antialiasing; + } + if (p->specified & FSPEC_SLANT && (p->slant == SLANT_OBLIQUE || p->slant == SLANT_ITALIC)) @@ -916,3 +928,14 @@ be_find_font_indices (struct haiku_font_pattern *pattern, return 1; } + +void +be_set_font_antialiasing (void *font, bool antialias_p) +{ + BFont *font_object; + + font_object = (BFont *) font; + font_object->SetFlags (antialias_p + ? B_FORCE_ANTIALIASING + : B_DISABLE_ANTIALIASING); +} diff --git a/src/haiku_support.h b/src/haiku_support.h index 7f8d471b65..97c2b6904a 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -271,6 +271,7 @@ enum haiku_font_specification FSPEC_WIDTH = 1 << 7, FSPEC_LANGUAGE = 1 << 8, FSPEC_INDICES = 1 << 9, + FSPEC_ANTIALIAS = 1 << 10, }; typedef char haiku_font_family_or_style[64]; @@ -390,6 +391,10 @@ struct haiku_font_pattern /* Temporary field used during font enumeration. */ int oblique_seen_p; + + /* Whether or not to enable antialising in the font. This field is + special in that it's not handled by `BFont_open_pattern'. */ + int use_antialiasing; }; struct haiku_scroll_bar_value_event @@ -684,6 +689,7 @@ extern const char *be_find_setting (const char *); extern haiku_font_family_or_style *be_list_font_families (size_t *); extern void be_font_style_to_flags (char *, struct haiku_font_pattern *); extern void *be_open_font_at_index (int, int, float); +extern void be_set_font_antialiasing (void *, bool); extern int be_get_ui_color (const char *, uint32_t *); extern void BMessage_delete (void *); diff --git a/src/haikufont.c b/src/haikufont.c index 54f11c6e41..77aa400631 100644 --- a/src/haikufont.c +++ b/src/haikufont.c @@ -381,54 +381,67 @@ haikufont_maybe_handle_special_family (Lisp_Object family, static Lisp_Object haikufont_pattern_to_entity (struct haiku_font_pattern *ptn) { - Lisp_Object ent; + Lisp_Object entity, extras; + + entity = font_make_entity (); + extras = Qnil; + + ASET (entity, FONT_TYPE_INDEX, Qhaiku); + ASET (entity, FONT_FOUNDRY_INDEX, Qhaiku); + ASET (entity, FONT_FAMILY_INDEX, Qdefault); + ASET (entity, FONT_ADSTYLE_INDEX, Qnil); + ASET (entity, FONT_REGISTRY_INDEX, Qiso10646_1); + ASET (entity, FONT_SIZE_INDEX, make_fixnum (0)); + ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0)); + ASET (entity, FONT_SPACING_INDEX, make_fixnum (FONT_SPACING_MONO)); + + /* FONT_EXTRA_INDEX in a font entity can contain a cons of two + numbers (STYLE . IDX) under the key :indices that tell Emacs how + to open a font. */ + if (ptn->specified & FSPEC_INDICES) + extras = Fcons (Fcons (QCindices, + Fcons (make_fixnum (ptn->family_index), + make_fixnum (ptn->style_index))), + extras); - ent = font_make_entity (); - ASET (ent, FONT_TYPE_INDEX, Qhaiku); - ASET (ent, FONT_FOUNDRY_INDEX, Qhaiku); - ASET (ent, FONT_FAMILY_INDEX, Qdefault); - ASET (ent, FONT_ADSTYLE_INDEX, Qnil); - ASET (ent, FONT_REGISTRY_INDEX, Qiso10646_1); - ASET (ent, FONT_SIZE_INDEX, make_fixnum (0)); - ASET (ent, FONT_AVGWIDTH_INDEX, make_fixnum (0)); - ASET (ent, FONT_SPACING_INDEX, make_fixnum (FONT_SPACING_MONO)); + if (ptn->specified & FSPEC_ANTIALIAS) + extras = Fcons (Fcons (QCantialias, + ptn->use_antialiasing ? Qt : Qnil), + extras); - /* FONT_EXTRA_INDEX in a font entity can be a cons of two numbers - (STYLE . IDX) that tell Emacs how to open a font. */ - if (ptn->specified & FSPEC_INDICES) - ASET (ent, FONT_EXTRA_INDEX, - Fcons (make_fixnum (ptn->family_index), - make_fixnum (ptn->style_index))); + ASET (entity, FONT_EXTRA_INDEX, extras); - FONT_SET_STYLE (ent, FONT_WIDTH_INDEX, Qnormal); - FONT_SET_STYLE (ent, FONT_WEIGHT_INDEX, Qnormal); - FONT_SET_STYLE (ent, FONT_SLANT_INDEX, Qnormal); + FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, Qnormal); + FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, Qnormal); + FONT_SET_STYLE (entity, FONT_SLANT_INDEX, Qnormal); if (ptn->specified & FSPEC_FAMILY) - ASET (ent, FONT_FAMILY_INDEX, intern (ptn->family)); + ASET (entity, FONT_FAMILY_INDEX, intern (ptn->family)); else - ASET (ent, FONT_FAMILY_INDEX, Qdefault); + ASET (entity, FONT_FAMILY_INDEX, Qdefault); if (ptn->specified & FSPEC_STYLE) - ASET (ent, FONT_ADSTYLE_INDEX, intern (ptn->style)); + ASET (entity, FONT_ADSTYLE_INDEX, intern (ptn->style)); else { if (ptn->specified & FSPEC_WEIGHT) - FONT_SET_STYLE (ent, FONT_WEIGHT_INDEX, + FONT_SET_STYLE (entity, FONT_WEIGHT_INDEX, haikufont_weight_to_lisp (ptn->weight)); if (ptn->specified & FSPEC_SLANT) - FONT_SET_STYLE (ent, FONT_SLANT_INDEX, + FONT_SET_STYLE (entity, FONT_SLANT_INDEX, haikufont_slant_to_lisp (ptn->slant)); if (ptn->specified & FSPEC_WIDTH) - FONT_SET_STYLE (ent, FONT_WIDTH_INDEX, + FONT_SET_STYLE (entity, FONT_WIDTH_INDEX, haikufont_width_to_lisp (ptn->width)); } if (ptn->specified & FSPEC_SPACING) - ASET (ent, FONT_SPACING_INDEX, - make_fixnum (ptn->mono_spacing_p ? - FONT_SPACING_MONO : FONT_SPACING_PROPORTIONAL)); - return ent; + ASET (entity, FONT_SPACING_INDEX, + make_fixnum (ptn->mono_spacing_p + ? FONT_SPACING_MONO + : FONT_SPACING_PROPORTIONAL)); + + return entity; } static void @@ -613,6 +626,13 @@ haikufont_spec_or_entity_to_pattern (Lisp_Object ent, int list_p, } } + tem = assq_no_quit (QCantialias, AREF (ent, FONT_EXTRA_INDEX)); + if (CONSP (tem)) + { + ptn->specified |= FSPEC_ANTIALIAS; + ptn->use_antialiasing = !NILP (XCDR (tem)); + } + tem = AREF (ent, FONT_REGISTRY_INDEX); if (SYMBOLP (tem)) haikufont_apply_registry (ptn, tem); @@ -732,10 +752,10 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x) struct haiku_font_pattern ptn; struct font *font; void *be_font; - Lisp_Object font_object, tem, extra; - int px_size, min_width, max_width, - avg_width, height, space_width, ascent, - descent, underline_pos, underline_thickness; + Lisp_Object font_object, tem, extra, indices, antialias; + int px_size, min_width, max_width; + int avg_width, height, space_width, ascent; + int descent, underline_pos, underline_thickness; if (x <= 0) { @@ -746,15 +766,21 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x) extra = AREF (font_entity, FONT_EXTRA_INDEX); + indices = assq_no_quit (QCindices, extra); + antialias = assq_no_quit (QCantialias, extra); + + if (CONSP (indices)) + indices = XCDR (indices); + /* If the font's indices is already available, open the font using those instead. */ - if (CONSP (extra) && FIXNUMP (XCAR (extra)) - && FIXNUMP (XCDR (extra))) + if (CONSP (indices) && FIXNUMP (XCAR (indices)) + && FIXNUMP (XCDR (indices))) { block_input (); - be_font = be_open_font_at_index (XFIXNUM (XCAR (extra)), - XFIXNUM (XCDR (extra)), x); + be_font = be_open_font_at_index (XFIXNUM (XCAR (indices)), + XFIXNUM (XCDR (indices)), x); unblock_input (); if (!be_font) @@ -778,13 +804,8 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x) block_input (); - /* `font_make_object' tries to treat the extra data as an alist. - There is never any real data here, so clear that field. */ - - ASET (font_entity, FONT_EXTRA_INDEX, Qnil); font_object = font_make_object (VECSIZE (struct haikufont_info), font_entity, x); - ASET (font_entity, FONT_EXTRA_INDEX, extra); ASET (font_object, FONT_TYPE_INDEX, Qhaiku); font_info = (struct haikufont_info *) XFONT_OBJECT (font_object); @@ -799,6 +820,9 @@ haikufont_open (struct frame *f, Lisp_Object font_entity, int x) font_info->be_font = be_font; font_info->glyphs = xzalloc (0x100 * sizeof *font_info->glyphs); + if (CONSP (antialias)) + be_set_font_antialiasing (be_font, !NILP (XCDR (antialias))); + font->pixel_size = 0; font->driver = &haikufont_driver; font->encoding_charset = -1; @@ -1270,6 +1294,8 @@ syms_of_haikufont (void) DEFSYM (Qko, "ko"); DEFSYM (Qjp, "jp"); + DEFSYM (QCindices, ":indices"); + #ifdef USE_BE_CAIRO Fput (Qhaiku, Qfont_driver_superseded_by, Qftcr); #endif commit 9a6b6b1887c62b2f5aee75e213bd1f62bc6577f6 Author: Po Lu Date: Mon Jun 20 09:17:21 2022 +0800 Don't generate superfluous wheel events during drag and drop * src/xterm.c (handle_one_xevent): Only set user time and don't create wheel events if DND is in progress. diff --git a/src/xterm.c b/src/xterm.c index 9a31f9ea09..12d091c1d9 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -19609,6 +19609,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_display_set_last_user_time (dpyinfo, xev->time, xev->send_event); + #if defined USE_GTK && !defined HAVE_GTK3 /* Unlike on Motif, we can't select for XI events on the scroll bar window under GTK+ 2. @@ -19623,6 +19624,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto XI_OTHER; #endif + /* If this happened during a drag-and-drop + operation, don't send an event. We only have + to set the user time. */ + if (x_dnd_in_progress + && (command_loop_level + minibuf_level + <= x_dnd_recursion_depth) + && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) + goto XI_OTHER; + if (fabs (total_x) > 0 || fabs (total_y) > 0) { inev.ie.kind = (fabs (total_y) >= fabs (total_x) @@ -20853,8 +20863,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif XSETFRAME (inev.ie.frame_or_window, f); - inev.ie.modifiers - = x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), state); + inev.ie.modifiers = x_x_to_emacs_modifiers (dpyinfo, state); inev.ie.timestamp = xev->time; #ifdef HAVE_X_I18N commit 772c0e6f20f789862883e42181dd16a6ac3cb0f6 Author: Po Lu Date: Mon Jun 20 09:16:41 2022 +0800 Fix earlier change in xfaces.c for antialiasing in the mode line * src/xfaces.c (realize_gui_face): Don't put QCantialias in empty spec if it doesn't exist in the original. diff --git a/src/xfaces.c b/src/xfaces.c index 25b5e4d185..f70fe87c95 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -5910,6 +5910,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] struct face *default_face; struct frame *f; Lisp_Object stipple, underline, overline, strike_through, box, temp_spec; + Lisp_Object temp_extra, antialias; eassert (FRAME_WINDOW_P (cache->f)); @@ -5957,11 +5958,18 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] preserve the antialiasing attribute. (bug#17973, bug#37473). */ temp_spec = Ffont_spec (0, NULL); + temp_extra = AREF (attrs[LFACE_FONT_INDEX], + FONT_EXTRA_INDEX); + /* If `:antialias' wasn't specified, keep it unspecified + instead of changing it to nil. */ - if (FONTP (attrs[LFACE_FONT_INDEX])) - Ffont_put (temp_spec, QCantialias, - Ffont_get (attrs[LFACE_FONT_INDEX], - QCantialias)); + if (CONSP (temp_extra)) + antialias = Fassq (QCantialias, temp_extra); + else + antialias = Qnil; + + if (FONTP (attrs[LFACE_FONT_INDEX]) && !NILP (antialias)) + Ffont_put (temp_spec, QCantialias, Fcdr (antialias)); attrs[LFACE_FONT_INDEX] = font_load_for_lface (f, attrs, temp_spec); commit 9c359b0cec5248871fb0ddb9f1f3bc84fffd4dd5 Author: Miha Rihtaršič Date: Sun Jun 19 15:29:59 2022 +0200 xref-goto-xref: Set input focus in addition to selecting window * lisp/progmodes/xref.el (xref--show-location): Set input focus in addition to selecting displayed window (Bug#55983). diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 683589d71c..0213ab3cc5 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -645,9 +645,15 @@ SELECT is `quit', also quit the *xref* window." (xref-buffer (current-buffer))) (cond (select (if (eq select 'quit) (quit-window nil nil)) - (select-window - (with-current-buffer xref-buffer - (xref--show-pos-in-buf marker buf)))) + (let* ((old-frame (selected-frame)) + (window (with-current-buffer xref-buffer + (xref--show-pos-in-buf marker buf))) + (frame (window-frame window))) + ;; If we chose another frame, make sure it gets input + ;; focus. + (unless (eq frame old-frame) + (select-frame-set-input-focus frame)) + (select-window window))) (t (save-selected-window (xref--with-dedicated-window commit 28bfd4db69c357b708e7b711c947122faf499368 Author: Lars Ingebrigtsen Date: Mon Jun 20 02:27:00 2022 +0200 Allow removing quotes around links in *Help* buffers * doc/emacs/help.texi (Help Mode): Document it. * lisp/help-mode.el (help-clean-buttons): New user option (help-xref-button): Use it. diff --git a/doc/emacs/help.texi b/doc/emacs/help.texi index 11ee9dc2b2..d206dee385 100644 --- a/doc/emacs/help.texi +++ b/doc/emacs/help.texi @@ -542,6 +542,11 @@ previous hyperlink. These commands act cyclically; for instance, typing @key{TAB} at the last hyperlink moves back to the first hyperlink. +@vindex help-clean-buttons + By default, many links in the help buffer are displayed surrounded +by quote characters. If the @code{help-clean-buttons} user option is +non-@code{nil}, these quote characters are removed from the buffer. + @kindex n @r{(Help mode)} @kindex p @r{(Help mode)} @findex help-goto-next-page diff --git a/etc/NEWS b/etc/NEWS index 1a90cf15c0..bf154b4b9e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -581,6 +581,10 @@ or ':scream:'. ** Help +*** New user option 'help-clean-buttons'. +If non-nil, link buttons in *Help* will have any surrounding quotes +removed. + --- *** 'M-x apropos-variable' output now includes values of variables. diff --git a/lisp/help-mode.el b/lisp/help-mode.el index a50524253b..a1b03700db 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -543,6 +543,12 @@ Each element has the form (NAME TESTFUN DESCFUN) where: and a frame), inserts the description of that symbol in the current buffer and returns that text as well.") +(defcustom help-clean-buttons nil + "If non-nil, remove quotes around link buttons." + :version "29.1" + :type 'boolean + :group 'help) + ;;;###autoload (defun help-make-xrefs (&optional buffer) "Parse and hyperlink documentation cross-references in the given BUFFER. @@ -691,12 +697,26 @@ that." MATCH-NUMBER is the subexpression of interest in the last matched regexp. TYPE is the type of button to use. Any remaining arguments are passed to the button's help-function when it is invoked. -See `help-make-xrefs'." +See `help-make-xrefs'. + +This function heeds the `help-clean-buttons' variable and will +remove quotes surrounding the match if non-nil." ;; Don't mung properties we've added specially in some instances. - (unless (button-at (match-beginning match-number)) - (make-text-button (match-beginning match-number) - (match-end match-number) - 'type type 'help-args args))) + (let ((beg (match-beginning match-number)) + (end (match-end match-number))) + (unless (button-at beg) + (make-text-button beg end 'type type 'help-args args) + (when (and help-clean-buttons + (> beg (point-min)) + (save-excursion + (goto-char (1- beg)) + (looking-at "['`‘]")) + (< end (point-max)) + (save-excursion + (goto-char end) + (looking-at "['’]"))) + (delete-region end (1+ end)) + (delete-region (1- beg) beg))))) ;;;###autoload (defun help-insert-xref-button (string type &rest args) commit ac39c327b53ccfba3743a3fa0e538175541bae5c Author: Lars Ingebrigtsen Date: Mon Jun 20 02:12:06 2022 +0200 Tweak quoting in help-fns--compiler-macro * lisp/help-fns.el (help-fns--compiler-macro): Fix quotes in help text. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 6eff0b9b0e..43855cd6d7 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -622,7 +622,7 @@ the C sources, too." (pcase-dolist (`(,type . ,handler) (list (cons "compiler macro" (function-get function 'compiler-macro)) - (cons "`byte-compile' property" + (cons (substitute-command-keys "`byte-compile' property") (function-get function 'byte-compile)) (cons "byte-code optimizer" (function-get function 'byte-optimizer)))) commit 3947037a33540fa879e5465ae25b9aec61511f85 Author: Pip Cet Date: Mon Jun 20 01:59:49 2022 +0200 Fix bytecompiler infloop compiling infloops * lisp/emacs-lisp/byte-opt.el (byte-optimize-lapcode): Don't apply optimization if we can't change anything (bug#46906). diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index fc49e88f8e..1a50c5a43a 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -2060,9 +2060,9 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance." ((and (memq (car lap0) byte-goto-ops) (memq (car (setq tmp (nth 1 (memq (cdr lap0) lap)))) '(byte-goto byte-return))) - (cond ((and (not (eq tmp lap0)) - (or (eq (car lap0) 'byte-goto) - (eq (car tmp) 'byte-goto))) + (cond ((and (or (eq (car lap0) 'byte-goto) + (eq (car tmp) 'byte-goto)) + (not (eq (cdr tmp) (cdr lap0)))) (byte-compile-log-lap " %s [%s]\t-->\t%s" (car lap0) tmp tmp) (if (eq (car tmp) 'byte-return) commit efc241f4020478122d506b3d42a815ad47f7910b Author: Drew Adams Date: Mon Jun 20 01:49:24 2022 +0200 Let `dired-omit-mode' match lines, as well as file names * lisp/dired-aux.el (dired-do-kill-lines): Adjust to use it. * lisp/dired-x.el (dired-omit-line-regexp): New user option (bug#46882). (dired-omit-mode, dired-omit-expunge): Use the new user option. diff --git a/etc/NEWS b/etc/NEWS index 8103ac0d67..1a90cf15c0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1618,6 +1618,11 @@ the thumbnail file. ** Dired +--- +*** New user option 'dired-omit-line-regexp'. +This is used by 'dired-omit-mode', and now allows you to hide based on +other things than just the file names. + +++ *** New user option 'dired-mouse-drag-files'. If non-nil, dragging file names with the mouse in a Dired buffer will diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 1b7088104d..91106e0704 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -1095,45 +1095,46 @@ With a prefix argument, kill that many lines starting with the current line. (dired-move-to-filename))) ;;;###autoload -(defun dired-do-kill-lines (&optional arg fmt) - "Kill all marked lines (not the files). -With a prefix argument, kill that many lines starting with the current line. -\(A negative argument kills backward.) +(defun dired-do-kill-lines (&optional arg fmt init-count) + "Remove all marked lines, or the next ARG lines. +The files or directories on those lines are _not_ deleted. Only the +Dired listing is affected. To restore the removals, use `\\[revert-buffer]'. -If you use this command with a prefix argument to kill the line -for a file that is a directory, which you have inserted in the -Dired buffer as a subdirectory, then it deletes that subdirectory -from the buffer as well. +With a numeric prefix arg, remove that many lines going forward, +starting with the current line. (A negative prefix arg removes lines +going backward.) -To kill an entire subdirectory \(without killing its line in the -parent directory), go to its directory header line and use this -command with a prefix argument (the value does not matter). +If you use a prefix arg to remove the line for a subdir whose listing +you have inserted into the Dired buffer, then that subdir listing is +also removed. -To undo the killing, the undo command can be used as normally. +To remove a subdir listing _without_ removing the subdir's line in its +parent listing, go to the header line of the subdir listing and use +this command with any prefix arg. -This function returns the number of killed lines. +When called from Lisp, non-nil INIT-COUNT is added to the number of +lines removed by this invocation, for the reporting message. -FMT is a format string used for messaging the user about the -killed lines, and defaults to \"Killed %d line%s.\" if not -present. A FMT of \"\" will suppress the messaging." +A FMT of \"\" will suppress the messaging." + ;; Returns count of killed lines. (interactive "P") (if arg (if (dired-get-subdir) - (dired-kill-subdir) - (dired-kill-line arg)) + (dired-kill-subdir) + (dired-kill-line arg)) (save-excursion (goto-char (point-min)) - (let (buffer-read-only - (count 0) - (regexp (dired-marker-regexp))) - (while (and (not (eobp)) - (re-search-forward regexp nil t)) - (setq count (1+ count)) - (delete-region (line-beginning-position) - (progn (forward-line 1) (point)))) - (or (equal "" fmt) - (message (or fmt "Killed %d line%s.") count (dired-plural-s count))) - count)))) + (let ((count (or init-count 0)) + (regexp (dired-marker-regexp)) + (inhibit-read-only t)) + (while (and (not (eobp)) + (re-search-forward regexp nil t)) + (setq count (1+ count)) + (delete-region (line-beginning-position) + (progn (forward-line 1) (point)))) + (unless (equal "" fmt) + (message (or fmt "Killed %d line%s.") count (dired-plural-s count))) + count)))) ;;; Compression diff --git a/lisp/dired-x.el b/lisp/dired-x.el index 56036b6c16..6eb0f63ee5 100644 --- a/lisp/dired-x.el +++ b/lisp/dired-x.el @@ -125,14 +125,49 @@ folding to be used on case-insensitive filesystems only." (file-name-case-insensitive-p dir) dired-omit-case-fold)) +(defcustom dired-omit-line-regexp nil + "Regexp matching lines to be omitted by `dired-omit-mode'. +The value can also be a variable whose value is such a regexp. +The value can also be nil, which means do no line matching. + +Some predefined regexp variables for Dired, which you can use as the +option value: + +* `dired-re-inode-size' +* `dired-re-mark' +* `dired-re-maybe-mark' +* `dired-re-dir' +* `dired-re-sym' +* `dired-re-exe' +* `dired-re-perms' +* `dired-re-dot' +* `dired-re-no-dot'" + :type `(choice + (const :tag "Do not match lines to omit" nil) + (regexp + :tag "Regexp to match lines to omit (default omits executables)" + :value ,dired-re-exe) + (restricted-sexp + :tag "Variable with regexp value (default: `dired-re-exe')" + :match-alternatives + ((lambda (obj) (and (symbolp obj) (boundp obj)))) + :value dired-re-exe)) + :group 'dired-x) + ;;;###autoload (define-minor-mode dired-omit-mode "Toggle omission of uninteresting files in Dired (Dired-Omit mode). +With prefix argument ARG, enable Dired-Omit mode if ARG is positive, +and disable it otherwise. + +If called from Lisp, enable the mode if ARG is omitted or nil. + +Dired-Omit mode is a buffer-local minor mode. -Dired-Omit mode is a buffer-local minor mode. When enabled in a -Dired buffer, Dired does not list files whose filenames match -regexp `dired-omit-files', nor files ending with extensions in -`dired-omit-extensions'. +When enabled in a Dired buffer, Dired does not list files whose +filenames match regexp `dired-omit-files', files ending with +extensions in `dired-omit-extensions', or files listed on lines +matching `dired-omit-line-regexp'. To enable omitting in every Dired buffer, you can put this in your init file: @@ -141,10 +176,16 @@ your init file: See Info node `(dired-x) Omitting Variables' for more information." :group 'dired-x - (if dired-omit-mode - ;; This will mention how many lines were omitted: - (let ((dired-omit-size-limit nil)) (dired-omit-expunge)) - (revert-buffer))) + (if (not dired-omit-mode) + (revert-buffer) + (let ((dired-omit-size-limit nil) + (file-count 0)) + ;; Omit by file-name match, then omit by line match. + ;; Use count of file-name match as INIT-COUNT for line match. + ;; Return total count. (Return value is not used anywhere, so far). + (setq file-count (dired-omit-expunge)) + (when dired-omit-line-regexp + (dired-omit-expunge dired-omit-line-regexp 'LINEP file-count))))) (put 'dired-omit-mode 'safe-local-variable 'booleanp) @@ -486,45 +527,61 @@ variables `dired-omit-mode' and `dired-omit-files'." :type '(repeat string) :group 'dired-x) -(defun dired-omit-expunge (&optional regexp) - "Erases all unmarked files matching REGEXP. -Does nothing if global variable `dired-omit-mode' is nil, or if called - non-interactively and buffer is bigger than `dired-omit-size-limit'. -If REGEXP is nil or not specified, uses `dired-omit-files', and also omits - filenames ending in `dired-omit-extensions'. -If REGEXP is the empty string, this function is a no-op. - -This functions works by temporarily binding `dired-marker-char' to -`dired-omit-marker-char' and calling `dired-do-kill-lines'." - (interactive "sOmit files (regexp): ") +(defun dired-omit-expunge (&optional regexp linep init-count) + "Erase all unmarked files whose names match REGEXP. +With a prefix arg (non-nil LINEP when called from Lisp), match REGEXP +against the whole line. Otherwise, match it against the file name. + +If REGEXP is nil, use `dired-omit-files', and also omit file names +ending in `dired-omit-extensions'. + +Do nothing if REGEXP is the empty string, `dired-omit-mode' is nil, or +if called from Lisp and buffer is bigger than `dired-omit-size-limit'. + +Optional arg INIT-COUNT is an initial count tha'is added to the number +of lines omitted by this invocation of `dired-omit-expunge', in the +status message." + (interactive "sOmit files (regexp): \nP") + ;; Bind `dired-marker-char' to `dired-omit-marker-char', + ;; then call `dired-do-kill-lines'. (if (and dired-omit-mode (or (called-interactively-p 'interactive) (not dired-omit-size-limit) (< (buffer-size) dired-omit-size-limit) - (progn - (when dired-omit-verbose - (message "Not omitting: directory larger than %d characters." - dired-omit-size-limit)) - (setq dired-omit-mode nil) - nil))) + (progn + (when dired-omit-verbose + (message "Not omitting: directory larger than %d characters." + dired-omit-size-limit)) + (setq dired-omit-mode nil) + nil))) (let ((omit-re (or regexp (dired-omit-regexp))) (old-modified-p (buffer-modified-p)) - count) - (or (string= omit-re "") - (let ((dired-marker-char dired-omit-marker-char)) - (when dired-omit-verbose (message "Omitting...")) - (if (dired-mark-unmarked-files omit-re nil nil dired-omit-localp - (dired-omit-case-fold-p (if (stringp dired-directory) - dired-directory - (car dired-directory)))) - (progn - (setq count (dired-do-kill-lines - nil - (if dired-omit-verbose "Omitted %d line%s." ""))) - (force-mode-line-update)) - (when dired-omit-verbose (message "(Nothing to omit)"))))) - ;; Try to preserve modified state of buffer. So `%*' doesn't appear - ;; in mode-line of omitted buffers. + (count (or init-count 0))) + (unless (string= omit-re "") + (let ((dired-marker-char dired-omit-marker-char)) + (when dired-omit-verbose (message "Omitting...")) + (if (not (if linep + (dired-mark-if + (and (= (following-char) ?\s) ; Not already marked + (string-match-p + omit-re (buffer-substring + (line-beginning-position) + (line-end-position)))) + nil) + (dired-mark-unmarked-files + omit-re nil nil dired-omit-localp + (dired-omit-case-fold-p (if (stringp dired-directory) + dired-directory + (car dired-directory)))))) + (when dired-omit-verbose (message "(Nothing to omit)")) + (setq count (+ count + (dired-do-kill-lines + nil + (if dired-omit-verbose "Omitted %d line%s" "") + init-count))) + (force-mode-line-update)))) + ;; Try to preserve modified state, so `%*' doesn't appear in + ;; `mode-line'. (set-buffer-modified-p (and old-modified-p (save-excursion (goto-char (point-min)) commit 9bf520593c81735398c3a8369df9854586218913 Author: Stefan Kangas Date: Mon Jun 20 01:26:05 2022 +0200 Update font scaling documentation to not talk about "face height" * lisp/play/gamegrid.el (gamegrid-init-buffer): * lisp/mwheel.el (mouse-wheel-scroll-amount): (mouse-wheel-text-scale): * lisp/faces.el (set-face-attribute): * lisp/face-remap.el (text-scale-mode-step): (text-scale-increase): (text-scale-adjust): * lisp/cus-face.el (custom-face-attributes): * doc/emacs/frames.texi (Mouse Commands): * doc/emacs/display.texi (Text Scale): Talk about font sized instead of "face height" (bug#46853). diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 16d6d5567e..e065155845 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -854,7 +854,8 @@ would be selected if you click a mouse or press @key{RET}. @node Text Scale @section Text Scale -@cindex adjust buffer face height +@cindex adjust buffer font size +@cindex font size, increase or decrease @findex text-scale-adjust @kindex C-x C-+ @kindex C-x C-- @@ -862,17 +863,21 @@ would be selected if you click a mouse or press @key{RET}. @kindex C-x C-0 @kindex C-wheel-down @kindex C-wheel-up - To increase the height of the default face in the current buffer, -type @kbd{C-x C-+} or @kbd{C-x C-=}. To decrease it, type @kbd{C-x -C--}. To restore the default (global) face height, type @kbd{C-x -C-0}. These keys are all bound to the same command, -@code{text-scale-adjust}, which looks at the last key typed to -determine which action to take. + To increase the font size in the current buffer, type @kbd{C-x C-+} +or @kbd{C-x C-=}. To decrease it, type @kbd{C-x C--}. To restore the +default (global) font size, type @kbd{C-x C-0}. These keys are all +bound to the same command, @code{text-scale-adjust}, which looks at +the last key typed to determine which action to take and adjusts the +font size accordingly by changing the height of the default face. + + Most faces are affected by these font size changes, but not faces +that have an explicit @code{:height} setting. The two exceptions to +this are the @code{default} and @code{header} faces: They will both be +scaled even if they have an explicit @code{:height} setting. Similarly, scrolling the mouse wheel with the @kbd{Ctrl} modifier pressed, when the mouse pointer is above buffer text, will increase or -decrease the height of the default face, depending on the direction of -the scrolling. +decrease the font size, depending on the direction of the scrolling. The final key of these commands may be repeated without the leading @kbd{C-x}. For instance, @kbd{C-x C-= C-= C-=} increases the face @@ -882,21 +887,20 @@ of 1.2; to change this factor, customize the variable to the @code{text-scale-adjust} command restores the default height, the same as typing @kbd{C-x C-0}. -@cindex increase buffer face height +@cindex increase buffer font size @findex text-scale-increase -@cindex decrease buffer face height +@cindex decrease buffer font size @findex text-scale-decrease The commands @code{text-scale-increase} and -@code{text-scale-decrease} increase or decrease the height of the -default face, just like @kbd{C-x C-+} and @kbd{C-x C--} respectively. -You may find it convenient to bind to these commands, rather than -@code{text-scale-adjust}. +@code{text-scale-decrease} increase or decrease the size of the font +in the current buffer, just like @kbd{C-x C-+} and @kbd{C-x C--} +respectively. You may find it convenient to bind to these commands, +rather than @code{text-scale-adjust}. -@cindex set buffer face height +@cindex set buffer font size @findex text-scale-set - The command @code{text-scale-set} scales the height of the default -face in the current buffer to an absolute level specified by its -prefix argument. + The command @code{text-scale-set} scales the size of the font in the +current buffer to an absolute level specified by its prefix argument. @findex text-scale-mode The above commands automatically enable the minor mode diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index fa248c1a58..d90a6ac672 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -223,8 +223,8 @@ mouse-wheel-mode}. The variables @code{mouse-wheel-follow-mouse} and buffers are scrolled. The variable @code{mouse-wheel-progressive-speed} determines whether the scroll speed is linked to how fast you move the wheel. This mode also -supports increasing or decreasing the height of the default face, by -default bound to scrolling with the @key{Ctrl} modifier. +supports increasing or decreasing the font size, by default bound to +scrolling with the @key{Ctrl} modifier. @vindex mouse-wheel-scroll-amount-horizontal Emacs also supports horizontal scrolling with the @key{Shift} diff --git a/lisp/cus-face.el b/lisp/cus-face.el index 80d0aaa0d5..73a33f064c 100644 --- a/lisp/cus-face.el +++ b/lisp/cus-face.el @@ -83,9 +83,9 @@ (:height (choice :tag "Height" - :help-echo "Face's font height." + :help-echo "Face's font size." :value 1.0 ; default - (integer :tag "Height in 1/10 pt") + (integer :tag "Font size in 1/10 pt") (number :tag "Scale" 1.0))) (:weight diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 50306a5e8a..75d7333f8a 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -230,7 +230,8 @@ not to inherit from the global definition of FACE at all." (defcustom text-scale-mode-step 1.2 "Scale factor used by `text-scale-mode'. -Each positive or negative step scales the default face height by this amount." +Each positive or negative step scales the size of the `default' +face's font by this amount." :group 'display :type 'number :version "23.1") @@ -335,7 +336,7 @@ the same amount)." ;;;###autoload (defun text-scale-increase (inc) - "Increase the height of the default face in the current buffer by INC steps. + "Increase the font size of the default face in current buffer by INC steps. If the new height is other than the default, `text-scale-mode' is enabled. Each step scales the height of the default face by the variable @@ -347,14 +348,14 @@ will remove any scaling currently active." (new-value (if (= inc 0) 0 (+ current-value inc)))) (if (or (> new-value (text-scale-max-amount)) (< new-value (text-scale-min-amount))) - (user-error "Cannot %s the default face height more than it already is" + (user-error "Cannot %s the font size any further" (if (> inc 0) "increase" "decrease"))) (setq text-scale-mode-amount new-value)) (text-scale-mode (if (zerop text-scale-mode-amount) -1 1))) ;;;###autoload (defun text-scale-decrease (dec) - "Decrease the height of the default face in the current buffer by DEC steps. + "Decrease the font size of the default face in the current buffer by DEC steps. See `text-scale-increase' for more details." (interactive "p") (text-scale-increase (- dec))) @@ -365,19 +366,18 @@ See `text-scale-increase' for more details." ;;;###autoload (define-key ctl-x-map [(control ?0)] 'text-scale-adjust) ;;;###autoload (defun text-scale-adjust (inc) - "Adjust the height of the default face by INC. - + "Adjust the font size in the current buffer by INC steps. INC may be passed as a numeric prefix argument. The actual adjustment made depends on the final component of the keybinding used to invoke the command, with all modifiers removed: - +, = Increase the height of the default face by one step - - Decrease the height of the default face by one step - 0 Reset the height of the default face to the global default + +, = Increase font size in current buffer by one step + - Decrease font size in current buffer by one step + 0 Reset the font size to the global default After adjusting, continue to read input events and further adjust -the face height as long as the input event read +the font size as long as the input event read \(with all modifiers removed) is one of the above characters. Each step scales the height of the default face by the variable @@ -389,7 +389,12 @@ This command is a special-purpose wrapper around the `text-scale-increase' command which makes repetition convenient even when it is bound in a non-top-level keymap. For binding in a top-level keymap, `text-scale-increase' or -`text-scale-decrease' may be more appropriate." +`text-scale-decrease' may be more appropriate. + +Most faces are affected by these font size changes, but not faces +that have an explicit `:height' setting. The two exceptions to +this are the `default' and `header' faces: They will both be +scaled even if they have an explicit `:height' setting." (interactive "p") (let ((ev last-command-event) (echo-keystrokes nil)) diff --git a/lisp/faces.el b/lisp/faces.el index d92569e7cd..d104fdbc2f 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -709,14 +709,14 @@ a.k.a. `regular'), `semi-expanded' (a.k.a. `demi-expanded'), `:height' -VALUE specifies the relative or absolute height of the font. An -absolute height is an integer, and specifies font height in units -of 1/10 pt. A relative height is either a floating point number, -which specifies a scaling factor for the underlying face height; -or a function that takes a single argument (the underlying face -height) and returns the new height. Note that for the `default' -face, you must specify an absolute height (since there is nothing -for it to be relative to). +VALUE specifies the relative or absolute font size (height of the +font). An absolute height is an integer, and specifies font height in +units of 1/10 pt. A relative height is either a floating point +number, which specifies a scaling factor for the underlying face +height; or a function that takes a single argument (the underlying +face height) and returns the new height. Note that for the `default' +face, you must specify an absolute height (since there is nothing for +it to be relative to). `:weight' diff --git a/lisp/mwheel.el b/lisp/mwheel.el index be493b3653..99ba9cb687 100644 --- a/lisp/mwheel.el +++ b/lisp/mwheel.el @@ -128,8 +128,9 @@ If AMOUNT is the symbol `hscroll', this means that with MODIFIER, the mouse wheel will scroll horizontally instead of vertically. If AMOUNT is the symbol `text-scale', this means that with -MODIFIER, the mouse wheel will change the face height instead of -scrolling." +MODIFIER, the mouse wheel will change the font size instead of +scrolling (by adjusting the font height of the default face). +For more information, see `text-scale-adjust'." :group 'mouse :type '(cons (choice :tag "Normal" @@ -417,7 +418,8 @@ value of ARG, and the command uses it in subsequent scrolls." (put 'mwheel-scroll 'scroll-command t) (defun mouse-wheel-text-scale (event) - "Increase or decrease the height of the default face according to the EVENT." + "Adjust font size of the default face according to EVENT. +See also `text-scale-adjust'." (interactive (list last-input-event)) (let ((selected-window (selected-window)) (scroll-window (mouse-wheel--get-scroll-window event)) diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el index 55c9244f2e..7a850b07ee 100644 --- a/lisp/play/gamegrid.el +++ b/lisp/play/gamegrid.el @@ -458,6 +458,7 @@ convert to an Emacs image-spec instead") ;; Adjust the height of the default face to the height of the ;; images. Unlike XEmacs, Emacs doesn't allow making the default ;; face buffer-local; so we do this with an overlay. + ;; FIXME: This is not correct. See face-remap.el. (when (eq gamegrid-display-mode 'glyph) (overlay-put (make-overlay (point-min) (point-max)) 'face gamegrid-face)) commit e02ebe91379459efc9c5fc7bb9de38fcf0e59cd7 Author: Lars Ingebrigtsen Date: Mon Jun 20 00:59:14 2022 +0200 Allow appending to the kill ring with mouse selections * lisp/bindings.el (ignore-preserving-kill-region): New function. (global-map): Use it. * lisp/mouse.el (mouse-set-region, mouse-drag-region) (mouse-drag-track): Allow appending to kill ring with mouse selections (bug#32747). diff --git a/lisp/bindings.el b/lisp/bindings.el index ed1325e326..c67a104b4c 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -1339,7 +1339,15 @@ if `inhibit-field-text-motion' is non-nil." ;; can use S-tab instead to access that binding. (define-key function-key-map [S-tab] [backtab]) -(define-key global-map [mouse-movement] 'ignore) +(defun ignore-preserving-kill-region (&rest _) + "Like `ignore', but don't overwrite `last-event' if it's `kill-region'." + (declare (completion ignore)) + (interactive) + (when (eq last-command 'kill-region) + (setq this-command 'kill-region)) + nil) + +(define-key global-map [mouse-movement] #'ignore-preserving-kill-region) (define-key global-map "\C-t" 'transpose-chars) (define-key esc-map "t" 'transpose-words) diff --git a/lisp/mouse.el b/lisp/mouse.el index 14cb20c234..82c8a14693 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -1439,7 +1439,8 @@ command alters the kill ring or not." ;; Don't set this-command to `kill-region', so a following ;; C-w won't double the text in the kill ring. Ignore ;; `last-command' so we don't append to a preceding kill. - (let (this-command last-command deactivate-mark) + (let ((last-command last-command) + this-command deactivate-mark) (copy-region-as-kill beg end))) (if (numberp beg) (goto-char beg)) ;; On a text terminal, bounce the cursor. @@ -1542,6 +1543,7 @@ is dragged over to." (mouse-drag-and-drop-region start-event) ;; Give temporary modes such as isearch a chance to turn off. (run-hooks 'mouse-leave-buffer-hook) + (ignore-preserving-kill-region) (mouse-drag-track start-event))) ;; Inhibit the region-confinement when undoing mouse-drag-region @@ -1751,7 +1753,8 @@ The region will be defined with mark and point." nil start-point)) ((>= mouse-row bottom) (mouse-scroll-subr start-window (1+ (- mouse-row bottom)) - nil start-point)))))))) + nil start-point)))))) + (ignore-preserving-kill-region))) map) t (lambda () (funcall cleanup) commit 694d7984a347652bd0ff337056b9e616dc5aaee8 Author: Michael Albinus Date: Sun Jun 19 21:07:29 2022 +0200 Fix last change in tramp-adb-handle-make-process * lisp/net/tramp-adb.el (tramp-adb-handle-make-process): Fix process buffer management. diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 0c3d87cc91..ebcdf00c48 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -955,18 +955,18 @@ implementation will be used." name1 (format "%s<%d>" name i))) (setq name name1) - (with-current-buffer (tramp-get-connection-buffer v) - (unwind-protect - ;; We catch this event. Otherwise, `make-process' - ;; could be called on the local host. - (save-excursion - (save-restriction - (with-tramp-saved-connection-property v "process-name" - (with-tramp-saved-connection-property v "process-buffer" - ;; Set the new process properties. - (tramp-set-connection-property v "process-name" name) - (tramp-set-connection-property - v "process-buffer" buffer) + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + ;; Set the new process properties. + (tramp-set-connection-property v "process-name" name) + (tramp-set-connection-property v "process-buffer" buffer) + (with-current-buffer (tramp-get-connection-buffer v) + (unwind-protect + ;; We catch this event. Otherwise, + ;; `make-process' could be called on the local + ;; host. + (save-excursion + (save-restriction ;; Activate narrowing in order to save ;; BUFFER contents. Clear also the ;; modification time; otherwise we might be @@ -980,8 +980,7 @@ implementation will be used." (clear-visited-file-modtime) (narrow-to-region (point-max) (point-max)) ;; We call `tramp-adb-maybe-open-connection', - ;; in order to cleanup the prompt - ;; afterwards. + ;; in order to cleanup the prompt afterwards. (tramp-adb-maybe-open-connection v) (delete-region (point-min) (point-max)) ;; Send the command. @@ -1001,55 +1000,58 @@ implementation will be used." ;; already. (ignore-errors (set-process-query-on-exit-flag p (null noquery)) - (set-marker (process-mark p) (point)))) - - ;; Copy tmpstderr file. "process-buffer" - ;; and "process-name" must be reset already; - ;; otherwise `rename-file', `delete-file' or - ;; `insert-file-contents' will fail. - (when (and (stringp stderr) - (not (tramp-tramp-file-p stderr))) - (add-function - :after (process-sentinel p) - (lambda (_proc _msg) - (rename-file remote-tmpstderr stderr)))) - ;; Read initial output. Remove the first - ;; line, which is the command echo. - (unless (eq filter t) - (while - (progn - (goto-char (point-min)) - (not (re-search-forward "[\n]" nil t))) - (tramp-accept-process-output p 0)) - (delete-region (point-min) (point))) - ;; Provide error buffer. This shows only - ;; initial error messages; messages arriving - ;; later on will be inserted when the - ;; process is deleted. The temporary file - ;; will exist until the process is deleted. - (when (bufferp stderr) - (with-current-buffer stderr - (insert-file-contents-literally - remote-tmpstderr 'visit)) - ;; Delete tmpstderr file. - (add-function - :after (process-sentinel p) - (lambda (_proc _msg) - (with-current-buffer stderr - (insert-file-contents-literally - remote-tmpstderr 'visit nil nil 'replace)) - (delete-file remote-tmpstderr)))) - ;; Return process. - p)))) - - ;; Save exit. - ;; FIXME: Does `tramp-get-connection-process' return - ;; the proper value? - (if (string-prefix-p tramp-temp-buffer-name (buffer-name)) - (ignore-errors - (set-process-buffer (tramp-get-connection-process v) nil) - (kill-buffer (current-buffer))) - (set-buffer-modified-p bmp)))))))))) + (set-marker (process-mark p) (point)) + ;; We must flush them here already; + ;; otherwise `rename-file', `delete-file' or + ;; `insert-file-contents' will fail. + (tramp-flush-connection-property v "process-name") + (tramp-flush-connection-property + v "process-buffer") + ;; Copy tmpstderr file. + (when (and (stringp stderr) + (not (tramp-tramp-file-p stderr))) + (add-function + :after (process-sentinel p) + (lambda (_proc _msg) + (rename-file remote-tmpstderr stderr)))) + ;; Read initial output. Remove the + ;; first line, which is the command + ;; echo. + (unless (eq filter t) + (while + (progn + (goto-char (point-min)) + (not (re-search-forward "[\n]" nil t))) + (tramp-accept-process-output p 0)) + (delete-region (point-min) (point))) + ;; Provide error buffer. This shows + ;; only initial error messages; messages + ;; arriving later on will be inserted + ;; when the process is deleted. The + ;; temporary file will exist until the + ;; process is deleted. + (when (bufferp stderr) + (with-current-buffer stderr + (insert-file-contents-literally + remote-tmpstderr 'visit)) + ;; Delete tmpstderr file. + (add-function + :after (process-sentinel p) + (lambda (_proc _msg) + (with-current-buffer stderr + (insert-file-contents-literally + remote-tmpstderr 'visit nil nil 'replace)) + (delete-file remote-tmpstderr)))) + ;; Return process. + p)))) + + ;; Save exit. + (if (string-prefix-p tramp-temp-buffer-name (buffer-name)) + (ignore-errors + (set-process-buffer + (tramp-get-connection-process v) nil) + (kill-buffer (current-buffer))) + (set-buffer-modified-p bmp)))))))))))) (defun tramp-adb-handle-exec-path () "Like `exec-path' for Tramp files." commit 1de63a3969d98b47776f12b985d055caacb5a702 Author: Stefan Kangas Date: Sun Jun 19 16:35:08 2022 +0200 Fix starting eshell with missing/invalid modules defined * lisp/eshell/esh-mode.el (eshell-mode): Warn instead of failing to start when 'eshell-modules-list' has invalid entries. (Bug#54976) diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el index c21484dc45..db36909fb8 100644 --- a/lisp/eshell/esh-mode.el +++ b/lisp/eshell/esh-mode.el @@ -361,7 +361,11 @@ and the hook `eshell-exit-hook'." (unless module-shortname (error "Invalid Eshell module name: %s" module-fullname)) (unless (featurep (intern module-shortname)) - (load module-shortname)))) + (condition-case nil + (load module-shortname) + (error (lwarn 'eshell :error + "Unable to load module `%s' (defined in `eshell-modules-list')" + module-fullname)))))) (unless (file-exists-p eshell-directory-name) (eshell-make-private-directory eshell-directory-name t)) commit a7ee25e90309fdf513d778ba0ae034aaff4cc559 Author: Lars Ingebrigtsen Date: Sun Jun 19 16:21:14 2022 +0200 Make describe-repeat-maps fontify key bindings * lisp/repeat.el (describe-repeat-maps): Fontify key bindings as key bindings. diff --git a/lisp/repeat.el b/lisp/repeat.el index 94ea9f7ac1..dff3931aeb 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -557,21 +557,24 @@ Used in `repeat-mode'." (push s (alist-get (get s 'repeat-map) keymaps))))) (with-help-window (help-buffer) (with-current-buffer standard-output - (princ "A list of keymaps used by commands with the symbol property `repeat-map'.\n\n") - - (dolist (keymap (sort keymaps (lambda (a b) (string-lessp (car a) (car b))))) - (princ (format-message "`%s' keymap is repeatable by these commands:\n" - (car keymap))) - (dolist (command (sort (cdr keymap) 'string-lessp)) + (insert "A list of keymaps used by commands with the symbol property `repeat-map'.\n\n") + + (dolist (keymap (sort keymaps (lambda (a b) + (string-lessp (car a) (car b))))) + (insert (format-message + "`%s' keymap is repeatable by these commands:\n" + (car keymap))) + (dolist (command (sort (cdr keymap) #'string-lessp)) (let* ((info (help-fns--analyze-function command)) (map (list (symbol-value (car keymap)))) (desc (mapconcat (lambda (key) - (format-message "`%s'" (key-description key))) + (propertize (key-description key) + 'face 'help-key-binding)) (or (where-is-internal command map) (where-is-internal (nth 3 info) map)) ", "))) - (princ (format-message " `%s' (bound to %s)\n" command desc)))) - (princ "\n"))))))) + (insert (format-message " `%s' (bound to %s)\n" command desc)))) + (insert "\n"))))))) (provide 'repeat) commit b89b23079cba00113fbc8b658a07e884392ff3a1 Author: Eli Zaretskii Date: Sun Jun 19 17:15:40 2022 +0300 Show warnings about aborted redisplay * src/xdisp.c (redisplay_window_error): Show messages about aborted redisplay of a window as delayed-warnings. diff --git a/src/xdisp.c b/src/xdisp.c index f95aeb6149..e9dcdd7233 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -17161,9 +17161,19 @@ redisplay_windows (Lisp_Object window) } static Lisp_Object -redisplay_window_error (Lisp_Object ignore) +redisplay_window_error (Lisp_Object error_data) { displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer); + + /* When in redisplay, the error is captured and not shown. Arrange + for it to be shown later. */ + if (max_redisplay_ticks > 0 + && CONSP (error_data) + && EQ (XCAR (error_data), Qerror) + && STRINGP (XCAR (XCDR (error_data)))) + Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data), + XCAR (XCDR (error_data))), + Vdelayed_warnings_list); return Qnil; } commit b2d11d69dd49864874f8fe53669b4049e83bfce9 Author: Po Lu Date: Sun Jun 19 21:57:11 2022 +0800 More conservative fix for bug#37473 * src/xfaces.c (realize_gui_face): Add more conservative fix, since the last change makes C-x C-+ lead to weight weirdness on my machine. diff --git a/src/xfaces.c b/src/xfaces.c index 424220591b..25b5e4d185 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -5909,7 +5909,7 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] #ifdef HAVE_WINDOW_SYSTEM struct face *default_face; struct frame *f; - Lisp_Object stipple, underline, overline, strike_through, box; + Lisp_Object stipple, underline, overline, strike_through, box, temp_spec; eassert (FRAME_WINDOW_P (cache->f)); @@ -5953,17 +5953,18 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) { /* We want attrs to allow overriding most elements in the - spec, but we don't want to start with an all-nil font, - either, because then we lose attributes like - antialiasing. This should probably be fixed in a - different way, see bug#17973 and bug#37473. */ - Lisp_Object spec = copy_font_spec (attrs[LFACE_FONT_INDEX]); - Ffont_put (spec, QCfoundry, Qnil); - Ffont_put (spec, QCfamily, Qnil); - Ffont_put (spec, QCregistry, Qnil); - Ffont_put (spec, QCadstyle, Qnil); + spec (IOW, to start out as an empty font spec), but + preserve the antialiasing attribute. (bug#17973, + bug#37473). */ + temp_spec = Ffont_spec (0, NULL); + + if (FONTP (attrs[LFACE_FONT_INDEX])) + Ffont_put (temp_spec, QCantialias, + Ffont_get (attrs[LFACE_FONT_INDEX], + QCantialias)); + attrs[LFACE_FONT_INDEX] - = font_load_for_lface (f, attrs, spec); + = font_load_for_lface (f, attrs, temp_spec); } if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) { commit 7bfb35f8a7b364877c5a07297f16bc38d00f1989 Author: Lars Ingebrigtsen Date: Sun Jun 19 15:47:45 2022 +0200 Make M-S-x output better in mode that have bindings for `undefined' * lisp/simple.el (command-completion-using-modes-p): Speed up case when there's no command modes. (execute-extended-command-for-buffer): Make M-S-x output better (bug#46665). diff --git a/lisp/simple.el b/lisp/simple.el index 99c951b24b..f2b3d82a7a 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2299,7 +2299,7 @@ This function uses the `read-extended-command-predicate' user option." (defun command-completion-using-modes-p (symbol buffer) "Say whether SYMBOL has been marked as a mode-specific command in BUFFER." ;; Check the modes. - (let ((modes (command-modes symbol))) + (when-let ((modes (command-modes symbol))) ;; Common fast case: Just a single mode. (if (null (cdr modes)) (or (provided-mode-derived-p @@ -2539,7 +2539,16 @@ maps." (read-extended-command-predicate (lambda (symbol buffer) (or (command-completion-using-modes-p symbol buffer) - (where-is-internal symbol keymaps))))) + ;; Include commands that are bound in a keymap in the + ;; current buffer. + (and (where-is-internal symbol keymaps) + ;; But not if they have a command predicate that + ;; says that they shouldn't. (This is the case + ;; for `ignore' and `undefined' and similar + ;; commands commonly found in keymaps.) + (or (null (get symbol 'completion-predicate)) + (funcall (get symbol 'completion-predicate) + symbol buffer))))))) (list current-prefix-arg (read-extended-command) execute-extended-command--last-typed))) commit 46db98ece2cab6bac67c05aff1def9d910591cbb Author: Lars Ingebrigtsen Date: Sun Jun 19 15:31:04 2022 +0200 Recognize \' as a quoted quote in MySQL * lisp/progmodes/sql.el (sql-mode): Recognize \' as a quoted quote in MySQL (bug#38302). diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el index 8d25986090..ef8375e859 100644 --- a/lisp/progmodes/sql.el +++ b/lisp/progmodes/sql.el @@ -4161,28 +4161,33 @@ must tell Emacs. Here's how to do that in your init file: (setq-local sql-contains-names t) (setq-local escaped-string-quote "'") (setq-local syntax-propertize-function - (syntax-propertize-rules - ;; Handle escaped apostrophes within strings. - ("''" - (0 - (if (save-excursion (nth 3 (syntax-ppss (match-beginning 0)))) - (string-to-syntax ".") - (forward-char -1) - nil))) - ;; Propertize rules to not have /- and -* start comments. - ("\\(/-\\)" (1 ".")) - ("\\(-\\*\\)" - (1 - (if (save-excursion - (not (ppss-comment-depth - (syntax-ppss (match-beginning 1))))) - ;; If we're outside a comment, we don't let -* - ;; start a comment. - (string-to-syntax ".") - ;; Inside a comment, ignore it to avoid -*/ not - ;; being interpreted as a comment end. - (forward-char -1) - nil))))) + (eval + '(syntax-propertize-rules + ;; Handle escaped apostrophes within strings. + ((if (eq sql-product 'mysql) + "\\\\'" + "''") + (0 + (if (save-excursion + (nth 3 (syntax-ppss (match-beginning 0)))) + (string-to-syntax ".") + (forward-char -1) + nil))) + ;; Propertize rules to not have /- and -* start comments. + ("\\(/-\\)" (1 ".")) + ("\\(-\\*\\)" + (1 + (if (save-excursion + (not (ppss-comment-depth + (syntax-ppss (match-beginning 1))))) + ;; If we're outside a comment, we don't let -* + ;; start a comment. + (string-to-syntax ".") + ;; Inside a comment, ignore it to avoid -*/ not + ;; being interpreted as a comment end. + (forward-char -1) + nil)))) + t)) ;; Set syntax and font-face highlighting ;; Catch changes to sql-product and highlight accordingly (sql-set-product (or sql-product 'ansi)) ; Fixes bug#13591 commit 94d76adde1b4b2bd86168f8d703241f60d1749b2 Author: Lars Ingebrigtsen Date: Sun Jun 19 15:29:21 2022 +0200 Don't handle reverseVideo X resource specially * lisp/term/x-win.el (window-system-initialization): Don't handle reverseVideo specially (bug#32921). diff --git a/etc/NEWS b/etc/NEWS index 81b34a1643..8103ac0d67 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -151,6 +151,14 @@ of 'user-emacs-directory'. * Incompatible changes in Emacs 29.1 +--- +** Previously, the X reverseVideo value at startup was heeded for all frames. +This meant that if you had a reverseVideo resource on the initial +display, and then opened up a new frame on a display without any +explicit reverseVideo setting, it would get heeded there, too. (This +included terminal frames.) In Emacs 29, the reverseVideo X resource +is handled like all the other X resources, and set on a per-frame basis. + +++ ** 'E' in 'query-replace' now edits the replacement with exact case. Previously, this command did the same as 'e'. diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 1f29b24ef2..31fc3ba534 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1291,14 +1291,6 @@ This returns an error if any Emacs frames are X frames." (cons (cons 'width (cdr (assq 'width parsed))) default-frame-alist)))))) - ;; Check the reverseVideo resource. - (let ((case-fold-search t)) - (let ((rv (x-get-resource "reverseVideo" "ReverseVideo"))) - (if (and rv - (string-match "^\\(true\\|yes\\|on\\)$" rv)) - (setq default-frame-alist - (cons '(reverse . t) default-frame-alist))))) - ;; Set x-selection-timeout, measured in milliseconds. (let ((res-selection-timeout (x-get-resource "selectionTimeout" "SelectionTimeout"))) commit e125d4b8207a330133e49263551bb85cd1e4fd31 Author: Sébastien Miquel Date: Sun Jun 19 15:12:44 2022 +0200 Small fix in font-lock-extend-region-multiline * lisp/font-lock.el (font-lock-extend-region-multiline): Do not extend the region if `font-lock-multiline' starts at `font-lock-end' (bug#46558). diff --git a/lisp/font-lock.el b/lisp/font-lock.el index 488874a175..df0a26f4d0 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -1245,12 +1245,17 @@ Put first the functions more likely to cause a change and cheaper to compute.") (setq font-lock-beg (or (previous-single-property-change font-lock-beg 'font-lock-multiline) (point-min)))) - ;; - (when (get-text-property font-lock-end 'font-lock-multiline) - (setq changed t) - (setq font-lock-end (or (text-property-any font-lock-end (point-max) - 'font-lock-multiline nil) - (point-max)))) + ;; If `font-lock-multiline' starts at `font-lock-end', do not + ;; extend the region. + (let ((before-end (max (point-min) (1- font-lock-end))) + (new-end nil)) + (when (get-text-property before-end 'font-lock-multiline) + (setq new-end (or (text-property-any before-end (point-max) + 'font-lock-multiline nil) + (point-max))) + (when (/= new-end font-lock-end) + (setq changed t) + (setq font-lock-end new-end)))) changed)) (defun font-lock-extend-region-wholelines () commit 37f168afdd272d4094da9a975425e797f253e63b Author: Lars Ingebrigtsen Date: Sun Jun 19 15:02:01 2022 +0200 Don't lose antialiasing info when hitting `C-x C-+' * src/xfaces.c (realize_gui_face): Don't lose antialiasing info when hitting `C-x C-+' (bug#37473). diff --git a/src/xfaces.c b/src/xfaces.c index 04e5439d9d..424220591b 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -5951,8 +5951,20 @@ realize_gui_face (struct face_cache *cache, Lisp_Object attrs[LFACE_VECTOR_SIZE] emacs_abort (); } if (! FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) - attrs[LFACE_FONT_INDEX] - = font_load_for_lface (f, attrs, Ffont_spec (0, NULL)); + { + /* We want attrs to allow overriding most elements in the + spec, but we don't want to start with an all-nil font, + either, because then we lose attributes like + antialiasing. This should probably be fixed in a + different way, see bug#17973 and bug#37473. */ + Lisp_Object spec = copy_font_spec (attrs[LFACE_FONT_INDEX]); + Ffont_put (spec, QCfoundry, Qnil); + Ffont_put (spec, QCfamily, Qnil); + Ffont_put (spec, QCregistry, Qnil); + Ffont_put (spec, QCadstyle, Qnil); + attrs[LFACE_FONT_INDEX] + = font_load_for_lface (f, attrs, spec); + } if (FONT_OBJECT_P (attrs[LFACE_FONT_INDEX])) { face->font = XFONT_OBJECT (attrs[LFACE_FONT_INDEX]); commit dcb7b9f5ff853bfb18c0a27af47507d9ecd7be64 Author: Po Lu Date: Sun Jun 19 20:56:46 2022 +0800 Fix setting last user time during drag-and-drop * src/xterm.c (handle_one_xevent): Set the last user time if a button press happens during drag and drop. Mysterious problems were other seen with sending selections to a clipboard immediately afterwards on Irix 6.5. diff --git a/src/xterm.c b/src/xterm.c index 1af0f41937..9a31f9ea09 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -18662,6 +18662,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (event->type == ButtonPress) { + x_display_set_last_user_time (dpyinfo, event->xbutton.time, + event->xbutton.send_event); + dpyinfo->grabbed |= (1 << event->xbutton.button); dpyinfo->last_mouse_frame = f; if (f && !tab_bar_p) @@ -20059,6 +20062,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif if (xev->evtype == XI_ButtonPress) { + x_display_set_last_user_time (dpyinfo, xev->time, + xev->send_event); + dpyinfo->grabbed |= (1 << xev->detail); dpyinfo->last_mouse_frame = f; if (f && !tab_bar_p) commit e611dbcc7c815d321199deb380df333737bab06a Author: Stefan Kangas Date: Sun Jun 19 13:16:19 2022 +0200 Add rudimentary font-locking to edmacro-mode * lisp/edmacro.el (edmacro-label): New face. (edmacro-mode-font-lock-keywords): New variable. (edit-kbd-macro): Use font-lock in 'edmacro-mode'. Minor improvement to command substitution. diff --git a/lisp/edmacro.el b/lisp/edmacro.el index 11afb68883..debd76c43a 100644 --- a/lisp/edmacro.el +++ b/lisp/edmacro.el @@ -76,6 +76,32 @@ Default nil means to write characters above \\177 in octal notation." "C-c C-c" #'edmacro-finish-edit "C-c C-q" #'edmacro-insert-key) +(defface edmacro-label + '((default :inherit bold) + (((class color) (background dark)) :foreground "light blue") + (((min-colors 88) (class color) (background light)) :foreground "DarkBlue") + (((class color) (background light)) :foreground "blue") + (t :inherit bold)) + "Face used for labels in `edit-kbd-macro'." + :version "29.1" + :group 'kmacro) + +(defvar edmacro-mode-font-lock-keywords + `((,(rx bol (group (or "Command" "Key" "Macro") ":")) 0 'edmacro-label) + (,(rx bol + (group ";; Keyboard Macro Editor. Press ") + (group (*? any)) + (group " to finish; press ")) + (1 'font-lock-comment-face) + (2 'help-key-binding) + (3 'font-lock-comment-face) + (,(rx (group (*? any)) + (group " to cancel" (* any))) + nil nil + (1 'help-key-binding) + (2 'font-lock-comment-face))) + (,(rx (one-or-more ";") (zero-or-more any)) 0 'font-lock-comment-face))) + (defvar edmacro-store-hook) (defvar edmacro-finish-hook) (defvar edmacro-original-buffer) @@ -151,11 +177,18 @@ With a prefix argument, format the macro in a more concise way." (setq-local edmacro-original-buffer oldbuf) (setq-local edmacro-finish-hook finish-hook) (setq-local edmacro-store-hook store-hook) + (setq-local font-lock-defaults + '(edmacro-mode-font-lock-keywords nil nil nil nil)) + (setq font-lock-multiline nil) (erase-buffer) (insert (substitute-command-keys (concat + ;; When editing this, make sure to update + ;; `edmacro-mode-font-lock-keywords' to match. ";; Keyboard Macro Editor. Press \\[edmacro-finish-edit] " - "to finish; press \\`C-x k RET' to cancel.\n"))) + "to finish; press \\[kill-buffer] \\`RET' to cancel.\n") + ;; Use 'no-face argument to not conflict with font-lock. + 'no-face)) (insert ";; Original keys: " fmt "\n") (unless store-hook (insert "\nCommand: " (if cmd (symbol-name cmd) "none") "\n") commit 176256cf2f80be2a692df444c7c79e9d6575c59b Author: Stefan Kangas Date: Sun Jun 19 03:36:45 2022 +0200 * lisp/obsolete/eieio-compat.el: Add missing Obsolete-since line. diff --git a/lisp/obsolete/eieio-compat.el b/lisp/obsolete/eieio-compat.el index 8d8211b849..b31bde4efb 100644 --- a/lisp/obsolete/eieio-compat.el +++ b/lisp/obsolete/eieio-compat.el @@ -5,6 +5,7 @@ ;; Author: Eric M. Ludlam ;; Keywords: OO, lisp ;; Package: eieio +;; Obsolete-since: 29.1 ;; This file is part of GNU Emacs. commit 491fb413b1a44c7a3ac1eb101a8b1b7cd2ba04cf Author: Stefan Kangas Date: Sun Jun 19 03:29:04 2022 +0200 Prefer defvar-keymap in kmacro.el * lisp/kmacro.el (kmacro-keymap, kmacro-step-edit-map): Prefer defvar-keymap. diff --git a/lisp/kmacro.el b/lisp/kmacro.el index 5746b770a2..ea60bc35f2 100644 --- a/lisp/kmacro.el +++ b/lisp/kmacro.el @@ -164,43 +164,41 @@ macro to be executed before appending to it." ;; Keymap -(defvar kmacro-keymap - (let ((map (make-sparse-keymap))) - ;; Start, end, execute macros - (define-key map "s" #'kmacro-start-macro) - (define-key map "\C-s" #'kmacro-start-macro) - (define-key map "\C-k" #'kmacro-end-or-call-macro-repeat) - (define-key map "r" #'apply-macro-to-region-lines) - (define-key map "q" #'kbd-macro-query) ;; Like C-x q - (define-key map "d" #'kmacro-redisplay) - - ;; macro ring - (define-key map "\C-n" #'kmacro-cycle-ring-next) - (define-key map "\C-p" #'kmacro-cycle-ring-previous) - (define-key map "\C-v" #'kmacro-view-macro-repeat) - (define-key map "\C-d" #'kmacro-delete-ring-head) - (define-key map "\C-t" #'kmacro-swap-ring) - (define-key map "\C-l" #'kmacro-call-ring-2nd-repeat) - - ;; macro counter - (define-key map "\C-f" #'kmacro-set-format) - (define-key map "\C-c" #'kmacro-set-counter) - (define-key map "\C-i" #'kmacro-insert-counter) - (define-key map "\C-a" #'kmacro-add-counter) - - ;; macro editing - (define-key map "\C-e" #'kmacro-edit-macro-repeat) - (define-key map "\r" #'kmacro-edit-macro) - (define-key map "e" #'edit-kbd-macro) - (define-key map "l" #'kmacro-edit-lossage) - (define-key map " " #'kmacro-step-edit-macro) - - ;; naming and binding - (define-key map "b" #'kmacro-bind-to-key) - (define-key map "n" #'kmacro-name-last-macro) - (define-key map "x" #'kmacro-to-register) - map) - "Keymap for keyboard macro commands.") +(defvar-keymap kmacro-keymap + :doc "Keymap for keyboard macro commands." + ;; Start, end, execute macros + "s" #'kmacro-start-macro + "C-s" #'kmacro-start-macro + "C-k" #'kmacro-end-or-call-macro-repeat + "r" #'apply-macro-to-region-lines + "q" #'kbd-macro-query ;; Like C-x q + "d" #'kmacro-redisplay + + ;; macro ring + "C-n" #'kmacro-cycle-ring-next + "C-p" #'kmacro-cycle-ring-previous + "C-v" #'kmacro-view-macro-repeat + "C-d" #'kmacro-delete-ring-head + "C-t" #'kmacro-swap-ring + "C-l" #'kmacro-call-ring-2nd-repeat + + ;; macro counter + "C-f" #'kmacro-set-format + "C-c" #'kmacro-set-counter + "C-i" #'kmacro-insert-counter + "C-a" #'kmacro-add-counter + + ;; macro editing + "C-e" #'kmacro-edit-macro-repeat + "RET" #'kmacro-edit-macro + "e" #'edit-kbd-macro + "l" #'kmacro-edit-lossage + "SPC" #'kmacro-step-edit-macro + + ;; naming and binding + "b" #'kmacro-bind-to-key + "n" #'kmacro-name-last-macro + "x" #'kmacro-to-register) (defalias 'kmacro-keymap kmacro-keymap) ;;; Provide some binding for startup: @@ -1049,34 +1047,30 @@ without repeating the prefix." (defvar kmacro-step-edit-help) ;; kmacro step edit help enabled (defvar kmacro-step-edit-num-input-keys) ;; to ignore duplicate pre-command hook -(defvar kmacro-step-edit-map - (let ((map (make-sparse-keymap))) - ;; query-replace-map answers include: `act', `skip', `act-and-show', - ;; `exit', `act-and-exit', `edit', `delete-and-edit', `recenter', - ;; `automatic', `backup', `exit-prefix', and `help'.") - ;; Also: `quit', `edit-replacement' - - (set-keymap-parent map query-replace-map) - - (define-key map "\t" 'act-repeat) - (define-key map [tab] 'act-repeat) - (define-key map "\C-k" 'skip-rest) - (define-key map "c" 'automatic) - (define-key map "f" 'skip-keep) - (define-key map "q" 'quit) - (define-key map "d" 'skip) - (define-key map "\C-d" 'skip) - (define-key map "i" 'insert) - (define-key map "I" 'insert-1) - (define-key map "r" 'replace) - (define-key map "R" 'replace-1) - (define-key map "a" 'append) - (define-key map "A" 'append-end) - map) - "Keymap that defines the responses to questions in `kmacro-step-edit-macro'. +(defvar-keymap kmacro-step-edit-map + :doc "Keymap that defines the responses to questions in `kmacro-step-edit-macro'. This keymap is an extension to the `query-replace-map', allowing the following additional answers: `insert', `insert-1', `replace', `replace-1', -`append', `append-end', `act-repeat', `skip-end', `skip-keep'.") +`append', `append-end', `act-repeat', `skip-end', `skip-keep'." + ;; query-replace-map answers include: `act', `skip', `act-and-show', + ;; `exit', `act-and-exit', `edit', `delete-and-edit', `recenter', + ;; `automatic', `backup', `exit-prefix', and `help'.") + ;; Also: `quit', `edit-replacement' + :parent query-replace-map + "TAB" 'act-repeat + "" 'act-repeat + "C-k" 'skip-rest + "c" 'automatic + "f" 'skip-keep + "q" 'quit + "d" 'skip + "C-d" 'skip + "i" 'insert + "I" 'insert-1 + "r" 'replace + "R" 'replace-1 + "a" 'append + "A" 'append-end) (defun kmacro-step-edit-prompt (macro index) ;; Show step-edit prompt commit d181e410fcb26a293e8345fad54507d275fc807c Author: Lars Ingebrigtsen Date: Sun Jun 19 14:25:37 2022 +0200 Fix edebug parsing of ., * lisp/emacs-lisp/edebug.el (edebug-next-token-class): Parse ., correctly (bug#37653). diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index ad66cfc2b8..b05ec3a768 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -675,7 +675,7 @@ Maybe clear the markers and delete the symbol's edebug property?" (or (and (eq (aref edebug-read-syntax-table (following-char)) 'symbol) (not (= (following-char) ?\;))) - (memq (following-char) '(?\, ?\.))))) + (eq (following-char) ?.)))) 'symbol (aref edebug-read-syntax-table (following-char)))) diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el index 35259a796a..008e1e467b 100644 --- a/test/lisp/emacs-lisp/edebug-tests.el +++ b/test/lisp/emacs-lisp/edebug-tests.el @@ -1104,5 +1104,14 @@ This avoids potential duplicate definitions (Bug#41988)." (edebug-initial-mode 'Go-nonstop)) (eval-buffer)))) +(ert-deftest edebug-test-dot-reader () + (with-temp-buffer + (insert "(defun x () `(t .,t))") + (goto-char (point-min)) + (should (equal (save-excursion + (edebug-read-storing-offsets (current-buffer))) + (save-excursion + (read (current-buffer))))))) + (provide 'edebug-tests) ;;; edebug-tests.el ends here commit d60d96ffa0d1992b0177a34ff09aa7efea279862 Author: Michael Heerdegen Date: Tue Jun 14 15:09:31 2022 +0200 Tune when to show "Quick Help" in Ediff mode-line * lisp/vc/ediff-wind.el (ediff-refresh-mode-lines): Decide whether to display "Quick Help" in the mode-line based on the value of `ediff-use-long-help-message' instead of checking `ediff-window-setup-function' (Bug#12840). diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el index 4549b910b1..6db3667545 100644 --- a/lisp/vc/ediff-wind.el +++ b/lisp/vc/ediff-wind.el @@ -1136,9 +1136,7 @@ It assumes that it is called from within the control buffer." (if (ediff-narrow-control-frame-p) (list " " mode-line-buffer-identification) (list "-- " mode-line-buffer-identification - (and (not (eq ediff-window-setup-function - 'ediff-setup-windows-plain)) - " Quick Help")))) + (list 'ediff-use-long-help-message " Quick Help")))) ;; control buffer id (setq mode-line-buffer-identification (if (ediff-narrow-control-frame-p) commit 196eebda168aaf7fec493cf4c38207969904abf3 Author: Lars Ingebrigtsen Date: Sun Jun 19 14:17:05 2022 +0200 Make checkdoc-defun-info parsing slightly less wrong * lisp/emacs-lisp/checkdoc.el (checkdoc-defun-info): Disregard `interactive' in nested parts of the defun (bug#56052). diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index 7ae01d03b0..2cb5fa120e 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -2007,6 +2007,7 @@ from the comment." (let ((defun (looking-at "(\\(?:cl-\\)?def\\(un\\|macro\\|subst\\|advice\\|generic\\|method\\)")) (is-advice (looking-at "(defadvice")) + (defun-depth (ppss-depth (syntax-ppss))) (lst nil) (ret nil) (oo (make-vector 3 0))) ;substitute obarray for `read' @@ -2022,11 +2023,17 @@ from the comment." (setq ret (cons nil ret)) ;; Interactive (save-excursion - (setq ret (cons - (re-search-forward "^\\s-*(interactive" - (save-excursion (end-of-defun) (point)) - t) - ret))) + (push (and (re-search-forward "^\\s-*(interactive" + (save-excursion + (end-of-defun) + (point)) + t) + ;; Disregard `interactive' from other parts of + ;; the function. + (= (ppss-depth (syntax-ppss)) + (+ defun-depth 2)) + (point)) + ret)) (skip-chars-forward " \t\n") (let ((bss (buffer-substring (point) (save-excursion (forward-sexp 1) (point)))) commit 287e714fe0f8819dbfd2dea82e5432665493ff50 Author: Eli Zaretskii Date: Sun Jun 19 14:56:43 2022 +0300 Update redisplay ticks for more operations, and misc modifications * src/xdisp.c (update_redisplay_ticks): Don't disable redisplay of mini-windows. * src/regex-emacs.c (re_match_2_internal): * src/bidi.c (bidi_find_bracket_pairs, bidi_fetch_char) (bidi_paragraph_init, bidi_find_other_level_edge): Update the redisplay tick count as appropriate, when moving the iterator by one character position actually requires to examine many more positions. * doc/emacs/trouble.texi (Long Lines): * src/xdisp.c (syms_of_xdisp) : Update recommended non-zero values. diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi index 75b97ac6a8..5dc9fe0068 100644 --- a/doc/emacs/trouble.texi +++ b/doc/emacs/trouble.texi @@ -487,9 +487,9 @@ modified or until you type @kbd{C-l} (@pxref{Recentering}) in one of that buffer's windows. If you decide to customize this variable to a non-zero value, we -recommend to use a value between 50,000 and 200,000, depending on your -patience and the speed of your system. The default value is zero, -which disables this feature. +recommend to use a value between 100,000 and 1,000,000, depending on +your patience and the speed of your system. The default value is +zero, which disables this feature. @node DEL Does Not Delete @subsection If @key{DEL} Fails to Delete diff --git a/src/bidi.c b/src/bidi.c index 4d2c74b17c..267b62fb0b 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -1277,6 +1277,12 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos, SET_TEXT_POS (pos, charpos, bytepos); *disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p, disp_prop); + /* The factor of 100 below is a heuristic that needs to be + tuned. It means we consider 100 buffer positions examined by + the above call roughly equivalent to the display engine + iterating over a single buffer position. */ + if (*disp_pos > charpos) + update_redisplay_ticks ((*disp_pos - charpos) / 100 + 1, w); } /* Fetch the character at BYTEPOS. */ @@ -1385,6 +1391,8 @@ bidi_fetch_char (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t *disp_pos, SET_TEXT_POS (pos, charpos + *nchars, bytepos + *ch_len); *disp_pos = compute_display_string_pos (&pos, string, w, frame_window_p, disp_prop); + if (*disp_pos > charpos + *nchars) + update_redisplay_ticks ((*disp_pos - charpos - *nchars) / 100 + 1, w); } return ch; @@ -1583,6 +1591,9 @@ bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte) return pos_byte; } +/* This tracks how far we needed to search for first strong character. */ +static ptrdiff_t nsearch_for_strong; + /* On a 3.4 GHz machine, searching forward for a strong directional character in a long paragraph full of weaks or neutrals takes about 1 ms for each 20K characters. The number below limits each call to @@ -1652,6 +1663,8 @@ find_first_strong_char (ptrdiff_t pos, ptrdiff_t bytepos, ptrdiff_t end, pos += *nchars; bytepos += *ch_len; } + + nsearch_for_strong += pos - pos1; return type; } @@ -1681,6 +1694,9 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) calls to BYTE_TO_CHAR and its ilk. */ ptrdiff_t begbyte = string_p ? 0 : BEGV_BYTE; ptrdiff_t end = string_p ? bidi_it->string.schars : ZV; + ptrdiff_t pos = bidi_it->charpos; + + nsearch_for_strong = 0; /* Special case for an empty buffer. */ if (bytepos == begbyte && bidi_it->charpos == end) @@ -1702,7 +1718,7 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) else if (dir == NEUTRAL_DIR) /* P2 */ { ptrdiff_t ch_len, nchars; - ptrdiff_t pos, disp_pos = -1; + ptrdiff_t disp_pos = -1; int disp_prop = 0; bidi_type_t type; const unsigned char *s; @@ -1800,6 +1816,14 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, bool no_default_p) bidi_it->level_stack[0].level = 0; bidi_line_init (bidi_it); + + /* The factor of 50 below is a heuristic that needs to be tuned. It + means we consider 50 buffer positions examined by this function + roughly equivalent to the display engine iterating over a single + buffer position. */ + ptrdiff_t nexamined = bidi_it->charpos - pos + nsearch_for_strong; + if (nexamined > 0) + update_redisplay_ticks (nexamined / 50, bidi_it->w); } @@ -2566,6 +2590,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) bidi_bracket_type_t btype; bidi_type_t type = bidi_it->type; bool retval = false; + ptrdiff_t n = 0; /* When scanning backwards, we don't expect any unresolved bidi bracket characters. */ @@ -2695,6 +2720,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) } old_sidx = bidi_it->stack_idx; type = bidi_resolve_weak (bidi_it); + n++; /* Skip level runs excluded from this isolating run sequence. */ new_sidx = bidi_it->stack_idx; if (bidi_it->level_stack[new_sidx].level > current_level @@ -2718,6 +2744,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) goto give_up; } type = bidi_resolve_weak (bidi_it); + n++; } } if (type == NEUTRAL_B @@ -2794,6 +2821,12 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it) } give_up: + /* The factor of 20 below is a heuristic that needs to be tuned. It + means we consider 20 buffer positions examined by this function + roughly equivalent to the display engine iterating over a single + buffer position. */ + if (n > 0) + update_redisplay_ticks (n / 20 + 1, bidi_it->w); return retval; } @@ -3363,6 +3396,7 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag) else { int new_level; + ptrdiff_t pos0 = bidi_it->charpos; /* If we are at end of level, its edges must be cached. */ if (end_flag) @@ -3398,6 +3432,12 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, bool end_flag) bidi_cache_iterator_state (bidi_it, 1, 1); } } while (new_level >= level); + /* The factor of 50 below is a heuristic that needs to be + tuned. It means we consider 50 buffer positions examined by + the above call roughly equivalent to the display engine + iterating over a single buffer position. */ + if (bidi_it->charpos > pos0) + update_redisplay_ticks ((bidi_it->charpos - pos0) / 50 + 1, bidi_it->w); } } diff --git a/src/dispnew.c b/src/dispnew.c index 9d587ea00e..4509262ea6 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -2732,18 +2732,23 @@ set_frame_matrix_frame (struct frame *f) operations in window matrices of frame_matrix_frame. */ static void -make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_matrix, int row) +make_current (struct glyph_matrix *desired_matrix, + struct glyph_matrix *current_matrix, int row) { struct glyph_row *current_row = MATRIX_ROW (current_matrix, row); struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row); bool mouse_face_p = current_row->mouse_face_p; /* If we aborted redisplay of this window, a row in the desired - matrix might not have its hash computed. */ - if (!(!desired_row->used[0] - && !desired_row->used[1] - && !desired_row->used[2]) - && !desired_row->hash) + matrix might not have its hash computed. But update_window + relies on each row having its correct hash, so do it here if + needed. */ + if (!desired_row->hash + /* A glyph row that is not completely empty is unlikely to have + a zero hash value. */ + && !(!desired_row->used[0] + && !desired_row->used[1] + && !desired_row->used[2])) desired_row->hash = row_hash (desired_row); /* Do current_row = desired_row. This exchanges glyph pointers diff --git a/src/regex-emacs.c b/src/regex-emacs.c index 8662fe8d6d..4d87418eea 100644 --- a/src/regex-emacs.c +++ b/src/regex-emacs.c @@ -33,6 +33,7 @@ #include "buffer.h" #include "syntax.h" #include "category.h" +#include "dispextern.h" /* Maximum number of duplicates an interval can allow. Some systems define this in other header files, but we want our value, so remove @@ -3953,6 +3954,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp, and need to test it, it's not garbage. */ re_char *match_end = NULL; + /* This keeps track of how many buffer/string positions we examined. */ + ptrdiff_t nchars = 0; + #ifdef DEBUG_COMPILES_ARGUMENTS /* Counts the total number of registers pushed. */ ptrdiff_t num_regs_pushed = 0; @@ -4209,6 +4213,12 @@ re_match_2_internal (struct re_pattern_buffer *bufp, unbind_to (count, Qnil); SAFE_FREE (); + /* The factor of 50 below is a heuristic that needs to be tuned. It + means we consider 50 buffer positions examined by this function + roughly equivalent to the display engine iterating over a single + buffer position. */ + if (nchars > 0) + update_redisplay_ticks (nchars / 50 + 1, NULL); return dcnt; } @@ -4261,6 +4271,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, p += pat_charlen; d += buf_charlen; mcnt -= pat_charlen; + nchars++; } while (mcnt > 0); else @@ -4298,6 +4309,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, p += pat_charlen; d++; mcnt -= pat_charlen; + nchars++; } while (mcnt > 0); @@ -4321,6 +4333,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, DEBUG_PRINT (" Matched \"%d\".\n", *d); d += buf_charlen; + nchars++; } break; @@ -4373,6 +4386,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, goto fail; d += len; + nchars++; } break; @@ -4492,6 +4506,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, goto fail; } d += dcnt, d2 += dcnt; + nchars++; } } break; @@ -4773,10 +4788,12 @@ re_match_2_internal (struct re_pattern_buffer *bufp, ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; UPDATE_SYNTAX_TABLE (charpos); GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; s1 = SYNTAX (c1); UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1); PREFETCH_NOLIMIT (); GET_CHAR_AFTER (c2, d, dummy); + nchars++; s2 = SYNTAX (c2); if (/* Case 2: Only one of S1 and S2 is Sword. */ @@ -4812,6 +4829,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, UPDATE_SYNTAX_TABLE (charpos); PREFETCH (); GET_CHAR_AFTER (c2, d, dummy); + nchars++; s2 = SYNTAX (c2); /* Case 2: S2 is not Sword. */ @@ -4822,6 +4840,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if (!AT_STRINGS_BEG (d)) { GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; UPDATE_SYNTAX_TABLE_BACKWARD (charpos - 1); s1 = SYNTAX (c1); @@ -4852,6 +4871,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; UPDATE_SYNTAX_TABLE (charpos); GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; s1 = SYNTAX (c1); /* Case 2: S1 is not Sword. */ @@ -4863,6 +4883,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, { PREFETCH_NOLIMIT (); GET_CHAR_AFTER (c2, d, dummy); + nchars++; UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1); s2 = SYNTAX (c2); @@ -4893,6 +4914,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, UPDATE_SYNTAX_TABLE (charpos); PREFETCH (); c2 = RE_STRING_CHAR (d, target_multibyte); + nchars++; s2 = SYNTAX (c2); /* Case 2: S2 is neither Sword nor Ssymbol. */ @@ -4903,6 +4925,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if (!AT_STRINGS_BEG (d)) { GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; UPDATE_SYNTAX_TABLE_BACKWARD (charpos - 1); s1 = SYNTAX (c1); @@ -4931,6 +4954,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, ptrdiff_t charpos = SYNTAX_TABLE_BYTE_TO_CHAR (offset) - 1; UPDATE_SYNTAX_TABLE (charpos); GET_CHAR_BEFORE_2 (c1, d, string1, end1, string2, end2); + nchars++; s1 = SYNTAX (c1); /* Case 2: S1 is neither Ssymbol nor Sword. */ @@ -4942,6 +4966,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, { PREFETCH_NOLIMIT (); c2 = RE_STRING_CHAR (d, target_multibyte); + nchars++; UPDATE_SYNTAX_TABLE_FORWARD (charpos + 1); s2 = SYNTAX (c2); @@ -4973,6 +4998,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if ((SYNTAX (c) != (enum syntaxcode) mcnt) ^ not) goto fail; d += len; + nchars++; } } break; @@ -4999,6 +5025,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, if ((!CHAR_HAS_CATEGORY (c, mcnt)) ^ not) goto fail; d += len; + nchars++; } } break; @@ -5060,6 +5087,9 @@ re_match_2_internal (struct re_pattern_buffer *bufp, unbind_to (count, Qnil); SAFE_FREE (); + if (nchars > 0) + update_redisplay_ticks (nchars / 50 + 1, NULL); + return -1; /* Failure to match. */ } diff --git a/src/xdisp.c b/src/xdisp.c index 1d52bbc6c9..f95aeb6149 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -17218,7 +17218,10 @@ update_redisplay_ticks (int ticks, struct window *w) } /* Some callers can be run in contexts unrelated to display code, so don't abort them and don't update the tick count in those cases. */ - if (!w && !redisplaying_p && !display_working_on_window_p) + if ((!w && !redisplaying_p && !display_working_on_window_p) + /* We never disable redisplay of a mini-window, since that is + absolutely essential for communicating with Emacs. */ + || (w && MINI_WINDOW_P (w))) return; if (ticks > 0) @@ -36765,7 +36768,7 @@ You can also decide to kill the buffer and visit it in some other way, like under `so-long-mode' or literally. The default value is zero, which disables this feature. -The recommended non-zero value is between 50000 and 200000, +The recommended non-zero value is between 100000 and 1000000, depending on your patience and the speed of your system. */); max_redisplay_ticks = 0; } commit 93b018c664e1f95b41d0239c651a79a237edfc38 Author: Lars Ingebrigtsen Date: Sun Jun 19 13:37:10 2022 +0200 Add mechanism for gradually phasing in new byte compilation warnings * lisp/Makefile.in (BYTE_COMPILE_FLAGS): Enable all byte compilation warnings. * lisp/emacs-lisp/bytecomp.el (byte-compile-warning-types): Add docstrings-non-ascii-quotes and document new semantics for `all' and t. (byte-compile--emacs-build-warning-types): New constant. (byte-compile-warning-enabled-p): Implement the new semantics. (byte-compile-docstring-style-warn): Reinstate the Unicode quote warning. diff --git a/lisp/Makefile.in b/lisp/Makefile.in index 8728467977..9516f2fc36 100644 --- a/lisp/Makefile.in +++ b/lisp/Makefile.in @@ -67,7 +67,8 @@ AUTOGENEL = ${loaddefs} ${srcdir}/cus-load.el ${srcdir}/finder-inf.el \ # Set load-prefer-newer for the benefit of the non-bootstrappers. BYTE_COMPILE_FLAGS = \ - --eval '(setq load-prefer-newer t)' $(BYTE_COMPILE_EXTRA_FLAGS) + --eval "(setq load-prefer-newer t byte-compile-warnings 'all)" \ + $(BYTE_COMPILE_EXTRA_FLAGS) # ... but we must prefer .elc files for those in the early bootstrap. # A larger `max-specpdl-size' is needed for emacs-lisp/comp.el. compile-first: BYTE_COMPILE_FLAGS = \ diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 7f408472da..2ae9aa13bb 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -299,10 +299,10 @@ The information is logged to `byte-compile-log-buffer'." '(redefine callargs free-vars unresolved obsolete noruntime interactive-only make-local mapcar constants suspicious lexical lexical-dynamic - docstrings not-unused) + docstrings docstrings-non-ascii-quotes not-unused) "The list of warning types used when `byte-compile-warnings' is t.") (defcustom byte-compile-warnings t - "List of warnings that the byte-compiler should issue (t for all). + "List of warnings that the byte-compiler should issue (t for almost all). Elements of the list may be: @@ -327,15 +327,28 @@ Elements of the list may be: `byte-compile-docstring-max-column' or `fill-column' characters, whichever is bigger) or have other stylistic issues. + docstrings-non-ascii-quotes docstrings that have non-ASCII quotes. + This depends on the `docstrings' warning type. suspicious constructs that usually don't do what the coder wanted. If the list begins with `not', then the remaining elements specify warnings to -suppress. For example, (not mapcar) will suppress warnings about mapcar." +suppress. For example, (not mapcar) will suppress warnings about mapcar. + +The t value means \"all non experimental warning types\", and +excludes the types in `byte-compile--emacs-build-warning-types'. +A value of `all' really means all." :type `(choice (const :tag "All" t) (set :menu-tag "Some" ,@(mapcar (lambda (x) `(const ,x)) byte-compile-warning-types)))) +(defconst byte-compile--emacs-build-warning-types + '(docstrings-non-ascii-quotes) + "List of warning types that are only enabled during Emacs builds. +This is typically either warning types that are being phased in +(but shouldn't be enabled for packages yet), or that are only relevant +for the Emacs build itself.") + (defvar byte-compile--suppressed-warnings nil "Dynamically bound by `with-suppressed-warnings' to suppress warnings.") @@ -354,10 +367,15 @@ suppress. For example, (not mapcar) will suppress warnings about mapcar." (memq symbol (cdr elem))) (setq suppress t))) (and (not suppress) - (or (eq byte-compile-warnings t) - (if (eq (car byte-compile-warnings) 'not) - (not (memq warning byte-compile-warnings)) - (memq warning byte-compile-warnings)))))) + ;; During an Emacs build, we want all warnings. + (or (eq byte-compile-warnings 'all) + ;; If t, we want almost all the warnings, but not the + ;; ones that are Emacs build specific. + (and (not (memq warning byte-compile--emacs-build-warning-types)) + (or (eq byte-compile-warnings t) + (if (eq (car byte-compile-warnings) 'not) + (not (memq warning byte-compile-warnings)) + (memq warning byte-compile-warnings)))))))) ;;;###autoload (defun byte-compile-disable-warning (warning) @@ -1761,7 +1779,14 @@ 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))))) + kind name)) + ;; There's a "Unicode quote" in the string -- it should probably + ;; be an ASCII one instead. + (when (byte-compile-warning-enabled-p 'docstrings-non-ascii-quotes) + (when (string-match-p "\\( \"\\|[ \t]\\|^\\)[‘’]" docs) + (byte-compile-warn-x + name "%s%sdocstring has wrong usage of \"fancy\" single quotation marks" + kind name)))))) form) ;; If we have compiled any calls to functions which are not known to be commit 76f3878e287542ffaa40126528fc0cb2dc6a2a3d Author: Po Lu Date: Sun Jun 19 15:21:46 2022 +0800 Ignore emulated mouse clicks during drag-and-drop * src/xterm.c (handle_one_xevent): Don't set dpyinfo->grab and last mouse frame for emulated mouse events during a drag-and-drop operation. diff --git a/src/xterm.c b/src/xterm.c index 455d5b795e..1af0f41937 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -20050,19 +20050,29 @@ handle_one_xevent (struct x_display_info *dpyinfo, { f = mouse_or_wdesc_frame (dpyinfo, xev->event); - if (xev->evtype == XI_ButtonPress) + /* Don't track grab status for emulated pointer + events, because they are ignored by the regular + mouse click processing code. */ +#ifdef XIPointerEmulated + if (!(xev->flags & XIPointerEmulated)) { - dpyinfo->grabbed |= (1 << xev->detail); - dpyinfo->last_mouse_frame = f; - if (f && !tab_bar_p) - f->last_tab_bar_item = -1; +#endif + if (xev->evtype == XI_ButtonPress) + { + dpyinfo->grabbed |= (1 << xev->detail); + dpyinfo->last_mouse_frame = f; + if (f && !tab_bar_p) + f->last_tab_bar_item = -1; #if ! defined (USE_GTK) - if (f && !tool_bar_p) - f->last_tool_bar_item = -1; + if (f && !tool_bar_p) + f->last_tool_bar_item = -1; #endif /* not USE_GTK */ + } + else + dpyinfo->grabbed &= ~(1 << xev->detail); +#ifdef XIPointerEmulated } - else - dpyinfo->grabbed &= ~(1 << xev->detail); +#endif if (xev->evtype == XI_ButtonPress && x_dnd_last_seen_window != None commit 823b503c9da3d69a369bfeb1c2496cd22933360a Author: Po Lu Date: Sun Jun 19 13:32:27 2022 +0800 Fix crashes when the _EMACS_DRAG_ATOM is the wrong type * src/xterm.c (xm_get_drag_atom_1): Don't use PropModeAppend if rc != Success. diff --git a/src/xterm.c b/src/xterm.c index d83a56a6cb..455d5b795e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2299,8 +2299,9 @@ xm_get_drag_atom_1 (struct x_display_info *dpyinfo, XChangeProperty (dpyinfo->display, dpyinfo->root_window, dpyinfo->Xatom_EMACS_DRAG_ATOM, XA_ATOM, 32, - (rc == Success && (actual_format != 32 - || actual_type != XA_ATOM) + (rc != Success + || (actual_format != 32 + || actual_type != XA_ATOM) ? PropModeReplace : PropModeAppend), (unsigned char *) &atom, 1); commit 6d0148c5412b0a08dc36cfe1e1814e4804d3f422 Merge: ec6f6d23eb 422f958030 Author: Stefan Kangas Date: Sun Jun 19 06:30:29 2022 +0200 Merge from origin/emacs-28 422f958030 Fix invalid defcustom :group when :predicate is used commit ec6f6d23eb37ebd4fad17eb02730bf463aa27c5a Author: Po Lu Date: Sun Jun 19 12:22:12 2022 +0800 Fix XDND from Firefox again * lisp/x-dnd.el (x-dnd-handle-xdnd): Prevent nil from appearing in format 32 list. (x-dnd-handle-motif): Send reply if the user quit out of the drop handler as well. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index d4aa68a10d..22277033f5 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -636,24 +636,26 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." timestamp))) success action) (x-display-set-last-user-time timestamp) - (setq action (if value - (condition-case info - (x-dnd-drop-data event frame window value - (x-dnd-current-type window)) - (error - (message "Error: %s" info) - nil)))) - (setq success (if action 1 0)) - (when (>= version 2) - (x-send-client-message - frame dnd-source frame "XdndFinished" 32 - (list (string-to-number - (frame-parameter frame 'outer-window-id)) - (if (>= version 5) success 0) ;; 1 = Success, 0 = Error - (when (>= version 5) - (if (not success) 0 - (car (rassoc action - x-dnd-xdnd-to-action))))))) + (unwind-protect + (setq action (if value + (condition-case info + (x-dnd-drop-data + event frame window value + (x-dnd-current-type window)) + (error + (message "Error: %s" info) + nil)))) + (setq success (if action 1 0)) + (when (>= version 2) + (x-send-client-message + frame dnd-source frame "XdndFinished" 32 + (list (string-to-number + (frame-parameter frame 'outer-window-id)) + (if (>= version 5) success 0) ;; 1 = Success, 0 = Error + (if (or (not success) (< version 5)) 0 + (or (car (rassoc action + x-dnd-xdnd-to-action)) + 0)))))) (x-dnd-forget-drop window))) (t (error "Unknown XDND message %s %s" message data)))) @@ -981,24 +983,25 @@ Return a vector of atoms containing the selection targets." "_MOTIF_DRAG_AND_DROP_MESSAGE" 8 reply) - (setq action - (when (and reply-action atom-name) - (let* ((value (x-get-selection-internal - (intern atom-name) - (intern (x-dnd-current-type window)) - timestamp))) - (when value - (condition-case info - (x-dnd-drop-data event frame window value - (x-dnd-current-type window)) - (error - (message "Error: %s" info) - nil)))))) - (x-get-selection-internal - (intern atom-name) - (if action 'XmTRANSFER_SUCCESS 'XmTRANSFER_FAILURE) - timestamp) - (x-dnd-forget-drop frame)))) + (unwind-protect + (setq action + (when (and reply-action atom-name) + (let* ((value (x-get-selection-internal + (intern atom-name) + (intern (x-dnd-current-type window)) + timestamp))) + (when value + (condition-case info + (x-dnd-drop-data event frame window value + (x-dnd-current-type window)) + (error + (message "Error: %s" info) + nil)))))) + (x-get-selection-internal + (intern atom-name) + (if action 'XmTRANSFER_SUCCESS 'XmTRANSFER_FAILURE) + timestamp) + (x-dnd-forget-drop frame))))) (t (message "Unknown Motif drag-and-drop message: %s" (logand (aref data 0) #x3f))))))) commit fd853c71a958e3156014378fdd145e6e4d8c2717 Author: Po Lu Date: Sun Jun 19 11:35:12 2022 +0800 Cache the Motif drag window to avoid fetching it every time * src/xterm.c (xm_get_drag_window_1): New function. (xm_get_drag_window): Cache the window. If it already exists, just return it. (xm_setup_dnd_targets): If a BadWindow error occurs, re-create the Motif drag window. * src/xterm.h (struct x_display_info): New field `motif_drag_window'. diff --git a/src/xterm.c b/src/xterm.c index f9f3e938e0..d83a56a6cb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1805,7 +1805,7 @@ xm_drag_window_io_error_handler (Display *dpy) } static Window -xm_get_drag_window (struct x_display_info *dpyinfo) +xm_get_drag_window_1 (struct x_display_info *dpyinfo) { Atom actual_type, _MOTIF_DRAG_WINDOW; int rc, actual_format; @@ -1975,6 +1975,16 @@ xm_get_drag_window (struct x_display_info *dpyinfo) return drag_window; } +static Window +xm_get_drag_window (struct x_display_info *dpyinfo) +{ + if (dpyinfo->motif_drag_window != None) + return dpyinfo->motif_drag_window; + + dpyinfo->motif_drag_window = xm_get_drag_window_1 (dpyinfo); + return dpyinfo->motif_drag_window; +} + static int xm_setup_dnd_targets (struct x_display_info *dpyinfo, Atom *targets, int ntargets) @@ -1984,6 +1994,7 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, unsigned char *tmp_data = NULL; unsigned long nitems, bytes_remaining; int rc, actual_format, idx; + bool had_errors; xm_targets_table_header header; xm_targets_table_rec **recs; xm_byte_order byteorder; @@ -1991,6 +2002,8 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, ptrdiff_t total_bytes, total_items, i; uint32_t size, target_count; + retry_drag_window: + drag_window = xm_get_drag_window (dpyinfo); if (drag_window == None || ntargets > 64) @@ -2003,12 +2016,26 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, sizeof (Atom), x_atoms_compare); XGrabServer (dpyinfo->display); + + x_catch_errors (dpyinfo->display); rc = XGetWindowProperty (dpyinfo->display, drag_window, dpyinfo->Xatom_MOTIF_DRAG_TARGETS, 0L, LONG_MAX, False, dpyinfo->Xatom_MOTIF_DRAG_TARGETS, &actual_type, &actual_format, &nitems, &bytes_remaining, &tmp_data) == Success; + had_errors = x_had_errors_p (dpyinfo->display); + x_uncatch_errors (); + + /* The drag window is probably invalid, so remove our record of + it. */ + if (had_errors) + { + dpyinfo->motif_drag_window = None; + XUngrabServer (dpyinfo->display); + + goto retry_drag_window; + } if (rc && tmp_data && !bytes_remaining && actual_type == dpyinfo->Xatom_MOTIF_DRAG_TARGETS diff --git a/src/xterm.h b/src/xterm.h index 3ef523d782..3d243f3eab 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -578,6 +578,9 @@ struct x_display_info /* The frame that currently owns `motif_drag_atom'. */ struct frame *motif_drag_atom_owner; + /* The drag window for this display. */ + Window motif_drag_window; + /* Extended window manager hints, Atoms supported by the window manager and atoms for setting the window type. */ Atom Xatom_net_supported, Xatom_net_supporting_wm_check; commit 3285901e9a87f083bf88ac732a3ed2eae6488fec Author: Po Lu Date: Sun Jun 19 10:31:33 2022 +0800 Fix timestamps recorded in Motif DND top level leave messages * src/xterm.c (xm_send_top_level_leave_message): Use X_SHRT_MAX since Motif treats x and y as signed. (handle_one_xevent): Use correct time for lmsg.timestamp sent in response to entering the return-frame. diff --git a/src/xterm.c b/src/xterm.c index 885344229a..f9f3e938e0 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2454,8 +2454,13 @@ xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source, XM_DROP_SITE_NONE, x_dnd_motif_operations, XM_DROP_ACTION_DROP_CANCEL); mmsg.timestamp = dmsg->timestamp; - mmsg.x = 65535; - mmsg.y = 65535; + + /* Use X_SHRT_MAX instead of the max value of uint16_t since + that will be interpreted as a plausible position by Motif, + and as such breaks if the drop target is beneath that + position. */ + mmsg.x = X_SHRT_MAX; + mmsg.y = X_SHRT_MAX; xm_send_drag_motion_message (dpyinfo, source, target, &mmsg); } @@ -19757,7 +19762,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, XM_DRAG_REASON_TOP_LEVEL_LEAVE); lmsg.byteorder = XM_BYTE_ORDER_CUR_FIRST; lmsg.zero = 0; - lmsg.timestamp = event->xmotion.time; + lmsg.timestamp = xev->time; lmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); if (x_dnd_motif_setup_p) commit 8b45e7c6811215a0b70ade840c96e920cdb1569f Author: Stefan Kangas Date: Sat Jun 18 19:56:09 2022 +0200 Prefer defvar-keymap in edmacro.el * lisp/edmacro.el (edmacro-mode-map): Prefer defvar-keymap. diff --git a/lisp/edmacro.el b/lisp/edmacro.el index 04adabd06b..11afb68883 100644 --- a/lisp/edmacro.el +++ b/lisp/edmacro.el @@ -72,11 +72,9 @@ Default nil means to write characters above \\177 in octal notation." :type 'boolean :group 'kmacro) -(defvar edmacro-mode-map - (let ((map (make-sparse-keymap))) - (define-key map "\C-c\C-c" #'edmacro-finish-edit) - (define-key map "\C-c\C-q" #'edmacro-insert-key) - map)) +(defvar-keymap edmacro-mode-map + "C-c C-c" #'edmacro-finish-edit + "C-c C-q" #'edmacro-insert-key) (defvar edmacro-store-hook) (defvar edmacro-finish-hook) commit 4f3c1eb4c5c1404c2f2726e36a4803f4fd6257b1 Author: Stefan Kangas Date: Sat Jun 18 16:01:45 2022 +0200 Respect no-face argument in literal key substitutions * lisp/help.el (substitute-command-keys): Respect 'no-face' argument also in literal key substitutions. * test/lisp/help-tests.el (help-tests-substitute-key-bindings/help-key-binding-face): Rename from help-tests-substitute-key-bindings/face-help-key-binding. (help-tests-substitute-key-bindings/help-key-binding-no-face): New test. diff --git a/lisp/help.el b/lisp/help.el index 766bae0845..2d02b22e52 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1176,9 +1176,10 @@ Otherwise, return a new string." ((and (not (string-match-p "\\`M-x " k)) (not (key-valid-p k))) (error "Invalid key sequence in substitution: `%s'" k)))) - (add-text-properties orig-point (point) - '( face help-key-binding - font-lock-face help-key-binding))) + (unless no-face + (add-text-properties orig-point (point) + '( face help-key-binding + font-lock-face help-key-binding)))) ;; 1C. \[foo] is replaced with the keybinding. ((and (= (following-char) ?\[) (save-excursion diff --git a/test/lisp/help-tests.el b/test/lisp/help-tests.el index 9c9dddcd19..14a1fb49ae 100644 --- a/test/lisp/help-tests.el +++ b/test/lisp/help-tests.el @@ -100,11 +100,19 @@ (should-error (substitute-command-keys "\\`c-c'")) (should-error (substitute-command-keys "\\`'"))) -(ert-deftest help-tests-substitute-key-bindings/face-help-key-binding () - (should (eq (get-text-property 0 'face (substitute-command-keys "\\[next-line]")) - 'help-key-binding)) - (should (eq (get-text-property 0 'face (substitute-command-keys "\\`f'")) - 'help-key-binding))) +(ert-deftest help-tests-substitute-key-bindings/help-key-binding-face () + (let ((A (substitute-command-keys "\\[next-line]")) + (B (substitute-command-keys "\\`f'"))) + (should (eq (get-text-property 0 'face A) 'help-key-binding)) + (should (eq (get-text-property 0 'face B) 'help-key-binding)))) + +(ert-deftest help-tests-substitute-key-bindings/help-key-binding-no-face () + (let ((A (substitute-command-keys "\\[next-line]" t)) + (B (substitute-command-keys "\\`f'" t))) + (should (eq (get-text-property 0 'face A) nil)) + (should (eq (get-text-property 0 'face B) nil)) + (should (equal A "C-n")) + (should (equal B "f")))) (defvar-keymap help-tests--test-keymap :doc "Just some keymap for testing." commit e8bb4aba71b651f5b661ad9c3ed798e95c6fd212 Author: Stefan Kangas Date: Sat Jun 18 15:54:28 2022 +0200 ; * etc/NEWS: Move Bookmark items to separate heading. diff --git a/etc/NEWS b/etc/NEWS index f9eb81908b..81b34a1643 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1636,6 +1636,22 @@ For example, the regexp ".*" will match only characters that are part of the file name. Also "^.*$" can be used to match at the beginning of the file name and at the end of the file name. +** Bookmarks + +--- +*** 'list-bookmarks' now includes a type column. +Types are registered via a 'bookmark-handler-type' symbol property on +the jumping function. + ++++ +*** 'bookmark-sort-flag' can now be set to 'last-modified'. +This will display bookmark list from most recently set to least +recently set. + +--- +*** When editing a bookmark annotation, 'C-c C-k' will now cancel. +It is bound to the new command 'bookmark-edit-annotation-cancel'. + ** Exif --- @@ -1796,20 +1812,6 @@ The resulting tables can display text in variable pitch fonts, text using fonts of different sizes, and images. See the "(vtable) Top" manual for more details. ---- -*** 'list-bookmarks' now includes a type column. -Types are registered via a 'bookmark-handler-type' symbol property on -the jumping function. - -+++ -*** 'bookmark-sort-flag' can now be set to 'last-modified'. -This will display bookmark list from most recently set to least -recently set. - ---- -*** When editing a bookmark annotation, 'C-c C-k' will now cancel. -It is bound to the new command 'bookmark-edit-annotation-cancel'. - --- *** New minor mode 'elide-head-mode'. Enabling this minor mode turns on hiding header material, like commit 4e68166d77cdd0f3b84c9bf5681f6a95e51ad238 Author: Basil L. Contovounesios Date: Sat Jun 18 19:52:31 2022 +0300 Fix last tty-select-active-regions change * lisp/frame.el (tty-select-active-regions): Pacify warning about missing defcustom :group by specifying the same group as select-active-regions, as well as the frames group. * src/keyboard.c (command_loop_1, syms_of_keyboard): Rename last occurrences of xterm-select-active-regions to tty-select-active-regions (bug#55883). diff --git a/lisp/frame.el b/lisp/frame.el index a6aa4475dd..6996bb2e9c 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2155,6 +2155,8 @@ On a text-mode terminal that supports setSelection command, if this variable is non-nil, Emacs will set the PRIMARY selection from the active region, according to `select-active-regions'. This is currently supported only on xterm." + :group 'frames + :group 'killing :version "29.1" :type 'boolean) diff --git a/src/keyboard.c b/src/keyboard.c index cd92cf8d4a..e62b2e56d3 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1572,7 +1572,7 @@ command_loop_1 (void) `select-active-regions' is non-nil. */ if ((!NILP (Fwindow_system (Qnil)) || ((symval = - find_symbol_value (Qxterm_select_active_regions), + find_symbol_value (Qtty_select_active_regions), (!EQ (symval, Qunbound) && !NILP (symval))) && !NILP (Fterminal_parameter (Qnil, Qxterm__set_selection)))) @@ -12170,7 +12170,7 @@ syms_of_keyboard (void) DEFSYM (Qgui_set_selection, "gui-set-selection"); DEFSYM (Qxterm__set_selection, "xterm--set-selection"); - DEFSYM (Qxterm_select_active_regions, "xterm-select-active-regions"); + DEFSYM (Qtty_select_active_regions, "tty-select-active-regions"); /* The primary selection. */ DEFSYM (QPRIMARY, "PRIMARY"); commit 9b44824620fd500b9e7094bd1a8ca23608cb2e5b Author: Alan Mackenzie Date: Sat Jun 18 16:41:57 2022 +0000 CC Mode: Add accurate handling for backslash in C line and block comments This is needed to handle the idiosyncratic meaning of backslash in comments in the C and C++ standards. * lisp/progmodes/cc-engine.el: Correct a spelling error. * lisp/progmodes/cc-mode.el (c-before-change-fix-comment-escapes) (c-after-change-fix-comment-escapes): New functions. * lisp/progmodes/cc-langs.el (c-get-state-before-change-functions): Add c-before-change-fix-comment-escapes to the C/Objc and C++ values. (c-before-font-lock-functions): Add c-after-change-fix-comment-escapes to the C/Objc and C++ values. diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index f9c33f5149..cfbb668bae 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -6837,7 +6837,7 @@ comment at the start of cc-engine.el for more info." (let ((type (c-syntactic-content from to c-recognize-<>-arglists))) (unless (gethash type c-found-types) (puthash type t c-found-types) - (when (and (not c-record-found-types) ; Only call `c-fontify-new-fount-type' + (when (and (not c-record-found-types) ; Only call `c-fontify-new-found-type' ; when we haven't "bound" c-found-types ; to itself in c-forward-<>-arglist. (eq (string-match c-symbol-key type) 0) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 68070cd058..c5964165c8 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -458,12 +458,14 @@ so that all identifiers are recognized as words.") c-before-change-check-<>-operators c-truncate-bs-cache c-before-change-check-unbalanced-strings - c-parse-quotes-before-change) + c-parse-quotes-before-change + c-before-change-fix-comment-escapes) (c objc) '(c-extend-region-for-CPP c-depropertize-CPP c-truncate-bs-cache c-before-change-check-unbalanced-strings - c-parse-quotes-before-change) + c-parse-quotes-before-change + c-before-change-fix-comment-escapes) java '(c-parse-quotes-before-change c-before-change-check-unbalanced-strings c-before-change-check-<>-operators) @@ -500,6 +502,7 @@ parameters \(point-min) and \(point-max).") c-after-change-mark-abnormal-strings c-change-expand-fl-region) (c objc) '(c-depropertize-new-text + c-after-change-fix-comment-escapes c-after-change-escape-NL-in-string c-parse-quotes-after-change c-after-change-mark-abnormal-strings @@ -507,6 +510,7 @@ parameters \(point-min) and \(point-max).") c-neutralize-syntax-in-CPP c-change-expand-fl-region) c++ '(c-depropertize-new-text + c-after-change-fix-comment-escapes c-after-change-escape-NL-in-string c-after-change-unmark-ml-strings c-parse-quotes-after-change diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index ae96cdbd2f..70fc1cb73a 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1979,6 +1979,87 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") (defvar c-new-id-is-type nil) (make-variable-buffer-local 'c-new-id-is-type) +(defun c-before-change-fix-comment-escapes (beg end) + "Remove punctuation syntax-table text properties from C/C++ comment markers. +This is to handle the rare case of two or more backslashes at an +end of line in a // comment or the equally rare case of a +backslash preceding the terminator of a /* comment, as \\*/. + +This function is used solely as a member of +`c-get-state-before-change-functions', where it should appear +late in that variable, and it must be used only together with +`c-after-change-fix-comment-escapes'. + +Note that the function currently only handles comments beginning +with // and /*, not more generic line and block comments." + (c-save-buffer-state (end-state) + (setq end-state (c-full-pp-to-literal end)) + (when (memq (cadr end-state) '(c c++)) + (goto-char (max (- beg 2) (point-min))) + (if (eq (cadr end-state) 'c) + (when (search-forward "\\*/" + (or (cdr (caddr end-state)) (point-max)) t) + (c-clear-char-property (match-beginning 0) 'syntax-table) + (c-truncate-lit-pos-cache (match-beginning 0))) + (while (search-forward "\\\\\n" + (or (cdr (caddr end-state)) (point-max)) t) + (c-clear-char-property (match-beginning 0) 'syntax-table) + (c-truncate-lit-pos-cache (match-beginning 0))))))) + +(defun c-after-change-fix-comment-escapes (beg end _old-len) + "Apply punctuation syntax-table text properties to C/C++ comment markers. +This is to handle the rare case of two or more backslashes at an +end of line in a // comment or the equally rare case of a +backslash preceding the terminator of a /* comment, as \\*/. + +This function is used solely as a member of +`c-before-font-lock-functions', where it should appear early in +that variable, and it must be used only together with +`c-before-change-fix-comment-escapes'. + +Note that the function currently only handles comments beginning +with // and /*, not more generic line and block comments." + (c-save-buffer-state (state) + ;; We cannot use `c-full-pp-to-literal' in this function, since the + ;; `syntax-table' text properties after point are not yet in a consistent + ;; state. + (setq state (c-semi-pp-to-literal beg)) + (goto-char (if (memq (cadr state) '(c c++)) + (caddr state) + (max (- beg 2) (point-min)))) + (while + (re-search-forward "\\\\\\(\\(\\\\\n\\)\\|\\(\\*/\\)\\)" + (min (+ end 2) (point-max)) t) + (setq state (c-semi-pp-to-literal (match-beginning 0))) + (when (cond + ((eq (cadr state) 'c) + (match-beginning 3)) + ((eq (cadr state) 'c++) + (match-beginning 2))) + (c-put-char-property (match-beginning 0) 'syntax-table '(1)) + (c-truncate-lit-pos-cache (match-beginning 0)))) + + (goto-char end) + (setq state (c-semi-pp-to-literal (point))) + (cond + ((eq (cadr state) 'c) + (when (search-forward "*/" nil t) + (when (eq (char-before (match-beginning 0)) ?\\) + (c-put-char-property (1- (match-beginning 0)) 'syntax-table '(1)) + (c-truncate-lit-pos-cache (1- (match-beginning 0)))))) + ((eq (cadr state) 'c++) + (while + (progn + (end-of-line) + (and (eq (char-before) ?\\) + (progn + (when (eq (char-before (1- (point))) ?\\) + (c-put-char-property (- (point) 2) 'syntax-table '(1)) + (c-truncate-lit-pos-cache (1- (point)))) + t) + (not (eobp)))) + (forward-char)))))) + (defun c-update-new-id (end) ;; Note the bounds of any identifier that END is in or just after, in ;; `c-new-id-start' and `c-new-id-end'. Otherwise set these variables to @@ -1990,7 +2071,6 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") c-new-id-end (and id-beg (progn (c-end-of-current-token) (point))))))) - (defun c-post-command () ;; If point was inside of a new identifier and no longer is, record that ;; fact. commit 7e1f84fa3bc7dfd84415813889c91070c0759da2 Author: Eli Zaretskii Date: Sat Jun 18 19:21:21 2022 +0300 Fix test failures due to 'xterm-select-active-regions' * lisp/frame.el (tty-select-active-regions): Rename from xterm-select-active-regions and move here from xterm.c. (display-selections-p): Adjust to the above. (Bug#55883) diff --git a/etc/NEWS b/etc/NEWS index 438cec9257..f9eb81908b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -509,8 +509,8 @@ the 'COLORTERM' environment variable is set to the value "truecolor". *** Select active regions with xterm selection support. On terminals with xterm setSelection support, the active region may be saved to the X primary selection, following the -'select-active-regions' variable. This support is enabled with -'xterm-select-active-regions'. +'select-active-regions' variable. This support is enabled when +'tty-select-active-regions' is non-nil. ** ERT diff --git a/lisp/frame.el b/lisp/frame.el index 35863c0135..a6aa4475dd 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2149,8 +2149,14 @@ frame's display)." (defalias 'display-multi-frame-p #'display-graphic-p) (defalias 'display-multi-font-p #'display-graphic-p) -;; From term/xterm.el -(defvar xterm-select-active-regions) +(defcustom tty-select-active-regions nil + "If non-nil, update PRIMARY window-system selection on text-mode frames. +On a text-mode terminal that supports setSelection command, if +this variable is non-nil, Emacs will set the PRIMARY selection +from the active region, according to `select-active-regions'. +This is currently supported only on xterm." + :version "29.1" + :type 'boolean) (defun display-selections-p (&optional display) "Return non-nil if DISPLAY supports selections. @@ -2167,7 +2173,7 @@ frame's display)." (not (null dos-windows-version)))) ((memq frame-type '(x w32 ns pgtk)) t) - ((and xterm-select-active-regions + ((and tty-select-active-regions (terminal-parameter nil 'xterm--set-selection)) t) (t diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index 0791780d40..a7e257f41c 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el @@ -80,14 +80,6 @@ capabilities, and only when that terminal understands bracketed paste." :version "28.1" :type 'boolean) -(defcustom xterm-select-active-regions nil - "If non-nil, update PRIMARY X selection on text-mode frames. -On a text-mode terminal that supports setSelection command, if -this variable is non-nil, Emacs will set the PRIMARY selection -from the active region, according to `select-active-regions'." - :version "29.1" - :type 'boolean) - (defconst xterm-paste-ending-sequence "\e[201~" "Characters sent by the terminal to end a bracketed paste.") commit 233b3dc7e167298611d96af923abb8009f587179 Author: Basil L. Contovounesios Date: Sat Jun 18 18:26:17 2022 +0300 ; Pacify byte-compiler warning in keymap-tests.el. diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el index eeac1dbe6d..18f292d215 100644 --- a/test/src/keymap-tests.el +++ b/test/src/keymap-tests.el @@ -419,6 +419,8 @@ g .. h foo (should-error (text-char-description ?\s-c))) (ert-deftest test-non-key-events () + ;; Dummy command. + (declare-function keymap-tests-command nil) (should (null (where-is-internal 'keymap-tests-command))) (keymap-set global-map "C-c g" #'keymap-tests-command) (should (equal (where-is-internal 'keymap-tests-command) '([3 103]))) commit 2ebe0524e823c2b811f484bd4df977df5fa49203 Author: Mattias Engdegård Date: Sat Jun 18 15:15:57 2022 +0200 More aggressive bytecode split between top-level forms (bug#55972) * lisp/emacs-lisp/bytecomp.el (byte-compile-keep-pending): Allow bytecode split between all kinds of top-level forms, not just those with chunk handlers, to prevent individual chunks from growing too large. In particular this helps compilation of package-quickstart.el. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index d28ec0be16..7f408472da 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -2521,13 +2521,12 @@ list that represents a doc string reference. (defun byte-compile-keep-pending (form &optional handler) (if (memq byte-optimize '(t source)) (setq form (byte-optimize-one-form form t))) + ;; To avoid consing up monstrously large forms at load time, we split + ;; the output regularly. + (when (nthcdr 300 byte-compile-output) + (byte-compile-flush-pending)) (if handler (let ((byte-compile--for-effect t)) - ;; To avoid consing up monstrously large forms at load time, we split - ;; the output regularly. - (and (memq (car-safe form) '(fset defalias)) - (nthcdr 300 byte-compile-output) - (byte-compile-flush-pending)) (funcall handler form) (if byte-compile--for-effect (byte-compile-discard))) commit 608f349cd29e9754279d963e33e19eb46b849882 Author: Lars Ingebrigtsen Date: Sat Jun 18 14:17:45 2022 +0200 Fix checkdoc--fix-y-or-n-p query * lisp/emacs-lisp/checkdoc.el (checkdoc--fix-y-or-n-p): Fix the query to match what's done (bug#56053). diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index 5700afbb03..7ae01d03b0 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -2628,7 +2628,7 @@ a space as a style error." (checkdoc-autofix-ask-replace (match-beginning 0) (match-end 0) (format-message - "`y-or-n-p' argument should end with \"? \". Fix?") + "`y-or-n-p' argument should end with \"?\". Fix?") "?\"" t)) nil (checkdoc-create-error commit 422f958030f1c105c8f62f670b82875559b38e69 Author: Richard Hansen Date: Sat Jun 18 14:11:01 2022 +0200 Fix invalid defcustom :group when :predicate is used * lisp/emacs-lisp/easy-mmode.el (define-globalized-minor-mode): Fix invalid `:group' argument for the `-modes' defcustom that is created when `:predicate' is used (bug#56049). diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index 1d93fe4801..df37903503 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -555,7 +555,7 @@ and nil means \"don't use\". There's an implicit nil at the end of the list." mode) :type '(repeat sexp) - :group ,group)) + ,@group)) ;; Autoloading define-globalized-minor-mode autoloads everything ;; up-to-here. commit 0dc75daf1189d2327c6efa4d747fa98fcba03ea3 Author: Lars Ingebrigtsen Date: Sat Jun 18 14:06:00 2022 +0200 Filter out NS non-key events from `where-is-internal' * doc/lispref/keymaps.texi (Scanning Keymaps): Document it. * lisp/keymap.el (make-non-key-event): New function. * lisp/term/common-win.el (x-setup-function-keys): Mark ns events as not being keys (bug#55940). * src/keymap.c (Fwhere_is_internal): Filter out key sequences that are marked as being non-keys. diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index a037c228f1..a27b0ea366 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -2209,6 +2209,11 @@ If @var{no-remap} is @code{nil}, return the bindings for non-@code{nil}, return the bindings for @var{command}, ignoring the fact that it is remapped. @end table + +If a command maps to a key binding like @code{[some-event]}, and +@code{some-event} has a symbol plist containing a non-@code{nil} +@code{non-key-event} property, then that binding is ignored by +@code{where-is-internal}. @end defun @deffn Command describe-bindings &optional prefix buffer-or-name diff --git a/etc/NEWS b/etc/NEWS index a9c8957dfb..438cec9257 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2363,6 +2363,12 @@ option. ** Keymaps and key definitions ++++ +*** 'where-is-internal' can now filter events marked as non key events. +If a command maps to a key binding like [some-event], and 'some-event' +has a symbol plist containing a non-nil 'non-key-event' property, then +that binding is ignored by 'where-is-internal'. + +++ *** New functions for defining and manipulating keystrokes. These all take the syntax defined by 'key-valid-p'. None of the older diff --git a/lisp/keymap.el b/lisp/keymap.el index 3a22610499..ad7d4fbbba 100644 --- a/lisp/keymap.el +++ b/lisp/keymap.el @@ -575,6 +575,11 @@ as the variable documentation string. (define-keymap ,@(nreverse opts) ,@defs) ,@(and doc (list doc))))) +(defun make-non-key-event (symbol) + "Mark SYMBOL as an event that shouldn't be returned from `where-is'." + (put symbol 'non-key-event t) + symbol) + (provide 'keymap) ;;; keymap.el ends here diff --git a/lisp/term/common-win.el b/lisp/term/common-win.el index 6f1e322aba..f7faba9cb7 100644 --- a/lisp/term/common-win.el +++ b/lisp/term/common-win.el @@ -59,20 +59,19 @@ (setq system-key-alist (list ;; These are special "keys" used to pass events from C to lisp. - (cons 1 'ns-power-off) - (cons 2 'ns-open-file) - (cons 3 'ns-open-temp-file) - (cons 4 'ns-drag-file) - (cons 5 'ns-drag-color) - (cons 6 'ns-drag-text) - (cons 8 'ns-open-file-line) -;;; (cons 9 'ns-insert-working-text) -;;; (cons 10 'ns-delete-working-text) - (cons 11 'ns-spi-service-call) - (cons 12 'ns-new-frame) - (cons 13 'ns-toggle-toolbar) - (cons 14 'ns-show-prefs) - )))) + (cons 1 (make-non-key-event 'ns-power-off)) + (cons 2 (make-non-key-event 'ns-open-file)) + (cons 3 (make-non-key-event 'ns-open-temp-file)) + (cons 4 (make-non-key-event 'ns-drag-file)) + (cons 5 (make-non-key-event 'ns-drag-color)) + (cons 6 (make-non-key-event 'ns-drag-text)) + (cons 8 (make-non-key-event 'ns-open-file-line)) +;;; (cons 9 (make-non-key-event 'ns-insert-working-text)) +;;; (cons 10 (make-non-key-event 'ns-delete-working-text)) + (cons 11 (make-non-key-event 'ns-spi-service-call)) + (cons 12 (make-non-key-event 'ns-new-frame)) + (cons 13 (make-non-key-event 'ns-toggle-toolbar)) + (cons 14 (make-non-key-event 'ns-show-prefs)))))) (set-terminal-parameter frame 'x-setup-function-keys t))) (defvar x-invocation-args) diff --git a/src/keymap.c b/src/keymap.c index c8b01eed6f..2b77a7fc44 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -2596,7 +2596,10 @@ The optional 5th arg NO-REMAP alters how command remapping is handled: - If DEFINITION is remapped to OTHER-COMMAND, normally return the bindings for OTHER-COMMAND. But if NO-REMAP is non-nil, return the - bindings for DEFINITION instead, ignoring its remapping. */) + bindings for DEFINITION instead, ignoring its remapping. + +Keys that are represented as events that have a `non-key-event' non-nil +symbol property are ignored. */) (Lisp_Object definition, Lisp_Object keymap, Lisp_Object firstonly, Lisp_Object noindirect, Lisp_Object no_remap) { /* The keymaps in which to search. */ @@ -2720,7 +2723,12 @@ The optional 5th arg NO-REMAP alters how command remapping is handled: /* It is a true unshadowed match. Record it, unless it's already been seen (as could happen when inheriting keymaps). */ - if (NILP (Fmember (sequence, found))) + if (NILP (Fmember (sequence, found)) + /* Filter out non key events. */ + && !(VECTORP (sequence) + && ASIZE (sequence) == 1 + && SYMBOLP (AREF (sequence, 0)) + && !NILP (Fget (AREF (sequence, 0), Qnon_key_event)))) found = Fcons (sequence, found); /* If firstonly is Qnon_ascii, then we can return the first @@ -3461,4 +3469,6 @@ that describe key bindings. That is why the default is nil. */); DEFSYM (Qkey_parse, "key-parse"); DEFSYM (Qkey_valid_p, "key-valid-p"); + + DEFSYM (Qnon_key_event, "non-key-event"); } diff --git a/test/src/keymap-tests.el b/test/src/keymap-tests.el index 69aa723849..eeac1dbe6d 100644 --- a/test/src/keymap-tests.el +++ b/test/src/keymap-tests.el @@ -418,6 +418,16 @@ g .. h foo (should-error (text-char-description ?\M-c)) (should-error (text-char-description ?\s-c))) +(ert-deftest test-non-key-events () + (should (null (where-is-internal 'keymap-tests-command))) + (keymap-set global-map "C-c g" #'keymap-tests-command) + (should (equal (where-is-internal 'keymap-tests-command) '([3 103]))) + (keymap-set global-map "" #'keymap-tests-command) + (should (equal (where-is-internal 'keymap-tests-command) + '([keymap-tests-event] [3 103]))) + (make-non-key-event 'keymap-tests-event) + (should (equal (where-is-internal 'keymap-tests-command) '([3 103])))) + (provide 'keymap-tests) ;;; keymap-tests.el ends here commit d7265d58f8dbab8049be4be0fa3f474e7fef7be6 Author: Po Lu Date: Sat Jun 18 12:03:18 2022 +0000 Remove unnecessary clearing of internal border on Haiku * src/haikuterm.c (haiku_new_font): Don't clear internal border. diff --git a/src/haikuterm.c b/src/haikuterm.c index 365b23cd92..a90955ebe7 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -286,11 +286,16 @@ haiku_clear_frame (struct frame *f) static Lisp_Object haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset) { - struct font *font = XFONT_OBJECT (font_object); + struct font *font; + int ascent, descent, unit; + + font = XFONT_OBJECT (font_object); + if (fontset < 0) fontset = fontset_from_font (font_object); FRAME_FONTSET (f) = fontset; + if (FRAME_FONT (f) == font) return font_object; @@ -298,12 +303,11 @@ haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_BASELINE_OFFSET (f) = font->baseline_offset; FRAME_COLUMN_WIDTH (f) = font->average_width; - int ascent, descent; get_font_ascent_descent (font, &ascent, &descent); FRAME_LINE_HEIGHT (f) = ascent + descent; FRAME_TAB_BAR_HEIGHT (f) = FRAME_TAB_BAR_LINES (f) * FRAME_LINE_HEIGHT (f); - int unit = FRAME_COLUMN_WIDTH (f); + unit = FRAME_COLUMN_WIDTH (f); if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit; @@ -311,13 +315,10 @@ haiku_new_font (struct frame *f, Lisp_Object font_object, int fontset) FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit; if (FRAME_HAIKU_WINDOW (f) && !FRAME_TOOLTIP_P (f)) - { - adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), - FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), - 3, false, Qfont); + adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), + FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), + 3, false, Qfont); - haiku_clear_under_internal_border (f); - } return font_object; } commit 606275e91ec57cccabeb4ac2feb93753f734cb00 Author: Lars Ingebrigtsen Date: Sat Jun 18 13:26:14 2022 +0200 Allow pretty-printing results from `C-x C-e' in edebug * doc/lispref/edebug.texi (Edebug Eval): Document it. * lisp/emacs-lisp/edebug.el (edebug-eval-expression): Allow displaying the full value in a different buffer. diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi index 377cd21da8..622578bcf1 100644 --- a/doc/lispref/edebug.texi +++ b/doc/lispref/edebug.texi @@ -719,7 +719,8 @@ Evaluate expression @var{exp} in the context of Edebug itself Evaluate the expression before point, in the context outside of Edebug (@code{edebug-eval-last-sexp}). With the prefix argument of zero (@kbd{C-u 0 C-x C-e}), don't shorten long items (like strings and -lists). +lists). Any other prefix will result in the value being +pretty-printed in a separate buffer. @end table @cindex lexical binding (Edebug) diff --git a/etc/NEWS b/etc/NEWS index f195a721f4..a9c8957dfb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1030,6 +1030,12 @@ which is a change in behaviour from previous Emacs versions. When invoked with a prefix argument, as in 'C-u e', this command will pop up a new buffer and show the full pretty-printed value there. ++++ +*** 'C-x C-e' now interprets a non-zero prefix arg to pretty-print the results. +When invoked with a non-zero prefix argument, as in 'C-u C-x C-e', +this command will pop up a new buffer and show the full pretty-printed +value there. + ** Compile +++ diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 58cfd47abd..ad66cfc2b8 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -3746,21 +3746,25 @@ this is the prefix key.)" (t (princ result))))) -(defun edebug-eval-last-sexp (&optional no-truncate) +(defun edebug-eval-last-sexp (&optional display-type) "Evaluate sexp before point in the outside environment. -Print value in minibuffer. - -If NO-TRUNCATE is non-nil (or interactively with a prefix -argument of zero), show the full length of the expression, not -limited by `edebug-print-length' or `edebug-print-level'." +If DISPLAY-TYPE is `pretty-print' (interactively, a non-zero +prefix argument), pretty-print the value in a separate buffer. +Otherwise, print the value in minibuffer. If DISPLAY-TYPE is any +other non-nil value (or interactively with a prefix argument of +zero), show the full length of the expression, not limited by +`edebug-print-length' or `edebug-print-level'." (interactive (list (and current-prefix-arg - (zerop (prefix-numeric-value current-prefix-arg))))) - (if no-truncate - (let ((edebug-print-length nil) - (edebug-print-level nil)) - (edebug-eval-expression (edebug-last-sexp))) - (edebug-eval-expression (edebug-last-sexp)))) + (if (zerop (prefix-numeric-value current-prefix-arg)) + 'no-truncate + 'pretty-print)))) + (if (or (null display-type) + (eq display-type 'pretty-print)) + (edebug-eval-expression (edebug-last-sexp) display-type) + (let ((edebug-print-length nil) + (edebug-print-level nil)) + (edebug-eval-expression (edebug-last-sexp))))) (defun edebug-eval-print-last-sexp (&optional no-truncate) "Evaluate sexp before point in outside environment; insert value. commit ba1508ed17f57642421f510fd9e1ac35e17bf208 Author: Alan Mackenzie Date: Sat Jun 18 11:23:06 2022 +0000 CC Mode: Fix infinite loop in noise macro near end of buffer This fixes bug #55771. Also fix an inaccuracy in c-defun-name-1 with the same cause. * lisp/progmodes/cc-cmds.el (c-defun-name-1) * lisp/progmodes/cc-engine.el (c-forward-noise-clause): Check the return value of c-forward-token-2 and act upon it when not zero. diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index e9cc63709e..82268f4943 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el @@ -2115,13 +2115,12 @@ with a brace block." (c-forward-syntactic-ws) (when (eq (char-after) ?\") (forward-sexp 1) + (c-forward-syntactic-ws) (c-forward-token-2)) ; over the comma and following WS. - (buffer-substring-no-properties - (point) - (progn - (c-forward-token-2) - (c-backward-syntactic-ws) - (point)))) + (setq pos (point)) + (and (zerop (c-forward-token-2)) + (progn (c-backward-syntactic-ws) t) + (buffer-substring-no-properties pos (point)))) ((and (c-major-mode-is 'objc-mode) (looking-at "[-+]\\s-*(")) ; Objective-C method ;; Move to the beginning of the method name. diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 8794a527f8..f9c33f5149 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -1239,7 +1239,7 @@ comment at the start of cc-engine.el for more info." (not comma-delimited) (not (c-looking-at-inexpr-block lim nil t)) (save-excursion - (c-backward-token-2 1 t nil) + (c-backward-token-2 1 t nil) ; Don't test the value (not (looking-at "=\\([^=]\\|$\\)"))) (or (not c-opt-block-decls-with-vars-key) @@ -8289,9 +8289,10 @@ multi-line strings (but not C++, for example)." (defun c-forward-noise-clause () ;; Point is at a c-noise-macro-with-parens-names macro identifier. Go ;; forward over this name, any parenthesis expression which follows it, and - ;; any syntactic WS, ending up at the next token. If there is an unbalanced - ;; paren expression, leave point at it. Always Return t. - (c-forward-token-2) + ;; any syntactic WS, ending up at the next token or EOB. If there is an + ;; unbalanced paren expression, leave point at it. Always Return t. + (or (zerop (c-forward-token-2)) + (goto-char (point-max))) (if (and (eq (char-after) ?\() (c-go-list-forward)) (c-forward-syntactic-ws)) commit 2cb5ed66c094cc1ea937c72eb7958c2dc674ac7f Author: Duncan Findlay Date: Fri Jun 10 18:46:49 2022 -0700 Support `select-active-regions' with xterm This allows Emacs to save the active region to the user's primary selection on supported terminals. The behavior follows the existing `select-active-regions' variable and requires `xterm-select-active-regions' to be non-nil. * src/keyboard.c (command_loop_1): * lisp/frame.el (display-selections-p): On text terminals, check terminal parameter `xterm--set-selections' and variable `xterm-select-active-regions' when deciding whether to update primary selection. (bug#55883) * lisp/term/xterm.el (xterm-select-active-regions): New defcustom. diff --git a/etc/NEWS b/etc/NEWS index 761f236925..f195a721f4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -506,6 +506,12 @@ This is in addition to previously-supported ways of discovering 24-bit color support: either via the "RGB" or "setf24" capabilities, or if the 'COLORTERM' environment variable is set to the value "truecolor". +*** Select active regions with xterm selection support. +On terminals with xterm setSelection support, the active region may be +saved to the X primary selection, following the +'select-active-regions' variable. This support is enabled with +'xterm-select-active-regions'. + ** ERT +++ diff --git a/lisp/frame.el b/lisp/frame.el index 27f99fb7d2..35863c0135 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2149,6 +2149,9 @@ frame's display)." (defalias 'display-multi-frame-p #'display-graphic-p) (defalias 'display-multi-font-p #'display-graphic-p) +;; From term/xterm.el +(defvar xterm-select-active-regions) + (defun display-selections-p (&optional display) "Return non-nil if DISPLAY supports selections. A selection is a way to transfer text or other data between programs @@ -2164,6 +2167,9 @@ frame's display)." (not (null dos-windows-version)))) ((memq frame-type '(x w32 ns pgtk)) t) + ((and xterm-select-active-regions + (terminal-parameter nil 'xterm--set-selection)) + t) (t nil)))) diff --git a/lisp/term/xterm.el b/lisp/term/xterm.el index a7e257f41c..0791780d40 100644 --- a/lisp/term/xterm.el +++ b/lisp/term/xterm.el @@ -80,6 +80,14 @@ capabilities, and only when that terminal understands bracketed paste." :version "28.1" :type 'boolean) +(defcustom xterm-select-active-regions nil + "If non-nil, update PRIMARY X selection on text-mode frames. +On a text-mode terminal that supports setSelection command, if +this variable is non-nil, Emacs will set the PRIMARY selection +from the active region, according to `select-active-regions'." + :version "29.1" + :type 'boolean) + (defconst xterm-paste-ending-sequence "\e[201~" "Characters sent by the terminal to end a bracketed paste.") diff --git a/src/keyboard.c b/src/keyboard.c index 60ff8f5ea6..cd92cf8d4a 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1567,9 +1567,15 @@ command_loop_1 (void) call0 (Qdeactivate_mark); else { + Lisp_Object symval; /* Even if not deactivating the mark, set PRIMARY if `select-active-regions' is non-nil. */ - if (!NILP (Fwindow_system (Qnil)) + if ((!NILP (Fwindow_system (Qnil)) + || ((symval = + find_symbol_value (Qxterm_select_active_regions), + (!EQ (symval, Qunbound) && !NILP (symval))) + && !NILP (Fterminal_parameter (Qnil, + Qxterm__set_selection)))) /* Even if mark_active is non-nil, the actual buffer marker may not have been set yet (Bug#7044). */ && XMARKER (BVAR (current_buffer, mark))->buffer @@ -12163,6 +12169,8 @@ syms_of_keyboard (void) DEFSYM (Qpolling_period, "polling-period"); DEFSYM (Qgui_set_selection, "gui-set-selection"); + DEFSYM (Qxterm__set_selection, "xterm--set-selection"); + DEFSYM (Qxterm_select_active_regions, "xterm-select-active-regions"); /* The primary selection. */ DEFSYM (QPRIMARY, "PRIMARY"); commit 4b00bc47c7e07bb2a329fa6d0220f39a45289875 Author: Eli Zaretskii Date: Sat Jun 18 13:45:13 2022 +0300 Update documentation * doc/emacs/trouble.texi (DEL Does Not Delete): Move to the end of the chapter. This issue is no longer frequent or important as it was back in Emacs 20 days. (Long Lines): Document 'max-redisplay-ticks'. * doc/emacs/emacs.texi (Top): Update the detailed menu. * etc/NEWS: Announce 'max-redisplay-ticks'. diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index ad0fa5f0cd..5e72699bbe 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -1183,7 +1183,6 @@ The Emacs Initialization File Dealing with Emacs Trouble -* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete. * Stuck Recursive:: '[...]' in mode line around the parentheses. * Screen Garbled:: Garbage on the screen. * Text Garbled:: Garbage in the text. @@ -1192,6 +1191,7 @@ Dealing with Emacs Trouble * After a Crash:: Recovering editing in an Emacs session that crashed. * Emergency Escape:: What to do if Emacs stops responding. * Long Lines:: Mitigating slowness due to extremely long lines. +* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete. Reporting Bugs diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi index 8da96de1cb..75b97ac6a8 100644 --- a/doc/emacs/trouble.texi +++ b/doc/emacs/trouble.texi @@ -151,7 +151,6 @@ garbled displays, running out of memory, and crashes and hangs. Emacs. @menu -* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete. * Stuck Recursive:: '[...]' in mode line around the parentheses. * Screen Garbled:: Garbage on the screen. * Text Garbled:: Garbage in the text. @@ -160,65 +159,9 @@ Emacs. * After a Crash:: Recovering editing in an Emacs session that crashed. * Emergency Escape:: What to do if Emacs stops responding. * Long Lines:: Mitigating slowness due to extremely long lines. +* DEL Does Not Delete:: What to do if @key{DEL} doesn't delete. @end menu -@node DEL Does Not Delete -@subsection If @key{DEL} Fails to Delete -@cindex @key{DEL} vs @key{BACKSPACE} -@cindex @key{BACKSPACE} vs @key{DEL} -@cindex @key{DEL} does not delete - - Every keyboard has a large key, usually labeled @key{BACKSPACE}, -which is ordinarily used to erase the last character that you typed. -In Emacs, this key is supposed to be equivalent to @key{DEL}. - - When Emacs starts up on a graphical display, it determines -automatically which key should be @key{DEL}. In some unusual cases, -Emacs gets the wrong information from the system, and @key{BACKSPACE} -ends up deleting forwards instead of backwards. - - Some keyboards also have a @key{Delete} key, which is ordinarily -used to delete forwards. If this key deletes backward in Emacs, that -too suggests Emacs got the wrong information---but in the opposite -sense. - - On a text terminal, if you find that @key{BACKSPACE} prompts for a -Help command, like @kbd{Control-h}, instead of deleting a character, -it means that key is actually sending the @samp{BS} character. Emacs -ought to be treating @key{BS} as @key{DEL}, but it isn't. - -@findex normal-erase-is-backspace-mode - In all of those cases, the immediate remedy is the same: use the -command @kbd{M-x normal-erase-is-backspace-mode}. This toggles -between the two modes that Emacs supports for handling @key{DEL}, so -if Emacs starts in the wrong mode, this should switch to the right -mode. On a text terminal, if you want to ask for help when @key{BS} -is treated as @key{DEL}, use @key{F1} instead of @kbd{C-h}; @kbd{C-?} -may also work, if it sends character code 127. - - To fix the problem in every Emacs session, put one of the following -lines into your initialization file (@pxref{Init File}). For the -first case above, where @key{BACKSPACE} deletes forwards instead of -backwards, use this line to make @key{BACKSPACE} act as @key{DEL}: - -@lisp -(normal-erase-is-backspace-mode 0) -@end lisp - -@noindent -For the other two cases, use this line: - -@lisp -(normal-erase-is-backspace-mode 1) -@end lisp - -@vindex normal-erase-is-backspace - Another way to fix the problem for every Emacs session is to -customize the variable @code{normal-erase-is-backspace}: the value -@code{t} specifies the mode where @key{BS} or @key{BACKSPACE} is -@key{DEL}, and @code{nil} specifies the other mode. @xref{Easy -Customization}. - @node Stuck Recursive @subsection Recursive Editing Levels @cindex stuck in recursive editing @@ -525,6 +468,86 @@ be substantial. Use @kbd{M-x so-long-commentary} to view the documentation for this library and learn more about how to enable and configure it. +@vindex max-redisplay-ticks + If even @code{so-long-mode} doesn't help making Emacs responsive +enough, or if you'd rather not disable the display-related features +that @code{so-long-mode} turns off, you can instead customize the +variable @code{max-redisplay-ticks} to a non-zero value. Then Emacs +will abort redisplay of a window and commands, like @kbd{C-n} and +@kbd{M-v}, which use the display code to do their job, if processing a +window needs more low-level display operations than the value of this +variable. The display of the offending window will then remain +outdated, and possibly incomplete, on the screen, but Emacs should +otherwise be responsive, and you could then switch to another buffer, +or kill the problematic buffer, or turn on @code{so-long-mode} or +@code{sol-long-minor-mode} in that buffer. When the display of a +window is aborted due to this reason, the buffer shown in that window +will not have any of its windows redisplayed until the buffer is +modified or until you type @kbd{C-l} (@pxref{Recentering}) in one of +that buffer's windows. + + If you decide to customize this variable to a non-zero value, we +recommend to use a value between 50,000 and 200,000, depending on your +patience and the speed of your system. The default value is zero, +which disables this feature. + +@node DEL Does Not Delete +@subsection If @key{DEL} Fails to Delete +@cindex @key{DEL} vs @key{BACKSPACE} +@cindex @key{BACKSPACE} vs @key{DEL} +@cindex @key{DEL} does not delete + + Every keyboard has a large key, usually labeled @key{BACKSPACE}, +which is ordinarily used to erase the last character that you typed. +In Emacs, this key is supposed to be equivalent to @key{DEL}. + + When Emacs starts up on a graphical display, it determines +automatically which key should be @key{DEL}. In some unusual cases, +Emacs gets the wrong information from the system, and @key{BACKSPACE} +ends up deleting forwards instead of backwards. + + Some keyboards also have a @key{Delete} key, which is ordinarily +used to delete forwards. If this key deletes backward in Emacs, that +too suggests Emacs got the wrong information---but in the opposite +sense. + + On a text terminal, if you find that @key{BACKSPACE} prompts for a +Help command, like @kbd{Control-h}, instead of deleting a character, +it means that key is actually sending the @samp{BS} character. Emacs +ought to be treating @key{BS} as @key{DEL}, but it isn't. + +@findex normal-erase-is-backspace-mode + In all of those cases, the immediate remedy is the same: use the +command @kbd{M-x normal-erase-is-backspace-mode}. This toggles +between the two modes that Emacs supports for handling @key{DEL}, so +if Emacs starts in the wrong mode, this should switch to the right +mode. On a text terminal, if you want to ask for help when @key{BS} +is treated as @key{DEL}, use @key{F1} instead of @kbd{C-h}; @kbd{C-?} +may also work, if it sends character code 127. + + To fix the problem in every Emacs session, put one of the following +lines into your initialization file (@pxref{Init File}). For the +first case above, where @key{BACKSPACE} deletes forwards instead of +backwards, use this line to make @key{BACKSPACE} act as @key{DEL}: + +@lisp +(normal-erase-is-backspace-mode 0) +@end lisp + +@noindent +For the other two cases, use this line: + +@lisp +(normal-erase-is-backspace-mode 1) +@end lisp + +@vindex normal-erase-is-backspace + Another way to fix the problem for every Emacs session is to +customize the variable @code{normal-erase-is-backspace}: the value +@code{t} specifies the mode where @key{BS} or @key{BACKSPACE} is +@key{DEL}, and @code{nil} specifies the other mode. @xref{Easy +Customization}. + @node Bugs @section Reporting Bugs diff --git a/etc/NEWS b/etc/NEWS index 424d1250c3..fa54d68a10 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -748,6 +748,14 @@ available options can be restored by enabling this option. Use it if you want Imenu to forget the buffer's index alist and recreate it anew next time 'imenu' is invoked. ++++ +** Emacs is now capable of aborting too-long redisplay processing. +This is controlled by the new variable 'max-redisplay-ticks'. If that +variable is set to a non-zero value, display of a window will be +aborted after that many low-level redisplay operations, thus +preventing Emacs from becoming wedged when visiting files with very +long lines. + * Editing Changes in Emacs 29.1 +++ commit a82af5ae786073aa3e7af82f3d181e8b18fdd594 Author: Eli Zaretskii Date: Sat Jun 18 13:12:21 2022 +0300 Don't count ticks too eagerly in syntax.c * src/syntax.c (scan_sexps_forward): Don't increment redisplay tick count of the loop didn't advance at all. diff --git a/src/syntax.c b/src/syntax.c index de9193e2de..c13a8179ee 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -3481,7 +3481,8 @@ do { prev_from = from; \ means we consider 10 buffer positions examined by this function roughly equivalent to the display engine iterating over a single buffer position. */ - update_redisplay_ticks ((from - started_from) / 10 + 1, NULL); + if (from > started_from) + update_redisplay_ticks ((from - started_from) / 10 + 1, NULL); } /* Convert a (lisp) parse state to the internal form used in commit 82626e62ab27b498848e4c1822f6c4c06ad53947 Author: Eli Zaretskii Date: Sat Jun 18 13:07:20 2022 +0300 Allow aborting redisplay stuck in 'parse-partial-sexp' * src/xdisp.c (display_working_on_window_p): New global variable. (unwind_display_working_on_window): New function. * src/keyboard.c (command_loop_1): Reset 'display_working_on_window_p' before and after executing commands. * src/window.c (Frecenter, window_scroll, displayed_window_lines): * src/indent.c (Fvertical_motion): Set 'display_working_on_window_p' before calling 'start_display'. * src/syntax.c (scan_sexps_forward): Call 'update_redisplay_ticks' after finishing the loop. diff --git a/src/dispextern.h b/src/dispextern.h index 0ea3ac8b07..8bcd13dbb6 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3407,6 +3407,8 @@ int partial_line_height (struct it *it_origin); bool in_display_vector_p (struct it *); int frame_mode_line_height (struct frame *); extern bool redisplaying_p; +extern bool display_working_on_window_p; +extern void unwind_display_working_on_window (void); extern bool help_echo_showing_p; extern Lisp_Object help_echo_string, help_echo_window; extern Lisp_Object help_echo_object, previous_help_echo_string; diff --git a/src/indent.c b/src/indent.c index 51f6f414de..7d9f0fe8b0 100644 --- a/src/indent.c +++ b/src/indent.c @@ -2177,6 +2177,8 @@ whether or not it is currently displayed in some window. */) line_number_display_width (w, &lnum_width, &lnum_pixel_width); SET_TEXT_POS (pt, PT, PT_BYTE); itdata = bidi_shelve_cache (); + record_unwind_protect_void (unwind_display_working_on_window); + display_working_on_window_p = true; start_display (&it, w, pt); it.lnum_width = lnum_width; first_x = it.first_visible_x; diff --git a/src/keyboard.c b/src/keyboard.c index 7d7dd2dba0..e5a991a8b2 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1505,8 +1505,10 @@ command_loop_1 (void) executing the command, so that we don't blame the new command for the sins of the previous one. */ update_redisplay_ticks (0, NULL); + display_working_on_window_p = false; call1 (Qcommand_execute, Vthis_command); + display_working_on_window_p = false; #ifdef HAVE_WINDOW_SYSTEM /* Do not check display_hourglass_p here, because diff --git a/src/window.c b/src/window.c index ac8408a9a9..9f0df6619a 100644 --- a/src/window.c +++ b/src/window.c @@ -5568,7 +5568,11 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror) /* On GUI frames, use the pixel-based version which is much slower than the line-based one but can handle varying line heights. */ if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame))) - window_scroll_pixel_based (window, n, whole, noerror); + { + record_unwind_protect_void (unwind_display_working_on_window); + display_working_on_window_p = true; + window_scroll_pixel_based (window, n, whole, noerror); + } else window_scroll_line_based (window, n, whole, noerror); @@ -6496,9 +6500,14 @@ displayed_window_lines (struct window *w) CLIP_TEXT_POS_FROM_MARKER (start, w->start); itdata = bidi_shelve_cache (); + + specpdl_ref count = SPECPDL_INDEX (); + record_unwind_protect_void (unwind_display_working_on_window); + display_working_on_window_p = true; start_display (&it, w, start); move_it_vertically (&it, height); bottom_y = line_bottom_y (&it); + unbind_to (count, Qnil); bidi_unshelve_cache (itdata, false); /* Add in empty lines at the bottom of the window. */ @@ -6592,6 +6601,10 @@ and redisplay normally--don't erase and redraw the frame. */) data structures might not be set up yet then. */ if (!FRAME_INITIAL_P (XFRAME (w->frame))) { + specpdl_ref count = SPECPDL_INDEX (); + + record_unwind_protect_void (unwind_display_working_on_window); + display_working_on_window_p = true; if (center_p) { struct it it; @@ -6708,6 +6721,7 @@ and redisplay normally--don't erase and redraw the frame. */) bidi_unshelve_cache (itdata, false); } + unbind_to (count, Qnil); } else { diff --git a/src/xdisp.c b/src/xdisp.c index 1ba9132e8c..1d52bbc6c9 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1030,6 +1030,15 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 }; bool redisplaying_p; +/* True while some display-engine code is working on layout of some + window. + + WARNING: Use sparingly, preferably only in top level of commands + and important functions, because using it in nested calls might + reset the flag when the inner call returns, behind the back of + the callers. */ +bool display_working_on_window_p; + /* If a string, XTread_socket generates an event to display that string. (The display is done in read_char.) */ @@ -10961,6 +10970,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to, max_y = XFIXNUM (y_limit); itdata = bidi_shelve_cache (); + start_display (&it, w, startp); int start_y = it.current_y; @@ -16970,6 +16980,13 @@ unwind_redisplay (void) unblock_buffer_flips (); } +/* Function registered with record_unwind_protect before calling + start_display outside of redisplay_internal. */ +void +unwind_display_working_on_window (void) +{ + display_working_on_window_p = false; +} /* Mark the display of leaf window W as accurate or inaccurate. If ACCURATE_P, mark display of W as accurate. @@ -17199,9 +17216,9 @@ update_redisplay_ticks (int ticks, struct window *w) cwindow = w; window_ticks = 0; } - /* Some callers can be run in contexts unrelated to redisplay, so + /* Some callers can be run in contexts unrelated to display code, so don't abort them and don't update the tick count in those cases. */ - if (!w && !redisplaying_p) + if (!w && !redisplaying_p && !display_working_on_window_p) return; if (ticks > 0) commit e321f87aa76c959faed784851b65ab7ada3fd129 Author: Mattias Engdegård Date: Sat Jun 18 11:08:23 2022 +0200 Avoid "control-control-KEY" (bug#55738) Constructs such as ?\C-^@ or ?\C-\C-m literally apply a Control modifier twice which doesn't make sense at all. What is really meant is a C0 base character with the Control modifier bit set. This change is only stylistic in nature. * lisp/edmacro.el (edmacro-format-keys): * lisp/keymap.el (key-parse): * lisp/subr.el (event-modifiers, event-basic-type): * test/lisp/subr-tests.el (subr-test-kbd): Use \0 and \r instead of ^@ and \C-m to represent NUL and RET when combined with other modifiers. diff --git a/lisp/edmacro.el b/lisp/edmacro.el index fe1fc086bc..04adabd06b 100644 --- a/lisp/edmacro.el +++ b/lisp/edmacro.el @@ -532,8 +532,8 @@ doubt, use whitespace." ((integerp ch) (concat (cl-loop for pf across "ACHMsS" - for bit in '(?\A-\^@ ?\C-\^@ ?\H-\^@ - ?\M-\^@ ?\s-\^@ ?\S-\^@) + for bit in '( ?\A-\0 ?\C-\0 ?\H-\0 + ?\M-\0 ?\s-\0 ?\S-\0) when (/= (logand ch bit) 0) concat (format "%c-" pf)) (let ((ch2 (logand ch (1- (ash 1 18))))) diff --git a/lisp/keymap.el b/lisp/keymap.el index 71454eba5e..3a22610499 100644 --- a/lisp/keymap.el +++ b/lisp/keymap.el @@ -241,13 +241,13 @@ See `kbd' for a descripion of KEYS." (setq bits (+ bits (cdr (assq (aref word 0) - '((?A . ?\A-\^@) (?C . ?\C-\^@) - (?H . ?\H-\^@) (?M . ?\M-\^@) - (?s . ?\s-\^@) (?S . ?\S-\^@)))))) + '((?A . ?\A-\0) (?C . ?\C-\0) + (?H . ?\H-\0) (?M . ?\M-\0) + (?s . ?\s-\0) (?S . ?\S-\0)))))) (setq prefix (+ prefix 2)) (setq word (substring word 2))) (when (string-match "^\\^.$" word) - (setq bits (+ bits ?\C-\^@)) + (setq bits (+ bits ?\C-\0)) (setq prefix (1+ prefix)) (setq word (substring word 1))) (let ((found (assoc word '(("NUL" . "\0") ("RET" . "\r") @@ -262,19 +262,19 @@ See `kbd' for a descripion of KEYS." (setq word (vector n)))) (cond ((= bits 0) (setq key word)) - ((and (= bits ?\M-\^@) (stringp word) + ((and (= bits ?\M-\0) (stringp word) (string-match "^-?[0-9]+$" word)) (setq key (mapcar (lambda (x) (+ x bits)) (append word nil)))) ((/= (length word) 1) (error "%s must prefix a single character, not %s" (substring orig-word 0 prefix) word)) - ((and (/= (logand bits ?\C-\^@) 0) (stringp word) + ((and (/= (logand bits ?\C-\0) 0) (stringp word) ;; We used to accept . and ? here, ;; but . is simply wrong, ;; and C-? is not used (we use DEL instead). (string-match "[@-_a-z]" word)) - (setq key (list (+ bits (- ?\C-\^@) + (setq key (list (+ bits (- ?\C-\0) (logand (aref word 0) 31))))) (t (setq key (list (+ bits (aref word 0))))))))) diff --git a/lisp/subr.el b/lisp/subr.el index c1c9759b03..d14efccd82 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1542,21 +1542,21 @@ the `click' modifier." ;; sure the symbol has already been parsed. (cdr (internal-event-symbol-parse-modifiers type)) (let ((list nil) - (char (logand type (lognot (logior ?\M-\^@ ?\C-\^@ ?\S-\^@ - ?\H-\^@ ?\s-\^@ ?\A-\^@))))) - (if (not (zerop (logand type ?\M-\^@))) + (char (logand type (lognot (logior ?\M-\0 ?\C-\0 ?\S-\0 + ?\H-\0 ?\s-\0 ?\A-\0))))) + (if (not (zerop (logand type ?\M-\0))) (push 'meta list)) - (if (or (not (zerop (logand type ?\C-\^@))) + (if (or (not (zerop (logand type ?\C-\0))) (< char 32)) (push 'control list)) - (if (or (not (zerop (logand type ?\S-\^@))) + (if (or (not (zerop (logand type ?\S-\0))) (/= char (downcase char))) (push 'shift list)) - (or (zerop (logand type ?\H-\^@)) + (or (zerop (logand type ?\H-\0)) (push 'hyper list)) - (or (zerop (logand type ?\s-\^@)) + (or (zerop (logand type ?\s-\0)) (push 'super list)) - (or (zerop (logand type ?\A-\^@)) + (or (zerop (logand type ?\A-\0)) (push 'alt list)) list)))) @@ -1570,7 +1570,7 @@ in the current Emacs session, then this function may return nil." (setq event (car event))) (if (symbolp event) (car (get event 'event-symbol-elements)) - (let* ((base (logand event (1- ?\A-\^@))) + (let* ((base (logand event (1- ?\A-\0))) (uncontrolled (if (< base 32) (logior base 64) base))) ;; There are some numbers that are invalid characters and ;; cause `downcase' to get an error. diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index a25eb363b0..45dd2d7160 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -112,7 +112,7 @@ (should (equal (kbd "C-x C-f") "\C-x\C-f")) (should (equal (kbd "C-M-") [C-M-down])) (should (equal (kbd "") [C-M-down])) - (should (equal (kbd "C-RET") [?\C-\C-m])) + (should (equal (kbd "C-RET") [?\C-\r])) (should (equal (kbd "C-SPC") [?\C- ])) (should (equal (kbd "C-TAB") [?\C-\t])) (should (equal (kbd "C-") [C-down])) commit 15238e2ed0eeba82fd43efbbd4b9237394f9fd55 Author: Stefan Kangas Date: Sat Jun 18 11:07:12 2022 +0200 Prefer URL commentary header in two files * lisp/transient.el: * test/lisp/progmodes/cperl-mode-tests.el: Prefer URL commentary header. diff --git a/lisp/transient.el b/lisp/transient.el index d329bbdbcd..06e4106192 100644 --- a/lisp/transient.el +++ b/lisp/transient.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2018-2022 Free Software Foundation, Inc. ;; Author: Jonas Bernoulli -;; Homepage: https://github.com/magit/transient +;; URL: https://github.com/magit/transient ;; Keywords: bindings ;; Package-Requires: ((emacs "25.1")) diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el index 47e39aa589..7eb2d9be75 100644 --- a/test/lisp/progmodes/cperl-mode-tests.el +++ b/test/lisp/progmodes/cperl-mode-tests.el @@ -5,7 +5,7 @@ ;; Author: Harald Jörg ;; Maintainer: Harald Jörg ;; Keywords: internal -;; Homepage: https://github.com/HaraldJoerg/cperl-mode +;; URL: https://github.com/HaraldJoerg/cperl-mode ;; This file is part of GNU Emacs. commit 99577312f569e22f05a4d0960cc881ff46d4dc3a Author: Eli Zaretskii Date: Sat Jun 18 10:27:19 2022 +0300 ; * lisp/misc.el (duplicate-line): Doc fix. diff --git a/lisp/misc.el b/lisp/misc.el index 64438cd6ca..3fb30e5372 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -66,6 +66,7 @@ Also see the `duplicate-line' command." ;;;###autoload (defun duplicate-line (&optional n) "Duplicate the current line N times. +Interactively, N is the prefix numeric argument, and defaults to 1. Also see the `copy-from-above-command' command." (interactive "p") (let ((line (buffer-substring (line-beginning-position) (line-end-position)))) commit 9f6461b0fe4ea6ee98629c6828ff28d79ff839b6 Author: Eli Zaretskii Date: Sat Jun 18 10:22:47 2022 +0300 ; * etc/NEWS: Expand the entry about 'e' in Edebug. diff --git a/etc/NEWS b/etc/NEWS index d18af0502d..761f236925 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1020,7 +1020,9 @@ lead to a (further) backtrace. By default, this variable is nil, which is a change in behaviour from previous Emacs versions. +++ -*** 'e' in edebug can now take a prefix to pretty-print the results. +*** 'e' in edebug can now take a prefix arg to pretty-print the results. +When invoked with a prefix argument, as in 'C-u e', this command will +pop up a new buffer and show the full pretty-printed value there. ** Compile commit f01213bc20fd7d1a0d24c061892cc0fdda9ea0bc Author: Stefan Kangas Date: Sat Jun 18 09:13:06 2022 +0200 Define docstring element for more forms in scheme-mode * lisp/progmodes/scheme.el: Define docstring element for more forms. (Bug#33117) diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el index 9b24c2155d..e0453c3b2f 100644 --- a/lisp/progmodes/scheme.el +++ b/lisp/progmodes/scheme.el @@ -388,12 +388,18 @@ See `run-hooks'." st)) (put 'lambda 'scheme-doc-string-elt 2) +(put 'lambda* 'scheme-doc-string-elt 2) ;; Docstring's pos in a `define' depends on whether it's a var or fun def. (put 'define 'scheme-doc-string-elt (lambda () ;; The function is called with point right after "define". (forward-comment (point-max)) (if (eq (char-after) ?\() 2 0))) +(put 'define* 'scheme-doc-string-elt 2) +(put 'case-lambda 'scheme-doc-string-elt 1) +(put 'case-lambda* 'scheme-doc-string-elt 1) +(put 'define-syntax-rule 'scheme-doc-string-elt 2) +(put 'syntax-rules 'scheme-doc-string-elt 2) (defun scheme-syntax-propertize (beg end) (goto-char beg) commit 6c0caf65af338bea40b0820109edd0a69c6886ab Author: Po Lu Date: Sat Jun 18 07:11:19 2022 +0000 Remove unused Haiku code * src/haiku_select.cc (be_get_clipboard_targets_1) (be_get_clipboard_targets): Delete functions. (init_haiku_select): Rename to `be_clipboard_init'. Avoid duplicate definition with haikuterm.h. * src/haikuselect.c (init_haiku_select): New function. * src/haikuselect.h: Update prototypes. diff --git a/src/haiku_select.cc b/src/haiku_select.cc index 764001f62b..80c5d29482 100644 --- a/src/haiku_select.cc +++ b/src/haiku_select.cc @@ -110,53 +110,6 @@ be_find_clipboard_data_1 (BClipboard *cb, const char *type, ssize_t *len) return (char *) value; } -static void -be_get_clipboard_targets_1 (BClipboard *cb, char **buf, int buf_size) -{ - BMessage *data; - char *name; - int32 count_found; - type_code type; - int32 i; - int index; - - if (!cb->Lock ()) - { - buf[0] = NULL; - return; - } - - data = cb->Data (); - index = 0; - - if (!data) - { - buf[0] = NULL; - cb->Unlock (); - return; - } - - for (i = 0; (data->GetInfo (B_ANY_TYPE, i, &name, - &type, &count_found) - == B_OK); ++i) - { - if (type == B_MIME_TYPE) - { - if (index < (buf_size - 1)) - { - buf[index++] = strdup (name); - - if (!buf[index - 1]) - break; - } - } - } - - buf[index] = NULL; - - cb->Unlock (); -} - static void be_set_clipboard_data_1 (BClipboard *cb, const char *type, const char *data, ssize_t len, bool clear) @@ -227,14 +180,6 @@ be_set_clipboard_data (enum haiku_clipboard id, const char *type, data, len, clear); } -void -be_get_clipboard_targets (enum haiku_clipboard id, char **targets, - int len) -{ - be_get_clipboard_targets_1 (get_clipboard_object (id), targets, - len); -} - static bool clipboard_owner_p (void) { @@ -278,7 +223,7 @@ be_clipboard_owner_p (enum haiku_clipboard clipboard) } void -init_haiku_select (void) +be_clipboard_init (void) { system_clipboard = new BClipboard ("system"); primary = new BClipboard ("primary"); diff --git a/src/haikuselect.c b/src/haikuselect.c index b2783a56a1..96223902f8 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -1014,6 +1014,12 @@ haiku_note_drag_motion (void) haiku_note_drag_motion_2); } +void +init_haiku_select (void) +{ + be_clipboard_init (); +} + void syms_of_haikuselect (void) { diff --git a/src/haikuselect.h b/src/haikuselect.h index e9a2f2dd77..ac8e069895 100644 --- a/src/haikuselect.h +++ b/src/haikuselect.h @@ -37,15 +37,12 @@ enum haiku_clipboard #ifdef __cplusplus extern "C" { -/* Also declared in haikuterm.h for use in emacs.c. */ -extern void init_haiku_select (void); #endif -/* Whether or not the selection was recently changed. */ +extern void be_clipboard_init (void); extern char *be_find_clipboard_data (enum haiku_clipboard, const char *, ssize_t *); extern void be_set_clipboard_data (enum haiku_clipboard, const char *, const char *, ssize_t, bool); -extern void be_get_clipboard_targets (enum haiku_clipboard, char **, int); extern bool be_clipboard_owner_p (enum haiku_clipboard); extern void be_update_clipboard_count (enum haiku_clipboard); @@ -64,6 +61,7 @@ extern int be_add_point_data (void *, const char *, float, float); extern int be_add_message_message (void *, const char *, void *); extern int be_lock_clipboard_message (enum haiku_clipboard, void **, bool); extern void be_unlock_clipboard (enum haiku_clipboard, bool); + #ifdef __cplusplus }; #endif commit 183a1b6c6d0106f801344c5266fc2f1e959923c7 Author: Po Lu Date: Sat Jun 18 06:04:24 2022 +0000 Fix type mixup in haikuselect.c * src/haikuselect.c (haiku_lisp_to_message): Fix variable mixup. Found with --enable-check-lisp-object-type. diff --git a/src/haikuselect.c b/src/haikuselect.c index 8a7b6f2e0b..b2783a56a1 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -515,7 +515,7 @@ haiku_lisp_to_message (Lisp_Object obj, void *message) unblock_input (); if (rc) - signal_error ("Invalid message", msg_data); + signal_error ("Invalid message", data); unbind_to (ref, Qnil); break; commit 0ed633a0c8a8589a1c5d5efab93b3c06a1e56f9f Author: Stefan Kangas Date: Sat Jun 18 01:39:12 2022 +0200 ; * lisp/doc-view.el (doc-view-bookmark-jump): Fix capitalization. diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 9d27347360..c167ead1c8 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -2260,7 +2260,7 @@ See the command `doc-view-mode' for more information on this mode." (add-hook 'bookmark-after-jump-hook show-fn-sym) (bookmark-default-handler bmk))) -(put 'doc-view-bookmark-jump 'bookmark-handler-type "Docview") +(put 'doc-view-bookmark-jump 'bookmark-handler-type "DocView") ;; Obsolete. commit b79f09d0952a7b04c1e3a84e40b9b5d0c7bcc5e4 Merge: 360e4798b4 024bbcb35e Author: Stefan Kangas Date: Sat Jun 18 06:31:20 2022 +0200 Merge from origin/emacs-28 024bbcb35e Prune the Gnus FAQ of some outdated data commit 360e4798b46caaa0448ef94774c997677829350c Merge: b28debadf3 c1f4cca7f0 Author: Stefan Kangas Date: Sat Jun 18 06:31:20 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: c1f4cca7f0 Fix efaq-w32.texi build warning commit b28debadf3ada1645ea3ea135d67189cf52fdc11 Merge: 06576d6a16 d671cd57c4 Author: Stefan Kangas Date: Sat Jun 18 06:31:18 2022 +0200 Merge from origin/emacs-28 d671cd57c4 Update cl-struct-sequence-type doc string 017bdb1611 Fix a tagging problem in tramp.texi e0bac17bbc Mention face quirks after the final line in the lispref ma... ad74677cf3 Delete reference to obsolete library complete.el commit 06576d6a16fa61f6f1d5031754145a92ab41aa9b Author: Po Lu Date: Sat Jun 18 11:19:01 2022 +0800 Prevent Lisp code or synthetic events from ruining the user time * src/xterm.c (x_display_set_last_user_time): New parameter `send_event'. Make sure user time is newer unless !send_event. (x_set_last_user_time_from_lisp): Remove redundant check. (XTmouse_position): (handle_one_xevent): Pass `send_event' whenever appropriate. diff --git a/src/xterm.c b/src/xterm.c index 67bb265172..885344229a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -6919,8 +6919,15 @@ static void x_scroll_bar_clear (struct frame *); static void x_check_font (struct frame *, struct font *); #endif +/* If SEND_EVENT, make sure that TIME is larger than the current last + user time. We don't sanitize timestamps from events sent by the X + server itself because some Lisp might have set the user time to a + ridiculously large value, and this way a more reasonable timestamp + can be obtained upon the next event. */ + static void -x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time) +x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time, + bool send_event) { #ifndef USE_GTK struct frame *focus_frame = dpyinfo->x_focus_frame; @@ -6930,7 +6937,8 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time) eassert (time <= X_ULONG_MAX); #endif - dpyinfo->last_user_time = time; + if (!send_event || time > dpyinfo->last_user_time) + dpyinfo->last_user_time = time; #ifndef USE_GTK if (focus_frame) @@ -7003,8 +7011,7 @@ void x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo, Time time) { - if (dpyinfo->last_user_time > time) - x_display_set_last_user_time (dpyinfo, time); + x_display_set_last_user_time (dpyinfo, time, true); } @@ -12625,7 +12632,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, && (dpyinfo->last_user_time < dpyinfo->last_mouse_movement_time)) x_display_set_last_user_time (dpyinfo, - dpyinfo->last_mouse_movement_time); + dpyinfo->last_mouse_movement_time, false); if ((!f1 || FRAME_TOOLTIP_P (f1)) && (EQ (track_mouse, Qdropping) @@ -17315,7 +17322,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto OTHER; case KeyPress: - x_display_set_last_user_time (dpyinfo, event->xkey.time); + x_display_set_last_user_time (dpyinfo, event->xkey.time, + event->xkey.send_event); ignore_next_mouse_click_timeout = 0; coding = Qlatin_1; @@ -17766,7 +17774,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif case EnterNotify: - x_display_set_last_user_time (dpyinfo, event->xcrossing.time); + x_display_set_last_user_time (dpyinfo, event->xcrossing.time, + event->xcrossing.send_event); if (x_top_window_to_frame (dpyinfo, event->xcrossing.window)) x_detect_focus_change (dpyinfo, any, event, &inev.ie); @@ -17851,7 +17860,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto OTHER; case LeaveNotify: - x_display_set_last_user_time (dpyinfo, event->xcrossing.time); + x_display_set_last_user_time (dpyinfo, event->xcrossing.time, + event->xcrossing.send_event); #ifdef HAVE_XWIDGETS { @@ -18575,7 +18585,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, case ButtonPress: { if (event->xbutton.type == ButtonPress) - x_display_set_last_user_time (dpyinfo, event->xbutton.time); + x_display_set_last_user_time (dpyinfo, event->xbutton.time, + event->xbutton.send_event); #ifdef HAVE_XWIDGETS struct xwidget_view *xvw = xwidget_view_from_window (event->xbutton.window); @@ -19124,7 +19135,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, ev.window = enter->event; ev.time = enter->time; - x_display_set_last_user_time (dpyinfo, enter->time); + x_display_set_last_user_time (dpyinfo, enter->time, + enter->send_event); #ifdef USE_MOTIF use_copy = true; @@ -19273,7 +19285,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, leave->deviceid, false); #endif - x_display_set_last_user_time (dpyinfo, leave->time); + x_display_set_last_user_time (dpyinfo, leave->time, + leave->send_event); #ifdef HAVE_XWIDGETS { @@ -19527,7 +19540,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (xv) { uint state = xev->mods.effective; - x_display_set_last_user_time (dpyinfo, xev->time); + x_display_set_last_user_time (dpyinfo, xev->time, + xev->send_event); if (xev->buttons.mask_len) { @@ -19556,7 +19570,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif if (found_valuator) { - x_display_set_last_user_time (dpyinfo, xev->time); + x_display_set_last_user_time (dpyinfo, xev->time, + xev->send_event); #if defined USE_GTK && !defined HAVE_GTK3 /* Unlike on Motif, we can't select for XI @@ -20274,7 +20289,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif if (xev->evtype == XI_ButtonPress) - x_display_set_last_user_time (dpyinfo, xev->time); + x_display_set_last_user_time (dpyinfo, xev->time, + xev->send_event); source = xi_device_from_id (dpyinfo, xev->sourceid); @@ -20624,7 +20640,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, } #endif - x_display_set_last_user_time (dpyinfo, xev->time); + x_display_set_last_user_time (dpyinfo, xev->time, + xev->send_event); ignore_next_mouse_click_timeout = 0; f = x_any_window_to_frame (dpyinfo, xev->event); @@ -21418,7 +21435,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); - x_display_set_last_user_time (dpyinfo, xev->time); + x_display_set_last_user_time (dpyinfo, xev->time, + xev->send_event); if (!device) goto XI_OTHER; @@ -21504,7 +21522,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); - x_display_set_last_user_time (dpyinfo, xev->time); + x_display_set_last_user_time (dpyinfo, xev->time, + xev->send_event); if (!device) goto XI_OTHER; @@ -21550,7 +21569,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, xev->deviceid); source = xi_device_from_id (dpyinfo, xev->sourceid); - x_display_set_last_user_time (dpyinfo, xev->time); + x_display_set_last_user_time (dpyinfo, xev->time, + xev->send_event); if (!device) goto XI_OTHER; @@ -21590,7 +21610,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, device = xi_device_from_id (dpyinfo, pev->deviceid); source = xi_device_from_id (dpyinfo, pev->sourceid); - x_display_set_last_user_time (dpyinfo, pev->time); + x_display_set_last_user_time (dpyinfo, pev->time, + pev->send_event); if (!device) goto XI_OTHER; commit 95370484d4750717ea32a94a3785be3cd18b9427 Author: Po Lu Date: Sat Jun 18 10:14:24 2022 +0800 Fix specifying named action lists in `x-begin-drag' * src/xfns.c (Fx_begin_drag): Record original value of `targets' separately. Pass that as the selection targets list instead. * src/xterm.c (x_dnd_delete_action_list): New function. (x_dnd_begin_drag_and_drop): Bind it if there are multiple actions. diff --git a/src/xfns.c b/src/xfns.c index 3df91679af..1372809da6 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6899,7 +6899,7 @@ that mouse buttons are being held down, such as immediately after a int ntargets = 0, nnames = 0; char *target_names[2048]; Atom *target_atoms; - Lisp_Object lval, original, tem, t1, t2; + Lisp_Object lval, original, targets_arg, tem, t1, t2; Atom xaction; Atom action_list[2048]; char *name_list[2048]; @@ -6908,6 +6908,7 @@ that mouse buttons are being held down, such as immediately after a CHECK_LIST (targets); original = targets; + targets_arg = targets; for (; CONSP (targets); targets = XCDR (targets)) { @@ -6995,7 +6996,7 @@ that mouse buttons are being held down, such as immediately after a xaction, return_frame, action_list, (const char **) &name_list, nnames, !NILP (allow_current_frame), target_atoms, - ntargets, original, !NILP (follow_tooltip)); + ntargets, targets_arg, !NILP (follow_tooltip)); SAFE_FREE (); return lval; diff --git a/src/xterm.c b/src/xterm.c index fe7b6ffe21..67bb265172 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11094,6 +11094,30 @@ x_clear_dnd_action (void) x_dnd_action_symbol = Qnil; } +/* Delete action descriptions from F after drag-and-drop. */ +static void +x_dnd_delete_action_list (Lisp_Object frame) +{ + struct frame *f; + + /* Delete those two properties, since some clients look at them and + not the action to decide whether or not the user should be + prompted to select an action. This can be called with FRAME no + longer alive (or its display dead). */ + + f = XFRAME (frame); + + if (!FRAME_LIVE_P (f) || !FRAME_DISPLAY_INFO (f)->display) + return; + + block_input (); + XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList); + XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription); + unblock_input (); +} + /* This function is defined far away from the rest of the XDND code so it can utilize `x_any_window_to_frame'. */ @@ -11262,6 +11286,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, = xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), ask_action_list[0]); + record_unwind_protect (x_dnd_delete_action_list, frame); + ask_actions = NULL; end = 0; count = SPECPDL_INDEX (); @@ -11306,19 +11332,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, unbind_to (count, Qnil); } - else - { - /* Delete those two properties, since some clients look at them - and not the action to decide whether or not the user should - be prompted to select an action. */ - - block_input (); - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList); - XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription); - unblock_input (); - } if (follow_tooltip) { commit 0d103e6f79d374766b64e56fb05e440076f4df5c Author: Lars Ingebrigtsen Date: Sat Jun 18 00:17:40 2022 +0200 Extend 'e' in edebug to pretty-print the values * doc/lispref/edebug.texi (Edebug Eval): Document it. * lisp/emacs-lisp/edebug.el (edebug-eval-expression): Allow displaying the full value in a different buffer. diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi index 0fc5271d5a..377cd21da8 100644 --- a/doc/lispref/edebug.texi +++ b/doc/lispref/edebug.texi @@ -701,7 +701,11 @@ on this process. @item e @var{exp} @key{RET} Evaluate expression @var{exp} in the context outside of Edebug (@code{edebug-eval-expression}). That is, Edebug tries to minimize -its interference with the evaluation. By default, this command +its interference with the evaluation. The result is shown in the echo +area, or, if this command is given a prefix, pop up a new buffer and +pretty-print the result there. + +By default, this command suppresses the debugger during evaluation, so that an error in the evaluated expression won't add a new error on top of the existing one. Set the @code{debug-allow-recursive-debug} user option to a diff --git a/etc/NEWS b/etc/NEWS index b9a2261735..d18af0502d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1019,6 +1019,9 @@ buffer or while edebugging) and 'C-x C-e' (while edebugging) commands lead to a (further) backtrace. By default, this variable is nil, which is a change in behaviour from previous Emacs versions. ++++ +*** 'e' in edebug can now take a prefix to pretty-print the results. + ** Compile +++ diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 9dc5a1315e..58cfd47abd 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -3707,30 +3707,44 @@ Return the result of the last expression." (defalias 'edebug-format #'format-message) (defalias 'edebug-message #'message) -(defun edebug-eval-expression (expr) +(defun edebug-eval-expression (expr &optional pp) "Evaluate an expression in the outside environment. If interactive, prompt for the expression. -Print result in minibuffer." - (interactive (list (read--expression "Eval: "))) + +Print result in minibuffer by default, but if PP is non-nil open +a new window and pretty-print the result there. (Interactively, +this is the prefix key.)" + (interactive (list (read--expression "Edebug eval: ") + current-prefix-arg)) (let* ((errored nil) - (result + (value (edebug-outside-excursion - (let ((result (if debug-allow-recursive-debug - (edebug-eval expr) - (condition-case err - (edebug-eval expr) - (error - (setq errored - (format "%s: %s" - (get (car err) 'error-message) - (car (cdr err))))))))) - (unless errored - (values--store-value result) - (concat (edebug-safe-prin1-to-string result) - (eval-expression-print-format result))))))) - (if errored - (message "Error: %s" errored) - (princ result)))) + (if debug-allow-recursive-debug + (edebug-eval expr) + (condition-case err + (edebug-eval expr) + (error + (setq errored + (format "%s: %s" + (get (car err) 'error-message) + (car (cdr err))))))))) + (result + (unless errored + (values--store-value value) + (concat (edebug-safe-prin1-to-string value) + (eval-expression-print-format value))))) + (cond + (errored + (message "Error: %s" errored)) + (pp + (save-selected-window + (pop-to-buffer "*Edebug Results*") + (erase-buffer) + (pp value (current-buffer)) + (goto-char (point-min)) + (lisp-data-mode))) + (t + (princ result))))) (defun edebug-eval-last-sexp (&optional no-truncate) "Evaluate sexp before point in the outside environment. commit 024bbcb35ebe70ab9ad4c79265c4e83fc1d3b732 Author: Lars Ingebrigtsen Date: Fri Jun 17 21:38:30 2022 +0200 Prune the Gnus FAQ of some outdated data * doc/misc/gnus-faq.texi (FAQ 9-2): Remove some outdated advice (bug#56042). diff --git a/doc/misc/gnus-faq.texi b/doc/misc/gnus-faq.texi index 14a8c4c12d..fd961be2f5 100644 --- a/doc/misc/gnus-faq.texi +++ b/doc/misc/gnus-faq.texi @@ -2193,18 +2193,9 @@ How to speed up the process of entering a group? A speed killer is setting the variable gnus-fetch-old-headers to anything different from @code{nil}, -so don't do this if speed is an issue. To speed up -building of summary say +so don't do this if speed is an issue. -@example -(gnus-compile) -@end example -@noindent - -at the bottom of your @file{~/.gnus.el}, this will make gnus -byte-compile things like -gnus-summary-line-format. -then you could increase the value of gc-cons-threshold +You could increase the value of gc-cons-threshold by saying something like @example @@ -2212,21 +2203,7 @@ by saying something like @end example @noindent -in ~/.emacs. If you don't care about width of CJK -characters or use Gnus 5.10 or younger together with a -recent GNU Emacs, you should say - -@example -(setq gnus-use-correct-string-widths nil) -@end example -@noindent - -in @file{~/.gnus.el} (thanks to Jesper harder for the last -two suggestions). Finally if you are still using 5.8.8 -or 5.9 and experience speed problems with summary -buffer generation, you definitely should update to -5.10 since there quite some work on improving it has -been done. +in ~/.emacs. @node FAQ 9-3 @subsubheading Question 9.3 commit c1370d83cb229c9f3f1b077d1e623b1e9ada6b50 Author: Stefan Kangas Date: Fri Jun 17 21:30:34 2022 +0200 Delete another library obsolete since 24.1 This file was missed in the last commit to delete libraries obsolete since Emacs 24.3 or older. * lisp/obsolete/pc-mode.el: Delete file. This library has been obsolete since Emacs 24.1. (Bug#50999) diff --git a/etc/NEWS b/etc/NEWS index d27c18f4ec..b9a2261735 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2016,7 +2016,7 @@ Previously it produced a nonsense value, -1, that was never intended. ** Some libraries obsolete since Emacs 24.1 and 24.3 have been removed: abbrevlist.el, assoc.el, complete.el, cust-print.el, erc-hecomplete.el, mailpost.el, mouse-sel.el, old-emacs-lock.el, -patcomp.el, pc-select.el, s-region.el, and sregex.el. +patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el. * Lisp Changes in Emacs 29.1 diff --git a/lisp/obsolete/pc-mode.el b/lisp/obsolete/pc-mode.el deleted file mode 100644 index 4c4bfb5b9c..0000000000 --- a/lisp/obsolete/pc-mode.el +++ /dev/null @@ -1,56 +0,0 @@ -;;; pc-mode.el --- emulate certain key bindings used on PCs -*- lexical-binding: t; -*- - -;; Copyright (C) 1995, 2001-2022 Free Software Foundation, Inc. - -;; Maintainer: emacs-devel@gnu.org -;; Keywords: emulations -;; Obsolete-since: 24.1 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -;;;###autoload -(defun pc-bindings-mode () - "Set up certain key bindings for PC compatibility. -The keys affected are: -Delete (and its variants) delete forward instead of backward. -C-Backspace kills backward a word (as C-Delete normally would). -M-Backspace does undo. -Home and End move to beginning and end of line -C-Home and C-End move to beginning and end of buffer. -C-Escape does list-buffers." - - (interactive) - (define-key function-key-map [delete] "\C-d") - (define-key function-key-map [M-delete] [?\M-d]) - (define-key function-key-map [C-delete] [?\M-d]) - (global-set-key [C-M-delete] #'kill-sexp) - (global-set-key [C-backspace] #'backward-kill-word) - (global-set-key [M-backspace] #'undo) - - (global-set-key [C-escape] #'list-buffers) - - (global-set-key [home] #'beginning-of-line) - (global-set-key [end] #'end-of-line) - (global-set-key [C-home] #'beginning-of-buffer) - (global-set-key [C-end] #'end-of-buffer)) - -(provide 'pc-mode) - -;;; pc-mode.el ends here commit c8f81c9d08c5883cfbdb75de29c40acb4e6b4778 Author: Lars Ingebrigtsen Date: Fri Jun 17 21:25:44 2022 +0200 Add hacek variations to `C-x 8' * lisp/international/iso-transl.el (iso-transl-char-map): Add hacek characters on `C-x 8 ^ ^'. diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el index 417f0076ef..912c4b72a0 100644 --- a/lisp/international/iso-transl.el +++ b/lisp/international/iso-transl.el @@ -207,6 +207,30 @@ ("^i" . [?î]) ("^o" . [?ô]) ("^u" . [?û]) + ("^^A" . [?Ǎ]) + ("^^C" . [?Č]) + ("^^E" . [?Ě]) + ("^^G" . [?Ǧ]) + ("^^I" . [?Ǐ]) + ("^^K" . [?Ǩ]) + ("^^N" . [?Ň]) + ("^^O" . [?Ǒ]) + ("^^R" . [?Ř]) + ("^^S" . [?Š]) + ("^^U" . [?Ǔ]) + ("^^Z" . [?Ž]) + ("^^a" . [?ǎ]) + ("^^c" . [?č]) + ("^^e" . [?ě]) + ("^^g" . [?ǧ]) + ("^^i" . [?ǐ]) + ("^^k" . [?ǩ]) + ("^^n" . [?ň]) + ("^^o" . [?ǒ]) + ("^^r" . [?ř]) + ("^^s" . [?š]) + ("^^u" . [?ǔ]) + ("^^z" . [?ž]) ("_a" . [?ª]) ("_o" . [?º]) ("`A" . [?À]) commit 8e6c663aeadc82b8eff1004633125941c184d1e8 Author: Stefan Kangas Date: Fri Jun 17 21:14:39 2022 +0200 image-dired: Use full name for bookmark handler type * lisp/image-dired.el (image-dired-bookmark-jump): Use full mode name for bookmark handler type. diff --git a/lisp/image-dired.el b/lisp/image-dired.el index 30bf5ee108..9ceaf1bf73 100644 --- a/lisp/image-dired.el +++ b/lisp/image-dired.el @@ -2795,7 +2795,7 @@ tags to their respective image file. Internal function used by ;; (bookmark-prop-get bookmark 'image-dired-file) (goto-char (point-min)))) -(put 'image-dired-bookmark-jump 'bookmark-handler-type "Image") +(put 'image-dired-bookmark-jump 'bookmark-handler-type "Image-Dired") ;;; Obsolete commit d62f94f16a647b6a8c00d56cb0e2bd489c58e5b2 Author: Stefan Kangas Date: Fri Jun 17 21:02:40 2022 +0200 Set bookmark handler type for Eshell * lisp/eshell/esh-mode.el (eshell-bookmark-jump): Set bookmark handler type. diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el index 59c8f8034f..c21484dc45 100644 --- a/lisp/eshell/esh-mode.el +++ b/lisp/eshell/esh-mode.el @@ -1034,5 +1034,7 @@ This function could be in the list `eshell-output-filter-functions'." (let ((default-directory (bookmark-prop-get bookmark 'location))) (eshell))) +(put 'eshell-bookmark-jump 'bookmark-handler-type "Eshell") + (provide 'esh-mode) ;;; esh-mode.el ends here commit da208f99d801306440092d7b18ccc8d799879f4c Author: Stefan Kangas Date: Fri Jun 17 20:08:55 2022 +0200 Update bookmark tests for recent change * test/lisp/bookmark-tests.el (bookmark-tests-set/bookmark-use-annotations-t) (bookmark-tests-edit-annotation) (bookmark-test-bmenu-send-edited-annotation) (bookmark-test-bmenu-send-edited-annotation/restore-focus): Update for recent change. diff --git a/test/lisp/bookmark-tests.el b/test/lisp/bookmark-tests.el index a2d8f2d260..3bea08bc37 100644 --- a/test/lisp/bookmark-tests.el +++ b/test/lisp/bookmark-tests.el @@ -301,7 +301,7 @@ the lexically-bound variable `buffer'." (bookmark-set "foo") (should (equal major-mode 'bookmark-edit-annotation-mode)) ;; Should return to the original buffer - (bookmark-send-edited-annotation) + (bookmark-edit-annotation-confirm) (should (equal (current-buffer) buffer)))))) (ert-deftest bookmark-tests-kill-line () @@ -334,7 +334,7 @@ the lexically-bound variable `buffer'." (with-bookmark-test (bookmark-edit-annotation "name") (insert "new text") - (bookmark-send-edited-annotation) + (bookmark-edit-annotation-confirm) (should (equal (bookmark-get-annotation "name") "new text")))) (ert-deftest bookmark-tests-jump () @@ -471,7 +471,7 @@ testing `bookmark-bmenu-list'." (with-bookmark-bmenu-test (bookmark-bmenu-edit-annotation) (insert "foo") - (bookmark-send-edited-annotation) + (bookmark-edit-annotation-confirm) (should (equal (bookmark-get-annotation "name") "foo")))) (ert-deftest bookmark-test-bmenu-send-edited-annotation/restore-focus () @@ -479,7 +479,7 @@ testing `bookmark-bmenu-list'." (with-bookmark-bmenu-test (bookmark-bmenu-edit-annotation) (insert "foo") - (bookmark-send-edited-annotation) + (bookmark-edit-annotation-confirm) (should (equal (buffer-name (current-buffer)) bookmark-bmenu-buffer)) (beginning-of-line) (forward-char 4) commit 4cdeec88cef60dfc4366368edc515115ef0ccd02 Author: Lars Ingebrigtsen Date: Fri Jun 17 19:47:08 2022 +0200 Fix copy-from-above-command doc string type * lisp/misc.el (copy-from-above-command): Fix doc string typo. diff --git a/lisp/misc.el b/lisp/misc.el index 88932681c1..64438cd6ca 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -35,7 +35,7 @@ Copy ARG characters, but not past the end of that line. If no argument given, copy the entire rest of the line. The characters copied are inserted in the buffer before point. -Also see the `copy-line' command." +Also see the `duplicate-line' command." (interactive "P") (let ((cc (current-column)) n commit 6362f65474bad81c1d57b9b603c65686a0dd853e Author: Lars Ingebrigtsen Date: Fri Jun 17 19:33:48 2022 +0200 Add new command `duplicate-line' * lisp/misc.el (copy-from-above-command): Mention it. (duplicate-line): New command (bug#46621). diff --git a/etc/NEWS b/etc/NEWS index 3b9515c2d4..d27c18f4ec 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -298,6 +298,10 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 +--- +** New command 'duplicate-line'. +This command duplicates the current line the specified number of times. + --- ** Files with the '.eld' extension are now visited in 'lisp-data-mode'. diff --git a/lisp/misc.el b/lisp/misc.el index 0bb8ee6c7b..88932681c1 100644 --- a/lisp/misc.el +++ b/lisp/misc.el @@ -33,7 +33,9 @@ "Copy characters from previous nonblank line, starting just above point. Copy ARG characters, but not past the end of that line. If no argument given, copy the entire rest of the line. -The characters copied are inserted in the buffer before point." +The characters copied are inserted in the buffer before point. + +Also see the `copy-line' command." (interactive "P") (let ((cc (current-column)) n @@ -61,6 +63,19 @@ The characters copied are inserted in the buffer before point." (+ n (point))))))) (insert string))) +;;;###autoload +(defun duplicate-line (&optional n) + "Duplicate the current line N times. +Also see the `copy-from-above-command' command." + (interactive "p") + (let ((line (buffer-substring (line-beginning-position) (line-end-position)))) + (save-excursion + (forward-line 1) + (unless (bolp) + (insert "\n")) + (dotimes (_ n) + (insert line "\n"))))) + ;; Variation of `zap-to-char'. ;;;###autoload commit 4311bd0bd73c17b883d3f88eab4928a44d056a3a Author: Mattias Engdegård Date: Fri Jun 17 19:13:33 2022 +0200 Slightly faster hash-table-keys and hash-table-values * lisp/emacs-lisp/subr-x.el (hash-table-keys, hash-table-values): Omit the reversal of the returned list. It is not ordered anyway. * test/lisp/emacs-lisp/subr-x-tests.el (subr-x--hash-table-keys-and-values): New test. diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 9cd793d05c..5c3dff62c8 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -87,11 +87,15 @@ threading." (defsubst hash-table-keys (hash-table) "Return a list of keys in HASH-TABLE." - (cl-loop for k being the hash-keys of hash-table collect k)) + (let ((keys nil)) + (maphash (lambda (k _) (push k keys)) hash-table) + keys)) (defsubst hash-table-values (hash-table) "Return a list of values in HASH-TABLE." - (cl-loop for v being the hash-values of hash-table collect v)) + (let ((values nil)) + (maphash (lambda (_ v) (push v values)) hash-table) + values)) (defsubst string-empty-p (string) "Check whether STRING is empty." diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el index 7f3916c2c0..0bec9db36e 100644 --- a/test/lisp/emacs-lisp/subr-x-tests.el +++ b/test/lisp/emacs-lisp/subr-x-tests.el @@ -743,6 +743,13 @@ (with-current-buffer inner (should-not (buffer-modified-p)))))))) +(ert-deftest subr-x--hash-table-keys-and-values () + (let ((h (make-hash-table))) + (puthash 'a 1 h) + (puthash 'c 3 h) + (puthash 'b 2 h) + (should (equal (sort (hash-table-keys h) #'string<) '(a b c))) + (should (equal (sort (hash-table-values h) #'<) '(1 2 3))))) (provide 'subr-x-tests) ;;; subr-x-tests.el ends here commit c1f4cca7f013772c217e9ca0ad4f7f49c2d1eb4e Author: Lars Ingebrigtsen Date: Fri Jun 17 16:59:18 2022 +0200 Fix efaq-w32.texi build warning * doc/misc/efaq-w32.texi (Other useful ports): Fix ordering to match nodes (or should the nodes be moved instead?). Do not merge to master. diff --git a/doc/misc/efaq-w32.texi b/doc/misc/efaq-w32.texi index d18a045b33..35ff01a336 100644 --- a/doc/misc/efaq-w32.texi +++ b/doc/misc/efaq-w32.texi @@ -2102,9 +2102,9 @@ suggestions} for improving the interaction of perldb and Emacs. @menu * Cygwin:: -* MinGW:: -* EZWinPorts:: * MinGW-w64:: +* EZWinPorts:: +* MinGW:: * GnuWin32:: * GTK:: * Read man pages:: commit a203ad5ed0959d60f01f0265c4b658119a0b6858 Author: Lars Ingebrigtsen Date: Fri Jun 17 19:11:16 2022 +0200 Regenerate ldefs-boot.el diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index 06e2e9027c..7d06328a54 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -300,8 +300,8 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...) BODY...) (fn FUNCTION ARGS &rest BODY)" nil t) -(function-put 'defadvice 'doc-string-elt '3) -(function-put 'defadvice 'lisp-indent-function '2) +(function-put 'defadvice 'doc-string-elt 3) +(function-put 'defadvice 'lisp-indent-function 2) (register-definition-prefixes "advice" '("ad-")) @@ -1844,7 +1844,7 @@ garbage collections that ran, and the time taken by garbage collection. See also `benchmark-run-compiled'. (fn &optional REPETITIONS &rest FORMS)" nil t) -(function-put 'benchmark-run 'lisp-indent-function '1) +(function-put 'benchmark-run 'lisp-indent-function 1) (autoload 'benchmark-run-compiled "benchmark" "\ Time execution of compiled version of FORMS. This is like `benchmark-run', but what is timed is a funcall of the @@ -1852,7 +1852,7 @@ byte code obtained by wrapping FORMS in a `lambda' and compiling the result. The overhead of the `lambda's is accounted for. (fn &optional REPETITIONS &rest FORMS)" nil t) -(function-put 'benchmark-run-compiled 'lisp-indent-function '1) +(function-put 'benchmark-run-compiled 'lisp-indent-function 1) (autoload 'benchmark "benchmark" "\ Print the time taken for REPETITIONS executions of FORM. Interactively, REPETITIONS is taken from the prefix arg, and @@ -1868,7 +1868,7 @@ Evaluate BODY and message the time taken. The return value is the value of the final form in BODY. (fn &rest BODY)" nil t) -(function-put 'benchmark-progn 'lisp-indent-function '0) +(function-put 'benchmark-progn 'lisp-indent-function 0) (register-definition-prefixes "benchmark" '("benchmark-")) @@ -3022,7 +3022,7 @@ actual Lisp function name. See Info node `(calc)Defining Functions'. (fn FUNC ARGS &rest BODY)" nil t) -(function-put 'defmath 'doc-string-elt '3) +(function-put 'defmath 'doc-string-elt 3) (function-put 'defmath 'lisp-indent-function 'defun) (register-definition-prefixes "calc" '("calc" "defcalcmodevar" "inexact-result" "math-" "var-")) @@ -3927,7 +3927,7 @@ MAP-SET := MAP-IDs | (MAP-IDs) MAP-SET MAP-ID := integer (fn NAME CCL-PROGRAM &optional DOC)" nil t) -(function-put 'define-ccl-program 'doc-string-elt '3) +(function-put 'define-ccl-program 'doc-string-elt 3) (function-put 'define-ccl-program 'lisp-indent-function 'defun) (autoload 'check-ccl-program "ccl" "\ Check validity of CCL-PROGRAM. @@ -4351,8 +4351,8 @@ OPTIONS-AND-METHODS currently understands: DEFAULT-BODY, if present, is used as the body of a default method. (fn NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest DEFAULT-BODY)" nil t) -(function-put 'cl-defgeneric 'lisp-indent-function '2) -(function-put 'cl-defgeneric 'doc-string-elt '3) +(function-put 'cl-defgeneric 'lisp-indent-function 2) +(function-put 'cl-defgeneric 'doc-string-elt 3) (autoload 'cl-generic-define "cl-generic" "\ @@ -6711,7 +6711,7 @@ the hook will be named `foo-mode-hook'. See Info node `(elisp)Derived Modes' for more details. (fn CHILD PARENT NAME [DOCSTRING] [KEYWORD-ARGS...] &rest BODY)" nil t) -(function-put 'define-derived-mode 'doc-string-elt '4) +(function-put 'define-derived-mode 'doc-string-elt 4) (function-put 'define-derived-mode 'lisp-indent-function 'defun) (autoload 'derived-mode-init-mode-variables "derived" "\ Initialize variables for a new MODE. @@ -8025,7 +8025,7 @@ the keywords can also be preceded by the obsolete triplet INIT-VALUE LIGHTER KEYMAP. (fn MODE DOC [KEYWORD VAL ... &rest BODY])" nil t) -(function-put 'define-minor-mode 'doc-string-elt '2) +(function-put 'define-minor-mode 'doc-string-elt 2) (function-put 'define-minor-mode 'lisp-indent-function 'defun) (defalias 'easy-mmode-define-global-mode #'define-globalized-minor-mode) (defalias 'define-global-minor-mode #'define-globalized-minor-mode) @@ -8059,7 +8059,7 @@ after running the major mode's hook. However, MODE is not turned on if the hook has explicitly disabled it. (fn GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)" nil t) -(function-put 'define-globalized-minor-mode 'doc-string-elt '2) +(function-put 'define-globalized-minor-mode 'doc-string-elt 2) (function-put 'define-globalized-minor-mode 'lisp-indent-function 'defun) (autoload 'easy-mmode-define-keymap "easy-mmode" "\ Return a keymap built from bindings BS. @@ -8087,15 +8087,15 @@ the constant's documentation. This macro is deprecated; use `defvar-keymap' instead. (fn M BS DOC &rest ARGS)" nil t) -(function-put 'easy-mmode-defmap 'doc-string-elt '3) -(function-put 'easy-mmode-defmap 'lisp-indent-function '1) +(function-put 'easy-mmode-defmap 'doc-string-elt 3) +(function-put 'easy-mmode-defmap 'lisp-indent-function 1) (autoload 'easy-mmode-defsyntax "easy-mmode" "\ Define variable ST as a syntax-table. CSS contains a list of syntax specifications of the form (CHAR . SYNTAX). (fn ST CSS DOC &rest ARGS)" nil t) -(function-put 'easy-mmode-defsyntax 'doc-string-elt '3) -(function-put 'easy-mmode-defsyntax 'lisp-indent-function '1) +(function-put 'easy-mmode-defsyntax 'doc-string-elt 3) +(function-put 'easy-mmode-defsyntax 'lisp-indent-function 1) (register-definition-prefixes "easy-mmode" '("easy-mmode-")) @@ -13001,8 +13001,8 @@ mode hook `MODE-hook'. See the file generic-x.el for some examples of `define-generic-mode'. (fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST AUTO-MODE-LIST FUNCTION-LIST &optional DOCSTRING)" nil t) -(function-put 'define-generic-mode 'lisp-indent-function '1) -(function-put 'define-generic-mode 'doc-string-elt '7) +(function-put 'define-generic-mode 'lisp-indent-function 1) +(function-put 'define-generic-mode 'doc-string-elt 7) (autoload 'generic-mode-internal "generic" "\ Go into the generic mode MODE. @@ -14373,7 +14373,7 @@ The returned value will then be an Elisp expression that first evaluates all the parts of PLACE that can be evaluated and then runs E. (fn (GETTER SETTER) PLACE &rest BODY)" nil t) -(function-put 'gv-letplace 'lisp-indent-function '2) +(function-put 'gv-letplace 'lisp-indent-function 2) (autoload 'gv-define-expander "gv" "\ Use HANDLER to handle NAME as a generalized var. NAME is a symbol: the name of a function, macro, or special form. @@ -14381,7 +14381,7 @@ HANDLER is a function which takes an argument DO followed by the same arguments as NAME. DO is a function as defined in `gv-get'. (fn NAME HANDLER)" nil t) -(function-put 'gv-define-expander 'lisp-indent-function '1) +(function-put 'gv-define-expander 'lisp-indent-function 1) (autoload 'gv--defun-declaration "gv" "\ @@ -14404,7 +14404,7 @@ to be pure and copyable. Example use: (gv-define-setter aref (v a i) \\=`(aset ,a ,i ,v)) (fn NAME ARGLIST &rest BODY)" nil t) -(function-put 'gv-define-setter 'lisp-indent-function '2) +(function-put 'gv-define-setter 'lisp-indent-function 2) (autoload 'gv-define-simple-setter "gv" "\ Define a simple setter method for generalized variable NAME. This macro is an easy-to-use substitute for `gv-define-expander' that works @@ -16720,7 +16720,7 @@ Example: (:type xbm :file \"~/test1.xbm\"))) (fn SYMBOL SPECS &optional DOC)" nil t) -(function-put 'defimage 'doc-string-elt '3) +(function-put 'defimage 'doc-string-elt 3) (function-put 'defimage 'lisp-indent-function 'defun) (autoload 'imagemagick-register-types "image" "\ Register file types that can be handled by ImageMagick. @@ -17534,7 +17534,7 @@ See Info node `(elisp)Defining Functions' for more details. (fn NAME ARGS &rest BODY)" nil t) (function-put 'define-inline 'lisp-indent-function 'defun) -(function-put 'define-inline 'doc-string-elt '3) +(function-put 'define-inline 'doc-string-elt 3) (register-definition-prefixes "inline" '("inline-")) @@ -18397,7 +18397,7 @@ inside the original alist by using dots inside the symbol, as displayed in the example above. (fn ALIST &rest BODY)" nil t) -(function-put 'let-alist 'lisp-indent-function '1) +(function-put 'let-alist 'lisp-indent-function 1) (register-definition-prefixes "let-alist" '("let-alist--")) @@ -20637,7 +20637,7 @@ This affects the implicit sorting of lists of coding systems returned by operations such as `find-coding-systems-region'. (fn CODING-SYSTEMS &rest BODY)" nil t) -(function-put 'with-coding-priority 'lisp-indent-function '1) +(function-put 'with-coding-priority 'lisp-indent-function 1) (autoload 'detect-coding-with-language-environment "mule-util" "\ Detect a coding system for the text between FROM and TO with LANG-ENV. The detection takes into account the coding system priorities for the @@ -22939,7 +22939,7 @@ See Info node `(elisp) Pattern-Matching Conditional' in the Emacs Lisp manual for more information and examples. (fn EXP &rest CASES)" nil t) -(function-put 'pcase 'lisp-indent-function '1) +(function-put 'pcase 'lisp-indent-function 1) (put 'pcase 'function-documentation '(pcase--make-docstring)) (autoload 'pcase--make-docstring "pcase" nil nil nil) (autoload 'pcase-exhaustive "pcase" "\ @@ -22951,7 +22951,7 @@ In contrast, `pcase' will return nil if there is no match, but not signal an error. (fn EXP &rest CASES)" nil t) -(function-put 'pcase-exhaustive 'lisp-indent-function '1) +(function-put 'pcase-exhaustive 'lisp-indent-function 1) (autoload 'pcase-lambda "pcase" "\ Like `lambda' but allow each argument to be a pattern. I.e. accepts the usual &optional and &rest keywords, but every @@ -22959,7 +22959,7 @@ formal argument can be any pattern accepted by `pcase' (a mere variable name being but a special case of it). (fn LAMBDA-LIST &rest BODY)" nil t) -(function-put 'pcase-lambda 'doc-string-elt '2) +(function-put 'pcase-lambda 'doc-string-elt 2) (function-put 'pcase-lambda 'lisp-indent-function 'defun) (autoload 'pcase-let* "pcase" "\ Like `let*', but supports destructuring BINDINGS using `pcase' patterns. @@ -22972,7 +22972,7 @@ respective PATTERN; a mismatch may signal an error or may go undetected, binding variables to arbitrary values, such as nil. (fn BINDINGS &rest BODY)" nil t) -(function-put 'pcase-let* 'lisp-indent-function '1) +(function-put 'pcase-let* 'lisp-indent-function 1) (autoload 'pcase-let "pcase" "\ Like `let', but supports destructuring BINDINGS using `pcase' patterns. BODY should be a list of expressions, and BINDINGS should be a list of @@ -22986,7 +22986,7 @@ respective PATTERN; a mismatch may signal an error or may go undetected, binding variables to arbitrary values, such as nil. (fn BINDINGS &rest BODY)" nil t) -(function-put 'pcase-let 'lisp-indent-function '1) +(function-put 'pcase-let 'lisp-indent-function 1) (autoload 'pcase-dolist "pcase" "\ Eval BODY once for each set of bindings defined by PATTERN and LIST elements. PATTERN should be a `pcase' pattern describing the structure of @@ -22999,7 +22999,7 @@ destructuring bindings of variables in PATTERN to the subfields of the elements of LIST is performed as if by `pcase-let'. (fn (PATTERN LIST) BODY...)" nil t) -(function-put 'pcase-dolist 'lisp-indent-function '1) +(function-put 'pcase-dolist 'lisp-indent-function 1) (autoload 'pcase-setq "pcase" "\ Assign values to variables by destructuring with `pcase'. PATTERNS are normal `pcase' patterns, and VALUES are expression. @@ -23021,8 +23021,8 @@ By convention, DOC should use \"EXPVAL\" to stand for the result of evaluating EXP (first arg to `pcase'). (fn NAME ARGS [DOC] &rest BODY...)" nil t) -(function-put 'pcase-defmacro 'lisp-indent-function '2) -(function-put 'pcase-defmacro 'doc-string-elt '3) +(function-put 'pcase-defmacro 'lisp-indent-function 2) +(function-put 'pcase-defmacro 'doc-string-elt 3) (register-definition-prefixes "pcase" '("pcase-")) @@ -26633,7 +26633,7 @@ To make global rx extensions, use `rx-define'. For more details, see Info node `(elisp) Extending Rx'. (fn BINDINGS BODY...)" nil t) -(function-put 'rx-let-eval 'lisp-indent-function '1) +(function-put 'rx-let-eval 'lisp-indent-function 1) (autoload 'rx-let "rx" "\ Evaluate BODY with local BINDINGS for `rx'. BINDINGS is an unevaluated list of bindings each on the form @@ -26655,7 +26655,7 @@ To make global rx extensions, use `rx-define'. For more details, see Info node `(elisp) Extending Rx'. (fn BINDINGS BODY...)" nil t) -(function-put 'rx-let 'lisp-indent-function '1) +(function-put 'rx-let 'lisp-indent-function 1) (autoload 'rx-define "rx" "\ Define NAME as a global `rx' definition. If the ARGS list is omitted, define NAME as an alias for the `rx' @@ -27930,7 +27930,7 @@ DOCUMENTATION is that of the command. SKELETON is as defined under `skeleton-insert'. (fn COMMAND DOCUMENTATION &rest SKELETON)" nil t) -(function-put 'define-skeleton 'doc-string-elt '2) +(function-put 'define-skeleton 'doc-string-elt 2) (function-put 'define-skeleton 'lisp-indent-function 'defun) (autoload 'skeleton-proxy-new "skeleton" "\ Insert SKELETON. commit f515d658e5e5382bfbcf835dee4a32099c9815e6 Author: Lars Ingebrigtsen Date: Fri Jun 17 19:10:44 2022 +0200 Don't quote numbers in byte-run--set-* * lisp/emacs-lisp/byte-run.el (byte-run--set-doc-string) (byte-run--set-indent): Don't quote numbers (bug#48145). diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el index 498435c58d..dd90bcf4d8 100644 --- a/lisp/emacs-lisp/byte-run.el +++ b/lisp/emacs-lisp/byte-run.el @@ -210,12 +210,16 @@ The return value of this function is not used." (defalias 'byte-run--set-doc-string #'(lambda (f _args pos) (list 'function-put (list 'quote f) - ''doc-string-elt (list 'quote pos)))) + ''doc-string-elt (if (numberp pos) + pos + (list 'quote pos))))) (defalias 'byte-run--set-indent #'(lambda (f _args val) (list 'function-put (list 'quote f) - ''lisp-indent-function (list 'quote val)))) + ''lisp-indent-function (if (numberp val) + val + (list 'quote val))))) (defalias 'byte-run--set-speed #'(lambda (f _args val) commit 8ce96f0d4d3b8c80a8b6165b69a67310afdf6a3a Author: Michael Albinus Date: Fri Jun 17 18:53:23 2022 +0200 Fix handling of "process-*" properties in Tramp * lisp/net/tramp.el (tramp-local-host-regexp): Add "localhost4". (with-tramp-saved-connection-property): New defmacro. * lisp/net/tramp-adb.el (tramp-adb-handle-make-process): * lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band) (tramp-sh-handle-make-process): * lisp/net/tramp-smb.el (tramp-smb-handle-copy-directory): (tramp-smb-handle-file-acl, tramp-smb-handle-process-file) (tramp-smb-handle-set-file-acl) (tramp-smb-handle-start-file-process): Use it. (Bug#55832) diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 8268b2d167..0c3d87cc91 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -942,7 +942,8 @@ implementation will be used." (or (null program) tramp-process-connection-type)) (bmp (and (buffer-live-p buffer) (buffer-modified-p buffer))) (name1 name) - (i 0)) + (i 0) + p) (when (string-match-p "[[:multibyte:]]" command) (tramp-error @@ -953,9 +954,6 @@ implementation will be used." (setq i (1+ i) name1 (format "%s<%d>" name i))) (setq name name1) - ;; Set the new process properties. - (tramp-set-connection-property v "process-name" name) - (tramp-set-connection-property v "process-buffer" buffer) (with-current-buffer (tramp-get-connection-buffer v) (unwind-protect @@ -963,45 +961,52 @@ implementation will be used." ;; could be called on the local host. (save-excursion (save-restriction - ;; Activate narrowing in order to save BUFFER - ;; contents. Clear also the modification time; - ;; otherwise we might be interrupted by - ;; `verify-visited-file-modtime'. - (let ((buffer-undo-list t) - (inhibit-read-only t) - (coding-system-for-write - (if (symbolp coding) coding (car coding))) - (coding-system-for-read - (if (symbolp coding) coding (cdr coding)))) - (clear-visited-file-modtime) - (narrow-to-region (point-max) (point-max)) - ;; We call `tramp-adb-maybe-open-connection', - ;; in order to cleanup the prompt afterwards. - (tramp-adb-maybe-open-connection v) - (delete-region (point-min) (point-max)) - ;; Send the command. - (let* ((p (tramp-get-connection-process v))) - (tramp-adb-send-command v command nil t) ; nooutput - ;; Set sentinel and filter. - (when sentinel - (set-process-sentinel p sentinel)) - (when filter - (set-process-filter p filter)) - (process-put p 'remote-command orig-command) + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + ;; Set the new process properties. + (tramp-set-connection-property v "process-name" name) (tramp-set-connection-property - p "remote-command" orig-command) - ;; Set query flag and process marker for - ;; this process. We ignore errors, because - ;; the process could have finished already. - (ignore-errors - (set-process-query-on-exit-flag p (null noquery)) - (set-marker (process-mark p) (point))) - ;; We must flush them here already; + v "process-buffer" buffer) + ;; Activate narrowing in order to save + ;; BUFFER contents. Clear also the + ;; modification time; otherwise we might be + ;; interrupted by `verify-visited-file-modtime'. + (let ((buffer-undo-list t) + (inhibit-read-only t) + (coding-system-for-write + (if (symbolp coding) coding (car coding))) + (coding-system-for-read + (if (symbolp coding) coding (cdr coding)))) + (clear-visited-file-modtime) + (narrow-to-region (point-max) (point-max)) + ;; We call `tramp-adb-maybe-open-connection', + ;; in order to cleanup the prompt + ;; afterwards. + (tramp-adb-maybe-open-connection v) + (delete-region (point-min) (point-max)) + ;; Send the command. + (setq p (tramp-get-connection-process v)) + (tramp-adb-send-command v command nil t) ; nooutput + ;; Set sentinel and filter. + (when sentinel + (set-process-sentinel p sentinel)) + (when filter + (set-process-filter p filter)) + (process-put p 'remote-command orig-command) + (tramp-set-connection-property + p "remote-command" orig-command) + ;; Set query flag and process marker for + ;; this process. We ignore errors, + ;; because the process could have finished + ;; already. + (ignore-errors + (set-process-query-on-exit-flag p (null noquery)) + (set-marker (process-mark p) (point)))) + + ;; Copy tmpstderr file. "process-buffer" + ;; and "process-name" must be reset already; ;; otherwise `rename-file', `delete-file' or ;; `insert-file-contents' will fail. - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer") - ;; Copy tmpstderr file. (when (and (stringp stderr) (not (tramp-tramp-file-p stderr))) (add-function @@ -1038,13 +1043,13 @@ implementation will be used." p)))) ;; Save exit. + ;; FIXME: Does `tramp-get-connection-process' return + ;; the proper value? (if (string-prefix-p tramp-temp-buffer-name (buffer-name)) (ignore-errors (set-process-buffer (tramp-get-connection-process v) nil) (kill-buffer (current-buffer))) - (set-buffer-modified-p bmp)) - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer"))))))))) + (set-buffer-modified-p bmp)))))))))) (defun tramp-adb-handle-exec-path () "Like `exec-path' for Tramp files." @@ -1360,7 +1365,7 @@ connection if a previous connection has died for some reason." (funcall orig-fun))) (add-function - :around (symbol-function #'shell-mode) #'tramp-adb-tolerate-tilde) + :around (symbol-function #'shell-mode) #'tramp-adb-tolerate-tilde) (add-hook 'tramp-adb-unload-hook (lambda () (remove-function diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 8f8b81186b..eccc15efe7 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -2417,53 +2417,53 @@ The method used must be an out-of-band method." (with-temp-buffer (unwind-protect - ;; The default directory must be remote. - (let ((default-directory - (file-name-directory (if v1 filename newname))) - (process-environment (copy-sequence process-environment))) - ;; Set the transfer process properties. - (tramp-set-connection-property - v "process-name" (buffer-name (current-buffer))) - (tramp-set-connection-property - v "process-buffer" (current-buffer)) - (when copy-env - (tramp-message - v 6 "%s=\"%s\"" - (car copy-env) (string-join (cdr copy-env) " ")) - (setenv (car copy-env) (string-join (cdr copy-env) " "))) - (setq - copy-args - (append - copy-args - (if remote-copy-program - (list (if v1 (concat ">" target) (concat "<" source))) - (list source target))) - ;; Use an asynchronous process. By this, password can - ;; be handled. We don't set a timeout, because the - ;; copying of large files can last longer than 60 secs. - p (let ((default-directory - tramp-compat-temporary-file-directory)) - (apply - #'start-process - (tramp-get-connection-name v) - (tramp-get-connection-buffer v) - copy-program copy-args))) - (tramp-message v 6 "%s" (string-join (process-command p) " ")) - (process-put p 'vector v) - (process-put p 'adjust-window-size-function #'ignore) - (set-process-query-on-exit-flag p nil) - - ;; We must adapt `tramp-local-end-of-line' for sending - ;; the password. Also, we indicate that perhaps several - ;; password prompts might appear. - (let ((tramp-local-end-of-line tramp-rsh-end-of-line) - (tramp-password-prompt-not-unique (and v1 v2))) - (tramp-process-actions - p v nil tramp-actions-copy-out-of-band))) - - ;; Reset the transfer process properties. - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer") + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + ;; The default directory must be remote. + (let ((default-directory + (file-name-directory (if v1 filename newname))) + (process-environment (copy-sequence process-environment))) + ;; Set the transfer process properties. + (tramp-set-connection-property + v "process-name" (buffer-name (current-buffer))) + (tramp-set-connection-property + v "process-buffer" (current-buffer)) + (when copy-env + (tramp-message + v 6 "%s=\"%s\"" + (car copy-env) (string-join (cdr copy-env) " ")) + (setenv (car copy-env) (string-join (cdr copy-env) " "))) + (setq + copy-args + (append + copy-args + (if remote-copy-program + (list (if v1 (concat ">" target) (concat "<" source))) + (list source target))) + ;; Use an asynchronous process. By this, password + ;; can be handled. We don't set a timeout, because + ;; the copying of large files can last longer than + ;; 60 secs. + p (let ((default-directory + tramp-compat-temporary-file-directory)) + (apply + #'start-process + (tramp-get-connection-name v) + (tramp-get-connection-buffer v) + copy-program copy-args))) + (tramp-message v 6 "%s" (string-join (process-command p) " ")) + (process-put p 'vector v) + (process-put p 'adjust-window-size-function #'ignore) + (set-process-query-on-exit-flag p nil) + + ;; We must adapt `tramp-local-end-of-line' for sending + ;; the password. Also, we indicate that perhaps several + ;; password prompts might appear. + (let ((tramp-local-end-of-line tramp-rsh-end-of-line) + (tramp-password-prompt-not-unique (and v1 v2))) + (tramp-process-actions + p v nil tramp-actions-copy-out-of-band))))) + ;; Clear the remote prompt. (when (and remote-copy-program (not (tramp-send-command-and-check v nil))) @@ -2976,94 +2976,99 @@ implementation will be used." (setq i (1+ i) name1 (format "%s<%d>" name i))) (setq name name1) - ;; Set the new process properties. - (tramp-set-connection-property v "process-name" name) - (tramp-set-connection-property v "process-buffer" buffer) (with-current-buffer (tramp-get-connection-buffer v) (unwind-protect - ;; We catch this event. Otherwise, `make-process' - ;; could be called on the local host. - (save-excursion - (save-restriction - ;; Activate narrowing in order to save BUFFER - ;; contents. Clear also the modification time; - ;; otherwise we might be interrupted by - ;; `verify-visited-file-modtime'. - (let ((buffer-undo-list t) - (inhibit-read-only t) - (mark (point-max)) - (coding-system-for-write - (if (symbolp coding) coding (car coding))) - (coding-system-for-read - (if (symbolp coding) coding (cdr coding)))) - (clear-visited-file-modtime) - (narrow-to-region (point-max) (point-max)) - (catch 'suppress - ;; Set the pid of the remote shell. This is - ;; needed when sending signals remotely. - (let ((pid (tramp-send-command-and-read v "echo $$"))) - (setq p (tramp-get-connection-process v)) - (process-put p 'remote-pid pid) - (tramp-set-connection-property p "remote-pid" pid)) - ;; Disable carriage return to newline - ;; translation. This does not work on - ;; macOS, see Bug#50748. - (when (and (memq connection-type '(nil pipe)) - (not (tramp-check-remote-uname v "Darwin"))) - (tramp-send-command v "stty -icrnl")) - ;; `tramp-maybe-open-connection' and - ;; `tramp-send-command-and-read' could have - ;; trashed the connection buffer. Remove this. - (widen) - (delete-region mark (point-max)) - (narrow-to-region (point-max) (point-max)) - ;; Now do it. - (if command - ;; Send the command. - (tramp-send-command v command nil t) ; nooutput - ;; Check, whether a pty is associated. - (unless (process-get p 'remote-tty) - (tramp-error - v 'file-error - "pty association is not supported for `%s'" - name)))) - ;; Set sentinel and filter. - (when sentinel - (set-process-sentinel p sentinel)) - (when filter - (set-process-filter p filter)) - (process-put p 'remote-command orig-command) - (tramp-set-connection-property - p "remote-command" orig-command) - ;; Set query flag and process marker for this - ;; process. We ignore errors, because the - ;; process could have finished already. - (ignore-errors - (set-process-query-on-exit-flag p (null noquery)) - (set-marker (process-mark p) (point))) - ;; Kill stderr process and delete named pipe. - (when (bufferp stderr) - (add-function - :after (process-sentinel p) - (lambda (_proc _msg) - (ignore-errors - (while (accept-process-output - (get-buffer-process stderr) 0 nil t)) - (delete-process (get-buffer-process stderr))) - (ignore-errors - (delete-file remote-tmpstderr))))) - ;; Return process. - p))) + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + ;; Set the new process properties. + (tramp-set-connection-property v "process-name" name) + (tramp-set-connection-property v "process-buffer" buffer) + ;; We catch this event. Otherwise, + ;; `make-process' could be called on the local + ;; host. + (save-excursion + (save-restriction + ;; Activate narrowing in order to save + ;; BUFFER contents. Clear also the + ;; modification time; otherwise we might be + ;; interrupted by `verify-visited-file-modtime'. + (let ((buffer-undo-list t) + (inhibit-read-only t) + (mark (point-max)) + (coding-system-for-write + (if (symbolp coding) coding (car coding))) + (coding-system-for-read + (if (symbolp coding) coding (cdr coding)))) + (clear-visited-file-modtime) + (narrow-to-region (point-max) (point-max)) + (catch 'suppress + ;; Set the pid of the remote shell. This is + ;; needed when sending signals remotely. + (let ((pid + (tramp-send-command-and-read v "echo $$"))) + (setq p (tramp-get-connection-process v)) + (process-put p 'remote-pid pid) + (tramp-set-connection-property + p "remote-pid" pid)) + ;; Disable carriage return to newline + ;; translation. This does not work on + ;; macOS, see Bug#50748. + (when (and (memq connection-type '(nil pipe)) + (not + (tramp-check-remote-uname v "Darwin"))) + (tramp-send-command v "stty -icrnl")) + ;; `tramp-maybe-open-connection' and + ;; `tramp-send-command-and-read' could have + ;; trashed the connection buffer. Remove this. + (widen) + (delete-region mark (point-max)) + (narrow-to-region (point-max) (point-max)) + ;; Now do it. + (if command + ;; Send the command. + (tramp-send-command v command nil t) ; nooutput + ;; Check, whether a pty is associated. + (unless (process-get p 'remote-tty) + (tramp-error + v 'file-error + "pty association is not supported for `%s'" + name)))) + ;; Set sentinel and filter. + (when sentinel + (set-process-sentinel p sentinel)) + (when filter + (set-process-filter p filter)) + (process-put p 'remote-command orig-command) + (tramp-set-connection-property + p "remote-command" orig-command) + ;; Set query flag and process marker for + ;; this process. We ignore errors, + ;; because the process could have finished + ;; already. + (ignore-errors + (set-process-query-on-exit-flag p (null noquery)) + (set-marker (process-mark p) (point))) + ;; Kill stderr process and delete named pipe. + (when (bufferp stderr) + (add-function + :after (process-sentinel p) + (lambda (_proc _msg) + (ignore-errors + (while (accept-process-output + (get-buffer-process stderr) 0 nil t)) + (delete-process (get-buffer-process stderr))) + (ignore-errors + (delete-file remote-tmpstderr))))) + ;; Return process. + p))))) ;; Save exit. (if (string-prefix-p tramp-temp-buffer-name (buffer-name)) (ignore-errors (set-process-buffer p nil) (kill-buffer (current-buffer))) - (set-buffer-modified-p bmp)) - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer"))))))))) + (set-buffer-modified-p bmp)))))))))) (defun tramp-sh-get-signal-strings (vec) "Strings to return by `process-file' in case of signals." @@ -6133,5 +6138,4 @@ function cell is returned to be applied on a buffer." ;; * Support hostname canonicalization in ~/.ssh/config. ;; - ;;; tramp-sh.el ends here diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 3654910133..528463c5a7 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -519,50 +519,50 @@ arguments to pass to the OPERATION." "tar qx -"))))) (unwind-protect - (with-temp-buffer - ;; Set the transfer process properties. - (tramp-set-connection-property - v "process-name" (buffer-name (current-buffer))) - (tramp-set-connection-property - v "process-buffer" (current-buffer)) - - (when t1 - ;; The smbclient tar command creates always - ;; complete paths. We must emulate the - ;; directory structure, and symlink to the - ;; real target. - (make-directory - (expand-file-name - ".." (concat tmpdir localname)) - 'parents) - (make-symbolic-link - newname - (directory-file-name (concat tmpdir localname)))) - - ;; Use an asynchronous processes. By this, - ;; password can be handled. - (let* ((default-directory tmpdir) - (p (apply - #'start-process - (tramp-get-connection-name v) - (tramp-get-connection-buffer v) - tramp-smb-program args))) - - (tramp-message - v 6 "%s" (string-join (process-command p) " ")) - (process-put p 'vector v) - (process-put p 'adjust-window-size-function #'ignore) - (set-process-query-on-exit-flag p nil) - (tramp-process-actions - p v nil tramp-smb-actions-with-tar) - - (while (process-live-p p) - (sleep-for 0.1)) - (tramp-message v 6 "\n%s" (buffer-string)))) - - ;; Reset the transfer process properties. - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer") + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + (with-temp-buffer + ;; Set the transfer process properties. + (tramp-set-connection-property + v "process-name" (buffer-name (current-buffer))) + (tramp-set-connection-property + v "process-buffer" (current-buffer)) + + (when t1 + ;; The smbclient tar command creates + ;; always complete paths. We must emulate + ;; the directory structure, and symlink to + ;; the real target. + (make-directory + (expand-file-name + ".." (concat tmpdir localname)) + 'parents) + (make-symbolic-link + newname + (directory-file-name (concat tmpdir localname)))) + + ;; Use an asynchronous processes. By this, + ;; password can be handled. + (let* ((default-directory tmpdir) + (p (apply + #'start-process + (tramp-get-connection-name v) + (tramp-get-connection-buffer v) + tramp-smb-program args))) + + (tramp-message + v 6 "%s" (string-join (process-command p) " ")) + (process-put p 'vector v) + (process-put p 'adjust-window-size-function #'ignore) + (set-process-query-on-exit-flag p nil) + (tramp-process-actions + p v nil tramp-smb-actions-with-tar) + + (while (process-live-p p) + (sleep-for 0.1)) + (tramp-message v 6 "\n%s" (buffer-string)))))) + + ;; Save exit. (when t1 (delete-directory tmpdir 'recursive)))) ;; Handle KEEP-DATE argument. @@ -824,33 +824,31 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (concat "2>" (tramp-get-remote-null-device v))))) (unwind-protect - (with-temp-buffer - ;; Set the transfer process properties. - (tramp-set-connection-property - v "process-name" (buffer-name (current-buffer))) - (tramp-set-connection-property - v "process-buffer" (current-buffer)) - - ;; Use an asynchronous process. By this, password can - ;; be handled. - (let ((p (apply - #'start-process - (tramp-get-connection-name v) - (tramp-get-connection-buffer v) - tramp-smb-acl-program args))) - - (tramp-message - v 6 "%s" (string-join (process-command p) " ")) - (process-put p 'vector v) - (process-put p 'adjust-window-size-function #'ignore) - (set-process-query-on-exit-flag p nil) - (tramp-process-actions p v nil tramp-smb-actions-get-acl) - (when (> (point-max) (point-min)) - (substring-no-properties (buffer-string))))) - - ;; Reset the transfer process properties. - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer")))))))) + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + (with-temp-buffer + ;; Set the transfer process properties. + (tramp-set-connection-property + v "process-name" (buffer-name (current-buffer))) + (tramp-set-connection-property + v "process-buffer" (current-buffer)) + + ;; Use an asynchronous process. By this, + ;; password can be handled. + (let ((p (apply + #'start-process + (tramp-get-connection-name v) + (tramp-get-connection-buffer v) + tramp-smb-acl-program args))) + + (tramp-message + v 6 "%s" (string-join (process-command p) " ")) + (process-put p 'vector v) + (process-put p 'adjust-window-size-function #'ignore) + (set-process-query-on-exit-flag p nil) + (tramp-process-actions p v nil tramp-smb-actions-get-acl) + (when (> (point-max) (point-min)) + (substring-no-properties (buffer-string)))))))))))))) (defun tramp-smb-handle-file-attributes (filename &optional id-format) "Like `file-attributes' for Tramp files." @@ -1342,33 +1340,34 @@ component is used as the target of the symlink." (setq i (1+ i) name1 (format "%s<%d>" name i))) - ;; Set the new process properties. - (tramp-set-connection-property v "process-name" name1) - (tramp-set-connection-property - v "process-buffer" - (or outbuf (generate-new-buffer tramp-temp-buffer-name))) - ;; Call it. (condition-case nil - (with-current-buffer (tramp-get-connection-buffer v) - ;; Preserve buffer contents. - (narrow-to-region (point-max) (point-max)) - (tramp-smb-call-winexe v) - (when (tramp-smb-get-share v) - (tramp-smb-send-command - v (format "cd //%s%s" host - (tramp-smb-shell-quote-argument - (file-name-directory localname))))) - (tramp-smb-send-command v command) - ;; Preserve command output. - (narrow-to-region (point-max) (point-max)) - (let ((p (tramp-get-connection-process v))) - (tramp-smb-send-command v "exit $lasterrorcode") - (while (process-live-p p) - (sleep-for 0.1) - (setq ret (process-exit-status p)))) - (delete-region (point-min) (point-max)) - (widen)) + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + ;; Set the new process properties. + (tramp-set-connection-property v "process-name" name1) + (tramp-set-connection-property + v "process-buffer" + (or outbuf (generate-new-buffer tramp-temp-buffer-name))) + (with-current-buffer (tramp-get-connection-buffer v) + ;; Preserve buffer contents. + (narrow-to-region (point-max) (point-max)) + (tramp-smb-call-winexe v) + (when (tramp-smb-get-share v) + (tramp-smb-send-command + v (format "cd //%s%s" host + (tramp-smb-shell-quote-argument + (file-name-directory localname))))) + (tramp-smb-send-command v command) + ;; Preserve command output. + (narrow-to-region (point-max) (point-max)) + (let ((p (tramp-get-connection-process v))) + (tramp-smb-send-command v "exit $lasterrorcode") + (while (process-live-p p) + (sleep-for 0.1) + (setq ret (process-exit-status p)))) + (delete-region (point-min) (point-max)) + (widen)))) ;; When the user did interrupt, we should do it also. We use ;; return code -1 as marker. @@ -1383,9 +1382,8 @@ component is used as the target of the symlink." ;; Cleanup. We remove all file cache values for the connection, ;; because the remote process could have changed them. - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer") (when tmpinput (delete-file tmpinput)) + ;; FIXME: Does connection-property "process-buffer" still exist? (unless outbuf (kill-buffer (tramp-get-connection-property v "process-buffer" nil))) (when process-file-side-effects @@ -1488,42 +1486,44 @@ component is used as the target of the symlink." "||" "echo" "tramp_exit_status" "1"))) (unwind-protect - (with-temp-buffer - ;; Set the transfer process properties. - (tramp-set-connection-property - v "process-name" (buffer-name (current-buffer))) - (tramp-set-connection-property - v "process-buffer" (current-buffer)) - - ;; Use an asynchronous process. By this, password can - ;; be handled. - (let ((p (apply - #'start-process - (tramp-get-connection-name v) - (tramp-get-connection-buffer v) - tramp-smb-acl-program args))) - - (tramp-message v 6 "%s" (string-join (process-command p) " ")) - (process-put p 'vector v) - (process-put p 'adjust-window-size-function #'ignore) - (set-process-query-on-exit-flag p nil) - (tramp-process-actions p v nil tramp-smb-actions-set-acl) - ;; This is meant for traces, and returning from the - ;; function. No error is propagated outside, due to - ;; the `ignore-errors' closure. - (unless (tramp-search-regexp "tramp_exit_status [[:digit:]]+") - (tramp-error - v 'file-error - "Couldn't find exit status of `%s'" tramp-smb-acl-program)) - (skip-chars-forward "^ ") - (when (zerop (read (current-buffer))) - ;; Success. - (tramp-set-file-property v localname "file-acl" acl-string) - t))) - - ;; Reset the transfer process properties. - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer"))))))) + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + (with-temp-buffer + ;; Set the transfer process properties. + (tramp-set-connection-property + v "process-name" (buffer-name (current-buffer))) + (tramp-set-connection-property + v "process-buffer" (current-buffer)) + + ;; Use an asynchronous process. By this, password + ;; can be handled. + (let ((p (apply + #'start-process + (tramp-get-connection-name v) + (tramp-get-connection-buffer v) + tramp-smb-acl-program args))) + + (tramp-message + v 6 "%s" (string-join (process-command p) " ")) + (process-put p 'vector v) + (process-put p 'adjust-window-size-function #'ignore) + (set-process-query-on-exit-flag p nil) + (tramp-process-actions p v nil tramp-smb-actions-set-acl) + ;; This is meant for traces, and returning from + ;; the function. No error is propagated + ;; outside, due to the `ignore-errors' closure. + (unless + (tramp-search-regexp "tramp_exit_status [[:digit:]]+") + (tramp-error + v 'file-error + "Couldn't find exit status of `%s'" + tramp-smb-acl-program)) + (skip-chars-forward "^ ") + (when (zerop (read (current-buffer))) + ;; Success. + (tramp-set-file-property + v localname "file-acl" acl-string) + t))))))))))) (defun tramp-smb-handle-set-file-modes (filename mode &optional flag) "Like `set-file-modes' for Tramp files." @@ -1555,46 +1555,47 @@ component is used as the target of the symlink." (i 0) p) (unwind-protect - (save-excursion - (save-restriction - (while (get-process name1) - ;; NAME must be unique as process name. - (setq i (1+ i) - name1 (format "%s<%d>" name i))) - ;; Set the new process properties. - (tramp-set-connection-property v "process-name" name1) - (tramp-set-connection-property v "process-buffer" buffer) - ;; Activate narrowing in order to save BUFFER contents. - (with-current-buffer (tramp-get-connection-buffer v) - (let ((buffer-undo-list t)) - (narrow-to-region (point-max) (point-max)) - (tramp-smb-call-winexe v) - (when (tramp-smb-get-share v) - (tramp-smb-send-command - v (format - "cd //%s%s" - host - (tramp-smb-shell-quote-argument - (file-name-directory localname))))) - (tramp-message v 6 "(%s); exit" command) - (tramp-send-string v command))) - (setq p (tramp-get-connection-process v)) - (when program - (process-put p 'remote-command (cons program args)) - (tramp-set-connection-property - p "remote-command" (cons program args))) - ;; Return value. - p)) + (with-tramp-saved-connection-property v "process-name" + (with-tramp-saved-connection-property v "process-buffer" + (save-excursion + (save-restriction + (while (get-process name1) + ;; NAME must be unique as process name. + (setq i (1+ i) + name1 (format "%s<%d>" name i))) + ;; Set the new process properties. + (tramp-set-connection-property v "process-name" name1) + (tramp-set-connection-property v "process-buffer" buffer) + ;; Activate narrowing in order to save BUFFER contents. + (with-current-buffer (tramp-get-connection-buffer v) + (let ((buffer-undo-list t)) + (narrow-to-region (point-max) (point-max)) + (tramp-smb-call-winexe v) + (when (tramp-smb-get-share v) + (tramp-smb-send-command + v (format + "cd //%s%s" + host + (tramp-smb-shell-quote-argument + (file-name-directory localname))))) + (tramp-message v 6 "(%s); exit" command) + (tramp-send-string v command))) + (setq p (tramp-get-connection-process v)) + (when program + (process-put p 'remote-command (cons program args)) + (tramp-set-connection-property + p "remote-command" (cons program args))) + ;; Return value. + p)))) ;; Save exit. + ;; FIXME: Does `tramp-get-connection-buffer' return the proper value? (with-current-buffer (tramp-get-connection-buffer v) (if (tramp-compat-string-search tramp-temp-buffer-name (buffer-name)) (progn (set-process-buffer (tramp-get-connection-process v) nil) (kill-buffer (current-buffer))) - (set-buffer-modified-p bmp))) - (tramp-flush-connection-property v "process-name") - (tramp-flush-connection-property v "process-buffer"))))) + (set-buffer-modified-p bmp))))))) (defun tramp-smb-handle-substitute-in-file-name (filename) "Like `substitute-in-file-name' for Tramp files. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index e4b14cfbc2..59a2710e00 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -522,11 +522,12 @@ host runs a restricted shell, it shall be added to this list, too." (concat "\\`" (regexp-opt - (list "localhost" "localhost6" tramp-system-name "127.0.0.1" "::1") t) + `("localhost" "localhost4" "localhost6" ,tramp-system-name "127.0.0.1" "::1") + t) "\\'") "Host names which are regarded as local host. If the local host runs a chrooted environment, set this to nil." - :version "27.1" + :version "29.1" :type '(choice (const :tag "Chrooted environment" nil) (regexp :tag "Host regexp"))) @@ -2393,6 +2394,16 @@ FILE must be a local file name on a connection identified via VEC." (tramp-set-connection-property ,key ,property value)) value)) +(defmacro with-tramp-saved-connection-property (key property &rest body) + "Save PROPERTY, run BODY, reset PROPERTY." + (declare (indent 2) (debug t)) + `(let ((value (tramp-get-connection-property + ,key ,property tramp-cache-undefined))) + (unwind-protect (progn ,@body) + (if (eq value tramp-cache-undefined) + (tramp-flush-connection-property ,key ,property) + (tramp-set-connection-property ,key ,property value))))) + (defun tramp-drop-volume-letter (name) "Cut off unnecessary drive letter from file NAME. The functions `tramp-*-handle-expand-file-name' call `expand-file-name' commit 0edc2f4901f606a9a298edbc2ddc630a44f04a26 Author: Lars Ingebrigtsen Date: Fri Jun 17 18:19:02 2022 +0200 Fix some declare-after-interactive functions * lisp/progmodes/opascal.el (opascal-new-comment-line): * lisp/image-mode.el (image-transform-fit-to-height): * lisp/help-fns.el (help-fns-edit-variable): * lisp/gnus/gnus-salt.el (gnus-pick-start-reading): * lisp/eshell/esh-util.el (eshell-for): * lisp/ldefs-boot.el (view-return-to-alist-update): Fix warnings about declare after interactive. diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el index b5a423f023..6b86498399 100644 --- a/lisp/eshell/esh-util.el +++ b/lisp/eshell/esh-util.el @@ -303,8 +303,7 @@ Prepend remote identification of `default-directory', if any." (defmacro eshell-for (for-var for-list &rest forms) "Iterate through a list." - (declare (obsolete dolist "24.1")) - (declare (indent 2)) + (declare (obsolete dolist "24.1") (indent 2)) `(let ((list-iter ,for-list)) (while list-iter (let ((,for-var (car list-iter))) diff --git a/lisp/gnus/gnus-salt.el b/lisp/gnus/gnus-salt.el index 3189655c8a..4ef2ebf1dd 100644 --- a/lisp/gnus/gnus-salt.el +++ b/lisp/gnus/gnus-salt.el @@ -133,9 +133,7 @@ It accepts the same format specs that `gnus-summary-line-format' does." (defun gnus-pick-start-reading (&optional catch-up) "Start reading the picked articles. If given a prefix, mark all unpicked articles as read." - (interactive "P") - (declare (completion (lambda (s b) - (completion-minor-mode-active-p s b 'gnus-pick-mode)))) + (interactive "P" gnus-pick-mode) (if gnus-newsgroup-processable (progn (gnus-summary-limit-to-articles nil) diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 18b12ee7b3..6eff0b9b0e 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1372,8 +1372,8 @@ it is displayed along with the global value." (put 'help-fns-edit-variable 'disabled t) (defun help-fns-edit-variable () "Edit the variable under point." - (interactive) (declare (completion ignore)) + (interactive) (let ((var (get-text-property (point) 'help-fns--edit-variable))) (unless var (error "No variable under point")) diff --git a/lisp/image-mode.el b/lisp/image-mode.el index ea5d7ff0f3..684f2ff3fc 100644 --- a/lisp/image-mode.el +++ b/lisp/image-mode.el @@ -1559,8 +1559,8 @@ return value is suitable for appending to an image spec." (defun image-transform-fit-to-height () "Fit the current image to the height of the current window." - (interactive) (declare (obsolete nil "29.1")) + (interactive) (setq image-transform-resize 'fit-height) (image-toggle-display-image)) diff --git a/lisp/progmodes/opascal.el b/lisp/progmodes/opascal.el index 4ab9b4a996..63399adf3a 100644 --- a/lisp/progmodes/opascal.el +++ b/lisp/progmodes/opascal.el @@ -1641,10 +1641,10 @@ An error is raised if not in a comment." (defun opascal-new-comment-line () "If in a // comment, do a newline, indented such that one is still in the comment block. If not in a // comment, just does a normal newline." - (interactive) (declare (obsolete "use comment-indent-new-line with comment-multi-line instead" "27.1")) + (interactive) (let ((comment (opascal-current-token))) (if (not (eq 'comment-single-line (opascal-token-kind comment))) ;; Not in a // comment. Just do the normal newline. commit da8fed0be06dc1ba936bfaa427f0890c881f133a Author: Lars Ingebrigtsen Date: Fri Jun 17 18:12:57 2022 +0200 Regenerate ldefs-boot.el diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index 353d539b59..06e2e9027c 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -1557,7 +1557,7 @@ value of `generated-autoload-file'. If any Lisp file binds autoloads into the specified file instead. (fn &rest DIRS)" t nil) -(make-obsolete 'update-directory-autoloads 'make-directory-autoloads '"28.1") +(make-obsolete 'update-directory-autoloads 'make-directory-autoloads "28.1") (autoload 'make-directory-autoloads "autoload" "\ Update autoload definitions for Lisp files in the directories DIRS. DIR can be either a single directory or a list of @@ -2509,7 +2509,7 @@ When called non-interactively, optional second argument NEW-WINDOW is used instead of `browse-url-new-window-flag'. (fn URL &optional NEW-WINDOW)" t nil) -(make-obsolete 'browse-url-gnome-moz 'nil '"25.1") +(make-obsolete 'browse-url-gnome-moz 'nil "25.1") (autoload 'browse-url-conkeror "browse-url" "\ Ask the Conkeror WWW browser to load URL. Default to the URL around or before point. Also pass the strings @@ -2529,7 +2529,7 @@ When called non-interactively, use optional second argument NEW-WINDOW instead of `browse-url-new-window-flag'. (fn URL &optional NEW-WINDOW)" t nil) -(make-obsolete 'browse-url-conkeror 'nil '"28.1") +(make-obsolete 'browse-url-conkeror 'nil "28.1") (autoload 'browse-url-w3 "browse-url" "\ Ask the w3 WWW browser to load URL. Default to the URL around or before point. @@ -2548,7 +2548,7 @@ The `browse-url-gnudoit-program' program is used with options given by `browse-url-gnudoit-args'. Default to the URL around or before point. (fn URL &optional NEW-WINDOW)" t nil) -(make-obsolete 'browse-url-w3-gnudoit 'nil '"25.1") +(make-obsolete 'browse-url-w3-gnudoit 'nil "25.1") (autoload 'browse-url-text-xterm "browse-url" "\ Ask a text browser to load URL. URL defaults to the URL around or before point. @@ -9204,7 +9204,7 @@ an elided material again. This is suitable as an entry on `find-file-hook' or appropriate mode hooks. (fn &optional ARG)" t nil) -(make-obsolete 'elide-head 'elide-head-mode '"29.1") +(make-obsolete 'elide-head 'elide-head-mode "29.1") (register-definition-prefixes "elide-head" '("elide-head-")) @@ -9862,7 +9862,7 @@ version requirement is met. (fn PROTOCOL &optional NO-CACHE PROGRAM-ALIST)" nil nil) (autoload 'epg-configuration "epg-config" "\ Return a list of internal configuration parameters of `epg-gpg-program'." nil nil) -(make-obsolete 'epg-configuration 'epg-find-configuration '"25.1") +(make-obsolete 'epg-configuration 'epg-find-configuration "25.1") (autoload 'epg-check-configuration "epg-config" "\ Verify that a sufficient version of GnuPG is installed. CONFIG should be a `epg-configuration' object (a plist). @@ -10436,7 +10436,7 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. (fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) -(make-obsolete 'find-tag 'xref-find-definitions '"25.1") +(make-obsolete 'find-tag 'xref-find-definitions "25.1") (autoload 'find-tag-other-window "etags" "\ Find tag (in current tags table) whose name contains TAGNAME. Select the buffer containing the tag's definition in another window, and @@ -10458,7 +10458,7 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. (fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) -(make-obsolete 'find-tag-other-window 'xref-find-definitions-other-window '"25.1") +(make-obsolete 'find-tag-other-window 'xref-find-definitions-other-window "25.1") (autoload 'find-tag-other-frame "etags" "\ Find tag (in current tags table) whose name contains TAGNAME. Select the buffer containing the tag's definition in another frame, and @@ -10480,7 +10480,7 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. (fn TAGNAME &optional NEXT-P)" t nil) -(make-obsolete 'find-tag-other-frame 'xref-find-definitions-other-frame '"25.1") +(make-obsolete 'find-tag-other-frame 'xref-find-definitions-other-frame "25.1") (autoload 'find-tag-regexp "etags" "\ Find tag (in current tags table) whose name matches REGEXP. Select the buffer containing the tag's definition and move point there. @@ -10500,7 +10500,7 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. (fn REGEXP &optional NEXT-P OTHER-WINDOW)" t nil) -(make-obsolete 'find-tag-regexp 'xref-find-apropos '"25.1") +(make-obsolete 'find-tag-regexp 'xref-find-apropos "25.1") (defalias 'pop-tag-mark 'xref-go-back) (defalias 'next-file 'tags-next-file) (autoload 'tags-next-file "etags" "\ @@ -10523,7 +10523,7 @@ Used noninteractively with non-nil argument to begin such a command (the argument is passed to `next-file', which see). (fn &optional FIRST-TIME)" t nil) -(make-obsolete 'tags-loop-continue 'fileloop-continue '"27.1") +(make-obsolete 'tags-loop-continue 'fileloop-continue "27.1") (autoload 'tags-search "etags" "\ Search through all files listed in tags table for match for REGEXP. Stops when a match is found. @@ -10563,7 +10563,7 @@ buffer. Display list of all tags in tags table REGEXP matches. (fn REGEXP)" t nil) -(make-obsolete 'tags-apropos 'xref-find-apropos '"25.1") +(make-obsolete 'tags-apropos 'xref-find-apropos "25.1") (autoload 'select-tags-table "etags" "\ Select a tags table file from a menu of those you have already used. The list of tags tables to select from is stored in `tags-table-set-list'; @@ -13028,7 +13028,7 @@ regular expression that can be used as an element of `font-lock-keywords'. (fn KEYWORD-LIST FACE &optional PREFIX SUFFIX)" nil nil) -(make-obsolete 'generic-make-keywords-list 'regexp-opt '"24.4") +(make-obsolete 'generic-make-keywords-list 'regexp-opt "24.4") (register-definition-prefixes "generic" '("generic-")) @@ -13758,7 +13758,7 @@ Both lists have to be sorted over <. (fn LIST1 LIST2)" nil nil) -(make-obsolete 'gnus-intersection 'seq-intersection '"28.1") +(make-obsolete 'gnus-intersection 'seq-intersection "28.1") (autoload 'gnus-sorted-intersection "gnus-range" "\ Return intersection of LIST1 and LIST2. LIST1 and LIST2 have to be sorted over <. @@ -14809,10 +14809,10 @@ Commands: (fn)" t nil) (autoload 'help-mode-setup "help-mode" "\ Enter Help mode in the current buffer." nil nil) -(make-obsolete 'help-mode-setup 'nil '"29.1") +(make-obsolete 'help-mode-setup 'nil "29.1") (autoload 'help-mode-finish "help-mode" "\ Finalize Help mode setup in current buffer." nil nil) -(make-obsolete 'help-mode-finish 'nil '"29.1") +(make-obsolete 'help-mode-finish 'nil "29.1") (autoload 'help-setup-xref "help-mode" "\ Invoked from commands using the \"*Help*\" buffer to install some xref info. @@ -16566,7 +16566,7 @@ Value is a symbol specifying the image type, or nil if type cannot be determined. (fn FILE)" nil nil) -(make-obsolete 'image-type-from-file-name 'image-supported-file-p '"29.1") +(make-obsolete 'image-type-from-file-name 'image-supported-file-p "29.1") (autoload 'image-type "image" "\ Determine and return image type. SOURCE is an image file name or image data. @@ -18217,7 +18217,7 @@ KEYS should be a vector or a string that obeys `key-valid-p'. (fn MAC &optional COUNTER FORMAT)" nil nil) -(make-obsolete 'kmacro-lambda-form 'kmacro '"29.1") +(make-obsolete 'kmacro-lambda-form 'kmacro "29.1") (register-definition-prefixes "kmacro" '("kmacro-")) @@ -19075,7 +19075,7 @@ Completable headers are according to `mail-complete-alist'. If none matches current header, calls `mail-complete-function' and passes prefix ARG if any. (fn ARG)" t nil) -(make-obsolete 'mail-complete 'mail-completion-at-point-function '"24.1") +(make-obsolete 'mail-complete 'mail-completion-at-point-function "24.1") (register-definition-prefixes "mailalias" '("build-mail-aliases" "mail-")) @@ -23121,7 +23121,7 @@ To use this function, just bind the TAB key to it, or add it to your completion functions list (it should occur fairly early in the list). (fn &optional INTERACTIVELY)" t nil) -(make-obsolete 'pcomplete '"use completion-at-point and pcomplete-completions-at-point" '"27.1") +(make-obsolete 'pcomplete '"use completion-at-point and pcomplete-completions-at-point" "27.1") (autoload 'pcomplete-reverse "pcomplete" "\ If cycling completion is in use, cycle backwards." t nil) (autoload 'pcomplete-expand-and-complete "pcomplete" "\ @@ -23134,7 +23134,7 @@ Expand the textual value of the current argument. This will modify the current buffer." t nil) (autoload 'pcomplete-help "pcomplete" "\ Display any help information relative to the current argument." t nil) -(make-obsolete 'pcomplete-help '"use completion-help-at-point and pcomplete-completions-at-point" '"27.1") +(make-obsolete 'pcomplete-help '"use completion-help-at-point and pcomplete-completions-at-point" "27.1") (autoload 'pcomplete-list "pcomplete" "\ Show the list of possible completions for the current argument." t nil) (autoload 'pcomplete-comint-setup "pcomplete" "\ @@ -33201,7 +33201,7 @@ By default, this command cycles through the registered backends. To get a prompt, use a prefix argument. (fn FILE BACKEND)" t nil) -(make-obsolete 'vc-switch-backend 'nil '"28.1") +(make-obsolete 'vc-switch-backend 'nil "28.1") (autoload 'vc-transfer-file "vc" "\ Transfer FILE to another version control system NEW-BACKEND. If NEW-BACKEND has a higher precedence than FILE's current backend @@ -34456,7 +34456,7 @@ entry for the selected window, purge that entry from `view-return-to-alist' before adding ITEM. (fn BUFFER &optional ITEM)" nil nil) -(make-obsolete 'view-return-to-alist-update '"this function has no effect." '"24.1") +(make-obsolete 'view-return-to-alist-update '"this function has no effect." "24.1") (autoload 'view-mode-enter "view" "\ Enter View mode and set up exit from view mode depending on optional arguments. Optional argument QUIT-RESTORE if non-nil must specify a valid commit a53c34d76a09cd6519d2d176b76d4b820bc26a51 Author: Lars Ingebrigtsen Date: Fri Jun 17 18:12:38 2022 +0200 Don't quote the `when' form in obsoletions * lisp/emacs-lisp/byte-run.el (byte-run--set-obsolete): The `when' is a string (or nil), so don't quote it (bug#48145). * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--print-form): Adjust folding. diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el index 17c1554966..498435c58d 100644 --- a/lisp/emacs-lisp/byte-run.el +++ b/lisp/emacs-lisp/byte-run.el @@ -166,7 +166,7 @@ The return value of this function is not used." (defalias 'byte-run--set-obsolete #'(lambda (f _args new-name when) (list 'make-obsolete - (list 'quote f) (list 'quote new-name) (list 'quote when)))) + (list 'quote f) (list 'quote new-name) when))) (defalias 'byte-run--set-interactive-only #'(lambda (f _args instead) diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index 86c776e301..a686de406a 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -633,6 +633,7 @@ If GENERATE-FULL, don't update, but regenerate all the loaddefs files." "Print DEF in the way make-docfile.c expects it." (if (or (not (consp def)) (not (symbolp (car def))) + (eq (car def) 'make-obsolete) (not (stringp (nth 3 def)))) (prin1 def (current-buffer) t) ;; The salient point here is that we have to have the doc string commit 73e75e18d170826e1838324d39ac0698948071f8 Author: Mattias Engdegård Date: Fri Jun 17 17:06:05 2022 +0200 Warn about misplaced or duplicated function/macro declarations Doc strings, `declare` and `interactive` forms must appear in that order and at most once each. Complain if they don't, instead of silently ignoring the problem (bug#55905). * lisp/emacs-lisp/byte-run.el (byte-run--parse-body) (byte-run--parse-declarations): New. (defmacro, defun): Check for declaration well-formedness as described above. Clarify doc strings. Refactor some common code. * test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el: * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-fun-attr-warn): New test. diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el index 92c2699c6e..17c1554966 100644 --- a/lisp/emacs-lisp/byte-run.el +++ b/lisp/emacs-lisp/byte-run.el @@ -272,6 +272,75 @@ This is used by `declare'.") (list 'function-put (list 'quote name) ''no-font-lock-keyword (list 'quote val)))) +(defalias 'byte-run--parse-body + #'(lambda (body allow-interactive) + "Decompose BODY into (DOCSTRING DECLARE INTERACTIVE BODY-REST WARNINGS)." + (let* ((top body) + (docstring nil) + (declare-form nil) + (interactive-form nil) + (warnings nil) + (warn #'(lambda (msg form) + (push (macroexp-warn-and-return msg nil nil t form) + warnings)))) + (while + (and body + (let* ((form (car body)) + (head (car-safe form))) + (cond + ((or (and (stringp form) (cdr body)) + (eq head :documentation)) + (cond + (docstring (funcall warn "More than one doc string" top)) + (declare-form + (funcall warn "Doc string after `declare'" declare-form)) + (interactive-form + (funcall warn "Doc string after `interactive'" + interactive-form)) + (t (setq docstring form))) + t) + ((eq head 'declare) + (cond + (declare-form + (funcall warn "More than one `declare' form" form)) + (interactive-form + (funcall warn "`declare' after `interactive'" form)) + (t (setq declare-form form))) + t) + ((eq head 'interactive) + (cond + ((not allow-interactive) + (funcall warn "No `interactive' form allowed here" form)) + (interactive-form + (funcall warn "More than one `interactive' form" form)) + (t (setq interactive-form form))) + t)))) + (setq body (cdr body))) + (list docstring declare-form interactive-form body warnings)))) + +(defalias 'byte-run--parse-declarations + #'(lambda (name arglist clauses construct declarations-alist) + (let* ((cl-decls nil) + (actions + (mapcar + #'(lambda (x) + (let ((f (cdr (assq (car x) declarations-alist)))) + (cond + (f (apply (car f) name arglist (cdr x))) + ;; Yuck!! + ((and (featurep 'cl) + (memq (car x) ;C.f. cl--do-proclaim. + '(special inline notinline optimize warn))) + (push (list 'declare x) cl-decls) + nil) + (t + (macroexp-warn-and-return + (format-message "Unknown %s property `%S'" + construct (car x)) + nil nil nil (car x)))))) + clauses))) + (cons actions cl-decls)))) + (defvar macro-declarations-alist (cons (list 'debug #'byte-run--set-debug) @@ -289,7 +358,7 @@ This is used by `declare'.") (defalias 'defmacro (cons 'macro - #'(lambda (name arglist &optional docstring &rest body) + #'(lambda (name arglist &rest body) "Define NAME as a macro. When the macro is called, as in (NAME ARGS...), the function (lambda ARGLIST BODY...) is applied to @@ -300,116 +369,73 @@ DECLS is a list of elements of the form (PROP . VALUES). These are interpreted according to `macro-declarations-alist'. The return value is undefined. -\(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)" - ;; We can't just have `decl' as an &optional argument, because we need - ;; to distinguish - ;; (defmacro foo (arg) (bar) nil) - ;; from - ;; (defmacro foo (arg) (bar)). - (let ((decls (cond - ((eq (car-safe docstring) 'declare) - (prog1 (cdr docstring) (setq docstring nil))) - ((and (stringp docstring) - (eq (car-safe (car body)) 'declare)) - (prog1 (cdr (car body)) (setq body (cdr body))))))) - (if docstring (setq body (cons docstring body)) - (if (null body) (setq body '(nil)))) - ;; Can't use backquote because it's not defined yet! - (let* ((fun (list 'function (cons 'lambda (cons arglist body)))) - (def (list 'defalias - (list 'quote name) - (list 'cons ''macro fun))) - (declarations - (mapcar - #'(lambda (x) - (let ((f (cdr (assq (car x) macro-declarations-alist)))) - (if f (apply (car f) name arglist (cdr x)) - (macroexp-warn-and-return - (format-message - "Unknown macro property %S in %S" - (car x) name) - nil nil nil (car x))))) - decls))) - ;; Refresh font-lock if this is a new macro, or it is an - ;; existing macro whose 'no-font-lock-keyword declaration - ;; has changed. - (if (and - ;; If lisp-mode hasn't been loaded, there's no reason - ;; to flush. - (fboundp 'lisp--el-font-lock-flush-elisp-buffers) - (or (not (fboundp name)) ;; new macro - (and (fboundp name) ;; existing macro - (member `(function-put ',name 'no-font-lock-keyword - ',(get name 'no-font-lock-keyword)) - declarations)))) - (lisp--el-font-lock-flush-elisp-buffers)) - (if declarations - (cons 'prog1 (cons def declarations)) +\(fn NAME ARGLIST [DOCSTRING] [DECL] BODY...)" + (let* ((parse (byte-run--parse-body body nil)) + (docstring (nth 0 parse)) + (declare-form (nth 1 parse)) + (body (nth 3 parse)) + (warnings (nth 4 parse)) + (declarations + (and declare-form (byte-run--parse-declarations + name arglist (cdr declare-form) 'macro + macro-declarations-alist)))) + (setq body (nconc warnings body)) + (setq body (nconc (cdr declarations) body)) + (if docstring + (setq body (cons docstring body))) + (if (null body) + (setq body '(nil))) + (let* ((fun (list 'function (cons 'lambda (cons arglist body)))) + (def (list 'defalias + (list 'quote name) + (list 'cons ''macro fun)))) + (if declarations + (cons 'prog1 (cons def (car declarations))) def)))))) ;; Now that we defined defmacro we can use it! -(defmacro defun (name arglist &optional docstring &rest body) +(defmacro defun (name arglist &rest body) "Define NAME as a function. -The definition is (lambda ARGLIST [DOCSTRING] BODY...). -See also the function `interactive'. +The definition is (lambda ARGLIST [DOCSTRING] [INTERACTIVE] BODY...). DECL is a declaration, optional, of the form (declare DECLS...) where DECLS is a list of elements of the form (PROP . VALUES). These are interpreted according to `defun-declarations-alist'. +INTERACTIVE is an optional `interactive' specification. The return value is undefined. -\(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)" - ;; We can't just have `decl' as an &optional argument, because we need - ;; to distinguish - ;; (defun foo (arg) (toto) nil) - ;; from - ;; (defun foo (arg) (toto)). +\(fn NAME ARGLIST [DOCSTRING] [DECL] [INTERACTIVE] BODY...)" (declare (doc-string 3) (indent 2)) (or name (error "Cannot define '%s' as a function" name)) (if (null (and (listp arglist) (null (delq t (mapcar #'symbolp arglist))))) (error "Malformed arglist: %s" arglist)) - (let ((decls (cond - ((eq (car-safe docstring) 'declare) - (prog1 (cdr docstring) (setq docstring nil))) - ((and (stringp docstring) - (eq (car-safe (car body)) 'declare)) - (prog1 (cdr (car body)) (setq body (cdr body))))))) - (if docstring (setq body (cons docstring body)) - (if (null body) (setq body '(nil)))) - (let ((declarations - (mapcar - #'(lambda (x) - (let ((f (cdr (assq (car x) defun-declarations-alist)))) - (cond - (f (apply (car f) name arglist (cdr x))) - ;; Yuck!! - ((and (featurep 'cl) - (memq (car x) ;C.f. cl-do-proclaim. - '(special inline notinline optimize warn))) - (push (list 'declare x) - (if (stringp docstring) - (if (eq (car-safe (cadr body)) 'interactive) - (cddr body) - (cdr body)) - (if (eq (car-safe (car body)) 'interactive) - (cdr body) - body))) - nil) - (t - (macroexp-warn-and-return - (format-message "Unknown defun property `%S' in %S" - (car x) name) - nil nil nil (car x)))))) - decls)) - (def (list 'defalias + (let* ((parse (byte-run--parse-body body t)) + (docstring (nth 0 parse)) + (declare-form (nth 1 parse)) + (interactive-form (nth 2 parse)) + (body (nth 3 parse)) + (warnings (nth 4 parse)) + (declarations + (and declare-form (byte-run--parse-declarations + name arglist (cdr declare-form) 'defun + defun-declarations-alist)))) + (setq body (nconc warnings body)) + (setq body (nconc (cdr declarations) body)) + (if interactive-form + (setq body (cons interactive-form body))) + (if docstring + (setq body (cons docstring body))) + (if (null body) + (setq body '(nil))) + (let ((def (list 'defalias (list 'quote name) (list 'function (cons 'lambda (cons arglist body)))))) (if declarations - (cons 'prog1 (cons def declarations)) - def)))) + (cons 'prog1 (cons def (car declarations))) + def)))) ;; Redefined in byte-opt.el. diff --git a/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el b/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el new file mode 100644 index 0000000000..be907b32f4 --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/fun-attr-warn.el @@ -0,0 +1,266 @@ +;;; -*- lexical-binding: t -*- + +;; Correct + +(defun faw-str-decl-code (x) + "something" + (declare (pure t)) + (print x)) + +(defun faw-doc-decl-code (x) + (:documentation "something") + (declare (pure t)) + (print x)) + +(defun faw-str-int-code (x) + "something" + (interactive "P") + (print x)) + +(defun faw-doc-int-code (x) + (:documentation "something") + (interactive "P") + (print x)) + +(defun faw-decl-int-code (x) + (declare (pure t)) + (interactive "P") + (print x)) + +(defun faw-str-decl-int-code (x) + "something" + (declare (pure t)) + (interactive "P") + (print x)) + +(defun faw-doc-decl-int-code (x) + (:documentation "something") + (declare (pure t)) + (interactive "P") + (print x)) + + +;; Correct (last string is return value) + +(defun faw-str () + "something") + +(defun faw-decl-str () + (declare (pure t)) + "something") + +(defun faw-decl-int-str () + (declare (pure t)) + (interactive) + "something") + +(defun faw-str-str () + "something" + "something else") + +(defun faw-doc-str () + (:documentation "something") + "something else") + + +;; Incorrect (bad order) + +(defun faw-int-decl-code (x) + (interactive "P") + (declare (pure t)) + (print x)) + +(defun faw-int-str-code (x) + (interactive "P") + "something" + (print x)) + +(defun faw-int-doc-code (x) + (interactive "P") + (:documentation "something") + (print x)) + +(defun faw-decl-str-code (x) + (declare (pure t)) + "something" + (print x)) + +(defun faw-decl-doc-code (x) + (declare (pure t)) + (:documentation "something") + (print x)) + +(defun faw-str-int-decl-code (x) + "something" + (interactive "P") + (declare (pure t)) + (print x)) + +(defun faw-doc-int-decl-code (x) + (:documentation "something") + (interactive "P") + (declare (pure t)) + (print x)) + +(defun faw-int-str-decl-code (x) + (interactive "P") + "something" + (declare (pure t)) + (print x)) + +(defun faw-int-doc-decl-code (x) + (interactive "P") + (:documentation "something") + (declare (pure t)) + (print x)) + +(defun faw-int-decl-str-code (x) + (interactive "P") + (declare (pure t)) + "something" + (print x)) + +(defun faw-int-decl-doc-code (x) + (interactive "P") + (declare (pure t)) + (:documentation "something") + (print x)) + +(defun faw-decl-int-str-code (x) + (declare (pure t)) + (interactive "P") + "something" + (print x)) + +(defun faw-decl-int-doc-code (x) + (declare (pure t)) + (interactive "P") + (:documentation "something") + (print x)) + +(defun faw-decl-str-int-code (x) + (declare (pure t)) + "something" + (interactive "P") + (print x)) + +(defun faw-decl-doc-int-code (x) + (declare (pure t)) + (:documentation "something") + (interactive "P") + (print x)) + + +;; Incorrect (duplication) + +(defun faw-str-str-decl-int-code (x) + "something" + "something else" + (declare (pure t)) + (interactive "P") + (print x)) + +(defun faw-str-doc-decl-int-code (x) + "something" + (:documentation "something else") + (declare (pure t)) + (interactive "P") + (print x)) + +(defun faw-doc-str-decl-int-code (x) + (:documentation "something") + "something else" + (declare (pure t)) + (interactive "P") + (print x)) + +(defun faw-doc-doc-decl-int-code (x) + (:documentation "something") + (:documentation "something else") + (declare (pure t)) + (interactive "P") + (print x)) + +(defun faw-str-decl-str-int-code (x) + "something" + (declare (pure t)) + "something else" + (interactive "P") + (print x)) + +(defun faw-doc-decl-str-int-code (x) + (:documentation "something") + (declare (pure t)) + "something else" + (interactive "P") + (print x)) + +(defun faw-str-decl-doc-int-code (x) + "something" + (declare (pure t)) + (:documentation "something else") + (interactive "P") + (print x)) + +(defun faw-doc-decl-doc-int-code (x) + (:documentation "something") + (declare (pure t)) + (:documentation "something else") + (interactive "P") + (print x)) + +(defun faw-str-decl-decl-int-code (x) + "something" + (declare (pure t)) + (declare (indent 1)) + (interactive "P") + (print x)) + +(defun faw-doc-decl-decl-int-code (x) + (:documentation "something") + (declare (pure t)) + (declare (indent 1)) + (interactive "P") + (print x)) + +(defun faw-str-decl-int-decl-code (x) + "something" + (declare (pure t)) + (interactive "P") + (declare (indent 1)) + (print x)) + +(defun faw-doc-decl-int-decl-code (x) + (:documentation "something") + (declare (pure t)) + (interactive "P") + (declare (indent 1)) + (print x)) + +(defun faw-str-decl-int-int-code (x) + "something" + (declare (pure t)) + (interactive "P") + (interactive "p") + (print x)) + +(defun faw-doc-decl-int-int-code (x) + (:documentation "something") + (declare (pure t)) + (interactive "P") + (interactive "p") + (print x)) + +(defun faw-str-int-decl-int-code (x) + "something" + (interactive "P") + (declare (pure t)) + (interactive "p") + (print x)) + +(defun faw-doc-int-decl-int-code (x) + (:documentation "something") + (interactive "P") + (declare (pure t)) + (interactive "p") + (print x)) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 9abc17a1c4..fbc00b30c5 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -1580,6 +1580,69 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \ (should (equal (get fname 'lisp-indent-function) 1)) (should (equal (aref bc 4) "tata\n\n(fn X)"))))) +(ert-deftest bytecomp-fun-attr-warn () + ;; Check that warnings are emitted when doc strings, `declare' and + ;; `interactive' forms don't come in the proper order, or more than once. + (let* ((filename "fun-attr-warn.el") + (el (ert-resource-file filename)) + (elc (concat el "c")) + (text-quoting-style 'grave)) + (with-current-buffer (get-buffer-create "*Compile-Log*") + (let ((inhibit-read-only t)) + (erase-buffer)) + (byte-compile-file el) + (let ((expected + '("70:4: Warning: `declare' after `interactive'" + "74:4: Warning: Doc string after `interactive'" + "79:4: Warning: Doc string after `interactive'" + "84:4: Warning: Doc string after `declare'" + "89:4: Warning: Doc string after `declare'" + "96:4: Warning: `declare' after `interactive'" + "102:4: Warning: `declare' after `interactive'" + "108:4: Warning: `declare' after `interactive'" + "106:4: Warning: Doc string after `interactive'" + "114:4: Warning: `declare' after `interactive'" + "112:4: Warning: Doc string after `interactive'" + "118:4: Warning: Doc string after `interactive'" + "119:4: Warning: `declare' after `interactive'" + "124:4: Warning: Doc string after `interactive'" + "125:4: Warning: `declare' after `interactive'" + "130:4: Warning: Doc string after `declare'" + "136:4: Warning: Doc string after `declare'" + "142:4: Warning: Doc string after `declare'" + "148:4: Warning: Doc string after `declare'" + "159:4: Warning: More than one doc string" + "165:4: Warning: More than one doc string" + "171:4: Warning: More than one doc string" + "178:4: Warning: More than one doc string" + "186:4: Warning: More than one doc string" + "192:4: Warning: More than one doc string" + "200:4: Warning: More than one doc string" + "206:4: Warning: More than one doc string" + "215:4: Warning: More than one `declare' form" + "222:4: Warning: More than one `declare' form" + "230:4: Warning: More than one `declare' form" + "237:4: Warning: More than one `declare' form" + "244:4: Warning: More than one `interactive' form" + "251:4: Warning: More than one `interactive' form" + "258:4: Warning: More than one `interactive' form" + "257:4: Warning: `declare' after `interactive'" + "265:4: Warning: More than one `interactive' form" + "264:4: Warning: `declare' after `interactive'"))) + (goto-char (point-min)) + (let ((actual nil)) + (while (re-search-forward + (rx bol (* (not ":")) ":" + (group (+ digit) ":" (+ digit) ": Warning: " + (or "More than one " (+ nonl) " form" + (: (+ nonl) " after " (+ nonl)))) + eol) + nil t) + (push (match-string 1) actual)) + (setq actual (nreverse actual)) + (should (equal actual expected))))))) + + ;; Local Variables: ;; no-byte-compile: t ;; End: commit 94672c2936dd58a1837fd208f8678074ca8193c3 Author: Eli Zaretskii Date: Fri Jun 17 18:24:33 2022 +0300 Handle too long syntactic fontifications * src/syntax.c (scan_sexps_forward): Call 'update_redisplay_ticks' after finishing the loop. * src/dispnew.c (make_current): Make sure enabled rows of the current matrix have a valid hash, even if redisplay of a window was aborted due to slowness. This avoids assertion violations in 'scrolling_window' due to the wrong hash value. diff --git a/src/dispnew.c b/src/dispnew.c index 7a4d9f8710..9d587ea00e 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -2738,6 +2738,14 @@ make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_ struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row); bool mouse_face_p = current_row->mouse_face_p; + /* If we aborted redisplay of this window, a row in the desired + matrix might not have its hash computed. */ + if (!(!desired_row->used[0] + && !desired_row->used[1] + && !desired_row->used[2]) + && !desired_row->hash) + desired_row->hash = row_hash (desired_row); + /* Do current_row = desired_row. This exchanges glyph pointers between both rows, and does a structure assignment otherwise. */ assign_row (current_row, desired_row); diff --git a/src/syntax.c b/src/syntax.c index f9022d18d2..de9193e2de 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -20,6 +20,7 @@ along with GNU Emacs. If not, see . */ #include #include "lisp.h" +#include "dispextern.h" #include "character.h" #include "buffer.h" #include "regex-emacs.h" @@ -3195,6 +3196,7 @@ scan_sexps_forward (struct lisp_parse_state *state, ptrdiff_t out_bytepos, out_charpos; int temp; unsigned short int quit_count = 0; + ptrdiff_t started_from = from; prev_from = from; prev_from_byte = from_byte; @@ -3474,6 +3476,12 @@ do { prev_from = from; \ state->levelstarts); state->prev_syntax = (SYNTAX_FLAGS_COMSTARTEND_FIRST (prev_from_syntax) || state->quoted) ? prev_from_syntax : Smax; + + /* The factor of 10 below is a heuristic that needs to be tuned. It + means we consider 10 buffer positions examined by this function + roughly equivalent to the display engine iterating over a single + buffer position. */ + update_redisplay_ticks ((from - started_from) / 10 + 1, NULL); } /* Convert a (lisp) parse state to the internal form used in commit e9c50055ff989a670d024045aba0050371a28fef Author: Lars Ingebrigtsen Date: Fri Jun 17 16:59:18 2022 +0200 Fix efaq-w32.texi build warning * doc/misc/efaq-w32.texi (Other useful ports): Fix ordering to match nodes (or should the nodes be moved instead?). diff --git a/doc/misc/efaq-w32.texi b/doc/misc/efaq-w32.texi index 0193279212..084b5a3254 100644 --- a/doc/misc/efaq-w32.texi +++ b/doc/misc/efaq-w32.texi @@ -2102,9 +2102,9 @@ suggestions} for improving the interaction of perldb and Emacs. @menu * Cygwin:: -* MinGW:: -* EZWinPorts:: * MinGW-w64:: +* EZWinPorts:: +* MinGW:: * GnuWin32:: * GTK:: * Read man pages:: commit bdb1c5ec458692b26281654f153729156e5c0ae8 Author: Lars Ingebrigtsen Date: Fri Jun 17 16:50:42 2022 +0200 Regenerated ldefs-boot.el diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index f4e9d2732f..353d539b59 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -1348,25 +1348,25 @@ Variables This is a brief overview of the different variables. For more info, see the documentation for the variables (type \\[describe-variable] RET). - artist-rubber-banding Interactively do rubber-banding or not - artist-first-char What to set at first/second point... - artist-second-char ...when not rubber-banding - artist-interface-with-rect If cut/copy/paste should interface with rect - artist-arrows The arrows to use when drawing arrows - artist-aspect-ratio Character height-to-width for squares - artist-trim-line-endings Trimming of line endings - artist-flood-fill-right-border Right border when flood-filling - artist-flood-fill-show-incrementally Update display while filling - artist-pointer-shape Pointer shape to use while drawing - artist-ellipse-left-char Character to use for narrow ellipses - artist-ellipse-right-char Character to use for narrow ellipses - artist-borderless-shapes If shapes should have borders - artist-picture-compatibility Whether or not to be picture mode compatible - artist-vaporize-fuzziness Tolerance when recognizing lines - artist-spray-interval Seconds between repeated sprayings - artist-spray-radius Size of the spray-area - artist-spray-chars The spray-\"color\" - artist-spray-new-chars Initial spray-\"color\" + `artist-rubber-banding' Interactively do rubber-banding or not + `artist-first-char' What to set at first/second point... + `artist-second-char' ...when not rubber-banding + `artist-interface-with-rect' Should cut/copy/paste interface with rect + `artist-arrows' The arrows to use when drawing arrows + `artist-aspect-ratio' Character height-to-width for squares + `artist-trim-line-endings' Trimming of line endings + `artist-flood-fill-right-border' Right border when flood-filling + `artist-flood-fill-show-incrementally' Update display while filling + `artist-pointer-shape' Pointer shape to use while drawing + `artist-ellipse-left-char' Character to use for narrow ellipses + `artist-ellipse-right-char' Character to use for narrow ellipses + `artist-borderless-shapes' If shapes should have borders + `artist-picture-compatibility' Picture mode compatibility on or off + `artist-vaporize-fuzziness' Tolerance when recognizing lines + `artist-spray-interval' Seconds between repeated sprayings + `artist-spray-radius' Size of the spray-area + `artist-spray-chars' The spray-\"color\" + `artist-spray-new-char' Initial spray-\"color\" Hooks @@ -3951,8 +3951,7 @@ See the documentation of `define-ccl-program' for the detail of CCL program. (autoload 'cconv-closure-convert "cconv" "\ Main entry point for closure conversion. --- FORM is a piece of Elisp code after macroexpansion. --- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST +FORM is a piece of Elisp code after macroexpansion. Returns a form where all lambdas don't have any free variables. @@ -14209,6 +14208,10 @@ to specify a command to run. If CONFIRM is non-nil, the user will be given an opportunity to edit the command before it's run. +Interactively, the user can use the `M-c' command while entering +the regexp to indicate whether the grep should be case sensitive +or not. + (fn REGEXP &optional FILES DIR CONFIRM)" t nil) (autoload 'zrgrep "grep" "\ Recursively grep for REGEXP in gzipped FILES in tree rooted at DIR. @@ -18506,7 +18509,9 @@ its autoloads into the specified file instead. The function does NOT recursively descend into subdirectories of the directory or directories specified. -If EXTRA-DATA, include this string at the start of the generated file. +If EXTRA-DATA, include this string at the start of the generated +file. This will also force generation of OUTPUT-FILE even if +there are no autoloads to put into the file. If INCLUDE-PACKAGE-VERSION, include package version data. @@ -22741,6 +22746,16 @@ PKG should be either a symbol, the package name, or a `package-desc' object. (fn PKG)" t nil) +(autoload 'package-recompile "package" "\ +Byte-compile package PKG again. +PKG should be either a symbol, the package name, or a `package-desc' +object. + +(fn PKG)" t nil) +(autoload 'package-recompile-all "package" "\ +Byte-compile all installed packages. +This is meant to be used only in the case the byte-compiled files +are invalid due to changed byte-code, macros or the like." t nil) (autoload 'package-autoremove "package" "\ Remove packages that are no longer needed. @@ -32064,18 +32079,6 @@ FRAC should be the inverse of the fractional value; for example, a value of (fn WPM &optional WORDLEN FRAC)" t nil) (register-definition-prefixes "type-break" '("timep" "type-break-")) - -;;; Generated autoloads from mail/uce.el - -(autoload 'uce-reply-to-uce "uce" "\ -Compose a reply to unsolicited commercial email (UCE). -Sets up a reply buffer addressed to: the sender, his postmaster, -his abuse@ address, and the postmaster of the mail relay used. -You might need to set `uce-mail-reader' before using this. - -(fn &optional IGNORED)" t nil) -(register-definition-prefixes "uce" '("uce-")) - ;;; Generated autoloads from international/ucs-normalize.el @@ -34903,6 +34906,7 @@ Interactively, it accepts one of the following chars: r toggle trailing blanks visualization l toggle \"long lines\" visualization L toggle \"long lines\" tail visualization + C-l toggle \"long lines\" one character visualization n toggle NEWLINE visualization e toggle empty line at bob and/or eob visualization C-i toggle indentation SPACEs visualization (via `indent-tabs-mode') @@ -34933,6 +34937,7 @@ The valid symbols are: trailing toggle trailing blanks visualization lines toggle \"long lines\" visualization lines-tail toggle \"long lines\" tail visualization + lines-char toggle \"long lines\" one character visualization newline toggle NEWLINE visualization empty toggle empty line at bob and/or eob visualization indentation toggle indentation SPACEs visualization commit d671cd57c488ec792997fd4051440187dec3434f Author: Lars Ingebrigtsen Date: Fri Jun 17 16:48:02 2022 +0200 Update cl-struct-sequence-type doc string * lisp/emacs-lisp/cl-macs.el (cl-struct-sequence-type): Fix doc string to reflect what it does (bug#46523). diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index c27a43f3ba..85ebcaade7 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -3288,8 +3288,9 @@ the form NAME which is a shorthand for (NAME NAME)." (defun cl-struct-sequence-type (struct-type) "Return the sequence used to build STRUCT-TYPE. -STRUCT-TYPE is a symbol naming a struct type. Return `record', -`vector', or `list' if STRUCT-TYPE is a struct type, nil otherwise." +STRUCT-TYPE is a symbol naming a struct type. Return values are +either `vector', `list' or nil (and the latter indicates a +`record' struct type." (declare (side-effect-free t) (pure t)) (cl--struct-class-type (cl--struct-get-class struct-type))) commit 719a3c821ba1a707968dcc55f14d4957e64a96bd Author: Stefan Kangas Date: Fri Jun 17 16:29:44 2022 +0200 Fix some command substitutions * lisp/net/rcirc.el (rcirc-edit-multiline): * lisp/textmodes/reftex-index.el (reftex-index-phrases-mode) (reftex-index-phrase-selection-or-word): * lisp/textmodes/remember.el (remember): Fix command substitutions. diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index 0d30b34922..00b57ab8e7 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -1708,7 +1708,10 @@ extracted." (setq rcirc-parent-buffer parent) (insert text) (and (> pos 0) (goto-char pos)) - (message "Type C-c C-c to return text to %s, or C-c C-k to cancel" parent)))) + (message "Type %s to return text to %s, or %s to cancel" + (substitute-command-keys "\\[rcirc-multiline-minor-submit]") + parent + (substitute-command-keys "\\[rcirc-multiline-minor-cancel]"))))) (defvar rcirc-multiline-minor-mode-map (let ((map (make-sparse-keymap))) diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el index 734f82aba3..9adf0c819b 100644 --- a/lisp/textmodes/reftex-index.el +++ b/lisp/textmodes/reftex-index.el @@ -1272,10 +1272,11 @@ This gets refreshed in every phrases command.") ;;;###autoload (defun reftex-index-phrase-selection-or-word (arg) "Add current selection or word at point to the phrases buffer. +\\ When you are in transient-mark-mode and the region is active, the selection will be used - otherwise the word at point. You get a chance to edit the entry in the phrases buffer - finish with -`C-c C-c'." +\\[reftex-index-phrases-save-and-return]." (interactive "P") (set-marker reftex-index-return-marker (point)) (reftex-index-selection-or-word arg 'phrase) @@ -1373,7 +1374,7 @@ If the buffer is non-empty, delete the old header first." ;;;###autoload (define-derived-mode reftex-index-phrases-mode fundamental-mode "Phrases" "Major mode for managing the Index phrases of a LaTeX document. -This buffer was created with RefTeX. +This buffer was created with RefTeX. \\ To insert new phrases, use - `C-c \\' in the LaTeX document to copy selection or word diff --git a/lisp/textmodes/remember.el b/lisp/textmodes/remember.el index e72f86f7db..f7ebe04bcf 100644 --- a/lisp/textmodes/remember.el +++ b/lisp/textmodes/remember.el @@ -296,7 +296,8 @@ With a prefix or a visible region, use the region as INITIAL." (insert "\n\n" annotation)) (setq remember-initial-contents nil) (goto-char (point-min))) - (message "Use C-c C-c to remember the data."))) + (message (substitute-command-keys + "Use \\[remember-finalize] to remember the data")))) ;;;###autoload (defun remember-other-frame (&optional initial) commit 2237e46ba9abc96a4217afc1a0dda5f95c0c5eb9 Author: Stefan Kangas Date: Fri Jun 17 16:06:10 2022 +0200 Rename command to bookmark-edit-annotation-confirm * lisp/bookmark.el (bookmark-edit-annotation-confirm): Rename from 'bookmark-send-edited-annotation' to be more consistent with 'bookmark-edit-annotation-cancel'. Make the old name into an obsolete function alias. diff --git a/lisp/bookmark.el b/lisp/bookmark.el index fdaea381ab..126c25966c 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -1029,7 +1029,7 @@ annotations." "# All lines which start with a `#' will be deleted.\n") (substitute-command-keys (concat - "# Type \\[bookmark-send-edited-annotation] when done. Type " + "# Type \\[bookmark-edit-annotation-confirm] when done. Type " "\\[bookmark-edit-annotation-cancel] to cancel.\n#\n")) "# Author: " (user-full-name) " <" (user-login-name) "@" (system-name) ">\n" @@ -1043,7 +1043,7 @@ It takes one argument, the name of the bookmark, as a string.") (defvar-keymap bookmark-edit-annotation-mode-map :doc "Keymap for editing an annotation of a bookmark." :parent text-mode-map - "C-c C-c" #'bookmark-send-edited-annotation + "C-c C-c" #'bookmark-edit-annotation-confirm "C-c C-k" #'bookmark-edit-annotation-cancel) (defun bookmark-insert-annotation (bookmark-name-or-record) @@ -1059,7 +1059,7 @@ It takes one argument, the name of the bookmark, as a string.") text-mode "Edit Bookmark Annotation" "Mode for editing the annotation of bookmarks. \\\ -When you have finished composing, type \\[bookmark-send-edited-annotation] \ +When you have finished composing, type \\[bookmark-edit-annotation-confirm] \ or \\[bookmark-edit-annotation-cancel] to cancel. \\{bookmark-edit-annotation-mode-map}") @@ -1083,7 +1083,7 @@ or \\[bookmark-edit-annotation-cancel] to cancel. (bookmark-edit-annotation--maybe-display-list (message "Canceled by user"))) -(defun bookmark-send-edited-annotation () +(defun bookmark-edit-annotation-confirm () "Use buffer contents as annotation for a bookmark. Lines beginning with `#' are ignored." (interactive nil bookmark-edit-annotation-mode) @@ -2571,6 +2571,12 @@ This also runs `bookmark-exit-hook'." (run-hooks 'bookmark-load-hook) + +;;; Obsolete: + +(define-obsolete-function-alias 'bookmark-send-edited-annotation + #'bookmark-edit-annotation-confirm "29.1") + (provide 'bookmark) ;;; bookmark.el ends here commit 250f9e7f8380e208d8ef32dd4d64218b41abbddf Author: Stefan Kangas Date: Fri Jun 17 16:03:52 2022 +0200 Improve help-enable-variable-value-editing help * lisp/help-fns.el (help-enable-variable-value-editing): Expand docstring to better explain what effect it has. (help-fns-edit-variable): Use command substitution. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index ca5750723f..18b12ee7b3 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -135,6 +135,11 @@ with the current prefix. The files are chosen according to (defcustom help-enable-variable-value-editing nil "If non-nil, allow editing values in *Help* buffers. + +To edit the value of a variable, use \\[describe-variable] to +display a \"*Help*\" buffer, move point after the text +\"Its value is\" and type \\`e'. + Values that aren't readable by the Emacs Lisp reader can't be edited even if this option is enabled." :type 'boolean @@ -1376,9 +1381,10 @@ it is displayed along with the global value." (prin1 (nth 1 var) (current-buffer)) (pp-buffer) (goto-char (point-min)) - (insert (format ";; Edit the `%s' variable.\n" (nth 0 var)) - ";; C-c C-c to update the value and exit.\n\n") (help-fns--edit-value-mode) + (insert (format ";; Edit the `%s' variable.\n" (nth 0 var)) + (substitute-command-keys + ";; \\[help-fns-edit-mode-done] to update the value and exit.\n\n")) (setq-local help-fns--edit-variable var))) (defvar-keymap help-fns--edit-value-mode-map commit af8ec14cd73888af462c8a67b5c1b0f613513a25 Author: Stefan Kangas Date: Fri Jun 17 15:54:29 2022 +0200 Fix command substitution in emacsbug.el * lisp/mail/emacsbug.el: Minor doc fix. (submit-emacs-patch, report-emacs-bug): Fix command substitution. Prefer keymap-set to define-key. diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el index df2b7a7453..9d2e20ae04 100644 --- a/lisp/mail/emacsbug.el +++ b/lisp/mail/emacsbug.el @@ -1,7 +1,6 @@ ;;; emacsbug.el --- command to report Emacs bugs to appropriate mailing list -*- lexical-binding: t; -*- -;; Copyright (C) 1985, 1994, 1997-1998, 2000-2022 Free Software -;; Foundation, Inc. +;; Copyright (C) 1985-2022 Free Software Foundation, Inc. ;; Author: K. Shane Hartman ;; Maintainer: emacs-devel@gnu.org @@ -30,6 +29,9 @@ ;; to complete the process. Alternatively, compose the bug report in ;; Emacs then paste it into your normal mail client. +;; `M-x submit-emacs-patch' can be used to send a patch to the Emacs +;; maintainers. + ;;; Code: (require 'sendmail) @@ -348,10 +350,10 @@ usually do not have translators for other languages.\n\n"))) ;; This is so the user has to type something in order to send easily. (use-local-map (nconc (make-sparse-keymap) (current-local-map))) - (define-key (current-local-map) "\C-c\C-i" #'info-emacs-bug) + (keymap-set (current-local-map) "C-c C-i" #'info-emacs-bug) (if can-insert-mail - (define-key (current-local-map) "\C-c\M-i" - #'report-emacs-bug-insert-to-mailer)) + (keymap-set (current-local-map) "C-c M-i" + #'report-emacs-bug-insert-to-mailer)) (setq report-emacs-bug-send-command (get mail-user-agent 'sendfunc) report-emacs-bug-send-hook (get mail-user-agent 'hookvar)) (if report-emacs-bug-send-command @@ -360,20 +362,23 @@ usually do not have translators for other languages.\n\n"))) (unless report-emacs-bug-no-explanations (with-output-to-temp-buffer "*Bug Help*" (princ "While in the mail buffer:\n\n") - (if report-emacs-bug-send-command - (princ (substitute-command-keys - (format " Type \\[%s] to send the bug report.\n" - report-emacs-bug-send-command)))) - (princ (substitute-command-keys - " Type \\[kill-buffer] RET to cancel (don't send it).\n")) - (if can-insert-mail - (princ (substitute-command-keys - " Type \\[report-emacs-bug-insert-to-mailer] to copy text to your preferred mail program.\n"))) - (terpri) - (princ (substitute-command-keys - " Type \\[info-emacs-bug] to visit in Info the Emacs Manual section + (let ((help + (substitute-command-keys + (format "%s%s%s%s" + (if report-emacs-bug-send-command + (format " Type \\[%s] to send the bug report.\n" + report-emacs-bug-send-command) + "") + " Type \\[kill-buffer] \\`RET' to cancel (don't send it).\n" + (if can-insert-mail + " Type \\[report-emacs-bug-insert-to-mailer] to \ +copy text to your preferred mail program.\n" + "") + " Type \\[info-emacs-bug] to visit in Info the Emacs Manual section about when and how to write a bug report, and what - information you should include to help fix the bug."))) + information you should include to help fix the bug.")))) + (with-current-buffer "*Bug Help*" + (insert help)))) (shrink-window-if-larger-than-buffer (get-buffer-window "*Bug Help*"))) ;; Make it less likely people will send empty messages. (if report-emacs-bug-send-hook @@ -501,9 +506,10 @@ Message buffer where you can explain more about the patch." (erase-buffer) (insert "Thank you for considering submitting a patch to the Emacs project.\n\n" "Please describe what the patch fixes (or, if it's a new feature, what it\n" - "implements) in the mail buffer below. When done, use the `C-c C-c' command\n" + "implements) in the mail buffer below. When done, use the " + (substitute-command-keys "\\\\[message-send-and-exit] command\n") "to send the patch as an email to the Emacs issue tracker.\n\n" - "If this is the first time you've submitted an Emacs patch, please\n" + "If this is the first time you're submitting an Emacs patch, please\n" "read the ") (insert-text-button "CONTRIBUTE" @@ -521,7 +527,8 @@ Message buffer where you can explain more about the patch." (emacs-bug--system-description) (mml-attach-file file "text/patch" nil "attachment") (message-goto-body) - (message "Write a description of the patch and use `C-c C-c' to send it") + (message "Write a description of the patch and use %s to send it" + (substitute-command-keys "\\[message-send-and-exit]")) (add-hook 'message-send-hook (lambda () (message-goto-body) commit 488a4cd61be621ad489bd91c221b0df2d0114203 Author: Lars Ingebrigtsen Date: Fri Jun 17 16:30:16 2022 +0200 Allow editing all symbols in help-fns--editable-variable * lisp/help-fns.el (help-fns--editable-variable): Allow editing all symbols (bug#56038). diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 61fc8037df..ca5750723f 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -1352,9 +1352,6 @@ it is displayed along with the global value." (defun help-fns--editable-variable (start end variable value buffer) (when (and (readablep value) - (or (not (symbolp value)) - (and (not (and (symbolp value) (boundp value))) - (not (and (symbolp value) (fboundp value))))) help-enable-variable-value-editing) (add-text-properties start end @@ -1362,6 +1359,7 @@ it is displayed along with the global value." 'help-fns--edit-variable (list variable value buffer (current-buffer)) 'keymap (define-keymap + :parent button-map "e" #'help-fns-edit-variable))))) (defvar help-fns--edit-variable) commit 6db5c7f8c47590269d196a329eab727228b9be19 Author: Lars Ingebrigtsen Date: Fri Jun 17 16:03:48 2022 +0200 Improve time parsing documentation * doc/lispref/os.texi (Time Parsing): Clarify which functions take/return timestamps and which ones take decoded time structures. * src/timefns.c (Fdecode_time): Clarify TIME argument (bug#46505). diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 11a0d02338..bc5374f10f 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -1754,9 +1754,10 @@ at the 15th of the month when adding months. Alternatively, you can use the @cindex time formatting @cindex formatting time values - These functions convert time values to text in a string, and vice versa. -Time values include @code{nil}, finite numbers, and Lisp timestamps -(@pxref{Time of Day}). + These functions convert time values to text in a string, and vice +versa. Time values are either represented as a Lisp timestamp +(@pxref{Time of Day}) or a decoded time structure (@pxref{Time +Conversion}). @defun date-to-time string This function parses the time-string @var{string} and returns the @@ -1769,22 +1770,11 @@ The operating system limits the range of time and zone values. @end defun @defun parse-time-string string -This function parses the time-string @var{string} into a list of the -following form: - -@example -(@var{sec} @var{min} @var{hour} @var{day} @var{mon} @var{year} @var{dow} @var{dst} @var{tz}) -@end example - -@noindent -The format of this list is the same as what @code{decode-time} accepts -(@pxref{Time Conversion}), and is described in more detail there. Any -@code{dst} element that cannot be determined from the input is set to -@minus{}1, and any other unknown element is set to -@code{nil}. The argument @var{string} should resemble an RFC 822 (or later) or -ISO 8601 string, like ``Fri, 25 Mar 2016 16:24:56 +0100'' or -``1998-09-12T12:21:54-0200'', but this function will attempt to parse -less well-formed time strings as well. +This function parses the time-string @var{string} into a decoded time +structure (@pxref{Time Conversion}). The argument @var{string} should +resemble an RFC 822 (or later) or ISO 8601 string, like ``Fri, 25 Mar +2016 16:24:56 +0100'' or ``1998-09-12T12:21:54-0200'', but this +function will attempt to parse less well-formed time strings as well. @end defun @vindex ISO 8601 date/time strings @@ -1801,11 +1791,11 @@ time structures, except the final one, which returns three of them @end defun @defun format-time-string format-string &optional time zone - -This function converts @var{time} (or the current time, if -@var{time} is omitted or @code{nil}) to a string according to -@var{format-string}. The conversion uses the time zone rule @var{zone}, which -defaults to the current time zone rule. @xref{Time Zone Rules}. The argument +This function converts @var{time} (which should be a Lisp timestamp, +and defaults to the current time if @var{time} is omitted or +@code{nil}) to a string according to @var{format-string}. The +conversion uses the time zone rule @var{zone}, which defaults to the +current time zone rule. @xref{Time Zone Rules}. The argument @var{format-string} may contain @samp{%}-sequences which say to substitute parts of the time. Here is a table of what the @samp{%}-sequences mean: diff --git a/src/timefns.c b/src/timefns.c index 13a84f6b3c..9df50eaecc 100644 --- a/src/timefns.c +++ b/src/timefns.c @@ -1463,7 +1463,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME ZONE) */) } DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 3, 0, - doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF). + doc: /* Decode a timestamp into (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF). The optional TIME is the time value to convert. See `format-time-string' for the various forms of a time value. commit 65675f676d510c16faffcc5fbba9f7f268f1707f Author: Lars Ingebrigtsen Date: Fri Jun 17 15:06:15 2022 +0200 Make uce.el obsolete (bug#46472) diff --git a/etc/TODO b/etc/TODO index 2f23d410a7..7ab913f779 100644 --- a/etc/TODO +++ b/etc/TODO @@ -806,7 +806,7 @@ kermit, log-edit, makesum, midnight [other than in Kill Buffer node], mouse-copy [?], mouse-drag, mouse-sel, net-utils, rcompile, snmp-mode [?], soundex [should be interactive?], strokes [start from the web page], talk, thingatpt [interactive functions?], type-break, vcursor, -xscheme, zone-mode [?], mlconvert [?], iso-cvt, feedmail [?], uce, +xscheme, zone-mode [?], mlconvert [?], iso-cvt, feedmail [?], gametree, page-ext, refbib, refer, scribe, texinfo, underline, cmacexp, hideif, pcomplete, xml, cvs-status (should be described in PCL-CVS manual); other progmodes, probably in separate manual. diff --git a/lisp/mail/uce.el b/lisp/obsolete/uce.el similarity index 99% rename from lisp/mail/uce.el rename to lisp/obsolete/uce.el index 2672cfca1f..2cbbf5dc65 100644 --- a/lisp/mail/uce.el +++ b/lisp/obsolete/uce.el @@ -5,6 +5,7 @@ ;; Author: stanislav shalunov ;; Created: 10 Dec 1996 ;; Keywords: mail, uce, unsolicited commercial email +;; Obsolete-since: 29.1 ;; This file is part of GNU Emacs. commit 7daa552c681bb14fa97428e5888cfb545108ce1d Author: Lars Ingebrigtsen Date: Fri Jun 17 14:47:16 2022 +0200 Fix wdired marking of unsuccessfully renamed files * lisp/wdired.el (wdired-finish-edit): Don't mark non-renamed files as renamed (bug#46438). diff --git a/lisp/wdired.el b/lisp/wdired.el index d2a6bad0f2..a5858ed190 100644 --- a/lisp/wdired.el +++ b/lisp/wdired.el @@ -521,7 +521,15 @@ non-nil means return old filename." files-renamed)))) (forward-line -1))) (when files-renamed - (setq errors (+ errors (wdired-do-renames files-renamed)))) + (pcase-let ((`(,errs . ,successful-renames) + (wdired-do-renames files-renamed))) + (cl-incf errors errs) + ;; Some of the renames may fail -- in that case, don't mark an + ;; already-existing file with the same name as renamed. + (pcase-dolist (`(,file . _) wdired--old-marks) + (unless (member file successful-renames) + (setq wdired--old-marks + (assoc-delete-all file wdired--old-marks #'equal)))))) ;; We have to be in wdired-mode when wdired-do-renames is executed ;; so that wdired--restore-properties runs, but we have to change ;; back to dired-mode before reverting the buffer to avoid using @@ -566,7 +574,8 @@ non-nil means return old filename." (errors 0) (total (1- (length renames))) (prep (make-progress-reporter "Renaming" 0 total)) - (overwrite (or (not wdired-confirm-overwrite) 1))) + (overwrite (or (not wdired-confirm-overwrite) 1)) + (successful-renames nil)) (while (or renames ;; We've done one round through the renames, we have found ;; some residue, but we also made some progress, so maybe @@ -617,13 +626,15 @@ non-nil means return old filename." (wdired-create-parentdirs file-new)) (dired-rename-file file-ori file-new overwrite)) + (:success + (push file-new successful-renames)) (error (setq errors (1+ errors)) (dired-log "Rename `%s' to `%s' failed:\n%s\n" file-ori file-new err))))))))) (progress-reporter-done prep) - errors)) + (cons errors successful-renames))) (defun wdired-create-parentdirs (file-new) "Create parent directories for FILE-NEW if they don't exist." commit 4aca0d818f2d0b7dd7dc511907cc19f63758e482 Author: Dmitry Gutov Date: Fri Jun 17 15:22:29 2022 +0300 buffer-match-p: Resolve backward compat concerns * doc/lispref/buffers.texi (Buffer List): Document 'major-mode' and 'derived-mode' predicates. Fix some typos. * lisp/subr.el (buffer-match-p): Use the structure initially pioneered by project-kill-buffer-conditions as-is (bug#54296). * lisp/progmodes/project.el (project-kill-buffer-conditions) (project--buffer-check): Revert the latest change. (project--buffer-check): Add support for lambda predicates. diff --git a/doc/lispref/buffers.texi b/doc/lispref/buffers.texi index 1cbe8bc093..aee440fe78 100644 --- a/doc/lispref/buffers.texi +++ b/doc/lispref/buffers.texi @@ -981,13 +981,18 @@ of Satisfied if @var{expr} doesn't satisfy @code{buffer-match-p} with the same buffer and @code{arg}. @item or -Satisfied if @var{oper} is a list and @emph{any} condition if +Satisfied if @var{expr} is a list and @emph{any} condition in @var{expr} satisfies @code{buffer-match-p}, with the same buffer and @code{arg}. @item and -Satisfied if @var{oper} is a list and @emph{all} condition if -@var{expr} satisfies @code{buffer-match-p}, with the same buffer and +Satisfied if @var{expr} is a list and @emph{all} conditions in +@var{expr} satisfy @code{buffer-match-p}, with the same buffer and @code{arg}. +@item derived-mode +Satisfied if the buffer's major mode derives from @var{expr}. +@item major-mode +Satisfied if the buffer's major mode is equal to @var{expr}. Prefer +using @code{derived-mode} instead when both can work. @end table @end itemize @end defun diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index f4d6742ed8..30f51704dc 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1221,22 +1221,18 @@ displayed." (display-buffer-other-frame buffer-or-name)) (defcustom project-kill-buffer-conditions - `(buffer-file-name ; All file-visiting buffers are included. + '(buffer-file-name ; All file-visiting buffers are included. ;; Most of the temp buffers in the background: - ,(lambda (buf) - (not (eq (buffer-local-value 'major-mode buf) - 'fundamental-mode))) + (major-mode . fundamental-mode) ;; non-text buffer such as xref, occur, vc, log, ... - (and (major-mode . special-mode) - ,(lambda (buf) - (not (eq (buffer-local-value 'major-mode buf) - 'help-mode)))) - (major-mode . compilation-mode) - (major-mode . dired-mode) - (major-mode . diff-mode) - (major-mode . comint-mode) - (major-mode . eshell-mode) - (major-mode . change-log-mode)) + (and (derived-mode . special-mode) + (not (major-mode . help-mode))) + (derived-mode . compilation-mode) + (derived-mode . dired-mode) + (derived-mode . diff-mode) + (derived-mode . comint-mode) + (derived-mode . eshell-mode) + (derived-mode . change-log-mode)) "List of conditions to kill buffers related to a project. This list is used by `project-kill-buffers'. Each condition is either: @@ -1246,11 +1242,9 @@ Each condition is either: - a cons-cell, where the car describes how to interpret the cdr. The car can be one of the following: * `major-mode': the buffer is killed if the buffer's major - mode is derived from the major mode denoted by the cons-cell's - cdr. + mode is eq to the cons-cell's cdr. * `derived-mode': the buffer is killed if the buffer's major - mode is eq to the cons-cell's cdr (this is deprecated and will - result in a warning if used). + mode is derived from the major mode in the cons-cell's cdr. * `not': the cdr is interpreted as a negation of a condition. * `and': the cdr is a list of recursive conditions, that all have to be met. @@ -1308,15 +1302,12 @@ form of CONDITIONS." (when (cond ((stringp c) (string-match-p c (buffer-name buf))) - ((symbolp c) + ((functionp c) (funcall c buf)) - ((eq (car-safe c) 'derived-mode) - (warn "The use of `derived-mode' in \ -`project--buffer-check' is deprecated.") - (provided-mode-derived-p - (buffer-local-value 'major-mode buf) - (cdr c))) ((eq (car-safe c) 'major-mode) + (eq (buffer-local-value 'major-mode buf) + (cdr c))) + ((eq (car-safe c) 'derived-mode) (provided-mode-derived-p (buffer-local-value 'major-mode buf) (cdr c))) diff --git a/lisp/subr.el b/lisp/subr.el index 50ae357a13..c1c9759b03 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -6855,9 +6855,11 @@ CONDITION is either: arguments, and returns non-nil if the buffer matches, - a cons-cell, where the car describes how to interpret the cdr. The car can be one of the following: - * `major-mode': the buffer matches if the buffer's major - mode is derived from the major mode denoted by the cons-cell's - cdr + * `derived-mode': the buffer matches if the buffer's major mode + is derived from the major mode in the cons-cell's cdr. + * `major-mode': the buffer matches if the buffer's major mode + is eq to the cons-cell's cdr. Prefer using `derived-mode' + instead when both can work. * `not': the cdr is interpreted as a negation of a condition. * `and': the cdr is a list of recursive conditions, that all have to be met. @@ -6877,6 +6879,10 @@ CONDITION is either: (funcall condition buffer) (funcall condition buffer arg))) ((eq (car-safe condition) 'major-mode) + (eq + (buffer-local-value 'major-mode buffer) + (cdr condition))) + ((eq (car-safe condition) 'derived-mode) (provided-mode-derived-p (buffer-local-value 'major-mode buffer) (cdr condition))) commit 017bdb161141c0b5f3981a124bdeadc17a20a558 Author: Lars Ingebrigtsen Date: Fri Jun 17 14:20:05 2022 +0200 Fix a tagging problem in tramp.texi * doc/misc/tramp.texi (Frequently Asked Questions): Restore an @end lisp removed by accident. diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index b8279c410a..745046f8fe 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -4985,6 +4985,7 @@ minibuffer: (before my-minibuffer-complete activate) (expand-abbrev)) @end group +@end lisp The reduced typing: @kbd{C-x C-f xy @key{TAB}}. commit 5e567af8e0608ccd6db37d548ccb36098eda95c4 Author: Po Lu Date: Fri Jun 17 20:19:19 2022 +0800 Reduce code duplication when setting user time window * src/xterm.c (x_make_frame_visible): Use `x_update_frame_user_time_window'. diff --git a/src/xterm.c b/src/xterm.c index 9d5e1babf3..fe7b6ffe21 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -24795,56 +24795,21 @@ x_make_frame_visible (struct frame *f) #ifndef USE_GTK output = FRAME_X_OUTPUT (f); + x_update_frame_user_time_window (f); - if (!x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time_window)) + /* It's been a while since I wrote that code... I don't + remember if it can leave `user_time_window' unset or not. */ + if (output->user_time_window != None) { - if (output->user_time_window == None) - output->user_time_window = FRAME_OUTER_WINDOW (f); - else if (output->user_time_window != FRAME_OUTER_WINDOW (f)) - { - XDestroyWindow (dpyinfo->display, - output->user_time_window); - XDeleteProperty (dpyinfo->display, - FRAME_OUTER_WINDOW (f), - dpyinfo->Xatom_net_wm_user_time_window); - output->user_time_window = FRAME_OUTER_WINDOW (f); - } - } - else - { - if (output->user_time_window == FRAME_OUTER_WINDOW (f) - || output->user_time_window == None) - { - XSetWindowAttributes attrs; - memset (&attrs, 0, sizeof attrs); - - output->user_time_window - = XCreateWindow (dpyinfo->display, FRAME_X_WINDOW (f), - -1, -1, 1, 1, 0, 0, InputOnly, - CopyFromParent, 0, &attrs); - - XDeleteProperty (dpyinfo->display, - FRAME_OUTER_WINDOW (f), - dpyinfo->Xatom_net_wm_user_time); - XChangeProperty (dpyinfo->display, - FRAME_OUTER_WINDOW (f), - dpyinfo->Xatom_net_wm_user_time_window, - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &output->user_time_window, - 1); - } + if (dpyinfo->last_user_time) + XChangeProperty (dpyinfo->display, output->user_time_window, + dpyinfo->Xatom_net_wm_user_time, + XA_CARDINAL, 32, PropModeReplace, + (unsigned char *) &dpyinfo->last_user_time, 1); + else + XDeleteProperty (dpyinfo->display, output->user_time_window, + dpyinfo->Xatom_net_wm_user_time); } - - if (dpyinfo->last_user_time) - XChangeProperty (dpyinfo->display, - output->user_time_window, - dpyinfo->Xatom_net_wm_user_time, - XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) &dpyinfo->last_user_time, 1); - else - XDeleteProperty (dpyinfo->display, - output->user_time_window, - dpyinfo->Xatom_net_wm_user_time); #endif f->output_data.x->asked_for_visible = true; commit e0bac17bbc51fc53d3555011b540b775942961d9 Author: Lars Ingebrigtsen Date: Fri Jun 17 14:17:51 2022 +0200 Mention face quirks after the final line in the lispref manual * doc/lispref/display.texi (Face Attributes): Mention the quirks about point after the final line (bug#56011). diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 1147ba112a..404cf1b247 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -2593,6 +2593,13 @@ doesn't specify an explicit value for a face, the value from the original face definition by @code{defface} is inherited (@pxref{Defining Faces}). +Some modes, like @code{hl-line-mode}, use a face with an +@code{:extend} property to mark the entire current line. Note, +however, that Emacs will always allow you to move point after the +final character in a buffer, and if the buffer ends with a newline +character, point can be placed on what is seemingly a line at the end +of the buffer---but Emacs can't highlight that ``line'', because it +doesn't really exist. @end table @defun font-family-list &optional frame commit c0c538b392240e388b80ae03f12774f577732a14 Author: Lars Ingebrigtsen Date: Fri Jun 17 13:48:53 2022 +0200 Speed up shr-string-pixel-width * lisp/net/eww.el (eww-update-header-line-format): Use string-pixel-width (since we don't care about shr-use-fonts here). * lisp/net/shr.el (shr-string-pixel-width): Use `string-pixel-width', which should be faster. diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 8f02be12ff..3c16942e7c 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -833,7 +833,7 @@ The renaming scheme is performed in accordance with (when url (setq url (propertize url 'face 'variable-pitch)) (let* ((parsed (url-generic-parse-url url)) - (host-length (shr-string-pixel-width + (host-length (string-pixel-width (propertize (format "%s://%s" (url-type parsed) (url-host parsed)) @@ -842,17 +842,17 @@ The renaming scheme is performed in accordance with (cond ;; The host bit is wider than the window, so nix ;; the title. - ((> (+ host-length (shr-string-pixel-width "xxxxx")) width) + ((> (+ host-length (string-pixel-width "xxxxx")) width) (setq title "")) ;; Trim the title. - ((> (+ (shr-string-pixel-width (concat title "xx")) + ((> (+ (string-pixel-width (concat title "xx")) host-length) width) (setq title (concat (eww--limit-string-pixelwise title (- width host-length - (shr-string-pixel-width + (string-pixel-width (propertize "...: " 'face 'variable-pitch)))) (propertize "..." 'face 'variable-pitch))))))) diff --git a/lisp/net/shr.el b/lisp/net/shr.el index b54144576e..b269607e32 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -337,6 +337,11 @@ and other things: 0)) (pixel-fill-width))) +(defmacro shr-string-pixel-width (string) + `(if (not shr-use-fonts) + (length ,string) + (string-pixel-width ,string))) + ;;;###autoload (defun shr-insert-document (dom) "Render the parsed document DOM into the current buffer. @@ -677,19 +682,6 @@ size, and full-buffer size." (goto-char (mark)) (shr-pixel-column)))) -(defun shr-string-pixel-width (string) - (if (not shr-use-fonts) - (length string) - ;; Save and restore point across with-temp-buffer, since - ;; shr-pixel-column uses save-window-excursion, which can reset - ;; point to 1. - (let ((pt (point))) - (prog1 - (with-temp-buffer - (insert string) - (shr-pixel-column)) - (goto-char pt))))) - (defsubst shr--translate-insertion-chars () ;; Remove soft hyphens. (goto-char (point-min)) commit dc6157bef758cf5ba490219eebccaf33e14430d3 Author: Stefan Kangas Date: Fri Jun 17 13:34:36 2022 +0200 Cancel editing bookmark annotations with C-c C-k * lisp/bookmark.el (bookmark-edit-annotation-cancel): New command. (bookmark-edit-annotation-mode): Document it. (bookmark-edit-annotation-mode-map): Bind it to 'C-c C-k'. (bookmark-default-annotation-text): Announce it when editing annotations. (bookmark-edit-annotation--maybe-display-list): New macro. (bookmark-send-edited-annotation): Use above new macro. diff --git a/etc/NEWS b/etc/NEWS index dd7996b277..3b9515c2d4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1785,6 +1785,10 @@ the jumping function. This will display bookmark list from most recently set to least recently set. +--- +*** When editing a bookmark annotation, 'C-c C-k' will now cancel. +It is bound to the new command 'bookmark-edit-annotation-cancel'. + --- *** New minor mode 'elide-head-mode'. Enabling this minor mode turns on hiding header material, like diff --git a/lisp/bookmark.el b/lisp/bookmark.el index 4a8ffc0fa0..fdaea381ab 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -1028,10 +1028,12 @@ annotations." (format-message "# All lines which start with a `#' will be deleted.\n") (substitute-command-keys - "# Type \\[bookmark-send-edited-annotation] when done.\n#\n") + (concat + "# Type \\[bookmark-send-edited-annotation] when done. Type " + "\\[bookmark-edit-annotation-cancel] to cancel.\n#\n")) "# Author: " (user-full-name) " <" (user-login-name) "@" (system-name) ">\n" - "# Date: " (current-time-string) "\n")) + "# Date: " (current-time-string) "\n")) (defvar bookmark-edit-annotation-text-func 'bookmark-default-annotation-text @@ -1041,7 +1043,8 @@ It takes one argument, the name of the bookmark, as a string.") (defvar-keymap bookmark-edit-annotation-mode-map :doc "Keymap for editing an annotation of a bookmark." :parent text-mode-map - "C-c C-c" #'bookmark-send-edited-annotation) + "C-c C-c" #'bookmark-send-edited-annotation + "C-c C-k" #'bookmark-edit-annotation-cancel) (defun bookmark-insert-annotation (bookmark-name-or-record) "Insert annotation for BOOKMARK-NAME-OR-RECORD at point." @@ -1055,10 +1058,30 @@ It takes one argument, the name of the bookmark, as a string.") (define-derived-mode bookmark-edit-annotation-mode text-mode "Edit Bookmark Annotation" "Mode for editing the annotation of bookmarks. -When you have finished composing, type \\[bookmark-send-edited-annotation]. +\\\ +When you have finished composing, type \\[bookmark-send-edited-annotation] \ +or \\[bookmark-edit-annotation-cancel] to cancel. \\{bookmark-edit-annotation-mode-map}") +(defmacro bookmark-edit-annotation--maybe-display-list (&rest body) + "Display bookmark list after editing if appropriate." + `(let ((from-bookmark-list bookmark--annotation-from-bookmark-list) + (old-buffer (current-buffer))) + ,@body + (quit-window) + (bookmark-bmenu-surreptitiously-rebuild-list) + (when from-bookmark-list + (pop-to-buffer (get-buffer bookmark-bmenu-buffer)) + (goto-char (point-min)) + (bookmark-bmenu-bookmark)) + (kill-buffer old-buffer))) + +(defun bookmark-edit-annotation-cancel () + "Cancel the current annotation edit." + (interactive nil bookmark-edit-annotation-mode) + (bookmark-edit-annotation--maybe-display-list + (message "Canceled by user"))) (defun bookmark-send-edited-annotation () "Use buffer contents as annotation for a bookmark. @@ -1072,22 +1095,14 @@ Lines beginning with `#' are ignored." (bookmark-kill-line t) (forward-line 1))) ;; Take no chances with text properties. - (let ((annotation (buffer-substring-no-properties (point-min) (point-max))) - (bookmark-name bookmark-annotation-name) - (from-bookmark-list bookmark--annotation-from-bookmark-list) - (old-buffer (current-buffer))) - (bookmark-set-annotation bookmark-name annotation) - (bookmark-update-last-modified bookmark-name) - (setq bookmark-alist-modification-count - (1+ bookmark-alist-modification-count)) - (message "Annotation updated for \"%s\"" bookmark-name) - (quit-window) - (bookmark-bmenu-surreptitiously-rebuild-list) - (when from-bookmark-list - (pop-to-buffer (get-buffer bookmark-bmenu-buffer)) - (goto-char (point-min)) - (bookmark-bmenu-bookmark)) - (kill-buffer old-buffer))) + (bookmark-edit-annotation--maybe-display-list + (let ((annotation (buffer-substring-no-properties (point-min) (point-max))) + (bookmark-name bookmark-annotation-name)) + (bookmark-set-annotation bookmark-name annotation) + (bookmark-update-last-modified bookmark-name) + (setq bookmark-alist-modification-count + (1+ bookmark-alist-modification-count)) + (message "Annotation updated for \"%s\"" bookmark-name)))) (defun bookmark-edit-annotation (bookmark-name-or-record &optional from-bookmark-list) commit abdc5887c1fb81ec7ce22d0645e4dfa10f9eee29 Author: Stefan Kangas Date: Fri Jun 17 12:49:57 2022 +0200 Use command substitution in bookmark-edit-annotation * lisp/bookmark.el (bookmark-default-annotation-text): Use command substitution. (bookmark-edit-annotation): Enter mode before inserting annotation to get the correct command substitution. diff --git a/lisp/bookmark.el b/lisp/bookmark.el index b0b54e52d8..4a8ffc0fa0 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -1027,7 +1027,8 @@ annotations." bookmark-name) (format-message "# All lines which start with a `#' will be deleted.\n") - "# Type C-c C-c when done.\n#\n" + (substitute-command-keys + "# Type \\[bookmark-send-edited-annotation] when done.\n#\n") "# Author: " (user-full-name) " <" (user-login-name) "@" (system-name) ">\n" "# Date: " (current-time-string) "\n")) @@ -1094,8 +1095,8 @@ Lines beginning with `#' are ignored." If optional argument FROM-BOOKMARK-LIST is non-nil, return to the bookmark list when editing is done." (pop-to-buffer (generate-new-buffer-name "*Bookmark Annotation Compose*")) - (bookmark-insert-annotation bookmark-name-or-record) (bookmark-edit-annotation-mode) + (bookmark-insert-annotation bookmark-name-or-record) (setq bookmark--annotation-from-bookmark-list from-bookmark-list) (setq bookmark-annotation-name bookmark-name-or-record)) commit 77c7a79a3fcc0ace2b58ae21b9fcb93bf536d923 Author: Stefan Kangas Date: Fri Jun 17 12:18:26 2022 +0200 * lisp/edmacro.el (edit-kbd-macro): Use command substitution. diff --git a/lisp/edmacro.el b/lisp/edmacro.el index 26f3ae02ab..fe1fc086bc 100644 --- a/lisp/edmacro.el +++ b/lisp/edmacro.el @@ -154,8 +154,10 @@ With a prefix argument, format the macro in a more concise way." (setq-local edmacro-finish-hook finish-hook) (setq-local edmacro-store-hook store-hook) (erase-buffer) - (insert ";; Keyboard Macro Editor. Press C-c C-c to finish; " - "press C-x k RET to cancel.\n") + (insert (substitute-command-keys + (concat + ";; Keyboard Macro Editor. Press \\[edmacro-finish-edit] " + "to finish; press \\`C-x k RET' to cancel.\n"))) (insert ";; Original keys: " fmt "\n") (unless store-hook (insert "\nCommand: " (if cmd (symbol-name cmd) "none") "\n") commit 17b3f8d56e254f8f0478ce583451f02e6034ed48 Author: Stefan Kangas Date: Fri Jun 17 11:52:20 2022 +0200 Delete most libraries obsolete since 24.1 and 24.3 Emacs 24.3 was released 10 years ago. * lisp/obsolete/abbrevlist.el: * lisp/obsolete/assoc.el: * lisp/obsolete/complete.el: * lisp/obsolete/cust-print.el: * lisp/obsolete/erc-hecomplete.el: * lisp/obsolete/mailpost.el: * lisp/obsolete/mouse-sel.el: * lisp/obsolete/old-emacs-lock.el: * lisp/obsolete/patcomp.el: * lisp/obsolete/pc-select.el: * lisp/obsolete/s-region.el: Delete files. These libraries have been obsolete since Emacs 24.1 or 24.3. (Bug#50999) * etc/NEWS: Announce their deletion. * lisp/minibuffer.el (minibuffer-confirm-exit-commands): * lisp/textmodes/rst.el: Remove references to above obsolete libraries. diff --git a/etc/NEWS b/etc/NEWS index e19b2f5eba..dd7996b277 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2004,6 +2004,12 @@ functions. --- ** '?\' at the end of a line now signals an error. Previously it produced a nonsense value, -1, that was never intended. + +** Some libraries obsolete since Emacs 24.1 and 24.3 have been removed: +abbrevlist.el, assoc.el, complete.el, cust-print.el, +erc-hecomplete.el, mailpost.el, mouse-sel.el, old-emacs-lock.el, +patcomp.el, pc-select.el, s-region.el, and sregex.el. + * Lisp Changes in Emacs 29.1 diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 23251a5474..e42d83af34 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1677,8 +1677,8 @@ DONT-CYCLE tells the function not to setup cycling." map))))))))) (defvar minibuffer-confirm-exit-commands - '(completion-at-point minibuffer-complete - minibuffer-complete-word PC-complete PC-complete-word) + '( completion-at-point minibuffer-complete + minibuffer-complete-word) "List of commands which cause an immediately following `minibuffer-complete-and-exit' to ask for extra confirmation.") diff --git a/lisp/obsolete/abbrevlist.el b/lisp/obsolete/abbrevlist.el deleted file mode 100644 index ca508a1554..0000000000 --- a/lisp/obsolete/abbrevlist.el +++ /dev/null @@ -1,56 +0,0 @@ -;;; abbrevlist.el --- list one abbrev table alphabetically ordered -*- lexical-binding: t; -*- - -;; Copyright (C) 1986, 1992, 2001-2022 Free Software Foundation, Inc. -;; Suggested by a previous version by Gildea. - -;; Maintainer: emacs-devel@gnu.org -;; Keywords: abbrev -;; Package: emacs -;; Obsolete-since: 24.1 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;;; Code: - -;;;###autoload -(defun list-one-abbrev-table (abbrev-table output-buffer) - "Display alphabetical listing of ABBREV-TABLE in buffer OUTPUT-BUFFER." - (with-output-to-temp-buffer output-buffer - (save-excursion - (let ((abbrev-list nil) (first-column 0)) - (set-buffer standard-output) - (mapatoms - (function (lambda (abbrev) - (setq abbrev-list (cons abbrev abbrev-list)))) - abbrev-table) - (setq abbrev-list (sort abbrev-list #'string-lessp)) - (while abbrev-list - (if (> (+ first-column 40) (window-width)) - (progn - (insert "\n") - (setq first-column 0))) - (indent-to first-column) - (insert (symbol-name (car abbrev-list))) - (indent-to (+ first-column 8)) - (insert (symbol-value (car abbrev-list))) - (setq first-column (+ first-column 40)) - (setq abbrev-list (cdr abbrev-list))))))) - -(provide 'abbrevlist) - -;;; abbrevlist.el ends here diff --git a/lisp/obsolete/assoc.el b/lisp/obsolete/assoc.el deleted file mode 100644 index 76fcb4b78b..0000000000 --- a/lisp/obsolete/assoc.el +++ /dev/null @@ -1,140 +0,0 @@ -;;; assoc.el --- insert/delete functions on association lists -*- lexical-binding: t -*- - -;; Copyright (C) 1996, 2001-2022 Free Software Foundation, Inc. - -;; Author: Barry A. Warsaw -;; Keywords: extensions -;; Obsolete-since: 24.3 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Association list utilities providing insertion, deletion, sorting -;; fetching off key-value pairs in association lists. - -;;; Code: - -(defun asort (alist-symbol key) - "Move a specified key-value pair to the head of an alist. -The alist is referenced by ALIST-SYMBOL. Key-value pair to move to -head is one matching KEY. Returns the sorted list and doesn't affect -the order of any other key-value pair. Side effect sets alist to new -sorted list." - (set alist-symbol - (sort (copy-alist (symbol-value alist-symbol)) - (lambda (a _b) (equal (car a) key))))) - - -(defun aelement (key value) - "Make a list of a cons cell containing car of KEY and cdr of VALUE. -The returned list is suitable for concatenating with an existing -alist, via `nconc'." - (list (cons key value))) - - -(defun aheadsym (alist) - "Return the key symbol at the head of ALIST." - (car (car alist))) - - -(defun anot-head-p (alist key) - "Find out if a specified key-value pair is not at the head of an alist. -The alist to check is specified by ALIST and the key-value pair is the -one matching the supplied KEY. Returns nil if ALIST is nil, or if -key-value pair is at the head of the alist. Returns t if key-value -pair is not at the head of alist. ALIST is not altered." - (not (equal (aheadsym alist) key))) - - -(defun aput (alist-symbol key &optional value) - "Insert a key-value pair into an alist. -The alist is referenced by ALIST-SYMBOL. The key-value pair is made -from KEY and optionally, VALUE. Returns the altered alist. - -If the key-value pair referenced by KEY can be found in the alist, and -VALUE is supplied non-nil, then the value of KEY will be set to VALUE. -If VALUE is not supplied, or is nil, the key-value pair will not be -modified, but will be moved to the head of the alist. If the key-value -pair cannot be found in the alist, it will be inserted into the head -of the alist (with value nil if VALUE is nil or not supplied)." - (let ((elem (aelement key value)) - alist) - (asort alist-symbol key) - (setq alist (symbol-value alist-symbol)) - (cond ((null alist) (set alist-symbol elem)) - ((anot-head-p alist key) (set alist-symbol (nconc elem alist))) - (value (setcar alist (car elem)) alist) - (t alist)))) - - -(defun adelete (alist-symbol key) - "Delete a key-value pair from the alist. -Alist is referenced by ALIST-SYMBOL and the key-value pair to remove -is pair matching KEY. Returns the altered alist." - (asort alist-symbol key) - (let ((alist (symbol-value alist-symbol))) - (cond ((null alist) nil) - ((anot-head-p alist key) alist) - (t (set alist-symbol (cdr alist)))))) - - -(defun aget (alist key &optional keynil-p) - "Return the value in ALIST that is associated with KEY. -Optional KEYNIL-P describes what to do if the value associated with -KEY is nil. If KEYNIL-P is not supplied or is nil, and the value is -nil, then KEY is returned. If KEYNIL-P is non-nil, then nil would be -returned. - -If no key-value pair matching KEY could be found in ALIST, or ALIST is -nil then nil is returned. ALIST is not altered." - (defvar assoc--copy) - (let ((assoc--copy (copy-alist alist))) - (cond ((null alist) nil) - ((progn (asort 'assoc--copy key) ; dynamic binding - (anot-head-p assoc--copy key)) nil) - ((cdr (car assoc--copy))) - (keynil-p nil) - ((car (car assoc--copy))) - (t nil)))) - - -(defun amake (alist-symbol keylist &optional valuelist) - "Make an association list. -The association list is attached to the alist referenced by -ALIST-SYMBOL. Each element in the KEYLIST becomes a key and is -associated with the value in VALUELIST with the same index. If -VALUELIST is not supplied or is nil, then each key in KEYLIST is -associated with nil. - -KEYLIST and VALUELIST should have the same number of elements, but -this isn't enforced. If VALUELIST is smaller than KEYLIST, remaining -keys are associated with nil. If VALUELIST is larger than KEYLIST, -extra values are ignored. Returns the created alist." - (let ((keycar (car keylist)) - (keycdr (cdr keylist)) - (valcar (car valuelist)) - (valcdr (cdr valuelist))) - (cond ((null keycdr) - (aput alist-symbol keycar valcar)) - (t - (amake alist-symbol keycdr valcdr) - (aput alist-symbol keycar valcar)))) - (symbol-value alist-symbol)) - -(provide 'assoc) - -;;; assoc.el ends here diff --git a/lisp/obsolete/complete.el b/lisp/obsolete/complete.el deleted file mode 100644 index 1b4c39b159..0000000000 --- a/lisp/obsolete/complete.el +++ /dev/null @@ -1,1122 +0,0 @@ -;;; complete.el --- partial completion mechanism plus other goodies -*- lexical-binding: t; -*- - -;; Copyright (C) 1990-1993, 1999-2022 Free Software Foundation, Inc. - -;; Author: Dave Gillespie -;; Keywords: abbrev convenience -;; Obsolete-since: 24.1 -;; -;; Special thanks to Hallvard Furuseth for his many ideas and contributions. - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Extended completion for the Emacs minibuffer. -;; -;; The basic idea is that the command name or other completable text is -;; divided into words and each word is completed separately, so that -;; "M-x p-b" expands to "M-x print-buffer". If the entry is ambiguous -;; each word is completed as much as possible and then the cursor is -;; left at the first position where typing another letter will resolve -;; the ambiguity. -;; -;; Word separators for this purpose are hyphen, space, and period. -;; These would most likely occur in command names, Info menu items, -;; and file names, respectively. But all word separators are treated -;; alike at all times. -;; -;; This completion package replaces the old-style completer's key -;; bindings for TAB, SPC, RET, and `?'. The old completer is still -;; available on the Meta versions of those keys. If you set -;; PC-meta-flag to nil, the old completion keys will be left alone -;; and the partial completer will use the Meta versions of the keys. - - -;; Usage: M-x partial-completion-mode. During completable minibuffer entry, -;; -;; TAB means to do a partial completion; -;; SPC means to do a partial complete-word; -;; RET means to do a partial complete-and-exit; -;; ? means to do a partial completion-help. -;; -;; If you set PC-meta-flag to nil, then TAB, SPC, RET, and ? perform -;; original Emacs completions, and M-TAB etc. do partial completion. -;; To do this, put the command, -;; -;; (setq PC-meta-flag nil) -;; -;; in your .emacs file. To load partial completion automatically, put -;; -;; (partial-completion-mode t) -;; -;; in your .emacs file, too. Things will be faster if you byte-compile -;; this file when you install it. -;; -;; As an extra feature, in cases where RET would not normally -;; complete (such as `C-x b'), the M-RET key will always do a partial -;; complete-and-exit. Thus `C-x b f.c RET' will select or create a -;; buffer called "f.c", but `C-x b f.c M-RET' will select the existing -;; buffer whose name matches that pattern (perhaps "filing.c"). -;; (PC-meta-flag does not affect this behavior; M-RET used to be -;; undefined in this situation.) -;; -;; The regular M-TAB (lisp-complete-symbol) command also supports -;; partial completion in this package. - -;; In addition, this package includes a feature for accessing include -;; files. For example, `C-x C-f RET' reads the file -;; /usr/include/sys/time.h. The variable PC-include-file-path is a -;; list of directories in which to search for include files. Completion -;; is supported in include file names. - - -;;; Code: - -(defgroup partial-completion nil - "Partial Completion of items." - :prefix "pc-" - :group 'minibuffer - :group 'convenience) - -(defcustom PC-first-char 'find-file - "Control how the first character of a string is to be interpreted. -If nil, the first character of a string is not taken literally if it is a word -delimiter, so that \".e\" matches \"*.e*\". -If t, the first character of a string is always taken literally even if it is a -word delimiter, so that \".e\" matches \".e*\". -If non-nil and non-t, the first character is taken literally only for file name -completion." - :type '(choice (const :tag "delimiter" nil) - (const :tag "literal" t) - (other :tag "find-file" find-file))) - -(defcustom PC-meta-flag t - "If non-nil, TAB means PC completion and M-TAB means normal completion. -Otherwise, TAB means normal completion and M-TAB means Partial Completion." - :type 'boolean) - -(defcustom PC-word-delimiters "-_. " - "A string of characters treated as word delimiters for completion. -Some arcane rules: -If `]' is in this string, it must come first. -If `^' is in this string, it must not come first. -If `-' is in this string, it must come first or right after `]'. -In other words, if S is this string, then `[S]' must be a valid Emacs regular -expression (not containing character ranges like `a-z')." - :type 'string) - -(defcustom PC-include-file-path '("/usr/include" "/usr/local/include") - "A list of directories in which to look for include files. -If nil, means use the colon-separated path in the variable $INCPATH instead." - :type '(repeat directory)) - -(defcustom PC-disable-includes nil - "If non-nil, include-file support in \\[find-file] is disabled." - :type 'boolean) - -(defvar PC-default-bindings t - "If non-nil, default partial completion key bindings are suppressed.") - -(defvar PC-env-vars-alist nil - "A list of the environment variable names and values.") - - -(defun PC-bindings (bind) - (let ((completion-map minibuffer-local-completion-map) - (must-match-map minibuffer-local-must-match-map)) - (cond ((not bind) - ;; These bindings are the default bindings. It would be better to - ;; restore the previous bindings. - (define-key read-expression-map "\e\t" #'completion-at-point) - - (define-key completion-map "\t" #'minibuffer-complete) - (define-key completion-map " " #'minibuffer-complete-word) - (define-key completion-map "?" #'minibuffer-completion-help) - - (define-key must-match-map "\r" #'minibuffer-complete-and-exit) - (define-key must-match-map "\n" #'minibuffer-complete-and-exit) - - (define-key global-map [remap lisp-complete-symbol] nil)) - (PC-default-bindings - (define-key read-expression-map "\e\t" #'PC-lisp-complete-symbol) - - (define-key completion-map "\t" #'PC-complete) - (define-key completion-map " " #'PC-complete-word) - (define-key completion-map "?" #'PC-completion-help) - - (define-key completion-map "\e\t" #'PC-complete) - (define-key completion-map "\e " #'PC-complete-word) - (define-key completion-map "\e\r" #'PC-force-complete-and-exit) - (define-key completion-map "\e\n" #'PC-force-complete-and-exit) - (define-key completion-map "\e?" #'PC-completion-help) - - (define-key must-match-map "\r" #'PC-complete-and-exit) - (define-key must-match-map "\n" #'PC-complete-and-exit) - - (define-key must-match-map "\e\r" #'PC-complete-and-exit) - (define-key must-match-map "\e\n" #'PC-complete-and-exit) - - (define-key global-map [remap lisp-complete-symbol] #'PC-lisp-complete-symbol))))) - -(defvar PC-do-completion-end nil - "Internal variable used by `PC-do-completion'.") - -(make-variable-buffer-local 'PC-do-completion-end) - -(defvar PC-goto-end nil - "Internal variable set in `PC-do-completion', used in -`choose-completion-string-functions'.") - -(make-variable-buffer-local 'PC-goto-end) - -;;;###autoload -(define-minor-mode partial-completion-mode - "Toggle Partial Completion mode. - -When Partial Completion mode is enabled, TAB (or M-TAB if `PC-meta-flag' is -nil) is enhanced so that if some string is divided into words and each word is -delimited by a character in `PC-word-delimiters', partial words are completed -as much as possible and `*' characters are treated likewise in file names. - -For example, M-x p-c-m expands to M-x partial-completion-mode since no other -command begins with that sequence of characters, and -\\[find-file] f_b.c TAB might complete to foo_bar.c if that file existed and no -other file in that directory begins with that sequence of characters. - -Unless `PC-disable-includes' is non-nil, the `<...>' sequence is interpreted -specially in \\[find-file]. For example, -\\[find-file] RET finds the file `/usr/include/sys/time.h'. -See also the variable `PC-include-file-path'. - -Partial Completion mode extends the meaning of `completion-auto-help' (which -see), so that if it is neither nil nor t, Emacs shows the `*Completions*' -buffer only on the second attempt to complete. That is, if TAB finds nothing -to complete, the first TAB just says \"Next char not unique\" and the -second TAB brings up the `*Completions*' buffer." - :global t - ;; Deal with key bindings... - (PC-bindings partial-completion-mode) - ;; Deal with include file feature... - (cond ((not partial-completion-mode) - (remove-hook 'find-file-not-found-functions - #'PC-look-for-include-file)) - ((not PC-disable-includes) - (add-hook 'find-file-not-found-functions #'PC-look-for-include-file))) - ;; Adjust the completion selection in *Completion* buffers to the way - ;; we work. The default minibuffer completion code only completes the - ;; text before point and leaves the text after point alone (new in - ;; Emacs-22). In contrast we use the whole text and we even sometimes - ;; move point to a place before EOB, to indicate the first position where - ;; there's a difference, so when the user uses choose-completion, we have - ;; to trick choose-completion into replacing the whole minibuffer text - ;; rather than only the text before point. --Stef - (funcall - (if partial-completion-mode #'add-hook #'remove-hook) - 'choose-completion-string-functions - (lambda (_choice buffer &rest _) - ;; When completing M-: (lisp- ) with point before the ), it is - ;; not appropriate to go to point-max (unlike the filename case). - (if (and (not PC-goto-end) - (minibufferp buffer)) - (goto-char (point-max)) - ;; Need a similar hack for the non-minibuffer-case -- gm. - (when PC-do-completion-end - (goto-char PC-do-completion-end) - (setq PC-do-completion-end nil))) - (setq PC-goto-end nil) - nil)) - ;; Build the env-completion and mapping table. - (when (and partial-completion-mode (null PC-env-vars-alist)) - (setq PC-env-vars-alist - (mapcar (lambda (string) - (let ((d (string-search "=" string))) - (cons (concat "$" (substring string 0 d)) - (and d (substring string (1+ d)))))) - process-environment)))) - - -(defun PC-complete () - "Like minibuffer-complete, but allows \"b--di\"-style abbreviations. -For example, \"M-x b--di\" would match `byte-recompile-directory', or any -name which consists of three or more words, the first beginning with \"b\" -and the third beginning with \"di\". - -The pattern \"b--d\" is ambiguous for `byte-recompile-directory' and -`beginning-of-defun', so this would produce a list of completions -just like when normal Emacs completions are ambiguous. - -Word-delimiters for the purposes of Partial Completion are \"-\", \"_\", -\".\", and SPC." - (interactive) - (if (PC-was-meta-key) - (minibuffer-complete) - ;; If the previous command was not this one, - ;; never scroll, always retry completion. - (or (eq last-command this-command) - (setq minibuffer-scroll-window nil)) - (let ((window minibuffer-scroll-window)) - ;; If there's a fresh completion window with a live buffer, - ;; and this command is repeated, scroll that window. - (if (and window (window-buffer window) - (buffer-name (window-buffer window))) - (with-current-buffer (window-buffer window) - (if (pos-visible-in-window-p (point-max) window) - (set-window-start window (point-min) nil) - (scroll-other-window))) - (PC-do-completion nil))))) - - -(defun PC-complete-word () - "Like `minibuffer-complete-word', but allows \"b--di\"-style abbreviations. -See `PC-complete' for details. -This can be bound to other keys, like `-' and `.', if you wish." - (interactive) - (if (eq (PC-was-meta-key) PC-meta-flag) - (if (eq last-command-event ? ) - (minibuffer-complete-word) - (self-insert-command 1)) - (self-insert-command 1) - (if (eobp) - (PC-do-completion 'word)))) - - -(defun PC-complete-space () - "Like `minibuffer-complete-word', but allows \"b--di\"-style abbreviations. -See `PC-complete' for details. -This is suitable for binding to other keys which should act just like SPC." - (interactive) - (if (eq (PC-was-meta-key) PC-meta-flag) - (minibuffer-complete-word) - (insert " ") - (if (eobp) - (PC-do-completion 'word)))) - - -(defun PC-complete-and-exit () - "Like `minibuffer-complete-and-exit', but allows \"b--di\"-style abbreviations. -See `PC-complete' for details." - (interactive) - (if (eq (PC-was-meta-key) PC-meta-flag) - (minibuffer-complete-and-exit) - (PC-do-complete-and-exit))) - -(defun PC-force-complete-and-exit () - "Like `minibuffer-complete-and-exit', but allows \"b--di\"-style abbreviations. -See `PC-complete' for details." - (interactive) - (let ((minibuffer-completion-confirm nil)) - (PC-do-complete-and-exit))) - -(defun PC-do-complete-and-exit () - (cond - ((= (point-max) (minibuffer-prompt-end)) - ;; Duplicate the "bug" that Info-menu relies on... - (exit-minibuffer)) - ((eq minibuffer-completion-confirm 'confirm) - (if (or (eq last-command this-command) - (test-completion (field-string) - minibuffer-completion-table - minibuffer-completion-predicate)) - (exit-minibuffer) - (PC-temp-minibuffer-message " [Confirm]"))) - ((eq minibuffer-completion-confirm 'confirm-after-completion) - ;; Similar to the above, but only if trying to exit immediately - ;; after typing TAB (this catches most minibuffer typos). - (if (and (memq last-command minibuffer-confirm-exit-commands) - (not (test-completion (field-string) - minibuffer-completion-table - minibuffer-completion-predicate))) - (PC-temp-minibuffer-message " [Confirm]") - (exit-minibuffer))) - (t - (let ((flag (PC-do-completion 'exit))) - (and flag - (if (or (eq flag 'complete) - (not minibuffer-completion-confirm)) - (exit-minibuffer) - (PC-temp-minibuffer-message " [Confirm]"))))))) - - -(defun PC-completion-help () - "Like `minibuffer-completion-help', but allows \"b--di\"-style abbreviations. -See `PC-complete' for details." - (interactive) - (if (eq (PC-was-meta-key) PC-meta-flag) - (minibuffer-completion-help) - (PC-do-completion 'help))) - -(defun PC-was-meta-key () - (or (/= (length (this-command-keys)) 1) - (let ((key (aref (this-command-keys) 0))) - (if (integerp key) - (>= key 128) - (not (null (memq 'meta (event-modifiers key)))))))) - - -(defvar PC-ignored-extensions 'empty-cache) -(defvar PC-delims 'empty-cache) -(defvar PC-ignored-regexp nil) -(defvar PC-word-failed-flag nil) -(defvar PC-delim-regex nil) -(defvar PC-ndelims-regex nil) -(defvar PC-delims-list nil) - -(defvar PC-completion-as-file-name-predicate - (lambda () minibuffer-completing-file-name) - "A function testing whether a minibuffer completion now will work filename-style. -The function takes no arguments, and typically looks at the value -of `minibuffer-completion-table' and the minibuffer contents.") - -;; Returns the sequence of non-delimiter characters that follow regexp in string. -(defun PC-chunk-after (string regexp) - (if (not (string-match regexp string)) - (let ((message "String %s didn't match regexp %s")) - (message message string regexp) - (error message string regexp))) - (let ((result (substring string (match-end 0)))) - ;; result may contain multiple chunks - (if (string-match PC-delim-regex result) - (setq result (substring result 0 (match-beginning 0)))) - result)) - -(defun test-completion-ignore-case (str table pred) - "Like `test-completion', but ignores case when possible." - ;; Binding completion-ignore-case to nil ensures, for compatibility with - ;; standard completion, that the return value is exactly one of the - ;; possibilities. Do this binding only if pred is nil, out of paranoia; - ;; perhaps it is safe even if pred is non-nil. - (if pred - (test-completion str table pred) - (let ((completion-ignore-case nil)) - (test-completion str table pred)))) - -;; The following function is an attempt to work around two problems: - -;; (1) When complete.el was written, (try-completion "" '(("") (""))) used to -;; return the value "". With a change from 2002-07-07 it returns t which caused -;; `PC-lisp-complete-symbol' to fail with a "Wrong type argument: sequencep, t" -;; error. `PC-try-completion' returns STRING in this case. - -;; (2) (try-completion "" '((""))) returned t before the above-mentioned change. -;; Since `PC-chop-word' operates on the return value of `try-completion' this -;; case might have provoked a similar error as in (1). `PC-try-completion' -;; returns "" instead. I don't know whether this is a real problem though. - -;; Since `PC-try-completion' is not a guaranteed to fix these bugs reliably, you -;; should try to look at the following discussions when you encounter problems: -;; - emacs-pretest-bug ("Partial Completion" starting 2007-02-23), -;; - emacs-devel ("[address-of-OP: Partial completion]" starting 2007-02-24), -;; - emacs-devel ("[address-of-OP: EVAL and mouse selection in *Completions*]" -;; starting 2007-03-05). -(defun PC-try-completion (string alist &optional predicate) - "Like `try-completion' but return STRING instead of t." - (let ((result (try-completion string alist predicate))) - (if (eq result t) string result))) - -(defvar completion-base-size) - -;; TODO document MODE magic... -(defun PC-do-completion (&optional mode beg end goto-end) - "Internal function to do the work of partial completion. -Text to be completed lies between BEG and END. Normally when -replacing text in the minibuffer, this function replaces up to -point-max (as is appropriate for completing a file name). If -GOTO-END is non-nil, however, it instead replaces up to END." - (or beg (setq beg (minibuffer-prompt-end))) - (or end (setq end (point-max))) - (let* ((table (if (eq minibuffer-completion-table 'read-file-name-internal) - 'PC-read-file-name-internal - minibuffer-completion-table)) - (pred minibuffer-completion-predicate) - (filename (funcall PC-completion-as-file-name-predicate)) - (dirname nil) ; non-nil only if a filename is being completed - ;; The following used to be "(dirlength 0)" which caused the erasure of - ;; the entire buffer text before `point' when inserting a completion - ;; into a buffer. - dirlength - (str (buffer-substring beg end)) - (incname (and filename (string-match "<\\([^\"<>]*\\)>?$" str))) - (ambig nil) - basestr origstr - env-on - regex - p offset - abbreviated - (poss nil) - helpposs - (case-fold-search completion-ignore-case)) - - ;; Check if buffer contents can already be considered complete - (if (and (eq mode 'exit) - (test-completion str table pred)) - 'complete - - ;; Do substitutions in directory names - (and filename - (setq basestr (or (file-name-directory str) "")) - (setq dirlength (length basestr)) - ;; Do substitutions in directory names - (setq p (substitute-in-file-name basestr)) - (not (string-equal basestr p)) - (setq str (concat p (file-name-nondirectory str))) - (progn - (delete-region beg end) - (insert str) - (setq end (+ beg (length str))))) - - ;; Prepare various delimiter strings - (or (equal PC-word-delimiters PC-delims) - (setq PC-delims PC-word-delimiters - PC-delim-regex (concat "[" PC-delims "]") - PC-ndelims-regex (concat "[^" PC-delims "]*") - PC-delims-list (append PC-delims nil))) - - ;; Add wildcards if necessary - (and filename - (let ((dir (file-name-directory str)) - (file (file-name-nondirectory str)) - ;; The base dir for file-completion was passed in `predicate'. - (default-directory (if (stringp pred) (expand-file-name pred) - default-directory))) - (while (and (stringp dir) (not (file-directory-p dir))) - (setq dir (directory-file-name dir)) - (setq file (concat (replace-regexp-in-string - PC-delim-regex "*\\&" - (file-name-nondirectory dir)) - "*/" file)) - (setq dir (file-name-directory dir))) - (setq origstr str str (concat dir file)))) - - ;; Look for wildcard expansions in directory name - (and filename - (string-match "\\*.*/" str) - (let ((pat str) - ;; The base dir for file-completion was passed in `predicate'. - (default-directory (if (stringp pred) (expand-file-name pred) - default-directory)) - files) - (setq p (1+ (string-match "/[^/]*\\'" pat))) - (while (setq p (string-match PC-delim-regex pat p)) - (setq pat (concat (substring pat 0 p) - "*" - (substring pat p)) - p (+ p 2))) - (setq files (file-expand-wildcards (concat pat "*"))) - (if files - (let ((dir (file-name-directory (car files))) - (p files)) - (while (and (setq p (cdr p)) - (equal dir (file-name-directory (car p))))) - (if p - (setq filename nil table nil - pred (if (stringp pred) nil pred) - ambig t) - (delete-region beg end) - (setq str (concat dir (file-name-nondirectory str))) - (insert str) - (setq end (+ beg (length str))))) - (if origstr - ;; If the wildcards were introduced by us, it's - ;; possible that PC-read-file-name-internal can - ;; still find matches for the original string - ;; even if we couldn't, so remove the added - ;; wildcards. - (setq str origstr) - (setq filename nil table nil - pred (if (stringp pred) nil pred)))))) - - ;; Strip directory name if appropriate - (if filename - (if incname - (setq basestr (substring str incname) - dirname (substring str 0 incname)) - (setq basestr (file-name-nondirectory str) - dirname (file-name-directory str)) - ;; Make sure str is consistent with its directory and basename - ;; parts. This is important on DOZe'NT systems when str only - ;; includes a drive letter, like in "d:". - (setq str (concat dirname basestr))) - (setq basestr str)) - - ;; Convert search pattern to a standard regular expression - (setq regex (regexp-quote basestr) - offset (if (and (> (length regex) 0) - (not (eq (aref basestr 0) ?\*)) - (or (eq PC-first-char t) - (and PC-first-char filename))) 1 0) - p offset) - (while (setq p (string-match PC-delim-regex regex p)) - (if (eq (aref regex p) ? ) - (setq regex (concat (substring regex 0 p) - PC-ndelims-regex - PC-delim-regex - (substring regex (1+ p))) - p (+ p (length PC-ndelims-regex) (length PC-delim-regex))) - (let ((bump (if (memq (aref regex p) - '(?$ ?^ ?\. ?* ?+ ?? ?\[ ?\] ?\\)) - -1 0))) - (setq regex (concat (substring regex 0 (+ p bump)) - PC-ndelims-regex - (substring regex (+ p bump))) - p (+ p (length PC-ndelims-regex) 1))))) - (setq p 0) - (if filename - (while (setq p (string-search "\\*" regex p)) - (setq regex (concat (substring regex 0 p) - "[^/]*" - (substring regex (+ p 2)))))) - ;;(setq the-regex regex) - (setq regex (concat "\\`" regex)) - - (and (> (length basestr) 0) - (= (aref basestr 0) ?$) - (setq env-on t - table PC-env-vars-alist - pred nil)) - - ;; Find an initial list of possible completions - (unless (setq p (string-match (concat PC-delim-regex - (if filename "\\|\\*" "")) - str - (+ (length dirname) offset))) - - ;; Minibuffer contains no hyphens -- simple case! - (setq poss (all-completions (if env-on basestr str) - table - pred)) - (unless (or poss (string-equal str "")) - ;; Try completion as an abbreviation, e.g. "mvb" -> - ;; "m-v-b" -> "multiple-value-bind", but only for - ;; non-empty strings. - (setq origstr str - abbreviated t) - (if filename - (cond - ;; "alpha" or "/alpha" -> expand whole path. - ((string-match "^/?\\([A-Za-z0-9]+\\)$" str) - (setq - basestr "" - p nil - poss (file-expand-wildcards - (concat "/" - (mapconcat #'list (match-string 1 str) "*/") - "*")) - beg (1- beg))) - ;; Alphanumeric trailer -> expand trailing file - ((string-match "^\\(.+/\\)\\([A-Za-z0-9]+\\)$" str) - (setq regex (concat "\\`" - (mapconcat #'list - (match-string 2 str) - "[A-Za-z0-9]*[^A-Za-z0-9]")) - p (1+ (length (match-string 1 str)))))) - (setq regex (concat "\\`" (mapconcat (lambda (c) - (regexp-quote (string c))) - str "[^-]*-")) - p 1)))) - (when p - ;; Use all-completions to do an initial cull. This is a big win, - ;; since all-completions is written in C! - (let ((compl (all-completions (if env-on - (file-name-nondirectory (substring str 0 p)) - (substring str 0 p)) - table - pred))) - (setq p compl) - (when (and compl abbreviated) - (if filename - (progn - (setq p nil) - (dolist (x compl) - (when (string-match regex x) - (push x p))) - (setq basestr (try-completion "" p))) - (setq basestr (mapconcat #'list str "-")) - (delete-region beg end) - (setq end (+ beg (length basestr))) - (insert basestr)))) - (while p - (and (string-match regex (car p)) - (progn - (set-text-properties 0 (length (car p)) '() (car p)) - (setq poss (cons (car p) poss)))) - (setq p (cdr p)))) - - ;; If table had duplicates, they can be here. - (delete-dups poss) - - ;; Handle completion-ignored-extensions - (and filename - (not (eq mode 'help)) - (let ((p2 poss)) - - ;; Build a regular expression representing the extensions list - (or (equal completion-ignored-extensions PC-ignored-extensions) - (setq PC-ignored-regexp - (concat "\\(" - (mapconcat - #'regexp-quote - (setq PC-ignored-extensions - completion-ignored-extensions) - "\\|") - "\\)\\'"))) - - ;; Check if there are any without an ignored extension. - ;; Also ignore `.' and `..'. - (setq p nil) - (while p2 - (or (string-match PC-ignored-regexp (car p2)) - (string-match "\\(\\`\\|/\\)[.][.]?/?\\'" (car p2)) - (setq p (cons (car p2) p))) - (setq p2 (cdr p2))) - - ;; If there are "good" names, use them - (and p (setq poss p)))) - - ;; Now we have a list of possible completions - - (cond - - ;; No valid completions found - ((null poss) - (if (and (eq mode 'word) - (not PC-word-failed-flag)) - (let ((PC-word-failed-flag t)) - (delete-char -1) - (PC-do-completion 'word)) - (when abbreviated - (delete-region beg end) - (insert origstr)) - (beep) - (PC-temp-minibuffer-message (if ambig - " [Ambiguous dir name]" - (if (eq mode 'help) - " [No completions]" - " [No match]"))) - nil)) - - ;; More than one valid completion found - ((or (cdr (setq helpposs poss)) - (memq mode '(help word))) - - ;; Is the actual string one of the possible completions? - (setq p (and (not (eq mode 'help)) poss)) - (while (and p - (not (string-equal (car p) basestr))) - (setq p (cdr p))) - (and p (null mode) - (PC-temp-minibuffer-message " [Complete, but not unique]")) - (if (and p - (not (and (null mode) - (eq this-command last-command)))) - t - - ;; If ambiguous, try for a partial completion - (let ((improved nil) - prefix - (pt nil) - (skip "\\`")) - - ;; Check if next few letters are the same in all cases - (if (and (not (eq mode 'help)) - (setq prefix (PC-try-completion - (PC-chunk-after basestr skip) poss))) - (let ((first t) i) - (if (eq mode 'word) - (setq prefix (PC-chop-word prefix basestr))) - (goto-char (+ beg (length dirname))) - (while (and (progn - (setq i 0) ; index into prefix string - (while (< i (length prefix)) - (if (and (< (point) end) - (or (eq (downcase (aref prefix i)) - (downcase (following-char))) - (and (looking-at " ") - (memq (aref prefix i) - PC-delims-list)))) - ;; replace " " by the actual delimiter - ;; or input char by prefix char - (progn - (delete-char 1) - (insert (substring prefix i (1+ i)))) - ;; insert a new character - (progn - (and filename (looking-at "\\*") - (progn - (delete-char 1) - (setq end (1- end)))) - (setq improved t) - (insert (substring prefix i (1+ i))) - (setq end (1+ end)))) - (setq i (1+ i))) - (or pt (setq pt (point))) - (looking-at PC-delim-regex)) - (setq skip (concat skip - (regexp-quote prefix) - PC-ndelims-regex) - prefix (PC-try-completion - (PC-chunk-after - ;; not basestr, because that does - ;; not reflect insertions - (buffer-substring - (+ beg (length dirname)) end) - skip) - (mapcar - (lambda (x) - (when (string-match skip x) - (substring x (match-end 0)))) - poss))) - (or (> i 0) (> (length prefix) 0)) - (or (not (eq mode 'word)) - (and first (> (length prefix) 0) - (setq first nil - prefix (substring prefix 0 1)))))) - (goto-char (if (eq mode 'word) end - (or pt beg))))) - - (if (and (eq mode 'word) - (not PC-word-failed-flag)) - - (if improved - - ;; We changed it... would it be complete without the space? - (if (test-completion (buffer-substring - (field-beginning) (1- end)) - table pred) - (delete-region (1- end) end))) - - (if improved - - ;; We changed it... enough to be complete? - (and (eq mode 'exit) - (test-completion-ignore-case (field-string) table pred)) - - ;; If totally ambiguous, display a list of completions - (if (or (eq completion-auto-help t) - (and completion-auto-help - (eq last-command this-command)) - (eq mode 'help)) - (let ((prompt-end (minibuffer-prompt-end))) - (with-output-to-temp-buffer "*Completions*" - (display-completion-list (sort helpposs #'string-lessp)) - (setq PC-do-completion-end end - PC-goto-end goto-end) - (with-current-buffer standard-output - ;; Record which part of the buffer we are completing - ;; so that choosing a completion from the list - ;; knows how much old text to replace. - ;; This was briefly nil in the non-dirname case. - ;; However, if one calls PC-lisp-complete-symbol - ;; on "(ne-f" with point on the hyphen, PC offers - ;; all completions starting with "(ne", some of - ;; which do not match the "-f" part (maybe it - ;; should not, but it does). In such cases, - ;; completion gets confused trying to figure out - ;; how much to replace, so we tell it explicitly - ;; (ie, the number of chars in the buffer before beg). - ;; - ;; Note that choose-completion-string-functions - ;; plays around with point. - (with-suppressed-warnings ((obsolete - completion-base-size)) - (setq completion-base-size - (if dirname - dirlength - (- beg prompt-end))))))) - (PC-temp-minibuffer-message " [Next char not unique]")) - ;; Expansion of filenames is not reversible, - ;; so just keep the prefix. - (when (and abbreviated filename) - (delete-region (point) end)) - nil))))) - - ;; Only one possible completion - (t - (if (and (equal basestr (car poss)) - (not (and env-on filename)) - (not abbreviated)) - (if (null mode) - (PC-temp-minibuffer-message " [Sole completion]")) - (delete-region beg end) - (insert (format "%s" - (if filename - (substitute-in-file-name (concat dirname (car poss))) - (car poss))))) - t))))) - -(defun PC-chop-word (new old) - (let ((i -1) - (j -1)) - (while (and (setq i (string-match PC-delim-regex old (1+ i))) - (setq j (string-match PC-delim-regex new (1+ j))))) - (if (and j - (or (not PC-word-failed-flag) - (setq j (string-match PC-delim-regex new (1+ j))))) - (substring new 0 (1+ j)) - new))) - -(defvar PC-not-minibuffer nil) - -(defun PC-temp-minibuffer-message (message) - "A Lisp version of `temp_minibuffer_message' from minibuf.c." - (cond (PC-not-minibuffer - (message "%s" message) - (sit-for 2) - (message "")) - ((fboundp 'temp-minibuffer-message) - (temp-minibuffer-message message)) - (t - (let ((point-max (point-max))) - (save-excursion - (goto-char point-max) - (insert message)) - (let ((inhibit-quit t)) - (sit-for 2) - (delete-region point-max (point-max)) - (when quit-flag - (setq quit-flag nil - unread-command-events '(7)))))))) - -;; Does not need to be buffer-local (?) because only used when one -;; PC-l-c-s immediately follows another. -(defvar PC-lisp-complete-end nil - "Internal variable used by `PC-lisp-complete-symbol'.") - -(defun PC-lisp-complete-symbol () - "Perform completion on Lisp symbol preceding point. -That symbol is compared against the symbols that exist -and any additional characters determined by what is there -are inserted. -If the symbol starts just after an open-parenthesis, -only symbols with function definitions are considered. -Otherwise, all symbols with function definitions, values -or properties are considered." - (interactive) - (let* ((end - (save-excursion - (with-syntax-table lisp-mode-syntax-table - (skip-syntax-forward "_w") - (point)))) - (beg (save-excursion - (with-syntax-table lisp-mode-syntax-table - (backward-sexp 1) - (while (= (char-syntax (following-char)) ?\') - (forward-char 1)) - (point)))) - (minibuffer-completion-table obarray) - (minibuffer-completion-predicate - (if (eq (char-after (1- beg)) ?\() - 'fboundp - (function (lambda (sym) - (or (boundp sym) (fboundp sym) - (symbol-plist sym)))))) - (PC-not-minibuffer t)) - ;; https://lists.gnu.org/r/emacs-devel/2007-03/msg01211.html - ;; - ;; This deals with cases like running PC-l-c-s on "M-: (n-f". - ;; The first call to PC-l-c-s expands this to "(ne-f", and moves - ;; point to the hyphen [1]. If one calls PC-l-c-s immediately after, - ;; then without the last-command check, one is offered all - ;; completions of "(ne", which is presumably not what one wants. - ;; - ;; This is arguably (at least, it seems to be the existing intended - ;; behavior) what one _does_ want if point has been explicitly - ;; positioned on the hyphen. Note that if PC-do-completion (qv) binds - ;; completion-base-size to nil, then completion does not replace the - ;; correct amount of text in such cases. - ;; - ;; Neither of these problems occur when using PC for filenames in the - ;; minibuffer, because in that case PC-do-completion is called without - ;; an explicit value for END, and so uses (point-max). This is fine for - ;; a filename, because the end of the filename must be at the end of - ;; the minibuffer. The same is not true for lisp symbols. - ;; - ;; [1] An alternate fix would be to not move point to the hyphen - ;; in such cases, but that would make the behavior different from - ;; that for filenames. It seems PC moves point to the site of the - ;; first difference between the possible completions. - ;; - ;; Alternatively alternatively, maybe end should be computed in - ;; the same way as beg. That would change the behavior though. - (if (equal last-command 'PC-lisp-complete-symbol) - (PC-do-completion nil beg PC-lisp-complete-end t) - (if PC-lisp-complete-end - (move-marker PC-lisp-complete-end end) - (setq PC-lisp-complete-end (copy-marker end t))) - (PC-do-completion nil beg end t)))) - -(defun PC-complete-as-file-name () - "Perform completion on file names preceding point. - Environment vars are converted to their values." - (interactive) - (let* ((end (point)) - (beg (if (re-search-backward "[^\\][ \t\n\"`'][^ \t\n\"`']" - (point-min) t) - (+ (point) 2) - (point-min))) - (minibuffer-completion-table 'PC-read-file-name-internal) - (minibuffer-completion-predicate nil) - (PC-not-minibuffer t)) - (goto-char end) - (PC-do-completion nil beg end))) - -;; Facilities for loading C header files. This is independent from the -;; main completion code. See also the variable `PC-include-file-path' -;; at top of this file. - -(defun PC-look-for-include-file () - (if (string-match "[\"<]\\([^\"<>]*\\)[\">]?$" (buffer-file-name)) - (let ((name (substring (buffer-file-name) - (match-beginning 1) (match-end 1))) - (punc (aref (buffer-file-name) (match-beginning 0))) - (path nil) - new-buf) - (kill-buffer (current-buffer)) - (if (equal name "") - (with-current-buffer (car (buffer-list)) - (save-excursion - (beginning-of-line) - (if (looking-at - "[ \t]*#[ \t]*include[ \t]+[<\"]\\(.+\\)[>\"][ \t]*[\n/]") - (setq name (buffer-substring (match-beginning 1) - (match-end 1)) - punc (char-after (1- (match-beginning 1)))) - ;; Suggested by Frank Siebenlist: - (if (or (looking-at - "[ \t]*([ \t]*load[ \t]+\"\\([^\"]+\\)\"") - (looking-at - "[ \t]*([ \t]*load-library[ \t]+\"\\([^\"]+\\)\"") - (looking-at - "[ \t]*([ \t]*require[ \t]+'\\([^\t )]+\\)[\t )]")) - (progn - (setq name (buffer-substring (match-beginning 1) - (match-end 1)) - punc ?\< - path load-path) - (if (string-match "\\.elc$" name) - (setq name (substring name 0 -1)) - (or (string-match "\\.el$" name) - (setq name (concat name ".el"))))) - (error "Not on an #include line")))))) - (or (string-match "\\.[[:alnum:]]+$" name) - (setq name (concat name ".h"))) - (if (eq punc ?\<) - (let ((path (or path (PC-include-file-path)))) - (while (and path - (not (file-exists-p - (concat (file-name-as-directory (car path)) - name)))) - (setq path (cdr path))) - (if path - (setq name (concat (file-name-as-directory (car path)) name)) - (error "No such include file: <%s>" name))) - (let ((dir (with-current-buffer (car (buffer-list)) - default-directory))) - (if (file-exists-p (concat dir name)) - (setq name (concat dir name)) - (error "No such include file: `%s'" name)))) - (setq new-buf (get-file-buffer name)) - (if new-buf - ;; no need to verify last-modified time for this! - (set-buffer new-buf) - (set-buffer (create-file-buffer name)) - (erase-buffer) - (insert-file-contents name t)) - ;; Returning non-nil with the new buffer current - ;; is sufficient to tell find-file to use it. - t) - nil)) - -(defun PC-include-file-path () - (or PC-include-file-path - (let ((env (getenv "INCPATH")) - (path nil) - pos) - (or env (error "No include file path specified")) - (while (setq pos (string-match ":[^:]+$" env)) - (setq path (cons (substring env (1+ pos)) path) - env (substring env 0 pos))) - path))) - -;; This is adapted from lib-complete.el, by Mike Williams. -(defun PC-include-file-all-completions (file search-path &optional full) - "Return all completions for FILE in any directory on SEARCH-PATH. -If optional third argument FULL is non-nil, returned pathnames should be -absolute rather than relative to some directory on the SEARCH-PATH." - (setq search-path - (mapcar (lambda (dir) - (if dir (file-name-as-directory dir) default-directory)) - search-path)) - (if (file-name-absolute-p file) - ;; It's an absolute file name, so don't need search-path - (progn - (setq file (expand-file-name file)) - (file-name-all-completions - (file-name-nondirectory file) (file-name-directory file))) - (let ((subdir (file-name-directory file)) - (ndfile (file-name-nondirectory file)) - file-lists) - ;; Append subdirectory part to each element of search-path - (if subdir - (setq search-path - (mapcar (lambda (dir) (concat dir subdir)) - search-path) - file nil)) - ;; Make list of completions in each directory on search-path - (while search-path - (let* ((dir (car search-path)) - (subdir (if full dir subdir))) - (if (file-directory-p dir) - (progn - (setq file-lists - (cons - (mapcar (lambda (file) (concat subdir file)) - (file-name-all-completions ndfile - (car search-path))) - file-lists)))) - (setq search-path (cdr search-path)))) - ;; Compress out duplicates while building complete list (slloooow!) - (let ((sorted (sort (apply #'nconc file-lists) - (lambda (x y) (not (string-lessp x y))))) - compressed) - (while sorted - (if (equal (car sorted) (car compressed)) nil - (setq compressed (cons (car sorted) compressed))) - (setq sorted (cdr sorted))) - compressed)))) - -(defun PC-read-file-name-internal (string pred action) - "Extend `read-file-name-internal' to handle include files. -This is only used by " - (if (string-match "<\\([^\"<>]*\\)>?\\'" string) - (let* ((name (match-string 1 string)) - (str2 (substring string (match-beginning 0))) - (completion-table - (mapcar (lambda (x) - (format (if (string-match "/\\'" x) "<%s" "<%s>") x)) - (PC-include-file-all-completions - name (PC-include-file-path))))) - (cond - ((not completion-table) nil) - ((eq action 'lambda) (test-completion str2 completion-table nil)) - ((eq action nil) (PC-try-completion str2 completion-table nil)) - ((eq action t) (all-completions str2 completion-table nil)))) - (read-file-name-internal string pred action))) - - -(provide 'complete) - -;;; complete.el ends here diff --git a/lisp/obsolete/cust-print.el b/lisp/obsolete/cust-print.el deleted file mode 100644 index 80ded08654..0000000000 --- a/lisp/obsolete/cust-print.el +++ /dev/null @@ -1,674 +0,0 @@ -;;; cust-print.el --- handles print-level and print-circle -*- lexical-binding: t; -*- - -;; Copyright (C) 1992, 2001-2022 Free Software Foundation, Inc. - -;; Author: Daniel LaLiberte -;; Adapted-By: ESR -;; Keywords: extensions -;; Obsolete-since: 24.3 - -;; LCD Archive Entry: -;; cust-print|Daniel LaLiberte|liberte@holonexus.org -;; |Handle print-level, print-circle and more. - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This package provides a general print handler for prin1 and princ -;; that supports print-level and print-circle, and by the way, -;; print-length since the standard routines are being replaced. Also, -;; to print custom types constructed from lists and vectors, use -;; custom-print-list and custom-print-vector. See the documentation -;; strings of these variables for more details. - -;; If the results of your expressions contain circular references to -;; other parts of the same structure, the standard Emacs print -;; subroutines may fail to print with an untrappable error, -;; "Apparently circular structure being printed". If you only use cdr -;; circular lists (where cdrs of lists point back; what is the right -;; term here?), you can limit the length of printing with -;; print-length. But car circular lists and circular vectors generate -;; the above mentioned error in Emacs version 18. Version -;; 19 supports print-level, but it is often useful to get a better -;; print representation of circular and shared structures; the print-circle -;; option may be used to print more concise representations. - -;; There are three main ways to use this package. First, you may -;; replace prin1, princ, and some subroutines that use them by calling -;; install-custom-print so that any use of these functions in -;; Lisp code will be affected; you can later reset with -;; uninstall-custom-print. Second, you may temporarily install -;; these functions with the macro with-custom-print. Third, you -;; could call the custom routines directly, thus only affecting the -;; printing that requires them. - -;; Note that subroutines which call print subroutines directly will -;; not use the custom print functions. In particular, the evaluation -;; functions like eval-region call the print subroutines directly. -;; Therefore, if you evaluate (aref circ-list 0), where circ-list is a -;; circular list rather than an array, aref calls error directly which -;; will jump to the top level instead of printing the circular list. - -;; Uninterned symbols are recognized when print-circle is non-nil, -;; but they are not printed specially here. Use the cl-packages package -;; to print according to print-gensym. - -;; Obviously the right way to implement this custom-print facility is -;; in C or with hooks into the standard printer. Please volunteer -;; since I don't have the time or need. More CL-like printing -;; capabilities could be added in the future. - -;; Implementation design: we want to use the same list and vector -;; processing algorithm for all versions of prin1 and princ, since how -;; the processing is done depends on print-length, print-level, and -;; print-circle. For circle printing, a preprocessing step is -;; required before the final printing. Thanks to Jamie Zawinski -;; for motivation and algorithms. - - -;;; Code: - -(defgroup cust-print nil - "Handles print-level and print-circle." - :prefix "print-" - :group 'lisp - :group 'extensions) - -;; If using cl-packages: - -'(defpackage "cust-print" - (:nicknames "CP" "custom-print") - (:use "el") - (:export - print-level - print-circle - - custom-print-install - custom-print-uninstall - custom-print-installed-p - with-custom-print - - custom-prin1 - custom-princ - custom-prin1-to-string - custom-print - custom-format - custom-message - custom-error - - custom-printers - add-custom-printer - )) - -'(in-package cust-print) - -;; Emacs 18 doesn't have defalias. -;; Provide def for byte compiler. - -;; Variables: -;;========================================================= - -;;(defvar print-length nil -;; "*Controls how many elements of a list, at each level, are printed. -;;This is defined by emacs.") - -(defcustom print-level nil - "Controls how many levels deep a nested data object will print. - -If nil, printing proceeds recursively and may lead to -max-lisp-eval-depth being exceeded or an error may occur: -`Apparently circular structure being printed.' -Also see `print-length' and `print-circle'. - -If non-nil, components at levels equal to or greater than `print-level' -are printed simply as `#'. The object to be printed is at level 0, -and if the object is a list or vector, its top-level components are at -level 1." - :type '(choice (const nil) integer)) - - -(defcustom print-circle nil - "Controls the printing of recursive structures. - -If nil, printing proceeds recursively and may lead to -`max-lisp-eval-depth' being exceeded or an error may occur: -\"Apparently circular structure being printed.\" Also see -`print-length' and `print-level'. - -If non-nil, shared substructures anywhere in the structure are printed -with `#N=' before the first occurrence (in the order of the print -representation) and `#N#' in place of each subsequent occurrence, -where N is a positive decimal integer." - :type 'boolean) - - -(defcustom custom-print-vectors nil - "Non-nil if printing of vectors should obey `print-level' and `print-length'." - :type 'boolean) - - -;; Custom printers -;;========================================================== - -(defvar custom-printers nil - ;; e.g. '((symbolp . pkg::print-symbol)) - "An alist for custom printing of any type. -Pairs are of the form (PREDICATE . PRINTER). If PREDICATE is true -for an object, then PRINTER is called with the object. -PRINTER should print to `standard-output' using cust-print-original-princ -if the standard printer is sufficient, or cust-print-prin for complex things. -The PRINTER should return the object being printed. - -Don't modify this variable directly. Use `add-custom-printer' and -`delete-custom-printer'") -;; Should cust-print-original-princ and cust-print-prin be exported symbols? -;; Or should the standard printers functions be replaced by -;; CP ones in Emacs Lisp so that CP internal functions need not be called? - -(defun add-custom-printer (pred printer) - "Add a pair of PREDICATE and PRINTER to `custom-printers'. -Any pair that has the same PREDICATE is first removed." - (setq custom-printers (cons (cons pred printer) - (delq (assq pred custom-printers) - custom-printers))) - ;; Rather than updating here, we could wait until cust-print-top-level is called. - (cust-print-update-custom-printers)) - -(defun delete-custom-printer (pred) - "Delete the custom printer associated with PREDICATE." - (setq custom-printers (delq (assq pred custom-printers) - custom-printers)) - (cust-print-update-custom-printers)) - - -(defun cust-print-use-custom-printer (_object) - ;; Default function returns nil. - nil) - -(defun cust-print-update-custom-printers () - ;; Modify the definition of cust-print-use-custom-printer - (defalias 'cust-print-use-custom-printer - ;; We don't really want to require the byte-compiler. - ;; (byte-compile - `(lambda (object) - (cond - ,@(mapcar (function - (lambda (pair) - `((,(car pair) object) - (,(cdr pair) object)))) - custom-printers) - ;; Otherwise return nil. - (t nil) - )) - ;; ) - )) - - -;; Saving and restoring emacs printing routines. -;;==================================================== - -(defun cust-print-set-function-cell (symbol-pair) - (defalias (car symbol-pair) - (symbol-function (car (cdr symbol-pair))))) - -(defun cust-print-original-princ (_object &optional _stream) nil) ; dummy def - -;; Save emacs routines. -(if (not (fboundp 'cust-print-original-prin1)) - (mapc #'cust-print-set-function-cell - '((cust-print-original-prin1 prin1) - (cust-print-original-princ princ) - (cust-print-original-print print) - (cust-print-original-prin1-to-string prin1-to-string) - (cust-print-original-format format) - (cust-print-original-message message) - (cust-print-original-error error)))) -(declare-function cust-print-original-format "cust-print") -(declare-function cust-print-original-message "cust-print") - -(defun custom-print-install () - "Replace print functions with general, customizable, Lisp versions. -The Emacs subroutines are saved away, and you can reinstall them -by running `custom-print-uninstall'." - (interactive) - (mapc #'cust-print-set-function-cell - '((prin1 custom-prin1) - (princ custom-princ) - (print custom-print) - (prin1-to-string custom-prin1-to-string) - (format custom-format) - (message custom-message) - (error custom-error) - )) - t) - -(defun custom-print-uninstall () - "Reset print functions to their Emacs subroutines." - (interactive) - (mapc #'cust-print-set-function-cell - '((prin1 cust-print-original-prin1) - (princ cust-print-original-princ) - (print cust-print-original-print) - (prin1-to-string cust-print-original-prin1-to-string) - (format cust-print-original-format) - (message cust-print-original-message) - (error cust-print-original-error) - )) - t) - -(defalias 'custom-print-funcs-installed-p #'custom-print-installed-p) -(defun custom-print-installed-p () - "Return t if custom-print is currently installed, nil otherwise." - (eq (symbol-function 'custom-prin1) (symbol-function 'prin1))) - -(defmacro with-custom-print (&rest body) - "Temporarily install the custom print package while executing BODY." - (declare (debug t)) - `(unwind-protect - (progn - (custom-print-install) - ,@body) - (custom-print-uninstall))) -(defalias 'with-custom-print-funcs #'with-custom-print) - - -;; Lisp replacements for prin1 and princ, and for some subrs that use them -;;=============================================================== -;; - so far only the printing and formatting subrs. - -(defun custom-prin1 (object &optional stream) - "Output the printed representation of OBJECT, any Lisp object. -Quoting characters are printed when needed to make output that `read' -can handle, whenever this is possible. -Output stream is STREAM, or value of `standard-output' (which see). - -This is the custom-print replacement for the standard `prin1'. It -uses the appropriate printer depending on the values of `print-level' -and `print-circle' (which see)." - (cust-print-top-level object stream 'cust-print-original-prin1)) - - -(defun custom-princ (object &optional stream) - "Output the printed representation of OBJECT, any Lisp object. -No quoting characters are used; no delimiters are printed around -the contents of strings. -Output stream is STREAM, or value of `standard-output' (which see). - -This is the custom-print replacement for the standard `princ'." - (cust-print-top-level object stream 'cust-print-original-princ)) - - -(defun custom-prin1-to-string (object &optional noescape) - "Return a string containing the printed representation of OBJECT, -any Lisp object. Quoting characters are used when needed to make output -that `read' can handle, whenever this is possible, unless the optional -second argument NOESCAPE is non-nil. - -This is the custom-print replacement for the standard `prin1-to-string'." - (let ((buf (get-buffer-create " *custom-print-temp*"))) - ;; We must erase the buffer before printing in case an error - ;; occurred during the last prin1-to-string and we are in debugger. - (with-current-buffer buf - (erase-buffer)) - ;; We must be in the current-buffer when the print occurs. - (if noescape - (custom-princ object buf) - (custom-prin1 object buf)) - (with-current-buffer buf - (buffer-string) - ;; We could erase the buffer again, but why bother? - ))) - - -(defun custom-print (object &optional stream) - "Output the printed representation of OBJECT, with newlines around it. -Quoting characters are printed when needed to make output that `read' -can handle, whenever this is possible. -Output stream is STREAM, or value of `standard-output' (which see). - -This is the custom-print replacement for the standard `print'." - (cust-print-original-princ "\n" stream) - (custom-prin1 object stream) - (cust-print-original-princ "\n" stream)) - - -(defun custom-format (fmt &rest args) - "Format a string out of a control-string and arguments. -The first argument is a control string. It, and subsequent arguments -substituted into it, become the value, which is a string. -It may contain %s or %d or %c to substitute successive following arguments. -%s means print an argument as a string, %d means print as number in decimal, -%c means print a number as a single character. -The argument used by %s must be a string or a symbol; -the argument used by %d, %b, %o, %x or %c must be a number. - -This is the custom-print replacement for the standard `format'. It -calls the Emacs `format' after first making strings for list, -vector, or symbol args. The format specification for such args should -be `%s' in any case, so a string argument will also work. The string -is generated with `custom-prin1-to-string', which quotes quotable -characters." - (apply #'cust-print-original-format fmt - (mapcar (function (lambda (arg) - (if (or (listp arg) (vectorp arg) (symbolp arg)) - (custom-prin1-to-string arg) - arg))) - args))) - - -(defun custom-message (fmt &rest args) - "Print a one-line message at the bottom of the screen. -The first argument is a control string. -It may contain %s or %d or %c to print successive following arguments. -%s means print an argument as a string, %d means print as number in decimal, -%c means print a number as a single character. -The argument used by %s must be a string or a symbol; -the argument used by %d or %c must be a number. - -This is the custom-print replacement for the standard `message'. -See `custom-format' for the details." - ;; It doesn't work to princ the result of custom-format as in: - ;; (cust-print-original-princ (apply 'custom-format fmt args)) - ;; because the echo area requires special handling - ;; to avoid duplicating the output. - ;; cust-print-original-message does it right. - (apply #'cust-print-original-message fmt - (mapcar (function (lambda (arg) - (if (or (listp arg) (vectorp arg) (symbolp arg)) - (custom-prin1-to-string arg) - arg))) - args))) - - -(defun custom-error (fmt &rest args) - "Signal an error, making error message by passing all args to `format'. - -This is the custom-print replacement for the standard `error'. -See `custom-format' for the details." - (signal 'error (list (apply #'custom-format fmt args)))) - - - -;; Support for custom prin1 and princ -;;========================================= - -;; Defs to quiet byte-compiler. -(defvar circle-table) -(defvar cust-print-current-level) - -(defun cust-print-original-printer (_object) nil) ; One of the standard printers. -(defun cust-print-low-level-prin (_object) nil) ; Used internally. -(defun cust-print-prin (_object) nil) ; Call this to print recursively. - -(defun cust-print-top-level (object stream emacs-printer) - ;; Set up for printing. - (let ((standard-output (or stream standard-output)) - ;; circle-table will be non-nil if anything is circular. - (circle-table (and print-circle - (cust-print-preprocess-circle-tree object))) - (cust-print-current-level (or print-level -1))) - - (defalias 'cust-print-original-printer emacs-printer) - (defalias 'cust-print-low-level-prin - (cond - ((or custom-printers - circle-table - print-level ; comment out for version 19 - ;; Emacs doesn't use print-level or print-length - ;; for vectors, but custom-print can. - (if custom-print-vectors - (or print-level print-length))) - 'cust-print-print-object) - (t 'cust-print-original-printer))) - (defalias 'cust-print-prin - (if circle-table 'cust-print-print-circular 'cust-print-low-level-prin)) - - (cust-print-prin object) - object)) - - -(defun cust-print-print-object (object) - ;; Test object type and print accordingly. - ;; Could be called as either cust-print-low-level-prin or cust-print-prin. - (cond - ((null object) (cust-print-original-printer object)) - ((cust-print-use-custom-printer object) object) - ((consp object) (cust-print-list object)) - ((vectorp object) (cust-print-vector object)) - ;; All other types, just print. - (t (cust-print-original-printer object)))) - - -(defun cust-print-print-circular (object) - ;; Printer for `prin1' and `princ' that handles circular structures. - ;; If OBJECT appears multiply, and has not yet been printed, - ;; prefix with label; if it has been printed, use `#N#' instead. - ;; Otherwise, print normally. - (let ((tag (assq object circle-table))) - (if tag - (let ((id (cdr tag))) - (if (> id 0) - (progn - ;; Already printed, so just print id. - (cust-print-original-princ "#") - (cust-print-original-princ id) - (cust-print-original-princ "#")) - ;; Not printed yet, so label with id and print object. - (setcdr tag (- id)) ; mark it as printed - (cust-print-original-princ "#") - (cust-print-original-princ (- id)) - (cust-print-original-princ "=") - (cust-print-low-level-prin object) - )) - ;; Not repeated in structure. - (cust-print-low-level-prin object)))) - - -;;================================================ -;; List and vector processing for print functions. - -(defun cust-print-list (list) - ;; Print a list using print-length, print-level, and print-circle. - (if (= cust-print-current-level 0) - (cust-print-original-princ "#") - (let ((cust-print-current-level (1- cust-print-current-level))) - (cust-print-original-princ "(") - (let ((length (or print-length 0))) - - ;; Print the first element always (even if length = 0). - (cust-print-prin (car list)) - (setq list (cdr list)) - (if list (cust-print-original-princ " ")) - (setq length (1- length)) - - ;; Print the rest of the elements. - (while (and list (/= 0 length)) - (if (and (listp list) - (not (assq list circle-table))) - (progn - (cust-print-prin (car list)) - (setq list (cdr list))) - - ;; cdr is not a list, or it is in circle-table. - (cust-print-original-princ ". ") - (cust-print-prin list) - (setq list nil)) - - (setq length (1- length)) - (if list (cust-print-original-princ " "))) - - (if (and list (= length 0)) (cust-print-original-princ "...")) - (cust-print-original-princ ")")))) - list) - - -(defun cust-print-vector (vector) - ;; Print a vector according to print-length, print-level, and print-circle. - (if (= cust-print-current-level 0) - (cust-print-original-princ "#") - (let ((cust-print-current-level (1- cust-print-current-level)) - (i 0) - (len (length vector))) - (cust-print-original-princ "[") - - (if print-length - (setq len (min print-length len))) - ;; Print the elements - (while (< i len) - (cust-print-prin (aref vector i)) - (setq i (1+ i)) - (if (< i (length vector)) (cust-print-original-princ " "))) - - (if (< i (length vector)) (cust-print-original-princ "...")) - (cust-print-original-princ "]") - )) - vector) - - - -;; Circular structure preprocessing -;;================================== - -(defun cust-print-preprocess-circle-tree (object) - ;; Fill up the table. - (let (;; Table of tags for each object in an object to be printed. - ;; A tag is of the form: - ;; ( ) - ;; The id-number is generated after the entire table has been computed. - ;; During walk through, the real circle-table lives in the cdr so we - ;; can use setcdr to add new elements instead of having to setq the - ;; variable sometimes (poor man's locf). - (circle-table (list nil))) - (cust-print-walk-circle-tree object) - - ;; Reverse table so it is in the order that the objects will be printed. - ;; This pass could be avoided if we always added to the end of the - ;; table with setcdr in walk-circle-tree. - (setcdr circle-table (nreverse (cdr circle-table))) - - ;; Walk through the table, assigning id-numbers to those - ;; objects which will be printed using #N= syntax. Delete those - ;; objects which will be printed only once (to speed up assq later). - (let ((rest circle-table) - (id -1)) - (while (cdr rest) - (let ((tag (car (cdr rest)))) - (cond ((cdr tag) - (setcdr tag id) - (setq id (1- id)) - (setq rest (cdr rest))) - ;; Else delete this object. - (t (setcdr rest (cdr (cdr rest)))))) - )) - ;; Drop the car. - (cdr circle-table) - )) - - - -(defun cust-print-walk-circle-tree (object) - (let (read-equivalent-p tag) - (while object - (setq read-equivalent-p - (or (numberp object) - (and (symbolp object) - ;; Check if it is uninterned. - (eq object (intern-soft (symbol-name object))))) - tag (and (not read-equivalent-p) - (assq object (cdr circle-table)))) - (cond (tag - ;; Seen this object already, so note that. - (setcdr tag t)) - - ((not read-equivalent-p) - ;; Add a tag for this object. - (setcdr circle-table - (cons (list object) - (cdr circle-table))))) - (setq object - (cond - (tag ;; No need to descend since we have already. - nil) - - ((consp object) - ;; Walk the car of the list recursively. - (cust-print-walk-circle-tree (car object)) - ;; But walk the cdr with the above while loop - ;; to avoid problems with max-lisp-eval-depth. - ;; And it should be faster than recursion. - (cdr object)) - - ((vectorp object) - ;; Walk the vector. - (let ((i (length object)) - (j 0)) - (while (< j i) - (cust-print-walk-circle-tree (aref object j)) - (setq j (1+ j)))))))))) - - -;; Example. -;;======================================= - -'(progn - (progn - ;; Create some circular structures. - (setq circ-sym (let ((x (make-symbol "FOO"))) (list x x))) - (setq circ-list (list 'a 'b (vector 1 2 3 4) 'd 'e 'f)) - (setcar (nthcdr 3 circ-list) circ-list) - (aset (nth 2 circ-list) 2 circ-list) - (setq dotted-circ-list (list 'a 'b 'c)) - (setcdr (cdr (cdr dotted-circ-list)) dotted-circ-list) - (setq circ-vector (vector 1 2 3 4 (list 'a 'b 'c 'd) 6 7)) - (aset circ-vector 5 (make-symbol "-gensym-")) - (setcar (cdr (aref circ-vector 4)) (aref circ-vector 5)) - nil) - - (install-custom-print) - ;; (setq print-circle t) - - (let ((print-circle t)) - (or (equal (prin1-to-string circ-list) "#1=(a b [1 2 #1# 4] #1# e f)") - (error "Circular object with array printing"))) - - (let ((print-circle t)) - (or (equal (prin1-to-string dotted-circ-list) "#1=(a b c . #1#)") - (error "Circular object with array printing"))) - - (let* ((print-circle t) - (x (list 'p 'q)) - (y (list (list 'a 'b) x 'foo x))) - (setcdr (cdr (cdr (cdr y))) (cdr y)) - (or (equal (prin1-to-string y) "((a b) . #1=(#2=(p q) foo #2# . #1#))" - ) - (error "Circular list example from CL manual"))) - - (let ((print-circle nil)) - ;; cl-packages.el is required to print uninterned symbols like #:FOO. - ;; (require 'cl-packages) - (or (equal (prin1-to-string circ-sym) "(#:FOO #:FOO)") - (error "Uninterned symbols in list"))) - (let ((print-circle t)) - (or (equal (prin1-to-string circ-sym) "(#1=FOO #1#)") - (error "Circular uninterned symbols in list"))) - - (uninstall-custom-print) - ) - -(provide 'cust-print) - -;;; cust-print.el ends here diff --git a/lisp/obsolete/erc-hecomplete.el b/lisp/obsolete/erc-hecomplete.el deleted file mode 100644 index 79ccf80440..0000000000 --- a/lisp/obsolete/erc-hecomplete.el +++ /dev/null @@ -1,218 +0,0 @@ -;;; erc-hecomplete.el --- Provides Nick name completion for ERC -*- lexical-binding: t; -*- - -;; Copyright (C) 2001-2002, 2004, 2006-2022 Free Software Foundation, -;; Inc. - -;; Author: Alex Schroeder -;; URL: https://www.emacswiki.org/cgi-bin/wiki.pl?ErcCompletion -;; Obsolete-since: 24.1 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This file is considered obsolete. It is recommended to use -;; completion from erc-pcomplete instead. - -;; This file is based on hippie-expand, while the new file is based on -;; pcomplete. - -;;; Code: - -(require 'erc) -(require 'erc-match); for erc-pals -(require 'hippie-exp); for the hippie expand stuff - -;;;###autoload (autoload 'erc-hecomplete-mode "erc-hecomplete" nil t) -(define-erc-module hecomplete nil - "Complete nick at point." - ((add-hook 'erc-complete-functions #'erc-hecomplete)) - ((remove-hook 'erc-complete-functions #'erc-hecomplete))) - -(defun erc-hecomplete () - "Complete nick at point. -See `erc-try-complete-nick' for more technical info. -This function is obsolete, use `erc-pcomplete' instead." - (interactive) - (let ((hippie-expand-try-functions-list '(erc-try-complete-nick))) - (hippie-expand nil))) - -(defgroup erc-hecomplete nil - "Nick completion. It is recommended to use `erc-pcomplete' instead." - :group 'erc) - -(defcustom erc-nick-completion 'all - "Determine how the list of nicks is determined during nick completion. -See `erc-complete-nick' for information on how to activate this. - -pals: Use `erc-pals'. -all: All channel members. - -You may also provide your own function that returns a list of completions. -One example is `erc-nick-completion-exclude-myself', -or you may use an arbitrary lisp expression." - :type '(choice (const :tag "List of pals" pals) - (const :tag "All channel members" all) - (const :tag "All channel members except yourself" - erc-nick-completion-exclude-myself) - (repeat :tag "List" (string :tag "Nick")) - function - sexp)) - -(defcustom erc-nick-completion-ignore-case t - "Non-nil means don't consider case significant in nick completion. -Case will be automatically corrected when non-nil. -For instance if you type \"dely TAB\" the word completes and changes to -\"delYsid\"." - :type 'boolean) - -(defun erc-nick-completion-exclude-myself () - "Get a list of all the channel members except you. - -This function returns a list of all the members in the channel, except -your own nick. This way if you're named foo and someone is called foobar, -typing \"f o TAB\" will directly give you foobar. Use this with -`erc-nick-completion'." - (remove - (erc-current-nick) - (erc-get-channel-nickname-list))) - -(defcustom erc-nick-completion-postfix ": " - "When `erc-complete' is used in the first word after the prompt, -add this string when a unique expansion was found." - :type 'string) - -(defun erc-command-list () - "Return a list of strings of the defined user commands." - (let ((case-fold-search nil)) - (mapcar (lambda (x) - (concat "/" (downcase (substring (symbol-name x) 8)))) - (apropos-internal "erc-cmd-[A-Z]+")))) - -(defun erc-try-complete-nick (old) - "Complete nick at point. -This is a function to put on `hippie-expand-try-functions-list'. -Then use \\[hippie-expand] to expand nicks. -The type of completion depends on `erc-nick-completion'." - (try-complete-erc-nick old (cond ((eq erc-nick-completion 'pals) erc-pals) - ((eq erc-nick-completion 'all) - (append - (erc-get-channel-nickname-list) - (erc-command-list))) - ((functionp erc-nick-completion) - (funcall erc-nick-completion)) - (t erc-nick-completion)))) - -(defvar try-complete-erc-nick-window-configuration nil - "The window configuration for `try-complete-erc-nick'. -When called the first time, a window config is stored here, -and when completion is done, the window config is restored -from here. See `try-complete-erc-nick-restore' and -`try-complete-erc-nick'.") - -(defun try-complete-erc-nick-restore () - "Restore window configuration." - (if (not try-complete-erc-nick-window-configuration) - (when (get-buffer "*Completions*") - (delete-windows-on "*Completions*")) - (set-window-configuration - try-complete-erc-nick-window-configuration) - (setq try-complete-erc-nick-window-configuration nil))) - -(defun try-complete-erc-nick (old completions) - "Try to complete current word depending on `erc-try-complete-nick'. -The argument OLD has to be nil the first call of this function, and t -for subsequent calls (for further possible completions of the same -string). It returns t if a new completion is found, nil otherwise. The -second argument COMPLETIONS is a list of completions to use. Actually, -it is only used when OLD is nil. It will be copied to `he-expand-list' -on the first call. After that, it is no longer used. -Window configurations are stored in -`try-complete-erc-nick-window-configuration'." - (let (expansion - final - (alist (if (consp (car completions)) - completions - (mapcar (lambda (s) - (if (and (erc-complete-at-prompt) - (and (not (= (length s) 0)) - (not (eq (elt s 0) ?/)))) - (list (concat s erc-nick-completion-postfix)) - (list (concat s " ")))) - completions))) ; make alist if required - (completion-ignore-case erc-nick-completion-ignore-case)) - (he-init-string (he-dabbrev-beg) (point)) - ;; If there is a string to complete, complete it using alist. - ;; expansion is the possible expansion, or t. If expansion is t - ;; or if expansion is the "real" thing, we are finished (final is - ;; t). Take care -- expansion can also be nil! - (unless (string= he-search-string "") - (setq expansion (try-completion he-search-string alist) - final (or (eq t expansion) - (and expansion - (eq t (try-completion expansion alist)))))) - (cond ((not expansion) - ;; There is no expansion at all. - (try-complete-erc-nick-restore) - (he-reset-string) - nil) - ((eq t expansion) - ;; The user already has the correct expansion. - (try-complete-erc-nick-restore) - (he-reset-string) - t) - ((and old (string= expansion he-search-string)) - ;; This is the second time around and nothing changed, - ;; ie. the user tried to expand something incomplete - ;; without making a choice -- hitting TAB twice, for - ;; example. - (try-complete-erc-nick-restore) - (he-reset-string) - nil) - (final - ;; The user has found the correct expansion. - (try-complete-erc-nick-restore) - (he-substitute-string expansion) - t) - (t - ;; We found something but we are not finished. Show a - ;; completions buffer. Substitute what we found and return - ;; t. - (setq try-complete-erc-nick-window-configuration - (current-window-configuration)) - (with-output-to-temp-buffer "*Completions*" - (display-completion-list (all-completions he-search-string alist))) - (he-substitute-string expansion) - t)))) - -(defun erc-at-beginning-of-line-p (point &optional bol-func) - (save-excursion - (funcall (or bol-func - 'erc-bol)) - (equal point (point)))) - -(defun erc-complete-at-prompt () - "Return t if point is directly after `erc-prompt' when doing completion." - (erc-at-beginning-of-line-p (he-dabbrev-beg))) - -(provide 'erc-hecomplete) - -;;; erc-hecomplete.el ends here -;; -;; Local Variables: -;; indent-tabs-mode: t -;; tab-width: 8 -;; End: diff --git a/lisp/obsolete/mailpost.el b/lisp/obsolete/mailpost.el deleted file mode 100644 index 5b3a76e2f7..0000000000 --- a/lisp/obsolete/mailpost.el +++ /dev/null @@ -1,101 +0,0 @@ -;;; mailpost.el --- RMAIL coupler to /usr/uci/post mailer -*- lexical-binding: t; -*- - -;; This is in the public domain -;; since Delp distributed it in 1986 without a copyright notice. - -;; This file is part of GNU Emacs. - -;; Author: Gary Delp -;; Maintainer: emacs-devel@gnu.org -;; Created: 13 Jan 1986 -;; Keywords: mail -;; Obsolete-since: 24.3 - -;;; Commentary: - -;; Yet another mail interface. this for the rmail system to provide -;; the missing sendmail interface on systems without /usr/lib/sendmail, -;; but with /usr/uci/post. - -;;; Code: - -(require 'mailalias) -(require 'sendmail) - -;; (setq send-mail-function 'post-mail-send-it) - -(defun post-mail-send-it () - "The MH -post interface for `rmail-mail' to call. -To use it, include \"(setq send-mail-function \\='post-mail-send-it)\" in -site-init." - (let ((errbuf (if mail-interactive - (generate-new-buffer " post-mail errors") - 0)) - temfile - (tembuf (generate-new-buffer " post-mail temp")) - (case-fold-search nil) - delimline - (mailbuf (current-buffer))) - (unwind-protect - (with-current-buffer tembuf - (erase-buffer) - (insert-buffer-substring mailbuf) - (goto-char (point-max)) - ;; require one newline at the end. - (or (= (preceding-char) ?\n) - (insert ?\n)) - ;; Change header-delimiter to be what post-mail expects. - (mail-sendmail-undelimit-header) - (setq delimline (point-marker)) - (if mail-aliases - (expand-mail-aliases (point-min) delimline)) - (goto-char (point-min)) - ;; ignore any blank lines in the header - (while (and (re-search-forward "\n\n\n*" delimline t) - (< (point) delimline)) - (replace-match "\n")) - ;; Find and handle any Fcc fields. - (let ((case-fold-search t)) - (goto-char (point-min)) - (if (re-search-forward "^Fcc:" delimline t) - (mail-do-fcc delimline)) - ;; If there is a From and no Sender, put it a Sender. - (goto-char (point-min)) - (and (re-search-forward "^From:" delimline t) - (not (save-excursion - (goto-char (point-min)) - (re-search-forward "^Sender:" delimline t))) - (progn - (forward-line 1) - (insert "Sender: " (user-login-name) "\n"))) - ;; don't send out a blank subject line - (goto-char (point-min)) - (if (re-search-forward "^Subject:[ \t]*\n" delimline t) - (replace-match "")) - (if mail-interactive - (with-current-buffer errbuf - (erase-buffer)))) - (with-file-modes 384 (setq temfile (make-temp-file ",rpost"))) - (apply #'call-process - (append (list (if (boundp 'post-mail-program) - post-mail-program - "/usr/uci/lib/mh/post") - nil errbuf nil - "-nofilter" "-msgid") - (if mail-interactive '("-watch") '("-nowatch")) - (list temfile))) - (if mail-interactive - (with-current-buffer errbuf - (goto-char (point-min)) - (while (re-search-forward "\n\n* *" nil t) - (replace-match "; ")) - (if (not (zerop (buffer-size))) - (error "Sending...failed to %s" - (buffer-substring (point-min) (point-max))))))) - (kill-buffer tembuf) - (if (bufferp errbuf) - (switch-to-buffer errbuf))))) - -(provide 'mailpost) - -;;; mailpost.el ends here diff --git a/lisp/obsolete/mouse-sel.el b/lisp/obsolete/mouse-sel.el deleted file mode 100644 index 3eacac65fb..0000000000 --- a/lisp/obsolete/mouse-sel.el +++ /dev/null @@ -1,731 +0,0 @@ -;;; mouse-sel.el --- multi-click selection support -*- lexical-binding: t; -*- - -;; Copyright (C) 1993-1995, 2001-2022 Free Software Foundation, Inc. - -;; Author: Mike Williams -;; Keywords: mouse -;; Obsolete-since: 24.3 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This module provides multi-click mouse support for GNU Emacs versions -;; 19.18 and later. I've tried to make it behave more like standard X -;; clients (eg. xterm) than the default Emacs 19 mouse selection handlers. -;; Basically: -;; -;; * Clicking mouse-1 starts (cancels) selection, dragging extends it. -;; -;; * Clicking or dragging mouse-3 extends the selection as well. -;; -;; * Double-clicking on word constituents selects words. -;; Double-clicking on symbol constituents selects symbols. -;; Double-clicking on quotes or parentheses selects sexps. -;; Double-clicking on whitespace selects whitespace. -;; Triple-clicking selects lines. -;; Quad-clicking selects paragraphs. -;; -;; * Selecting sets the region & X primary selection, but does NOT affect -;; the kill-ring. Because the mouse handlers set the primary selection -;; directly, mouse-sel sets the variables interprogram-cut-function -;; and interprogram-paste-function to nil. -;; -;; * Clicking mouse-2 inserts the contents of the primary selection at -;; the mouse position (or point, if mouse-yank-at-point is non-nil). -;; -;; * Pressing mouse-2 while selecting or extending copies selection -;; to the kill ring. Pressing mouse-1 or mouse-3 kills it. -;; -;; * Double-clicking mouse-3 also kills selection. -;; -;; * M-mouse-1, M-mouse-2 & M-mouse-3 work similarly to mouse-1, mouse-2 -;; & mouse-3, but operate on the X secondary selection rather than the -;; primary selection and region. -;; -;; This module requires my thingatpt.el module, which it uses to find the -;; bounds of words, lines, sexps, etc. -;; -;; Thanks to KevinB@bartley.demon.co.uk for his useful input. -;; -;;--- Customization ------------------------------------------------------- -;; -;; * You may want to use none or more of following: -;; -;; ;; Enable region highlight -;; (transient-mark-mode 1) -;; -;; ;; But only in the selected window -;; (setq highlight-nonselected-windows nil) -;; -;; ;; Enable pending-delete -;; (delete-selection-mode 1) -;; -;; * You can control the way mouse-sel binds its keys by setting the value -;; of mouse-sel-default-bindings before loading mouse-sel. -;; -;; (a) If mouse-sel-default-bindings = t (the default) -;; -;; Mouse sets and insert selection -;; mouse-1 mouse-select -;; mouse-2 mouse-insert-selection -;; mouse-3 mouse-extend -;; -;; Selection/kill-ring interaction is disabled -;; interprogram-cut-function = nil -;; interprogram-paste-function = nil -;; -;; (b) If mouse-sel-default-bindings = 'interprogram-cut-paste -;; -;; Mouse sets selection, and pastes from kill-ring -;; mouse-1 mouse-select -;; mouse-2 mouse-insert-selection -;; mouse-3 mouse-extend -;; In this mode, mouse-insert-selection just calls mouse-yank-at-click. -;; -;; Selection/kill-ring interaction is retained -;; interprogram-cut-function = gui-select-text -;; interprogram-paste-function = gui-selection-value -;; -;; What you lose is the ability to select some text in -;; delete-selection-mode and yank over the top of it. -;; -;; (c) If mouse-sel-default-bindings = nil, no bindings are made. -;; -;; * By default, mouse-insert-selection (mouse-2) inserts the selection at -;; the mouse position. You can tell it to insert at point instead with: -;; -;; (setq mouse-yank-at-point t) -;; -;; * I like to leave point at the end of the region nearest to where the -;; mouse was, even though this makes region highlighting mis-leading (the -;; cursor makes it look like one extra character is selected). You can -;; disable this behavior with: -;; -;; (setq mouse-sel-leave-point-near-mouse nil) -;; -;; * By default, mouse-select cycles the click count after 4 clicks. That -;; is, clicking mouse-1 five times has the same effect as clicking it -;; once, clicking six times has the same effect as clicking twice, etc. -;; Disable this behavior with: -;; -;; (setq mouse-sel-cycle-clicks nil) -;; -;; * The variables mouse-sel-{set,get}-selection-function control how the -;; selection is handled. Under X Windows, these variables default so -;; that the X primary selection is used. Under other windowing systems, -;; alternate functions are used, which simply store the selection value -;; in a variable. - -;;; Code: - -(require 'mouse) -(require 'thingatpt) - -;;=== User Variables ====================================================== - -(defgroup mouse-sel nil - "Mouse selection enhancement." - :group 'mouse) - -(defcustom mouse-sel-leave-point-near-mouse t - "Leave point near last mouse position. -If non-nil, \\[mouse-select] and \\[mouse-extend] will leave point at the end -of the region nearest to where the mouse last was. -If nil, point will always be placed at the beginning of the region." - :type 'boolean) - -(defcustom mouse-sel-cycle-clicks t - "If non-nil, \\[mouse-select] cycles the click-counts after 4 clicks." - :type 'boolean) - -(defcustom mouse-sel-default-bindings t - "Control mouse bindings." - :type '(choice (const :tag "none" nil) - (const :tag "cut and paste" interprogram-cut-paste) - (other :tag "default bindings" t))) - -;;=== Key bindings ======================================================== - -(defconst mouse-sel-bound-events - '(;; Primary selection bindings. - ;; - ;; Bind keys to `ignore' instead of unsetting them because modes may - ;; bind `down-mouse-1', for instance, without binding `mouse-1'. - ;; If we unset `mouse-1', this leads to a bitch_at_user when the - ;; mouse goes up because no matching binding is found for that. - ([mouse-1] . ignore) - ([drag-mouse-1] . ignore) - ([mouse-3] . ignore) - ([down-mouse-1] . mouse-select) - ([down-mouse-3] . mouse-extend) - ([mouse-2] . mouse-insert-selection) - ;; Secondary selection bindings. - ([M-mouse-1] . ignore) - ([M-drag-mouse-1] . ignore) - ([M-mouse-3] . ignore) - ([M-down-mouse-1] . mouse-select-secondary) - ([M-mouse-2] . mouse-insert-secondary) - ([M-down-mouse-3] . mouse-extend-secondary)) - "An alist of events that `mouse-sel-mode' binds.") - -;;=== User Command ======================================================== - -(defvar mouse-sel-original-bindings nil) - -(defalias 'mouse-sel--ignore #'ignore) - -;;;###autoload -(define-minor-mode mouse-sel-mode - "Toggle Mouse Sel mode. - -Mouse Sel mode is a global minor mode. When enabled, mouse -selection is enhanced in various ways: - -- Double-clicking on symbol constituents selects symbols. -Double-clicking on quotes or parentheses selects sexps. -Double-clicking on whitespace selects whitespace. -Triple-clicking selects lines. -Quad-clicking selects paragraphs. - -- Selecting sets the region & X primary selection, but does NOT affect -the `kill-ring', nor do the kill-ring functions change the X selection. -Because the mouse handlers set the primary selection directly, -mouse-sel sets the variables `interprogram-cut-function' and -`interprogram-paste-function' to nil. - -- Clicking mouse-2 inserts the contents of the primary selection at -the mouse position (or point, if `mouse-yank-at-point' is non-nil). - -- mouse-2 while selecting or extending copies selection to the -kill ring; mouse-1 or mouse-3 kills it." - :global t - (if mouse-sel-mode - (progn - ;; If mouse-2 has never been done by the user, initialize the - ;; `event-kind' property to ensure that `follow-link' clicks - ;; are interpreted correctly. - (put 'mouse-2 'event-kind 'mouse-click) - (add-hook 'x-lost-selection-functions #'mouse-sel-lost-selection-hook) - (when mouse-sel-default-bindings - ;; Save original bindings and replace them with new ones. - (setq mouse-sel-original-bindings - (mapcar (lambda (binding) - (let ((event (car binding))) - (prog1 (cons event (lookup-key global-map event)) - (global-set-key event (cdr binding))))) - mouse-sel-bound-events)) - ;; Update interprogram functions. - (unless (eq mouse-sel-default-bindings 'interprogram-cut-paste) - (add-function :override interprogram-cut-function - #'mouse-sel--ignore) - (add-function :override interprogram-paste-function - #'mouse-sel--ignore)))) - - ;; Restore original bindings - (remove-hook 'x-lost-selection-functions #'mouse-sel-lost-selection-hook) - (dolist (binding mouse-sel-original-bindings) - (global-set-key (car binding) (cdr binding))) - ;; Restore the old values of these variables, - ;; only if they were actually saved previously. - (remove-function interprogram-cut-function #'mouse-sel--ignore) - (remove-function interprogram-paste-function #'mouse-sel--ignore))) - -(make-obsolete 'mouse-sel-mode "use the normal mouse modes" "24.3") - -;;=== Internal Variables/Constants ======================================== - -(defvar mouse-sel-primary-thing nil - "Type of PRIMARY selection in current buffer.") -(make-variable-buffer-local 'mouse-sel-primary-thing) - -(defvar mouse-sel-secondary-thing nil - "Type of SECONDARY selection in current buffer.") -(make-variable-buffer-local 'mouse-sel-secondary-thing) - -;; Ensure that secondary overlay is defined -(unless (overlayp mouse-secondary-overlay) - (setq mouse-secondary-overlay (make-overlay 1 1)) - (overlay-put mouse-secondary-overlay 'face 'secondary-selection)) - -(defconst mouse-sel-primary-overlay - (let ((ol (make-overlay (point-min) (point-min)))) - (delete-overlay ol) - (overlay-put ol 'face 'region) - ol) - "An overlay which records the current primary selection. -This is used by Mouse Sel mode only.") - -(defconst mouse-sel-selection-alist - '((PRIMARY mouse-sel-primary-overlay mouse-sel-primary-thing) - (SECONDARY mouse-secondary-overlay mouse-sel-secondary-thing)) - "Alist associating selections with variables. -Each element is of the form: - - (SELECTION-NAME OVERLAY-SYMBOL SELECTION-THING-SYMBOL) - -where SELECTION-NAME = name of selection - OVERLAY-SYMBOL = name of variable containing overlay to use - SELECTION-THING-SYMBOL = name of variable where the current selection - type for this selection should be stored.") - -(defvar mouse-sel-set-selection-function - (if (eq mouse-sel-default-bindings 'interprogram-cut-paste) - 'gui-set-selection - (lambda (selection value) - (if (eq selection 'PRIMARY) - (gui-select-text value) - (gui-set-selection selection value)))) - "Function to call to set selection. -Called with two arguments: - - SELECTION, the name of the selection concerned, and - VALUE, the text to store. - -This sets the selection, unless `mouse-sel-default-bindings' -is `interprogram-cut-paste'.") - - -(defvar mouse-sel-get-selection-function - (lambda (selection) - (if (eq selection 'PRIMARY) - (or (gui-selection-value) - (bound-and-true-p x-last-selected-text-primary) - gui--last-selected-text-primary) - (gui-get-selection selection))) - "Function to call to get the selection. -Called with one argument: - - SELECTION: the name of the selection concerned.") - -;;=== Support/access functions ============================================ - -(defun mouse-sel-determine-selection-thing (nclicks) - "Determine what `thing' `mouse-sel' should operate on. -The first argument is NCLICKS, is the number of consecutive -mouse clicks at the same position. - -Double-clicking on word constituents selects words. -Double-clicking on symbol constituents selects symbols. -Double-clicking on quotes or parentheses selects sexps. -Double-clicking on whitespace selects whitespace. -Triple-clicking selects lines. -Quad-clicking selects paragraphs. - -Feel free to re-define this function to support your own desired -multi-click semantics." - (let* ((next-char (char-after (point))) - (char-syntax (if next-char (char-syntax next-char)))) - (if mouse-sel-cycle-clicks - (setq nclicks (1+ (% (1- nclicks) 4)))) - (cond - ((= nclicks 1) nil) - ((= nclicks 3) 'line) - ((>= nclicks 4) 'paragraph) - ((memq char-syntax '(?\( ?\) ?\" ?')) 'sexp) - ((memq next-char '(?\s ?\t ?\n)) 'whitespace) - ((eq char-syntax ?_) 'symbol) - ((eq char-syntax ?w) 'word)))) - -(defun mouse-sel-set-selection (selection value) - "Set the specified SELECTION to VALUE." - (if mouse-sel-set-selection-function - (funcall mouse-sel-set-selection-function selection value) - (put 'mouse-sel-internal-selection selection value))) - -(defun mouse-sel-get-selection (selection) - "Get the value of the specified SELECTION." - (if mouse-sel-get-selection-function - (funcall mouse-sel-get-selection-function selection) - (get 'mouse-sel-internal-selection selection))) - -(defun mouse-sel-selection-overlay (selection) - "Return overlay corresponding to SELECTION." - (let ((symbol (nth 1 (assoc selection mouse-sel-selection-alist)))) - (or symbol (error "No overlay corresponding to %s selection" selection)) - (symbol-value symbol))) - -(defun mouse-sel-selection-thing (selection) - "Return overlay corresponding to SELECTION." - (let ((symbol (nth 2 (assoc selection mouse-sel-selection-alist)))) - (or symbol (error "No symbol corresponding to %s selection" selection)) - symbol)) - -(defun mouse-sel-region-to-primary (orig-window) - "Convert region to PRIMARY overlay and deactivate region. -Argument ORIG-WINDOW specifies the window the cursor was in when the -originating command was issued, and is used to determine whether the -region was visible or not." - (if transient-mark-mode - (let ((overlay (mouse-sel-selection-overlay 'PRIMARY))) - (cond - ((and mark-active - (or highlight-nonselected-windows - (eq orig-window (selected-window)))) - ;; Region was visible, so convert region to overlay - (move-overlay overlay (region-beginning) (region-end) - (current-buffer))) - ((eq orig-window (selected-window)) - ;; Point was visible, so set overlay at point - (move-overlay overlay (point) (point) (current-buffer))) - (t - ;; Nothing was visible, so remove overlay - (delete-overlay overlay))) - (setq mark-active nil)))) - -(defun mouse-sel-primary-to-region (&optional direction) - "Convert PRIMARY overlay to region. -Optional argument DIRECTION specifies the mouse drag direction: a value of -1 indicates that the mouse was dragged left-to-right, otherwise it was -dragged right-to-left." - (let* ((overlay (mouse-sel-selection-overlay 'PRIMARY)) - (start (overlay-start overlay)) - (end (overlay-end overlay))) - (if (eq start end) - (progn - (if start (goto-char start)) - (deactivate-mark)) - (if (and mouse-sel-leave-point-near-mouse (eq direction 1)) - (progn - (goto-char end) - (push-mark start 'nomsg 'active)) - (goto-char start) - (push-mark end 'nomsg 'active))) - (if transient-mark-mode (delete-overlay overlay)))) - -(defmacro mouse-sel-eval-at-event-end (event &rest forms) - "Evaluate forms at mouse position. -Move to the end position of EVENT, execute FORMS, and restore original -point and window." - `(let ((posn (event-end ,event))) - (if posn (mouse-minibuffer-check ,event)) - (if (and posn (not (windowp (posn-window posn)))) - (error "Cursor not in text area of window")) - (let (orig-window orig-point-marker) - (setq orig-window (selected-window)) - (if posn (select-window (posn-window posn))) - (setq orig-point-marker (point-marker)) - (if (and posn (numberp (posn-point posn))) - (goto-char (posn-point posn))) - (unwind-protect - (progn - ,@forms) - (goto-char (marker-position orig-point-marker)) - (move-marker orig-point-marker nil) - (select-window orig-window))))) - -(put 'mouse-sel-eval-at-event-end 'lisp-indent-hook 1) - -;;=== Select ============================================================== - -(defun mouse-select (event) - "Set region/selection using the mouse. - -Click sets point & mark to click position. -Dragging extends region/selection. - -Multi-clicking selects word/lines/paragraphs, as determined by -`mouse-sel-determine-selection-thing'. - -Clicking mouse-2 while selecting copies selected text to the kill-ring. -Clicking mouse-1 or mouse-3 kills the selected text. - -This should be bound to a down-mouse event." - (interactive "@e") - (let (select) - (unwind-protect - (setq select (mouse-select-internal 'PRIMARY event)) - (if (and select (listp select)) - (push (cons 'mouse-2 (cdr event)) unread-command-events) - (mouse-sel-primary-to-region select))))) - -(defun mouse-select-secondary (event) - "Set secondary selection using the mouse. - -Click sets the start of the secondary selection to click position. -Dragging extends the secondary selection. - -Multi-clicking selects word/lines/paragraphs, as determined by -`mouse-sel-determine-selection-thing'. - -Clicking mouse-2 while selecting copies selected text to the kill-ring. -Clicking mouse-1 or mouse-3 kills the selected text. - -This should be bound to a down-mouse event." - (interactive "e") - (mouse-select-internal 'SECONDARY event)) - -(defun mouse-select-internal (selection event) - "Set SELECTION using the mouse, with EVENT as the initial down-event. -Normally, this returns the direction in which the selection was -made: a value of 1 indicates that the mouse was dragged -left-to-right, otherwise it was dragged right-to-left. - -However, if `mouse-1-click-follows-link' is non-nil and the -subsequent mouse events specify following a link, this returns -the final mouse-event. In that case, the selection is not set." - (mouse-sel-eval-at-event-end event - (let ((thing-symbol (mouse-sel-selection-thing selection)) - (overlay (mouse-sel-selection-overlay selection))) - (set thing-symbol - (mouse-sel-determine-selection-thing (event-click-count event))) - (let ((object-bounds (bounds-of-thing-at-point - (symbol-value thing-symbol)))) - (if object-bounds - (progn - (move-overlay overlay - (car object-bounds) (cdr object-bounds) - (current-buffer))) - (move-overlay overlay (point) (point) (current-buffer))))) - (catch 'follow-link - (mouse-extend-internal selection event t)))) - -;;=== Extend ============================================================== - -(defun mouse-extend (event) - "Extend region/selection using the mouse." - (interactive "e") - (let ((orig-window (selected-window)) - direction) - (select-window (posn-window (event-end event))) - (unwind-protect - (progn - (mouse-sel-region-to-primary orig-window) - (setq direction (mouse-extend-internal 'PRIMARY event))) - (mouse-sel-primary-to-region direction)))) - -(defun mouse-extend-secondary (event) - "Extend secondary selection using the mouse." - (interactive "e") - (save-window-excursion - (mouse-extend-internal 'SECONDARY event))) - -(defun mouse-extend-internal (selection &optional initial-event no-process) - "Extend specified SELECTION using the mouse. -Track mouse-motion events, adjusting the SELECTION appropriately. -Optional argument INITIAL-EVENT specifies an initial down-mouse event. -Optional argument NO-PROCESS means not to process the initial -event. - -See documentation for mouse-select-internal for more details." - (mouse-sel-eval-at-event-end initial-event - (let ((orig-cursor-type - (cdr (assoc 'cursor-type (frame-parameters (selected-frame)))))) - (unwind-protect - - (let* ((thing-symbol (mouse-sel-selection-thing selection)) - (overlay (mouse-sel-selection-overlay selection)) - (orig-window (selected-window)) - (top (nth 1 (window-edges orig-window))) - (bottom (nth 3 (window-edges orig-window))) - (mark-active nil) ; inhibit normal region highlight - (echo-keystrokes 0) ; don't echo mouse events - min max - direction - event) - - ;; Get current bounds of overlay - (if (eq (overlay-buffer overlay) (current-buffer)) - (setq min (overlay-start overlay) - max (overlay-end overlay)) - (setq min (point) - max min) - (set thing-symbol nil)) - - - ;; Bar cursor - (if (fboundp 'modify-frame-parameters) - (modify-frame-parameters (selected-frame) - '((cursor-type . bar)))) - - ;; Handle dragging - (track-mouse - - (while (if (and initial-event (not no-process)) - ;; Use initial event - (prog1 - (setq event initial-event) - (setq initial-event nil)) - (setq event (read-event)) - (and (consp event) - (memq (car event) '(mouse-movement switch-frame)))) - - (let ((selection-thing (symbol-value thing-symbol)) - (end (event-end event))) - - (cond - - ;; Ignore any movement outside the frame - ((eq (car-safe event) 'switch-frame) nil) - ((and (posn-window end) - (not (eq (let ((posn-w (posn-window end))) - (if (windowp posn-w) - (window-frame posn-w) - posn-w)) - (window-frame orig-window)))) nil) - - ;; Different window, same frame - ((not (eq (posn-window end) orig-window)) - (let ((end-row (cdr (cdr (mouse-position))))) - (cond - ((and end-row (not (bobp)) (< end-row top)) - (mouse-scroll-subr orig-window (- end-row top) - overlay max)) - ((and end-row (not (eobp)) (>= end-row bottom)) - (mouse-scroll-subr orig-window (1+ (- end-row bottom)) - overlay min)) - ))) - - ;; On the mode line - ((eq (posn-point end) 'mode-line) - (mouse-scroll-subr orig-window 1 overlay min)) - - ;; In original window - (t (goto-char (posn-point end))) - - ) - - ;; Determine direction of drag - (cond - ((and (not direction) (not (eq min max))) - (setq direction (if (< (point) (/ (+ min max) 2)) -1 1))) - ((and (not (eq direction -1)) (<= (point) min)) - (setq direction -1)) - ((and (not (eq direction 1)) (>= (point) max)) - (setq direction 1))) - - (if (not selection-thing) nil - - ;; If dragging forward, goal is next character - (if (and (eq direction 1) (not (eobp))) (forward-char 1)) - - ;; Move to start/end of selected thing - (let ((goal (point))) - (goto-char (if (eq 1 direction) min max)) - (condition-case nil - (progn - (while (> (* direction (- goal (point))) 0) - (forward-thing selection-thing direction)) - (let ((end (point))) - (forward-thing selection-thing (- direction)) - (goto-char - (if (> (* direction (- goal (point))) 0) - end (point))))) - (error)))) - - ;; Move overlay - (move-overlay overlay - (if (eq 1 direction) min (point)) - (if (eq -1 direction) max (point)) - (current-buffer)) - - ))) ; end track-mouse - - ;; Detect follow-link events - (when (mouse-sel-follow-link-p initial-event event) - (throw 'follow-link event)) - - ;; Finish up after dragging - (let ((overlay-start (overlay-start overlay)) - (overlay-end (overlay-end overlay))) - - ;; Set selection - (if (not (eq overlay-start overlay-end)) - (mouse-sel-set-selection - selection - (buffer-substring overlay-start overlay-end))) - - ;; Handle copy/kill - (let (this-command) - (cond - ((eq (event-basic-type last-input-event) 'mouse-2) - (copy-region-as-kill overlay-start overlay-end) - (read-event) (read-event)) - ((and (memq (event-basic-type last-input-event) - '(mouse-1 mouse-3)) - (memq 'down (event-modifiers last-input-event))) - (kill-region overlay-start overlay-end) - (move-overlay overlay overlay-start overlay-start) - (read-event) (read-event)) - ((and (eq (event-basic-type last-input-event) 'mouse-3) - (memq 'double (event-modifiers last-input-event))) - (kill-region overlay-start overlay-end) - (move-overlay overlay overlay-start overlay-start))))) - - direction) - - ;; Restore cursor - (if (fboundp 'modify-frame-parameters) - (modify-frame-parameters - (selected-frame) (list (cons 'cursor-type orig-cursor-type)))) - - )))) - -(defun mouse-sel-follow-link-p (initial final) - "Return t if we should follow a link, given INITIAL and FINAL mouse events. -See `mouse-1-click-follows-link' for details. Currently, Mouse -Sel mode does not support using a `double' value to follow links -using double-clicks." - (and initial final mouse-1-click-follows-link - (eq (car initial) 'down-mouse-1) - (mouse-on-link-p (event-start initial)) - (= (posn-point (event-start initial)) - (posn-point (event-end final))) - (= (event-click-count initial) 1) - (or (not (integerp mouse-1-click-follows-link)) - (let ((t0 (posn-timestamp (event-start initial))) - (t1 (posn-timestamp (event-end final)))) - (and (integerp t0) (integerp t1) - (if (> mouse-1-click-follows-link 0) - (<= (- t1 t0) mouse-1-click-follows-link) - (< (- t0 t1) mouse-1-click-follows-link))))))) - -;;=== Paste =============================================================== - -(defun mouse-insert-selection (event arg) - "Insert the contents of the PRIMARY selection at mouse click. -If `mouse-yank-at-point' is non-nil, insert at point instead." - (interactive "e\nP") - (if (eq mouse-sel-default-bindings 'interprogram-cut-paste) - (mouse-yank-at-click event arg) - (mouse-insert-selection-internal 'PRIMARY event))) - -(defun mouse-insert-secondary (event) - "Insert the contents of the SECONDARY selection at mouse click. -If `mouse-yank-at-point' is non-nil, insert at point instead." - (interactive "e") - (mouse-insert-selection-internal 'SECONDARY event)) - -(defun mouse-insert-selection-internal (selection event) - "Insert the contents of the named SELECTION at mouse click. -If `mouse-yank-at-point' is non-nil, insert at point instead." - (unless mouse-yank-at-point - (mouse-set-point event)) - (when mouse-sel-get-selection-function - (push-mark (point) 'nomsg) - (insert-for-yank - (or (funcall mouse-sel-get-selection-function selection) "")))) - -;;=== Handle loss of selections =========================================== - -(defun mouse-sel-lost-selection-hook (selection) - "Remove the overlay for a lost selection." - (let ((overlay (mouse-sel-selection-overlay selection))) - (delete-overlay overlay))) - -(provide 'mouse-sel) - -;;; mouse-sel.el ends here diff --git a/lisp/obsolete/old-emacs-lock.el b/lisp/obsolete/old-emacs-lock.el deleted file mode 100644 index 70123e7537..0000000000 --- a/lisp/obsolete/old-emacs-lock.el +++ /dev/null @@ -1,102 +0,0 @@ -;;; old-emacs-lock.el --- prevents you from exiting Emacs if a buffer is locked -*- lexical-binding: t; -*- - -;; Copyright (C) 1994, 1997, 2001-2022 Free Software Foundation, Inc. - -;; Author: Tom Wurgler -;; Created: 12/8/94 -;; Keywords: extensions, processes -;; Obsolete-since: 24.1 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This code sets a buffer-local variable to t if toggle-emacs-lock is run, -;; then if the user attempts to exit Emacs, the locked buffer name will be -;; displayed and the exit aborted. This is just a way of protecting -;; yourself from yourself. For example, if you have a shell running a big -;; program and exiting Emacs would abort that program, you may want to lock -;; that buffer, then if you forget about it after a while, you won't -;; accidentally exit Emacs. To unlock the buffer, just goto the buffer and -;; run toggle-emacs-lock again. - -;;; Code: - -(defvar emacs-lock-from-exiting nil - "Whether Emacs is locked to prevent exiting. See `check-emacs-lock'.") -(make-variable-buffer-local 'emacs-lock-from-exiting) - -(defvar emacs-lock-buffer-locked nil - "Whether a shell or telnet buffer was locked when its process was killed.") -(make-variable-buffer-local 'emacs-lock-buffer-locked) -(put 'emacs-lock-buffer-locked 'permanent-local t) - -(defun check-emacs-lock () - "Check if variable `emacs-lock-from-exiting' is t for any buffer. -If any locked buffer is found, signal error and display the buffer's name." - (save-excursion - (dolist (buffer (buffer-list)) - (set-buffer buffer) - (when emacs-lock-from-exiting - (error "Emacs is locked from exit due to buffer: %s" (buffer-name)))))) - -(defun toggle-emacs-lock () - "Toggle `emacs-lock-from-exiting' for the current buffer. -See `check-emacs-lock'." - (interactive) - (setq emacs-lock-from-exiting (not emacs-lock-from-exiting)) - (if emacs-lock-from-exiting - (message "Buffer is now locked") - (message "Buffer is now unlocked"))) - -(defun emacs-lock-check-buffer-lock () - "Check if variable `emacs-lock-from-exiting' is t for a buffer. -If the buffer is locked, signal error and display its name." - (when emacs-lock-from-exiting - (error "Buffer `%s' is locked, can't delete it" (buffer-name)))) - -; These next defuns make it so if you exit a shell that is locked, the lock -; is shut off for that shell so you can exit Emacs. Same for telnet. -; Also, if a shell or a telnet buffer was locked and the process killed, -; turn the lock back on again if the process is restarted. - -(defun emacs-lock-shell-sentinel () - (set-process-sentinel - (get-buffer-process (buffer-name)) (function emacs-lock-clear-sentinel))) - -(defun emacs-lock-clear-sentinel (_proc _str) - (if emacs-lock-from-exiting - (progn - (setq emacs-lock-from-exiting nil) - (setq emacs-lock-buffer-locked t) - (message "Buffer is now unlocked")) - (setq emacs-lock-buffer-locked nil))) - -(defun emacs-lock-was-buffer-locked () - (if emacs-lock-buffer-locked - (setq emacs-lock-from-exiting t))) - -(unless noninteractive - (add-hook 'kill-emacs-hook #'check-emacs-lock)) -(add-hook 'kill-buffer-hook #'emacs-lock-check-buffer-lock) -(add-hook 'shell-mode-hook #'emacs-lock-was-buffer-locked) -(add-hook 'shell-mode-hook #'emacs-lock-shell-sentinel) -(add-hook 'telnet-mode-hook #'emacs-lock-was-buffer-locked) -(add-hook 'telnet-mode-hook #'emacs-lock-shell-sentinel) - -(provide 'emacs-lock) - -;;; old-emacs-lock.el ends here diff --git a/lisp/obsolete/patcomp.el b/lisp/obsolete/patcomp.el deleted file mode 100644 index 2c35cb0700..0000000000 --- a/lisp/obsolete/patcomp.el +++ /dev/null @@ -1,24 +0,0 @@ -;;; patcomp.el --- used by patch files to update Emacs releases -*- lexical-binding: t; -*- - -;; This file is part of GNU Emacs. - -;; Obsolete-since: 24.3 - -;;; Commentary: - -;;; Code: - -(defun batch-byte-recompile-emacs () - "Recompile the Emacs `lisp' directory. -This is used after installing the patches for a new version." - (let ((load-path (list (expand-file-name "lisp")))) - (byte-recompile-directory "lisp"))) - -(defun batch-byte-compile-emacs () - "Compile new files installed in the Emacs `lisp' directory. -This is used after installing the patches for a new version. -It uses the command line arguments to specify the files to compile." - (let ((load-path (list (expand-file-name "lisp")))) - (batch-byte-compile))) - -;;; patcomp.el ends here diff --git a/lisp/obsolete/pc-select.el b/lisp/obsolete/pc-select.el deleted file mode 100644 index 922358bcd6..0000000000 --- a/lisp/obsolete/pc-select.el +++ /dev/null @@ -1,410 +0,0 @@ -;;; pc-select.el --- emulate mark, cut, copy and paste from Motif -*- lexical-binding: t; -*- -;;; (or MAC GUI or MS-windoze (bah)) look-and-feel -;;; including key bindings. - -;; Copyright (C) 1995-1997, 2000-2022 Free Software Foundation, Inc. - -;; Author: Michael Staats -;; Keywords: convenience emulations -;; Created: 26 Sep 1995 -;; Obsolete-since: 24.1 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This package emulates the mark, copy, cut and paste look-and-feel of motif -;; programs (which is the same as the MAC gui and (sorry for that) MS-Windows). -;; It modifies the keybindings of the cursor keys and the next, prior, -;; home and end keys. They will modify mark-active. -;; You can still get the old behavior of cursor moving with the -;; control sequences C-f, C-b, etc. -;; This package uses transient-mark-mode and -;; delete-selection-mode. -;; -;; In addition to that all key-bindings from the pc-mode are -;; done here too (as suggested by RMS). -;; -;; As I found out after I finished the first version, s-region.el tries -;; to do the same.... But my code is a little more complete and using -;; delete-selection-mode is very important for the look-and-feel. -;; Pete Forman provided some motif -;; compliant keybindings which I added. I had to modify them a little -;; to add the -mark and -nomark functionality of cursor moving. -;; -;; Credits: -;; Many thanks to all who made comments. -;; Thanks to RMS and Ralf Muschall for criticism. -;; Kevin Cutts added the beginning-of-buffer -;; and end-of-buffer functions which I modified a little. -;; David Biesack suggested some more cleanup. -;; Thanks to Pete Forman -;; for additional motif keybindings. -;; Thanks to jvromans@squirrel.nl (Johan Vromans) for a bug report -;; concerning setting of this-command. -;; Dan Nicolaescu suggested suppressing the -;; scroll-up/scroll-down error. -;; Eli Barzilay (eli@cs.bgu.ac.il) suggested the sexps functions and -;; keybindings. -;; -;; Ok, some details about the idea of PC Selection mode: -;; -;; o The standard keys for moving around (right, left, up, down, home, end, -;; prior, next, called "move-keys" from now on) will always de-activate -;; the mark. -;; o If you press "Shift" together with the "move-keys", the region -;; you pass along is activated -;; o You have the copy, cut and paste functions (as in many other programs) -;; which will operate on the active region -;; It was not possible to bind them to C-v, C-x and C-c for obvious -;; emacs reasons. -;; They will be bound according to the "old" behavior to S-delete (cut), -;; S-insert (paste) and C-insert (copy). These keys do the same in many -;; other programs. -;; - -;;; Code: - -;; Customization: -(defgroup pc-select nil - "Emulate pc bindings." - :prefix "pc-select" - :group 'emulations) - -(define-obsolete-variable-alias 'pc-select-override-scroll-error - 'scroll-error-top-bottom - "24.1") -(defcustom pc-select-override-scroll-error t - "Non-nil means don't generate error on scrolling past edge of buffer. -This variable applies in PC Selection mode only. -The scroll commands normally generate an error if you try to scroll -past the top or bottom of the buffer. This is annoying when selecting -text with these commands. If you set this variable to non-nil, these -errors are suppressed." - :type 'boolean) - -(defcustom pc-select-selection-keys-only nil - "Non-nil means only bind the basic selection keys when started. -Other keys that emulate pc-behavior will be untouched. -This gives mostly Emacs-like behavior with only the selection keys enabled." - :type 'boolean) - -(defcustom pc-select-meta-moves-sexps nil - "Non-nil means move sexp-wise with Meta key, otherwise move word-wise." - :type 'boolean) - -(defcustom pc-selection-mode-hook nil - "The hook to run when PC Selection mode is toggled." - :type 'hook) - -(defvar pc-select-saved-settings-alist nil - "The values of the variables before PC Selection mode was toggled on. -When PC Selection mode is toggled on, it sets quite a few variables -for its own purposes. This alist holds the original values of the -variables PC Selection mode had set, so that these variables can be -restored to their original values when PC Selection mode is toggled off.") - -(defvar pc-select-map nil - "The keymap used as the global map when PC Selection mode is on." ) - -(defvar pc-select-saved-global-map nil - "The global map that was in effect when PC Selection mode was toggled on.") - -(defvar pc-select-key-bindings-alist nil - "This alist holds all the key bindings PC Selection mode sets.") - -(defvar pc-select-default-key-bindings nil - "These key bindings always get set by PC Selection mode.") - -(defvar pc-select-extra-key-bindings - ;; The following keybindings are for standard ISO keyboards - ;; as they are used with IBM compatible PCs, IBM RS/6000, - ;; MACs, many X-Stations and probably more. - '(;; Commented out since it's been standard at least since Emacs-21. - ;;([S-insert] . yank) - ;;([C-insert] . copy-region-as-kill) - ;;([S-delete] . kill-region) - - ;; The following bindings are useful on Sun Type 3 keyboards - ;; They implement the Get-Delete-Put (copy-cut-paste) - ;; functions from sunview on the L6, L8 and L10 keys - ;; Sam Steingold says that f16 is copy and f18 is paste. - ([f16] . copy-region-as-kill) - ([f18] . yank) - ([f20] . kill-region) - - ;; The following bindings are from Pete Forman. - ([f6] . other-window) ; KNextPane F6 - ([C-delete] . kill-line) ; KEraseEndLine cDel - ("\M-\d" . undo) ; KUndo aBS - - ;; The following binding is taken from pc-mode.el - ;; as suggested by RMS. - ;; I only used the one that is not covered above. - ([C-M-delete] . kill-sexp) - ;; Next line proposed by Eli Barzilay - ([C-escape] . electric-buffer-list)) - "Key bindings to set only if `pc-select-selection-keys-only' is nil.") - -(defvar pc-select-meta-moves-sexps-key-bindings - '((([M-right] . forward-sexp) - ([M-left] . backward-sexp)) - (([M-right] . forward-word) - ([M-left] . backward-word))) - "The list of key bindings controlled by `pc-select-meta-moves-sexp'. -The bindings in the car of this list get installed if -`pc-select-meta-moves-sexp' is t, the bindings in the cadr of this -list get installed otherwise.") - -;; This is for tty. We don't turn on normal-erase-is-backspace, -;; but bind keys as pc-selection-mode did before -;; normal-erase-is-backspace was invented, to keep us back -;; compatible. -(defvar pc-select-tty-key-bindings - '(([delete] . delete-char) ; KDelete Del - ([C-backspace] . backward-kill-word)) - "The list of key bindings controlled by `pc-select-selection-keys-only'. -These key bindings get installed when running in a tty, but only if -`pc-select-selection-keys-only' is nil.") - -(defvar pc-select-old-M-delete-binding nil - "Holds the old mapping of [M-delete] in the `function-key-map'. -This variable holds the value associated with [M-delete] in the -`function-key-map' before PC Selection mode had changed that -association.") - -;;;; -;; misc -;;;; - -(provide 'pc-select) - -(defun pc-select-define-keys (alist keymap) - "Make KEYMAP have the key bindings specified in ALIST." - (let ((lst alist)) - (while lst - (define-key keymap (caar lst) (cdar lst)) - (setq lst (cdr lst))))) - -(defun pc-select-restore-keys (alist keymap saved-map) - "Use ALIST to restore key bindings from SAVED-MAP into KEYMAP. -Go through all the key bindings in ALIST, and, for each key -binding, if KEYMAP and ALIST still agree on the key binding, -restore the previous value of that key binding from SAVED-MAP." - (let ((lst alist)) - (while lst - (when (equal (lookup-key keymap (caar lst)) (cdar lst)) - (define-key keymap (caar lst) (lookup-key saved-map (caar lst)))) - (setq lst (cdr lst))))) - -(defmacro pc-select-add-to-alist (alist var val) - "Ensure that ALIST contains the cons cell (VAR . VAL). -If a cons cell whose car is VAR is already on the ALIST, update the -cdr of that cell with VAL. Otherwise, make a new cons cell -\(VAR . VAL), and prepend it onto ALIST." - (let ((elt (make-symbol "elt"))) - `(let ((,elt (assq ',var ,alist))) - (if ,elt - (setcdr ,elt ,val) - (setq ,alist (cons (cons ',var ,val) ,alist)))))) - -(defmacro pc-select-save-and-set-var (var newval) - "Set VAR to NEWVAL; save the old value. -The old value is saved on the `pc-select-saved-settings-alist'." - `(when (boundp ',var) - (pc-select-add-to-alist pc-select-saved-settings-alist ,var ,var) - (setq ,var ,newval))) - -(defmacro pc-select-save-and-set-mode (mode &optional arg mode-var) - "Call the function MODE; save the old value of the variable MODE. -MODE is presumed to be a function which turns on a minor mode. First, -save the value of the variable MODE on `pc-select-saved-settings-alist'. -Then, if ARG is specified, call MODE with ARG, otherwise call it with -nil as an argument. If MODE-VAR is specified, save the value of the -variable MODE-VAR (instead of the value of the variable MODE) on -`pc-select-saved-settings-alist'." - (unless mode-var (setq mode-var mode)) - `(when (fboundp ',mode) - (pc-select-add-to-alist pc-select-saved-settings-alist - ,mode-var ,mode-var) - (,mode ,arg))) - -(defmacro pc-select-restore-var (var) - "Restore the previous value of the variable VAR. -Look up VAR's previous value in `pc-select-saved-settings-alist', and, -if the value is found, set VAR to that value." - (let ((elt (make-symbol "elt"))) - `(let ((,elt (assq ',var pc-select-saved-settings-alist))) - (unless (null ,elt) - (setq ,var (cdr ,elt)))))) - -(defmacro pc-select-restore-mode (mode) - "Restore the previous state (either on or off) of the minor mode MODE. -Look up the value of the variable MODE on `pc-select-saved-settings-alist'. -If the value is non-nil, call the function MODE with an argument of -1, otherwise call it with an argument of -1." - (let ((elt (make-symbol "elt"))) - `(when (fboundp ',mode) - (let ((,elt (assq ',mode pc-select-saved-settings-alist))) - (unless (null ,elt) - (,mode (if (cdr ,elt) 1 -1))))))) - - -;;;###autoload -(define-minor-mode pc-selection-mode - "Change mark behavior to emulate Motif, Mac or MS-Windows cut and paste style. - -This mode enables Delete Selection mode and Transient Mark mode. - -The arrow keys (and others) are bound to new functions -which modify the status of the mark. - -The ordinary arrow keys disable the mark. -The shift-arrow keys move, leaving the mark behind. - -C-LEFT and C-RIGHT move back or forward one word, disabling the mark. -S-C-LEFT and S-C-RIGHT move back or forward one word, leaving the mark behind. - -M-LEFT and M-RIGHT move back or forward one word or sexp, disabling the mark. -S-M-LEFT and S-M-RIGHT move back or forward one word or sexp, leaving the mark -behind. To control whether these keys move word-wise or sexp-wise set the -variable `pc-select-meta-moves-sexps' after loading pc-select.el but before -turning PC Selection mode on. - -C-DOWN and C-UP move back or forward a paragraph, disabling the mark. -S-C-DOWN and S-C-UP move back or forward a paragraph, leaving the mark behind. - -HOME moves to beginning of line, disabling the mark. -S-HOME moves to beginning of line, leaving the mark behind. -With Ctrl or Meta, these keys move to beginning of buffer instead. - -END moves to end of line, disabling the mark. -S-END moves to end of line, leaving the mark behind. -With Ctrl or Meta, these keys move to end of buffer instead. - -PRIOR or PAGE-UP scrolls and disables the mark. -S-PRIOR or S-PAGE-UP scrolls and leaves the mark behind. - -S-DELETE kills the region (`kill-region'). -S-INSERT yanks text from the kill ring (`yank'). -C-INSERT copies the region into the kill ring (`copy-region-as-kill'). - -In addition, certain other PC bindings are imitated (to avoid this, set -the variable `pc-select-selection-keys-only' to t after loading pc-select.el -but before calling PC Selection mode): - - F6 other-window - DELETE delete-char - C-DELETE kill-line - M-DELETE kill-word - C-M-DELETE kill-sexp - C-BACKSPACE backward-kill-word - M-BACKSPACE undo" - ;; FIXME: bring pc-bindings-mode here ? - :global t - - (if pc-selection-mode - (if (null pc-select-key-bindings-alist) - (progn - (setq pc-select-saved-global-map (copy-keymap (current-global-map))) - (setq pc-select-key-bindings-alist - (append pc-select-default-key-bindings - (if pc-select-selection-keys-only - nil - pc-select-extra-key-bindings) - (if pc-select-meta-moves-sexps - (car pc-select-meta-moves-sexps-key-bindings) - (cadr pc-select-meta-moves-sexps-key-bindings)) - (if (or pc-select-selection-keys-only - (eq window-system 'x) - (memq system-type '(ms-dos windows-nt))) - nil - pc-select-tty-key-bindings))) - - (pc-select-define-keys pc-select-key-bindings-alist - (current-global-map)) - - (unless (or pc-select-selection-keys-only - (eq window-system 'x) - (memq system-type '(ms-dos windows-nt))) - ;; it is not clear that we need the following line - ;; I hope it doesn't do too much harm to leave it in, though... - (setq pc-select-old-M-delete-binding - (lookup-key function-key-map [M-delete])) - (define-key function-key-map [M-delete] [?\M-d])) - - (when (and (not pc-select-selection-keys-only) - (or (eq window-system 'x) - (memq system-type '(ms-dos windows-nt))) - (fboundp 'normal-erase-is-backspace-mode)) - (pc-select-save-and-set-mode normal-erase-is-backspace-mode 1 - normal-erase-is-backspace)) - ;; the original author also had this above: - ;; (setq-default normal-erase-is-backspace t) - ;; However, the documentation for the variable says that - ;; "setting it with setq has no effect", so I'm removing it. - - (pc-select-save-and-set-var highlight-nonselected-windows nil) - (pc-select-save-and-set-var transient-mark-mode t) - (pc-select-save-and-set-var shift-select-mode t) - (pc-select-save-and-set-var mark-even-if-inactive t) - (pc-select-save-and-set-mode delete-selection-mode 1)) - ;;else - ;; If the user turned on pc-selection-mode a second time - ;; do not clobber the values of the variables that were - ;; saved from before pc-selection mode was activated -- - ;; just make sure the values are the way we like them. - (pc-select-define-keys pc-select-key-bindings-alist - (current-global-map)) - (unless (or pc-select-selection-keys-only - (eq window-system 'x) - (memq system-type '(ms-dos windows-nt))) - ;; it is not clear that we need the following line - ;; I hope it doesn't do too much harm to leave it in, though... - (define-key function-key-map [M-delete] [?\M-d])) - (when (and (not pc-select-selection-keys-only) - (or (eq window-system 'x) - (memq system-type '(ms-dos windows-nt))) - (fboundp 'normal-erase-is-backspace-mode)) - (normal-erase-is-backspace-mode 1)) - (setq highlight-nonselected-windows nil) - (transient-mark-mode 1) - (setq mark-even-if-inactive t) - (delete-selection-mode 1)) - ;;else - (when pc-select-key-bindings-alist - (when (and (not pc-select-selection-keys-only) - (or (eq window-system 'x) - (memq system-type '(ms-dos windows-nt)))) - (pc-select-restore-mode normal-erase-is-backspace-mode)) - - (pc-select-restore-keys - pc-select-key-bindings-alist (current-global-map) - pc-select-saved-global-map) - - (pc-select-restore-var highlight-nonselected-windows) - (pc-select-restore-var transient-mark-mode) - (pc-select-restore-var shift-select-mode) - (pc-select-restore-var mark-even-if-inactive) - (pc-select-restore-mode delete-selection-mode) - (and pc-select-old-M-delete-binding - (define-key function-key-map [M-delete] - pc-select-old-M-delete-binding)) - (setq pc-select-key-bindings-alist nil - pc-select-saved-settings-alist nil)))) -(make-obsolete 'pc-selection-mode 'delete-selection-mode "24.1") - -;;; pc-select.el ends here diff --git a/lisp/obsolete/s-region.el b/lisp/obsolete/s-region.el deleted file mode 100644 index 9dfc9831f4..0000000000 --- a/lisp/obsolete/s-region.el +++ /dev/null @@ -1,123 +0,0 @@ -;;; s-region.el --- set region using shift key -*- lexical-binding: t; -*- - -;; Copyright (C) 1994-1995, 2001-2022 Free Software Foundation, Inc. - -;; Author: Morten Welinder -;; Keywords: terminals -;; Favorite-brand-of-beer: None, I hate beer. -;; Obsolete-since: 24.1 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Having loaded this code you can set the region by holding down the -;; shift key and move the cursor to the other end of the region. The -;; functionality provided by this code is similar to that provided by -;; the editors of Borland International's compilers for ms-dos. - -;; Currently, s-region-move may be bound only to events that are vectors -;; of length one and whose last element is a symbol. Also, the functions -;; that are given this kind of overlay should be (interactive "p") -;; functions. - -;; If the following keys are not already bound then... -;; C-insert is bound to copy-region-as-kill -;; S-delete is bound to kill-region -;; S-insert is bound to yank - -;;; Code: - -(defvar s-region-overlay (make-overlay 1 1)) -(overlay-put s-region-overlay 'face 'region) -(overlay-put s-region-overlay 'priority 1000000) ; for hilit19 - -(defun s-region-unshift (key) - "Remove shift modifier from last keypress KEY and return that as a key." - (if (vectorp key) - (let ((last (aref key (1- (length key))))) - (if (symbolp last) - (let* ((keyname (symbol-name last)) - (pos (string-match "S-" keyname))) - (if pos - ;; We skip all initial parts of the event assuming that - ;; those are setting up the prefix argument to the command. - (vector (intern (concat (substring keyname 0 pos) - (substring keyname (+ 2 pos))))) - (error "Non-shifted key: %S" key))) - (error "Key does not end in a symbol: %S" key))) - (error "Non-vector key: %S" key))) - -(defun s-region-move-p1 (&rest arg) - "This is an overlay function to point-moving keys that are interactive \"p\"." - (interactive "p") - (apply (function s-region-move) arg)) - -(defun s-region-move-p2 (&rest arg) - "This is an overlay function to point-moving keys that are interactive \"P\"." - (interactive "P") - (apply (function s-region-move) arg)) - -(defun s-region-move (&rest arg) - (if (if mark-active (not (equal last-command 's-region-move)) t) - (set-mark-command nil) - (message "")) ; delete the "Mark set" message - (setq this-command 's-region-move) - (apply (key-binding (s-region-unshift (this-command-keys))) arg) - (move-overlay s-region-overlay (mark) (point) (current-buffer)) - (sit-for 1) - (delete-overlay s-region-overlay)) - -(defun s-region-bind (keylist &optional map) - "Bind shifted keys in KEYLIST to `s-region-move-p1' or `s-region-move-p2'. -Each key in KEYLIST is shifted and bound to one of the `s-region-move' -functions provided it is already bound to some command or other. -Optional second argument MAP specifies keymap to add binding to, defaulting -to global keymap." - (let ((p2 (list 'scroll-up 'scroll-down - 'beginning-of-buffer 'end-of-buffer))) - (or map (setq map global-map)) - (while keylist - (let* ((key (car keylist)) - (binding (key-binding key))) - (if (commandp binding) - (define-key - map - (vector (intern (concat "S-" (symbol-name (aref key 0))))) - (cond ((memq binding p2) - 's-region-move-p2) - (t 's-region-move-p1))))) - (setq keylist (cdr keylist))))) - -;; Single keys (plus modifiers) only! -(s-region-bind - (list [right] [left] [up] [down] - [C-left] [C-right] [C-up] [C-down] - [M-left] [M-right] [M-up] [M-down] - [next] [previous] [home] [end] - [C-next] [C-previous] [C-home] [C-end] - [M-next] [M-previous] [M-home] [M-end])) - -(or (global-key-binding [C-insert]) - (global-set-key [C-insert] #'copy-region-as-kill)) -(or (global-key-binding [S-delete]) - (global-set-key [S-delete] #'kill-region)) -(or (global-key-binding [S-insert]) - (global-set-key [S-insert] #'yank)) - -(provide 's-region) - -;;; s-region.el ends here diff --git a/lisp/obsolete/sregex.el b/lisp/obsolete/sregex.el deleted file mode 100644 index f8722f6129..0000000000 --- a/lisp/obsolete/sregex.el +++ /dev/null @@ -1,605 +0,0 @@ -;;; sregex.el --- symbolic regular expressions -*- lexical-binding: t; -*- - -;; Copyright (C) 1997-1998, 2000-2022 Free Software Foundation, Inc. - -;; Author: Bob Glickstein -;; Maintainer: emacs-devel@gnu.org -;; Keywords: extensions -;; Obsolete-since: 24.1 - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; This package allows you to write regular expressions using a -;; totally new, Lisp-like syntax. - -;; A "symbolic regular expression" (sregex for short) is a Lisp form -;; that, when evaluated, produces the string form of the specified -;; regular expression. Here's a simple example: - -;; (sregexq (or "Bob" "Robert")) => "Bob\\|Robert" - -;; As you can see, an sregex is specified by placing one or more -;; special clauses in a call to `sregexq'. The clause in this case is -;; the `or' of two strings (not to be confused with the Lisp function -;; `or'). The list of allowable clauses appears below. - -;; With sregex, it is never necessary to "escape" magic characters -;; that are meant to be taken literally; that happens automatically. -;; For example: - -;; (sregexq "M*A*S*H") => "M\\*A\\*S\\*H" - -;; It is also unnecessary to "group" parts of the expression together -;; to overcome operator precedence; that also happens automatically. -;; For example: - -;; (sregexq (opt (or "Bob" "Robert"))) => "\\(?:Bob\\|Robert\\)?" - -;; It *is* possible to group parts of the expression in order to refer -;; to them with numbered backreferences: - -;; (sregexq (group (or "Go" "Run")) -;; ", Spot, " -;; (backref 1)) => "\\(Go\\|Run\\), Spot, \\1" - -;; `sregexq' is a macro. Each time it is used, it constructs a simple -;; Lisp expression that then invokes a moderately complex engine to -;; interpret the sregex and render the string form. Because of this, -;; I don't recommend sprinkling calls to `sregexq' throughout your -;; code, the way one normally does with string regexes (which are -;; cheap to evaluate). Instead, it's wiser to precompute the regexes -;; you need wherever possible instead of repeatedly constructing the -;; same ones over and over. Example: - -;; (let ((field-regex (sregexq (opt "resent-") -;; (or "to" "cc" "bcc")))) -;; ... -;; (while ... -;; ... -;; (re-search-forward field-regex ...) -;; ...)) - -;; The arguments to `sregexq' are automatically quoted, but the -;; flipside of this is that it is not straightforward to include -;; computed (i.e., non-constant) values in `sregexq' expressions. So -;; `sregex' is a function that is like `sregexq' but which does not -;; automatically quote its values. Literal sregex clauses must be -;; explicitly quoted like so: - -;; (sregex '(or "Bob" "Robert")) => "Bob\\|Robert" - -;; but computed clauses can be included easily, allowing for the reuse -;; of common clauses: - -;; (let ((dotstar '(0+ any)) -;; (whitespace '(1+ (syntax ?-))) -;; (digits '(1+ (char (?0 . ?9))))) -;; (sregex 'bol dotstar ":" whitespace digits)) => "^.*:\\s-+[0-9]+" - -;; To use this package in a Lisp program, simply (require 'sregex). - -;; Here are the clauses allowed in an `sregex' or `sregexq' -;; expression: - -;; - a string -;; This stands for the literal string. If it contains -;; metacharacters, they will be escaped in the resulting regex -;; (using `regexp-quote'). - -;; - the symbol `any' -;; This stands for ".", a regex matching any character except -;; newline. - -;; - the symbol `bol' -;; Stands for "^", matching the empty string at the beginning of a line - -;; - the symbol `eol' -;; Stands for "$", matching the empty string at the end of a line - -;; - (group CLAUSE ...) -;; Groups the given CLAUSEs using "\\(" and "\\)". - -;; - (sequence CLAUSE ...) - -;; Groups the given CLAUSEs; may or may not use "\\(?:" and "\\)". -;; Clauses grouped by `sequence' do not count for purposes of -;; numbering backreferences. Use `sequence' in situations like -;; this: - -;; (sregexq (or "dog" "cat" -;; (sequence (opt "sea ") "monkey"))) -;; => "dog\\|cat\\|\\(?:sea \\)?monkey" - -;; where a single `or' alternate needs to contain multiple -;; subclauses. - -;; - (backref N) -;; Matches the same string previously matched by the Nth "group" in -;; the same sregex. N is a positive integer. - -;; - (or CLAUSE ...) -;; Matches any one of the CLAUSEs by separating them with "\\|". - -;; - (0+ CLAUSE ...) -;; Concatenates the given CLAUSEs and matches zero or more -;; occurrences by appending "*". - -;; - (1+ CLAUSE ...) -;; Concatenates the given CLAUSEs and matches one or more -;; occurrences by appending "+". - -;; - (opt CLAUSE ...) -;; Concatenates the given CLAUSEs and matches zero or one occurrence -;; by appending "?". - -;; - (repeat MIN MAX CLAUSE ...) -;; Concatenates the given CLAUSEs and constructs a regex matching at -;; least MIN occurrences and at most MAX occurrences. MIN must be a -;; non-negative integer. MAX must be a non-negative integer greater -;; than or equal to MIN; or MAX can be nil to mean "infinity." - -;; - (char CHAR-CLAUSE ...) -;; Creates a "character class" matching one character from the given -;; set. See below for how to construct a CHAR-CLAUSE. - -;; - (not-char CHAR-CLAUSE ...) -;; Creates a "character class" matching any one character not in the -;; given set. See below for how to construct a CHAR-CLAUSE. - -;; - the symbol `bot' -;; Stands for "\\`", matching the empty string at the beginning of -;; text (beginning of a string or of a buffer). - -;; - the symbol `eot' -;; Stands for "\\'", matching the empty string at the end of text. - -;; - the symbol `point' -;; Stands for "\\=", matching the empty string at point. - -;; - the symbol `word-boundary' -;; Stands for "\\b", matching the empty string at the beginning or -;; end of a word. - -;; - the symbol `not-word-boundary' -;; Stands for "\\B", matching the empty string not at the beginning -;; or end of a word. - -;; - the symbol `bow' -;; Stands for "\\<", matching the empty string at the beginning of a -;; word. - -;; - the symbol `eow' -;; Stands for "\\>", matching the empty string at the end of a word. - -;; - the symbol `wordchar' -;; Stands for the regex "\\w", matching a word-constituent character -;; (as determined by the current syntax table) - -;; - the symbol `not-wordchar' -;; Stands for the regex "\\W", matching a non-word-constituent -;; character. - -;; - (syntax CODE) -;; Stands for the regex "\\sCODE", where CODE is a syntax table code -;; (a single character). Matches any character with the requested -;; syntax. - -;; - (not-syntax CODE) -;; Stands for the regex "\\SCODE", where CODE is a syntax table code -;; (a single character). Matches any character without the -;; requested syntax. - -;; - (regex REGEX) -;; This is a "trapdoor" for including ordinary regular expression -;; strings in the result. Some regular expressions are clearer when -;; written the old way: "[a-z]" vs. (sregexq (char (?a . ?z))), for -;; instance. - -;; Each CHAR-CLAUSE that is passed to (char ...) and (not-char ...) -;; has one of the following forms: - -;; - a character -;; Adds that character to the set. - -;; - a string -;; Adds all the characters in the string to the set. - -;; - A pair (MIN . MAX) -;; Where MIN and MAX are characters, adds the range of characters -;; from MIN through MAX to the set. - -;;; To do: - -;; An earlier version of this package could optionally translate the -;; symbolic regex into other languages' syntaxes, e.g. Perl. For -;; instance, with Perl syntax selected, (sregexq (or "ab" "cd")) would -;; yield "ab|cd" instead of "ab\\|cd". It might be useful to restore -;; such a facility. - -;; - handle multibyte chars in sregex--char-aux -;; - add support for character classes ([:blank:], ...) -;; - add support for non-greedy operators *? and +? -;; - bug: (sregexq (opt (opt ?a))) returns "a??" which is a non-greedy "a?" - -;;; Code: - -(eval-when-compile (require 'cl-lib)) - -;; Compatibility code for when we didn't have shy-groups -(defvar sregex--current-sregex nil) -(defun sregex-info () nil) -(defmacro sregex-save-match-data (&rest forms) (cons 'save-match-data forms)) -(defun sregex-replace-match (r &optional f l str subexp _x) - (replace-match r f l str subexp)) -(defun sregex-match-string (c &optional i _x) (match-string c i)) -(defun sregex-match-string-no-properties (count &optional in-string _sregex) - (match-string-no-properties count in-string)) -(defun sregex-match-beginning (count &optional _sregex) (match-beginning count)) -(defun sregex-match-end (count &optional _sregex) (match-end count)) -(defun sregex-match-data (&optional _sregex) (match-data)) -(defun sregex-backref-num (n &optional _sregex) n) - - -(defun sregex (&rest exps) - "Symbolic regular expression interpreter. -This is exactly like `sregexq' (q.v.) except that it evaluates all its -arguments, so literal sregex clauses must be quoted. For example: - - (sregex \\='(or \"Bob\" \"Robert\")) => \"Bob\\\\|Robert\" - -An argument-evaluating sregex interpreter lets you reuse sregex -subexpressions: - - (let ((dotstar \\='(0+ any)) - (whitespace \\='(1+ (syntax ?-))) - (digits \\='(1+ (char (?0 . ?9))))) - (sregex \\='bol dotstar \":\" whitespace digits)) => \"^.*:\\\\s-+[0-9]+\"" - (sregex--sequence exps nil)) - -(defmacro sregexq (&rest exps) - "Symbolic regular expression interpreter. -This macro allows you to specify a regular expression (regexp) in -symbolic form, and converts it into the string form required by Emacs's -regex functions such as `re-search-forward' and `looking-at'. Here is -a simple example: - - (sregexq (or \"Bob\" \"Robert\")) => \"Bob\\\\|Robert\" - -As you can see, an sregex is specified by placing one or more special -clauses in a call to `sregexq'. The clause in this case is the `or' -of two strings (not to be confused with the Lisp function `or'). The -list of allowable clauses appears below. - -With `sregex', it is never necessary to \"escape\" magic characters -that are meant to be taken literally; that happens automatically. -For example: - - (sregexq \"M*A*S*H\") => \"M\\\\*A\\\\*S\\\\*H\" - -It is also unnecessary to \"group\" parts of the expression together -to overcome operator precedence; that also happens automatically. -For example: - - (sregexq (opt (or \"Bob\" \"Robert\"))) => \"\\\\(Bob\\\\|Robert\\\\)?\" - -It *is* possible to group parts of the expression in order to refer -to them with numbered backreferences: - - (sregexq (group (or \"Go\" \"Run\")) - \", Spot, \" - (backref 1)) => \"\\\\(Go\\\\|Run\\\\), Spot, \\\\1\" - -If `sregexq' needs to introduce its own grouping parentheses, it will -automatically renumber your backreferences: - - (sregexq (opt \"resent-\") - (group (or \"to\" \"cc\" \"bcc\")) - \": \" - (backref 1)) => \"\\\\(resent-\\\\)?\\\\(to\\\\|cc\\\\|bcc\\\\): \\\\2\" - -`sregexq' is a macro. Each time it is used, it constructs a simple -Lisp expression that then invokes a moderately complex engine to -interpret the sregex and render the string form. Because of this, I -don't recommend sprinkling calls to `sregexq' throughout your code, -the way one normally does with string regexes (which are cheap to -evaluate). Instead, it's wiser to precompute the regexes you need -wherever possible instead of repeatedly constructing the same ones -over and over. Example: - - (let ((field-regex (sregexq (opt \"resent-\") - (or \"to\" \"cc\" \"bcc\")))) - ... - (while ... - ... - (re-search-forward field-regex ...) - ...)) - -The arguments to `sregexq' are automatically quoted, but the -flipside of this is that it is not straightforward to include -computed (i.e., non-constant) values in `sregexq' expressions. So -`sregex' is a function that is like `sregexq' but which does not -automatically quote its values. Literal sregex clauses must be -explicitly quoted like so: - - (sregex \\='(or \"Bob\" \"Robert\")) => \"Bob\\\\|Robert\" - -but computed clauses can be included easily, allowing for the reuse -of common clauses: - - (let ((dotstar \\='(0+ any)) - (whitespace \\='(1+ (syntax ?-))) - (digits \\='(1+ (char (?0 . ?9))))) - (sregex \\='bol dotstar \":\" whitespace digits)) => \"^.*:\\\\s-+[0-9]+\" - -Here are the clauses allowed in an `sregex' or `sregexq' expression: - -- a string - This stands for the literal string. If it contains - metacharacters, they will be escaped in the resulting regex - (using `regexp-quote'). - -- the symbol `any' - This stands for \".\", a regex matching any character except - newline. - -- the symbol `bol' - Stands for \"^\", matching the empty string at the beginning of a line - -- the symbol `eol' - Stands for \"$\", matching the empty string at the end of a line - -- (group CLAUSE ...) - Groups the given CLAUSEs using \"\\\\(\" and \"\\\\)\". - -- (sequence CLAUSE ...) - - Groups the given CLAUSEs; may or may not use \"\\\\(\" and \"\\\\)\". - Clauses grouped by `sequence' do not count for purposes of - numbering backreferences. Use `sequence' in situations like - this: - - (sregexq (or \"dog\" \"cat\" - (sequence (opt \"sea \") \"monkey\"))) - => \"dog\\\\|cat\\\\|\\\\(?:sea \\\\)?monkey\" - - where a single `or' alternate needs to contain multiple - subclauses. - -- (backref N) - Matches the same string previously matched by the Nth \"group\" in - the same sregex. N is a positive integer. - -- (or CLAUSE ...) - Matches any one of the CLAUSEs by separating them with \"\\\\|\". - -- (0+ CLAUSE ...) - Concatenates the given CLAUSEs and matches zero or more - occurrences by appending \"*\". - -- (1+ CLAUSE ...) - Concatenates the given CLAUSEs and matches one or more - occurrences by appending \"+\". - -- (opt CLAUSE ...) - Concatenates the given CLAUSEs and matches zero or one occurrence - by appending \"?\". - -- (repeat MIN MAX CLAUSE ...) - Concatenates the given CLAUSEs and constructs a regex matching at - least MIN occurrences and at most MAX occurrences. MIN must be a - non-negative integer. MAX must be a non-negative integer greater - than or equal to MIN; or MAX can be nil to mean \"infinity.\" - -- (char CHAR-CLAUSE ...) - Creates a \"character class\" matching one character from the given - set. See below for how to construct a CHAR-CLAUSE. - -- (not-char CHAR-CLAUSE ...) - Creates a \"character class\" matching any one character not in the - given set. See below for how to construct a CHAR-CLAUSE. - -- the symbol `bot' - Stands for \"\\\\\\=`\", matching the empty string at the beginning of - text (beginning of a string or of a buffer). - -- the symbol `eot' - Stands for \"\\\\'\", matching the empty string at the end of text. - -- the symbol `point' - Stands for \"\\\\=\\=\", matching the empty string at point. - -- the symbol `word-boundary' - Stands for \"\\\\b\", matching the empty string at the beginning or - end of a word. - -- the symbol `not-word-boundary' - Stands for \"\\\\B\", matching the empty string not at the beginning - or end of a word. - -- the symbol `bow' - Stands for \"\\\\=\\<\", matching the empty string at the beginning of a - word. - -- the symbol `eow' - Stands for \"\\\\=\\>\", matching the empty string at the end of a word. - -- the symbol `wordchar' - Stands for the regex \"\\\\w\", matching a word-constituent character - (as determined by the current syntax table) - -- the symbol `not-wordchar' - Stands for the regex \"\\\\W\", matching a non-word-constituent - character. - -- (syntax CODE) - Stands for the regex \"\\\\sCODE\", where CODE is a syntax table code - (a single character). Matches any character with the requested - syntax. - -- (not-syntax CODE) - Stands for the regex \"\\\\SCODE\", where CODE is a syntax table code - (a single character). Matches any character without the - requested syntax. - -- (regex REGEX) - This is a \"trapdoor\" for including ordinary regular expression - strings in the result. Some regular expressions are clearer when - written the old way: \"[a-z]\" vs. (sregexq (char (?a . ?z))), for - instance. - -Each CHAR-CLAUSE that is passed to (char ...) and (not-char ...) -has one of the following forms: - -- a character - Adds that character to the set. - -- a string - Adds all the characters in the string to the set. - -- A pair (MIN . MAX) - Where MIN and MAX are characters, adds the range of characters - from MIN through MAX to the set." - `(apply 'sregex ',exps)) - -(defun sregex--engine (exp combine) - (cond - ((stringp exp) - (if (and combine - (eq combine 'suffix) - (/= (length exp) 1)) - (concat "\\(?:" (regexp-quote exp) "\\)") - (regexp-quote exp))) - ((symbolp exp) - (cl-ecase exp - (any ".") - (bol "^") - (eol "$") - (wordchar "\\w") - (not-wordchar "\\W") - (bot "\\`") - (eot "\\'") - (point "\\=") - (word-boundary "\\b") - (not-word-boundary "\\B") - (bow "\\<") - (eow "\\>"))) - ((consp exp) - (funcall (intern (concat "sregex--" - (symbol-name (car exp)))) - (cdr exp) - combine)) - (t (error "Invalid expression: %s" exp)))) - -(defun sregex--sequence (exps combine) - (if (= (length exps) 1) (sregex--engine (car exps) combine) - (let ((re (mapconcat - (lambda (e) (sregex--engine e 'concat)) - exps ""))) - (if (eq combine 'suffix) - (concat "\\(?:" re "\\)") - re)))) - -(defun sregex--or (exps combine) - (if (= (length exps) 1) (sregex--engine (car exps) combine) - (let ((re (mapconcat - (lambda (e) (sregex--engine e 'or)) - exps "\\|"))) - (if (not (eq combine 'or)) - (concat "\\(?:" re "\\)") - re)))) - -(defun sregex--group (exps _combine) (concat "\\(" (sregex--sequence exps nil) "\\)")) - -(defun sregex--backref (exps _combine) (concat "\\" (int-to-string (car exps)))) -(defun sregex--opt (exps _combine) (concat (sregex--sequence exps 'suffix) "?")) -(defun sregex--0+ (exps _combine) (concat (sregex--sequence exps 'suffix) "*")) -(defun sregex--1+ (exps _combine) (concat (sregex--sequence exps 'suffix) "+")) - -(defun sregex--char (exps _combine) (sregex--char-aux nil exps)) -(defun sregex--not-char (exps _combine) (sregex--char-aux t exps)) - -(defun sregex--syntax (exps _combine) (format "\\s%c" (car exps))) -(defun sregex--not-syntax (exps _combine) (format "\\S%c" (car exps))) - -(defun sregex--regex (exps combine) - (if combine (concat "\\(?:" (car exps) "\\)") (car exps))) - -(defun sregex--repeat (exps _combine) - (let* ((min (or (pop exps) 0)) - (minstr (number-to-string min)) - (max (pop exps))) - (concat (sregex--sequence exps 'suffix) - (concat "\\{" minstr "," - (when max (number-to-string max)) "\\}")))) - -(defun sregex--char-range (start end) - (let ((startc (char-to-string start)) - (endc (char-to-string end))) - (cond - ((> end (+ start 2)) (concat startc "-" endc)) - ((> end (+ start 1)) (concat startc (char-to-string (1+ start)) endc)) - ((> end start) (concat startc endc)) - (t startc)))) - -(defun sregex--char-aux (complement args) - ;; regex-opt does the same, we should join effort. - (let ((chars (make-bool-vector 256 nil))) ; Yeah, right! - (dolist (arg args) - (cond ((integerp arg) (aset chars arg t)) - ((stringp arg) (mapc (lambda (c) (aset chars c t)) arg)) - ((consp arg) - (let ((start (car arg)) - (end (cdr arg))) - (when (> start end) - (let ((tmp start)) (setq start end) (setq end tmp))) - ;; now start <= end - (let ((i start)) - (while (<= i end) - (aset chars i t) - (setq i (1+ i)))))))) - ;; now chars is a map of the characters in the class - (let ((caret (aref chars ?^)) - (dash (aref chars ?-)) - (class (if (aref chars ?\]) "]" ""))) - (aset chars ?^ nil) - (aset chars ?- nil) - (aset chars ?\] nil) - - (let (start end) - (dotimes (i 256) - (if (aref chars i) - (progn - (unless start (setq start i)) - (setq end i) - (aset chars i nil)) - (when start - (setq class (concat class (sregex--char-range start end))) - (setq start nil)))) - (if start - (setq class (concat class (sregex--char-range start end))))) - - (if (> (length class) 0) - (setq class (concat class (if caret "^") (if dash "-"))) - (setq class (concat class (if dash "-") (if caret "^")))) - (if (and (not complement) (= (length class) 1)) - (regexp-quote class) - (concat "[" (if complement "^") class "]"))))) - -(provide 'sregex) - -;;; sregex.el ends here diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el index 6a91cef1d9..964baed03c 100644 --- a/lisp/textmodes/rst.el +++ b/lisp/textmodes/rst.el @@ -522,7 +522,7 @@ argument list for `rst-re'.") (defvar rst-re-alist) ; Forward declare to use it in `rst-re'. -;; FIXME: Use `sregex' or `rx' instead of re-inventing the wheel. +;; FIXME: Use `rx' instead of re-inventing the wheel. (rst-testcover-add-compose 'rst-re) (defun rst-re (&rest args) ;; testcover: ok. commit 3eb47077d3d9e9e90ac7b9644d13c0da26c3ede8 Author: Po Lu Date: Fri Jun 17 19:04:08 2022 +0800 Clarify doc of `x-display-set-last-user-time' * src/xfns.c (Fx_display_last_user_time): Explain in more detail the meaning of TERMINAL. diff --git a/src/xfns.c b/src/xfns.c index 595f3fffff..3df91679af 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -9478,7 +9478,10 @@ DEFUN ("x-display-set-last-user-time", Fx_display_last_user_time, TIME-OBJECT is the X server time, in milliseconds, of the last user interaction. This is the timestamp that `x-get-selection-internal' will use by default to fetch selection data. -TERMINAL is the terminal on which the user interaction occurred. */) +The optional second argument TERMINAL specifies which display to act +on. TERMINAL should be a terminal object, a frame or a display name +(a string). If TERMINAL is omitted or nil, that stands for the +selected frame's display. */) (Lisp_Object time_object, Lisp_Object terminal) { struct x_display_info *dpyinfo; commit ad74677cf3a0b15b14bf8003ae77c5da12505b60 Author: Stefan Kangas Date: Fri Jun 17 12:04:48 2022 +0200 Delete reference to obsolete library complete.el * doc/misc/tramp.texi (Frequently Asked Questions): Delete reference to obsolete library complete.el. diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index a8079a0fa4..b8279c410a 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -4986,14 +4986,6 @@ minibuffer: (expand-abbrev)) @end group -@group -;; If you use partial-completion-mode -(defadvice PC-do-completion - (before my-PC-do-completion activate) - (expand-abbrev)) -@end group -@end lisp - The reduced typing: @kbd{C-x C-f xy @key{TAB}}. The minibuffer expands for further editing. commit 39826148d62d88906bea80c310a316312d5e681c Author: Mattias Engdegård Date: Fri Jun 17 10:32:54 2022 +0200 * src/fns.c (Fmapconcat): Better empty-string-or-nil detection. diff --git a/src/fns.c b/src/fns.c index a6ceac2935..4a9954ce90 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2836,7 +2836,7 @@ FUNCTION must be a function of one argument, and must return a value ptrdiff_t nargs = 2 * nmapped - 1; eassert (nmapped == leni); - if (!NILP (Fequal (separator, empty_multibyte_string))) + if (NILP (separator) || (STRINGP (separator) && SCHARS (separator) == 0)) nargs = nmapped; else { commit d4d0a09427ca25cf799024abf18b636a0bfd1474 Author: Stefan Kangas Date: Fri Jun 17 10:07:47 2022 +0200 Fix misplaced interactive spec * test/lisp/progmodes/cperl-mode-tests.el (cperl-test-bug-10483): * test/lisp/cedet/srecode/document-tests.el (srecode-document-function-comment-extract-test): * test/lisp/obsolete/inversion-tests.el (inversion-unit-test): * test/lisp/cedet/cedet-files-tests.el (cedet-files-utest): Remove misplaced interactive spec. (cedet-files-utest-list): Minor doc fix; improve formatting. diff --git a/test/lisp/cedet/cedet-files-tests.el b/test/lisp/cedet/cedet-files-tests.el index d264410e3c..daaf3edfc4 100644 --- a/test/lisp/cedet/cedet-files-tests.el +++ b/test/lisp/cedet/cedet-files-tests.el @@ -29,20 +29,17 @@ (require 'cedet-files) (defvar cedet-files-utest-list - '( - ( "/home/me/src/myproj/src/foo.c" . "!home!me!src!myproj!src!foo.c" ) - ( "c:/work/myproj/foo.el" . "!drive_c!work!myproj!foo.el" ) - ( "//windows/proj/foo.java" . "!!windows!proj!foo.java" ) - ( "/home/me/proj!bang/foo.c" . "!home!me!proj!!bang!foo.c" ) - ) - "List of different file names to test. -Each entry is a cons cell of ( FNAME . CONVERTED ) + '(("/home/me/src/myproj/src/foo.c" . "!home!me!src!myproj!src!foo.c") + ("c:/work/myproj/foo.el" . "!drive_c!work!myproj!foo.el") + ("//windows/proj/foo.java" . "!!windows!proj!foo.java") + ("/home/me/proj!bang/foo.c" . "!home!me!proj!!bang!foo.c")) + "List of file names to test. +Each entry is a cons cell of (FNAME . CONVERTED) where FNAME is some file name, and CONVERTED is what it should be converted into.") (ert-deftest cedet-files-utest () - "Test out some file name conversions." - (interactive) + "Test some file name conversions." (dolist (FT cedet-files-utest-list) (let ((dir->file (cedet-directory-name-to-file-name (car FT) t)) (file->dir (cedet-file-name-to-directory-name (cdr FT) t))) diff --git a/test/lisp/cedet/srecode/document-tests.el b/test/lisp/cedet/srecode/document-tests.el index 71c4cd7410..5341bb0936 100644 --- a/test/lisp/cedet/srecode/document-tests.el +++ b/test/lisp/cedet/srecode/document-tests.el @@ -35,8 +35,6 @@ "Test old comment extraction. Dump out the extracted dictionary." :tags '(:unstable) - (interactive) - (srecode-load-tables-for-mode major-mode) (srecode-load-tables-for-mode major-mode 'document) diff --git a/test/lisp/obsolete/inversion-tests.el b/test/lisp/obsolete/inversion-tests.el index 7c8815c282..8af91d7d14 100644 --- a/test/lisp/obsolete/inversion-tests.el +++ b/test/lisp/obsolete/inversion-tests.el @@ -30,7 +30,6 @@ (ert-deftest inversion-unit-test () "Test inversion to make sure it can identify different version strings." - (interactive) (let ((c1 (inversion-package-version 'inversion)) (c1i (inversion-package-incompatibility-version 'inversion)) (c2 (inversion-decode-version "1.3alpha2")) diff --git a/test/lisp/progmodes/cperl-mode-tests.el b/test/lisp/progmodes/cperl-mode-tests.el index 4e0debffb6..47e39aa589 100644 --- a/test/lisp/progmodes/cperl-mode-tests.el +++ b/test/lisp/progmodes/cperl-mode-tests.el @@ -747,7 +747,6 @@ without a statement terminator on the same line does not loop forever. The test starts an asynchronous Emacs batch process under timeout control." :tags '(:expensive-test) - (interactive) (skip-unless (not (getenv "EMACS_HYDRA_CI"))) ; FIXME times out (skip-unless (not (< emacs-major-version 28))) ; times out in older Emacsen (skip-unless (eq cperl-test-mode #'cperl-mode)) commit 4ce2322894a21a1bd3045a6c0dcb2069b31a9c05 Author: Po Lu Date: Fri Jun 17 15:29:59 2022 +0800 Improve compatibility when receiving drops from early XDND programs * lisp/x-dnd.el (x-dnd-handle-xdnd): Save version in state. If version is less than 5, don't put action and success in XdndFinished events. If less than 2, always use `copy' as the selected action. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 81aa565818..d4aa68a10d 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -572,19 +572,23 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (version (x-dnd-version-from-flags flags)) (more-than-3 (x-dnd-more-than-3-from-flags flags)) (dnd-source (aref data 0))) - (if version ;; If flags is bad, version will be nil. - (x-dnd-save-state - window nil nil - (if (> more-than-3 0) - (x-window-property "XdndTypeList" - frame "AnyPropertyType" - dnd-source nil t) - (vector (x-get-atom-name (aref data 2)) - (x-get-atom-name (aref data 3)) - (x-get-atom-name (aref data 4)))))))) + (when version ;; If flags is bad, version will be nil. + (x-dnd-save-state + window nil nil + (if (> more-than-3 0) + (x-window-property "XdndTypeList" + frame "AnyPropertyType" + dnd-source nil t) + (vector (x-get-atom-name (aref data 2)) + (x-get-atom-name (aref data 3)) + (x-get-atom-name (aref data 4)))) + version)))) ((equal "XdndPosition" message) - (let* ((action (x-get-atom-name (aref data 4))) + (let* ((state (x-dnd-get-state-for-frame window)) + (version (aref state 6)) + (action (if (< version 2) 'copy ; `copy' is the default action. + (x-get-atom-name (aref data 4)))) (dnd-source (aref data 0)) (action-type (x-dnd-maybe-call-test-function window @@ -604,7 +608,14 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (x-dnd-get-drop-x-y frame window) (x-dnd-get-drop-width-height frame window (eq accept 1)) - (or reply-action 0)))) + ;; The no-toolkit Emacs build can actually + ;; receive drops from programs that speak + ;; versions of XDND earlier than 3 (such as + ;; GNUstep), since the toplevel window is the + ;; innermost window. + (if (>= version 2) + (or reply-action 0) + 0)))) (x-send-client-message frame dnd-source frame "XdndStatus" 32 list-to-send) (dnd-handle-movement (event-start event)))) @@ -614,7 +625,9 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." ((equal "XdndDrop" message) (if (windowp window) (select-window window)) - (let* ((dnd-source (aref data 0)) + (let* ((state (x-dnd-get-state-for-frame frame)) + (version (aref state 6)) + (dnd-source (aref data 0)) (timestamp (aref data 2)) (value (and (x-dnd-current-type window) (x-get-selection-internal @@ -630,15 +643,17 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (error (message "Error: %s" info) nil)))) - (setq success (if action 1 0)) - - (x-send-client-message - frame dnd-source frame "XdndFinished" 32 - (list (string-to-number (frame-parameter frame 'outer-window-id)) - success ;; 1 = Success, 0 = Error - (if success "XdndActionPrivate" 0) - )) + (when (>= version 2) + (x-send-client-message + frame dnd-source frame "XdndFinished" 32 + (list (string-to-number + (frame-parameter frame 'outer-window-id)) + (if (>= version 5) success 0) ;; 1 = Success, 0 = Error + (when (>= version 5) + (if (not success) 0 + (car (rassoc action + x-dnd-xdnd-to-action))))))) (x-dnd-forget-drop window))) (t (error "Unknown XDND message %s %s" message data)))) commit 10d23f4ed4a7cded2f6177f35b8d9aa9c3686d72 Author: Po Lu Date: Fri Jun 17 06:58:20 2022 +0000 Fix computation of screen width and height on Haiku * src/haiku_support.cc (be_get_screen_dimensions): Use correct macros to extract width and height. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 182f212847..e09f886990 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -3474,8 +3474,8 @@ be_get_screen_dimensions (int *width, int *height) frame = screen.Frame (); - *width = 1 + frame.right - frame.left; - *height = 1 + frame.bottom - frame.top; + *width = BE_RECT_WIDTH (frame); + *height = BE_RECT_HEIGHT (frame); } /* Resize VIEW to WIDTH, HEIGHT. */ commit cce197c630ed3913ef4b5d39bdcb1d684c861a87 Author: Po Lu Date: Fri Jun 17 12:57:03 2022 +0800 Fix instances of not using a usable Motif drag atom * src/xterm.c (xm_get_drag_atom_1): If another frame owns an atom, use it anyway. diff --git a/src/xterm.c b/src/xterm.c index e26cd58679..9d5e1babf3 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1063,6 +1063,7 @@ static void x_frame_rehighlight (struct x_display_info *); static void x_clip_to_row (struct window *, struct glyph_row *, enum glyph_row_area, GC); static struct scroll_bar *x_window_to_scroll_bar (Display *, Window, int); +static struct frame *x_window_to_frame (struct x_display_info *, int); static void x_scroll_bar_report_motion (struct frame **, Lisp_Object *, enum scroll_bar_part *, Lisp_Object *, Lisp_Object *, @@ -2197,6 +2198,7 @@ xm_get_drag_atom_1 (struct x_display_info *dpyinfo, int rc, actual_format; unsigned long i; char *buffer; + Window owner; /* Make sure this operation is done atomically. */ XGrabServer (dpyinfo->display); @@ -2221,11 +2223,18 @@ xm_get_drag_atom_1 (struct x_display_info *dpyinfo, for (i = 0; i < nitems; ++i) { - if (XGetSelectionOwner (dpyinfo->display, - atoms[i]) == None - && !x_had_errors_p (dpyinfo->display)) + owner = XGetSelectionOwner (dpyinfo->display, atoms[i]); + + if (!x_had_errors_p (dpyinfo->display) + && (owner == None + /* If we already own this selection (even if another + frame owns it), use it. There is no way of + knowing when ownership was asserted, so it still + has to be owned again. */ + || x_window_to_frame (dpyinfo, owner))) { atom = atoms[i]; + break; } } commit d1a10a1cf2aac0cc14888043a48528741d591751 Merge: a8cf6567dd f419de6eca Author: Stefan Kangas Date: Fri Jun 17 06:30:35 2022 +0200 Merge from origin/emacs-28 f419de6eca * lisp/textmodes/artist.el: Minor doc fixes. 5ddd0f1a35 * lisp/net/tramp.el (tramp-methods): Fix quoting in docstr... b0c5accb99 Update MS Windows FAQ for MinGW64-w64/MSYS2 commit a8cf6567dd61a58d0bec64fa27beb3e757ffaa51 Author: Po Lu Date: Fri Jun 17 10:57:42 2022 +0800 Improve window manager user time reporting mode switching * src/xterm.c (x_display_set_last_user_time): Stop periodically checking for user time window support. (x_update_frame_user_time_window): New function. (handle_one_xevent): Call it on toplevel ReparentNotify if the frame has been visible at least once. * src/xterm.h (struct x_display_info): Remove `last_user_check_time'. diff --git a/src/xterm.c b/src/xterm.c index 96fe75f41e..e26cd58679 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -6915,7 +6915,6 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time) { #ifndef USE_GTK struct frame *focus_frame = dpyinfo->x_focus_frame; - struct x_output *output; #endif #ifdef ENABLE_CHECKING @@ -6925,56 +6924,6 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time) dpyinfo->last_user_time = time; #ifndef USE_GTK - if (focus_frame - && (dpyinfo->last_user_time - > (dpyinfo->last_user_check_time + 2000))) - { - output = FRAME_X_OUTPUT (focus_frame); - - if (!x_wm_supports (focus_frame, - dpyinfo->Xatom_net_wm_user_time_window)) - { - if (output->user_time_window == None) - output->user_time_window = FRAME_OUTER_WINDOW (focus_frame); - else if (output->user_time_window != FRAME_OUTER_WINDOW (focus_frame)) - { - XDestroyWindow (dpyinfo->display, - output->user_time_window); - XDeleteProperty (dpyinfo->display, - FRAME_OUTER_WINDOW (focus_frame), - dpyinfo->Xatom_net_wm_user_time_window); - output->user_time_window = FRAME_OUTER_WINDOW (focus_frame); - } - } - else - { - if (output->user_time_window == FRAME_OUTER_WINDOW (focus_frame) - || output->user_time_window == None) - { - XSetWindowAttributes attrs; - memset (&attrs, 0, sizeof attrs); - - output->user_time_window - = XCreateWindow (dpyinfo->display, - FRAME_X_WINDOW (focus_frame), - -1, -1, 1, 1, 0, 0, InputOnly, - CopyFromParent, 0, &attrs); - - XDeleteProperty (dpyinfo->display, - FRAME_OUTER_WINDOW (focus_frame), - dpyinfo->Xatom_net_wm_user_time); - XChangeProperty (dpyinfo->display, - FRAME_OUTER_WINDOW (focus_frame), - dpyinfo->Xatom_net_wm_user_time_window, - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &output->user_time_window, - 1); - } - } - - dpyinfo->last_user_check_time = time; - } - if (focus_frame) { while (FRAME_PARENT_FRAME (focus_frame)) @@ -6990,6 +6939,57 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time) #endif } +/* Not needed on GTK because GTK handles reporting the user time + itself. */ + +#ifndef USE_GTK +static void +x_update_frame_user_time_window (struct frame *f) +{ + struct x_output *output; + struct x_display_info *dpyinfo; + XSetWindowAttributes attrs; + + output = FRAME_X_OUTPUT (f); + dpyinfo = FRAME_DISPLAY_INFO (f); + + if (!x_wm_supports (f, dpyinfo->Xatom_net_wm_user_time_window)) + { + if (output->user_time_window == None) + output->user_time_window = FRAME_OUTER_WINDOW (f); + else if (output->user_time_window != FRAME_OUTER_WINDOW (f)) + { + XDestroyWindow (dpyinfo->display, + output->user_time_window); + XDeleteProperty (dpyinfo->display, + FRAME_OUTER_WINDOW (f), + dpyinfo->Xatom_net_wm_user_time_window); + output->user_time_window = FRAME_OUTER_WINDOW (f); + } + } + else + { + if (output->user_time_window == FRAME_OUTER_WINDOW (f) + || output->user_time_window == None) + { + memset (&attrs, 0, sizeof attrs); + + output->user_time_window + = XCreateWindow (dpyinfo->display, FRAME_X_WINDOW (f), + -1, -1, 1, 1, 0, 0, InputOnly, + CopyFromParent, 0, &attrs); + + XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f), + dpyinfo->Xatom_net_wm_user_time); + XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f), + dpyinfo->Xatom_net_wm_user_time_window, + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &output->user_time_window, 1); + } + } +} +#endif + void x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo, Time time) @@ -16914,8 +16914,26 @@ handle_one_xevent (struct x_display_info *dpyinfo, { /* Maybe we shouldn't set this for child frames ?? */ f->output_data.x->parent_desc = event->xreparent.parent; + if (!FRAME_PARENT_FRAME (f)) - x_real_positions (f, &f->left_pos, &f->top_pos); + { + x_real_positions (f, &f->left_pos, &f->top_pos); + + /* Perhaps reparented due to a WM restart. Reset this. */ + FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; + FRAME_DISPLAY_INFO (f)->net_supported_window = 0; + +#ifndef USE_GTK + /* The window manager could have restarted and the new + window manager might not support user time windows, + so update what is used accordingly. + + Note that this doesn't handle changes between + non-reparenting window managers. */ + if (FRAME_X_OUTPUT (f)->has_been_visible) + x_update_frame_user_time_window (f); +#endif + } else { Window root; @@ -16928,10 +16946,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, unblock_input (); } - /* Perhaps reparented due to a WM restart. Reset this. */ - FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; - FRAME_DISPLAY_INFO (f)->net_supported_window = 0; - x_set_frame_alpha (f); } goto OTHER; diff --git a/src/xterm.h b/src/xterm.h index 17402f962c..3ef523d782 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -495,9 +495,8 @@ struct x_display_info struct scroll_bar *last_mouse_scroll_bar; /* Time of last user interaction as returned in X events on this - display, and time where WM support for `_NET_WM_USER_TIME_WINDOW' - was last checked. */ - Time last_user_time, last_user_check_time; + display. */ + Time last_user_time; /* Position where the mouse was last time we reported a motion. This is a position on last_mouse_motion_frame. */ commit 61a312ba0cae10e8e19b7424540751a71d0170b1 Author: Po Lu Date: Fri Jun 17 10:24:05 2022 +0800 Update last event time during DND operations * lisp/x-dnd.el (x-dnd-handle-xdnd, x-dnd-handle-motif): Set last user time to provided timestamp. * src/xfns.c (Fx_display_last_user_time): New function. (syms_of_xfns): New defsubr. * src/xterm.c (x_set_last_user_time_from_lisp): New function. * src/xterm.h: Update prototypes. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 531a58f71f..81aa565818 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -137,6 +137,7 @@ any protocol specific data.") (declare-function x-get-selection-internal "xselect.c" (selection-symbol target-type &optional time-stamp terminal)) +(declare-function x-display-set-last-user-time "xfns.c") (defconst x-dnd-xdnd-to-action '(("XdndActionPrivate" . private) @@ -621,7 +622,7 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (intern (x-dnd-current-type window)) timestamp))) success action) - + (x-display-set-last-user-time timestamp) (setq action (if value (condition-case info (x-dnd-drop-data event frame window value @@ -861,6 +862,7 @@ Return a vector of atoms containing the selection targets." timestamp x y))) + (x-display-set-last-user-time timestamp) (x-send-client-message frame dnd-source frame @@ -898,6 +900,7 @@ Return a vector of atoms containing the selection targets." my-byteorder) reply-flags timestamp))) + (x-display-set-last-user-time timestamp) (x-send-client-message frame dnd-source frame @@ -956,7 +959,7 @@ Return a vector of atoms containing the selection targets." (timestamp (x-dnd-get-motif-value data 4 4 source-byteorder)) action) - + (x-display-set-last-user-time timestamp) (x-send-client-message frame dnd-source frame diff --git a/src/xfns.c b/src/xfns.c index 4cd03136e6..595f3fffff 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -9472,6 +9472,25 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0, #endif /* HAVE_GTK3 */ #endif /* USE_GTK */ +DEFUN ("x-display-set-last-user-time", Fx_display_last_user_time, + Sx_display_set_last_user_time, 1, 2, 0, + doc: /* Set the last user time of TERMINAL to TIME-OBJECT. +TIME-OBJECT is the X server time, in milliseconds, of the last user +interaction. This is the timestamp that `x-get-selection-internal' +will use by default to fetch selection data. +TERMINAL is the terminal on which the user interaction occurred. */) + (Lisp_Object time_object, Lisp_Object terminal) +{ + struct x_display_info *dpyinfo; + Time time; + + dpyinfo = check_x_display_info (terminal); + CONS_TO_INTEGER (time_object, Time, time); + + x_set_last_user_time_from_lisp (dpyinfo, time); + return Qnil; +} + DEFUN ("x-internal-focus-input-context", Fx_internal_focus_input_context, Sx_internal_focus_input_context, 1, 1, 0, doc: /* Focus and set the client window of all focused frames' GTK input context. @@ -9937,6 +9956,7 @@ eliminated in future versions of Emacs. */); defsubr (&Sx_hide_tip); defsubr (&Sx_double_buffered_p); defsubr (&Sx_begin_drag); + defsubr (&Sx_display_set_last_user_time); tip_timer = Qnil; staticpro (&tip_timer); tip_frame = Qnil; diff --git a/src/xterm.c b/src/xterm.c index 45c96c5106..96fe75f41e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -6921,6 +6921,7 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time) #ifdef ENABLE_CHECKING eassert (time <= X_ULONG_MAX); #endif + dpyinfo->last_user_time = time; #ifndef USE_GTK @@ -6989,6 +6990,14 @@ x_display_set_last_user_time (struct x_display_info *dpyinfo, Time time) #endif } +void +x_set_last_user_time_from_lisp (struct x_display_info *dpyinfo, + Time time) +{ + if (dpyinfo->last_user_time > time) + x_display_set_last_user_time (dpyinfo, time); +} + /* Set S->gc to a suitable GC for drawing glyph string S in cursor face. */ diff --git a/src/xterm.h b/src/xterm.h index ad0df6bff9..17402f962c 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1427,10 +1427,11 @@ extern void x_unwind_errors_to (int); extern void x_uncatch_errors (void); extern void x_uncatch_errors_after_check (void); extern void x_clear_errors (Display *); -extern void x_set_window_size (struct frame *f, bool, int, int); -extern void x_make_frame_visible (struct frame *f); -extern void x_make_frame_invisible (struct frame *f); -extern void x_iconify_frame (struct frame *f); +extern void x_set_window_size (struct frame *, bool, int, int); +extern void x_set_last_user_time_from_lisp (struct x_display_info *, Time); +extern void x_make_frame_visible (struct frame *); +extern void x_make_frame_invisible (struct frame *); +extern void x_iconify_frame (struct frame *); extern void x_free_frame_resources (struct frame *); extern void x_wm_set_size_hint (struct frame *, long, bool); commit f419de6eca4ca6a6d03db1eec4b9086a3d1e5b86 Author: Stefan Kangas Date: Thu Jun 16 09:48:05 2022 +0200 * lisp/textmodes/artist.el: Minor doc fixes. diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el index 18e03b4904..e6fddd216d 100644 --- a/lisp/textmodes/artist.el +++ b/lisp/textmodes/artist.el @@ -46,8 +46,8 @@ ;; ;; * Rubber-banding: When drawing lines you can interactively see the ;; result while holding the mouse button down and moving the mouse. If -;; your machine is not fast enough (a 386 is a bit to slow, but a -;; pentium is well enough), you can turn this feature off. You will +;; your machine is not fast enough (a 386 is a bit too slow, but a +;; Pentium is good enough), you can turn this feature off. You will ;; then see 1's and 2's which mark the 1st and 2nd endpoint of the line ;; you are drawing. ;; @@ -75,10 +75,10 @@ ;; * Flood-filling: You can fill any area with a certain character by ;; flood-filling. ;; -;; * Cut copy and paste: You can cut, copy and paste rectangular +;; * Cut, copy and paste: You can cut, copy and paste rectangular ;; regions. Artist also interfaces with the rect package (this can be ;; turned off if it causes you any trouble) so anything you cut in -;; artist can be yanked with C-x r y and vice versa. +;; artist can be yanked with `C-x r y' and vice versa. ;; ;; * Drawing with keys: Everything you can do with the mouse, you can ;; also do without the mouse. @@ -86,7 +86,7 @@ ;; * Arrows: After having drawn a (straight) line or a (straight) ;; poly-line, you can set arrows on the line-ends by typing < or >. ;; -;; * Aspect-ratio: You can set the variable artist-aspect-ratio to +;; * Aspect-ratio: You can set the user option `artist-aspect-ratio' to ;; reflect the height-width ratio for the font you are using. Squares ;; and circles are then drawn square/round. Note, that once your ;; ascii-file is shown with font with a different height-width ratio, @@ -95,7 +95,7 @@ ;; * Picture mode compatibility: Artist is picture mode compatible (this ;; can be turned off). ;; -;; See the documentation for the function artist-mode for a detailed +;; See the documentation for the function `artist-mode' for a detailed ;; description on how to use artist. ;; ;; @@ -119,8 +119,8 @@ ;;; Known bugs: ;; It is not possible to change between shifted and unshifted operation -;; while drawing with the mouse. (See the comment in the function -;; artist-shift-has-changed for further details.) +;; while drawing with the mouse. (See the comment in the function +;; `artist-shift-has-changed' for further details.) ;;; ChangeLog: @@ -149,9 +149,9 @@ ;; ;; 1.2.1 15-Nov-2000 ;; New: Documentation fixes. -;; Bugfix: Sets next-line-add-newlines to t while in artist-mode. +;; Bugfix: Set `next-line-add-newlines' to t while in `artist-mode'. ;; Drawing with keys was confusing without this fix, if -;; next-line-add-newlines was set to nil. +;; `next-line-add-newlines' was set to nil. ;; Thanks to Tatsuo Furukawa for this. ;; ;; 1.2 22-Oct-2000 @@ -462,7 +462,7 @@ This variable is initialized by the `artist-make-prev-next-op-alist' function.") (if artist-picture-compatibility (require 'picture)) -;; Variables that are made local in artist-mode-init +;; Variables that are made local in `artist-mode-init' (defvar artist-key-is-drawing nil) (defvar artist-key-endpoint1 nil) (defvar artist-key-poly-point-list nil) @@ -1334,25 +1334,25 @@ Variables This is a brief overview of the different variables. For more info, see the documentation for the variables (type \\[describe-variable] RET). - artist-rubber-banding Interactively do rubber-banding or not - artist-first-char What to set at first/second point... - artist-second-char ...when not rubber-banding - artist-interface-with-rect If cut/copy/paste should interface with rect - artist-arrows The arrows to use when drawing arrows - artist-aspect-ratio Character height-to-width for squares - artist-trim-line-endings Trimming of line endings - artist-flood-fill-right-border Right border when flood-filling - artist-flood-fill-show-incrementally Update display while filling - artist-pointer-shape Pointer shape to use while drawing - artist-ellipse-left-char Character to use for narrow ellipses - artist-ellipse-right-char Character to use for narrow ellipses - artist-borderless-shapes If shapes should have borders - artist-picture-compatibility Whether or not to be picture mode compatible - artist-vaporize-fuzziness Tolerance when recognizing lines - artist-spray-interval Seconds between repeated sprayings - artist-spray-radius Size of the spray-area - artist-spray-chars The spray-\"color\" - artist-spray-new-chars Initial spray-\"color\" + `artist-rubber-banding' Interactively do rubber-banding or not + `artist-first-char' What to set at first/second point... + `artist-second-char' ...when not rubber-banding + `artist-interface-with-rect' Should cut/copy/paste interface with rect + `artist-arrows' The arrows to use when drawing arrows + `artist-aspect-ratio' Character height-to-width for squares + `artist-trim-line-endings' Trimming of line endings + `artist-flood-fill-right-border' Right border when flood-filling + `artist-flood-fill-show-incrementally' Update display while filling + `artist-pointer-shape' Pointer shape to use while drawing + `artist-ellipse-left-char' Character to use for narrow ellipses + `artist-ellipse-right-char' Character to use for narrow ellipses + `artist-borderless-shapes' If shapes should have borders + `artist-picture-compatibility' Picture mode compatibility on or off + `artist-vaporize-fuzziness' Tolerance when recognizing lines + `artist-spray-interval' Seconds between repeated sprayings + `artist-spray-radius' Size of the spray-area + `artist-spray-chars' The spray-\"color\" + `artist-spray-new-char' Initial spray-\"color\" Hooks commit e75ce9ca384d2f0c52c2a5b53eb9cbac9111956f Author: Stefan Monnier Date: Thu Jun 16 14:05:26 2022 -0400 * src/fns.c (Fmapconcat): Optimize the case where separator=="" diff --git a/src/fns.c b/src/fns.c index 4df944507c..a6ceac2935 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2834,12 +2834,18 @@ FUNCTION must be a function of one argument, and must return a value SAFE_ALLOCA_LISP (args, args_alloc); ptrdiff_t nmapped = mapcar1 (leni, args, function, sequence); ptrdiff_t nargs = 2 * nmapped - 1; + eassert (nmapped == leni); - for (ptrdiff_t i = nmapped - 1; i > 0; i--) - args[i + i] = args[i]; + if (!NILP (Fequal (separator, empty_multibyte_string))) + nargs = nmapped; + else + { + for (ptrdiff_t i = nmapped - 1; i > 0; i--) + args[i + i] = args[i]; - for (ptrdiff_t i = 1; i < nargs; i += 2) - args[i] = separator; + for (ptrdiff_t i = 1; i < nargs; i += 2) + args[i] = separator; + } Lisp_Object ret = Fconcat (nargs, args); SAFE_FREE (); commit cd9b920217e039e9999d9019c60cf7b0db6c2bca Author: Michael Albinus Date: Thu Jun 16 19:29:55 2022 +0200 Fix Tramp test * test/lisp/net/tramp-tests.el (tramp-test03-file-name-method-rules): Remove superfluous checks. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 87c8eb0ada..63fd96cae8 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -2016,17 +2016,7 @@ Also see `ignore'." :type 'user-error) (should-error (expand-file-name "/method:user1@host1|ssh:user2@host2:/path/to/file") - :type 'user-error)) - - ;; Samba does not support file names with periods followed by - ;; spaces, and trailing periods or spaces. - (when (tramp--test-smb-p) - (dolist (file '("foo." "foo. bar" "foo ")) - (should-error - (tramp-smb-get-localname - (tramp-dissect-file-name - (expand-file-name file ert-remote-temporary-file-directory))) - :type 'file-error)))) + :type 'user-error))) (ert-deftest tramp-test04-substitute-in-file-name () "Check `substitute-in-file-name'." commit d934363ca153f7e479f49a88b2d3fcfef6746337 Author: Eli Zaretskii Date: Thu Jun 16 20:22:56 2022 +0300 ; * doc/emacs/package.texi (Package Installation): Fix markup. diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi index 2eb12e096a..7e16c82cf5 100644 --- a/doc/emacs/package.texi +++ b/doc/emacs/package.texi @@ -487,9 +487,9 @@ the package menu with the @samp{held} status. @findex package-recompile-all Emacs byte code is quite stable, but it's possible for byte code to become outdated, or for the compiled files to rely on macros that have -changed in new versions of Emacs. You can use the @kbd{M-x -package-recompile} command to recompile a particular package, or -@kbd{M-x package-recompile-all} to rebuild all the packages. (The +changed in new versions of Emacs. You can use the command @w{@kbd{M-x +package-recompile}} to recompile a particular package, or +@w{@kbd{M-x package-recompile-all}} to recompile all the packages. (The latter command might take quite a while to run if you have many installed packages.) commit 5eb9383ccc9cc74c4e788e5c390412c98da56296 Author: Eli Zaretskii Date: Thu Jun 16 19:53:45 2022 +0300 Fix disruption of windows' display by shr.el * src/window.c (struct saved_window): New member 'vscroll'. (Fset_window_configuration, save_window_save): Save and restore the window's vscroll value. * lisp/net/shr.el (shr-insert-document): Restore the original window's hscroll, in case we are rendering in a window other than where the document will be eventually displayed. This avoids resetting hscroll of windows we use temporarily for shr's rendering job. (Bug#56008) diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 505a093392..b54144576e 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -361,6 +361,7 @@ DOM should be a parse tree as generated by (shr--window-width))) (max-specpdl-size max-specpdl-size) (shr--link-targets nil) + (hscroll (window-hscroll)) ;; `bidi-display-reordering' is supposed to be only used for ;; debugging purposes, but Shr's naïve filling algorithm ;; cannot cope with the complexity of RTL text in an LTR @@ -380,11 +381,14 @@ DOM should be a parse tree as generated by ;; below will misbehave, because it silently assumes that it ;; starts with a non-hscrolled window (vertical-motion will move ;; to a wrong place otherwise). - (set-window-hscroll nil 0) - (shr-descend dom) - (shr-fill-lines start (point)) - (shr--remove-blank-lines-at-the-end start (point)) - (shr--set-target-ids shr--link-targets) + (unwind-protect + (progn + (set-window-hscroll nil 0) + (shr-descend dom) + (shr-fill-lines start (point)) + (shr--remove-blank-lines-at-the-end start (point)) + (shr--set-target-ids shr--link-targets)) + (set-window-hscroll nil hscroll)) (when shr-warning (message "%s" shr-warning)))) diff --git a/src/window.c b/src/window.c index c94e7bde29..ad7a85cf55 100644 --- a/src/window.c +++ b/src/window.c @@ -6901,6 +6901,7 @@ struct saved_window Lisp_Object left_col, top_line, total_cols, total_lines; Lisp_Object normal_cols, normal_lines; Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll; + Lisp_Object vscroll; Lisp_Object parent, prev; Lisp_Object start_at_line_beg; Lisp_Object display_table; @@ -7128,6 +7129,7 @@ the return value is nil. Otherwise the value is t. */) w->suspend_auto_hscroll = !NILP (p->suspend_auto_hscroll); w->min_hscroll = XFIXNAT (p->min_hscroll); w->hscroll_whole = XFIXNAT (p->hscroll_whole); + w->vscroll = -XFIXNAT (p->vscroll); wset_display_table (w, p->display_table); w->left_margin_cols = XFIXNUM (p->left_margin_cols); w->right_margin_cols = XFIXNUM (p->right_margin_cols); @@ -7462,6 +7464,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i) p->suspend_auto_hscroll = w->suspend_auto_hscroll ? Qt : Qnil; XSETFASTINT (p->min_hscroll, w->min_hscroll); XSETFASTINT (p->hscroll_whole, w->hscroll_whole); + XSETFASTINT (p->vscroll, -w->vscroll); p->display_table = w->display_table; p->left_margin_cols = make_fixnum (w->left_margin_cols); p->right_margin_cols = make_fixnum (w->right_margin_cols); commit 28218092a699c637ab5164db69ff68f3209c5f84 Author: Michael Heerdegen Date: Tue Jun 14 13:26:06 2022 +0200 Allow number register insertion in Calc (Bug#55943) * lisp/calc/calc-yank.el (calc-get-register): Convert number values to strings. diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el index 172ccf1adc..c98505a0b1 100644 --- a/lisp/calc/calc-yank.el +++ b/lisp/calc/calc-yank.el @@ -266,14 +266,16 @@ as well as set the contents of the Emacs register REGISTER to TEXT." "Return the CALCVAL portion of the contents of the Calc register REG, unless the TEXT portion doesn't match the contents of the Emacs register REG, in which case either return the contents of the Emacs register (if it is -text) or nil." +text or a number) or nil." (let ((cval (cdr (assq reg calc-register-alist))) (val (cdr (assq reg register-alist)))) - (if (stringp val) - (if (and (stringp (car cval)) - (string= (car cval) val)) - (cdr cval) - val)))) + (cond + ((stringp val) + (if (and (stringp (car cval)) + (string= (car cval) val)) + (cdr cval) + val)) + ((numberp val) (number-to-string val))))) (defun calc-copy-to-register (register start end &optional delete-flag) "Copy the lines in the region into register REGISTER. commit a0f7d81a8dfefc20a283585dca3a37240a2b7a9a Author: Mattias Engdegård Date: Thu Jun 16 16:04:48 2022 +0200 * src/fns.c (mapcar1): Test types in rough order of likelyhood. diff --git a/src/fns.c b/src/fns.c index 97af39c416..4df944507c 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2757,20 +2757,26 @@ usage: (nconc &rest LISTS) */) static EMACS_INT mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq) { - if (VECTORP (seq) || COMPILEDP (seq)) + if (NILP (seq)) + return 0; + else if (CONSP (seq)) { + Lisp_Object tail = seq; for (ptrdiff_t i = 0; i < leni; i++) { - Lisp_Object dummy = call1 (fn, AREF (seq, i)); + if (! CONSP (tail)) + return i; + Lisp_Object dummy = call1 (fn, XCAR (tail)); if (vals) vals[i] = dummy; + tail = XCDR (tail); } } - else if (BOOL_VECTOR_P (seq)) + else if (VECTORP (seq) || COMPILEDP (seq)) { - for (EMACS_INT i = 0; i < leni; i++) + for (ptrdiff_t i = 0; i < leni; i++) { - Lisp_Object dummy = call1 (fn, bool_vector_ref (seq, i)); + Lisp_Object dummy = call1 (fn, AREF (seq, i)); if (vals) vals[i] = dummy; } @@ -2788,17 +2794,14 @@ mapcar1 (EMACS_INT leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq) vals[i_before] = dummy; } } - else /* Must be a list, since Flength did not get an error */ + else { - Lisp_Object tail = seq; - for (ptrdiff_t i = 0; i < leni; i++) + eassert (BOOL_VECTOR_P (seq)); + for (EMACS_INT i = 0; i < leni; i++) { - if (! CONSP (tail)) - return i; - Lisp_Object dummy = call1 (fn, XCAR (tail)); + Lisp_Object dummy = call1 (fn, bool_vector_ref (seq, i)); if (vals) vals[i] = dummy; - tail = XCDR (tail); } } commit 946d70a8910a827d74a384ff6421b9e952e0df2e Author: Mattias Engdegård Date: Thu Jun 16 14:11:03 2022 +0200 Use BASE_EQ instead of EQ where obviously safe * src/alloc.c (deadp): * src/buffer.c (reset_buffer_local_variables, candidate_buffer) (Fkill_buffer, Fbuffer_swap_text, Fmake_overlay, Fmove_overlay): * src/callint.c (Fcall_interactively): * src/coding.c (decode_coding_object, encode_coding_object) (code_convert_region, Ffind_operation_coding_system): * src/comp.c (Fcomp_el_to_eln_rel_filename): * src/conf_post.h (RE_TRANSLATE_P): * src/data.c (Fkill_local_variable, Fash, expt_integer): * src/dired.c (file_name_completion): * src/dispnew.c (set_window_cursor_after_update, update_frame_1) (Fframe_or_buffer_changed_p): * src/doc.c (Fdocumentation, Fdocumentation_property) (default_to_grave_quoting_style): * src/editfns.c (Fconstrain_to_field, save_excursion_save) (save_excursion_restore, Fngettext): * src/eval.c (Fautoload, un_autoload, specbind): * src/fileio.c (Fmake_temp_file_internal): * src/fns.c (string_char_to_byte, string_byte_to_char) (Fnthcdr, Fnreverse): * src/indent.c (vmotion): * src/inotify.c (add_watch): * src/keyboard.c (command_loop_1, read_char) (read_char_minibuf_menu_prompt): * src/lread.c (oblookup): * src/macfont.m (macfont_descriptor_entity, macfont_open): * src/minibuf.c (Finnermost_minibuffer_p, Ftry_completion) (Ftest_completion): * src/nsfns.m (ns_set_icon_name): * src/pdumper.c (dump_queue_dequeue): * src/pgtkfns.c (pgtk_set_icon_type, pgtk_set_icon_name): * src/process.c (Faccept_process_output): * src/textprop.c (set_text_properties): * src/w32fns.c (w32_set_icon_type, w32_set_icon_name): * src/w32select.c (validate_coding_system): * src/window.c (decode_next_window_args, window_loop) (save_window_save): * src/xdisp.c (wset_redisplay): * src/xfaces.c (Fx_family_fonts, resolve_face_name) (gui_supports_face_attributes_p): * src/xfns.c (x_set_icon_type, x_set_icon_name): * src/xselect.c (clean_local_selection_data): Use BASE_EQ instead of EQ where it is obvious that neither argument can be a symbol with properties or at least one argument is a non-symbol. diff --git a/src/alloc.c b/src/alloc.c index 02d3a3ea3a..55e18ecd77 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -475,7 +475,7 @@ enum mem_type static bool deadp (Lisp_Object x) { - return EQ (x, dead_object ()); + return BASE_EQ (x, dead_object ()); } #ifdef GC_MALLOC_CHECK diff --git a/src/buffer.c b/src/buffer.c index a0761f5b59..7adcd22d88 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1065,7 +1065,7 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too) eassert (XSYMBOL (sym)->u.s.redirect == SYMBOL_LOCALIZED); /* Need not do anything if some other buffer's binding is now cached. */ - if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer)) + if (BASE_EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer)) { /* Symbol is set up for this buffer's old local value: swap it out! */ @@ -1607,7 +1607,7 @@ This does not change the name of the visited file (if any). */) static bool candidate_buffer (Lisp_Object b, Lisp_Object buffer) { - return (BUFFERP (b) && !EQ (b, buffer) + return (BUFFERP (b) && !BASE_EQ (b, buffer) && BUFFER_LIVE_P (XBUFFER (b)) && !BUFFER_HIDDEN_P (XBUFFER (b))); } @@ -1851,7 +1851,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) since anything can happen within do_yes_or_no_p. */ /* Don't kill the minibuffer now current. */ - if (EQ (buffer, XWINDOW (minibuf_window)->contents)) + if (BASE_EQ (buffer, XWINDOW (minibuf_window)->contents)) return Qnil; /* When we kill an ordinary buffer which shares its buffer text @@ -1895,7 +1895,7 @@ cleaning up all windows currently displaying the buffer to be killed. */) is the sole other buffer give up. */ XSETBUFFER (tem, current_buffer); if (EQ (tem, XWINDOW (minibuf_window)->contents) - && EQ (buffer, Fother_buffer (buffer, Qnil, Qnil))) + && BASE_EQ (buffer, Fother_buffer (buffer, Qnil, Qnil))) return Qnil; /* Now there is no question: we can kill the buffer. */ @@ -2501,23 +2501,23 @@ results, see Info node `(elisp)Swapping Text'. */) { ws = Fcons (w, ws); if (MARKERP (XWINDOW (w)->pointm) - && (EQ (XWINDOW (w)->contents, buf1) - || EQ (XWINDOW (w)->contents, buf2))) + && (BASE_EQ (XWINDOW (w)->contents, buf1) + || BASE_EQ (XWINDOW (w)->contents, buf2))) Fset_marker (XWINDOW (w)->pointm, make_fixnum (BUF_BEGV (XBUFFER (XWINDOW (w)->contents))), XWINDOW (w)->contents); /* Blindly copied from pointm part. */ if (MARKERP (XWINDOW (w)->old_pointm) - && (EQ (XWINDOW (w)->contents, buf1) - || EQ (XWINDOW (w)->contents, buf2))) + && (BASE_EQ (XWINDOW (w)->contents, buf1) + || BASE_EQ (XWINDOW (w)->contents, buf2))) Fset_marker (XWINDOW (w)->old_pointm, make_fixnum (BUF_BEGV (XBUFFER (XWINDOW (w)->contents))), XWINDOW (w)->contents); if (MARKERP (XWINDOW (w)->start) - && (EQ (XWINDOW (w)->contents, buf1) - || EQ (XWINDOW (w)->contents, buf2))) + && (BASE_EQ (XWINDOW (w)->contents, buf1) + || BASE_EQ (XWINDOW (w)->contents, buf2))) Fset_marker (XWINDOW (w)->start, make_fixnum (XBUFFER (XWINDOW (w)->contents)->last_window_start), @@ -2527,10 +2527,11 @@ results, see Info node `(elisp)Swapping Text'. */) } if (current_buffer->text->intervals) - (eassert (EQ (current_buffer->text->intervals->up.obj, buffer)), + (eassert (BASE_EQ (current_buffer->text->intervals->up.obj, buffer)), XSETBUFFER (current_buffer->text->intervals->up.obj, current_buffer)); if (other_buffer->text->intervals) - (eassert (EQ (other_buffer->text->intervals->up.obj, Fcurrent_buffer ())), + (eassert (BASE_EQ (other_buffer->text->intervals->up.obj, + Fcurrent_buffer ())), XSETBUFFER (other_buffer->text->intervals->up.obj, other_buffer)); return Qnil; @@ -3940,9 +3941,9 @@ for the rear of the overlay advance when text is inserted there else CHECK_BUFFER (buffer); - if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer)) + if (MARKERP (beg) && !BASE_EQ (Fmarker_buffer (beg), buffer)) signal_error ("Marker points into wrong buffer", beg); - if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer)) + if (MARKERP (end) && !BASE_EQ (Fmarker_buffer (end), buffer)) signal_error ("Marker points into wrong buffer", end); CHECK_FIXNUM_COERCE_MARKER (beg); @@ -4060,9 +4061,9 @@ buffer. */) if (NILP (Fbuffer_live_p (buffer))) error ("Attempt to move overlay to a dead buffer"); - if (MARKERP (beg) && !EQ (Fmarker_buffer (beg), buffer)) + if (MARKERP (beg) && !BASE_EQ (Fmarker_buffer (beg), buffer)) signal_error ("Marker points into wrong buffer", beg); - if (MARKERP (end) && !EQ (Fmarker_buffer (end), buffer)) + if (MARKERP (end) && !BASE_EQ (Fmarker_buffer (end), buffer)) signal_error ("Marker points into wrong buffer", end); CHECK_FIXNUM_COERCE_MARKER (beg); diff --git a/src/callint.c b/src/callint.c index 8283c61da6..ffa3b231eb 100644 --- a/src/callint.c +++ b/src/callint.c @@ -439,7 +439,7 @@ invoke it (via an `interactive' spec that contains, for instance, an && (w = XCAR (w), WINDOWP (w))) { if (MINI_WINDOW_P (XWINDOW (w)) - && ! (minibuf_level > 0 && EQ (w, minibuf_window))) + && ! (minibuf_level > 0 && BASE_EQ (w, minibuf_window))) error ("Attempt to select inactive minibuffer window"); /* If the current buffer wants to clean up, let it. */ @@ -509,7 +509,7 @@ invoke it (via an `interactive' spec that contains, for instance, an case 'b': /* Name of existing buffer. */ args[i] = Fcurrent_buffer (); - if (EQ (selected_window, minibuf_window)) + if (BASE_EQ (selected_window, minibuf_window)) args[i] = Fother_buffer (args[i], Qnil, Qnil); args[i] = Fread_buffer (callint_message, args[i], Qt, Qnil); break; diff --git a/src/coding.c b/src/coding.c index aa32efc3f6..68f3201de8 100644 --- a/src/coding.c +++ b/src/coding.c @@ -8194,7 +8194,7 @@ decode_coding_object (struct coding_system *coding, if (saved_pt >= 0) { /* This is the case of: - (BUFFERP (src_object) && EQ (src_object, dst_object)) + (BUFFERP (src_object) && BASE_EQ (src_object, dst_object)) As we have moved PT while replacing the original buffer contents, we must recover it now. */ set_buffer_internal (XBUFFER (src_object)); @@ -8298,7 +8298,7 @@ encode_coding_object (struct coding_system *coding, attrs = CODING_ID_ATTRS (coding->id); bool same_buffer = false; - if (EQ (src_object, dst_object) && BUFFERP (src_object)) + if (BASE_EQ (src_object, dst_object) && BUFFERP (src_object)) { struct Lisp_Marker *tail; @@ -8379,7 +8379,7 @@ encode_coding_object (struct coding_system *coding, if (BUFFERP (dst_object)) { coding->dst_object = dst_object; - if (EQ (src_object, dst_object)) + if (BASE_EQ (src_object, dst_object)) { coding->dst_pos = from; coding->dst_pos_byte = from_byte; @@ -8434,7 +8434,7 @@ encode_coding_object (struct coding_system *coding, if (saved_pt >= 0) { /* This is the case of: - (BUFFERP (src_object) && EQ (src_object, dst_object)) + (BUFFERP (src_object) && BASE_EQ (src_object, dst_object)) As we have moved PT while replacing the original buffer contents, we must recover it now. */ set_buffer_internal (XBUFFER (src_object)); @@ -9416,7 +9416,7 @@ code_convert_region (Lisp_Object start, Lisp_Object end, setup_coding_system (coding_system, &coding); coding.mode |= CODING_MODE_LAST_BLOCK; - if (BUFFERP (dst_object) && !EQ (dst_object, src_object)) + if (BUFFERP (dst_object) && !BASE_EQ (dst_object, src_object)) { struct buffer *buf = XBUFFER (dst_object); ptrdiff_t buf_pt = BUF_PT (buf); @@ -10785,7 +10785,7 @@ usage: (find-operation-coding-system OPERATION ARGUMENTS...) */) && ((STRINGP (target) && STRINGP (XCAR (elt)) && fast_string_match (XCAR (elt), target) >= 0) - || (FIXNUMP (target) && EQ (target, XCAR (elt))))) + || (FIXNUMP (target) && BASE_EQ (target, XCAR (elt))))) { val = XCDR (elt); /* Here, if VAL is both a valid coding system and a valid diff --git a/src/comp.c b/src/comp.c index c230536ac5..0c78e60fc4 100644 --- a/src/comp.c +++ b/src/comp.c @@ -4397,7 +4397,7 @@ one for the file name and another for its contents, followed by .eln. */) { Lisp_Object match_idx = Fstring_match (XCAR (lds_re_tail), filename, Qnil, Qnil); - if (EQ (match_idx, make_fixnum (0))) + if (BASE_EQ (match_idx, make_fixnum (0))) { filename = Freplace_match (build_string ("//"), Qt, Qt, filename, Qnil); diff --git a/src/conf_post.h b/src/conf_post.h index 5108e44efb..6ecebf36ab 100644 --- a/src/conf_post.h +++ b/src/conf_post.h @@ -267,7 +267,7 @@ extern void _DebPrint (const char *fmt, ...); /* Tell regex.c to use a type compatible with Emacs. */ #define RE_TRANSLATE_TYPE Lisp_Object #define RE_TRANSLATE(TBL, C) char_table_translate (TBL, C) -#define RE_TRANSLATE_P(TBL) (!EQ (TBL, make_fixnum (0))) +#define RE_TRANSLATE_P(TBL) (!BASE_EQ (TBL, make_fixnum (0))) #endif /* Tell time_rz.c to use Emacs's getter and setter for TZ. diff --git a/src/data.c b/src/data.c index cf180b16fb..d665da04da 100644 --- a/src/data.c +++ b/src/data.c @@ -2330,7 +2330,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */) forwarded objects won't work right. */ { Lisp_Object buf; XSETBUFFER (buf, current_buffer); - if (EQ (buf, blv->where)) + if (BASE_EQ (buf, blv->where)) swap_in_global_binding (sym); } @@ -3522,7 +3522,7 @@ In this case, the sign bit is duplicated. */) if (! FIXNUMP (count)) { - if (EQ (value, make_fixnum (0))) + if (BASE_EQ (value, make_fixnum (0))) return value; if (mpz_sgn (*xbignum_val (count)) < 0) { @@ -3567,11 +3567,11 @@ Lisp_Object expt_integer (Lisp_Object x, Lisp_Object y) { /* Special cases for -1 <= x <= 1, which never overflow. */ - if (EQ (x, make_fixnum (1))) + if (BASE_EQ (x, make_fixnum (1))) return x; - if (EQ (x, make_fixnum (0))) - return EQ (x, y) ? make_fixnum (1) : x; - if (EQ (x, make_fixnum (-1))) + if (BASE_EQ (x, make_fixnum (0))) + return BASE_EQ (x, y) ? make_fixnum (1) : x; + if (BASE_EQ (x, make_fixnum (-1))) return ((FIXNUMP (y) ? XFIXNUM (y) & 1 : mpz_odd_p (*xbignum_val (y))) ? x : make_fixnum (1)); diff --git a/src/dired.c b/src/dired.c index cd50012ddc..e31ad9121c 100644 --- a/src/dired.c +++ b/src/dired.c @@ -521,9 +521,9 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, name = DECODE_FILE (name); ptrdiff_t name_blen = SBYTES (name), name_len = SCHARS (name); if (completion_ignore_case - && !EQ (Fcompare_strings (name, zero, file_len, file, zero, file_len, - Qt), - Qt)) + && !BASE_EQ (Fcompare_strings (name, zero, file_len, file, zero, + file_len, Qt), + Qt)) continue; switch (dirent_type (dp)) @@ -603,10 +603,12 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, skip = name_len - elt_len; cmp_len = make_fixnum (elt_len); if (skip < 0 - || !EQ (Fcompare_strings (name, make_fixnum (skip), - Qnil, - elt, zero, cmp_len, Qt), - Qt)) + || !BASE_EQ (Fcompare_strings (name, + make_fixnum (skip), + Qnil, + elt, zero, cmp_len, + Qt), + Qt)) continue; } break; @@ -637,10 +639,12 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, skip = name_len - elt_len; cmp_len = make_fixnum (elt_len); if (skip < 0 - || !EQ (Fcompare_strings (name, make_fixnum (skip), - Qnil, - elt, zero, cmp_len, Qt), - Qt)) + || !BASE_EQ (Fcompare_strings (name, + make_fixnum (skip), + Qnil, + elt, zero, cmp_len, + Qt), + Qt)) continue; } break; @@ -699,7 +703,7 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, = Fcompare_strings (name, zero, make_fixnum (compare), file, zero, make_fixnum (compare), completion_ignore_case ? Qt : Qnil); - if (!EQ (cmp, Qt)) + if (!BASE_EQ (cmp, Qt)) continue; } @@ -722,7 +726,8 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, = Fcompare_strings (bestmatch, zero, make_fixnum (compare), name, zero, make_fixnum (compare), completion_ignore_case ? Qt : Qnil); - ptrdiff_t matchsize = EQ (cmp, Qt) ? compare : eabs (XFIXNUM (cmp)) - 1; + ptrdiff_t matchsize = BASE_EQ (cmp, Qt) + ? compare : eabs (XFIXNUM (cmp)) - 1; if (completion_ignore_case) { @@ -751,13 +756,13 @@ file_name_completion (Lisp_Object file, Lisp_Object dirname, bool all_flag, file, zero, Qnil, Qnil), - EQ (Qt, cmp)) + BASE_EQ (Qt, cmp)) && (cmp = Fcompare_strings (bestmatch, zero, make_fixnum (SCHARS (file)), file, zero, Qnil, Qnil), - ! EQ (Qt, cmp)))) + ! BASE_EQ (Qt, cmp)))) bestmatch = name; } bestmatchsize = matchsize; diff --git a/src/dispnew.c b/src/dispnew.c index 7a4d9f8710..3bd2e0e96c 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -4284,11 +4284,11 @@ set_window_cursor_after_update (struct window *w) /* If we are showing a message instead of the mini-buffer, show the cursor for the message instead. */ && XWINDOW (minibuf_window) == w - && EQ (minibuf_window, echo_area_window) + && BASE_EQ (minibuf_window, echo_area_window) /* These cases apply only to the frame that contains the active mini-buffer window. */ && FRAME_HAS_MINIBUF_P (f) - && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)) + && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)) { cx = cy = vpos = hpos = 0; @@ -4948,13 +4948,13 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p, /* If we are showing a message instead of the mini-buffer, show the cursor for the message instead of for the (now hidden) mini-buffer contents. */ - || (EQ (minibuf_window, selected_window) - && EQ (minibuf_window, echo_area_window) + || (BASE_EQ (minibuf_window, selected_window) + && BASE_EQ (minibuf_window, echo_area_window) && !NILP (echo_area_buffer[0]))) /* These cases apply only to the frame that contains the active mini-buffer window. */ && FRAME_HAS_MINIBUF_P (f) - && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)) + && BASE_EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)) { int top = WINDOW_TOP_EDGE_LINE (XWINDOW (FRAME_MINIBUF_WINDOW (f))); int col; @@ -6306,7 +6306,7 @@ pass nil for VARIABLE. */) { if (idx == ASIZE (state)) goto changed; - if (!EQ (AREF (state, idx++), frame)) + if (!BASE_EQ (AREF (state, idx++), frame)) goto changed; if (idx == ASIZE (state)) goto changed; @@ -6321,7 +6321,7 @@ pass nil for VARIABLE. */) continue; if (idx == ASIZE (state)) goto changed; - if (!EQ (AREF (state, idx++), buf)) + if (!BASE_EQ (AREF (state, idx++), buf)) goto changed; if (idx == ASIZE (state)) goto changed; diff --git a/src/doc.c b/src/doc.c index 14db3189f3..34b80d03aa 100644 --- a/src/doc.c +++ b/src/doc.c @@ -346,7 +346,7 @@ string is passed through `substitute-command-keys'. */) /* If DOC is 0, it's typically because of a dumped file missing from the DOC file (bug in src/Makefile.in). */ - if (EQ (doc, make_fixnum (0))) + if (BASE_EQ (doc, make_fixnum (0))) doc = Qnil; if (FIXNUMP (doc) || CONSP (doc)) { @@ -400,7 +400,7 @@ aren't strings. */) tem = Fget (indirect, prop); } - if (EQ (tem, make_fixnum (0))) + if (BASE_EQ (tem, make_fixnum (0))) tem = Qnil; /* See if we want to look for the string in the DOC file. */ @@ -637,7 +637,7 @@ default_to_grave_quoting_style (void) Lisp_Object dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table), LEFT_SINGLE_QUOTATION_MARK); return (VECTORP (dv) && ASIZE (dv) == 1 - && EQ (AREF (dv, 0), make_fixnum ('`'))); + && BASE_EQ (AREF (dv, 0), make_fixnum ('`'))); } DEFUN ("text-quoting-style", Ftext_quoting_style, diff --git a/src/editfns.c b/src/editfns.c index 17f0252969..84947af508 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -648,7 +648,7 @@ Field boundaries are not noticed if `inhibit-field-text-motion' is non-nil. */) prev_new = make_fixnum (XFIXNUM (new_pos) - 1); if (NILP (Vinhibit_field_text_motion) - && !EQ (new_pos, old_pos) + && !BASE_EQ (new_pos, old_pos) && (!NILP (Fget_char_property (new_pos, Qfield, Qnil)) || !NILP (Fget_char_property (old_pos, Qfield, Qnil)) /* To recognize field boundaries, we must also look at the @@ -797,7 +797,7 @@ save_excursion_save (union specbinding *pdl) pdl->unwind_excursion.marker = Fpoint_marker (); /* Selected window if current buffer is shown in it, nil otherwise. */ pdl->unwind_excursion.window - = (EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ()) + = (BASE_EQ (XWINDOW (selected_window)->contents, Fcurrent_buffer ()) ? selected_window : Qnil); } @@ -821,7 +821,7 @@ save_excursion_restore (Lisp_Object marker, Lisp_Object window) /* If buffer was visible in a window, and a different window was selected, and the old selected window is still showing this buffer, restore point in that window. */ - if (WINDOWP (window) && !EQ (window, selected_window)) + if (WINDOWP (window) && !BASE_EQ (window, selected_window)) { /* Set window point if WINDOW is live and shows the current buffer. */ Lisp_Object contents = XWINDOW (window)->contents; @@ -2843,7 +2843,7 @@ otherwise MSGID-PLURAL. */) CHECK_INTEGER (n); /* Placeholder implementation until we get our act together. */ - return EQ (n, make_fixnum (1)) ? msgid : msgid_plural; + return BASE_EQ (n, make_fixnum (1)) ? msgid : msgid_plural; } DEFUN ("message", Fmessage, Smessage, 1, MANY, 0, diff --git a/src/eval.c b/src/eval.c index 1c62b9248e..346dff8bdc 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2195,7 +2195,7 @@ this does nothing and returns nil. */) && !AUTOLOADP (XSYMBOL (function)->u.s.function)) return Qnil; - if (!NILP (Vpurify_flag) && EQ (docstring, make_fixnum (0))) + if (!NILP (Vpurify_flag) && BASE_EQ (docstring, make_fixnum (0))) /* `read1' in lread.c has found the docstring starting with "\ and assumed the docstring will be provided by Snarf-documentation, so it passed us 0 instead. But that leads to accidental sharing in purecopy's @@ -2216,7 +2216,7 @@ un_autoload (Lisp_Object oldqueue) while (CONSP (queue)) { Lisp_Object first = XCAR (queue); - if (CONSP (first) && EQ (XCAR (first), make_fixnum (0))) + if (CONSP (first) && BASE_EQ (XCAR (first), make_fixnum (0))) Vfeatures = XCDR (first); else Ffset (first, Fcar (Fcdr (Fget (first, Qfunction_history)))); @@ -3451,7 +3451,7 @@ specbind (Lisp_Object symbol, Lisp_Object value) specpdl_ptr->let.where = Fcurrent_buffer (); eassert (sym->u.s.redirect != SYMBOL_LOCALIZED - || (EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ()))); + || (BASE_EQ (SYMBOL_BLV (sym)->where, Fcurrent_buffer ()))); if (sym->u.s.redirect == SYMBOL_LOCALIZED) { diff --git a/src/fileio.c b/src/fileio.c index 39b731bb0b..10d4b8bc15 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -708,7 +708,7 @@ This function does not grok magic file names. */) memset (data + prefix_len, 'X', nX); memcpy (data + prefix_len + nX, SSDATA (encoded_suffix), suffix_len); int kind = (NILP (dir_flag) ? GT_FILE - : EQ (dir_flag, make_fixnum (0)) ? GT_NOCREATE + : BASE_EQ (dir_flag, make_fixnum (0)) ? GT_NOCREATE : GT_DIR); int fd = gen_tempname (data, suffix_len, O_BINARY | O_CLOEXEC, kind); bool failed = fd < 0; diff --git a/src/fns.c b/src/fns.c index 6094c00b27..97af39c416 100644 --- a/src/fns.c +++ b/src/fns.c @@ -1045,7 +1045,7 @@ string_char_to_byte (Lisp_Object string, ptrdiff_t char_index) if (best_above == best_above_byte) return char_index; - if (EQ (string, string_char_byte_cache_string)) + if (BASE_EQ (string, string_char_byte_cache_string)) { if (string_char_byte_cache_charpos < char_index) { @@ -1105,7 +1105,7 @@ string_byte_to_char (Lisp_Object string, ptrdiff_t byte_index) if (best_above == best_above_byte) return byte_index; - if (EQ (string, string_char_byte_cache_string)) + if (BASE_EQ (string, string_char_byte_cache_string)) { if (string_char_byte_cache_bytepos < byte_index) { @@ -1576,7 +1576,7 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0, { /* If the tortoise just jumped (which is rare), update TORTOISE_NUM accordingly. */ - if (EQ (tail, li.tortoise)) + if (BASE_EQ (tail, li.tortoise)) tortoise_num = num; saved_tail = XCDR (tail); @@ -2014,7 +2014,7 @@ This function may destructively modify SEQ to produce the value. */) next = XCDR (tail); /* If SEQ contains a cycle, attempting to reverse it in-place will inevitably come back to SEQ. */ - if (EQ (next, seq)) + if (BASE_EQ (next, seq)) circular_list (seq); Fsetcdr (tail, prev); prev = tail; diff --git a/src/indent.c b/src/indent.c index 51f6f414de..c071b43ab4 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1861,7 +1861,7 @@ vmotion (ptrdiff_t from, ptrdiff_t from_byte, /* If the window contains this buffer, use it for getting text properties. Otherwise use the current buffer as arg for doing that. */ - if (EQ (w->contents, Fcurrent_buffer ())) + if (BASE_EQ (w->contents, Fcurrent_buffer ())) text_prop_object = window; else text_prop_object = Fcurrent_buffer (); diff --git a/src/inotify.c b/src/inotify.c index e92ad40abc..16d20e7e92 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -217,7 +217,7 @@ add_watch (int wd, Lisp_Object filename, /* Assign a watch ID that is not already in use, by looking for a gap in the existing sorted list. */ for (; ! NILP (XCDR (tail)); tail = XCDR (tail), id++) - if (!EQ (XCAR (XCAR (XCDR (tail))), make_fixnum (id))) + if (!BASE_EQ (XCAR (XCAR (XCDR (tail))), make_fixnum (id))) break; if (MOST_POSITIVE_FIXNUM < id) emacs_abort (); diff --git a/src/keyboard.c b/src/keyboard.c index 55d710ed62..60ff8f5ea6 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1345,7 +1345,7 @@ command_loop_1 (void) if (minibuf_level && !NILP (echo_area_buffer[0]) - && EQ (minibuf_window, echo_area_window) + && BASE_EQ (minibuf_window, echo_area_window) && NUMBERP (Vminibuffer_message_timeout)) { /* Bind inhibit-quit to t so that C-g gets read in @@ -2576,7 +2576,7 @@ read_char (int commandflag, Lisp_Object map, && (input_was_pending || !redisplay_dont_pause))) { input_was_pending = input_pending; - if (help_echo_showing_p && !EQ (selected_window, minibuf_window)) + if (help_echo_showing_p && !BASE_EQ (selected_window, minibuf_window)) redisplay_preserve_echo_area (5); else redisplay (); @@ -2924,7 +2924,7 @@ read_char (int commandflag, Lisp_Object map, goto exit; } - if (EQ (c, make_fixnum (-2))) + if (BASE_EQ (c, make_fixnum (-2))) return c; if (CONSP (c) && EQ (XCAR (c), Qt)) @@ -3249,7 +3249,7 @@ read_char (int commandflag, Lisp_Object map, unbind_to (count, Qnil); redisplay (); - if (EQ (c, make_fixnum (040))) + if (BASE_EQ (c, make_fixnum (040))) { cancel_echoing (); do @@ -9498,7 +9498,7 @@ read_char_minibuf_menu_prompt (int commandflag, if (!FIXNUMP (obj) || XFIXNUM (obj) == -2 || (! EQ (obj, menu_prompt_more_char) && (!FIXNUMP (menu_prompt_more_char) - || ! EQ (obj, make_fixnum (Ctl (XFIXNUM (menu_prompt_more_char))))))) + || ! BASE_EQ (obj, make_fixnum (Ctl (XFIXNUM (menu_prompt_more_char))))))) { if (!NILP (KVAR (current_kboard, defining_kbd_macro))) store_kbd_macro_char (obj); diff --git a/src/lread.c b/src/lread.c index 77831f028e..a00590e466 100644 --- a/src/lread.c +++ b/src/lread.c @@ -4855,7 +4855,7 @@ oblookup (Lisp_Object obarray, register const char *ptr, ptrdiff_t size, ptrdiff hash = hash_string (ptr, size_byte) % obsize; bucket = AREF (obarray, hash); oblookup_last_bucket_number = hash; - if (EQ (bucket, make_fixnum (0))) + if (BASE_EQ (bucket, make_fixnum (0))) ; else if (!SYMBOLP (bucket)) /* Like CADR error message. */ diff --git a/src/macfont.m b/src/macfont.m index 4dd55e7746..fe30908f5d 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -929,7 +929,7 @@ static void mac_font_get_glyphs_for_variants (CFDataRef, UTF32Char, cfnumber_get_font_symbolic_traits_value (num, &sym_traits); CFRelease (dict); } - if (EQ (AREF (entity, FONT_SIZE_INDEX), make_fixnum (0))) + if (BASE_EQ (AREF (entity, FONT_SIZE_INDEX), make_fixnum (0))) ASET (entity, FONT_AVGWIDTH_INDEX, make_fixnum (0)); ASET (entity, FONT_EXTRA_INDEX, Fcopy_sequence (extra)); name = CTFontDescriptorCopyAttribute (desc, kCTFontNameAttribute); @@ -2653,7 +2653,7 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no macfont_info->cgfont = CTFontCopyGraphicsFont (macfont, NULL); val = assq_no_quit (QCdestination, AREF (entity, FONT_EXTRA_INDEX)); - if (CONSP (val) && EQ (XCDR (val), make_fixnum (1))) + if (CONSP (val) && BASE_EQ (XCDR (val), make_fixnum (1))) macfont_info->screen_font = mac_screen_font_create_with_name (font_name, size); else diff --git a/src/minibuf.c b/src/minibuf.c index 1f77a6cdc1..85d6ec4434 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -427,8 +427,8 @@ No argument or nil as argument means use the current buffer as BUFFER. */) { if (NILP (buffer)) buffer = Fcurrent_buffer (); - return EQ (buffer, (Fcar (Fnthcdr (make_fixnum (minibuf_level), - Vminibuffer_list)))) + return BASE_EQ (buffer, (Fcar (Fnthcdr (make_fixnum (minibuf_level), + Vminibuffer_list)))) ? Qt : Qnil; } @@ -1791,10 +1791,10 @@ or from one of the possible completions. */) if (bestmatchsize != SCHARS (eltstring) || bestmatchsize != matchsize || (completion_ignore_case - && !EQ (Fcompare_strings (old_bestmatch, zero, lcompare, - eltstring, zero, lcompare, - Qnil), - Qt))) + && !BASE_EQ (Fcompare_strings (old_bestmatch, zero, + lcompare, eltstring, zero, + lcompare, Qnil), + Qt))) /* Don't count the same string multiple times. */ matchcount += matchcount <= 1; bestmatchsize = matchsize; @@ -2110,10 +2110,11 @@ the values STRING, PREDICATE and `lambda'. */) if (SYMBOLP (tail)) while (1) { - if (EQ (Fcompare_strings (string, make_fixnum (0), Qnil, - Fsymbol_name (tail), - make_fixnum (0) , Qnil, Qt), - Qt)) + if (BASE_EQ (Fcompare_strings (string, make_fixnum (0), + Qnil, + Fsymbol_name (tail), + make_fixnum (0) , Qnil, Qt), + Qt)) { tem = tail; break; @@ -2144,9 +2145,9 @@ the values STRING, PREDICATE and `lambda'. */) if (BASE_EQ (tem, Qunbound)) continue; Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem); if (!STRINGP (strkey)) continue; - if (EQ (Fcompare_strings (string, Qnil, Qnil, - strkey, Qnil, Qnil, - completion_ignore_case ? Qt : Qnil), + if (BASE_EQ (Fcompare_strings (string, Qnil, Qnil, + strkey, Qnil, Qnil, + completion_ignore_case ? Qt : Qnil), Qt)) goto found_matching_key; } diff --git a/src/nsfns.m b/src/nsfns.m index 5ab2b2ee35..1617421066 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -382,7 +382,7 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side. /* See if it's changed. */ if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt)) return; } else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg)) diff --git a/src/pdumper.c b/src/pdumper.c index 50ae4f85e7..af451920eb 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -1210,8 +1210,8 @@ dump_queue_find_score_of_one_weight_queue (struct dump_queue *dump_queue, static Lisp_Object dump_queue_dequeue (struct dump_queue *dump_queue, dump_off basis) { - eassert (EQ (Fhash_table_count (dump_queue->sequence_numbers), - Fhash_table_count (dump_queue->link_weights))); + eassert (BASE_EQ (Fhash_table_count (dump_queue->sequence_numbers), + Fhash_table_count (dump_queue->link_weights))); eassert (XFIXNUM (Fhash_table_count (dump_queue->sequence_numbers)) <= (dump_tailq_length (&dump_queue->fancy_weight_objects) diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 294bdb3791..4f15ec6ff6 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -613,7 +613,7 @@ pgtk_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt)) return; } else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg)) @@ -643,7 +643,7 @@ pgtk_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt)) return; } else if (!NILP (arg) || NILP (oldval)) diff --git a/src/process.c b/src/process.c index ccfc0bdf54..0cbac172fe 100644 --- a/src/process.c +++ b/src/process.c @@ -4775,7 +4775,7 @@ corresponding connection was closed. */) /* Can't wait for a process that is dedicated to a different thread. */ - if (!NILP (proc->thread) && !EQ (proc->thread, Fcurrent_thread ())) + if (!NILP (proc->thread) && !BASE_EQ (proc->thread, Fcurrent_thread ())) { Lisp_Object proc_thread_name = XTHREAD (proc->thread)->name; diff --git a/src/textprop.c b/src/textprop.c index c11ee98f02..d69682d3ea 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -1407,8 +1407,8 @@ set_text_properties (Lisp_Object start, Lisp_Object end, Lisp_Object properties, /* If we want no properties for a whole string, get rid of its intervals. */ if (NILP (properties) && STRINGP (object) - && EQ (start, make_fixnum (0)) - && EQ (end, make_fixnum (SCHARS (object)))) + && BASE_EQ (start, make_fixnum (0)) + && BASE_EQ (end, make_fixnum (SCHARS (object)))) { if (!string_intervals (object)) return Qnil; diff --git a/src/w32fns.c b/src/w32fns.c index 8716b762eb..b093d3c32e 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -1463,7 +1463,7 @@ w32_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) return; if (STRINGP (arg) && STRINGP (oldval) - && EQ (Fstring_equal (oldval, arg), Qt)) + && BASE_EQ (Fstring_equal (oldval, arg), Qt)) return; if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval)) @@ -1486,7 +1486,7 @@ w32_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt)) return; } else if (!NILP (arg) || NILP (oldval)) diff --git a/src/w32select.c b/src/w32select.c index eae1a0bac0..3720611812 100644 --- a/src/w32select.c +++ b/src/w32select.c @@ -631,7 +631,7 @@ validate_coding_system (Lisp_Object coding_system) eol_type = Fcoding_system_eol_type (coding_system); /* Already a DOS coding system? */ - if (EQ (eol_type, make_fixnum (1))) + if (BASE_EQ (eol_type, make_fixnum (1))) return coding_system; /* Get EOL_TYPE vector of the base of CODING_SYSTEM. */ diff --git a/src/window.c b/src/window.c index ac8408a9a9..c94e7bde29 100644 --- a/src/window.c +++ b/src/window.c @@ -2786,7 +2786,7 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object ? miniwin : Qnil); else if (EQ (*all_frames, Qvisible)) ; - else if (EQ (*all_frames, make_fixnum (0))) + else if (BASE_EQ (*all_frames, make_fixnum (0))) ; else if (FRAMEP (*all_frames)) ; @@ -3083,7 +3083,7 @@ window_loop (enum window_loop type, Lisp_Object obj, bool mini, if (f) frame_arg = Qlambda; - else if (EQ (frames, make_fixnum (0))) + else if (BASE_EQ (frames, make_fixnum (0))) frame_arg = frames; else if (EQ (frames, Qvisible)) frame_arg = frames; @@ -7493,7 +7493,7 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i) hare = XCDR (hare); tortoise = XCDR (tortoise); - if (EQ (hare, tortoise)) + if (BASE_EQ (hare, tortoise)) /* Reset Vwindow_persistent_parameters to Qnil. */ { Vwindow_persistent_parameters = Qnil; diff --git a/src/xdisp.c b/src/xdisp.c index b02375ab2d..90809ac3ab 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -832,7 +832,7 @@ void wset_redisplay (struct window *w) { /* Beware: selected_window can be nil during early stages. */ - if (!EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window)) + if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window)) redisplay_other_windows (); w->redisplay = true; } diff --git a/src/xfaces.c b/src/xfaces.c index 7395ce157e..04e5439d9d 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -1584,8 +1584,9 @@ the face font sort order, see `face-font-selection-order'. */) /* If the font was specified in a way different from XLFD (e.g., on MS-Windows), we will have a number there, not 'p'. */ - || EQ (spacing, - make_fixnum (FONT_SPACING_PROPORTIONAL))) + || BASE_EQ (spacing, + make_fixnum + (FONT_SPACING_PROPORTIONAL))) ? Qnil : Qt, Ffont_xlfd_name (font, Qnil), AREF (font, FONT_REGISTRY_INDEX)); @@ -1942,7 +1943,7 @@ resolve_face_name (Lisp_Object face_name, bool signal_p) break; tortoise = Fget (tortoise, Qface_alias); - if (EQ (hare, tortoise)) + if (BASE_EQ (hare, tortoise)) { if (signal_p) circular_list (orig_face); @@ -5176,8 +5177,9 @@ gui_supports_face_attributes_p (struct frame *f, return true; s1 = SYMBOL_NAME (face->font->props[i]); s2 = SYMBOL_NAME (def_face->font->props[i]); - if (! EQ (Fcompare_strings (s1, make_fixnum (0), Qnil, - s2, make_fixnum (0), Qnil, Qt), Qt)) + if (! BASE_EQ (Fcompare_strings (s1, make_fixnum (0), Qnil, + s2, make_fixnum (0), Qnil, Qt), + Qt)) return true; } return false; diff --git a/src/xfns.c b/src/xfns.c index 05023524a7..4cd03136e6 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1584,7 +1584,7 @@ x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt)) return; } else if (!STRINGP (oldval) && NILP (oldval) == NILP (arg)) @@ -1616,7 +1616,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) if (STRINGP (arg)) { - if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt)) + if (STRINGP (oldval) && BASE_EQ (Fstring_equal (oldval, arg), Qt)) return; } else if (!NILP (arg) || NILP (oldval)) diff --git a/src/xselect.c b/src/xselect.c index fff79fb99f..dd82a906af 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -1939,9 +1939,9 @@ clean_local_selection_data (Lisp_Object obj) && INTEGERP (XCAR (obj)) && FIXNUMP (XCDR (obj))) { - if (EQ (XCAR (obj), make_fixnum (0))) + if (BASE_EQ (XCAR (obj), make_fixnum (0))) return XCDR (obj); - if (EQ (XCAR (obj), make_fixnum (-1))) + if (BASE_EQ (XCAR (obj), make_fixnum (-1))) return make_fixnum (- XFIXNUM (XCDR (obj))); } if (VECTORP (obj)) commit decb64fd835ef1740d720ff877788eb0626737b5 Author: Lars Ingebrigtsen Date: Thu Jun 16 14:25:47 2022 +0200 Make package-recompile delete all .elc files first * lisp/emacs-lisp/package.el (package-recompile): Delete all .elc files under the package directory. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index ef46bd3a27..2c43db9899 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2437,7 +2437,8 @@ object." ;; Delete the old .elc files to ensure that we don't inadvertently ;; load them (in case they contain byte code/macros that are now ;; invalid). - (dolist (elc (directory-files (package-desc-dir pkg-desc) t "\\.elc\\'")) + (dolist (elc (directory-files-recursively + (package-desc-dir pkg-desc) "\\.elc\\'")) (delete-file elc)) (package--compile pkg-desc))) commit feb654b4605cd84d1913d33a7d4c687bd4e71be7 Author: Lars Ingebrigtsen Date: Thu Jun 16 13:49:02 2022 +0200 Add new package.el commands for recompilation * doc/emacs/package.texi (Package Installation): Document them. * lisp/emacs-lisp/package.el (package-recompile): (package-recompile-all): New commands (bug#27253). diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi index eb4f5b0eda..2eb12e096a 100644 --- a/doc/emacs/package.texi +++ b/doc/emacs/package.texi @@ -483,6 +483,16 @@ The default value is just @code{'(all)}. installed will be ignored. The @samp{muse} package will be listed in the package menu with the @samp{held} status. +@findex package-recompile +@findex package-recompile-all + Emacs byte code is quite stable, but it's possible for byte code to +become outdated, or for the compiled files to rely on macros that have +changed in new versions of Emacs. You can use the @kbd{M-x +package-recompile} command to recompile a particular package, or +@kbd{M-x package-recompile-all} to rebuild all the packages. (The +latter command might take quite a while to run if you have many +installed packages.) + @node Package Files @section Package Files and Directory Layout @cindex package directory diff --git a/etc/NEWS b/etc/NEWS index 43b88e6cd4..e19b2f5eba 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -982,6 +982,11 @@ list-packages'. *** New command 'package-update-all'. This command allows updating all packages without any queries. ++++ +*** New commands 'package-recompile' and 'package-recompile-all'. +These commands can be useful if the .elc files are out of date +(invalid byte code and macros). + +++ *** New DWIM action on 'x' in "*Packages*" buffer. If no packages are marked, 'x' will install the package under point if diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 9aaeb052d0..ef46bd3a27 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2422,6 +2422,34 @@ object." 'force 'nosave) (package-install pkg 'dont-select)) +;;;###autoload +(defun package-recompile (pkg) + "Byte-compile package PKG again. +PKG should be either a symbol, the package name, or a `package-desc' +object." + (interactive (list (intern (completing-read + "Recompile package: " + (mapcar #'symbol-name + (mapcar #'car package-alist)))))) + (let ((pkg-desc (if (package-desc-p pkg) + pkg + (cadr (assq pkg package-alist))))) + ;; Delete the old .elc files to ensure that we don't inadvertently + ;; load them (in case they contain byte code/macros that are now + ;; invalid). + (dolist (elc (directory-files (package-desc-dir pkg-desc) t "\\.elc\\'")) + (delete-file elc)) + (package--compile pkg-desc))) + +;;;###autoload +(defun package-recompile-all () + "Byte-compile all installed packages. +This is meant to be used only in the case the byte-compiled files +are invalid due to changed byte-code, macros or the like." + (interactive) + (pcase-dolist (`(_ ,pkg-desc) package-alist) + (package-recompile pkg-desc))) + ;;;###autoload (defun package-autoremove () "Remove packages that are no longer needed. commit 5ddd0f1a3573ce3155b06850398dbc656539c669 Author: Michael Albinus Date: Thu Jun 16 10:45:15 2022 +0200 * lisp/net/tramp.el (tramp-methods): Fix quoting in docstring. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 3ee1169139..88715e3230 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -238,7 +238,7 @@ pair of the form (KEY VALUE). The following KEYs are defined: unchanged after expansion (i.e. no host, no user or no port were specified), that sublist is not used. For e.g. - '((\"-a\" \"-b\") (\"-l\" \"%u\")) + \\='((\"-a\" \"-b\") (\"-l\" \"%u\")) that means that (\"-l\" \"%u\") is used only if the user was specified, and it is thus effectively optional. commit 217c41c7b07b10d5a93f4cf7b6619db411603e65 Merge: b3cbcebd9a fdd4dc6bdf Author: Eli Zaretskii Date: Thu Jun 16 11:09:19 2022 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit b3cbcebd9aae16e018e167233cf0c39bfac31198 Author: Eli Zaretskii Date: Thu Jun 16 11:06:29 2022 +0300 Speed up Org to Texinfo generation * doc/misc/Makefile.in ($(1:.org=.texi)): Use a higher GC threshold, to speed up .org=.texi conversion. Patch by Ihor Radchenko . diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in index d9c5173c07..1d881a5fc7 100644 --- a/doc/misc/Makefile.in +++ b/doc/misc/Makefile.in @@ -248,6 +248,7 @@ emacs = "${EMACS}" -batch --no-site-file --no-site-lisp --eval '(setq load-prefe define org_template $(1:.org=.texi): $(1) ${top_srcdir}/lisp/org/ox-texinfo.el $${AM_V_GEN}cd "$${srcdir}" && $${emacs} -l ox-texinfo \ + --eval '(setq gc-cons-threshold 50000000)' \ -f org-texinfo-export-to-texinfo-batch $$(notdir $$<) $$(notdir $$@) endef commit fdd4dc6bdf6ba6e333f81cc19b241105adfa836b Author: Stefan Kangas Date: Thu Jun 16 09:48:18 2022 +0200 Make artist-version variable obsolete * lisp/textmodes/artist.el (artist-version): Make obsolete. This has not been updated in nearly two decades; use the Emacs version instead. (artist-submit-bug-report): Don't use above obsolete variable. diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el index 9912c0fcfc..5ba18dfed1 100644 --- a/lisp/textmodes/artist.el +++ b/lisp/textmodes/artist.el @@ -184,7 +184,6 @@ ;; Variables -(defconst artist-version "1.2.6") (defconst artist-maintainer-address "tab@lysator.liu.se, bug-gnu-emacs@gnu.org") (defvar x-pointer-crosshair) @@ -5361,7 +5360,7 @@ The event, EV, is the mouse event." (setq vars (delq x vars)))) vars) (reporter-submit-bug-report artist-maintainer-address - (concat "artist.el " artist-version) + (concat "artist.el in Emacs " emacs-version) vars nil nil (concat "Hello Tomas,\n\n" @@ -5369,6 +5368,9 @@ The event, EV, is the mouse event." (define-obsolete-function-alias 'artist-uniq #'seq-uniq "28.1") +(defconst artist-version "1.2.6") +(make-obsolete-variable 'artist-version 'emacs-version "29.1") + (provide 'artist) commit e9647059212116b46cb3e44e398d4db3805f94f7 Author: Stefan Kangas Date: Thu Jun 16 09:47:47 2022 +0200 Prefer defvar-keymap for artist-mode-map * lisp/textmodes/artist.el (artist-mode-map): Prefer defvar-keymap. diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el index ff4311c3ac..9912c0fcfc 100644 --- a/lisp/textmodes/artist.el +++ b/lisp/textmodes/artist.el @@ -475,60 +475,57 @@ This variable is initialized by the `artist-make-prev-next-op-alist' function.") (defvar artist-arrow-point-1 nil) (defvar artist-arrow-point-2 nil) -(defvar artist-mode-map - (let ((map (make-sparse-keymap))) - (setq artist-mode-map (make-sparse-keymap)) - (define-key map [down-mouse-1] 'artist-down-mouse-1) - (define-key map [S-down-mouse-1] 'artist-down-mouse-1) - (define-key map [down-mouse-2] 'artist-mouse-choose-operation) - (define-key map [S-down-mouse-2] 'artist-mouse-choose-operation) - (define-key map [down-mouse-3] 'artist-down-mouse-3) - (define-key map [S-down-mouse-3] 'artist-down-mouse-3) - (define-key map [C-mouse-4] 'artist-select-prev-op-in-list) - (define-key map [C-mouse-5] 'artist-select-next-op-in-list) - (define-key map "\r" 'artist-key-set-point) ; return - (define-key map [up] 'artist-previous-line) - (define-key map "\C-p" 'artist-previous-line) - (define-key map [down] 'artist-next-line) - (define-key map "\C-n" 'artist-next-line) - (define-key map [left] 'artist-backward-char) - (define-key map "\C-b" 'artist-backward-char) - (define-key map [right] 'artist-forward-char) - (define-key map "\C-f" 'artist-forward-char) - (define-key map "<" 'artist-toggle-first-arrow) - (define-key map ">" 'artist-toggle-second-arrow) - (define-key map "\C-c\C-a\C-e" 'artist-select-erase-char) - (define-key map "\C-c\C-a\C-f" 'artist-select-fill-char) - (define-key map "\C-c\C-a\C-l" 'artist-select-line-char) - (define-key map "\C-c\C-a\C-o" 'artist-select-operation) - (define-key map "\C-c\C-a\C-r" 'artist-toggle-rubber-banding) - (define-key map "\C-c\C-a\C-t" 'artist-toggle-trim-line-endings) - (define-key map "\C-c\C-a\C-s" 'artist-toggle-borderless-shapes) - (define-key map "\C-c\C-c" 'artist-mode-off) - (define-key map "\C-c\C-al" 'artist-select-op-line) - (define-key map "\C-c\C-aL" 'artist-select-op-straight-line) - (define-key map "\C-c\C-ar" 'artist-select-op-rectangle) - (define-key map "\C-c\C-aR" 'artist-select-op-square) - (define-key map "\C-c\C-as" 'artist-select-op-square) - (define-key map "\C-c\C-ap" 'artist-select-op-poly-line) - (define-key map "\C-c\C-aP" 'artist-select-op-straight-poly-line) - (define-key map "\C-c\C-ae" 'artist-select-op-ellipse) - (define-key map "\C-c\C-ac" 'artist-select-op-circle) - (define-key map "\C-c\C-at" 'artist-select-op-text-see-thru) - (define-key map "\C-c\C-aT" 'artist-select-op-text-overwrite) - (define-key map "\C-c\C-aS" 'artist-select-op-spray-can) - (define-key map "\C-c\C-az" 'artist-select-op-spray-set-size) - (define-key map "\C-c\C-a\C-d" 'artist-select-op-erase-char) - (define-key map "\C-c\C-aE" 'artist-select-op-erase-rectangle) - (define-key map "\C-c\C-av" 'artist-select-op-vaporize-line) - (define-key map "\C-c\C-aV" 'artist-select-op-vaporize-lines) - (define-key map "\C-c\C-a\C-k" 'artist-select-op-cut-rectangle) - (define-key map "\C-c\C-a\M-w" 'artist-select-op-copy-rectangle) - (define-key map "\C-c\C-a\C-y" 'artist-select-op-paste) - (define-key map "\C-c\C-af" 'artist-select-op-flood-fill) - (define-key map "\C-c\C-a\C-b" 'artist-submit-bug-report) - map) - "Keymap for `artist-mode'.") +(defvar-keymap artist-mode-map + :doc "Keymap for `artist-mode'." + "" #'artist-down-mouse-1 + "S-" #'artist-down-mouse-1 + "" #'artist-mouse-choose-operation + "S-" #'artist-mouse-choose-operation + "" #'artist-down-mouse-3 + "S-" #'artist-down-mouse-3 + "C-" #'artist-select-prev-op-in-list + "C-" #'artist-select-next-op-in-list + "RET" #'artist-key-set-point ; return + "" #'artist-previous-line + "C-p" #'artist-previous-line + "" #'artist-next-line + "C-n" #'artist-next-line + "" #'artist-backward-char + "C-b" #'artist-backward-char + "" #'artist-forward-char + "C-f" #'artist-forward-char + "<" #'artist-toggle-first-arrow + ">" #'artist-toggle-second-arrow + "C-c C-a C-e" #'artist-select-erase-char + "C-c C-a C-f" #'artist-select-fill-char + "C-c C-a C-l" #'artist-select-line-char + "C-c C-a C-o" #'artist-select-operation + "C-c C-a C-r" #'artist-toggle-rubber-banding + "C-c C-a C-t" #'artist-toggle-trim-line-endings + "C-c C-a C-s" #'artist-toggle-borderless-shapes + "C-c C-c" #'artist-mode-off + "C-c C-a l" #'artist-select-op-line + "C-c C-a L" #'artist-select-op-straight-line + "C-c C-a r" #'artist-select-op-rectangle + "C-c C-a R" #'artist-select-op-square + "C-c C-a s" #'artist-select-op-square + "C-c C-a p" #'artist-select-op-poly-line + "C-c C-a P" #'artist-select-op-straight-poly-line + "C-c C-a e" #'artist-select-op-ellipse + "C-c C-a c" #'artist-select-op-circle + "C-c C-a t" #'artist-select-op-text-see-thru + "C-c C-a T" #'artist-select-op-text-overwrite + "C-c C-a S" #'artist-select-op-spray-can + "C-c C-a z" #'artist-select-op-spray-set-size + "C-c C-a C-d" #'artist-select-op-erase-char + "C-c C-a E" #'artist-select-op-erase-rectangle + "C-c C-a v" #'artist-select-op-vaporize-line + "C-c C-a V" #'artist-select-op-vaporize-lines + "C-c C-a C-k" #'artist-select-op-cut-rectangle + "C-c C-a M-w" #'artist-select-op-copy-rectangle + "C-c C-a C-y" #'artist-select-op-paste + "C-c C-a f" #'artist-select-op-flood-fill + "C-c C-a C-b" #'artist-submit-bug-report) (easy-menu-define artist-menu-map artist-mode-map "Menu for `artist-mode'." commit f94e93a6eec92d834a6b545d8d4b68280b0993b0 Author: Ihor Radchenko Date: Thu Jun 16 10:43:29 2022 +0800 org-cite-list-citations: Cache footnote-definition searches * lisp/org/oc.el (org-cite-list-citations): Avoid quadratic complexity. Pre-calculate list of all footnote definitions and cache the footnote label search hits. Do not make `org-element-map' accumulate unused result. diff --git a/lisp/org/oc.el b/lisp/org/oc.el index eb5f519cb6..c4cd0268c7 100644 --- a/lisp/org/oc.el +++ b/lisp/org/oc.el @@ -808,6 +808,8 @@ INFO is the export communication channel, as a property list." (or (plist-get info :citations) (letrec ((cites nil) (tree (plist-get info :parse-tree)) + (definition-cache (make-hash-table :test #'equal)) + (definition-list nil) (find-definition ;; Find definition for standard reference LABEL. At ;; this point, it is impossible to rely on @@ -816,11 +818,21 @@ INFO is the export communication channel, as a property list." ;; un-processed citation objects. So we use ;; a simplified version of the function above. (lambda (label) - (org-element-map tree 'footnote-definition - (lambda (d) - (and (equal label (org-element-property :label d)) - (or (org-element-contents d) ""))) - info t))) + (or (gethash label definition-cache) + (org-element-map + (or definition-list + (setq definition-list + (org-element-map + tree + 'footnote-definition + #'identity info))) + 'footnote-definition + (lambda (d) + (and (equal label (org-element-property :label d)) + (puthash label + (or (org-element-contents d) "") + definition-cache))) + info t)))) (search-cites (lambda (data) (org-element-map data '(citation footnote-reference) @@ -834,7 +846,8 @@ INFO is the export communication channel, as a property list." (_ (let ((label (org-element-property :label datum))) (funcall search-cites - (funcall find-definition label)))))) + (funcall find-definition label))))) + nil) info nil 'footnote-definition t)))) (funcall search-cites tree) (let ((result (nreverse cites))) commit 4f37a3b299bcec71a0e9bdd84b7b226494006fe4 Author: Ihor Radchenko Date: Thu Jun 16 09:28:27 2022 +0800 org-element-map: Avoid repetitive `plist-get' call * lisp/org/org-element.el (org-element-map): Do not call `(plist-get info :ignore-list)' on every iteration. diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el index 9db1406b3f..20b5b03039 100644 --- a/lisp/org/org-element.el +++ b/lisp/org/org-element.el @@ -4391,6 +4391,7 @@ looking into captions: ;; every element it encounters. (and (not (eq category 'elements)) (setq category 'elements)))))))) + (--ignore-list (plist-get info :ignore-list)) --acc) (letrec ((--walk-tree (lambda (--data) @@ -4400,7 +4401,7 @@ looking into captions: (cond ((not --data)) ;; Ignored element in an export context. - ((and info (memq --data (plist-get info :ignore-list)))) + ((and info (memq --data --ignore-list))) ;; List of elements or objects. ((not --type) (mapc --walk-tree --data)) ;; Unconditionally enter parse trees. commit 979308b4cad2b573606ed71a1689a47a9e7a9e98 Author: Ihor Radchenko Date: Thu Jun 16 01:01:53 2022 +0800 org-export-data: Concatenate strings in temporary buffer for performance * lisp/org/ox.el (org-export-data): Use temporary buffer to collect export data instead of `mapconcat'. Using buffer puts less load on garbage collector. diff --git a/lisp/org/ox.el b/lisp/org/ox.el index a4512270c9..ae7e41e576 100644 --- a/lisp/org/ox.el +++ b/lisp/org/ox.el @@ -1923,28 +1923,34 @@ Return a string." (and (not greaterp) (memq type org-element-recursive-objects))) (contents - (mapconcat - (lambda (element) (org-export-data element info)) - (org-element-contents - (if (or greaterp objectp) data - ;; Elements directly containing - ;; objects must have their indentation - ;; normalized first. - (org-element-normalize-contents - data - ;; When normalizing first paragraph - ;; of an item or - ;; a footnote-definition, ignore - ;; first line's indentation. - (and - (eq type 'paragraph) - (memq (org-element-type parent) - '(footnote-definition item)) - (eq (car (org-element-contents parent)) - data) - (eq (org-element-property :pre-blank parent) - 0))))) - ""))) + (let ((export-buffer (current-buffer))) + (with-temp-buffer + (dolist (element (org-element-contents + (if (or greaterp objectp) data + ;; Elements directly containing + ;; objects must have their indentation + ;; normalized first. + (org-element-normalize-contents + data + ;; When normalizing first paragraph + ;; of an item or + ;; a footnote-definition, ignore + ;; first line's indentation. + (and + (eq type 'paragraph) + (memq (org-element-type parent) + '(footnote-definition item)) + (eq (car (org-element-contents parent)) + data) + (eq (org-element-property :pre-blank parent) + 0)))))) + (insert + ;; Use right local variable + ;; environment if there are, for + ;; example, #+BIND variables. + (with-current-buffer export-buffer + (org-export-data element info)))) + (buffer-string))))) (broken-link-handler (funcall transcoder data (if (not greaterp) contents commit 0f7ceb4803cabcb3c406fa7c27ccb7625096058e Author: Ihor Radchenko Date: Thu Jun 16 01:03:18 2022 +0800 org-export-as: Do not update buffer settings when not modified * lisp/org/ox.el (org-export-as): Use `buffer-chars-modified-tick' and avoid extra invocations of `org-set-regexps-and-options' and `org-update-radio-target-regexp' when the buffer is not changed. Also, disable folding checks. Folding is irrelevant inside export buffer. diff --git a/lisp/org/ox.el b/lisp/org/ox.el index b431d71193..a4512270c9 100644 --- a/lisp/org/ox.el +++ b/lisp/org/ox.el @@ -2956,11 +2956,12 @@ Return code as a string." (mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o))) (append (org-export-get-all-options backend) org-export-options-alist)))) - tree) + tree modified-tick) ;; Update communication channel and get parse tree. Buffer ;; isn't parsed directly. Instead, all buffer modifications ;; and consequent parsing are undertaken in a temporary copy. (org-export-with-buffer-copy + (font-lock-mode -1) ;; Run first hook with current back-end's name as argument. (run-hook-with-args 'org-export-before-processing-hook (org-export-backend-name backend)) @@ -2972,6 +2973,7 @@ Return code as a string." ;; potentially invasive changes. (org-set-regexps-and-options) (org-update-radio-target-regexp) + (setq modified-tick (buffer-chars-modified-tick)) ;; Possibly execute Babel code. Re-run a macro expansion ;; specifically for {{{results}}} since inline source blocks ;; may have generated some more. Refresh buffer properties @@ -2979,8 +2981,10 @@ Return code as a string." (when org-export-use-babel (org-babel-exp-process-buffer) (org-macro-replace-all '(("results" . "$1")) parsed-keywords) - (org-set-regexps-and-options) - (org-update-radio-target-regexp)) + (unless (eq modified-tick (buffer-chars-modified-tick)) + (org-set-regexps-and-options) + (org-update-radio-target-regexp)) + (setq modified-tick (buffer-chars-modified-tick))) ;; Run last hook with current back-end's name as argument. ;; Update buffer properties and radio targets one last time ;; before parsing. @@ -2988,8 +2992,10 @@ Return code as a string." (save-excursion (run-hook-with-args 'org-export-before-parsing-hook (org-export-backend-name backend))) - (org-set-regexps-and-options) - (org-update-radio-target-regexp) + (unless (eq modified-tick (buffer-chars-modified-tick)) + (org-set-regexps-and-options) + (org-update-radio-target-regexp)) + (setq modified-tick (buffer-chars-modified-tick)) ;; Update communication channel with environment. (setq info (org-combine-plists commit d21412df06b99b551e67d39c097d95e8a284de73 Author: Ihor Radchenko Date: Sun Jun 12 13:32:35 2022 +0800 org-export-resolve-id-link: Pre-cache all the ids in the parse tree * lisp/org/ox.el (org-export-resolve-id-link): Pre-cache all the ids in the parse tree for faster lookup. diff --git a/lisp/org/ox.el b/lisp/org/ox.el index 4a9387519f..b431d71193 100644 --- a/lisp/org/ox.el +++ b/lisp/org/ox.el @@ -4393,15 +4393,27 @@ tree or a file name. Assume LINK type is either \"id\" or \"custom-id\". Throw an error if no match is found." (let ((id (org-element-property :path link))) ;; First check if id is within the current parse tree. - (or (org-element-map (plist-get info :parse-tree) 'headline - (lambda (headline) - (when (or (equal (org-element-property :ID headline) id) - (equal (org-element-property :CUSTOM_ID headline) id)) - headline)) - info 'first-match) - ;; Otherwise, look for external files. - (cdr (assoc id (plist-get info :id-alist))) - (signal 'org-link-broken (list id))))) + (or (let ((local-ids (or (plist-get info :id-local-cache) + (let ((table (make-hash-table :test #'equal))) + (org-element-map + (plist-get info :parse-tree) + 'headline + (lambda (headline) + (let ((id (org-element-property :ID headline)) + (custom-id (org-element-property :CUSTOM_ID headline))) + (when id + (unless (gethash id table) + (puthash id headline table))) + (when custom-id + (unless (gethash custom-id table) + (puthash custom-id headline table))))) + info) + (plist-put info :id-local-cache table) + table)))) + (gethash id local-ids)) + ;; Otherwise, look for external files. + (cdr (assoc id (plist-get info :id-alist))) + (signal 'org-link-broken (list id))))) (defun org-export-resolve-radio-link (link info) "Return radio-target object referenced as LINK destination. commit c782d6de796c361f982b52dabb14c5ed1d28827a Author: Po Lu Date: Thu Jun 16 15:51:56 2022 +0800 Fix Motif drag-and-drop timestamps * lisp/x-dnd.el (x-dnd-handle-motif): Pass timestamp when retrieving DND selection value. Bug found on Solaris 2.6. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 52f7340657..531a58f71f 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -967,7 +967,8 @@ Return a vector of atoms containing the selection targets." (when (and reply-action atom-name) (let* ((value (x-get-selection-internal (intern atom-name) - (intern (x-dnd-current-type window))))) + (intern (x-dnd-current-type window)) + timestamp))) (when value (condition-case info (x-dnd-drop-data event frame window value commit 3236dedc2de5975afde877f7460bd012da89a98d Author: Ihor Radchenko Date: Sun Jun 12 13:06:47 2022 +0800 org-export-resolve-fuzyy-link: Pre-cache all possible search cells * lisp/org/ox.el (org-export-resolve-fuzzy-link): Before matching LINK, pre-process and cache all the non-nil search cells in the parse tree. When matching, use the pre-processed info. Fix the :test function for the cache hash table. diff --git a/lisp/org/ox.el b/lisp/org/ox.el index 7f90dc36f7..4a9387519f 100644 --- a/lisp/org/ox.el +++ b/lisp/org/ox.el @@ -4346,17 +4346,27 @@ significant." (let* ((search-cells (org-export-string-to-search-cell (org-element-property :path link))) (link-cache (or (plist-get info :resolve-fuzzy-link-cache) - (let ((table (make-hash-table :test #'eq))) + (let ((table (make-hash-table :test #'equal))) + ;; Cache all the element search cells. + (org-element-map (plist-get info :parse-tree) + (append pseudo-types '(target) org-element-all-elements) + (lambda (datum) + (dolist (cell (org-export-search-cells datum)) + (if (gethash cell table) + (push datum (gethash cell table)) + (puthash cell (list datum) table))))) (plist-put info :resolve-fuzzy-link-cache table) table))) (cached (gethash search-cells link-cache 'not-found))) (if (not (eq cached 'not-found)) cached (let ((matches - (org-element-map (plist-get info :parse-tree) - (append pseudo-types '(target) org-element-all-elements) - (lambda (datum) - (and (org-export-match-search-cell-p datum search-cells) - datum))))) + (let (result) + (dolist (search-cell search-cells) + (setq result + (nconc + result + (gethash search-cell link-cache)))) + (delq nil result)))) (unless matches (signal 'org-link-broken (list (org-element-property :path link)))) (puthash commit 5b3d4e7bf0b6a1eb576e1c6e6592028e3589f792 Author: Ihor Radchenko Date: Sun Jun 12 13:05:16 2022 +0800 org-export-get-footnote-definition: Pre-cache references in parse tree * lisp/org/ox.el (org-export-get-footnote-definition): Pre-process parse tree once to filter out all non-footnote elements. This speeds up subsequent footnote definition searches. diff --git a/lisp/org/ox.el b/lisp/org/ox.el index 2a3edaa500..7f90dc36f7 100644 --- a/lisp/org/ox.el +++ b/lisp/org/ox.el @@ -3748,28 +3748,33 @@ definition can be found, raise an error." (if (not label) (org-element-contents footnote-reference) (let ((cache (or (plist-get info :footnote-definition-cache) (let ((hash (make-hash-table :test #'equal))) + ;; Cache all the footnotes in document for + ;; later search. + (org-element-map (plist-get info :parse-tree) + '(footnote-definition footnote-reference) + (lambda (f) + ;; Skip any standard footnote reference + ;; since those cannot contain a + ;; definition. + (unless (eq (org-element-property :type f) 'standard) + (puthash + (cons :element (org-element-property :label f)) + f + hash))) + info) (plist-put info :footnote-definition-cache hash) hash)))) (or (gethash label cache) (puthash label - (org-element-map (plist-get info :parse-tree) - '(footnote-definition footnote-reference) - (lambda (f) - (cond - ;; Skip any footnote with a different label. - ;; Also skip any standard footnote reference - ;; with the same label since those cannot - ;; contain a definition. - ((not (equal (org-element-property :label f) label)) nil) - ((eq (org-element-property :type f) 'standard) nil) - ((org-element-contents f)) - ;; Even if the contents are empty, we can not - ;; return nil since that would eventually raise - ;; the error. Instead, return the equivalent - ;; empty string. - (t ""))) - info t) + (let ((hashed (gethash (cons :element label) cache))) + (when hashed + (or (org-element-contents hashed) + ;; Even if the contents are empty, we can not + ;; return nil since that would eventually raise + ;; the error. Instead, return the equivalent + ;; empty string. + ""))) cache) (error "Definition not found for footnote %s" label)))))) commit 1054d38bc7a0280dd0910aff4db0a781512fe85e Author: Robert Pluim Date: Thu Jun 16 09:34:28 2022 +0200 Fix check for window system with toolkit scrollbars * configure.ac (USE_TOOLKIT_SCROLL_BARS): Add missing 'test' to condition. (Bug#55970) diff --git a/configure.ac b/configure.ac index 5b86e90925..c91b7de322 100644 --- a/configure.ac +++ b/configure.ac @@ -3436,7 +3436,7 @@ if test "${with_toolkit_scroll_bars}" != "no"; then AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) USE_TOOLKIT_SCROLL_BARS=yes fi -elif test "${window_system}" != "x11" && "${window_system}" != "none"; then +elif test "${window_system}" != "x11" && test "${window_system}" != "none"; then AC_MSG_ERROR(Non-toolkit scroll bars are not implemented for your system) fi commit b2b939e5a10aa9b61ac1f73e297fb94f50b86f5b Author: Po Lu Date: Thu Jun 16 15:26:55 2022 +0800 Fix byte-swapping of Motif DND tables * src/xterm.c (xm_read_targets_table_rec): Swap nitems first before checking the length. diff --git a/src/xterm.c b/src/xterm.c index 04e3223478..45c96c5106 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1663,12 +1663,12 @@ xm_read_targets_table_rec (uint8_t *bytes, ptrdiff_t length, nitems = *(uint16_t *) bytes; - if (length < 2 + nitems * 4) - return NULL; - if (byteorder != XM_BYTE_ORDER_CUR_FIRST) SWAPCARD16 (nitems); + if (length < 2 + nitems * 4) + return NULL; + rec = xmalloc (FLEXSIZEOF (struct xm_targets_table_rec, targets, nitems * 4)); rec->n_targets = nitems; commit b0c5accb996ce8ed4c3a6ca8a7acc555a7397f76 Author: Arash Esbati Date: Wed Jun 15 21:35:47 2022 +0200 Update MS Windows FAQ for MinGW64-w64/MSYS2 * doc/misc/efaq-w32.texi (Compiling, Debugging): Mention MinGW64-w64/MSYS2 as the preferred way for building Emacs on capable systems. (Attachments with Gnus): Catch up with emacs-mime.texi in the example given. (Spell check): Add the availability of GNU Aspell and Hunspell in MSYS2 distribution. (Other useful ports): Add an entry for MinGW64-w64/MSYS2. Fix link for MinGW homepage. Remove entry for defunct UWIN project. (Bug#55930) diff --git a/doc/misc/efaq-w32.texi b/doc/misc/efaq-w32.texi index 3a49f0a5da..d18a045b33 100644 --- a/doc/misc/efaq-w32.texi +++ b/doc/misc/efaq-w32.texi @@ -130,10 +130,8 @@ from Windows 98 onward, and all versions of the NT family starting from NT 4.0; this includes all the modern versions from Windows XP and on. The Windows port is built using the Win32 API and supports most features of the X version, including variable width fonts, images and -tooltips. - -Emacs on Windows can be compiled as either a 32-bit or a 64-bit -executable, using the MinGW GCC compiler and development tools. +tooltips. Emacs on Windows can be compiled as either a 64-bit or a +32-bit executable. @node Other versions of Emacs @section What other versions of Emacs run on Windows? @@ -177,8 +175,8 @@ best-effort basis in the @file{windows} subdirectory of the above ftp site (as zip files digitally signed by the person who built them). See the @file{README} file in that directory for more information. Building Emacs from source yourself should be straightforward, -following the instructions in @file{nt/INSTALL}, so we encourage you -to give it a try. @xref{Compiling}. +following the instructions in the @file{nt} directory, so we +encourage you to give it a try. @xref{Compiling}. @cindex latest development version of Emacs @cindex Emacs Development @@ -190,21 +188,27 @@ development site. @section How can I compile Emacs myself? @cindex compiling Emacs -To compile Emacs on Windows, you will need the MinGW port of GCC and -Binutils, the MinGW runtime and development environment, and the MSYS -suite of tools. For the details, see the file @file{nt/INSTALL} in -the Emacs source distribution. +To compile Emacs on a 64-bit version of Windows 7 or newer, we +recommend to use the MinGW-w64 port of GCC and Binutils with the MSYS2 +suite of tools. For the details, see the file @file{nt/INSTALL.W64} +in the Emacs source distribution. + +If you need to build or run Emacs on MS Windows before Windows 7, you +have to use the MinGW port of GCC and the MSYS suite of tools. The +file @file{nt/INSTALL} in Emacs source distribution contains the +details. Support for displaying images, as well as XML/HTML rendering and TLS networking requires external libraries, the headers and import libraries for which will need to be installed where your compiler can find them. Again, the details, including URLs of sites where you can -download these libraries are in @file{nt/INSTALL}. @xref{Other useful -ports}, for auxiliary tools you may wish to install and use in -conjunction with Emacs. +download these libraries are in @file{nt/INSTALL.W64} or +@file{nt/INSTALL}. @xref{Other useful ports}, for auxiliary tools you +may wish to install and use in conjunction with Emacs. After unpacking the source, or checking out of the repository, be sure -to read the instructions in @file{nt/README} and @file{nt/INSTALL}. +to read the instructions in @file{nt/README} and the respective +install file. @node Debugging @section How do I use a debugger on Emacs? @@ -222,18 +226,18 @@ specific notes about debugging Emacs. @cindex debugging Emacs with GDB GDB is the GNU debugger, which can be used to debug Emacs when it has -been compiled with MinGW GCC@. The best results will be obtained if -you start gdb from the @file{src} directory as @kbd{gdb ./emacs.exe}. +been compiled with GCC@. The best results will be obtained if you +start gdb from the @file{src} directory as @kbd{gdb ./emacs.exe}. This will load the init file @file{.gdbinit}@footnote{ Latest versions of GDB might refuse to load the init file for security reasons, unless you customize GDB; alternatively, use an explicit @kbd{source ./gdbinit} command after entering GDB. } in that directory, to define some extra commands for working with -lisp while debugging, and set up breakpoints to catch abnormal -aborts. +lisp while debugging, and set up breakpoints to catch abnormal aborts. -A Windows port of GDB can be found on MinGW download sites and on some -others. +A Windows port of GDB is installed with MinGW64-w64 and MSYS2 +(@samp{mingw-w64--toolchain} group) or can be found on MinGW +download sites and on some others. @c ------------------------------------------------------------ @node Installing Emacs @@ -307,8 +311,8 @@ bsdtar -xf emacs-@value{EMACSVER}.tar.xz Expect @command{bsdtar} to unpack the whole distribution without any complaints. -Once you unpack the source distribution, look in @file{nt/INSTALL} -file for build instructions. +Once you unpack the source distribution, look in the @file{nt} +directory for build instructions. @node Installing binaries @section How do I install Emacs after unpacking the binary zip? @@ -1645,8 +1649,8 @@ obtained the packages from if you want to use them. In your @env{HOME} directory create a file called @file{.mailcap}, with contents like the following: @example -application/zip "C:/Program Files/7-Zip/7zFM.exe" -video/* "C:/Program Files/VideoLAN/VLC/vlc.exe" +application/zip; "C:/Program Files/7-Zip/7zFM.exe" +video/*; "C:/Program Files/VideoLAN/VLC/vlc.exe" @end example @strong{Warning:} Associating MIME types with @command{start} or other @@ -1754,11 +1758,13 @@ A number of implementations are listed on the Emacs has support for spell checking on demand (@code{ispell}) and as your type (@code{flyspell}). Both packages depend on a copy of @command{ispell} 3.2 or a compatible spell-checking program. -GNU Aspell is a popular choice these days, Windows installers are -available from the @uref{http://aspell.net/win32/, official site}. +GNU Aspell is a popular choice these days, outdated Windows installers +are available from the @uref{http://aspell.net/win32/, official site}. Another possibility is Hunspell, which is available from @uref{https://sourceforge.net/projects/ezwinports/files/?source=navbar, -the ezwinports site}. +the ezwinports site}. If you're using the MSYS2 distribution, you can +install a recent version of either GNU Aspell or Hunspell through the +package manager Pacman. @xref{Other useful ports}. Once installed, you will need to configure @code{ispell-program-name} to tell ispell and flyspell to use @command{aspell} or @@ -2098,7 +2104,7 @@ suggestions} for improving the interaction of perldb and Emacs. * Cygwin:: * MinGW:: * EZWinPorts:: -* UWIN:: +* MinGW-w64:: * GnuWin32:: * GTK:: * Read man pages:: @@ -2133,22 +2139,25 @@ Cygwin on your system @env{PATH} for this reason. Instead you can make the Cygwin tools available within Emacs by setting @code{exec-path} in your init file. -@node MinGW -@section MinGW and MSYS -@cindex mingw tools -@cindex msys environment -@cindex subprocesses, mingw and msys +@node MinGW-w64 +@section MinGW-w64 and MSYS2 +@cindex mingw-w64 tools +@cindex msys2 environment +@cindex subprocesses, mingw-w64 and msys2 -@uref{http://www.mingw.org/} +@uref{https://www.msys2.org/} -MinGW is a set of development tools that produce native Windows +MinGW-w64 is a set of development tools that produce native Windows executables, not dependent on Cygwin's POSIX emulation DLLs. +MinGW-w64 has forked the original MinGW in 2007 in order to provide +support for 64 bits and new APIs. -MSYS is a POSIX shell and minimal set of tools that are commonly used in -configure scripts. Like Cygwin, this environment uses a non-native -filesystem mapping to appear more POSIX like to the scripts that it -runs. This is intended to complement the MinGW tools to make it easier -to port software to Windows. +MSYS2 is software distribution and a building platform for Windows. +MSYS2 is an independent rewrite of MSYS, based on modern Cygwin and +MinGW-w64 with the aim of better interoperability with native Windows +software. It plays the same role MSYS does in MinGW. Being a +distribution, MSYS2 provides tools to build software as well as more +than 2.600 precompiled packages ready for use. @node EZWinPorts @section EZWinPorts @@ -2161,16 +2170,22 @@ software. This includes all the optional libraries used by Emacs @command{man} command, Grep, xz, bzip2, bsdtar, ID Utils, Findutils, Hunspell, Gawk, GNU Make, Groff, GDB. -@node UWIN -@section UWIN -@cindex uwin environment -@cindex subprocesses, uwin +@node MinGW +@section MinGW and MSYS +@cindex mingw tools +@cindex msys environment +@cindex subprocesses, mingw and msys + +@uref{https://osdn.net/projects/mingw/} -@uref{http://www.research.att.com/sw/tools/uwin/} +MinGW is another set of development tools that produce native Windows +executables, not dependent on Cygwin's POSIX emulation DLLs. -UWIN is another POSIX emulation environment, like Cygwin and MSYS, -that provides a large number of ported tools. The shell used by UWIN -is @command{ksh}, the Korn shell. +MSYS is a POSIX shell and minimal set of tools that are commonly used in +configure scripts. Like Cygwin, this environment uses a non-native +filesystem mapping to appear more POSIX like to the scripts that it +runs. This is intended to complement the MinGW tools to make it easier +to port software to Windows. @node GnuWin32 @section GnuWin32 commit 61bdad468511c982714800556e3e01e2b41946f8 Author: Eli Zaretskii Date: Thu Jun 16 10:08:10 2022 +0300 ; Fix last change in documentation of 'strz' bindat type * doc/lispref/processes.texi (Bindat Types): Fix wording and clarify the description of 'strz'. (Bug#55952) diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 179980c0ed..b9200aedde 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3493,21 +3493,26 @@ any null bytes in the packed input string will appear in the unpacked output. @item strz &optional @var{len} -If @var{len} is not provided: Variable-length null-terminated unibyte -string (@pxref{Text Representations}). When packing, the entire input -string is copied to the packed output followed by a null (zero) byte. -The length of the packed output is the length of the input string plus -one (for the null terminator). The input string must not contain any -null bytes. If the input string is multibyte with only ASCII and +If @var{len} is not provided, this is a variable-length +null-terminated unibyte string (@pxref{Text Representations}). When +packing into @code{strz}, the entire input string is copied to the +packed output followed by a null (zero) byte. (If pre-allocated +string is provided for packing into @code{strz}, that pre-allocated +string should have enough space for the additional null byte appended +to the output string contents, @pxref{Bindat Functions}). The length +of the packed output is the length of the input string plus one (for +the null terminator). The input string must not contain any null +bytes. If the input string is multibyte with only ASCII and @code{eight-bit} characters, it is converted to unibyte before it is -packed; other multibyte strings signal an error. When unpacking, the -resulting string contains all bytes up to (but excluding) the null -byte. - -If @var{len} is provided: @code{strz} behaves the same as @code{str} -with one difference: When unpacking, the first null byte encountered -in the packed string and all subsequent bytes are excluded from the -unpacked result. +packed; other multibyte strings signal an error. When unpacking a +@code{strz}, the resulting output string will contain all bytes up to +(but excluding) the null byte that terminated the input string. + +If @var{len} is provided, @code{strz} behaves the same as @code{str}, +but with one difference: when unpacking, the first null byte +encountered in the packed string is interpreted as the terminating +byte, and it and all subsequent bytes are excluded from the result of +the unpacking. @quotation Caution The packed output will not be null-terminated unless one of the commit 6c3b6149d9e7c882729634dc5a7e647daeecfdf3 Author: Richard Hansen Date: Thu Jun 9 20:41:50 2022 -0400 bindat (strz): Write null terminator after variable length string * lisp/emacs-lisp/bindat.el (bindat--pack-strz): Explicitly write a null byte after packing a variable-length string to ensure proper termination when packing to a pre-allocated string. * doc/lispref/processes.texi (Bindat Types): Update documentation. * test/lisp/emacs-lisp/bindat-tests.el (bindat-test--str-strz-prealloc): Update tests. diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 8c8f8fd6b2..179980c0ed 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3495,24 +3495,15 @@ output. @item strz &optional @var{len} If @var{len} is not provided: Variable-length null-terminated unibyte string (@pxref{Text Representations}). When packing, the entire input -string is copied to the packed output. The following byte will be -null (zero) unless a pre-allocated string was provided to -@code{bindat-pack}, in which case that byte is left unmodified. The -length of the packed output is the length of the input string plus one -(for the null terminator). The input string must not contain any null -bytes. If the input string is multibyte with only ASCII and +string is copied to the packed output followed by a null (zero) byte. +The length of the packed output is the length of the input string plus +one (for the null terminator). The input string must not contain any +null bytes. If the input string is multibyte with only ASCII and @code{eight-bit} characters, it is converted to unibyte before it is packed; other multibyte strings signal an error. When unpacking, the resulting string contains all bytes up to (but excluding) the null byte. -@quotation Caution -If a pre-allocated string is provided to @code{bindat-pack}, the -packed output will not be properly null-terminated unless the -pre-allocated string already has a null byte at the appropriate -location. -@end quotation - If @var{len} is provided: @code{strz} behaves the same as @code{str} with one difference: When unpacking, the first null byte encountered in the packed string and all subsequent bytes are excluded from the diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 9ba89a5e3f..46e2a4901c 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -450,6 +450,9 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." ;; need to scan the input string looking for a null byte. (error "Null byte encountered in input strz string")) (aset bindat-raw (+ bindat-idx i) (aref v i))) + ;; Explicitly write a null terminator in case the user provided a + ;; pre-allocated string to bindat-pack that wasn't zeroed first. + (aset bindat-raw (+ bindat-idx len) 0) (setq bindat-idx (+ bindat-idx len 1)))) (defun bindat--pack-bits (len v) diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el index 7d1233ded7..cc223ad14e 100644 --- a/test/lisp/emacs-lisp/bindat-tests.el +++ b/test/lisp/emacs-lisp/bindat-tests.el @@ -182,8 +182,8 @@ ((((x strz 2)) ((x . "a"))) . "ax") ((((x strz 2)) ((x . "ab"))) . "ab") ((((x strz 2)) ((x . "abc"))) . "ab") - ((,(bindat-type strz) "") . "xx") - ((,(bindat-type strz) "a") . "ax"))) + ((,(bindat-type strz) "") . "\0x") + ((,(bindat-type strz) "a") . "a\0"))) (let ((prealloc (make-string 2 ?x))) (apply #'bindat-pack (append (car tc) (list prealloc))) (should (equal prealloc (cdr tc)))))) commit dcee64d4bf2751a6b67716e2e43267d9e73640cd Author: Po Lu Date: Thu Jun 16 14:41:21 2022 +0800 Fix defcustom in last change * lisp/x-dnd.el (x-dnd-use-offix-drop): Fix defcustom. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 3b15eb432e..52f7340657 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -115,9 +115,9 @@ If the symbol `files', use the OffiX protocol when dropping files, and the fallback drop method (which is used with programs like xterm) for text." :version "29.1" - :type '(choice (const "Don't use the OffiX protocol for drag-and-drop") - (const "Only use the OffiX protocol to drop files") - (const "Use the OffiX protocol for both files and text")) + :type '(choice (const :tag "Don't use the OffiX protocol for drag-and-drop" nil) + (const :tag "Only use the OffiX protocol to drop files" files) + (const :tag "Use the OffiX protocol for both files and text" t)) :group 'x) ;; Internal variables commit e5dbe60e3cfbdfd3a3e1a045e8557a92cb146af0 Author: Po Lu Date: Thu Jun 16 14:33:30 2022 +0800 Improve handling of fallback drop protocols * lisp/x-dnd.el (x-dnd-use-offix-drop): New value `files', which means to only drop files using the OffiX protocol. Make it the default. (x-dnd-handle-old-kde): Handle other data types correctly. (x-dnd-offix-old-kde-to-name): New variable. (x-dnd-offix-id-to-name): Fix typo in doc string. (x-dnd-handle-unsupported-drop): Implement new value. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index aa4eb8849f..3b15eb432e 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -24,8 +24,9 @@ ;;; Commentary: -;; This file provides the drop part only. Currently supported protocols -;; are XDND, Motif and the old KDE 1.x protocol. +;; This file provides the receiving side of the XDND and Motif +;; protocols, and both the receiving and initiating ends of the old +;; KDE (OffiX) and new OffiX protocols. ;;; Code: @@ -103,14 +104,20 @@ The types are chosen in the order they appear in the list." :type '(repeat string) :group 'x) -(defcustom x-dnd-use-offix-drop nil +(defcustom x-dnd-use-offix-drop 'files "If non-nil, use the OffiX protocol to drop files and text. This allows dropping (via `dired-mouse-drag-files' or `mouse-drag-and-drop-region-cross-program') on some old Java applets and old KDE programs. Turning this off allows dropping -only text on some other programs such as xterm and urxvt." +only text on some other programs such as xterm and urxvt. + +If the symbol `files', use the OffiX protocol when dropping +files, and the fallback drop method (which is used with programs +like xterm) for text." :version "29.1" - :type 'boolean + :type '(choice (const "Don't use the OffiX protocol for drag-and-drop") + (const "Only use the OffiX protocol to drop files") + (const "Use the OffiX protocol for both files and text")) :group 'x) ;; Internal variables @@ -402,21 +409,43 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;; Old KDE protocol. Only dropping of files. +;;; Old KDE protocol. (declare-function x-window-property "xfns.c" (prop &optional frame type source delete-p vector-ret-p)) -(defun x-dnd-handle-old-kde (_event frame window _message _format data) - "Open the files in a KDE 1.x drop." +(defvar x-dnd-offix-old-kde-to-name '((-1 . DndTypeInvalid) + (0 . DndTypeUnknown) + (1 . DndTypeRawData) + (2 . DndTypeFile) + (3 . DndTypeFiles) + (4 . DndTypeText) + (5 . DndTypeDir) + (6 . DndTypeLink) + (7 . DndTypeExe) + (8 . DndTypeUrl)) + "Alist of old KDE data types to their names.") + +(defun x-dnd-handle-old-kde (event frame window _message _format data) + "Handle an old KDE (OffiX) drop. +EVENT, FRAME, WINDOW and DATA mean the same thing they do in +`x-dnd-handle-offix.'" (let ((proto (aref data 4))) ;; If PROTO > 0, this is an old KDE drop emulated by a program ;; supporting a newer version of the OffiX protocol, so we should ;; wait for the corresponding modern event instead. (when (zerop proto) - (let ((values (x-window-property "DndSelection" frame nil 0 t))) - (x-dnd-handle-uri-list window 'private - (replace-regexp-in-string "\0$" "" values)))))) + (let ((type (cdr (assq (aref data 0) x-dnd-offix-old-kde-to-name))) + (data (x-window-property "DndSelection" frame nil 0 t))) + ;; First save state. + (x-dnd-save-state window nil nil (vector type) nil) + ;; Now call the test function to decide what action to perform. + (x-dnd-maybe-call-test-function window 'private) + (unwind-protect + (x-dnd-drop-data event frame window data + (symbol-name type)) + (x-dnd-forget-drop window)))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; New OffiX protocol. @@ -432,7 +461,7 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." (8 . DndTypeUrl) (9 . DndTypeMime) (10 . DndTypePixmap)) - "Alist of OffiX protocol types to their names.") + "Alist of OffiX data types to their names.") (defun x-dnd-handle-offix-file (window action string) "Convert OffiX file name to a regular file name. @@ -1031,6 +1060,8 @@ WINDOW-ID is the X window the drop should happen to." (not (and (or (eq action 'XdndActionCopy) (eq action 'XdndActionMove)) (not (and x-dnd-use-offix-drop + (or (not (eq x-dnd-use-offix-drop 'files)) + (member "FILE_NAME" targets)) (x-dnd-do-offix-drop targets x y frame window-id))) (or commit 55e9d729ca34c4dd05bfb0d606425b8fc27d53ca Author: Po Lu Date: Thu Jun 16 13:58:39 2022 +0800 Fix Motif DND after atom ownership is lost due to frame destruction * src/xterm.c (xm_get_drag_atom_1): Record owner. (x_free_frame_resources): Clear drag atom if owner was freed. * src/xterm.h (struct x_display_info): New field `motif_drag_atom_owner'. diff --git a/src/xterm.c b/src/xterm.c index cc47427a9d..04e3223478 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2281,6 +2281,7 @@ xm_get_drag_atom_1 (struct x_display_info *dpyinfo, } dpyinfo->motif_drag_atom_time = dpyinfo->last_user_time; + dpyinfo->motif_drag_atom_owner = source_frame; XUngrabServer (dpyinfo->display); return atom; @@ -25310,6 +25311,12 @@ x_free_frame_resources (struct frame *f) g_object_unref (FRAME_OUTPUT_DATA (f)->scrollbar_foreground_css_provider); #endif + if (f == dpyinfo->motif_drag_atom_owner) + { + dpyinfo->motif_drag_atom_owner = NULL; + dpyinfo->motif_drag_atom = None; + } + if (f == dpyinfo->x_focus_frame) dpyinfo->x_focus_frame = 0; if (f == dpyinfo->x_focus_event_frame) diff --git a/src/xterm.h b/src/xterm.h index 119382c73c..ad0df6bff9 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -576,6 +576,9 @@ struct x_display_info /* When it was owned. */ Time motif_drag_atom_time; + /* The frame that currently owns `motif_drag_atom'. */ + struct frame *motif_drag_atom_owner; + /* Extended window manager hints, Atoms supported by the window manager and atoms for setting the window type. */ Atom Xatom_net_supported, Xatom_net_supporting_wm_check; commit 054832c9e12ed0deb669e1962674957b2ffa5638 Merge: 6dd4c5b953 4d7a936ac2 Author: Stefan Kangas Date: Thu Jun 16 06:52:01 2022 +0200 Merge from origin/emacs-28 4d7a936ac2 ; * src/fileio.c (Fset_file_modes): Improve previous change 32cff740e2 Describe 'set-file-modes' argument prompting commit 6dd4c5b953b666a9079910665d770ed56ecbf65d Author: Po Lu Date: Thu Jun 16 12:49:07 2022 +0800 Improve drag atom computation * src/xterm.c (xm_get_drag_window): Avoid leak if error occured creating drag window. Also use StructureNotifyMask instead of ButtonPressMask. (xm_get_drag_atom_1): Update. Make EMACS_DRAG_ATOM a list of atoms and use the first one that isn't currently owned. (xm_get_drag_atom): Stop owning selection here. (xm_setup_drag_info): Record chosen atom. (x_dnd_cleanup_drag_and_drop, x_dnd_begin_drag_and_drop) (x_dnd_update_state, handle_one_xevent, x_connection_closed): Use chosen atom. * src/xterm.h (struct x_display_info): New field `motif_drag_atom_time'. diff --git a/src/xterm.c b/src/xterm.c index 0e00632174..cc47427a9d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1164,6 +1164,9 @@ static bool x_dnd_xm_use_help; /* Whether or not Motif drag initiator info was set up. */ static bool x_dnd_motif_setup_p; +/* The Motif drag atom used during the drag-and-drop operation. */ +static Atom x_dnd_motif_atom; + /* The target window we are waiting for an XdndFinished message from. */ static Window x_dnd_pending_finish_target; @@ -1829,10 +1832,8 @@ xm_get_drag_window (struct x_display_info *dpyinfo) { drag_window = *(Window *) tmp_data; x_catch_errors (dpyinfo->display); - /* We use ButtonPressMask since it's one of the events an - input-only window can never get. */ XSelectInput (dpyinfo->display, drag_window, - ButtonPressMask); + StructureNotifyMask); rc = !x_had_errors_p (dpyinfo->display); x_uncatch_errors_after_check (); @@ -1928,6 +1929,8 @@ xm_get_drag_window (struct x_display_info *dpyinfo) punt. */ if (error) { + XSetCloseDownMode (temp_display, DestroyAll); + /* If the drag window was actually created, delete it now. Probably, a BadAlloc happened during the XChangeProperty request. */ @@ -1958,10 +1961,7 @@ xm_get_drag_window (struct x_display_info *dpyinfo) current display, and the XOpenDisplay above didn't accidentally connect to some other display. */ x_catch_errors (dpyinfo->display); - /* We use ButtonPressMask since it's one of the events an - input-only window can never get. */ - XSelectInput (dpyinfo->display, drag_window, - ButtonPressMask); + XSelectInput (dpyinfo->display, drag_window, StructureNotifyMask); rc = !x_had_errors_p (dpyinfo->display); x_uncatch_errors_after_check (); unblock_input (); @@ -2178,14 +2178,24 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, return idx; } +/* Allocate an atom that will be used for the Motif selection during + the drag-and-drop operation. + + Grab the server, and then retrieve a list of atoms named + _EMACS_DRAG_ATOM from the root window. Find the first atom that + has no selection owner, own it and return it. If there is no such + atom, add a unique atom to the end of the list and return that + instead. */ + static Atom -xm_get_drag_atom_1 (struct x_display_info *dpyinfo) +xm_get_drag_atom_1 (struct x_display_info *dpyinfo, + struct frame *source_frame) { - Atom actual_type, atom; + Atom actual_type, *atoms, atom; unsigned long nitems, bytes_remaining; unsigned char *tmp_data; - unsigned long inumber; int rc, actual_format; + unsigned long i; char *buffer; /* Make sure this operation is done atomically. */ @@ -2193,38 +2203,84 @@ xm_get_drag_atom_1 (struct x_display_info *dpyinfo) rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, dpyinfo->Xatom_EMACS_DRAG_ATOM, - 0, 1, False, XA_CARDINAL, &actual_type, + 0, LONG_MAX, False, XA_ATOM, &actual_type, &actual_format, &nitems, &bytes_remaining, &tmp_data); + atom = None; + /* GCC thinks i is used unitialized, but it's always initialized if + `atoms' exists at that particular spot. */ + i = 0; if (rc == Success - && actual_format == 32 && nitems == 1 - && actual_type == XA_CARDINAL) + && actual_format == 32 && nitems + && actual_type == XA_ATOM) { - inumber = *(unsigned long *) tmp_data; - inumber &= 0xffffffff; + atoms = (Atom *) tmp_data; + + x_catch_errors (dpyinfo->display); + + for (i = 0; i < nitems; ++i) + { + if (XGetSelectionOwner (dpyinfo->display, + atoms[i]) == None + && !x_had_errors_p (dpyinfo->display)) + { + atom = atoms[i]; + break; + } + } + + x_uncatch_errors (); } - else - inumber = 0; if (tmp_data) XFree (tmp_data); - if (X_LONG_MAX - inumber < 1) - inumber = 0; - - inumber += 1; buffer = dpyinfo->motif_drag_atom_name; - /* FIXME: this interns a unique atom for every Emacs session. - Eventually the atoms simply pile up. It may be worth - implementing the Motif atoms table logic here. */ - sprintf (buffer, "_EMACS_ATOM_%lu", inumber); - atom = XInternAtom (dpyinfo->display, buffer, False); + if (atom) + { + sprintf (buffer, "_EMACS_ATOM_%lu", i + 1); + XSetSelectionOwner (dpyinfo->display, atom, + FRAME_X_WINDOW (source_frame), + dpyinfo->last_user_time); + + /* The selection's last-change time is newer than our + last_user_time, so create a new selection instead. */ + if (XGetSelectionOwner (dpyinfo->display, atom) + != FRAME_X_WINDOW (source_frame)) + atom = None; + } + + while (!atom) + { + sprintf (buffer, "_EMACS_ATOM_%lu", nitems + 1); + atom = XInternAtom (dpyinfo->display, buffer, False); + + XSetSelectionOwner (dpyinfo->display, atom, + FRAME_X_WINDOW (source_frame), + dpyinfo->last_user_time); + + XChangeProperty (dpyinfo->display, dpyinfo->root_window, + dpyinfo->Xatom_EMACS_DRAG_ATOM, XA_ATOM, 32, + (rc == Success && (actual_format != 32 + || actual_type != XA_ATOM) + ? PropModeReplace : PropModeAppend), + (unsigned char *) &atom, 1); - XChangeProperty (dpyinfo->display, dpyinfo->root_window, - dpyinfo->Xatom_EMACS_DRAG_ATOM, XA_CARDINAL, 32, - PropModeReplace, (unsigned char *) &inumber, 1); + actual_format = 32; + actual_type = XA_ATOM; + rc = Success; + nitems += 1; + + /* The selection's last-change time is newer than our + last_user_time, so create a new selection (again). */ + if (XGetSelectionOwner (dpyinfo->display, atom) + != FRAME_X_WINDOW (source_frame)) + atom = None; + } + + dpyinfo->motif_drag_atom_time = dpyinfo->last_user_time; XUngrabServer (dpyinfo->display); return atom; @@ -2238,7 +2294,7 @@ xm_get_drag_atom (struct x_display_info *dpyinfo) if (dpyinfo->motif_drag_atom != None) atom = dpyinfo->motif_drag_atom; else - atom = xm_get_drag_atom_1 (dpyinfo); + atom = xm_get_drag_atom_1 (dpyinfo, x_dnd_frame); dpyinfo->motif_drag_atom = atom; return atom; @@ -2250,18 +2306,11 @@ xm_setup_drag_info (struct x_display_info *dpyinfo, { Atom atom; xm_drag_initiator_info drag_initiator_info; - int idx, rc; + int idx; atom = xm_get_drag_atom (dpyinfo); - x_catch_errors (dpyinfo->display); - XSetSelectionOwner (dpyinfo->display, atom, - FRAME_X_WINDOW (source_frame), - dpyinfo->last_user_time); - rc = x_had_errors_p (dpyinfo->display); - x_uncatch_errors_after_check (); - - if (rc) + if (atom == None) return; XSETCAR (x_dnd_selection_alias_cell, @@ -2284,6 +2333,7 @@ xm_setup_drag_info (struct x_display_info *dpyinfo, &drag_initiator_info); x_dnd_motif_setup_p = true; + x_dnd_motif_atom = atom; } } @@ -4423,7 +4473,7 @@ x_dnd_cleanup_drag_and_drop (void *frame) XM_DROP_ACTION_DROP_CANCEL); dmsg.x = 0; dmsg.y = 0; - dmsg.index_atom = xm_get_drag_atom (FRAME_DISPLAY_INFO (f)); + dmsg.index_atom = x_dnd_motif_atom; dmsg.source_window = FRAME_X_WINDOW (f); x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, @@ -11491,7 +11541,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, XM_DROP_ACTION_DROP_CANCEL); dmsg.x = 0; dmsg.y = 0; - dmsg.index_atom = xm_get_drag_atom (FRAME_DISPLAY_INFO (f)); + dmsg.index_atom = x_dnd_motif_atom; dmsg.source_window = FRAME_X_WINDOW (f); x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, @@ -11529,7 +11579,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* Delete the Motif drag initiator info if it was set up. */ if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - xm_get_drag_atom (FRAME_DISPLAY_INFO (f))); + x_dnd_motif_atom); /* Remove any type list set as well. */ @@ -11584,7 +11634,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, XM_DROP_ACTION_DROP_CANCEL); dmsg.x = 0; dmsg.y = 0; - dmsg.index_atom = xm_get_drag_atom (FRAME_DISPLAY_INFO (f)); + dmsg.index_atom = x_dnd_motif_atom; dmsg.source_window = FRAME_X_WINDOW (f); x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, @@ -11621,7 +11671,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* Delete the Motif drag initiator info if it was set up. */ if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - xm_get_drag_atom (FRAME_DISPLAY_INFO (f))); + x_dnd_motif_atom); /* Remove any type list set as well. */ @@ -11665,7 +11715,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* Delete the Motif drag initiator info if it was set up. */ if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - xm_get_drag_atom (FRAME_DISPLAY_INFO (f))); + x_dnd_motif_atom); /* Remove any type list set as well. */ if (x_dnd_init_type_lists && x_dnd_n_targets > 3) @@ -15728,7 +15778,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) emsg.zero = 0; emsg.timestamp = timestamp; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); - emsg.index_atom = xm_get_drag_atom (dpyinfo); + emsg.index_atom = x_dnd_motif_atom; if (x_dnd_motif_setup_p) xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), @@ -15800,7 +15850,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) XM_DROP_ACTION_DROP_CANCEL); dsmsg.x = 0; dsmsg.y = 0; - dsmsg.index_atom = xm_get_drag_atom (dpyinfo); + dsmsg.index_atom = x_dnd_motif_atom; dsmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); x_dnd_send_xm_leave_for_drop (dpyinfo, x_dnd_frame, @@ -16558,6 +16608,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, { const XSelectionClearEvent *eventp = &event->xselectionclear; + if (eventp->selection == dpyinfo->motif_drag_atom + && dpyinfo->motif_drag_atom_time <= eventp->time) + dpyinfo->motif_drag_atom = None; + inev.sie.kind = SELECTION_CLEAR_EVENT; SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo; SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; @@ -16600,7 +16654,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (x_dnd_waiting_for_finish && x_dnd_waiting_for_motif_finish == 2 && dpyinfo == x_dnd_waiting_for_motif_finish_display - && eventp->selection == xm_get_drag_atom (dpyinfo) + && eventp->selection == x_dnd_motif_atom && (eventp->target == dpyinfo->Xatom_XmTRANSFER_SUCCESS || eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE)) { @@ -18009,7 +18063,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, emsg.zero = 0; emsg.timestamp = event->xbutton.time; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); - emsg.index_atom = xm_get_drag_atom (dpyinfo); + emsg.index_atom = x_dnd_motif_atom; if (x_dnd_motif_setup_p) xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), @@ -18623,7 +18677,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dmsg.timestamp = event->xbutton.time; dmsg.x = event->xbutton.x_root; dmsg.y = event->xbutton.y_root; - dmsg.index_atom = xm_get_drag_atom (dpyinfo); + dmsg.index_atom = x_dnd_motif_atom; dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style)) @@ -19734,7 +19788,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, emsg.zero = 0; emsg.timestamp = xev->time; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); - emsg.index_atom = xm_get_drag_atom (dpyinfo); + emsg.index_atom = x_dnd_motif_atom; if (x_dnd_motif_setup_p) xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), @@ -20030,7 +20084,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, instances of Emacs try to drag into the same window at the same time. */ - dmsg.index_atom = xm_get_drag_atom (dpyinfo); + dmsg.index_atom = x_dnd_motif_atom; dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style)) @@ -22921,7 +22975,7 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) XM_DROP_ACTION_DROP_CANCEL); dmsg.x = 0; dmsg.y = 0; - dmsg.index_atom = xm_get_drag_atom (FRAME_DISPLAY_INFO (f)); + dmsg.index_atom = x_dnd_motif_atom; dmsg.source_window = FRAME_X_WINDOW (f); x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, diff --git a/src/xterm.h b/src/xterm.h index 9df1feae5b..119382c73c 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -573,6 +573,9 @@ struct x_display_info char motif_drag_atom_name[sizeof "_EMACS_ATOM_%lu" - 3 + INT_STRLEN_BOUND (unsigned long)]; + /* When it was owned. */ + Time motif_drag_atom_time; + /* Extended window manager hints, Atoms supported by the window manager and atoms for setting the window type. */ Atom Xatom_net_supported, Xatom_net_supporting_wm_check; commit 343482d641511b54aa0444791770b4ea70d27cc7 Author: Paul Eggert Date: Wed Jun 15 23:08:03 2022 -0500 Streamline time decoding and conversion * src/lisp.h (lisp_h_BASE2_EQ, BASE2_EQ): New macros and functions. * src/timefns.c (tzlookup, Fdecode_time): Use them. (Ftime_convert): Convert to symbol once, instead of many times. diff --git a/src/lisp.h b/src/lisp.h index 499bacc330..05b0754ff6 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -368,6 +368,11 @@ typedef EMACS_INT Lisp_Word; ((ok) ? (void) 0 : wrong_type_argument (predicate, x)) #define lisp_h_CONSP(x) TAGGEDP (x, Lisp_Cons) #define lisp_h_BASE_EQ(x, y) (XLI (x) == XLI (y)) +#define lisp_h_BASE2_EQ(x, y) \ + (BASE_EQ (x, y) \ + || (symbols_with_pos_enabled \ + && SYMBOL_WITH_POS_P (x) \ + && BASE_EQ (XSYMBOL_WITH_POS (x)->sym, y))) /* FIXME: Do we really need to inline the whole thing? * What about keeping the part after `symbols_with_pos_enabled` in @@ -453,6 +458,7 @@ typedef EMACS_INT Lisp_Word; # define CHECK_TYPE(ok, predicate, x) lisp_h_CHECK_TYPE (ok, predicate, x) # define CONSP(x) lisp_h_CONSP (x) # define BASE_EQ(x, y) lisp_h_BASE_EQ (x, y) +# define BASE2_EQ(x, y) lisp_h_BASE2_EQ (x, y) # define FLOATP(x) lisp_h_FLOATP (x) # define FIXNUMP(x) lisp_h_FIXNUMP (x) # define NILP(x) lisp_h_NILP (x) @@ -1318,6 +1324,14 @@ INLINE bool return lisp_h_BASE_EQ (x, y); } +/* Return true if X and Y are the same object, reckoning X to be the + same as a bare symbol Y if X is Y with position. */ +INLINE bool +(BASE2_EQ) (Lisp_Object x, Lisp_Object y) +{ + return lisp_h_BASE2_EQ (x, y); +} + /* Return true if X and Y are the same object, reckoning a symbol with position as being the same as the bare symbol. */ INLINE bool diff --git a/src/timefns.c b/src/timefns.c index 6333e302ea..13a84f6b3c 100644 --- a/src/timefns.c +++ b/src/timefns.c @@ -212,7 +212,7 @@ tzlookup (Lisp_Object zone, bool settz) if (NILP (zone)) return local_tz; - else if (EQ (zone, Qt) || BASE_EQ (zone, make_fixnum (0))) + else if (BASE_EQ (zone, make_fixnum (0)) || BASE2_EQ (zone, Qt)) { zone_string = "UTC0"; new_tz = utc_tz; @@ -221,7 +221,7 @@ tzlookup (Lisp_Object zone, bool settz) { bool plain_integer = FIXNUMP (zone); - if (EQ (zone, Qwall)) + if (BASE2_EQ (zone, Qwall)) zone_string = 0; else if (STRINGP (zone)) zone_string = SSDATA (ENCODE_SYSTEM (zone)); @@ -729,7 +729,7 @@ decode_time_components (enum timeform form, case TIMEFORM_TICKS_HZ: if (INTEGERP (high) - && (!NILP (Fnatnump (low)) && !BASE_EQ (low, make_fixnum (0)))) + && !NILP (Fnatnump (low)) && !BASE_EQ (low, make_fixnum (0))) return decode_ticks_hz (high, low, result, dresult); return EINVAL; @@ -1535,7 +1535,7 @@ usage: (decode-time &optional TIME ZONE FORM) */) /* Compute SEC from LOCAL_TM.tm_sec and HZ. */ Lisp_Object hz = lt.hz, sec; - if (BASE_EQ (hz, make_fixnum (1)) || !EQ (form, Qt)) + if (BASE_EQ (hz, make_fixnum (1)) || !BASE2_EQ (form, Qt)) sec = make_fixnum (local_tm.tm_sec); else { @@ -1748,11 +1748,13 @@ bits, and USEC and PSEC are the microsecond and picosecond counts. */) enum timeform input_form = decode_lisp_time (time, false, &t, 0); if (NILP (form)) form = current_time_list ? Qlist : Qt; - if (EQ (form, Qlist)) + if (symbols_with_pos_enabled && SYMBOL_WITH_POS_P (form)) + form = SYMBOL_WITH_POS_SYM (form); + if (BASE_EQ (form, Qlist)) return ticks_hz_list4 (t.ticks, t.hz); - if (EQ (form, Qinteger)) + if (BASE_EQ (form, Qinteger)) return FASTER_TIMEFNS && INTEGERP (time) ? time : lisp_time_seconds (t); - if (EQ (form, Qt)) + if (BASE_EQ (form, Qt)) form = t.hz; if (FASTER_TIMEFNS && input_form == TIMEFORM_TICKS_HZ && BASE_EQ (form, XCDR (time))) commit 9a2be29672b8569406777af24d60f0afabf8b52d Author: Paul Eggert Date: Wed Jun 15 23:08:03 2022 -0500 Don’t test time functions for NaNs, INF * test/src/timefns-tests.el (decode-then-encode-time) (time-equal-p-NaN-NaN, time-arith-tests): Don’t test time functions with infinities and NaNs, which are not Lisp time values. diff --git a/test/src/timefns-tests.el b/test/src/timefns-tests.el index 08d06f27d9..24f9000ffb 100644 --- a/test/src/timefns-tests.el +++ b/test/src/timefns-tests.el @@ -93,7 +93,6 @@ most-negative-fixnum most-positive-fixnum (1- most-negative-fixnum) (1+ most-positive-fixnum) - 1e+INF -1e+INF 1e+NaN -1e+NaN '(0 1 0 0) '(1 0 0 0) '(-1 0 0 0) '(123456789000000 . 1000000) (cons (1+ most-positive-fixnum) 1000000000000) @@ -169,10 +168,6 @@ a fixed place on the right and are padded on the left." (ert-deftest time-equal-p-nil-nil () (should (time-equal-p nil nil))) -(ert-deftest time-equal-p-NaN-NaN () - (let ((x 0.0e+NaN)) - (should (not (time-equal-p x x))))) - (ert-deftest time-arith-tests () (let ((time-values (list 0 -1 1 0.0 -0.0 -1.0 1.0 most-negative-fixnum most-positive-fixnum @@ -184,7 +179,6 @@ a fixed place on the right and are padded on the left." 1e10 -1e10 1e-10 -1e-10 1e16 -1e16 1e-16 -1e-16 1e37 -1e37 1e-37 -1e-37 - 1e+INF -1e+INF 1e+NaN -1e+NaN '(0 0 0 1) '(0 0 1 0) '(0 1 0 0) '(1 0 0 0) '(-1 0 0 0) '(1 2 3 4) '(-1 2 3 4) '(-123456789 . 100000) '(123456789 . 1000000) commit 9bce1f3d7019f00f7c1c889d8be7832e9b645bec Author: Paul Eggert Date: Wed Jun 15 23:08:03 2022 -0500 Prefer BASE_EQ in time-sensitive ops * src/timefns.c (tzlookup, lisp_time_hz_ticks) (decode_time_components, lisp_to_timespec, lispint_arith) (time_arith, time_cmp, Fdecode_time, Fencode_time) (Ftime_convert): Prefer BASE_EQ to EQ where either will do. diff --git a/src/timefns.c b/src/timefns.c index 7d2e3f6414..6333e302ea 100644 --- a/src/timefns.c +++ b/src/timefns.c @@ -212,7 +212,7 @@ tzlookup (Lisp_Object zone, bool settz) if (NILP (zone)) return local_tz; - else if (EQ (zone, Qt) || EQ (zone, make_fixnum (0))) + else if (EQ (zone, Qt) || BASE_EQ (zone, make_fixnum (0))) { zone_string = "UTC0"; new_tz = utc_tz; @@ -516,7 +516,7 @@ lisp_time_hz_ticks (struct lisp_time t, Lisp_Object hz) /* The idea is to return the floor of ((T.ticks * HZ) / T.hz). */ /* For speed, just return T.ticks if T.hz == HZ. */ - if (FASTER_TIMEFNS && EQ (t.hz, hz)) + if (FASTER_TIMEFNS && BASE_EQ (t.hz, hz)) return t.ticks; /* Check HZ for validity. */ @@ -729,7 +729,7 @@ decode_time_components (enum timeform form, case TIMEFORM_TICKS_HZ: if (INTEGERP (high) - && (!NILP (Fnatnump (low)) && !EQ (low, make_fixnum (0)))) + && (!NILP (Fnatnump (low)) && !BASE_EQ (low, make_fixnum (0)))) return decode_ticks_hz (high, low, result, dresult); return EINVAL; @@ -923,7 +923,7 @@ lisp_to_timespec (struct lisp_time t) yielding quotient Q (tv_sec) and remainder NS (tv_nsec). Return an invalid timespec if Q does not fit in time_t. For speed, prefer fixnum arithmetic if it works. */ - if (FASTER_TIMEFNS && EQ (t.hz, timespec_hz)) + if (FASTER_TIMEFNS && BASE_EQ (t.hz, timespec_hz)) { if (FIXNUMP (t.ticks)) { @@ -942,7 +942,7 @@ lisp_to_timespec (struct lisp_time t) else ns = mpz_fdiv_q_ui (*q, *xbignum_val (t.ticks), TIMESPEC_HZ); } - else if (FASTER_TIMEFNS && EQ (t.hz, make_fixnum (1))) + else if (FASTER_TIMEFNS && BASE_EQ (t.hz, make_fixnum (1))) { ns = 0; if (FIXNUMP (t.ticks)) @@ -1043,7 +1043,7 @@ lispint_arith (Lisp_Object a, Lisp_Object b, bool subtract) if (FASTER_TIMEFNS && FIXNUMP (b)) { - if (EQ (b, make_fixnum (0))) + if (BASE_EQ (b, make_fixnum (0))) return a; /* For speed, use EMACS_INT arithmetic if it will do. */ @@ -1090,14 +1090,14 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract) quicker while we're at it. Compare here rather than earlier, to handle NaNs and check formats. */ struct lisp_time tb; - if (EQ (a, b)) + if (BASE_EQ (a, b)) bform = aform, tb = ta; else tb = lisp_time_struct (b, &bform); Lisp_Object ticks, hz; - if (FASTER_TIMEFNS && EQ (ta.hz, tb.hz)) + if (FASTER_TIMEFNS && BASE_EQ (ta.hz, tb.hz)) { hz = ta.hz; ticks = lispint_arith (ta.ticks, tb.ticks, subtract); @@ -1175,7 +1175,7 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract) either input used (TICKS . HZ) form or the result can't be expressed exactly in (HI LO US PS) form, otherwise the (HI LO US PS) form for backward compatibility. */ - return (EQ (hz, make_fixnum (1)) + return (BASE_EQ (hz, make_fixnum (1)) ? ticks : (!current_time_list || aform == TIMEFORM_TICKS_HZ @@ -1222,7 +1222,7 @@ time_cmp (Lisp_Object a, Lisp_Object b) while we're at it. Compare here rather than earlier, to handle NaNs. This means (time-equal-p X X) does not signal an error if X is not a valid time value, but that's OK. */ - if (EQ (a, b)) + if (BASE_EQ (a, b)) return 0; /* Compare (ATICKS . AZ) to (BTICKS . BHZ) by comparing @@ -1231,7 +1231,7 @@ time_cmp (Lisp_Object a, Lisp_Object b) struct lisp_time tb = lisp_time_struct (b, 0); mpz_t const *za = bignum_integer (&mpz[0], ta.ticks); mpz_t const *zb = bignum_integer (&mpz[1], tb.ticks); - if (! (FASTER_TIMEFNS && EQ (ta.hz, tb.hz))) + if (! (FASTER_TIMEFNS && BASE_EQ (ta.hz, tb.hz))) { /* This could be sped up by looking at the signs, sizes, and number of bits of the two sides; see how GMP does mpq_cmp. @@ -1535,7 +1535,7 @@ usage: (decode-time &optional TIME ZONE FORM) */) /* Compute SEC from LOCAL_TM.tm_sec and HZ. */ Lisp_Object hz = lt.hz, sec; - if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt)) + if (BASE_EQ (hz, make_fixnum (1)) || !EQ (form, Qt)) sec = make_fixnum (local_tm.tm_sec); else { @@ -1685,7 +1685,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */) struct lisp_time lt; decode_lisp_time (secarg, false, <, 0); Lisp_Object hz = lt.hz, sec, subsecticks; - if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1))) + if (FASTER_TIMEFNS && BASE_EQ (hz, make_fixnum (1))) { sec = lt.ticks; subsecticks = make_fixnum (0); @@ -1715,7 +1715,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */) if (tm.tm_wday < 0) time_error (mktime_errno); - if (EQ (hz, make_fixnum (1))) + if (BASE_EQ (hz, make_fixnum (1))) return (current_time_list ? list2 (hi_time (value), lo_time (value)) : INT_TO_INTEGER (value)); @@ -1755,7 +1755,7 @@ bits, and USEC and PSEC are the microsecond and picosecond counts. */) if (EQ (form, Qt)) form = t.hz; if (FASTER_TIMEFNS - && input_form == TIMEFORM_TICKS_HZ && EQ (form, XCDR (time))) + && input_form == TIMEFORM_TICKS_HZ && BASE_EQ (form, XCDR (time))) return time; return Fcons (lisp_time_hz_ticks (t, form), form); } commit 16ee227c18db0d70d9a3e97230119464924797cc Author: Paul Eggert Date: Wed Jun 15 23:05:22 2022 -0500 icalendar-tests no longer assumes TZ = wall Do not assume that the TZ environment variable is either unset or agrees with /etc/localtime. I ran into this test bug while running ‘TZ=America/Chicago make check’ on a platform where /etc/localtime was America/Los_Angeles. * test/lisp/calendar/icalendar-tests.el: (icalendar-tests--decode-isodatetime): Don’t use set-time-zone-rule, whose doc string says “Instead of calling this function, you typically want something else” for a reason. Instead, pass the zone arg to icalendar-test--format. diff --git a/test/lisp/calendar/icalendar-tests.el b/test/lisp/calendar/icalendar-tests.el index c918b0f63f..ac7a84aa57 100644 --- a/test/lisp/calendar/icalendar-tests.el +++ b/test/lisp/calendar/icalendar-tests.el @@ -1639,19 +1639,17 @@ SUMMARY:NNN Wwwwwwww Wwwww - Aaaaaa Pppppppp rrrrrr ddd oo Nnnnnnnn 30 "2004-09-17T03:09:10+0000")) (let ((orig (icalendar-test--format "20040917T050910"))) (unwind-protect - (progn - (set-time-zone-rule "UTC-02:00") - (should (equal (icalendar-test--format "20040917T050910") + (let ((zone "XXX-02")) + (should (equal (icalendar-test--format "20040917T050910" nil zone) "2004-09-17T03:09:10+0000")) - (should (equal (icalendar-test--format "20040917T0509") + (should (equal (icalendar-test--format "20040917T0509" nil zone) "2004-09-17T03:09:00+0000")) - (should (equal (icalendar-test--format "20040917") + (should (equal (icalendar-test--format "20040917" nil zone) "2004-09-16T22:00:00+0000")) - (should (equal (icalendar-test--format "20040917T050910" 1) + (should (equal (icalendar-test--format "20040917T050910" 1 zone) "2004-09-18T03:09:10+0000")) - (should (equal (icalendar-test--format "20040917T050910" 30) + (should (equal (icalendar-test--format "20040917T050910" 30 zone) "2004-10-17T03:09:10+0000"))) - (set-time-zone-rule 'wall) ;; (set-time-zone-rule nil) is broken (should (equal orig (icalendar-test--format "20040917T050910"))))) (should (equal (icalendar-test--format "20040917T050910Z") "2004-09-17T05:09:10+0000")) commit 160b22ebf7cc6a3bbe7fb0955179d53f0d02dac0 Author: Po Lu Date: Thu Jun 16 10:39:01 2022 +0800 Handle OffiX drop of multiple files * lisp/x-dnd.el (x-dnd-types-alist): Register DndTypeFiles. (x-dnd-offix-id-to-name): Fix typo. (x-dnd-handle-offix-files): New function. (x-dnd-convert-to-offix): Fix conversion to DndTypeFiles. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 684f8f8155..aa4eb8849f 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -67,6 +67,7 @@ The default value for this variable is `x-dnd-default-test-function'." (,(purecopy "STRING") . dnd-insert-text) (,(purecopy "TEXT") . dnd-insert-text) (,(purecopy "DndTypeFile") . x-dnd-handle-offix-file) + (,(purecopy "DndTypeFiles") . x-dnd-handle-offix-files) (,(purecopy "DndTypeText") . dnd-insert-text)) "Which function to call to handle a drop of that type. If the type for the drop is not present, or the function is nil, @@ -426,7 +427,7 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." (3 . DndTypeFiles) (4 . DndTypeText) (5 . DndTypeDir) - (6 . DndTypeLInk) + (6 . DndTypeLink) (7 . DndTypeExe) (8 . DndTypeUrl) (9 . DndTypeMime) @@ -438,10 +439,23 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." Then, call `x-dnd-handle-file-name'. WINDOW and ACTION mean the same as in `x-dnd-handle-file-name'. -STRING is the raw offiX file name data." +STRING is the raw OffiX file name data." (x-dnd-handle-file-name window action (replace-regexp-in-string "\0$" "" string))) +(defun x-dnd-handle-offix-files (window action string) + "Convert OffiX file name list to a URI list. +Then, call `x-dnd-handle-file-name'. + +WINDOW and ACTION mean the same as in `x-dnd-handle-file-name'. +STRING is the raw OffiX file name data." + (x-dnd-handle-file-name window action + ;; OffiX file name lists contain one extra + ;; NULL byte at the end. + (if (string-suffix-p "\0\0" string) + (substring string 0 (1- (length string))) + string))) + (defun x-dnd-handle-offix (event frame window _message-atom _format data) "Handle OffiX drop event EVENT. FRAME is the frame where the drop happened. @@ -966,7 +980,7 @@ data could not be converted." ;; This means there are multiple file names in ;; XdndSelection. Convert the file name data to a format ;; that OffiX understands. - (cons 'DndTypeFiles (concat file-name-data "\0")) + (cons 'DndTypeFiles (concat file-name-data "\0\0")) (cons 'DndTypeFile (concat file-name-data "\0")))) ((and (member "STRING" targets) (setq string-data commit 9accc800a75529c1eaf81d6844c53b6ca2f5622f Author: Po Lu Date: Thu Jun 16 10:08:12 2022 +0800 Comply with the Motif requirement for unique drag atoms * src/xselect.c (x_handle_selection_request) (Fx_get_selection_internal, syms_of_xselect): New variable `x-selection-alias-alist'. Respect that alist of aliases. * src/xterm.c (x_atom_refs): Intern _EMACS_DRAG_ATOM. (xm_get_drag_atom_1, xm_get_drag_atom): New functions. (xm_setup_drag_info, x_dnd_cleanup_drag_and_drop) (x_dnd_begin_drag_and_drop, x_dnd_update_state, handle_one_xevent) (x_connection_closed, x_intern_cached_atom): Alias the drag atom to XdndSelection. Use it instead of XdndSelection to set the Motif index atom. (x_get_atom_name): Handle new atoms. (syms_of_xterm): New defsym. * src/xterm.h (struct x_display_info): New fields for new atoms and their names. diff --git a/src/xselect.c b/src/xselect.c index 96c1e9830f..fff79fb99f 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -774,6 +774,25 @@ x_handle_selection_request (struct selection_input_event *event) bool success = false; specpdl_ref count = SPECPDL_INDEX (); bool pushed; + Lisp_Object alias, tem; + + alias = Vx_selection_alias_alist; + + FOR_EACH_TAIL_SAFE (alias) + { + tem = Qnil; + + if (CONSP (alias)) + tem = XCAR (alias); + + if (CONSP (tem) + && EQ (XCAR (tem), selection_symbol) + && SYMBOLP (XCDR (tem))) + { + selection_symbol = XCDR (tem); + break; + } + } pushed = false; @@ -2055,15 +2074,27 @@ On Nextstep, TIME-STAMP and TERMINAL are unused. */) Lisp_Object time_stamp, Lisp_Object terminal) { Lisp_Object val = Qnil; + Lisp_Object maybe_alias; struct frame *f = frame_for_x_selection (terminal); CHECK_SYMBOL (selection_symbol); CHECK_SYMBOL (target_type); + if (EQ (target_type, QMULTIPLE)) error ("Retrieving MULTIPLE selections is currently unimplemented"); if (!f) error ("X selection unavailable for this frame"); + /* Quitting inside this function is okay, so we don't have to use + FOR_EACH_TAIL_SAFE. */ + maybe_alias = Fassq (selection_symbol, Vx_selection_alias_alist); + + if (!NILP (maybe_alias)) + { + selection_symbol = XCDR (maybe_alias); + CHECK_SYMBOL (selection_symbol); + } + val = x_get_local_selection (selection_symbol, target_type, true, FRAME_DISPLAY_INFO (f)); @@ -2818,6 +2849,15 @@ If non-nil, selection converters for string types (`STRING', when Emacs itself is converting the selection. */); Vx_treat_local_requests_remotely = Qnil; + DEFVAR_LISP ("x-selection-alias-alist", Vx_selection_alias_alist, + doc: /* List of selections to alias to another. +It should be an alist of a selection name to another. When a +selection request arrives for the first selection, Emacs will respond +as if the request was meant for the other. + +Note that this does not affect setting or owning selections. */); + Vx_selection_alias_alist = Qnil; + /* QPRIMARY is defined in keyboard.c. */ DEFSYM (QSECONDARY, "SECONDARY"); DEFSYM (QSTRING, "STRING"); diff --git a/src/xterm.c b/src/xterm.c index f2f80b42be..0e00632174 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -931,6 +931,7 @@ static const struct x_atom_ref x_atom_refs[] = ATOM_REFS_INIT ("CLIPBOARD_MANAGER", Xatom_CLIPBOARD_MANAGER) ATOM_REFS_INIT ("_XEMBED_INFO", Xatom_XEMBED_INFO) ATOM_REFS_INIT ("_MOTIF_WM_HINTS", Xatom_MOTIF_WM_HINTS) + ATOM_REFS_INIT ("_EMACS_DRAG_ATOM", Xatom_EMACS_DRAG_ATOM) /* For properties of font. */ ATOM_REFS_INIT ("PIXEL_SIZE", Xatom_PIXEL_SIZE) ATOM_REFS_INIT ("AVERAGE_WIDTH", Xatom_AVERAGE_WIDTH) @@ -1297,6 +1298,11 @@ static bool x_dnd_inside_handle_one_xevent; started. */ static int x_dnd_recursion_depth; +/* The cons cell containing the selection alias between the Motif drag + selection and `XdndSelection'. The car and cdr are only set when + initiating Motif drag-and-drop for the first time. */ +static Lisp_Object x_dnd_selection_alias_cell; + /* Structure describing a single window that can be the target of drag-and-drop operations. */ struct x_client_list_window @@ -2172,12 +2178,95 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, return idx; } +static Atom +xm_get_drag_atom_1 (struct x_display_info *dpyinfo) +{ + Atom actual_type, atom; + unsigned long nitems, bytes_remaining; + unsigned char *tmp_data; + unsigned long inumber; + int rc, actual_format; + char *buffer; + + /* Make sure this operation is done atomically. */ + XGrabServer (dpyinfo->display); + + rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, + dpyinfo->Xatom_EMACS_DRAG_ATOM, + 0, 1, False, XA_CARDINAL, &actual_type, + &actual_format, &nitems, &bytes_remaining, + &tmp_data); + + if (rc == Success + && actual_format == 32 && nitems == 1 + && actual_type == XA_CARDINAL) + { + inumber = *(unsigned long *) tmp_data; + inumber &= 0xffffffff; + } + else + inumber = 0; + + if (tmp_data) + XFree (tmp_data); + + if (X_LONG_MAX - inumber < 1) + inumber = 0; + + inumber += 1; + buffer = dpyinfo->motif_drag_atom_name; + + /* FIXME: this interns a unique atom for every Emacs session. + Eventually the atoms simply pile up. It may be worth + implementing the Motif atoms table logic here. */ + sprintf (buffer, "_EMACS_ATOM_%lu", inumber); + atom = XInternAtom (dpyinfo->display, buffer, False); + + XChangeProperty (dpyinfo->display, dpyinfo->root_window, + dpyinfo->Xatom_EMACS_DRAG_ATOM, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *) &inumber, 1); + + XUngrabServer (dpyinfo->display); + return atom; +} + +static Atom +xm_get_drag_atom (struct x_display_info *dpyinfo) +{ + Atom atom; + + if (dpyinfo->motif_drag_atom != None) + atom = dpyinfo->motif_drag_atom; + else + atom = xm_get_drag_atom_1 (dpyinfo); + + dpyinfo->motif_drag_atom = atom; + return atom; +} + static void xm_setup_drag_info (struct x_display_info *dpyinfo, struct frame *source_frame) { + Atom atom; xm_drag_initiator_info drag_initiator_info; - int idx; + int idx, rc; + + atom = xm_get_drag_atom (dpyinfo); + + x_catch_errors (dpyinfo->display); + XSetSelectionOwner (dpyinfo->display, atom, + FRAME_X_WINDOW (source_frame), + dpyinfo->last_user_time); + rc = x_had_errors_p (dpyinfo->display); + x_uncatch_errors_after_check (); + + if (rc) + return; + + XSETCAR (x_dnd_selection_alias_cell, + x_atom_to_symbol (dpyinfo, atom)); + XSETCDR (x_dnd_selection_alias_cell, QXdndSelection); idx = xm_setup_dnd_targets (dpyinfo, x_dnd_targets, x_dnd_n_targets); @@ -2187,10 +2276,10 @@ xm_setup_drag_info (struct x_display_info *dpyinfo, drag_initiator_info.byteorder = XM_BYTE_ORDER_CUR_FIRST; drag_initiator_info.protocol = XM_DRAG_PROTOCOL_VERSION; drag_initiator_info.table_index = idx; - drag_initiator_info.selection = dpyinfo->Xatom_XdndSelection; + drag_initiator_info.selection = atom; - xm_write_drag_initiator_info (dpyinfo->display, FRAME_X_WINDOW (source_frame), - dpyinfo->Xatom_XdndSelection, + xm_write_drag_initiator_info (dpyinfo->display, + FRAME_X_WINDOW (source_frame), atom, dpyinfo->Xatom_MOTIF_DRAG_INITIATOR_INFO, &drag_initiator_info); @@ -4334,7 +4423,7 @@ x_dnd_cleanup_drag_and_drop (void *frame) XM_DROP_ACTION_DROP_CANCEL); dmsg.x = 0; dmsg.y = 0; - dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; + dmsg.index_atom = xm_get_drag_atom (FRAME_DISPLAY_INFO (f)); dmsg.source_window = FRAME_X_WINDOW (f); x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, @@ -11189,6 +11278,16 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, record_unwind_protect_void (release_xg_select); #endif + /* Set up a meaningless alias. */ + XSETCAR (x_dnd_selection_alias_cell, QSECONDARY); + XSETCDR (x_dnd_selection_alias_cell, QSECONDARY); + + /* Bind this here. The cell doesn't actually alias between + anything until `xm_setup_dnd_targets' is called. */ + specbind (Qx_selection_alias_alist, + Fcons (x_dnd_selection_alias_cell, + Vx_selection_alias_alist)); + /* Initialize most of the state for the drag-and-drop operation. */ x_dnd_in_progress = true; x_dnd_recursion_depth = command_loop_level + minibuf_level; @@ -11392,7 +11491,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, XM_DROP_ACTION_DROP_CANCEL); dmsg.x = 0; dmsg.y = 0; - dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; + dmsg.index_atom = xm_get_drag_atom (FRAME_DISPLAY_INFO (f)); dmsg.source_window = FRAME_X_WINDOW (f); x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, @@ -11430,7 +11529,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* Delete the Motif drag initiator info if it was set up. */ if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + xm_get_drag_atom (FRAME_DISPLAY_INFO (f))); /* Remove any type list set as well. */ @@ -11485,7 +11584,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, XM_DROP_ACTION_DROP_CANCEL); dmsg.x = 0; dmsg.y = 0; - dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; + dmsg.index_atom = xm_get_drag_atom (FRAME_DISPLAY_INFO (f)); dmsg.source_window = FRAME_X_WINDOW (f); x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, @@ -11522,7 +11621,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* Delete the Motif drag initiator info if it was set up. */ if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + xm_get_drag_atom (FRAME_DISPLAY_INFO (f))); /* Remove any type list set as well. */ @@ -11566,7 +11665,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* Delete the Motif drag initiator info if it was set up. */ if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), - FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + xm_get_drag_atom (FRAME_DISPLAY_INFO (f))); /* Remove any type list set as well. */ if (x_dnd_init_type_lists && x_dnd_n_targets > 3) @@ -15629,7 +15728,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) emsg.zero = 0; emsg.timestamp = timestamp; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); - emsg.index_atom = dpyinfo->Xatom_XdndSelection; + emsg.index_atom = xm_get_drag_atom (dpyinfo); if (x_dnd_motif_setup_p) xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), @@ -15701,8 +15800,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) XM_DROP_ACTION_DROP_CANCEL); dsmsg.x = 0; dsmsg.y = 0; - dsmsg.index_atom - = FRAME_DISPLAY_INFO (x_dnd_frame)->Xatom_XdndSelection; + dsmsg.index_atom = xm_get_drag_atom (dpyinfo); dsmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); x_dnd_send_xm_leave_for_drop (dpyinfo, x_dnd_frame, @@ -16502,7 +16600,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (x_dnd_waiting_for_finish && x_dnd_waiting_for_motif_finish == 2 && dpyinfo == x_dnd_waiting_for_motif_finish_display - && eventp->selection == dpyinfo->Xatom_XdndSelection + && eventp->selection == xm_get_drag_atom (dpyinfo) && (eventp->target == dpyinfo->Xatom_XmTRANSFER_SUCCESS || eventp->target == dpyinfo->Xatom_XmTRANSFER_FAILURE)) { @@ -17911,7 +18009,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, emsg.zero = 0; emsg.timestamp = event->xbutton.time; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); - emsg.index_atom = dpyinfo->Xatom_XdndSelection; + emsg.index_atom = xm_get_drag_atom (dpyinfo); if (x_dnd_motif_setup_p) xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), @@ -18525,7 +18623,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, dmsg.timestamp = event->xbutton.time; dmsg.x = event->xbutton.x_root; dmsg.y = event->xbutton.y_root; - dmsg.index_atom = dpyinfo->Xatom_XdndSelection; + dmsg.index_atom = xm_get_drag_atom (dpyinfo); dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style)) @@ -19636,7 +19734,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, emsg.zero = 0; emsg.timestamp = xev->time; emsg.source_window = FRAME_X_WINDOW (x_dnd_frame); - emsg.index_atom = dpyinfo->Xatom_XdndSelection; + emsg.index_atom = xm_get_drag_atom (dpyinfo); if (x_dnd_motif_setup_p) xm_send_top_level_enter_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), @@ -19932,7 +20030,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, instances of Emacs try to drag into the same window at the same time. */ - dmsg.index_atom = dpyinfo->Xatom_XdndSelection; + dmsg.index_atom = xm_get_drag_atom (dpyinfo); dmsg.source_window = FRAME_X_WINDOW (x_dnd_frame); if (!XM_DRAG_STYLE_IS_DROP_ONLY (drag_receiver_info.protocol_style)) @@ -22823,7 +22921,7 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) XM_DROP_ACTION_DROP_CANCEL); dmsg.x = 0; dmsg.y = 0; - dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; + dmsg.index_atom = xm_get_drag_atom (FRAME_DISPLAY_INFO (f)); dmsg.source_window = FRAME_X_WINDOW (f); x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, @@ -25253,6 +25351,10 @@ x_intern_cached_atom (struct x_display_info *dpyinfo, if (!strcmp (name, "WINDOW")) return XA_WINDOW; + if (dpyinfo->motif_drag_atom != None + && !strcmp (name, dpyinfo->motif_drag_atom_name)) + return dpyinfo->motif_drag_atom; + for (i = 0; i < ARRAYELTS (x_atom_refs); ++i) { ptr = (char *) dpyinfo; @@ -25311,6 +25413,10 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom, return xstrdup ("WINDOW"); default: + if (dpyinfo->motif_drag_atom + && atom == dpyinfo->motif_drag_atom) + return xstrdup (dpyinfo->motif_drag_atom_name); + if (atom == dpyinfo->Xatom_xsettings_sel) { sprintf (buffer, "_XSETTINGS_S%d", @@ -27203,6 +27309,9 @@ syms_of_xterm (void) x_dnd_action_symbol = Qnil; staticpro (&x_dnd_action_symbol); + x_dnd_selection_alias_cell = Fcons (Qnil, Qnil); + staticpro (&x_dnd_selection_alias_cell); + DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); DEFSYM (Qlatin_1, "latin-1"); DEFSYM (Qnow, "now"); @@ -27291,6 +27400,7 @@ With MS Windows, Haiku windowing or Nextstep, the value is t. */); DEFSYM (Qsuper, "super"); Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier)); DEFSYM (QXdndSelection, "XdndSelection"); + DEFSYM (Qx_selection_alias_alist, "x-selection-alias-alist"); DEFVAR_LISP ("x-ctrl-keysym", Vx_ctrl_keysym, doc: /* Which keys Emacs uses for the ctrl modifier. diff --git a/src/xterm.h b/src/xterm.h index d710069fad..9df1feae5b 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -428,8 +428,8 @@ struct x_display_info /* More atoms for font properties. The last three are private properties, see the comments in src/fontset.h. */ Atom Xatom_PIXEL_SIZE, Xatom_AVERAGE_WIDTH, - Xatom_MULE_BASELINE_OFFSET, Xatom_MULE_RELATIVE_COMPOSE, - Xatom_MULE_DEFAULT_ASCENT; + Xatom_MULE_BASELINE_OFFSET, Xatom_MULE_RELATIVE_COMPOSE, + Xatom_MULE_DEFAULT_ASCENT; /* More atoms for Ghostscript support. */ Atom Xatom_DONE, Xatom_PAGE; @@ -448,6 +448,9 @@ struct x_display_info Xatom_MOTIF_DRAG_TARGETS, Xatom_MOTIF_DRAG_AND_DROP_MESSAGE, Xatom_MOTIF_DRAG_INITIATOR_INFO, Xatom_MOTIF_DRAG_RECEIVER_INFO; + /* Atoms used by Emacs internally. */ + Atom Xatom_EMACS_DRAG_ATOM; + /* Special selections used by the Motif drop protocol to indicate success or failure. */ Atom Xatom_XmTRANSFER_SUCCESS, Xatom_XmTRANSFER_FAILURE; @@ -562,6 +565,14 @@ struct x_display_info ptrdiff_t x_dnd_atoms_size; ptrdiff_t x_dnd_atoms_length; + /* The unique drag and drop atom used on Motif. None if it was not + already computed. */ + Atom motif_drag_atom; + + /* Its name. */ + char motif_drag_atom_name[sizeof "_EMACS_ATOM_%lu" - 3 + + INT_STRLEN_BOUND (unsigned long)]; + /* Extended window manager hints, Atoms supported by the window manager and atoms for setting the window type. */ Atom Xatom_net_supported, Xatom_net_supporting_wm_check; commit 556c304007fbea1a552c65529fa86c0a5637b27b Author: Sean Whitton Date: Wed Jun 15 14:42:40 2022 -0700 * .dir-locals.el: Set emacs-lisp-docstring-fill-column. diff --git a/.dir-locals.el b/.dir-locals.el index b313945936..7812beb001 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -4,6 +4,7 @@ ((nil . ((tab-width . 8) (sentence-end-double-space . t) (fill-column . 70) + (emacs-lisp-docstring-fill-column . 65) (bug-reference-url-format . "https://debbugs.gnu.org/%s"))) (c-mode . ((c-file-style . "GNU") (c-noise-macro-names . ("INLINE" "ATTRIBUTE_NO_SANITIZE_UNDEFINED" "UNINIT" "CALLBACK" "ALIGN_STACK")) commit 82694cdb204ad61b4b08cc66e71d6526949d8e40 Author: Sean Whitton Date: Wed Jun 15 14:41:17 2022 -0700 ; * etc/NEWS: Add entry for recent minibuffer abbrev table changes. diff --git a/etc/NEWS b/etc/NEWS index 19ca21f666..43b88e6cd4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1132,6 +1132,11 @@ This means that typing 'C-u RET' on a completion candidate in the "*Completions*" buffer inserts the completion to the minibuffer, but doesn't exit the minibuffer. ++++ +*** You can now define abbrevs for the fundamental minibuffer modes. +'minibuffer-mode-abbrev-table' and +'minibuffer-inactive-mode-abbrev-table' are now defined. + ** Isearch and Replace +++ commit a29e0f1c64f82f046d6ac89d194d3c019e933a33 Author: Lars Ingebrigtsen Date: Wed Jun 15 18:36:58 2022 +0200 Adjust ibuffer test * test/lisp/ibuffer-tests.el (ibuffer-format-qualifier): Adjust test after recent formatting changes. diff --git a/test/lisp/ibuffer-tests.el b/test/lisp/ibuffer-tests.el index 252d2c5d7f..343e2ae50b 100644 --- a/test/lisp/ibuffer-tests.el +++ b/test/lisp/ibuffer-tests.el @@ -785,7 +785,7 @@ (funcall tag (funcall description 'starred-name) - ": " "nil")) + "" "")) (funcall tag (funcall description 'directory) ": " "\\"))))) @@ -806,7 +806,7 @@ (funcall tag "AND" (funcall tag (funcall description 'starred-name) - ": " "nil") + "" "") (funcall tag (funcall description 'name) ": " "elisp")) commit 1ead480ca1f49b6759bb30353ee78656490149ae Author: Lars Ingebrigtsen Date: Wed Jun 15 18:29:42 2022 +0200 Allow completing tags, parameters and values in html-mode * lisp/textmodes/sgml-mode.el (html-mode--complete-at-point): Allow completing tags, parameters and values (bug#29057). diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index b49541f47d..ff881377a7 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el @@ -2409,6 +2409,7 @@ To work around that, do: (lambda () (char-before (match-end 0)))) (setq-local add-log-current-defun-function #'html-current-defun-name) (setq-local sentence-end-base "[.?!][]\"'”)}]*\\(<[^>]*>\\)*") + (add-hook 'completion-at-point-functions 'html-mode--complete-at-point nil t) (when (fboundp 'libxml-parse-html-region) (defvar css-class-list-function) @@ -2434,6 +2435,36 @@ To work around that, do: ;; (setq imenu-sort-function nil) ; sorting the menu defeats the purpose ) +(defun html-mode--complete-at-point () + ;; Complete a tag like Date: Wed Jun 15 17:52:38 2022 +0200 Do not display 'nil for 0-ary filter qualifier in ibuf * lisp/ibuf-ext.el (ibuffer-format-qualifier-1): Do not display nil in header for 0-ary filter qualifier. * lisp/ibuf-macs.el (define-ibuffer-filter): Also fix the message. diff --git a/lisp/ibuf-ext.el b/lisp/ibuf-ext.el index 30b494f573..822ecbdd99 100644 --- a/lisp/ibuf-ext.el +++ b/lisp/ibuf-ext.el @@ -1211,7 +1211,9 @@ Interactively, prompt for NAME, and use the current filters." (let ((type (assq (car qualifier) ibuffer-filtering-alist))) (unless qualifier (error "Ibuffer: Bad qualifier %s" qualifier)) - (concat " [" (cadr type) ": " (format "%s]" (cdr qualifier))))))) + (if (cdr qualifier) + (format " [%s: %s]" (cadr type) (cdr qualifier)) + (format " [%s]" (cadr type))))))) (defun ibuffer-list-buffer-modes (&optional include-parents) "Create a completion table of buffer modes currently in use. diff --git a/lisp/ibuf-macs.el b/lisp/ibuf-macs.el index 5d2dd47945..51b206d7c4 100644 --- a/lisp/ibuf-macs.el +++ b/lisp/ibuf-macs.el @@ -321,10 +321,15 @@ bound to the current value of the filter. (when (cdr qualifier) ; Compose individual filters with `or'. (setq ,filter `(or ,@(mapcar (lambda (m) (cons ',name m)) qualifier)))))) (if (null (ibuffer-push-filter ,filter)) - (message ,(format "Filter by %s already applied: %%s" description) - ,qualifier-str) - (message ,(format "Filter by %s added: %%s" description) - ,qualifier-str) + (if ,qualifier-str + (message ,(format "Filter by %s already applied: %%s" + description) + ,qualifier-str) + (message ,(format "Filter by %s already applied" description))) + (if ,qualifier-str + (message ,(format "Filter by %s added: %%s" description) + ,qualifier-str) + (message ,(format "Filter by %s added" description))) (ibuffer-update nil t)))) (push (list ',name ,description (lambda (buf qualifier) commit ebdda80b0733f67cca58380fd28aa08db06f11ff Author: Stefan Kangas Date: Wed Jun 15 16:43:22 2022 +0200 Prefer defvar-keymap in ibuffer.el * lisp/ibuffer.el (ibuffer--filter-map, ibuffer-name-map) (ibuffer-filename/process-header-map, ibuffer-mode-name-map) (ibuffer-name-header-map, ibuffer-size-header-map) (ibuffer-mode-header-map, ibuffer-mode-filter-group-map): Prefer defvar-keymap. diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el index 7cfa428e9b..742d21d0b0 100644 --- a/lisp/ibuffer.el +++ b/lisp/ibuffer.el @@ -34,7 +34,7 @@ ;; you might be interested in replacing the default `list-buffers' key ;; binding by adding the following to your init file: ;; -;; (global-set-key (kbd "C-x C-b") 'ibuffer) +;; (keymap-global-set "C-x C-b" 'ibuffer) ;; ;; See also the various customization options, not least the ;; documentation for `ibuffer-formats'. @@ -364,173 +364,170 @@ directory, like `default-directory'." (regexp :tag "From") (regexp :tag "To")))) -(defvar ibuffer--filter-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "RET") 'ibuffer-filter-by-mode) - (define-key map (kbd "SPC") 'ibuffer-filter-chosen-by-completion) - (define-key map (kbd "m") 'ibuffer-filter-by-used-mode) - (define-key map (kbd "M") 'ibuffer-filter-by-derived-mode) - (define-key map (kbd "n") 'ibuffer-filter-by-name) - (define-key map (kbd "E") 'ibuffer-filter-by-process) - (define-key map (kbd "*") 'ibuffer-filter-by-starred-name) - (define-key map (kbd "f") 'ibuffer-filter-by-filename) - (define-key map (kbd "F") 'ibuffer-filter-by-directory) - (define-key map (kbd "b") 'ibuffer-filter-by-basename) - (define-key map (kbd ".") 'ibuffer-filter-by-file-extension) - (define-key map (kbd "<") 'ibuffer-filter-by-size-lt) - (define-key map (kbd ">") 'ibuffer-filter-by-size-gt) - (define-key map (kbd "i") 'ibuffer-filter-by-modified) - (define-key map (kbd "v") 'ibuffer-filter-by-visiting-file) - (define-key map (kbd "c") 'ibuffer-filter-by-content) - (define-key map (kbd "e") 'ibuffer-filter-by-predicate) - - (define-key map (kbd "r") 'ibuffer-switch-to-saved-filters) - (define-key map (kbd "a") 'ibuffer-add-saved-filters) - (define-key map (kbd "x") 'ibuffer-delete-saved-filters) - (define-key map (kbd "d") 'ibuffer-decompose-filter) - (define-key map (kbd "s") 'ibuffer-save-filters) - (define-key map (kbd "p") 'ibuffer-pop-filter) - (define-key map (kbd "") 'ibuffer-pop-filter) - (define-key map (kbd "!") 'ibuffer-negate-filter) - (define-key map (kbd "t") 'ibuffer-exchange-filters) - (define-key map (kbd "TAB") 'ibuffer-exchange-filters) - (define-key map (kbd "o") 'ibuffer-or-filter) - (define-key map (kbd "|") 'ibuffer-or-filter) - (define-key map (kbd "&") 'ibuffer-and-filter) - (define-key map (kbd "g") 'ibuffer-filters-to-filter-group) - (define-key map (kbd "P") 'ibuffer-pop-filter-group) - (define-key map (kbd "S-") 'ibuffer-pop-filter-group) - (define-key map (kbd "D") 'ibuffer-decompose-filter-group) - (define-key map (kbd "/") 'ibuffer-filter-disable) - - (define-key map (kbd "S") 'ibuffer-save-filter-groups) - (define-key map (kbd "R") 'ibuffer-switch-to-saved-filter-groups) - (define-key map (kbd "X") 'ibuffer-delete-saved-filter-groups) - (define-key map (kbd "\\") 'ibuffer-clear-filter-groups) - map)) - -(defvar ibuffer-mode-map - (let ((map (make-keymap))) - (define-key map (kbd "0") 'digit-argument) - (define-key map (kbd "1") 'digit-argument) - (define-key map (kbd "2") 'digit-argument) - (define-key map (kbd "3") 'digit-argument) - (define-key map (kbd "4") 'digit-argument) - (define-key map (kbd "5") 'digit-argument) - (define-key map (kbd "6") 'digit-argument) - (define-key map (kbd "7") 'digit-argument) - (define-key map (kbd "8") 'digit-argument) - (define-key map (kbd "9") 'digit-argument) - - (define-key map (kbd "m") 'ibuffer-mark-forward) - (define-key map (kbd "t") 'ibuffer-toggle-marks) - (define-key map (kbd "u") 'ibuffer-unmark-forward) - (define-key map (kbd "=") 'ibuffer-diff-with-file) - (define-key map (kbd "j") 'ibuffer-jump-to-buffer) - (define-key map (kbd "M-g") 'ibuffer-jump-to-buffer) - (define-key map (kbd "M-s a C-s") 'ibuffer-do-isearch) - (define-key map (kbd "M-s a M-C-s") 'ibuffer-do-isearch-regexp) - (define-key map (kbd "M-s a C-o") 'ibuffer-do-occur) - (define-key map (kbd "DEL") 'ibuffer-unmark-backward) - (define-key map (kbd "M-DEL") 'ibuffer-unmark-all) - (define-key map (kbd "* *") 'ibuffer-unmark-all) - (define-key map (kbd "* c") 'ibuffer-change-marks) - (define-key map (kbd "U") 'ibuffer-unmark-all-marks) - (define-key map (kbd "* M") 'ibuffer-mark-by-mode) - (define-key map (kbd "* m") 'ibuffer-mark-modified-buffers) - (define-key map (kbd "* u") 'ibuffer-mark-unsaved-buffers) - (define-key map (kbd "* s") 'ibuffer-mark-special-buffers) - (define-key map (kbd "* r") 'ibuffer-mark-read-only-buffers) - (define-key map (kbd "* /") 'ibuffer-mark-dired-buffers) - (define-key map (kbd "* e") 'ibuffer-mark-dissociated-buffers) - (define-key map (kbd "* h") 'ibuffer-mark-help-buffers) - (define-key map (kbd "* z") 'ibuffer-mark-compressed-file-buffers) - (define-key map (kbd ".") 'ibuffer-mark-old-buffers) - - (define-key map (kbd "d") 'ibuffer-mark-for-delete) - (define-key map (kbd "C-d") 'ibuffer-mark-for-delete-backwards) - (define-key map (kbd "k") 'ibuffer-mark-for-delete) - (define-key map (kbd "x") 'ibuffer-do-kill-on-deletion-marks) - - ;; immediate operations - (define-key map (kbd "n") 'ibuffer-forward-line) - (define-key map (kbd "SPC") 'forward-line) - (define-key map (kbd "p") 'ibuffer-backward-line) - (define-key map (kbd "M-}") 'ibuffer-forward-next-marked) - (define-key map (kbd "M-{") 'ibuffer-backwards-next-marked) - (define-key map (kbd "l") 'ibuffer-redisplay) - (define-key map (kbd "g") 'ibuffer-update) - (define-key map "`" 'ibuffer-switch-format) - (define-key map "-" 'ibuffer-add-to-tmp-hide) - (define-key map "+" 'ibuffer-add-to-tmp-show) - (define-key map "b" 'ibuffer-bury-buffer) - (define-key map (kbd ",") 'ibuffer-toggle-sorting-mode) - (define-key map (kbd "s i") 'ibuffer-invert-sorting) - (define-key map (kbd "s a") 'ibuffer-do-sort-by-alphabetic) - (define-key map (kbd "s v") 'ibuffer-do-sort-by-recency) - (define-key map (kbd "s s") 'ibuffer-do-sort-by-size) - (define-key map (kbd "s f") 'ibuffer-do-sort-by-filename/process) - (define-key map (kbd "s m") 'ibuffer-do-sort-by-major-mode) - - (define-key map (kbd "M-n") 'ibuffer-forward-filter-group) - (define-key map "\t" 'ibuffer-forward-filter-group) - (define-key map (kbd "M-p") 'ibuffer-backward-filter-group) - (define-key map [backtab] 'ibuffer-backward-filter-group) - (define-key map (kbd "M-j") 'ibuffer-jump-to-filter-group) - (define-key map (kbd "C-k") 'ibuffer-kill-line) - (define-key map (kbd "C-y") 'ibuffer-yank) - - (define-key map (kbd "% n") 'ibuffer-mark-by-name-regexp) - (define-key map (kbd "% m") 'ibuffer-mark-by-mode-regexp) - (define-key map (kbd "% f") 'ibuffer-mark-by-file-name-regexp) - (define-key map (kbd "% g") 'ibuffer-mark-by-content-regexp) - (define-key map (kbd "% L") 'ibuffer-mark-by-locked) - - (define-key map (kbd "C-t") 'ibuffer-visit-tags-table) - - (define-key map (kbd "|") 'ibuffer-do-shell-command-pipe) - (define-key map (kbd "!") 'ibuffer-do-shell-command-file) - (define-key map (kbd "~") 'ibuffer-do-toggle-modified) - ;; marked operations - (define-key map (kbd "A") 'ibuffer-do-view) - (define-key map (kbd "D") 'ibuffer-do-delete) - (define-key map (kbd "E") 'ibuffer-do-eval) - (define-key map (kbd "F") 'ibuffer-do-shell-command-file) - (define-key map (kbd "I") 'ibuffer-do-query-replace-regexp) - (define-key map (kbd "H") 'ibuffer-do-view-other-frame) - (define-key map (kbd "N") 'ibuffer-do-shell-command-pipe-replace) - (define-key map (kbd "M") 'ibuffer-do-toggle-modified) - (define-key map (kbd "O") 'ibuffer-do-occur) - (define-key map (kbd "P") 'ibuffer-do-print) - (define-key map (kbd "Q") 'ibuffer-do-query-replace) - (define-key map (kbd "R") 'ibuffer-do-rename-uniquely) - (define-key map (kbd "S") 'ibuffer-do-save) - (define-key map (kbd "T") 'ibuffer-do-toggle-read-only) - (define-key map (kbd "L") 'ibuffer-do-toggle-lock) - (define-key map (kbd "r") 'ibuffer-do-replace-regexp) - (define-key map (kbd "V") 'ibuffer-do-revert) - (define-key map (kbd "W") 'ibuffer-do-view-and-eval) - (define-key map (kbd "X") 'ibuffer-do-shell-command-pipe) - - (define-key map (kbd "k") 'ibuffer-do-kill-lines) - (define-key map (kbd "w") 'ibuffer-copy-filename-as-kill) - (define-key map (kbd "B") 'ibuffer-copy-buffername-as-kill) - - (define-key map (kbd "RET") 'ibuffer-visit-buffer) - (define-key map (kbd "e") 'ibuffer-visit-buffer) - (define-key map (kbd "f") 'ibuffer-visit-buffer) - (define-key map (kbd "C-x C-f") 'ibuffer-find-file) - (define-key map (kbd "o") 'ibuffer-visit-buffer-other-window) - (define-key map (kbd "C-o") 'ibuffer-visit-buffer-other-window-noselect) - (define-key map (kbd "M-o") 'ibuffer-visit-buffer-1-window) - (define-key map (kbd "v") 'ibuffer-do-view) - (define-key map (kbd "C-x v") 'ibuffer-do-view-horizontally) - (define-key map (kbd "C-c C-a") 'ibuffer-auto-mode) - (define-key map (kbd "C-x 4 RET") 'ibuffer-visit-buffer-other-window) - (define-key map (kbd "C-x 5 RET") 'ibuffer-visit-buffer-other-frame) - - (define-key map (kbd "/") ibuffer--filter-map) - map)) +(defvar-keymap ibuffer--filter-map + "RET" #'ibuffer-filter-by-mode + "SPC" #'ibuffer-filter-chosen-by-completion + "m" #'ibuffer-filter-by-used-mode + "M" #'ibuffer-filter-by-derived-mode + "n" #'ibuffer-filter-by-name + "E" #'ibuffer-filter-by-process + "*" #'ibuffer-filter-by-starred-name + "f" #'ibuffer-filter-by-filename + "F" #'ibuffer-filter-by-directory + "b" #'ibuffer-filter-by-basename + "." #'ibuffer-filter-by-file-extension + "<" #'ibuffer-filter-by-size-lt + ">" #'ibuffer-filter-by-size-gt + "i" #'ibuffer-filter-by-modified + "v" #'ibuffer-filter-by-visiting-file + "c" #'ibuffer-filter-by-content + "e" #'ibuffer-filter-by-predicate + + "r" #'ibuffer-switch-to-saved-filters + "a" #'ibuffer-add-saved-filters + "x" #'ibuffer-delete-saved-filters + "d" #'ibuffer-decompose-filter + "s" #'ibuffer-save-filters + "p" #'ibuffer-pop-filter + "" #'ibuffer-pop-filter + "!" #'ibuffer-negate-filter + "t" #'ibuffer-exchange-filters + "TAB" #'ibuffer-exchange-filters + "o" #'ibuffer-or-filter + "|" #'ibuffer-or-filter + "&" #'ibuffer-and-filter + "g" #'ibuffer-filters-to-filter-group + "P" #'ibuffer-pop-filter-group + "S-" #'ibuffer-pop-filter-group + "D" #'ibuffer-decompose-filter-group + "/" #'ibuffer-filter-disable + + "S" #'ibuffer-save-filter-groups + "R" #'ibuffer-switch-to-saved-filter-groups + "X" #'ibuffer-delete-saved-filter-groups + "\\" #'ibuffer-clear-filter-groups) + +(defvar-keymap ibuffer-mode-map + :full t + "0" #'digit-argument + "1" #'digit-argument + "2" #'digit-argument + "3" #'digit-argument + "4" #'digit-argument + "5" #'digit-argument + "6" #'digit-argument + "7" #'digit-argument + "8" #'digit-argument + "9" #'digit-argument + + "m" #'ibuffer-mark-forward + "t" #'ibuffer-toggle-marks + "u" #'ibuffer-unmark-forward + "=" #'ibuffer-diff-with-file + "j" #'ibuffer-jump-to-buffer + "M-g" #'ibuffer-jump-to-buffer + "M-s a C-s" #'ibuffer-do-isearch + "M-s a C-M-s" #'ibuffer-do-isearch-regexp + "M-s a C-o" #'ibuffer-do-occur + "DEL" #'ibuffer-unmark-backward + "M-DEL" #'ibuffer-unmark-all + "* *" #'ibuffer-unmark-all + "* c" #'ibuffer-change-marks + "U" #'ibuffer-unmark-all-marks + "* M" #'ibuffer-mark-by-mode + "* m" #'ibuffer-mark-modified-buffers + "* u" #'ibuffer-mark-unsaved-buffers + "* s" #'ibuffer-mark-special-buffers + "* r" #'ibuffer-mark-read-only-buffers + "* /" #'ibuffer-mark-dired-buffers + "* e" #'ibuffer-mark-dissociated-buffers + "* h" #'ibuffer-mark-help-buffers + "* z" #'ibuffer-mark-compressed-file-buffers + "." #'ibuffer-mark-old-buffers + + "d" #'ibuffer-mark-for-delete + "C-d" #'ibuffer-mark-for-delete-backwards + "k" #'ibuffer-mark-for-delete + "x" #'ibuffer-do-kill-on-deletion-marks + + ;; immediate operations + "n" #'ibuffer-forward-line + "SPC" #'forward-line + "p" #'ibuffer-backward-line + "M-}" #'ibuffer-forward-next-marked + "M-{" #'ibuffer-backwards-next-marked + "l" #'ibuffer-redisplay + "g" #'ibuffer-update + "`" #'ibuffer-switch-format + "-" #'ibuffer-add-to-tmp-hide + "+" #'ibuffer-add-to-tmp-show + "b" #'ibuffer-bury-buffer + "," #'ibuffer-toggle-sorting-mode + "s i" #'ibuffer-invert-sorting + "s a" #'ibuffer-do-sort-by-alphabetic + "s v" #'ibuffer-do-sort-by-recency + "s s" #'ibuffer-do-sort-by-size + "s f" #'ibuffer-do-sort-by-filename/process + "s m" #'ibuffer-do-sort-by-major-mode + + "M-n" #'ibuffer-forward-filter-group + "TAB" #'ibuffer-forward-filter-group + "M-p" #'ibuffer-backward-filter-group + "" #'ibuffer-backward-filter-group + "M-j" #'ibuffer-jump-to-filter-group + "C-k" #'ibuffer-kill-line + "C-y" #'ibuffer-yank + + "% n" #'ibuffer-mark-by-name-regexp + "% m" #'ibuffer-mark-by-mode-regexp + "% f" #'ibuffer-mark-by-file-name-regexp + "% g" #'ibuffer-mark-by-content-regexp + "% L" #'ibuffer-mark-by-locked + + "C-t" #'ibuffer-visit-tags-table + + "|" #'ibuffer-do-shell-command-pipe + "!" #'ibuffer-do-shell-command-file + "~" #'ibuffer-do-toggle-modified + ;; marked operations + "A" #'ibuffer-do-view + "D" #'ibuffer-do-delete + "E" #'ibuffer-do-eval + "F" #'ibuffer-do-shell-command-file + "I" #'ibuffer-do-query-replace-regexp + "H" #'ibuffer-do-view-other-frame + "N" #'ibuffer-do-shell-command-pipe-replace + "M" #'ibuffer-do-toggle-modified + "O" #'ibuffer-do-occur + "P" #'ibuffer-do-print + "Q" #'ibuffer-do-query-replace + "R" #'ibuffer-do-rename-uniquely + "S" #'ibuffer-do-save + "T" #'ibuffer-do-toggle-read-only + "L" #'ibuffer-do-toggle-lock + "r" #'ibuffer-do-replace-regexp + "V" #'ibuffer-do-revert + "W" #'ibuffer-do-view-and-eval + "X" #'ibuffer-do-shell-command-pipe + + "k" #'ibuffer-do-kill-lines + "w" #'ibuffer-copy-filename-as-kill + "B" #'ibuffer-copy-buffername-as-kill + + "RET" #'ibuffer-visit-buffer + "e" #'ibuffer-visit-buffer + "f" #'ibuffer-visit-buffer + "C-x C-f" #'ibuffer-find-file + "o" #'ibuffer-visit-buffer-other-window + "C-o" #'ibuffer-visit-buffer-other-window-noselect + "M-o" #'ibuffer-visit-buffer-1-window + "v" #'ibuffer-do-view + "C-x v" #'ibuffer-do-view-horizontally + "C-c C-a" #'ibuffer-auto-mode + "C-x 4 RET" #'ibuffer-visit-buffer-other-window + "C-x 5 RET" #'ibuffer-visit-buffer-other-frame + + "/" ibuffer--filter-map) (defun ibuffer-mode--groups-menu-definition (&optional is-popup) "Build the `ibuffer' \"Filter\" menu. Internal." @@ -758,46 +755,32 @@ directory, like `default-directory'." ["Diff with file" ibuffer-diff-with-file :help "View the differences between this buffer and its file"])) -(defvar ibuffer-name-map - (let ((map (make-sparse-keymap))) - (define-key map [(mouse-1)] 'ibuffer-mouse-toggle-mark) - (define-key map [(mouse-2)] 'ibuffer-mouse-visit-buffer) - (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu) - map)) - -(defvar ibuffer-filename/process-header-map - (let ((map (make-sparse-keymap))) - (define-key map [(mouse-1)] 'ibuffer-do-sort-by-filename/process) - map)) - -(defvar ibuffer-mode-name-map - (let ((map (make-sparse-keymap))) - (define-key map [(mouse-2)] 'ibuffer-mouse-filter-by-mode) - (define-key map (kbd "RET") 'ibuffer-interactive-filter-by-mode) - map)) - -(defvar ibuffer-name-header-map - (let ((map (make-sparse-keymap))) - (define-key map [(mouse-1)] 'ibuffer-do-sort-by-alphabetic) - map)) - -(defvar ibuffer-size-header-map - (let ((map (make-sparse-keymap))) - (define-key map [(mouse-1)] 'ibuffer-do-sort-by-size) - map)) - -(defvar ibuffer-mode-header-map - (let ((map (make-sparse-keymap))) - (define-key map [(mouse-1)] 'ibuffer-do-sort-by-major-mode) - map)) - -(defvar ibuffer-mode-filter-group-map - (let ((map (make-sparse-keymap))) - (define-key map [(mouse-1)] 'ibuffer-mouse-toggle-mark) - (define-key map [(mouse-2)] 'ibuffer-mouse-toggle-filter-group) - (define-key map (kbd "RET") 'ibuffer-toggle-filter-group) - (define-key map [down-mouse-3] 'ibuffer-mouse-popup-menu) - map)) +(defvar-keymap ibuffer-name-map + "" #'ibuffer-mouse-toggle-mark + "" #'ibuffer-mouse-visit-buffer + "" #'ibuffer-mouse-popup-menu) + +(defvar-keymap ibuffer-filename/process-header-map + "" #'ibuffer-do-sort-by-filename/process) + +(defvar-keymap ibuffer-mode-name-map + "" #'ibuffer-mouse-filter-by-mode + "RET" #'ibuffer-interactive-filter-by-mode) + +(defvar-keymap ibuffer-name-header-map + "" #'ibuffer-do-sort-by-alphabetic) + +(defvar-keymap ibuffer-size-header-map + "" #'ibuffer-do-sort-by-size) + +(defvar-keymap ibuffer-mode-header-map + "" #'ibuffer-do-sort-by-major-mode) + +(defvar-keymap ibuffer-mode-filter-group-map + "" #'ibuffer-mouse-toggle-mark + "" #'ibuffer-mouse-toggle-filter-group + "RET" #'ibuffer-toggle-filter-group + "" #'ibuffer-mouse-popup-menu) (defvar ibuffer-did-modification nil) commit 4d7a936ac2a682087d0b4e91c12b2ad87363631f Author: Robert Pluim Date: Wed Jun 15 15:16:47 2022 +0200 ; * src/fileio.c (Fset_file_modes): Improve previous change diff --git a/src/fileio.c b/src/fileio.c index a240216dea..481001b423 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -3510,7 +3510,7 @@ DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 3, Only the 12 low bits of MODE are used. If optional FLAG is `nofollow', do not follow FILENAME if it is a symbolic link. -Interactively, prompts for FILENAME, and reads MODE with +Interactively, prompt for FILENAME, and read MODE with `read-file-modes', which accepts symbolic notation, like the `chmod' command from GNU Coreutils. */) (Lisp_Object filename, Lisp_Object mode, Lisp_Object flag) commit 9b053968effd7c9066f194b6f4c786652f545041 Author: Po Lu Date: Wed Jun 15 21:00:55 2022 +0800 Implement using the OffiX protocol for dropping * lisp/x-dnd.el (x-dnd-use-offix-drop): New user option. (x-dnd-handle-unsupported-drop): Return t if the OffiX protocol was used. (x-treat-local-requests-remotely): New defvar. (x-dnd-convert-to-offix, x-dnd-do-offix-drop): New functions. * src/xterm.c: Update commentary. (x_term_init): Extend number of DND atoms allocated by default. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 7022b71c55..684f8f8155 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -102,6 +102,16 @@ The types are chosen in the order they appear in the list." :type '(repeat string) :group 'x) +(defcustom x-dnd-use-offix-drop nil + "If non-nil, use the OffiX protocol to drop files and text. +This allows dropping (via `dired-mouse-drag-files' or +`mouse-drag-and-drop-region-cross-program') on some old Java +applets and old KDE programs. Turning this off allows dropping +only text on some other programs such as xterm and urxvt." + :version "29.1" + :type 'boolean + :group 'x) + ;; Internal variables (defvar x-dnd-current-state nil @@ -938,14 +948,82 @@ Return a vector of atoms containing the selection targets." ;;; Handling drops. -(defun x-dnd-handle-unsupported-drop (targets _x _y action _window-id _frame _time) - "Return non-nil if the drop described by TARGETS and ACTION should not proceed." +(defvar x-treat-local-requests-remotely) + +(defun x-dnd-convert-to-offix (targets) + "Convert the contents of `XdndSelection' to OffiX data. +TARGETS should be the list of targets currently available in +`XdndSelection'. Return a list of an OffiX type, and data +suitable for passing to `x-change-window-property', or nil if the +data could not be converted." + (let ((x-treat-local-requests-remotely t) + file-name-data string-data) + (cond + ((and (member "FILE_NAME" targets) + (setq file-name-data + (gui-get-selection 'XdndSelection 'FILE_NAME))) + (if (string-match-p "\0" file-name-data) + ;; This means there are multiple file names in + ;; XdndSelection. Convert the file name data to a format + ;; that OffiX understands. + (cons 'DndTypeFiles (concat file-name-data "\0")) + (cons 'DndTypeFile (concat file-name-data "\0")))) + ((and (member "STRING" targets) + (setq string-data + (gui-get-selection 'XdndSelection 'STRING))) + (cons 'DndTypeText (encode-coding-string string-data + 'latin-1)))))) + +(defun x-dnd-do-offix-drop (targets x y frame window-id) + "Perform an OffiX drop on WINDOW-ID with the contents of `XdndSelection'. +Return non-nil if the drop succeeded, or nil if it did not +happen, which can happen if TARGETS didn't contain anything that +the OffiX protocol can represent. + +X and Y are the root window coordinates of the drop. TARGETS is +the list of targets `XdndSelection' can be converted to." + (if-let* ((data (x-dnd-convert-to-offix targets)) + (type-id (car (rassq (car data) + x-dnd-offix-id-to-name))) + (source-id (string-to-number + (frame-parameter frame 'window-id))) + (message-data (list type-id ; l[0] = DataType + 0 ; l[1] = event->xbutton.state + source-id ; l[2] = window + (+ x (* 65536 y)) ; l[3] = drop_x + 65536 * drop_y + 1))) ; l[4] = protocol version + (prog1 t + ;; Send a legacy (old KDE) message first. Newer clients will + ;; ignore it, since the protocol version is 1. + (x-change-window-property "DndSelection" + (cdr data) frame + "STRING" 8 nil 0) + (x-send-client-message frame window-id + frame "DndProtocol" + 32 message-data) + ;; Now send a modern _DND_PROTOCOL message. + (x-change-window-property "_DND_SELECTION" + (cdr data) frame + "STRING" 8 nil 0) + (x-send-client-message frame window-id + frame "_DND_PROTOCOL" + 32 message-data)))) + +(defun x-dnd-handle-unsupported-drop (targets x y action window-id frame _time) + "Return non-nil if the drop described by TARGETS and ACTION should not proceed. +X and Y are the root window coordinates of the drop. +FRAME is the frame the drop originated on. +WINDOW-ID is the X window the drop should happen to." (not (and (or (eq action 'XdndActionCopy) (eq action 'XdndActionMove)) - (or (member "STRING" targets) - (member "UTF8_STRING" targets) - (member "COMPOUND_TEXT" targets) - (member "TEXT" targets))))) + (not (and x-dnd-use-offix-drop + (x-dnd-do-offix-drop targets x + y frame window-id))) + (or + (member "STRING" targets) + (member "UTF8_STRING" targets) + (member "COMPOUND_TEXT" targets) + (member "TEXT" targets))))) (defvar x-dnd-targets-list) (defvar x-dnd-native-test-function) diff --git a/src/xterm.c b/src/xterm.c index b1e7ee578a..f2f80b42be 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -520,9 +520,9 @@ along with GNU Emacs. If not, see . */ replying to the initiating client) is performed from Lisp inside `x-dnd.el'. - However, dragging contents from Emacs is implemented entirely in C. - X Windows has several competing drag-and-drop protocols, of which - Emacs supports two: the XDND protocol (see + However, dragging contents from Emacs is implemented almost entirely + in C. X Windows has several competing drag-and-drop protocols, of + which Emacs supports two on the C level: the XDND protocol (see https://freedesktop.org/wiki/Specifications/XDND) and the Motif drag and drop protocols. These protocols are based on the initiator owning a special selection, specifying an action the recipient @@ -545,7 +545,16 @@ along with GNU Emacs. If not, see . */ released over the recipient window, Emacs sends a "drop" message to the target window, waits for a reply, and returns the action selected by the recipient to the Lisp code that initiated the - drag-and-drop operation. */ + drag-and-drop operation. + + When a drop happens on a window not supporting any protocol + implemented on the C level, the function inside + `x-dnd-unsupported-drop-function' is called with some parameters of + the drop. If it returns non-nil, then Emacs tries to simulate a + drop happening with the primary selection and synthetic button + events (see `x_dnd_do_unsupported_drop'). That function implements + the OffiX drag-and-drop protocol by default. See + `x-dnd-handle-unsupported-drop' in `x-dnd.el' for more details. */ #include #include @@ -26571,7 +26580,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) x_find_modifier_meanings (dpyinfo); #endif - dpyinfo->x_dnd_atoms_size = 8; + dpyinfo->x_dnd_atoms_size = 16; dpyinfo->x_dnd_atoms = xmalloc (sizeof *dpyinfo->x_dnd_atoms * dpyinfo->x_dnd_atoms_size); dpyinfo->gray commit 32cff740e2a618583094a408890f3dcdf0aa01a1 Author: Robert Pluim Date: Wed Jun 15 14:25:17 2022 +0200 Describe 'set-file-modes' argument prompting * src/fileio.c (Fset_file_modes): Document that FILENAME is prompted for. (Bug#55984) diff --git a/src/fileio.c b/src/fileio.c index 7d392e0de7..a240216dea 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -3510,8 +3510,9 @@ DEFUN ("set-file-modes", Fset_file_modes, Sset_file_modes, 2, 3, Only the 12 low bits of MODE are used. If optional FLAG is `nofollow', do not follow FILENAME if it is a symbolic link. -Interactively, mode bits are read by `read-file-modes', which accepts -symbolic notation, like the `chmod' command from GNU Coreutils. */) +Interactively, prompts for FILENAME, and reads MODE with +`read-file-modes', which accepts symbolic notation, like the `chmod' +command from GNU Coreutils. */) (Lisp_Object filename, Lisp_Object mode, Lisp_Object flag) { CHECK_FIXNUM (mode); commit 8ee9e20f8cf1f1f880792dcc1048293ea0342ba4 Author: Miha Rihtaršič Date: Wed Jun 15 14:24:24 2022 +0200 whitespace.el: New whitespace style `lines-char' * lisp/whitespace.el (whitespace-style): (whitespace-style-value-list): (whitespace-toggle-option-alist): (global-whitespace-toggle-options): (whitespace-help-text): (whitespace-interactive-char): (whitespace-style-face-p): (whitespace-color-on): (whitespace-lines-regexp): New whitespace style `lines-char', which highlights only the first character over the whitespace-line-column limit (bug#55980). diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 610d670ac9..7ee8a46cec 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -295,8 +295,8 @@ It's a list containing some or all of the following values: `whitespace-line-column' are highlighted via faces. Whole line is highlighted. - It has precedence over `lines-tail' (see - below). + It has precedence over `lines-tail' and + `lines-char' (see below). It has effect only if `face' (see above) is present in `whitespace-style'. @@ -310,6 +310,15 @@ It's a list containing some or all of the following values: and if `face' (see above) is present in `whitespace-style'. + lines-char lines which have columns beyond + `whitespace-line-column' are highlighted via + putting a face on the first character that goes + beyond the `whitespace-line-column' column. + It has effect only if `lines' or + `lines-tail' (see above) is not present + in `whitespace-style' and if `face' (see + above) is present in `whitespace-style'. + newline NEWLINEs are visualized via faces. It has effect only if `face' (see above) is present in `whitespace-style'. @@ -431,6 +440,7 @@ See also `whitespace-display-mappings' for documentation." (const :tag "(Face) SPACEs and HARD SPACEs" spaces) (const :tag "(Face) Lines" lines) (const :tag "(Face) Lines, only overlong part" lines-tail) + (const :tag "(Face) Lines, only first character" lines-char) (const :tag "(Face) NEWLINEs" newline) (const :tag "(Face) Missing newlines at EOB" missing-newline-at-eof) @@ -772,7 +782,8 @@ Used when `whitespace-style' includes `big-indent'." It must be an integer or nil. If nil, the `fill-column' variable value is used. -Used when `whitespace-style' includes `lines' or `lines-tail'." +Used when `whitespace-style' includes `lines', `lines-tail' or +`lines-char'." :type '(choice :tag "Line Length Limit" (integer :tag "Line Length") (const :tag "Use fill-column" nil)) @@ -1058,6 +1069,7 @@ See also `whitespace-newline' and `whitespace-display-mappings'." trailing lines lines-tail + lines-char newline empty indentation @@ -1085,6 +1097,7 @@ See also `whitespace-newline' and `whitespace-display-mappings'." (?r . trailing) (?l . lines) (?L . lines-tail) + (?\C-l . lines-char) (?n . newline) (?e . empty) (?\C-i . indentation) @@ -1244,6 +1257,7 @@ Interactively, it accepts one of the following chars: r toggle trailing blanks visualization l toggle \"long lines\" visualization L toggle \"long lines\" tail visualization + C-l toggle \"long lines\" one character visualization n toggle NEWLINE visualization e toggle empty line at bob and/or eob visualization C-i toggle indentation SPACEs visualization (via `indent-tabs-mode') @@ -1274,6 +1288,7 @@ The valid symbols are: trailing toggle trailing blanks visualization lines toggle \"long lines\" visualization lines-tail toggle \"long lines\" tail visualization + lines-char toggle \"long lines\" one character visualization newline toggle NEWLINE visualization empty toggle empty line at bob and/or eob visualization indentation toggle indentation SPACEs visualization @@ -1770,6 +1785,7 @@ cleaning up these problems." [] r - toggle trailing blanks visualization [] l - toggle \"long lines\" visualization [] L - toggle \"long lines\" tail visualization + [] C-l - toggle \"long lines\" one character visualization [] n - toggle NEWLINE visualization [] e - toggle empty line at bob and/or eob visualization [] C-i - toggle indentation SPACEs visualization (via `indent-tabs-mode') @@ -1892,6 +1908,7 @@ It accepts one of the following chars: r toggle trailing blanks visualization l toggle \"long lines\" visualization L toggle \"long lines\" tail visualization + C-l toggle \"long lines\" one character visualization n toggle NEWLINE visualization e toggle empty line at bob and/or eob visualization C-i toggle indentation SPACEs visualization (via `indent-tabs-mode') @@ -2020,6 +2037,7 @@ resultant list will be returned." (memq 'trailing whitespace-active-style) (memq 'lines whitespace-active-style) (memq 'lines-tail whitespace-active-style) + (memq 'lines-char whitespace-active-style) (memq 'newline whitespace-active-style) (memq 'empty whitespace-active-style) (memq 'indentation whitespace-active-style) @@ -2066,12 +2084,17 @@ resultant list will be returned." ;; Show trailing blanks. `((,#'whitespace-trailing-regexp 1 whitespace-trailing t))) ,@(when (or (memq 'lines whitespace-active-style) - (memq 'lines-tail whitespace-active-style)) + (memq 'lines-tail whitespace-active-style) + (memq 'lines-char whitespace-active-style)) ;; Show "long" lines. `((,#'whitespace-lines-regexp - ,(if (memq 'lines whitespace-active-style) - 0 ; whole line - 2) ; line tail + ,(cond + ;; whole line + ((memq 'lines whitespace-active-style) 0) + ;; line tail + ((memq 'lines-tail whitespace-active-style) 2) + ;; first overflowing character + ((memq 'lines-char whitespace-active-style) 3)) whitespace-line prepend))) ,@(when (or (memq 'space-before-tab whitespace-active-style) (memq 'space-before-tab::tab whitespace-active-style) @@ -2182,7 +2205,7 @@ resultant list will be returned." (re-search-forward (let ((line-column (or whitespace-line-column fill-column))) (format - "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(.+\\)$" + "^\\([^\t\n]\\{%s\\}\\|[^\t\n]\\{0,%s\\}\t\\)\\{%d\\}%s\\(?2:\\(?3:.\\).*\\)$" tab-width (1- tab-width) (/ line-column tab-width) commit 12d6aad132bef7b4bf89ed0196332d85e25427de Author: Po Lu Date: Wed Jun 15 20:08:51 2022 +0800 Handle receiving new OffiX protocol during drag-and-drop * lisp/x-dnd.el (x-dnd-types-alist, x-dnd-known-types): Add DndTypeFile and DndTypeText. (x-dnd-init-frame): Add _DND_PROTOCOL. (x-dnd-handle-drag-n-drop-event): Handle _DND_PROTOCOL events. (x-dnd-handle-old-kde): Drop event if proto is too new. (x-dnd-offix-id-to-name): New list. (x-dnd-handle-offix-file, x-dnd-handle-offix): New functions. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index bcf74762cc..7022b71c55 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -65,7 +65,9 @@ The default value for this variable is `x-dnd-default-test-function'." (,(purecopy "text/plain") . dnd-insert-text) (,(purecopy "COMPOUND_TEXT") . x-dnd-insert-ctext) (,(purecopy "STRING") . dnd-insert-text) - (,(purecopy "TEXT") . dnd-insert-text)) + (,(purecopy "TEXT") . dnd-insert-text) + (,(purecopy "DndTypeFile") . x-dnd-handle-offix-file) + (,(purecopy "DndTypeText") . dnd-insert-text)) "Which function to call to handle a drop of that type. If the type for the drop is not present, or the function is nil, the drop is rejected. The function takes three arguments, WINDOW, ACTION @@ -91,7 +93,9 @@ if drop is successful, nil if not." "text/plain" "COMPOUND_TEXT" "STRING" - "TEXT")) + "TEXT" + "DndTypeFile" + "DndTypeText")) "The types accepted by default for dropped data. The types are chosen in the order they appear in the list." :version "22.1" @@ -137,6 +141,7 @@ any protocol specific data.") (x-register-dnd-atom "XdndPosition" frame) (x-register-dnd-atom "XdndLeave" frame) (x-register-dnd-atom "XdndDrop" frame) + (x-register-dnd-atom "_DND_PROTOCOL" frame) (x-dnd-init-xdnd-for-frame frame) (x-dnd-init-motif-for-frame frame))) @@ -375,7 +380,8 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." (data (aref client-message 3))) (cond ((equal "DndProtocol" message-atom) ; Old KDE 1.x. (x-dnd-handle-old-kde event frame window message-atom format data)) - + ((equal "_DND_PROTOCOL" message-atom) ; OffiX protocol. + (x-dnd-handle-offix event frame window message-atom format data)) ((equal "_MOTIF_DRAG_AND_DROP_MESSAGE" message-atom) ; Motif (x-dnd-handle-motif event frame window message-atom format data)) @@ -390,14 +396,59 @@ Currently XDND, Motif and old KDE 1.x protocols are recognized." (declare-function x-window-property "xfns.c" (prop &optional frame type source delete-p vector-ret-p)) -(defun x-dnd-handle-old-kde (_event frame window _message _format _data) +(defun x-dnd-handle-old-kde (_event frame window _message _format data) "Open the files in a KDE 1.x drop." - (let ((values (x-window-property "DndSelection" frame nil 0 t))) - (x-dnd-handle-uri-list window 'private - (replace-regexp-in-string "\0$" "" values)))) + (let ((proto (aref data 4))) + ;; If PROTO > 0, this is an old KDE drop emulated by a program + ;; supporting a newer version of the OffiX protocol, so we should + ;; wait for the corresponding modern event instead. + (when (zerop proto) + (let ((values (x-window-property "DndSelection" frame nil 0 t))) + (x-dnd-handle-uri-list window 'private + (replace-regexp-in-string "\0$" "" values)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - - +;;; New OffiX protocol. + +(defvar x-dnd-offix-id-to-name '((-1 . DndTypeInvalid) + (0 . DndTypeUnknown) + (1 . DndTypeRawData) + (2 . DndTypeFile) + (3 . DndTypeFiles) + (4 . DndTypeText) + (5 . DndTypeDir) + (6 . DndTypeLInk) + (7 . DndTypeExe) + (8 . DndTypeUrl) + (9 . DndTypeMime) + (10 . DndTypePixmap)) + "Alist of OffiX protocol types to their names.") + +(defun x-dnd-handle-offix-file (window action string) + "Convert OffiX file name to a regular file name. +Then, call `x-dnd-handle-file-name'. + +WINDOW and ACTION mean the same as in `x-dnd-handle-file-name'. +STRING is the raw offiX file name data." + (x-dnd-handle-file-name window action + (replace-regexp-in-string "\0$" "" string))) + +(defun x-dnd-handle-offix (event frame window _message-atom _format data) + "Handle OffiX drop event EVENT. +FRAME is the frame where the drop happened. +WINDOW is the window where the drop happened. +_MESSAGE-ATOM and _FORMAT are unused. +DATA is the vector containing the contents of the client +message (format 32) that caused EVENT to be generated." + (let ((type (cdr (assq (aref data 0) x-dnd-offix-id-to-name))) + (data (x-window-property "_DND_SELECTION" frame nil 0 t))) + ;; First save state. + (x-dnd-save-state window nil nil (vector type) nil) + ;; Now call the test function to decide what action to perform. + (x-dnd-maybe-call-test-function window 'private) + (unwind-protect + (x-dnd-drop-data event frame window data + (symbol-name type)) + (x-dnd-forget-drop window)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; XDND protocol. commit 0d383b592c2fd1d9b73ebd611d05d80089c7a3a6 Author: Lars Ingebrigtsen Date: Wed Jun 15 14:05:07 2022 +0200 Fix ;;;###autoload scanning from (some) packages * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--parse-file): Fix autoloads scanning from packages. diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index 95666ddb2a..86c776e301 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -366,7 +366,11 @@ don't include." ;; We always return the package version (even for pre-dumped ;; files). - (when package-data + (if (not package-data) + ;; We have to switch `emacs-lisp-mode' when scanning + ;; loaddefs for packages so that `syntax-ppss' later gives + ;; correct results. + (emacs-lisp-mode) (let ((version (lm-header "version")) package) (when (and version commit 6237aec6ca2dcd2958999323b7ccf7e9c502dd94 Author: Michael Albinus Date: Wed Jun 15 12:43:17 2022 +0200 Fix file name quoting in tramp-smb.el * lisp/net/tramp-smb.el (tramp-smb-shell-quote-localname): New defun. (tramp-smb-handle-add-name-to-file, tramp-smb-handle-copy-file) (tramp-smb-handle-delete-directory) (tramp-smb-handle-delete-file) (tramp-smb-do-file-attributes-with-stat) (tramp-smb-handle-file-local-copy) (tramp-smb-handle-file-system-info) (tramp-smb-handle-make-directory-internal) (tramp-smb-handle-make-symbolic-link) (tramp-smb-handle-process-file, tramp-smb-handle-rename-file) (tramp-smb-handle-set-file-modes) (tramp-smb-handle-start-file-process) (tramp-smb-handle-write-region, tramp-smb-get-file-entries) (tramp-smb-get-stat-capability): Use it. (tramp-smb-get-localname): Remove superfluous test. (Bug#55855) diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 8037c89829..3654910133 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -386,14 +386,13 @@ arguments to pass to the OPERATION." ;; We must also flush the cache of the directory, because ;; `file-attributes' reads the values from there. (tramp-flush-file-properties v2 v2-localname) - (unless - (tramp-smb-send-command - v1 - (format - "%s \"%s\" \"%s\"" - (if (tramp-smb-get-cifs-capabilities v1) "link" "hardlink") - (tramp-smb-get-localname v1) - (tramp-smb-get-localname v2))) + (unless (tramp-smb-send-command + v1 + (format + "%s %s %s" + (if (tramp-smb-get-cifs-capabilities v1) "link" "hardlink") + (tramp-smb-shell-quote-localname v1) + (tramp-smb-shell-quote-localname v2))) (tramp-error v2 'file-error "error with add-name-to-file, see buffer `%s' for details" @@ -641,9 +640,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (tramp-error v 'file-error "Target `%s' must contain a share name" newname)) (unless (tramp-smb-send-command - v (format "put \"%s\" \"%s\"" - (tramp-compat-file-name-unquote filename) - (tramp-smb-get-localname v))) + v (format "put %s %s" + (tramp-smb-shell-quote-argument filename) + (tramp-smb-shell-quote-localname v))) (tramp-error v 'file-error "Cannot copy `%s' to `%s'" filename newname))))) @@ -672,10 +671,10 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (tramp-flush-directory-properties v localname) (unless (tramp-smb-send-command v (format - "%s \"%s\"" + "%s %s" (if (tramp-smb-get-cifs-capabilities v) "posix_rmdir" "rmdir") - (tramp-smb-get-localname v))) + (tramp-smb-shell-quote-localname v))) ;; Error. (with-current-buffer (tramp-get-connection-buffer v) (goto-char (point-min)) @@ -698,9 +697,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (move-file-to-trash filename) (unless (tramp-smb-send-command v (format - "%s \"%s\"" + "%s %s" (if (tramp-smb-get-cifs-capabilities v) "posix_unlink" "rm") - (tramp-smb-get-localname v))) + (tramp-smb-shell-quote-localname v))) ;; Error. (with-current-buffer (tramp-get-connection-buffer v) (goto-char (point-min)) @@ -898,7 +897,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." vec 5 "file attributes with stat: %s" (tramp-file-name-localname vec)) (let* (size id link uid gid atime mtime ctime mode inode) (when (tramp-smb-send-command - vec (format "stat \"%s\"" (tramp-smb-get-localname vec))) + vec (format "stat %s" (tramp-smb-shell-quote-localname vec))) ;; Loop the listing. (with-current-buffer (tramp-get-connection-buffer vec) @@ -972,7 +971,8 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (when (and (stringp id) (tramp-smb-send-command vec - (format "readlink \"%s\"" (tramp-smb-get-localname vec)))) + (format + "readlink %s" (tramp-smb-shell-quote-localname vec)))) (goto-char (point-min)) (and (looking-at ".+ -> \\(.+\\)") (setq id (match-string 1)))) @@ -991,8 +991,9 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (with-tramp-progress-reporter v 3 (format "Fetching %s to tmp file %s" filename tmpfile) (unless (tramp-smb-send-command - v (format "get \"%s\" \"%s\"" - (tramp-smb-get-localname v) tmpfile)) + v (format "get %s %s" + (tramp-smb-shell-quote-localname v) + (tramp-smb-shell-quote-argument tmpfile))) ;; Oops, an error. We shall cleanup. (delete-file tmpfile) (tramp-error @@ -1025,7 +1026,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (when (tramp-smb-get-share v) (tramp-message v 5 "file system info: %s" localname) (tramp-smb-send-command - v (format "du %s/*" (tramp-smb-get-localname v))) + v (format "du %s/*" (tramp-smb-shell-quote-localname v))) (with-current-buffer (tramp-get-connection-buffer v) (let (total avail blocksize) (goto-char (point-min)) @@ -1215,18 +1216,17 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (unless (file-name-absolute-p directory) (setq directory (expand-file-name directory default-directory))) (with-parsed-tramp-file-name directory nil - (let* ((file (tramp-smb-get-localname v))) - (when (file-directory-p (file-name-directory directory)) - (tramp-smb-send-command - v - (if (tramp-smb-get-cifs-capabilities v) - (format "posix_mkdir \"%s\" %o" file (default-file-modes)) - (format "mkdir \"%s\"" file))) - ;; We must also flush the cache of the directory, because - ;; `file-attributes' reads the values from there. - (tramp-flush-file-properties v localname)) - (unless (file-directory-p directory) - (tramp-error v 'file-error "Couldn't make directory %s" directory))))) + (when (file-directory-p (file-name-directory directory)) + (tramp-smb-send-command + v (if (tramp-smb-get-cifs-capabilities v) + (format "posix_mkdir %s %o" + (tramp-smb-shell-quote-localname v) (default-file-modes)) + (format "mkdir %s" (tramp-smb-shell-quote-localname v)))) + ;; We must also flush the cache of the directory, because + ;; `file-attributes' reads the values from there. + (tramp-flush-file-properties v localname)) + (unless (file-directory-p directory) + (tramp-error v 'file-error "Couldn't make directory %s" directory)))) (defun tramp-smb-handle-make-symbolic-link (target linkname &optional ok-if-already-exists) @@ -1270,11 +1270,10 @@ component is used as the target of the symlink." ;; `file-attributes' reads the values from there. (tramp-flush-file-properties v localname) - (unless - (tramp-smb-send-command - v (format "symlink \"%s\" \"%s\"" - (tramp-compat-file-name-unquote target) - (tramp-smb-get-localname v))) + (unless (tramp-smb-send-command + v (format "symlink %s %s" + (tramp-smb-shell-quote-argument target) + (tramp-smb-shell-quote-localname v))) (tramp-error v 'file-error "error with make-symbolic-link, see buffer `%s' for details" @@ -1357,7 +1356,9 @@ component is used as the target of the symlink." (tramp-smb-call-winexe v) (when (tramp-smb-get-share v) (tramp-smb-send-command - v (format "cd \"//%s%s\"" host (file-name-directory localname)))) + v (format "cd //%s%s" host + (tramp-smb-shell-quote-argument + (file-name-directory localname))))) (tramp-smb-send-command v command) ;; Preserve command output. (narrow-to-region (point-max) (point-max)) @@ -1432,9 +1433,9 @@ component is used as the target of the symlink." v2 'file-error "Target `%s' must contain a share name" newname)) (unless (tramp-smb-send-command - v2 (format "rename \"%s\" \"%s\"" - (tramp-smb-get-localname v1) - (tramp-smb-get-localname v2))) + v2 (format "rename %s %s" + (tramp-smb-shell-quote-localname v1) + (tramp-smb-shell-quote-localname v2))) (tramp-error v2 'file-error "Cannot rename `%s'" filename)))) ;; We must rename via copy. @@ -1532,7 +1533,8 @@ component is used as the target of the symlink." (when (tramp-smb-get-cifs-capabilities v) (tramp-flush-file-properties v localname) (unless (tramp-smb-send-command - v (format "chmod \"%s\" %o" (tramp-smb-get-localname v) mode)) + v + (format "chmod %s %o" (tramp-smb-shell-quote-localname v) mode)) (tramp-error v 'file-error "Error while changing file's mode %s" filename)))))) @@ -1570,8 +1572,10 @@ component is used as the target of the symlink." (when (tramp-smb-get-share v) (tramp-smb-send-command v (format - "cd \"//%s%s\"" - host (file-name-directory localname)))) + "cd //%s%s" + host + (tramp-smb-shell-quote-argument + (file-name-directory localname))))) (tramp-message v 6 "(%s); exit" command) (tramp-send-string v command))) (setq p (tramp-get-connection-process v)) @@ -1635,8 +1639,9 @@ VEC or USER, or if there is no home directory, return nil." v 3 (format "Moving tmp file %s to %s" tmpfile filename) (unwind-protect (unless (tramp-smb-send-command - v (format "put %s \"%s\"" - tmpfile (tramp-smb-get-localname v))) + v (format "put %s %s" + (tramp-smb-shell-quote-argument tmpfile) + (tramp-smb-shell-quote-localname v))) (tramp-error v 'file-error "Cannot write `%s'" filename)) (delete-file tmpfile)))))) @@ -1672,9 +1677,8 @@ If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"." (when (string-match "\\(\\$\\$\\)\\(/\\|$\\)" localname) (setq localname (replace-match "$" nil nil localname 1))) - ;; A period followed by a space, or trailing periods and spaces, - ;; are not supported. - (when (string-match-p "\\. \\|\\.$\\| $" localname) + ;; A trailing space is not supported. + (when (string-match-p " $" localname) (tramp-error vec 'file-error "Invalid file name %s" (tramp-make-tramp-file-name vec localname))) @@ -1705,7 +1709,7 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)." ;; Read entries. (if share (tramp-smb-send-command - v (format "dir \"%s*\"" (tramp-smb-get-localname v))) + v (format "dir %s*" (tramp-smb-shell-quote-localname v))) ;; `tramp-smb-maybe-open-connection' lists also the share names. (tramp-smb-maybe-open-connection v)) @@ -1909,7 +1913,7 @@ are listed. Result is the list (LOCALNAME MODE SIZE MTIME)." (if (and (tramp-smb-get-share vec) (process-live-p (tramp-get-connection-process vec))) (with-tramp-connection-property (tramp-get-process vec) "stat-capability" - (tramp-smb-send-command vec "stat \"/\"")))) + (tramp-smb-send-command vec "stat /")))) ;; Connection functions. @@ -2169,6 +2173,10 @@ Removes smb prompt. Returns nil if an error message has appeared." (let ((system-type 'ms-dos)) (tramp-unquote-shell-quote-argument s))) +(defun tramp-smb-shell-quote-localname (vec) + "Call `tramp-smb-shell-quote-argument' on localname of VEC." + (tramp-smb-shell-quote-argument (tramp-smb-get-localname vec))) + (add-hook 'tramp-unload-hook (lambda () (unload-feature 'tramp-smb 'force))) commit 8fca44da816af3d8f3dde2cea871c7563961ef69 Author: Michael Albinus Date: Wed Jun 15 10:57:56 2022 +0200 Improve Tramp debugging * lisp/net/tramp-cache.el (tramp-list-connections): Fix docstring. * lisp/net/tramp.el (tramp-backtrace): New optional arg FORCE. diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index dc1e3d28b5..a0cbfed64e 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -427,7 +427,7 @@ used to cache connection properties of the local machine." ;;;###tramp-autoload (defun tramp-list-connections () - "Return all known `tramp-file-name' structs according to `tramp-cache'." + "Return all active `tramp-file-name' structs according to `tramp-cache-data'." (let ((tramp-verbose 0)) (delq nil (mapcar (lambda (key) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index cee8897b4f..e4b14cfbc2 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -2148,15 +2148,17 @@ applicable)." (put #'tramp-message 'tramp-suppress-trace t) -(defsubst tramp-backtrace (&optional vec-or-proc) +(defsubst tramp-backtrace (&optional vec-or-proc force) "Dump a backtrace into the debug buffer. -If VEC-OR-PROC is nil, the buffer *debug tramp* is used. This -function is meant for debugging purposes." - (when (>= tramp-verbose 10) - (if vec-or-proc - (tramp-message - vec-or-proc 10 "\n%s" (with-output-to-string (backtrace))) - (with-output-to-temp-buffer "*debug tramp*" (backtrace))))) +If VEC-OR-PROC is nil, the buffer *debug tramp* is used. FORCE +forces the backtrace even if `tramp-verbose' is less than 10. +This function is meant for debugging purposes." + (let ((tramp-verbose (if force 10 tramp-verbose))) + (when (>= tramp-verbose 10) + (if vec-or-proc + (tramp-message + vec-or-proc 10 "\n%s" (with-output-to-string (backtrace))) + (with-output-to-temp-buffer "*debug tramp*" (backtrace)))))) (put #'tramp-backtrace 'tramp-suppress-trace t) commit 112b6b8e37b5df268ced98c4354802275a4da417 Author: Juri Linkov Date: Wed Jun 15 10:32:09 2022 +0300 Update args of isearch-search-fun-in-text-property (bug#14013) * lisp/isearch.el (isearch-search-fun-in-text-property): Swap signature args. * lisp/dired-aux.el (dired-isearch-search-filenames): Update the call. diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index d16aee0fa8..1b7088104d 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -3208,7 +3208,7 @@ Intended to be added to `isearch-mode-hook'." The returned function narrows the search to match the search string only as part of a file name enclosed by the text property `dired-filename'. It's intended to override the default search function." - (isearch-search-fun-in-text-property 'dired-filename (funcall orig-fun))) + (isearch-search-fun-in-text-property (funcall orig-fun) 'dired-filename)) ;;;###autoload (defun dired-isearch-filenames () diff --git a/lisp/isearch.el b/lisp/isearch.el index 91aaa66a5b..7650ebcfce 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -4455,12 +4455,12 @@ LAX-WHITESPACE: The value of `isearch-lax-whitespace' and (funcall after-change nil nil nil))))) -(defun isearch-search-fun-in-text-property (property &optional search-fun) +(defun isearch-search-fun-in-text-property (search-fun property) "Return the function to search inside text that has the specified PROPERTY. The function will limit the search for matches only inside text which has this property in the current buffer. -Optional argument SEARCH-FUN provides the function to search text, and -defaults to the value of `isearch-search-fun-default'." +The argument SEARCH-FUN provides the function to search text, and +defaults to the value of `isearch-search-fun-default' when nil." (lambda (string &optional bound noerror count) (let* ((old (point)) ;; Check if point is already on the property. commit 7547e4e60eb57051bc6fd4e74f1643f2760bba65 Author: Visuwesh Date: Tue Jun 14 22:59:47 2022 +0530 repeat-mode: Don't echo unset keys in help message * repeat.el (repeat-echo-message-string): Check if the key is set. (bug#55977) diff --git a/lisp/repeat.el b/lisp/repeat.el index ea4e3d0bd8..94ea9f7ac1 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -500,7 +500,7 @@ See `describe-repeat-maps' for a list of all repeatable commands." (defun repeat-echo-message-string (keymap) "Return a string with a list of repeating keys." (let (keys) - (map-keymap (lambda (key _) (push key keys)) keymap) + (map-keymap (lambda (key cmd) (and cmd (push key keys))) keymap) (format-message "Repeat with %s%s" (mapconcat (lambda (key) (key-description (vector key))) commit 36f96c351a97bb2d068e8541167d94803dde6ab8 Author: Po Lu Date: Wed Jun 15 14:46:21 2022 +0800 Handle coordinates for the old KDE drop protocol * src/xterm.c (x_atom_refs): Add DndProtocol and _DND_PROTOCOL. (x_coords_from_dnd_message): Handle the old KDE protocol. * src/xterm.h (struct x_display_info): New atoms. diff --git a/src/xterm.c b/src/xterm.c index bf8a33f70c..b1e7ee578a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1008,6 +1008,9 @@ static const struct x_atom_ref x_atom_refs[] = Xatom_MOTIF_DRAG_RECEIVER_INFO) ATOM_REFS_INIT ("XmTRANSFER_SUCCESS", Xatom_XmTRANSFER_SUCCESS) ATOM_REFS_INIT ("XmTRANSFER_FAILURE", Xatom_XmTRANSFER_FAILURE) + /* Old OffiX (a.k.a. old KDE) drop protocol support. */ + ATOM_REFS_INIT ("DndProtocol", Xatom_DndProtocol) + ATOM_REFS_INIT ("_DND_PROTOCOL", Xatom_DND_PROTOCOL) }; enum @@ -15893,6 +15896,7 @@ x_coords_from_dnd_message (struct x_display_info *dpyinfo, xm_drag_motion_reply dreply; xm_drop_start_message smsg; xm_drop_start_reply reply; + unsigned long kde_data; if (event->type != ClientMessage) return false; @@ -15943,6 +15947,23 @@ x_coords_from_dnd_message (struct x_display_info *dpyinfo, } } + if (((event->xclient.message_type + == dpyinfo->Xatom_DndProtocol) + || (event->xclient.message_type + == dpyinfo->Xatom_DND_PROTOCOL)) + && event->xclient.format == 32 + /* Check that the version of the old KDE protocol is new + enough to include coordinates. */ + && event->xclient.data.l[4]) + { + kde_data = (unsigned long) event->xclient.data.l[3]; + + *x_out = (kde_data & 0xffff); + *y_out = (kde_data >> 16 & 0xffff); + + return true; + } + return false; } diff --git a/src/xterm.h b/src/xterm.h index 82b4308041..d710069fad 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -443,12 +443,19 @@ struct x_display_info /* Atom used to determine whether or not the screen is composited. */ Atom Xatom_NET_WM_CM_Sn; + /* Atoms used by the Motif drag and drop protocols. */ Atom Xatom_MOTIF_WM_HINTS, Xatom_MOTIF_DRAG_WINDOW, Xatom_MOTIF_DRAG_TARGETS, Xatom_MOTIF_DRAG_AND_DROP_MESSAGE, Xatom_MOTIF_DRAG_INITIATOR_INFO, Xatom_MOTIF_DRAG_RECEIVER_INFO; + /* Special selections used by the Motif drop protocol to indicate + success or failure. */ Atom Xatom_XmTRANSFER_SUCCESS, Xatom_XmTRANSFER_FAILURE; + /* Atoms used by both versions of the OffiX DND protocol (the "old + KDE" protocol in x-dnd.el). */ + Atom Xatom_DndProtocol, Xatom_DND_PROTOCOL; + /* The frame (if any) which has the X window that has keyboard focus. Zero if none. This is examined by Ffocus_frame in xfns.c. Note that a mere EnterNotify event can set this; if you need to know the commit 5b7f24e58a3505131fcfe433be505bf7212b57bf Merge: 1302c329eb 850050ca5c Author: Stefan Kangas Date: Wed Jun 15 06:32:14 2022 +0200 Merge from origin/emacs-28 850050ca5c Revert "Clarify what a Calc registeri in in calc-insert-re... commit 1302c329eb09b40a8895198fc0ec98b3abac6b96 Author: Po Lu Date: Wed Jun 15 11:37:39 2022 +0800 Fix link action handling with Motif DND * src/xterm.c (enum xm_drag_operation): New alternate definition. (XM_DRAG_OPERATION_IS_LINK): New macro. (handle_one_xevent): Use it instead. diff --git a/src/xterm.c b/src/xterm.c index 7f78f40bb7..bf8a33f70c 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1504,12 +1504,16 @@ typedef struct xm_top_level_leave_message enum xm_drag_operation { - XM_DRAG_NOOP = 0, - XM_DRAG_MOVE = (1L << 0), - XM_DRAG_COPY = (1L << 1), - XM_DRAG_LINK = (1L << 2), + XM_DRAG_NOOP = 0, + XM_DRAG_MOVE = (1L << 0), + XM_DRAG_COPY = (1L << 1), + XM_DRAG_LINK = (1L << 2), + XM_DRAG_LINK_REC = 3, }; +#define XM_DRAG_OPERATION_IS_LINK(op) ((op) == XM_DRAG_LINK \ + || (op) == XM_DRAG_LINK_REC) + enum xm_drag_action { XM_DROP_ACTION_DROP = 0, @@ -16097,7 +16101,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (operation != XM_DRAG_MOVE && operation != XM_DRAG_COPY - && operation != XM_DRAG_LINK) + && XM_DRAG_OPERATION_IS_LINK (operation)) { x_dnd_waiting_for_finish = false; goto done; @@ -16121,7 +16125,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_action = dpyinfo->Xatom_XdndActionCopy; break; - case XM_DRAG_LINK: + /* This means XM_DRAG_OPERATION_IS_LINK (operation). */ + default: x_dnd_action = dpyinfo->Xatom_XdndActionLink; break; } commit 2e2913654b65fea657e79705df2c1842207000cf Author: Po Lu Date: Wed Jun 15 09:26:46 2022 +0800 Handle coordinates from XM_DRAG_REASON_DRAG_MOTION replies * src/xterm.c (struct xm_drag_motion_reply): New struct. (xm_read_drag_motion_reply): New function. (x_coords_from_dnd_message): Handle those messages as well. diff --git a/src/xterm.c b/src/xterm.c index 2cc17b455d..7f78f40bb7 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1471,6 +1471,17 @@ typedef struct xm_drag_motion_message /* CARD16 */ uint16_t x, y; } xm_drag_motion_message; +typedef struct xm_drag_motion_reply +{ + /* BYTE */ uint8_t reason; + /* BYTE */ uint8_t byte_order; + + /* CARD16 */ uint16_t side_effects; + /* CARD32 */ uint32_t timestamp; + /* CARD16 */ uint16_t better_x; + /* CARD16 */ uint16_t better_y; +} xm_drag_motion_reply; + typedef struct xm_top_level_leave_message { /* BYTE */ uint8_t reason; @@ -2467,6 +2478,39 @@ xm_read_drag_motion_message (const XEvent *msg, return 0; } +static int +xm_read_drag_motion_reply (const XEvent *msg, xm_drag_motion_reply *reply) +{ + const uint8_t *data; + + data = (const uint8_t *) &msg->xclient.data.b[0]; + + if ((XM_DRAG_REASON_CODE (data[0]) + != XM_DRAG_REASON_DRAG_MOTION) + || (XM_DRAG_REASON_ORIGINATOR (data[0]) + != XM_DRAG_ORIGINATOR_RECEIVER)) + return 1; + + reply->reason = *(data++); + reply->byte_order = *(data++); + reply->side_effects = *(uint16_t *) data; + reply->timestamp = *(uint32_t *) (data + 2); + reply->better_x = *(uint16_t *) (data + 6); + reply->better_y = *(uint16_t *) (data + 8); + + if (reply->byte_order != XM_BYTE_ORDER_CUR_FIRST) + { + SWAPCARD16 (reply->side_effects); + SWAPCARD32 (reply->timestamp); + SWAPCARD16 (reply->better_x); + SWAPCARD16 (reply->better_y); + } + + reply->byte_order = XM_BYTE_ORDER_CUR_FIRST; + + return 0; +} + static void x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo, struct frame *f, Window wdesc, @@ -15842,6 +15886,7 @@ x_coords_from_dnd_message (struct x_display_info *dpyinfo, XEvent *event, int *x_out, int *y_out) { xm_drag_motion_message dmsg; + xm_drag_motion_reply dreply; xm_drop_start_message smsg; xm_drop_start_reply reply; @@ -15869,6 +15914,13 @@ x_coords_from_dnd_message (struct x_display_info *dpyinfo, *x_out = dmsg.x; *y_out = dmsg.y; + return true; + } + else if (!xm_read_drag_motion_reply (event, &dreply)) + { + *x_out = dreply.better_x; + *y_out = dreply.better_y; + return true; } else if (!xm_read_drop_start_message (event, &smsg)) commit 787c4ad8b0776280305a220d6669c956d9ed8a5d Author: Sean Whitton Date: Mon Jun 13 12:24:17 2022 -0500 Add abbrev tables for minibuffer-mode and minibuffer-inactive-mode * lisp/minibuffer.el (minibuffer-mode, minibuffer-inactive-mode): Add an abbrev table for each of these modes (bug#55946). diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 7d589c0174..23251a5474 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2837,7 +2837,6 @@ not active." "" #'ignore) (define-derived-mode minibuffer-inactive-mode nil "InactiveMinibuffer" - :abbrev-table nil ;abbrev.el is not loaded yet during dump. ;; Note: this major mode is called from minibuf.c. "Major mode to use in the minibuffer when it is not active. This is only used when the minibuffer area has no active minibuffer. @@ -2859,7 +2858,6 @@ For customizing this mode, it is better to use `minibuffer-setup-hook' and `minibuffer-exit-hook' rather than the mode hook of this mode." :syntax-table nil - :abbrev-table nil :interactive nil) ;;; Completion tables. commit 94e118536986207ae17535c3d130b4172e408b7c Author: Eli Zaretskii Date: Tue Jun 14 22:13:49 2022 +0300 Support callers which sometimes run unrelated to display code * src/xdisp.c (update_redisplay_ticks): Don't abort callers with w == NULL if we are called outside of display engine code, and don't update the tick count in that case. diff --git a/src/xdisp.c b/src/xdisp.c index d14955af41..1ba9132e8c 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -17199,6 +17199,11 @@ update_redisplay_ticks (int ticks, struct window *w) cwindow = w; window_ticks = 0; } + /* Some callers can be run in contexts unrelated to redisplay, so + don't abort them and don't update the tick count in those cases. */ + if (!w && !redisplaying_p) + return; + if (ticks > 0) window_ticks += ticks; if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks) commit 1ac74e28622e3ebbe76daf84f0a6f310a8ea3c45 Author: Mattias Engdegård Date: Mon Jun 6 11:10:05 2022 +0200 Simplify byte-compiler assuming cconv normalisations * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker) (byte-optimize-let-form, byte-optimize-letX): * lisp/emacs-lisp/bytecomp.el (byte-compile-unwind-protect): Simplify source optimisation and codegen code that can now rely on normalised let/let* and unwind-protect forms. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 0e10e332b2..fc49e88f8e 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -422,7 +422,7 @@ for speeding up processing.") (byte-optimize-body (cdr clause) for-effect)))) clauses))) - (`(unwind-protect ,exp . ,exps) + (`(unwind-protect ,exp :fun-body ,f) ;; The unwinding part of an unwind-protect is compiled (and thus ;; optimized) as a top-level form, but run the optimizer for it here ;; anyway for lexical variable usage and substitution. But the @@ -430,13 +430,7 @@ for speeding up processing.") ;; unwind-protect itself. (The unwinding part is always for effect, ;; but that isn't handled properly yet.) (let ((bodyform (byte-optimize-form exp for-effect))) - (pcase exps - (`(:fun-body ,f) - `(,fn ,bodyform - :fun-body ,(byte-optimize-form f nil))) - (_ - `(,fn ,bodyform - . ,(byte-optimize-body exps t)))))) + `(,fn ,bodyform :fun-body ,(byte-optimize-form f nil)))) (`(catch ,tag . ,exps) `(,fn ,(byte-optimize-form tag nil) @@ -695,13 +689,8 @@ for speeding up processing.") (let ((byte-optimize--lexvars nil)) (cons (mapcar (lambda (binding) - (if (symbolp binding) - binding - (when (or (atom binding) (cddr binding)) - (byte-compile-warn-x - binding "malformed let binding: `%S'" binding)) - (list (car binding) - (byte-optimize-form (nth 1 binding) nil)))) + (list (car binding) + (byte-optimize-form (nth 1 binding) nil))) (car form)) (byte-optimize-body (cdr form) for-effect))))) @@ -1253,28 +1242,17 @@ See Info node `(elisp) Integer Basics'." ;; Body is empty or just contains a constant. (`(,head ,bindings . ,(or '() `(,(and const (pred macroexp-const-p))))) (if (eq head 'let) - `(progn ,@(mapcar (lambda (binding) - (and (consp binding) (cadr binding))) - bindings) - ,const) - `(,head ,(butlast bindings) - ,@(and (consp (car (last bindings))) - (cdar (last bindings))) - ,const))) + `(progn ,@(mapcar #'cadr bindings) ,const) + `(,head ,(butlast bindings) ,(cadar (last bindings)) ,const))) ;; Body is last variable. (`(,head ,(and bindings - (let last-var (let ((last (car (last bindings)))) - (if (consp last) (car last) last)))) + (let last-var (caar (last bindings)))) ,(and last-var ; non-linear pattern (pred symbolp) (pred (not keywordp)) (pred (not booleanp)))) (if (eq head 'let) - `(progn ,@(mapcar (lambda (binding) - (and (consp binding) (cadr binding))) - bindings)) - `(,head ,(butlast bindings) - ,@(and (consp (car (last bindings))) - (cdar (last bindings)))))) + `(progn ,@(mapcar #'cadr bindings)) + `(,head ,(butlast bindings) ,(cadar (last bindings))))) (_ form))) diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index af74c0699b..d28ec0be16 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -4806,11 +4806,8 @@ binding slots have been popped." (byte-compile-out-tag endtag))) (defun byte-compile-unwind-protect (form) - (pcase (cddr form) - (`(:fun-body ,f) - (byte-compile-form f)) - (handlers - (byte-compile-form `#'(lambda () ,@handlers)))) + (cl-assert (eq (caddr form) :fun-body)) + (byte-compile-form (nth 3 form)) (byte-compile-out 'byte-unwind-protect 0) (byte-compile-form-do-effect (car (cdr form))) (byte-compile-out 'byte-unbind 1)) commit d6600481ae9423eb2c51150967050afb05c301b8 Author: Mattias Engdegård Date: Tue Jun 14 19:09:20 2022 +0200 Run cconv for dynbound code as well Make cconv work for dynamically bound code and always run it. This allows later stages to benefit from transformations and normalisations in cconv. * lisp/emacs-lisp/bytecomp.el (byte-compile-preprocess): Always run cconv. * lisp/emacs-lisp/cconv.el (cconv--analyze-function) (cconv-analyze-form): In dynbound code, treat all variable bindings as dynamic (lambda, let, let* and condition-case). diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 1f868d2217..af74c0699b 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -2557,9 +2557,7 @@ list that represents a doc string reference. ;; macroexpand-all. ;; (if (memq byte-optimize '(t source)) ;; (setq form (byte-optimize-form form for-effect))) - (cond - (lexical-binding (cconv-closure-convert form)) - (t form))) + (cconv-closure-convert form)) ;; byte-hunk-handlers cannot call this! (defun byte-compile-toplevel-file-form (top-level-form) diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index b12f1db677..eca1123899 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el @@ -664,18 +664,19 @@ FORM is the parent form that binds this var." ;; Push it before recursing, so cconv-freevars-alist contains entries in ;; the order they'll be used by closure-convert-rec. (push freevars cconv-freevars-alist) - (dolist (arg args) - (cond - ((byte-compile-not-lexical-var-p arg) - (byte-compile-warn-x - arg - "Lexical argument shadows the dynamic variable %S" - arg)) - ((eq ?& (aref (symbol-name arg) 0)) nil) ;Ignore &rest, &optional, ... - (t (let ((varstruct (list arg nil nil nil nil))) - (cl-pushnew arg byte-compile-lexical-variables) - (push (cons (list arg) (cdr varstruct)) newvars) - (push varstruct newenv))))) + (when lexical-binding + (dolist (arg args) + (cond + ((byte-compile-not-lexical-var-p arg) + (byte-compile-warn-x + arg + "Lexical argument shadows the dynamic variable %S" + arg)) + ((eq ?& (aref (symbol-name arg) 0)) nil) ;Ignore &rest, &optional, ... + (t (let ((varstruct (list arg nil nil nil nil))) + (cl-pushnew arg byte-compile-lexical-variables) + (push (cons (list arg) (cdr varstruct)) newvars) + (push varstruct newenv)))))) (dolist (form body) ;Analyze body forms. (cconv-analyze-form form newenv)) ;; Summarize resulting data about arguments. @@ -724,7 +725,7 @@ This function does not return anything but instead fills the (cconv-analyze-form value (if (eq letsym 'let*) env orig-env))) - (unless (byte-compile-not-lexical-var-p var) + (unless (or (byte-compile-not-lexical-var-p var) (not lexical-binding)) (cl-pushnew var byte-compile-lexical-variables) (let ((varstruct (list var nil nil nil nil))) (push (cons binder (cdr varstruct)) newvars) @@ -769,6 +770,8 @@ This function does not return anything but instead fills the (`(condition-case ,var ,protected-form . ,handlers) (cconv-analyze-form protected-form env) + (unless lexical-binding + (setq var nil)) (when (and var (symbolp var) (byte-compile-not-lexical-var-p var)) (byte-compile-warn-x var "Lexical variable shadows the dynamic variable %S" var)) commit 6825e5686a4bf21f5d5a0ae1af889097cfa2f597 Author: Mattias Engdegård Date: Fri Jun 3 20:31:10 2022 +0200 Normalise setq during macro-expansion Early normalisation of setq during macroexpand-all allows later stages, cconv, byte-opt and codegen, to be simplified and duplicated checks to be eliminated. * lisp/emacs-lisp/macroexp.el (macroexp--expand-all): Normalise all setq forms to a sequence of (setq VAR EXPR). Emit warnings if necessary. * lisp/emacs-lisp/cconv.el (cconv-convert, cconv-analyze-form): * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): * lisp/emacs-lisp/bytecomp.el (byte-compile-setq): Simplify. * test/lisp/emacs-lisp/bytecomp-tests.el: Adapt and add tests. * test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el; * test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el: New files. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 69795f9c11..0e10e332b2 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -463,32 +463,21 @@ for speeding up processing.") ;; is a *value* and shouldn't appear in the car. (`((closure . ,_) . ,_) form) - (`(setq . ,args) - (let ((var-expr-list nil)) - (while args - (unless (and (consp args) - (symbolp (car args)) (consp (cdr args))) - (byte-compile-warn-x form "malformed setq form: %S" form)) - (let* ((var (car args)) - (expr (cadr args)) - (lexvar (assq var byte-optimize--lexvars)) - (value (byte-optimize-form expr nil))) - (when lexvar - (setcar (cdr lexvar) t) ; Mark variable to be kept. - (setcdr (cdr lexvar) nil) ; Inhibit further substitution. - - (when (memq var byte-optimize--aliased-vars) - ;; Cancel aliasing of variables aliased to this one. - (dolist (v byte-optimize--lexvars) - (when (eq (nth 2 v) var) - ;; V is bound to VAR but VAR is now mutated: - ;; cancel aliasing. - (setcdr (cdr v) nil))))) - - (push var var-expr-list) - (push value var-expr-list)) - (setq args (cddr args))) - (cons fn (nreverse var-expr-list)))) + (`(setq ,var ,expr) + (let ((lexvar (assq var byte-optimize--lexvars)) + (value (byte-optimize-form expr nil))) + (when lexvar + (setcar (cdr lexvar) t) ; Mark variable to be kept. + (setcdr (cdr lexvar) nil) ; Inhibit further substitution. + + (when (memq var byte-optimize--aliased-vars) + ;; Cancel aliasing of variables aliased to this one. + (dolist (v byte-optimize--lexvars) + (when (eq (nth 2 v) var) + ;; V is bound to VAR but VAR is now mutated: + ;; cancel aliasing. + (setcdr (cdr v) nil))))) + `(,fn ,var ,value))) (`(defvar ,(and (pred symbolp) name) . ,rest) (let ((optimized-rest (and rest diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index ab21fba8a2..1f868d2217 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -4225,25 +4225,13 @@ This function is never called when `lexical-binding' is nil." (byte-defop-compiler-1 quote) (defun byte-compile-setq (form) - (let* ((args (cdr form)) - (len (length args))) - (if (= (logand len 1) 1) - (progn - (byte-compile-report-error - (format-message - "missing value for `%S' at end of setq" (car (last args)))) - (byte-compile-form - `(signal 'wrong-number-of-arguments '(setq ,len)) - byte-compile--for-effect)) - (if args - (while args - (byte-compile-form (car (cdr args))) - (or byte-compile--for-effect (cdr (cdr args)) - (byte-compile-out 'byte-dup 0)) - (byte-compile-variable-set (car args)) - (setq args (cdr (cdr args)))) - ;; (setq), with no arguments. - (byte-compile-form nil byte-compile--for-effect))) + (cl-assert (= (length form) 3)) ; normalised in macroexp + (let ((var (nth 1 form)) + (expr (nth 2 form))) + (byte-compile-form expr) + (unless byte-compile--for-effect + (byte-compile-out 'byte-dup 0)) + (byte-compile-variable-set var) (setq byte-compile--for-effect nil))) (byte-defop-compiler-1 set-default) diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index 1a501f50bf..b12f1db677 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el @@ -555,29 +555,19 @@ places where they originally did not directly appear." `(,(car form) ,(cconv-convert form1 env extend) :fun-body ,(cconv--convert-function () body env form1))) - (`(setq . ,forms) ; setq special form - (if (= (logand (length forms) 1) 1) - ;; With an odd number of args, let bytecomp.el handle the error. - form - (let ((prognlist ())) - (while forms - (let* ((sym (pop forms)) - (sym-new (or (cdr (assq sym env)) sym)) - (value (cconv-convert (pop forms) env extend))) - (push (pcase sym-new - ((pred symbolp) `(,(car form) ,sym-new ,value)) - (`(car-safe ,iexp) `(setcar ,iexp ,value)) - ;; This "should never happen", but for variables which are - ;; mutated+captured+unused, we may end up trying to `setq' - ;; on a closed-over variable, so just drop the setq. - (_ ;; (byte-compile-report-error - ;; (format "Internal error in cconv of (setq %s ..)" - ;; sym-new)) - value)) - prognlist))) - (if (cdr prognlist) - `(progn . ,(nreverse prognlist)) - (car prognlist))))) + (`(setq ,var ,expr) + (let ((var-new (or (cdr (assq var env)) var)) + (value (cconv-convert expr env extend))) + (pcase var-new + ((pred symbolp) `(,(car form) ,var-new ,value)) + (`(car-safe ,iexp) `(setcar ,iexp ,value)) + ;; This "should never happen", but for variables which are + ;; mutated+captured+unused, we may end up trying to `setq' + ;; on a closed-over variable, so just drop the setq. + (_ ;; (byte-compile-report-error + ;; (format "Internal error in cconv of (setq %s ..)" + ;; sym-new)) + value)))) (`(,(and (or 'funcall 'apply) callsym) ,fun . ,args) ;; These are not special forms but we treat them separately for the needs @@ -751,14 +741,13 @@ This function does not return anything but instead fills the (cconv-analyze-form (cadr (pop body-forms)) env)) (cconv--analyze-function vrs body-forms env form)) - (`(setq . ,forms) + (`(setq ,var ,expr) ;; If a local variable (member of env) is modified by setq then ;; it is a mutated variable. - (while forms - (let ((v (assq (car forms) env))) ; v = non nil if visible - (when v (setf (nth 2 v) t))) - (cconv-analyze-form (cadr forms) env) - (setq forms (cddr forms)))) + (let ((v (assq var env))) ; v = non nil if visible + (when v + (setf (nth 2 v) t))) + (cconv-analyze-form expr env)) (`((lambda . ,_) . ,_) ; First element is lambda expression. (byte-compile-warn-x diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index 51c6e8e0ca..bae303c213 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -369,6 +369,54 @@ Assumes the caller has bound `macroexpand-all-environment'." (macroexp--all-forms body)) (cdr form)) form))) + (`(setq ,(and var (pred symbolp) + (pred (not booleanp)) (pred (not keywordp))) + ,expr) + ;; Fast path for the setq common case. + (let ((new-expr (macroexp--expand-all expr))) + (if (eq new-expr expr) + form + `(,fn ,var ,new-expr)))) + (`(setq . ,args) + ;; Normalise to a sequence of (setq SYM EXPR). + ;; Malformed code is translated to code that signals an error + ;; at run time. + (let ((nargs (length args))) + (if (/= (logand nargs 1) 0) + (macroexp-warn-and-return + "odd number of arguments in `setq' form" + `(signal 'wrong-number-of-arguments '(setq ,nargs)) + nil 'compile-only fn) + (let ((assignments nil)) + (while (consp (cdr-safe args)) + (let* ((var (car args)) + (expr (cadr args)) + (new-expr (macroexp--expand-all expr)) + (assignment + (if (and (symbolp var) + (not (booleanp var)) (not (keywordp var))) + `(,fn ,var ,new-expr) + (macroexp-warn-and-return + (format-message "attempt to set %s `%s'" + (if (symbolp var) + "constant" + "non-variable") + var) + (cond + ((keywordp var) + ;; Accept `(setq :a :a)' for compatibility. + `(if (eq ,var ,new-expr) + ,var + (signal 'setting-constant (list ',var)))) + ((symbolp var) + `(signal 'setting-constant (list ',var))) + (t + `(signal 'wrong-type-argument + (list 'symbolp ',var)))) + nil 'compile-only var)))) + (push assignment assignments)) + (setq args (cddr args))) + (cons 'progn (nreverse assignments)))))) (`(,(and fun `(lambda . ,_)) . ,args) ;; Embedded lambda in function position. ;; If the byte-optimizer is loaded, try to unfold this, diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el new file mode 100644 index 0000000000..5a56913cd9 --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el @@ -0,0 +1,3 @@ +;;; -*- lexical-binding: t -*- +(defun foo () + (setq (a) nil)) diff --git a/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el new file mode 100644 index 0000000000..9ce80de08c --- /dev/null +++ b/test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el @@ -0,0 +1,3 @@ +;;; -*- lexical-binding: t -*- +(defun foo (a b) + (setq a 1 b)) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 27098d0bb1..9abc17a1c4 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -951,11 +951,17 @@ byte-compiled. Run with dynamic binding." "let-bind nonvariable") (bytecomp--define-warning-file-test "warn-variable-set-constant.el" - "variable reference to constant") + "attempt to set constant") (bytecomp--define-warning-file-test "warn-variable-set-nonvariable.el" "variable reference to nonvariable") +(bytecomp--define-warning-file-test "warn-variable-setq-nonvariable.el" + "attempt to set non-variable") + +(bytecomp--define-warning-file-test "warn-variable-setq-odd.el" + "odd number of arguments") + (bytecomp--define-warning-file-test "warn-wide-docstring-autoload.el" "autoload .foox. docstring wider than .* characters") commit 264472a507ea275476eef5a80ee630aa007434f1 Author: Eli Zaretskii Date: Tue Jun 14 20:27:12 2022 +0300 Handle W = NULL in 'update_redisplay_ticks' * src/xdisp.c (update_redisplay_ticks): If W == NULL, assume we are iterating the current buffer. diff --git a/src/xdisp.c b/src/xdisp.c index ae428f4b40..d14955af41 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -17179,7 +17179,11 @@ redisplay_window_1 (Lisp_Object window) means to initialize the tick count to zero. W can be NULL if TICKS is zero: that means unconditionally - re-initialize the current tick count to zero. */ + re-initialize the current tick count to zero. + + W can also be NULL if the caller doesn't know which window is being + processed by the display code. In that case, if TICKS is non-zero, + we assume it's the last window that shows the current buffer. */ void update_redisplay_ticks (int ticks, struct window *w) { @@ -17204,9 +17208,11 @@ update_redisplay_ticks (int ticks, struct window *w) the one used for the native tool bar). */ Lisp_Object contents = w ? w->contents : Qnil; char *bufname = - BUFFERP (contents) - ? SSDATA (BVAR (XBUFFER (contents), name)) - : (char *) ""; + NILP (contents) + ? SSDATA (BVAR (current_buffer, name)) + : (BUFFERP (contents) + ? SSDATA (BVAR (XBUFFER (contents), name)) + : (char *) ""); windows_or_buffers_changed = 177; error ("Window showing buffer %s takes too long to redisplay", bufname); commit 175bc8e5a53740432c844b5aae1981d4f47c96f7 Author: Juri Linkov Date: Tue Jun 14 19:35:02 2022 +0300 * lisp/replace.el (read-regexp): Use minibuffer-message in the minibuffer. diff --git a/lisp/replace.el b/lisp/replace.el index c9d41d3fa3..c5c24c7a36 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -968,10 +968,11 @@ respect this or not; see `read-regexp-case-fold-search'.)" 'inhibit-fold)))) 'inhibit-fold 'fold)) - (message "Case folding is now %s" - (if (eq case-fold 'fold) - "on" - "off")))) + (minibuffer-message + "Case folding is now %s" + (if (eq case-fold 'fold) + "on" + "off")))) nil (or history 'regexp-history) suggestions t)) (result (if (equal input "") ;; Return the default value when the user enters commit bd44f39d6d4900e406f87d6f4df1ee015dd21300 Author: Eli Zaretskii Date: Tue Jun 14 19:05:38 2022 +0300 Restart tick counting every command * src/keyboard.c (command_loop_1): Reinitialize the tick count before executing each command in the loop. * src/xdisp.c (update_redisplay_ticks): Be more defensive to W being NULL and to its buffer being nil. Set 'windows_or_buffers_changed' to avoid trusting stale window data like w->window_end_valid. diff --git a/src/keyboard.c b/src/keyboard.c index 55d710ed62..7d7dd2dba0 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -1501,6 +1501,11 @@ command_loop_1 (void) point_before_last_command_or_undo = PT; buffer_before_last_command_or_undo = current_buffer; + /* Restart our counting of redisplay ticks before + executing the command, so that we don't blame the new + command for the sins of the previous one. */ + update_redisplay_ticks (0, NULL); + call1 (Qcommand_execute, Vthis_command); #ifdef HAVE_WINDOW_SYSTEM diff --git a/src/xdisp.c b/src/xdisp.c index 27041cb162..ae428f4b40 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -17176,7 +17176,10 @@ redisplay_window_1 (Lisp_Object window) redisplay of the window takes "too long". TICKS is the amount of ticks to add to the W's current count; zero - means to initialize the count to zero. */ + means to initialize the tick count to zero. + + W can be NULL if TICKS is zero: that means unconditionally + re-initialize the current tick count to zero. */ void update_redisplay_ticks (int ticks, struct window *w) { @@ -17184,9 +17187,9 @@ update_redisplay_ticks (int ticks, struct window *w) static struct window *cwindow; static EMACS_INT window_ticks; - /* We only initialize the count if this is a different window. - Otherwise, this is a call from init_iterator for the same window - we tracked before, and we should keep the count. */ + /* We only initialize the count if this is a different window or + NULL. Otherwise, this is a call from init_iterator for the same + window we tracked before, and we should keep the count. */ if (!ticks && w != cwindow) { cwindow = w; @@ -17195,8 +17198,19 @@ update_redisplay_ticks (int ticks, struct window *w) if (ticks > 0) window_ticks += ticks; if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks) - error ("Window showing buffer %s takes too long to redisplay", - SSDATA (BVAR (XBUFFER (w->contents), name))); + { + /* In addition to a buffer, this could be a window (for non-leaf + windows, not expected here) or nil (for pseudo-windows like + the one used for the native tool bar). */ + Lisp_Object contents = w ? w->contents : Qnil; + char *bufname = + BUFFERP (contents) + ? SSDATA (BVAR (XBUFFER (contents), name)) + : (char *) ""; + + windows_or_buffers_changed = 177; + error ("Window showing buffer %s takes too long to redisplay", bufname); + } } commit d8f9cf7772f87ed3f34890c16e170260fa424e19 Author: Robert Pluim Date: Wed Jun 8 14:51:31 2022 +0200 Add more characters with macron in C-x 8 map and latin input methods * lisp/international/iso-transl.el (iso-transl-char-map): Add sequences for {AE,ae,G,g} with macron. * lisp/leim/quail/latin-post.el ("latin-postfix"): Add missing entries for {AE,ae,G,g} with macron. * lisp/leim/quail/latin-pre.el ("latin-prefix"): Add entries for 'letter with macron' for {A,a,E,e,AE,ae,I,I,O,o,U,u,Y,y} with macron. (Bug#55668) diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el index a14253ee58..417f0076ef 100644 --- a/lisp/international/iso-transl.el +++ b/lisp/international/iso-transl.el @@ -143,6 +143,10 @@ ("=a" . [?ā]) ("=E" . [?Ē]) ("=e" . [?ē]) + ("=/E" . [?Ǣ]) + ("=/e" . [?ǣ]) + ("=G" . [?Ḡ]) + ("=g" . [?ḡ]) ("=I" . [?Ī]) ("=i" . [?ī]) ("=O" . [?Ō]) diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el index 9573723e45..76ddf3c274 100644 --- a/lisp/leim/quail/latin-post.el +++ b/lisp/leim/quail/latin-post.el @@ -2239,6 +2239,7 @@ of characters from a single Latin-N charset. tilde | ~ | a~ -> ã cedilla | , | c, -> ç ogonek | , | a, -> ą + macron | - | a- -> ā g- -> ḡ e/- -> ǣ -- -> ¯ breve | ~ | a~ -> ă caron | ~ | c~ -> č dbl. acute | : | o: -> ő @@ -2256,7 +2257,7 @@ of characters from a single Latin-N charset. Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' " nil t nil nil nil nil nil nil nil nil t) -;; Fixme: ¦ § ¨ © ¬ ­ ¯ ± ´ µ ¶ · ¸ × ÷ +;; Fixme: ¦ § ¨ © ¬ ± ´ µ ¶ · ¸ × ÷ (quail-define-rules ("2/" ?½) ("3/" ?¾) @@ -2315,11 +2316,13 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("E-" ?Ē) ("E." ?Ė) ("E/" ?Æ) + ("E/-" ?Ǣ) ("E\"" ?Ë) ("E^" ?Ê) ("E`" ?È) ("E~" ?Ě) ("G," ?Ģ) + ("G-" ?Ḡ) ("G." ?Ġ) ("G^" ?Ĝ) ("G~" ?Ğ) @@ -2405,12 +2408,14 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("e-" ?ē) ("e." ?ė) ("e/" ?æ) + ("e/-" ?ǣ) ("e\"" ?ë) ("e^" ?ê) ("e`" ?è) ("e~" ?ě) ("e=" ?€) ("g," ?ģ) + ("g-" ?ḡ) ("g." ?ġ) ("g^" ?ĝ) ("g~" ?ğ) @@ -2475,6 +2480,7 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("z'" ?ź) ("z." ?ż) ("z~" ?ž) + ("--" ?¯) ("2//" ["2/"]) ("3//" ["3/"]) @@ -2530,11 +2536,13 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("E--" ["E-"]) ("E.." ["E."]) ("E//" ["E/"]) + ("E/--" ["E/-"]) ("E\"\"" ["E\""]) ("E^^" ["E^"]) ("E``" ["E`"]) ("E~~" ["E~"]) ("G,," ["G,"]) + ("G--" ["G-"]) ("G.." ["G."]) ("G^^" ["G^"]) ("G~~" ["G~"]) @@ -2613,12 +2621,14 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("e--" ["e-"]) ("e.." ["e."]) ("e//" ["e/"]) + ("e/--" ["e/-"]) ("e\"\"" ["e\""]) ("e^^" ["e^"]) ("e``" ["e`"]) ("e==" ["e="]) ("e~~" ["e~"]) ("g,," ["g,"]) + ("g--" ["g-"]) ("g.." ["g."]) ("g^^" ["g^"]) ("g~~" ["g~"]) @@ -2677,6 +2687,7 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("z''" ["z'"]) ("z.." ["z."]) ("z~~" ["z~"]) + ("---" ["--"]) ) ;; Derived from Slovenian.kmap from Yudit diff --git a/lisp/leim/quail/latin-pre.el b/lisp/leim/quail/latin-pre.el index d53da832be..48e0ce9efc 100644 --- a/lisp/leim/quail/latin-pre.el +++ b/lisp/leim/quail/latin-pre.el @@ -1104,6 +1104,7 @@ of characters from a single Latin-N charset. cedilla | , ~ | ,c -> ç ~c -> ç caron | ~ | ~c -> č ~g -> ğ breve | ~ | ~a -> ă + macron | - | -a -> ā -/e -> ǣ -- -> ¯ dot above | / . | /g -> ġ .g -> ġ misc | \" ~ / | \"s -> ß ~d -> ð ~t -> þ /a -> å /e -> æ /o -> ø symbol | ~ | ~> -> » ~< -> « ~! -> ¡ ~? -> ¿ ~~ -> ¸ @@ -1112,6 +1113,23 @@ of characters from a single Latin-N charset. " nil t nil nil nil nil nil nil nil nil t) (quail-define-rules + ("--" ?¯) + ("-A" ?Ā) + ("-a" ?ā) + ("-E" ?Ē) + ("-e" ?ē) + ("-/E" ?Ǣ) + ("-/e" ?ǣ) + ("-G" ?Ḡ) + ("-g" ?ḡ) + ("-I" ?Ī) + ("-i" ?ī) + ("-O" ?Ō) + ("-o" ?ō) + ("-U" ?Ū) + ("-u" ?ū) + ("-Y" ?Ȳ) + ("-y" ?ȳ) ("' " ?') ("''" ?´) ("'A" ?Á) commit b090dbdae802b72c6c6de60c61c8487539acf197 Author: Stephen Berman Date: Tue Jun 14 15:37:53 2022 +0200 Fix errors when aligning text in find-dired * lisp/find-dired.el (find-dired-filter): Don't error out while trying to align the text (by just removing that code) (bug#46218). diff --git a/lisp/find-dired.el b/lisp/find-dired.el index 8c1e684b7e..61e626080e 100644 --- a/lisp/find-dired.el +++ b/lisp/find-dired.el @@ -325,11 +325,7 @@ specifies what to use in place of \"-ls\" as the final argument." (save-restriction (widen) (let ((buffer-read-only nil) - (beg (point-max)) - (l-opt (and (consp find-ls-option) - (string-match "l" (cdr find-ls-option)))) - (ls-regexp (concat "^ +[^ \t\r\n]+\\( +[^ \t\r\n]+\\) +" - "[^ \t\r\n]+ +[^ \t\r\n]+\\( +[^[:space:]]+\\)"))) + (beg (point-max))) (goto-char beg) (insert string) (goto-char beg) @@ -344,18 +340,6 @@ specifies what to use in place of \"-ls\" as the final argument." (goto-char (- beg 3)) ; no error if < 0 (while (search-forward " ./" nil t) (delete-region (point) (- (point) 2))) - ;; Pad the number of links and file size. This is a - ;; quick and dirty way of getting the columns to line up - ;; most of the time, but it's not foolproof. - (when l-opt - (goto-char beg) - (goto-char (line-beginning-position)) - (while (re-search-forward ls-regexp nil t) - (replace-match (format "%4s" (match-string 1)) - nil nil nil 1) - (replace-match (format "%9s" (match-string 2)) - nil nil nil 2) - (forward-line 1))) ;; Find all the complete lines in the unprocessed ;; output and process it to add text properties. (goto-char (point-max)) commit 9225599ca73ce52f219f7e7c33676c5e740ae9a8 Author: Lars Ingebrigtsen Date: Tue Jun 14 15:24:19 2022 +0200 Make flymake-proc--delete-temp-directory slightly safer * lisp/progmodes/flymake-proc.el (flymake-proc--delete-temp-directory): Temp dir name may be abbreviatated, so expand it first (bug#46203). diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.el index eebfa70e34..4ab16831bc 100644 --- a/lisp/progmodes/flymake-proc.el +++ b/lisp/progmodes/flymake-proc.el @@ -903,7 +903,7 @@ can also be executed interactively independently of (defun flymake-proc--delete-temp-directory (dir-name) "Attempt to delete temp dir DIR-NAME, do not fail on error." - (let* ((temp-dir temporary-file-directory) + (let* ((temp-dir (file-truename temporary-file-directory)) (suffix (substring dir-name (1+ (length (directory-file-name temp-dir)))))) (while (> (length suffix) 0) commit 03124c42019401022e58ca9ebfa9b41735957ffb Author: Lars Ingebrigtsen Date: Tue Jun 14 15:01:44 2022 +0200 Fix .dir-local.el caching for symlinks * lisp/files.el (dir-locals-read-from-dir): We want the time stamp of the actual file, not the time stamp of the symlink (if .dir-locals.el is a symlink) (bug#46122). diff --git a/lisp/files.el b/lisp/files.el index 22fccb151c..a804f0088e 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -4497,7 +4497,7 @@ Return the new class name, which is a symbol named DIR." (with-demoted-errors "Error reading dir-locals: %S" (dolist (file files) (let ((file-time (file-attribute-modification-time - (file-attributes file)))) + (file-attributes (file-chase-links file))))) (if (time-less-p latest file-time) (setq latest file-time))) (with-temp-buffer commit a02bb84c80f63a7b1199f0e68d605f7d418167fd Author: Lars Ingebrigtsen Date: Tue Jun 14 14:38:05 2022 +0200 Leave the contents on the *Backtrace* buffer on `q' * lisp/emacs-lisp/debug.el (debug): Don't clear the contents of the buffer on `q' (bug#55863). diff --git a/etc/NEWS b/etc/NEWS index 73416fb30c..19ca21f666 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -997,6 +997,13 @@ inadvertently delete the "*scratch*" buffer. ** Debugging +--- +*** 'q' in a *Backtrace* buffer no longer clears the buffer. +Instead it just buries the buffer and switches the mode from +'debugger-mode' to 'backtrace-mode', since commands like 'e' are no +longer available after exiting the recursive edit. + ++++ *** New user option 'debug-allow-recursive-debug'. This user option controls whether the 'e' (in a "*Backtrace*" buffer or while edebugging) and 'C-x C-e' (while edebugging) commands diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el index 6c172d6c31..c4929eb2b0 100644 --- a/lisp/emacs-lisp/debug.el +++ b/lisp/emacs-lisp/debug.el @@ -305,16 +305,15 @@ the debugger will not be entered." (set-buffer debugger-old-buffer))) ;; Forget debugger window, it won't be back (Bug#17882). (setq debugger-previous-window nil)) - ;; Restore previous state of debugger-buffer in case we were - ;; in a recursive invocation of the debugger, otherwise just - ;; erase the buffer. + ;; Restore previous state of debugger-buffer in case we + ;; were in a recursive invocation of the debugger, + ;; otherwise just exit (after changing the mode, since we + ;; can't interact with the buffer in the same way). (when (buffer-live-p debugger-buffer) (with-current-buffer debugger-buffer (if debugger-previous-state (debugger--restore-buffer-state debugger-previous-state) - (setq backtrace-insert-header-function nil) - (setq backtrace-frames nil) - (backtrace-print)))) + (backtrace-mode)))) (with-timeout-unsuspend debugger-with-timeout-suspend) (set-match-data debugger-outer-match-data))) (setq debug-on-next-call debugger-step-after-exit) commit bea90d8de27e673a039a71e15a08bcb0cb6f7011 Author: Lars Ingebrigtsen Date: Tue Jun 14 14:26:58 2022 +0200 Fix gud parsing of empty jdb classpaths * lisp/progmodes/gud.el (gud-jdb-marker-filter): Parse empty classpaths (like classpath: []) correctly (bug#55957). diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el index 213ebef92f..26fecf9c9f 100644 --- a/lisp/progmodes/gud.el +++ b/lisp/progmodes/gud.el @@ -2460,7 +2460,7 @@ during jdb initialization depending on the value of ;; not supported/followed) (if (and gud-jdb-use-classpath (not gud-jdb-classpath-string) - (or (string-match "classpath:[ \t[]+\\([^]]+\\)" gud-marker-acc) + (or (string-match "classpath:[ \t[]+\\([^]]*\\)" gud-marker-acc) (string-match "-classpath[ \t\"]+\\([^ \"]+\\)" gud-marker-acc))) (setq gud-jdb-classpath (gud-jdb-parse-classpath-string commit 3e74cf65161841ee4a0a584fdbba8958372753f9 Author: Daniel Martín Date: Tue Jun 14 14:23:06 2022 +0200 Bind Cmd-t to menu-set-font on macOS * lisp/term/ns-win.el (global-map): set-frame-font asks for a font using the minibuffer, but the former ns-popup-font-panel always showed the graphical font panel on macOS. To preserve the same behavior, bind it to menu-set-font, which is also called by Options, Set Default Font (bug#55967). diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index 677ebb400e..84c5b087b9 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -142,7 +142,7 @@ The properties returned may include `top', `left', `height', and `width'." (define-key global-map [?\s-p] 'ns-print-buffer) (define-key global-map [?\s-q] 'save-buffers-kill-emacs) (define-key global-map [?\s-s] 'save-buffer) -(define-key global-map [?\s-t] 'set-frame-font) +(define-key global-map [?\s-t] 'menu-set-font) (define-key global-map [?\s-u] 'revert-buffer) (define-key global-map [?\s-v] 'yank) (define-key global-map [?\s-w] 'delete-frame) commit 441f081a643d6ad61208409fdcffe3a8a018f8ff Author: Lars Ingebrigtsen Date: Tue Jun 14 14:16:55 2022 +0200 Allow using alists in ido completion and hitting TAB * lisp/ido.el (ido-completion-help): Allow using an alist COMPLETIONS (bug#46091). diff --git a/lisp/ido.el b/lisp/ido.el index 73cd163d46..f970fce1ed 100644 --- a/lisp/ido.el +++ b/lisp/ido.el @@ -3976,23 +3976,30 @@ If `ido-change-word-sub' cannot be found in WORD, return nil." (setq display-it t)) (if (and ido-completion-buffer display-it) (with-output-to-temp-buffer ido-completion-buffer - (let ((completion-list (sort - (cond - (ido-directory-too-big - (message "Reading directory...") - (setq ido-directory-too-big nil - ido-ignored-list nil - ido-cur-list (ido-all-completions) - ido-rescan t) - (ido-set-matches) - (or ido-matches ido-cur-list)) - (ido-use-merged-list - (ido-flatten-merged-list (or ido-matches ido-cur-list))) - ((or full-list ido-completion-buffer-all-completions) - (ido-all-completions)) - (t - (copy-sequence (or ido-matches ido-cur-list)))) - #'ido-file-lessp))) + (let* ((comps + (cond + (ido-directory-too-big + (message "Reading directory...") + (setq ido-directory-too-big nil + ido-ignored-list nil + ido-cur-list (ido-all-completions) + ido-rescan t) + (ido-set-matches) + (or ido-matches ido-cur-list)) + (ido-use-merged-list + (ido-flatten-merged-list (or ido-matches ido-cur-list))) + ((or full-list ido-completion-buffer-all-completions) + (ido-all-completions)) + (t + (copy-sequence (or ido-matches ido-cur-list))))) + (completion-list + ;; If we have an alist COMPLETIONS, transform to a + ;; simple list first. + (sort (if (and (consp comps) + (consp (car comps))) + (mapcar #'car comps) + comps) + #'ido-file-lessp))) ;;(add-hook 'completion-setup-hook #'completion-setup-function) (display-completion-list completion-list)))))) commit 850050ca5c4873be9acafce7c9950c10d04d381d Author: Lars Ingebrigtsen Date: Tue Jun 14 13:56:07 2022 +0200 Revert "Clarify what a Calc registeri in in calc-insert-register" This reverts commit 73400e4002ce8fca060093548e6791b3a784eeaa. This has been fixed in Emacs 29 by making it possible to use regular registers in calc. diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el index 189ee0a244..8c6d3f51e5 100644 --- a/lisp/calc/calc-yank.el +++ b/lisp/calc/calc-yank.el @@ -301,10 +301,7 @@ Interactively, reads the register using `register-read-with-preview'." (defun calc-insert-register (register) "Insert the contents of register REGISTER. -Interactively, reads the register using `register-read-with-preview'. - -Note that this command only works with Calc registers, and they -have nothing to do with the Emacs-wide register mechanism." +Interactively, reads the register using `register-read-with-preview'." (interactive (list (register-read-with-preview "Insert register: "))) (if (eq major-mode 'calc-mode) (let ((val (calc-get-register register))) commit 706ef0ae932a68b8eca86678d0cc627854c25c15 Author: Lars Ingebrigtsen Date: Mon Jun 13 20:57:25 2022 +0200 Mention how to only get syntactic font locking in the manual * doc/lispref/modes.texi (Syntactic Font Lock): Note how to only get syntactic font locking (bug#46039). diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index ddcda661a0..4f40f35ff4 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -3665,6 +3665,10 @@ the value is @code{nil}, Font Lock will call @code{jit-lock-register} (@pxref{Other Font Lock Variables}) to set up for automatic refontification of buffer text following a modified line to reflect the new syntactic context due to the change. + +To use only syntactic fontification, this variable should +be non-@code{nil}, while @code{font-lock-keywords} should be set to +@code{nil} (@pxref{Font Lock Basics}). @end defvar @defvar font-lock-syntax-table commit 8fa1cdc1faf901f45554e97843efd1f01adc2e92 Author: Po Lu Date: Tue Jun 14 19:49:58 2022 +0800 ; Improve doc of `x-dnd-native-test-function' * src/xterm.c (syms_of_xterm): Improve doc. Suggested by Eli Zaretskii . diff --git a/src/xterm.c b/src/xterm.c index 333520c8bc..2cc17b455d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -27365,13 +27365,15 @@ argument to `x-begin-drag'. */); Vx_dnd_targets_list = Qnil; DEFVAR_LISP ("x-dnd-native-test-function", Vx_dnd_native_test_function, - doc: /* Function called to determine return when dropping on Emacs itself. -It should accept two arguments POS and ACTION, and return a symbol -describing what to return from `x-begin-drag'. POS is a mouse -position list detailing the location of the drop, and ACTION is the -action specified by the caller of `x-begin-drag'. - -If nil or a non-symbol value is returned, the drop will be -cancelled. */); + doc: /* Function that determines return value of drag-and-drop on Emacs frames. +If the value is a function, `x-begin-drag' will call it with two +arguments, POS and ACTION, where POS is a mouse position list +that specifies the location of the drop, and ACTION is the +action specified by the caller of `x-begin-drag'. The function +should return a symbol describing what to return from +`x-begin-drag' if the drop happens on an Emacs frame. + +If the value is nil, or the function returns a value that is not +a symbol, a drop on an Emacs frame will be canceled. */); Vx_dnd_native_test_function = Qnil; } commit fda5cccba8d1d0ef50894576ba9372711b176c22 Author: Michael Albinus Date: Tue Jun 14 13:04:34 2022 +0200 Fix Tramp problem with non-essential * lisp/net/tramp.el (tramp-run-real-handler): Handle also functions which use a `tramp-file-name' for the file name handler. (Bug#55832) (tramp-get-home-directory, tramp-get-remote-uid) (tramp-get-remote-gid): VEC can also be nil. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 27c6dfde33..cee8897b4f 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -2526,6 +2526,7 @@ arguments to pass to the OPERATION." ,(and (eq inhibit-file-name-operation operation) inhibit-file-name-handlers))) (inhibit-file-name-operation operation) + (args (if (tramp-file-name-p (car args)) (cons nil (cdr args)) args)) signal-hook-function) (apply operation args))) @@ -2708,6 +2709,7 @@ Fall back to normal file name handler if no Tramp file name handler exists." (tramp-message v 5 "Non-essential received in operation %s" (cons operation args)) + (let ((tramp-verbose 10)) (tramp-backtrace v)) (tramp-run-real-handler operation args)) ((eq result 'suppress) (let ((inhibit-message t)) @@ -2952,7 +2954,7 @@ not in completion mode." (m (tramp-find-method method user host)) all-user-hosts) - (unless localname ;; Nothing to complete. + (unless localname ;; Nothing to complete. (if (or user host) @@ -5746,26 +5748,29 @@ be granted." If USER is a string, return its home directory instead of the user identified by VEC. If there is no user specified in either VEC or USER, or if there is no home directory, return nil." - (with-tramp-connection-property vec (concat "~" user) - (tramp-file-name-handler #'tramp-get-home-directory vec user))) + (and (tramp-file-name-p vec) + (with-tramp-connection-property vec (concat "~" user) + (tramp-file-name-handler #'tramp-get-home-directory vec user)))) (defun tramp-get-remote-uid (vec id-format) "The uid of the remote connection VEC, in ID-FORMAT. ID-FORMAT valid values are `string' and `integer'." - (with-tramp-connection-property vec (format "uid-%s" id-format) - (or (tramp-file-name-handler #'tramp-get-remote-uid vec id-format) - ;; Ensure there is a valid result. - (and (equal id-format 'integer) tramp-unknown-id-integer) - (and (equal id-format 'string) tramp-unknown-id-string)))) + (or (and (tramp-file-name-p vec) + (with-tramp-connection-property vec (format "uid-%s" id-format) + (tramp-file-name-handler #'tramp-get-remote-uid vec id-format))) + ;; Ensure there is a valid result. + (and (equal id-format 'integer) tramp-unknown-id-integer) + (and (equal id-format 'string) tramp-unknown-id-string))) (defun tramp-get-remote-gid (vec id-format) "The gid of the remote connection VEC, in ID-FORMAT. ID-FORMAT valid values are `string' and `integer'." - (with-tramp-connection-property vec (format "gid-%s" id-format) - (or (tramp-file-name-handler #'tramp-get-remote-gid vec id-format) - ;; Ensure there is a valid result. - (and (equal id-format 'integer) tramp-unknown-id-integer) - (and (equal id-format 'string) tramp-unknown-id-string)))) + (or (and (tramp-file-name-p vec) + (with-tramp-connection-property vec (format "gid-%s" id-format) + (tramp-file-name-handler #'tramp-get-remote-gid vec id-format))) + ;; Ensure there is a valid result. + (and (equal id-format 'integer) tramp-unknown-id-integer) + (and (equal id-format 'string) tramp-unknown-id-string))) (defun tramp-local-host-p (vec) "Return t if this points to the local host, nil otherwise. commit 9fb80aee176f6d5dc8fd33b63880b11a99a19657 Author: Mattias Engdegård Date: Tue Jun 14 12:08:15 2022 +0200 ; * lisp/emacs-lisp/cconv.el: Fix outdated comments. diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index 4535f1aa6e..1a501f50bf 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el @@ -25,21 +25,20 @@ ;;; Commentary: ;; This takes a piece of Elisp code, and eliminates all free variables from -;; lambda expressions. The user entry points are cconv-closure-convert and -;; cconv-closure-convert-toplevel (for toplevel forms). +;; lambda expressions. The user entry point is `cconv-closure-convert'. ;; All macros should be expanded beforehand. ;; ;; Here is a brief explanation how this code works. -;; Firstly, we analyze the tree by calling cconv-analyze-form. +;; Firstly, we analyze the tree by calling `cconv-analyze-form'. ;; This function finds all mutated variables, all functions that are suitable ;; for lambda lifting and all variables captured by closure. It passes the tree ;; once, returning a list of three lists. ;; ;; Then we calculate the intersection of the first and third lists returned by -;; cconv-analyze form to find all mutated variables that are captured by +;; `cconv-analyze-form' to find all mutated variables that are captured by ;; closure. -;; Armed with this data, we call cconv-closure-convert-rec, that rewrites the +;; Armed with this data, we call `cconv-convert', that rewrites the ;; tree recursively, lifting lambdas where possible, building closures where it ;; is needed and eliminating mutable variables used in closure. ;; @@ -141,11 +140,9 @@ is less than this number.") ;;;###autoload (defun cconv-closure-convert (form) "Main entry point for closure conversion. --- FORM is a piece of Elisp code after macroexpansion. --- TOPLEVEL(optional) is a boolean variable, true if we are at the root of AST +FORM is a piece of Elisp code after macroexpansion. Returns a form where all lambdas don't have any free variables." - ;; (message "Entering cconv-closure-convert...") (let ((cconv-freevars-alist '()) (cconv-var-classification '())) ;; Analyze form - fill these variables with new information. commit 18a1c7de2e4278493a4ff6dff6add310869b5070 Author: Po Lu Date: Tue Jun 14 17:43:08 2022 +0800 Fix mishandling of dnd-scroll-margin with scroll bar motion * lisp/dnd.el (dnd-handle-movement): Ignore posns inside scroll bars for now. diff --git a/lisp/dnd.el b/lisp/dnd.el index 7eb43f5baa..9d72a4b595 100644 --- a/lisp/dnd.el +++ b/lisp/dnd.el @@ -112,7 +112,9 @@ program." "Handle mouse movement to POSN when receiving a drop from another program." (when (windowp (posn-window posn)) (with-selected-window (posn-window posn) - (when dnd-scroll-margin + (when (and dnd-scroll-margin + ;; TODO: handle scroll bars reasonably. + (not (posn-area posn))) (ignore-errors (let* ((row (cdr (posn-col-row posn))) (window (when (windowp (posn-window posn)) commit 99cb3a7154cd1e1b751b7cdf84479cd850e7da17 Author: Juri Linkov Date: Tue Jun 14 10:14:52 2022 +0300 * lisp/minibuffer.el (minibuffer-complete-history): New command. (minibuffer-complete-defaults): New command. https://lists.gnu.org/archive/html/emacs-devel/2022-06/msg00498.html diff --git a/etc/NEWS b/etc/NEWS index eb4c6956b8..73416fb30c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1090,6 +1090,12 @@ to complete. The value 'visual' is like 'always', but only updates the completions if they are already visible. The default value 't' always hides the completion buffer after some completion is made. +*** New commands to complete the minibuffer history. +'minibuffer-complete-history' ('C-x up') is like 'minibuffer-complete' +but completes on the history items instead of the default completion +table. 'minibuffer-complete-defaults' ('C-x down') completes +on the list of default items. + +++ *** New user option 'completions-sort'. This option controls the sorting of the completion candidates in diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index bf89874ecc..7d589c0174 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -4425,6 +4425,36 @@ minibuffer, but don't quit the completions window." (let ((completion-use-base-affixes t)) (choose-completion nil no-exit no-quit)))) +(defun minibuffer-complete-history () + "Complete the minibuffer history as far as possible. +Like `minibuffer-complete' but completes on the history items +instead of the default completion table." + (interactive) + (let ((completions-sort nil) + (history (mapcar (lambda (h) + ;; Support e.g. `C-x ESC ESC TAB' as + ;; a replacement of `list-command-history' + (if (consp h) (format "%S" h) h)) + (symbol-value minibuffer-history-variable)))) + (completion-in-region (minibuffer--completion-prompt-end) (point-max) + history nil))) + +(defun minibuffer-complete-defaults () + "Complete minibuffer defaults as far as possible. +Like `minibuffer-complete' but completes on the default items +instead of the completion table." + (interactive) + (let ((completions-sort nil)) + (when (and (not minibuffer-default-add-done) + (functionp minibuffer-default-add-function)) + (setq minibuffer-default-add-done t + minibuffer-default (funcall minibuffer-default-add-function))) + (completion-in-region (minibuffer--completion-prompt-end) (point-max) + (ensure-list minibuffer-default) nil))) + +(define-key minibuffer-local-map [?\C-x up] 'minibuffer-complete-history) +(define-key minibuffer-local-map [?\C-x down] 'minibuffer-complete-defaults) + (defcustom minibuffer-default-prompt-format " (default %s)" "Format string used to output \"default\" values. When prompting for input, there will often be a default value, commit e494222814585cffaafa2c7784a2e4d632b8cd2d Author: Juri Linkov Date: Tue Jun 14 10:04:56 2022 +0300 * lisp/simple.el (completion-auto-wrap): Rename from completion-wrap-movement. (next-completion): Use completion-auto-wrap. https://lists.gnu.org/archive/html/emacs-devel/2022-06/msg00139.html diff --git a/etc/NEWS b/etc/NEWS index 1b8560a923..eb4c6956b8 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1076,17 +1076,11 @@ To enable this behavior, customize the user option the second one will switch to the "*Completions*" buffer. --- -*** New user option 'completion-wrap-movement'. +*** New user option 'completion-auto-wrap'. When non-nil, the commands 'next-completion' and 'previous-completion' automatically wrap around on reaching the beginning or the end of the "*Completions*" buffer. -+++ -*** New user option 'completions-sort'. -This option controls the sorting of the completion candidates in -the "*Completions*" buffer. Available styles are no sorting, -alphabetical (the default), or a custom sort function. - +++ *** New values for the 'completion-auto-help' user option. There are two new values to control the way the "*Completions*" buffer @@ -1096,6 +1090,12 @@ to complete. The value 'visual' is like 'always', but only updates the completions if they are already visible. The default value 't' always hides the completion buffer after some completion is made. ++++ +*** New user option 'completions-sort'. +This option controls the sorting of the completion candidates in +the "*Completions*" buffer. Available styles are no sorting, +alphabetical (the default), or a custom sort function. + +++ *** New user option 'completions-max-height'. This option limits the height of the "*Completions*" buffer. diff --git a/lisp/simple.el b/lisp/simple.el index 05a0855a96..99c951b24b 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -9502,10 +9502,10 @@ Go to the window from which completion was requested." (if (get-buffer-window buf) (select-window (get-buffer-window buf)))))) -(defcustom completion-wrap-movement t +(defcustom completion-auto-wrap t "Non-nil means to wrap around when selecting completion options. -This affects the commands `next-completion' and -`previous-completion'." +This affects the commands `next-completion' and `previous-completion'. +When `completion-auto-select' is t, it wraps through the minibuffer." :type 'boolean :version "29.1" :group 'completion) @@ -9549,7 +9549,7 @@ the completions is popped up and down." With prefix argument N, move back N items (negative N means move forward). -Also see the `completion-wrap-movement' variable." +Also see the `completion-auto-wrap' variable." (interactive "p") (next-completion (- n))) @@ -9558,7 +9558,7 @@ Also see the `completion-wrap-movement' variable." With prefix argument N, move N items (negative N means move backward). -Also see the `completion-wrap-movement' variable." +Also see the `completion-auto-wrap' variable." (interactive "p") (let ((tabcommand (member (this-command-keys) '("\t" [backtab]))) pos) @@ -9574,7 +9574,7 @@ Also see the `completion-wrap-movement' variable." (goto-char pos) ;; If at the last completion option, wrap or skip ;; to the minibuffer, if requested. - (when completion-wrap-movement + (when completion-auto-wrap (if (and (eq completion-auto-select t) tabcommand (minibufferp completion-reference-buffer)) (throw 'bound nil) @@ -9598,7 +9598,7 @@ Also see the `completion-wrap-movement' variable." (point) 'mouse-face nil (point-min))))) ;; If at the first completion option, wrap or skip ;; to the minibuffer, if requested. - (when completion-wrap-movement + (when completion-auto-wrap (if (and (eq completion-auto-select t) tabcommand (minibufferp completion-reference-buffer)) (progn diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el index 56db00a124..ec93c8f42a 100644 --- a/test/lisp/minibuffer-tests.el +++ b/test/lisp/minibuffer-tests.el @@ -383,7 +383,7 @@ (should (eq (current-buffer) (get-buffer "*Completions*")))))) (ert-deftest completion-auto-wrap-test () - (let ((completion-wrap-movement nil)) + (let ((completion-auto-wrap nil)) (completing-read-with-minibuffer-setup '("aa" "ab" "ac") (insert "a") @@ -397,7 +397,7 @@ (should (equal "ac" (get-text-property (point) 'completion--string))) (previous-completion 5) (should (equal "aa" (get-text-property (point) 'completion--string))))) - (let ((completion-wrap-movement t)) + (let ((completion-auto-wrap t)) (completing-read-with-minibuffer-setup '("aa" "ab" "ac") (insert "a") @@ -453,11 +453,11 @@ (switch-to-completions) (should (equal 'highlight (get-text-property (point) 'mouse-face))) (should (equal "aa" (get-text-property (point) 'completion--string))) - (let ((completion-wrap-movement t)) + (let ((completion-auto-wrap t)) (next-completion 3)) (should (equal 'highlight (get-text-property (point) 'mouse-face))) (should (equal "aa" (get-text-property (point) 'completion--string))) - (let ((completion-wrap-movement nil)) + (let ((completion-auto-wrap nil)) (next-completion 3)) (should (equal 'highlight (get-text-property (point) 'mouse-face))) (should (equal "ac" (get-text-property (point) 'completion--string))) commit 42203acd60d03feceafccbd8a63a17744ff36a36 Author: Po Lu Date: Tue Jun 14 14:06:59 2022 +0800 Fix out of date parts in NS doc and keyboard bindings * doc/emacs/macos.texi (Mac / GNUstep Events): Remove `ns-drag-n-drop' which doesn't exist anymore. Add events to concept index and document `ns-show-prefs'. (bug#55940) * lisp/term/ns-win.el (global-map): Remove ns-popup-font-panel. diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi index 37f48619d1..d7c432d420 100644 --- a/doc/emacs/macos.texi +++ b/doc/emacs/macos.texi @@ -223,6 +223,7 @@ keystrokes. Here is a list of these events. @table @key @item ns-open-file +@cindex ns-open-file event @vindex ns-pop-up-frames This event occurs when another Nextstep application requests that Emacs open a file. A typical reason for this would be a user @@ -239,44 +240,29 @@ means to always visit the file in a new frame. A value of @code{nil} means to always visit the file in the selected frame. @item ns-open-temp-file +@cindex ns-open-temp-file event This event occurs when another application requests that Emacs open a temporary file. By default, this is handled by just generating a @code{ns-open-file} event, the results of which are described above. @item ns-open-file-line +@cindex ns-open-file-line event Some applications, such as ProjectBuilder and gdb, request not only a particular file, but also a particular line or sequence of lines in the file. Emacs handles this by visiting that file and highlighting the requested line (@code{ns-open-file-select-line}). -@item ns-drag-n-drop -This event occurs when a user drags an object from another application -into an Emacs frame. The default behavior is to open a file in the -window under the mouse, or to insert text at point of the window under -the mouse. - -The sending application has some limited ability to decide how Emacs -handles the sent object, but the user may override the default -behavior by holding one or more modifier key. - -@table @kbd -@item control -Insert as text in the current buffer. If the object is a file, this -will insert the filename. -@item alt/option -Attempt to open the object as though it is a file or URL. -@item super/command -Perform the default action for the type. This can be useful when an -application is overriding the default behavior. -@end table - -The modifier keys listed above are defined by macOS and are unaffected -by user changes to the modifiers in Emacs. - @item ns-power-off +@cindex ns-power-off event This event occurs when the user logs out and Emacs is still running, or when ``Quit Emacs'' is chosen from the application menu. The default behavior is to save all file-visiting buffers. + +@item ns-show-prefs +@cindex ns-show-prefs event +This event occurs when the user selects ``Preferences'' from the +application menu. By default, it is bound to the command +@code{customize}. @end table @cindex using Nextstep services (macOS) diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index ac1007f94f..677ebb400e 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -142,7 +142,7 @@ The properties returned may include `top', `left', `height', and `width'." (define-key global-map [?\s-p] 'ns-print-buffer) (define-key global-map [?\s-q] 'save-buffers-kill-emacs) (define-key global-map [?\s-s] 'save-buffer) -(define-key global-map [?\s-t] 'ns-popup-font-panel) +(define-key global-map [?\s-t] 'set-frame-font) (define-key global-map [?\s-u] 'revert-buffer) (define-key global-map [?\s-v] 'yank) (define-key global-map [?\s-w] 'delete-frame) commit 82ce218394e8e35cbea9eb4d17d67720161b6475 Author: Po Lu Date: Tue Jun 14 13:52:38 2022 +0800 Handle coordinates of Motif drop start messages * src/xterm.c (xm_read_drop_start_message): New function. (xm_read_drag_motion_message): Check that the originator is correct. (x_coords_from_dnd_message): Read drop start messages as well. diff --git a/src/xterm.c b/src/xterm.c index 443c589e3b..333520c8bc 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2339,6 +2339,44 @@ xm_read_drop_start_reply (const XEvent *msg, xm_drop_start_reply *reply) return 0; } +static int +xm_read_drop_start_message (const XEvent *msg, + xm_drop_start_message *dmsg) +{ + const uint8_t *data; + + data = (const uint8_t *) &msg->xclient.data.b[0]; + + if ((XM_DRAG_REASON_ORIGINATOR (data[0]) + != XM_DRAG_ORIGINATOR_INITIATOR) + || (XM_DRAG_REASON_CODE (data[0]) + != XM_DRAG_REASON_DROP_START)) + return 1; + + dmsg->reason = *(data++); + dmsg->byte_order = *(data++); + dmsg->side_effects = *(uint16_t *) data; + dmsg->timestamp = *(uint32_t *) (data + 2); + dmsg->x = *(uint16_t *) (data + 6); + dmsg->y = *(uint16_t *) (data + 8); + dmsg->index_atom = *(uint32_t *) (data + 10); + dmsg->source_window = *(uint32_t *) (data + 14); + + if (dmsg->byte_order != XM_BYTE_ORDER_CUR_FIRST) + { + SWAPCARD16 (dmsg->side_effects); + SWAPCARD32 (dmsg->timestamp); + SWAPCARD16 (dmsg->x); + SWAPCARD16 (dmsg->y); + SWAPCARD32 (dmsg->index_atom); + SWAPCARD32 (dmsg->source_window); + } + + dmsg->byte_order = XM_BYTE_ORDER_CUR_FIRST; + + return 0; +} + static int xm_read_drag_receiver_info (struct x_display_info *dpyinfo, Window wdesc, xm_drag_receiver_info *rec) @@ -2395,7 +2433,7 @@ xm_read_drag_receiver_info (struct x_display_info *dpyinfo, return !rc; } -static void +static int xm_read_drag_motion_message (const XEvent *msg, xm_drag_motion_message *dmsg) { @@ -2403,6 +2441,12 @@ xm_read_drag_motion_message (const XEvent *msg, data = (const uint8_t *) &msg->xclient.data.b[0]; + if ((XM_DRAG_REASON_CODE (data[0]) + != XM_DRAG_REASON_DRAG_MOTION) + || (XM_DRAG_REASON_ORIGINATOR (data[0]) + != XM_DRAG_ORIGINATOR_INITIATOR)) + return 1; + dmsg->reason = *(data++); dmsg->byteorder = *(data++); dmsg->side_effects = *(uint16_t *) data; @@ -2417,6 +2461,10 @@ xm_read_drag_motion_message (const XEvent *msg, SWAPCARD16 (dmsg->x); SWAPCARD16 (dmsg->y); } + + dmsg->byteorder = XM_BYTE_ORDER_CUR_FIRST; + + return 0; } static void @@ -15794,6 +15842,8 @@ x_coords_from_dnd_message (struct x_display_info *dpyinfo, XEvent *event, int *x_out, int *y_out) { xm_drag_motion_message dmsg; + xm_drop_start_message smsg; + xm_drop_start_reply reply; if (event->type != ClientMessage) return false; @@ -15814,13 +15864,25 @@ x_coords_from_dnd_message (struct x_display_info *dpyinfo, == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE) && event->xclient.format == 8) { - if (event->xclient.data.b[0] - == XM_DRAG_REASON_DRAG_MOTION) + if (!xm_read_drag_motion_message (event, &dmsg)) { - xm_read_drag_motion_message (event, &dmsg); *x_out = dmsg.x; *y_out = dmsg.y; + return true; + } + else if (!xm_read_drop_start_message (event, &smsg)) + { + *x_out = smsg.x; + *y_out = smsg.y; + + return true; + } + else if (!xm_read_drop_start_reply (event, &reply)) + { + *x_out = reply.better_x; + *y_out = reply.better_y; + return true; } } commit 6fd33fbf6a4edf0b905cf1a01bb763e89b860339 Merge: f5fb969cab 73400e4002 Author: Stefan Kangas Date: Tue Jun 14 06:30:43 2022 +0200 Merge from origin/emacs-28 73400e4002 Clarify what a Calc registeri in in calc-insert-register commit f5fb969cab48228d612d641f1ba5fd123f50cf86 Author: Po Lu Date: Tue Jun 14 10:12:48 2022 +0800 Handle coordinate extraction for more event types * src/xterm.c (xm_read_drag_motion_message): New function. (x_coords_from_dnd_message): Handle XM_DRAG_REASON_DRAG_MOTION. diff --git a/src/xterm.c b/src/xterm.c index d79871e021..443c589e3b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2395,6 +2395,30 @@ xm_read_drag_receiver_info (struct x_display_info *dpyinfo, return !rc; } +static void +xm_read_drag_motion_message (const XEvent *msg, + xm_drag_motion_message *dmsg) +{ + const uint8_t *data; + + data = (const uint8_t *) &msg->xclient.data.b[0]; + + dmsg->reason = *(data++); + dmsg->byteorder = *(data++); + dmsg->side_effects = *(uint16_t *) data; + dmsg->timestamp = *(uint32_t *) (data + 2); + dmsg->x = *(uint16_t *) (data + 6); + dmsg->y = *(uint16_t *) (data + 8); + + if (dmsg->byteorder != XM_BYTE_ORDER_CUR_FIRST) + { + SWAPCARD16 (dmsg->side_effects); + SWAPCARD32 (dmsg->timestamp); + SWAPCARD16 (dmsg->x); + SWAPCARD16 (dmsg->y); + } +} + static void x_dnd_send_xm_leave_for_drop (struct x_display_info *dpyinfo, struct frame *f, Window wdesc, @@ -15769,6 +15793,8 @@ static bool x_coords_from_dnd_message (struct x_display_info *dpyinfo, XEvent *event, int *x_out, int *y_out) { + xm_drag_motion_message dmsg; + if (event->type != ClientMessage) return false; @@ -15784,6 +15810,21 @@ x_coords_from_dnd_message (struct x_display_info *dpyinfo, return true; } + if ((event->xclient.message_type + == dpyinfo->Xatom_MOTIF_DRAG_AND_DROP_MESSAGE) + && event->xclient.format == 8) + { + if (event->xclient.data.b[0] + == XM_DRAG_REASON_DRAG_MOTION) + { + xm_read_drag_motion_message (event, &dmsg); + *x_out = dmsg.x; + *y_out = dmsg.y; + + return true; + } + } + return false; } commit 907f3a4f8d83c228a3be3772a3cb7d5079261752 Author: Po Lu Date: Tue Jun 14 09:41:59 2022 +0800 Use coordinates provided by DND messages if available This avoids an extra sync, which matters when dropping onto Emacs running over a slow connection. * src/xselect.c (x_handle_dnd_message): New args `root_window_coords', `root_x' and `root_y'. * src/xterm.c (x_coords_from_dnd_message): New function. (handle_one_xevent): Pass root window coordinates to x_handle_dnd_message. * src/xterm.h: Update prototypes. diff --git a/src/xselect.c b/src/xselect.c index 490a008dfc..96c1e9830f 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -2522,7 +2522,8 @@ FRAME is on. If FRAME is nil, the selected frame is used. */) bool x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, - struct x_display_info *dpyinfo, struct input_event *bufp) + struct x_display_info *dpyinfo, struct input_event *bufp, + bool root_window_coords, int root_x, int root_y) { Lisp_Object vec; Lisp_Object frame; @@ -2532,6 +2533,7 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, unsigned char *data = (unsigned char *) event->data.b; int idata[5]; ptrdiff_t i; + Window child_return; for (i = 0; i < dpyinfo->x_dnd_atoms_length; ++i) if (dpyinfo->x_dnd_atoms[i] == event->message_type) break; @@ -2563,7 +2565,15 @@ x_handle_dnd_message (struct frame *f, const XClientMessageEvent *event, event->format, size)); - x_relative_mouse_position (f, &x, &y); + if (!root_window_coords) + x_relative_mouse_position (f, &x, &y); + else + XTranslateCoordinates (dpyinfo->display, + dpyinfo->root_window, + FRAME_X_WINDOW (f), + root_x, root_y, + &x, &y, &child_return); + bufp->kind = DRAG_N_DROP_EVENT; bufp->frame_or_window = frame; bufp->timestamp = CurrentTime; diff --git a/src/xterm.c b/src/xterm.c index d9dd29ca12..d79871e021 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15762,6 +15762,31 @@ x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data) } #endif +/* Extract the root window coordinates from the client message EVENT + if it is a message that we already understand. Return false if the + event was not understood. */ +static bool +x_coords_from_dnd_message (struct x_display_info *dpyinfo, + XEvent *event, int *x_out, int *y_out) +{ + if (event->type != ClientMessage) + return false; + + if (event->xclient.message_type == dpyinfo->Xatom_XdndPosition) + { + if (event->xclient.format != 32) + return false; + + *x_out = (((unsigned long) event->xclient.data.l[2]) >> 16 + & 0xffff); + *y_out = (event->xclient.data.l[2] & 0xffff); + + return true; + } + + return false; +} + /* Handles the XEvent EVENT on display DPYINFO. *FINISH is X_EVENT_GOTO_OUT if caller should stop reading events. @@ -15804,6 +15829,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, GdkEvent *copy = NULL; GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display); #endif + int dx, dy; USE_SAFE_ALLOCA; *finish = X_EVENT_NORMAL; @@ -15835,6 +15861,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, { case ClientMessage: { + int rc; + if (x_dnd_in_progress && FRAME_DISPLAY_INFO (x_dnd_frame) == dpyinfo && event->xclient.message_type == dpyinfo->Xatom_XdndStatus) @@ -16211,7 +16239,17 @@ handle_one_xevent (struct x_display_info *dpyinfo, f = any; if (!f) goto OTHER; - if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie)) + + /* These values are always used initialized, but GCC doesn't + know that. */ + dx = 0; + dy = 0; + + rc = x_coords_from_dnd_message (dpyinfo, (XEvent *) event, + &dx, &dy); + + if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie, + rc, dx, dy)) *finish = X_EVENT_DROP; } break; diff --git a/src/xterm.h b/src/xterm.h index 25c2453ee7..82b4308041 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1540,7 +1540,8 @@ extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom); extern bool x_handle_dnd_message (struct frame *, const XClientMessageEvent *, struct x_display_info *, - struct input_event *); + struct input_event *, + bool, int, int); extern int x_check_property_data (Lisp_Object); extern void x_fill_property_data (Display *, Lisp_Object, commit 915b34d2800fe0014b12eda0bbf5def976c14c32 Author: Dmitry Gutov Date: Tue Jun 14 04:00:22 2022 +0300 project--git-submodules: Parse more strictly * lisp/progmodes/project.el (project--git-submodules): Don't mistake 'load-path' for 'path' (bug#55396). diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 859ad2e047..f4d6742ed8 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -599,7 +599,7 @@ backend implementation of `project-external-roots'.") (insert-file-contents ".gitmodules") (let (res) (goto-char (point-min)) - (while (re-search-forward "path *= *\\(.+\\)" nil t) + (while (re-search-forward "^[ \t]*path *= *\\(.+\\)" nil t) (push (match-string 1) res)) (nreverse res))) (file-missing nil))) commit 5678829a62752eb332caef3abebeb64cb0722708 Author: Paul Eggert Date: Mon Jun 13 14:25:58 2022 -0700 Default decoded-time dst slot to -1 * lisp/simple.el (decoded-time): Default dst slot to -1. Improve related doc strings. diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el index 40374c3bb4..d19134db83 100644 --- a/lisp/calendar/time-date.el +++ b/lisp/calendar/time-date.el @@ -557,7 +557,8 @@ changes in daylight saving time are not taken into account." (list second minute hour day month year nil dst zone)) (defun decoded-time-set-defaults (time &optional default-zone) - "Set any nil values in `decoded-time' TIME to default values. + "Set most nil values in `decoded-time' TIME to default values. +This can set TIME's year, month, day, hour, minute and second. The default value is based on January 1st, 1970 at midnight. This year is used to guarantee portability; see Info node `(elisp) Time of Day'. diff --git a/lisp/simple.el b/lisp/simple.el index f6932339c9..05a0855a96 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -10511,10 +10511,10 @@ This is an integer between 1 and 12 (inclusive). January is 1.") (year nil :documentation "This is a four digit integer.") (weekday nil :documentation "\ This is a number between 0 and 6, and 0 is Sunday.") - (dst nil :documentation "\ + (dst -1 :documentation "\ This is t if daylight saving time is in effect, nil if it is not -in effect, and -1 if daylight saving information is not -available.") +in effect, and -1 if daylight saving information is not available. +Also see `decoded-time-dst'.") (zone nil :documentation "\ This is an integer indicating the UTC offset in seconds, i.e., the number of seconds east of Greenwich.") @@ -10524,9 +10524,13 @@ the number of seconds east of Greenwich.") ;; It should return -1 indicating unknown DST, but currently returns ;; nil indicating standard time. (put 'decoded-time-dst 'function-documentation - (append (get 'decoded-time-dst 'function-documentation) - "As a special case, `decoded-time-dst' returns an unspecified -value when given a list too short to have a dst element.")) + "Access slot \"dst\" of `decoded-time' struct CL-X. +This is t if daylight saving time is in effect, nil if it is not +in effect, and -1 if daylight saving information is not available. +As a special case, return an unspecified value when given a list +too short to have a dst element. + +(fn CL-X)") (defun get-scratch-buffer-create () "Return the *scratch* buffer, creating a new one if needed." commit 24b2cc177acd47fdac15db1fa73afbc412eb1e0a Author: Paul Eggert Date: Mon Jun 13 13:37:37 2022 -0700 Pacify GCC 12.1.1 -Wanalyzer-use-of-uninitialized-value * src/xfont.c (xfont_list_pattern): Initialize a local. Although I’m not sure this is needed, it doesn’t change behavior (except possibly to make undefined behavior defined). diff --git a/src/xfont.c b/src/xfont.c index 684c28ab21..74237e8aa8 100644 --- a/src/xfont.c +++ b/src/xfont.c @@ -295,7 +295,7 @@ xfont_list_pattern (Display *display, const char *pattern, { Lisp_Object list = Qnil; Lisp_Object chars = Qnil; - struct charset *encoding, *repertory = NULL; + struct charset *encoding = NULL, *repertory = NULL; int i, limit, num_fonts; char **names; /* Large enough to decode the longest XLFD (255 bytes). */ commit de6601e62efd959cf74455cfd8030f60448cd713 Author: Paul Eggert Date: Mon Jun 13 13:21:18 2022 -0700 Pacify GCC 12.1.1 in default developer build * src/pdumper.c (pdumper_load): Use explicit memset to work around GCC bug . diff --git a/src/pdumper.c b/src/pdumper.c index 0efd5cfb0b..50ae4f85e7 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -5543,7 +5543,10 @@ pdumper_load (const char *dump_filename, char *argv0) struct dump_header header_buf = { 0 }; struct dump_header *header = &header_buf; - struct dump_memory_map sections[NUMBER_DUMP_SECTIONS] = { 0 }; + struct dump_memory_map sections[NUMBER_DUMP_SECTIONS]; + + /* Use memset instead of "= { 0 }" to work around GCC bug 105961. */ + memset (sections, 0, sizeof sections); const struct timespec start_time = current_timespec (); char *dump_filename_copy; commit 7fdb53ddaf3af135d441e68edc86dd98ee157a8e Author: Juri Linkov Date: Mon Jun 13 20:19:32 2022 +0300 * lisp/progmodes/grep.el (grep-read-files): Combine files with aliases. Use completion-table-merge to combine completions of files from read-file-name-internal with a list of defaults from grep-files-aliases (bug#55800). diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index 4dedbc66ae..a3ef90f397 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -1066,15 +1066,18 @@ REGEXP is used as a string in the prompt." default-extension (car grep-files-history) (car (car grep-files-aliases)))) + (defaults + (delete-dups + (delq nil + (append (list default default-alias default-extension) + (mapcar #'car grep-files-aliases))))) (files (completing-read (format-prompt "Search for \"%s\" in files matching wildcard" default regexp) - #'read-file-name-internal - nil nil nil 'grep-files-history - (delete-dups - (delq nil - (append (list default default-alias default-extension) - (mapcar #'car grep-files-aliases))))))) + (completion-table-merge + (lambda (_string _pred _action) defaults) + #'read-file-name-internal) + nil nil nil 'grep-files-history defaults))) (and files (or (cdr (assoc files grep-files-aliases)) files)))) commit abe75e55209073366670339c519fa69a3f93441e Author: Lars Ingebrigtsen Date: Mon Jun 13 17:30:36 2022 +0200 Mention \`M-x ...' in the lispref manual * doc/lispref/help.texi (Keys in Documentation): Note \`M-x ...' syntax. diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi index bc79033203..463039c5a0 100644 --- a/doc/lispref/help.texi +++ b/doc/lispref/help.texi @@ -345,7 +345,10 @@ stands for a key sequence @var{KEYSEQ}, which will use the same face as a command substitution. This should be used only when a key sequence has no corresponding command, for example when it is read directly with @code{read-key-sequence}. It must be a valid key -sequence according to @code{key-valid-p}. +sequence according to @code{key-valid-p}. It can also be used with +command names, like @samp{\`M-x foo'}, where you want this to be +fontified like a keyboard sequence, but you want to inhibit +translating it into a key sequence like @samp{\[foo]} does. @item ` (grave accent) stands for a left quote. commit 73400e4002ce8fca060093548e6791b3a784eeaa Author: Lars Ingebrigtsen Date: Mon Jun 13 17:14:08 2022 +0200 Clarify what a Calc registeri in in calc-insert-register * lisp/calc/calc-yank.el (calc-insert-register): Note that these aren't normal registers (bug#55943). diff --git a/lisp/calc/calc-yank.el b/lisp/calc/calc-yank.el index 8c6d3f51e5..189ee0a244 100644 --- a/lisp/calc/calc-yank.el +++ b/lisp/calc/calc-yank.el @@ -301,7 +301,10 @@ Interactively, reads the register using `register-read-with-preview'." (defun calc-insert-register (register) "Insert the contents of register REGISTER. -Interactively, reads the register using `register-read-with-preview'." +Interactively, reads the register using `register-read-with-preview'. + +Note that this command only works with Calc registers, and they +have nothing to do with the Emacs-wide register mechanism." (interactive (list (register-read-with-preview "Insert register: "))) (if (eq major-mode 'calc-mode) (let ((val (calc-get-register register))) commit f188b0185e7ace193b1c5501c5520578b4216ea0 Author: Lars Ingebrigtsen Date: Mon Jun 13 17:02:55 2022 +0200 Allow saying \\=`M-x ...' in a doc string * lisp/help.el (substitute-command-keys): Allow saying \\=`M-x foo' in doc strings (and have it be fontified as a key binding). diff --git a/lisp/help.el b/lisp/help.el index 9928b28fb6..766bae0845 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1173,7 +1173,8 @@ Otherwise, return a new string." (let ((k (buffer-substring-no-properties orig-point (point)))) (cond ((= (length k) 0) (error "Empty key sequence in substitution")) - ((not (key-valid-p k)) + ((and (not (string-match-p "\\`M-x " k)) + (not (key-valid-p k))) (error "Invalid key sequence in substitution: `%s'" k)))) (add-text-properties orig-point (point) '( face help-key-binding commit 5faa0bfdda012d049ddfa24f119ca33e16b026a7 Author: Lars Ingebrigtsen Date: Mon Jun 13 16:46:14 2022 +0200 Massage In-Reply-To data in message-mail * lisp/gnus/message.el (message-mail): Fix up Message-IDs from Firefox (bug#55926). diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 5936d29c9d..6973d8a86b 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -7017,7 +7017,15 @@ is a function used to switch to and display the mail buffer." ;; https://lists.gnu.org/r/emacs-devel/2011-01/msg00337.html ;; We need to convert any string input, eg from rmail-start-mail. (dolist (h other-headers other-headers) - (if (stringp (car h)) (setcar h (intern (capitalize (car h))))))) + (when (stringp (car h)) + (setcar h (intern (capitalize (car h))))) + ;; Firefox sends us In-Reply-To headers that are Message-IDs + ;; without <> around them. Fix that. + (when (and (eq (car h) 'In-Reply-To) + ;; Looks like a Message-ID. + (string-match-p "\\`[^ @]+@[^ @]+\\'" (cdr h)) + (not (string-match-p "\\`<.*>\\'" (cdr h)))) + (setcdr h (concat "<" (cdr h) ">"))))) yank-action send-actions continue switch-function return-action)))) commit 5f5617727d91664bb3e4e559a1347bec86759846 Author: Lassi Kortela Date: Mon Jun 13 16:32:45 2022 +0200 Match complete words in dns-mode * lisp/textmodes/dns-mode.el (dns-mode-font-lock-keywords): Match complete words like SOA and not all words that contain the string SOA (bug#55944). Copyright-paperwork-exempt: yes diff --git a/lisp/textmodes/dns-mode.el b/lisp/textmodes/dns-mode.el index d4acbe24eb..42d547504c 100644 --- a/lisp/textmodes/dns-mode.el +++ b/lisp/textmodes/dns-mode.el @@ -110,11 +110,11 @@ "26.1" 'set) (defcustom dns-mode-font-lock-keywords - `((,(concat "^\\$" (regexp-opt dns-mode-control-entities)) + `((,(concat "^\\$" (regexp-opt dns-mode-control-entities) "\\>") 0 ,dns-mode-control-entity-face) ("^\\$[a-z0-9A-Z]+" 0 ,dns-mode-bad-control-entity-face) - (,(regexp-opt dns-mode-classes) 0 ,dns-mode-class-face) - (,(regexp-opt dns-mode-types) 0 ,dns-mode-type-face)) + (,(regexp-opt dns-mode-classes 'words) 0 ,dns-mode-class-face) + (,(regexp-opt dns-mode-types 'words) 0 ,dns-mode-type-face)) "Font lock keywords used to highlight text in DNS master file mode." :version "26.1" :type 'sexp) commit 57cd069f73808f862c326bac4191ab507f3c973f Author: Lars Ingebrigtsen Date: Mon Jun 13 16:17:40 2022 +0200 Allow `query-replace' to do exact replacement of the current item * doc/emacs/search.texi (Query Replace): Document it. * lisp/replace.el (query-replace-help): Amend help text. (query-replace-map): Bind `E' to the exact case replacement. (perform-replace): Allow editing a replacement with exact case (bug#8504). diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi index b123ef83a1..f4e12d29e9 100644 --- a/doc/emacs/search.texi +++ b/doc/emacs/search.texi @@ -1827,12 +1827,18 @@ occurrence of @var{string}. When done, exit the recursive editing level with @kbd{C-M-c} to proceed to the next occurrence. @item e -@itemx E to edit the replacement string in the minibuffer. When you exit the minibuffer by typing @key{RET}, the minibuffer contents replace the current occurrence of the pattern. They also become the new replacement string for any further occurrences. +@item E +is like @kbd{e}, but the next replacement will be done with exact +case. I.e., if you have a @code{query-replace} from @samp{foo} to +@samp{bar}, a text like @samp{Foo} will be normally be replaced with +@samp{Bar}. Use this command to do the current replacement with exact +case. + @item C-l to redisplay the screen. Then you must type another character to specify what to do with this occurrence. diff --git a/etc/NEWS b/etc/NEWS index 8e3228864c..1b8560a923 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -151,6 +151,10 @@ of 'user-emacs-directory'. * Incompatible changes in Emacs 29.1 ++++ +** 'E' in 'query-replace' now edits the replacement with exact case. +Previously, this command did the same as 'e'. + --- ** '/ a' in *Packages* now limits by package name(s) instead of regexp. diff --git a/lisp/replace.el b/lisp/replace.el index b84e6eaa65..c9d41d3fa3 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -2506,7 +2506,8 @@ To be added to `context-menu-functions'." \\`^' to move point back to previous match, \\`u' to undo previous replacement, \\`U' to undo all replacements, -\\`E' to edit the replacement string. +\\`e' to edit the replacement string. +\\`E' to edit the replacement string with exact case. In multi-buffer replacements type \\`Y' to replace all remaining matches in all remaining buffers with no more questions, \\`N' to skip to the next buffer without replacing remaining matches @@ -2524,7 +2525,7 @@ in the current buffer." (define-key map "Y" 'act) (define-key map "N" 'skip) (define-key map "e" 'edit-replacement) - (define-key map "E" 'edit-replacement) + (define-key map "E" 'edit-replacement-exact-case) (define-key map "," 'act-and-show) (define-key map "q" 'exit) (define-key map "\r" 'exit) @@ -2561,8 +2562,9 @@ The \"bindings\" in this map are not commands; they are answers. The valid answers include `act', `skip', `act-and-show', `act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up', `scroll-down', `scroll-other-window', `scroll-other-window-down', -`edit', `edit-replacement', `delete-and-edit', `automatic', -`backup', `undo', `undo-all', `quit', and `help'. +`edit', `edit-replacement', `edit-replacement-exact-case', +`delete-and-edit', `automatic', `backup', `undo', `undo-all', +`quit', and `help'. This keymap is used by `y-or-n-p' as well as `query-replace'.") @@ -3336,19 +3338,29 @@ characters." (setq match-again (and (looking-at search-string) (match-data))))) ;; Edit replacement. - ((eq def 'edit-replacement) + ((or (eq def 'edit-replacement) + (eq def 'edit-replacement-exact-case)) (setq real-match-data (replace-match-data nil real-match-data real-match-data) next-replacement - (read-string "Edit replacement string: " - next-replacement) + (read-string + (format "Edit replacement string%s: " + (if (eq def + 'edit-replacement-exact-case) + " (exact case)" + "")) + next-replacement) noedit nil) (if replaced (set-match-data real-match-data) (setq noedit (replace-match-maybe-edit - next-replacement nocasify literal noedit + next-replacement + (if (eq def 'edit-replacement-exact-case) + t + nocasify) + literal noedit real-match-data backward) replaced t) (setq next-replacement-replaced next-replacement)) commit 288ffb25edbf38998aba65182e94b54cb2a3c04f Author: Lars Ingebrigtsen Date: Mon Jun 13 15:57:26 2022 +0200 Add to mode cedilla characters to iso-transl-char-map * lisp/international/iso-transl.el (iso-transl-char-map): Add some more cedilla characters. diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el index 0d0ff7f138..a14253ee58 100644 --- a/lisp/international/iso-transl.el +++ b/lisp/international/iso-transl.el @@ -112,8 +112,12 @@ (",," . [?¸]) (",A" . [?Ą]) (",C" . [?Ç]) + (",N" . [?Ņ]) + (",S" . [?Ş]) (",a" . [?ą]) (",c" . [?ç]) + (",n" . [?ņ]) + (",s" . [?ş]) ("*-" . [?­]) ("-" . [?­]) ("*." . [?·]) commit 5381a1e6ddcbc898439bd7f53d5dd0816f910feb Author: समीर सिंह Sameer Singh Date: Sat Jun 11 18:53:43 2022 +0530 Add support for the Meetei Mayek script * lisp/language/indian.el ("Meetei Mayek"): New language environment. Add composition rules for Meetei Mayek. Add sample text and input method. * lisp/international/fontset.el (script-representative-chars) (setup-default-fontset): Support Meetei Mayek. * lisp/leim/quail/indian.el ("meetei-mayek"): New input method. * etc/HELLO: Add a Meetei Mayek greeting. * etc/NEWS: Announce the new language environment. diff --git a/etc/HELLO b/etc/HELLO index baa8af0f07..d73465318c 100644 --- a/etc/HELLO +++ b/etc/HELLO @@ -83,6 +83,7 @@ Malayalam (മലയാളം) നമസ്കാരം Maldivian (ދިވެހި) އައްސަލާމު ޢަލައިކުމް / ކިހިނެހް؟ Maltese (il-Malti) Bonġu / Saħħa Mathematics ∀ p ∈ world • hello p □ +Meetei Mayek (ꯃꯤꯇꯩ ꯃꯌꯦꯛ) ꯈꯨꯔꯨꯝꯖꯔꯤ Modi (𑘦𑘻𑘚𑘲) 𑘡𑘦𑘭𑘿𑘎𑘰𑘨 Mongolian (монгол хэл) Сайн байна уу? Northern Thai (ᨣᩣᩴᨾᩮᩬᩥᨦ / ᨽᩣᩈᩣᩃ᩶ᩣ᩠ᨶᨶᩣ) ᩈ᩠ᩅᩢᩔ᩠ᨯᩦᨣᩕᩢ᩠ᨸ diff --git a/etc/NEWS b/etc/NEWS index f533575c93..8e3228864c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -890,6 +890,7 @@ corresponding language environments are: **** Grantha script and language environment **** Kharoshthi script and language environment **** Lepcha script and language environment +**** Meetei Mayek script and language environment --- *** The "Oriya" language environment was renamed to "Odia". diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index 273cba8d63..8d34aa99c3 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -211,6 +211,7 @@ (javanese #xA98F #xA9B4 #xA9CA) (cham #xAA00) (tai-viet #xAA80) + (meetei-mayek #xABC0 #xABE3 #xAAE0 #xAAF6) (hangul #xAC00) (linear-b #x10000) (aegean-number #x10100) @@ -776,6 +777,7 @@ rejang javanese tai-viet + meetei-mayek aegean-number ancient-greek-number ancient-symbol diff --git a/lisp/language/indian.el b/lisp/language/indian.el index 6e0fb10b4f..2887d410ad 100644 --- a/lisp/language/indian.el +++ b/lisp/language/indian.el @@ -255,6 +255,17 @@ Lepcha language and its script are supported in this language environment.")) '("Indian")) +(set-language-info-alist + "Meetei Mayek" '((charset unicode) + (coding-system utf-8) + (coding-priority utf-8) + (input-method . "meetei-mayek") + (sample-text . "Meetei Mayek (ꯃꯤꯇꯩ ꯃꯌꯦꯛ) ꯈꯨꯔꯨꯝꯖꯔꯤ") + (documentation . "\ +Meetei language and its script Meetei Mayek are supported in this +language environment.")) + '("Indian")) + ;; Replace mnemonic characters in REGEXP according to TABLE. TABLE is ;; an alist of (MNEMONIC-STRING . REPLACEMENT-STRING). @@ -760,5 +771,21 @@ language environment.")) other-signs "?") 1 'font-shape-gstring)))) +;; Meetei Mayek composition rules +(let ((akshara "[\xABC0-\xABE2\xAAE0-\xAAEA]") + (vowel "[\xABE3-\xABE9\xAAEB-\xAAEC]") + (nasal "\xABEA") + (visarga "\xAAF5") + (virama "[\xABED\xAAF6]") + (heavy-tone "\x11640")) + (set-char-table-range composition-function-table + '(#xABE3 . #xABED) + (list (vector + ;; Consonant based syllables + (concat akshara "\\(?:" virama akshara "\\)*\\(?:" + virama "\\|" vowel "*" nasal "?" visarga "?" + heavy-tone "?\\)") + 1 'font-shape-gstring)))) + (provide 'indian) ;;; indian.el ends here diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el index bc61a312fa..8fffcc3511 100644 --- a/lisp/leim/quail/indian.el +++ b/lisp/leim/quail/indian.el @@ -1863,5 +1863,104 @@ Full key sequences are listed below:") ("M" ?ᰖ) ("`m" ?ᰮ)) +(quail-define-package + "meetei-mayek" "Meetei Mayek" "ꯃꯤ" t "Meetei Mayek phonetic input method. + + `\\=`' is used to switch levels instead of Alt-Gr." + nil t t t t nil nil nil nil nil t) + +(quail-define-rules + ("``" ?₹) + ("1" ?꯱) + ("`1" ?1) + ("2" ?꯲) + ("`2" ?2) + ("3" ?꯳) + ("`3" ?3) + ("4" ?꯴) + ("`4" ?4) + ("5" ?꯵) + ("`5" ?5) + ("6" ?꯶) + ("`6" ?6) + ("7" ?꯷) + ("`7" ?7) + ("8" ?꯸) + ("`8" ?8) + ("9" ?꯹) + ("`9" ?9) + ("0" ?꯰) + ("`0" ?0) + ("`\\" ?꫰) + ("`|" ?꯫) + ("`" ?ꫤ) + ("q" ?ꫤ) + ("Q" ?ꫥ) + ("w" ?ꯋ) + ("W" ?ꫦ) + ("`w" ?ꫧ) + ("e" ?ꯦ) + ("E" ?ꯩ) + ("`e" ?ꫠ) + ("r" ?ꯔ) + ("t" ?ꯇ) + ("T" ?ꯊ) + ("`t" ?ꯠ) + ("y" ?ꯌ) + ("u" ?ꯨ) + ("U" ?ꯎ) + ("`u" ?ꫬ) + ("i" ?ꯤ) + ("I" ?ꯏ) + ("`i" ?ꯢ) + ("`I" ?ꫫ) + ("o" ?ꯣ) + ("O" ?ꯧ) + ("`o" ?ꫡ) + ("`O" ?ꫮ) + ("p" ?ꯄ) + ("P" ?ꯐ) + ("`p" ?ꯞ) + ("a" ?ꯥ) + ("A" ?ꯑ) + ("`a" ?ꫭ) + ("`A" ?ꫯ) + ("s" ?ꯁ) + ("S" ?ꫩ) + ("`s" ?ꫪ) + ("d" ?ꯗ) + ("D" ?ꯙ) + ("f" ?꯭) + ("F" ?꫶) + ("g" ?ꯒ) + ("G" ?ꯘ) + ("h" ?ꯍ) + ("H" ?ꫵ) + ("j" ?ꯖ) + ("J" ?ꯓ) + ("k" ?ꯀ) + ("K" ?ꯈ) + ("`k" ?ꯛ) + ("l" ?ꯂ) + ("L" ?ꯜ) + ("z" ?ꯉ) + ("Z" ?ꯡ) + ("`z" ?ꫣ) + ("x" ?ꯪ) + ("c" ?ꯆ) + ("C" ?ꫢ) + ("v" ?꯬) + ("V" ?ꫳ) + ("`v" ?ꫴ) + ("b" ?ꯕ) + ("B" ?ꯚ) + ("n" ?ꯅ) + ("N" ?ꯟ) + ("`n" ?ꫨ) + ("m" ?ꯃ) + ("M" ?ꯝ) + ("`m" ?ꫲ) + ("`?" ?꫱)) + (provide 'indian) ;;; indian.el ends here commit 27600ad6738a7bdf219b858b0805c11d189533ee Author: Lars Ingebrigtsen Date: Mon Jun 13 15:49:56 2022 +0200 Make the ediff control panel mode line prettier * lisp/vc/ediff-wind.el (ediff-refresh-mode-lines): Don't include "Quick Help" in the mode line in the plain version (bug#12840). (ediff-make-wide-control-buffer-id): Make the informative part of the mode line bold. (Code from Michael Heerdegen.) diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el index 1e702edb41..4549b910b1 100644 --- a/lisp/vc/ediff-wind.el +++ b/lisp/vc/ediff-wind.el @@ -1135,7 +1135,10 @@ It assumes that it is called from within the control buffer." (setq mode-line-format (if (ediff-narrow-control-frame-p) (list " " mode-line-buffer-identification) - (list "-- " mode-line-buffer-identification " Quick Help"))) + (list "-- " mode-line-buffer-identification + (and (not (eq ediff-window-setup-function + 'ediff-setup-windows-plain)) + " Quick Help")))) ;; control buffer id (setq mode-line-buffer-identification (if (ediff-narrow-control-frame-p) @@ -1213,18 +1216,20 @@ It assumes that it is called from within the control buffer." ediff-control-buffer-suffix)) (defun ediff-make-wide-control-buffer-id () - (cond ((< ediff-current-difference 0) - (list (format "%%b At start of %d diffs" - ediff-number-of-differences))) - ((>= ediff-current-difference ediff-number-of-differences) - (list (format "%%b At end of %d diffs" - ediff-number-of-differences))) - (t - (list (format "%%b diff %d of %d" - (1+ ediff-current-difference) - ediff-number-of-differences))))) - - + (list + (concat "%b " + (propertize + (cond ((< ediff-current-difference 0) + (format "At start of %d diffs" + ediff-number-of-differences)) + ((>= ediff-current-difference ediff-number-of-differences) + (format "At end of %d diffs" + ediff-number-of-differences)) + (t + (format "diff %d of %d" + (1+ ediff-current-difference) + ediff-number-of-differences))) + 'face 'mode-line-buffer-id)))) ;; If buff is not live, return nil (defun ediff-get-visible-buffer-window (buff) commit 18f5984c654130e3822c8b30a77737a36772bd40 Author: Eli Zaretskii Date: Mon Jun 13 16:46:45 2022 +0300 ; * etc/NEWS: Fix wording. diff --git a/etc/NEWS b/etc/NEWS index df636084df..f533575c93 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -294,7 +294,8 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 -** Files with the '.eld' extension are now opened in 'lisp-data-mode'. +--- +** Files with the '.eld' extension are now visited in 'lisp-data-mode'. +++ ** New command 'find-sibling-file'. commit df081b9f9c156c6dc674216523571880d4cbe730 Author: Eli Zaretskii Date: Mon Jun 13 16:45:05 2022 +0300 ; * doc/lispref/minibuf.texi (Text from Minibuffer): Fix indexing. diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index a59261cb9d..f2adc01c8f 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -310,6 +310,8 @@ specifying a minibuffer history list to use (@pxref{Minibuffer History}). If it is omitted or @code{nil}, the history list defaults to @code{regexp-history}. +@cindex @code{case-fold}, text property +@findex read-regexp-case-fold-search The user can use the @kbd{M-c} command to indicate whether case folding should be on or off. If the user has used this command, the returned string will have the text property @code{case-fold} set to commit e418e9109140bba06b03a9ea5f1dec9f7aa541a3 Author: Lars Ingebrigtsen Date: Mon Jun 13 15:32:57 2022 +0200 Allow rgrep users to indicate case folding easier * lisp/progmodes/grep.el (rgrep): Allow the user to toggle case sensitivity interactively (bug#16913). diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index a8d743b87a..4dedbc66ae 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -1205,7 +1205,11 @@ When called programmatically and FILES is nil, REGEXP is expected to specify a command to run. If CONFIRM is non-nil, the user will be given an opportunity to edit the -command before it's run." +command before it's run. + +Interactively, the user can use the `M-c' command while entering +the regexp to indicate whether the grep should be case sensitive +or not." (interactive (progn (grep-compute-defaults) @@ -1233,7 +1237,8 @@ command before it's run." grep-find-command))) (compilation-start regexp #'grep-mode)) (setq dir (file-name-as-directory (expand-file-name dir))) - (let ((command (rgrep-default-command regexp files nil))) + (let* ((case-fold-search (read-regexp-case-fold-search regexp)) + (command (rgrep-default-command regexp files nil))) (when command (if confirm (setq command commit 027fecb24bb0a17543efb0ef63bb7b160e2630d1 Author: Lars Ingebrigtsen Date: Mon Jun 13 15:31:25 2022 +0200 Add a `M-c' command to `read-regexp' * doc/lispref/minibuf.texi (Text from Minibuffer): Document it. * lisp/replace.el (read-regexp): Add a `M-c' command to indicate case folding (bug#16913). diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index 1451e59d05..a59261cb9d 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -309,6 +309,20 @@ The optional argument @var{history}, if non-@code{nil}, is a symbol specifying a minibuffer history list to use (@pxref{Minibuffer History}). If it is omitted or @code{nil}, the history list defaults to @code{regexp-history}. + +The user can use the @kbd{M-c} command to indicate whether case +folding should be on or off. If the user has used this command, the +returned string will have the text property @code{case-fold} set to +either @code{fold} or @code{inhibit-fold}. It is up to the caller of +@code{read-regexp} to actually use this value, and the convenience +function @code{read-regexp-case-fold-search} is provided for that. A +typical usage pattern here might look like: + +@lisp +(let* ((regexp (read-regexp "Search for: ")) + (case-fold-search (read-regexp-case-fold-search regexp))) + (re-search-forward regexp)) +@end lisp @end defun @defopt read-regexp-defaults-function diff --git a/etc/NEWS b/etc/NEWS index 9440baee6a..df636084df 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1978,6 +1978,9 @@ Previously it produced a nonsense value, -1, that was never intended. * Lisp Changes in Emacs 29.1 ++++ +** 'read-regexp' now allows the user to indicate whether to use case folding. + +++ ** 'completing-read' now allows a function as its REQUIRE-MATCH argument. This function is called to see whether what the user has typed in is a diff --git a/lisp/replace.el b/lisp/replace.el index 3d0877a9a6..b84e6eaa65 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -928,7 +928,13 @@ If the first element of DEFAULTS is non-nil (and if PROMPT does not end in \":\", followed by optional whitespace), DEFAULT is added to the prompt. The optional argument HISTORY is a symbol to use for the history list. -If nil, use `regexp-history'." +If nil, use `regexp-history'. + +If the user has used the `M-c' command to specify case +sensitivity, the returned string will have a text property named +`case-fold' that has a value of either `fold' or +`inhibit-fold'. (It's up to the caller of `read-regexp' to +respect this or not; see `read-regexp-case-fold-search'.)" (let* ((defaults (if (and defaults (symbolp defaults)) (cond @@ -944,21 +950,50 @@ If nil, use `regexp-history'." (suggestions (delete-dups (delq nil (delete "" suggestions)))) ;; Do not automatically add default to the history for empty input. (history-add-new-input nil) + (case-fold case-fold-search) (input (read-from-minibuffer (if (string-match-p ":[ \t]*\\'" prompt) prompt (format-prompt prompt (and (length> default 0) (query-replace-descr default)))) - nil nil nil (or history 'regexp-history) suggestions t))) - (if (equal input "") - ;; Return the default value when the user enters empty input. - (prog1 (or default input) - (when default - (add-to-history (or history 'regexp-history) default))) - ;; Otherwise, add non-empty input to the history and return input. - (prog1 input - (add-to-history (or history 'regexp-history) input))))) - + nil + (define-keymap + :parent minibuffer-local-map + "M-c" (lambda () + (interactive) + (setq case-fold + (if (or (eq case-fold 'fold) + (and case-fold + (not (eq case-fold + 'inhibit-fold)))) + 'inhibit-fold + 'fold)) + (message "Case folding is now %s" + (if (eq case-fold 'fold) + "on" + "off")))) + nil (or history 'regexp-history) suggestions t)) + (result (if (equal input "") + ;; Return the default value when the user enters + ;; empty input. + default + input))) + (when result + (add-to-history (or history 'regexp-history) result)) + (if (and result + (or (eq case-fold 'fold) + (eq case-fold 'inhibit-fold))) + (propertize result 'case-fold case-fold) + (or result input)))) + +(defun read-regexp-case-fold-search (regexp) + "Return a value for `case-fold-search' based on REGEXP and current settings. +REGEXP is a string as returned by `read-regexp'." + (let ((fold (get-text-property 0 'case-fold regexp))) + (cond + ((eq fold 'fold) t) + ((eq fold 'inhibit-fold) nil) + (t case-fold-search)))) (defalias 'delete-non-matching-lines 'keep-lines) (defalias 'delete-matching-lines 'flush-lines) commit 86325f960af8eb1df712e2f26e2b708f80c14ac6 Author: Richard Hansen Date: Mon Jun 13 14:32:01 2022 +0200 bindat (strz): Error on null byte if packing variable-length string * lisp/emacs-lisp/bindat.el (strz): Signal an error if a null byte is encountered while packing a string to a variable-length strz field. * test/lisp/emacs-lisp/bindat-tests.el (strz): Add tests (bug#55938). diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 2d6589b52d..9ba89a5e3f 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -444,6 +444,11 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." (let* ((v (string-to-unibyte v)) (len (length v))) (dotimes (i len) + (when (= (aref v i) 0) + ;; Alternatively we could pretend that this was the end of + ;; the string and stop packing, but then bindat-length would + ;; need to scan the input string looking for a null byte. + (error "Null byte encountered in input strz string")) (aset bindat-raw (+ bindat-idx i) (aref v i))) (setq bindat-idx (+ bindat-idx len 1)))) diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el index 8bb3baa485..7d1233ded7 100644 --- a/test/lisp/emacs-lisp/bindat-tests.el +++ b/test/lisp/emacs-lisp/bindat-tests.el @@ -240,7 +240,12 @@ (ert-deftest bindat-test--strz-varlen-pack () (should (equal (bindat-pack spec "") "\0")) - (should (equal (bindat-pack spec "abc") "abc\0"))) + (should (equal (bindat-pack spec "abc") "abc\0")) + ;; Null bytes in the input string break unpacking. + (should-error (bindat-pack spec "\0")) + (should-error (bindat-pack spec "\0x")) + (should-error (bindat-pack spec "x\0")) + (should-error (bindat-pack spec "x\0y"))) (ert-deftest bindat-test--strz-varlen-unpack () (should (equal (bindat-unpack spec "\0") "")) commit 86f30c972bb421db1b8f83951ecfc15ad607fb03 Author: Stefan Monnier Date: Mon Jun 13 08:58:09 2022 -0400 * files.el (auto-mode-alist): Add entry to `.eld` files diff --git a/etc/NEWS b/etc/NEWS index 5df7713aea..9440baee6a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -294,6 +294,8 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 +** Files with the '.eld' extension are now opened in 'lisp-data-mode'. + +++ ** New command 'find-sibling-file'. This command jumps to a file considered a "sibling file", which is diff --git a/lisp/files.el b/lisp/files.el index eb1b90fc29..22fccb151c 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2797,6 +2797,9 @@ since only a single case-insensitive search through the alist is made." ;; .dir-locals.el is not really Elisp. Could use the ;; `dir-locals-file' constant if it weren't defined below. ("\\.dir-locals\\(?:-2\\)?\\.el\\'" . lisp-data-mode) + ("\\.eld\\'" . lisp-data-mode) + ;; FIXME: The lisp-data-mode files below should use the `.eld' extension + ;; (or a -*- mode cookie) so we don't need ad-hoc entries here. ("eww-bookmarks\\'" . lisp-data-mode) ("tramp\\'" . lisp-data-mode) ("/archive-contents\\'" . lisp-data-mode) commit 0fdd37c7fbbd0880e569d41bb5ecb9a40f099b00 Author: Lars Ingebrigtsen Date: Mon Jun 13 14:20:22 2022 +0200 Make `/ a' in *Package* filter by name * lisp/emacs-lisp/package.el (package-menu-filter-by-archive): Filter by package name instead of by regexp, so that if the user types "gnu", they won't get "nongnu", too (bug#55919). diff --git a/etc/NEWS b/etc/NEWS index 6f00a51a70..5df7713aea 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -151,6 +151,9 @@ of 'user-emacs-directory'. * Incompatible changes in Emacs 29.1 +--- +** '/ a' in *Packages* now limits by package name(s) instead of regexp. + +++ ** Setting the goal columns now also affects '' and ''. Previously, 'C-x C-n' only affected 'next-line' and 'previous-line', diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 48551f59b4..9aaeb052d0 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -3963,16 +3963,14 @@ packages." (mapcar #'car package-archives))) package-menu-mode) (package--ensure-package-menu-mode) - (let ((re (if (listp archive) - (regexp-opt archive) - archive))) - (package-menu--filter-by (lambda (pkg-desc) - (let ((pkg-archive (package-desc-archive pkg-desc))) - (and pkg-archive - (string-match-p re pkg-archive)))) - (concat "archive:" (if (listp archive) - (string-join archive ",") - archive))))) + (let ((archives (ensure-list archive))) + (package-menu--filter-by + (lambda (pkg-desc) + (let ((pkg-archive (package-desc-archive pkg-desc))) + (or (null archives) + (and pkg-archive + (member pkg-archive archives))))) + (concat "archive:" (string-join archives ","))))) (defun package-menu-filter-by-description (description) "Filter the \"*Packages*\" buffer by DESCRIPTION regexp. commit f8ac290945102f2b59a4474bd4c53ba22db6a076 Author: Visuwesh Date: Sun Jun 12 12:35:08 2022 +0200 * lisp/find-dired.el (find-dired): Make directory clickable. * lisp/find-dired.el (find-dired): Make the directory line clickable (bug#55906). diff --git a/lisp/find-dired.el b/lisp/find-dired.el index c04545e44e..8c1e684b7e 100644 --- a/lisp/find-dired.el +++ b/lisp/find-dired.el @@ -241,6 +241,8 @@ it finishes, type \\[kill-find]." ;; Subdir headlerline must come first because the first marker in ;; subdir-alist points there. (insert " " dir ":\n") + (when dired-make-directory-clickable + (dired--make-directory-clickable)) ;; Make second line a ``find'' line in analogy to the ``total'' or ;; ``wildcard'' line. (let ((point (point))) commit a1a435b3f6c7afa910da2256334471ba49010974 Author: Po Lu Date: Mon Jun 13 15:01:06 2022 +0800 Respect test function when performing local drag-and-drop * lisp/x-dnd.el (x-dnd-test-function): Fix doc string to describe what is actually accepted. (x-dnd-known-types, x-dnd-targets-list): Fix coding style. (x-dnd-handle-native-drop): New function. * src/xselect.c (x_atom_to_symbol): Export. * src/xterm.c (x_dnd_note_self_drop): Call new variable to determine what action to return. (x_clear_dnd_action): New function. (x_dnd_begin_drag_and_drop): Respect new variable. (syms_of_xterm): New defvar `x-dnd-native-test-function'. * src/xterm.h: Update prototypes. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 7ee20e0fc3..bcf74762cc 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -35,22 +35,24 @@ (defcustom x-dnd-test-function #'x-dnd-default-test-function "The function drag and drop uses to determine if to accept or reject a drop. The function takes three arguments, WINDOW, ACTION and TYPES. -WINDOW is where the mouse is when the function is called. WINDOW may be a -frame if the mouse isn't over a real window (i.e. menu bar, tool bar or -scroll bar). ACTION is the suggested action from the drag and drop source, -one of the symbols move, copy, link or ask. TYPES is a list of available -types for the drop. - -The function shall return nil to reject the drop or a cons with two values, -the wanted action as car and the wanted type as cdr. The wanted action -can be copy, move, link, ask or private. +WINDOW is where the mouse is when the function is called. WINDOW +may be a frame if the mouse isn't over a real window (i.e. menu +bar, tool bar or scroll bar). ACTION is the suggested action +from the drag and drop source, one of the symbols move, copy, +link or ask. TYPES is a vector of available types for the drop. + +Each element of TYPE should either be a string (containing the +name of the type's X atom), or a symbol, whose name will be used. + +The function shall return nil to reject the drop or a cons with +two values, the wanted action as car and the wanted type as cdr. +The wanted action can be copy, move, link, ask or private. + The default value for this variable is `x-dnd-default-test-function'." :version "22.1" :type 'symbol :group 'x) - - (defcustom x-dnd-types-alist `((,(purecopy "text/uri-list") . x-dnd-handle-uri-list) (,(purecopy "text/x-moz-url") . x-dnd-handle-moz-url) @@ -94,8 +96,7 @@ if drop is successful, nil if not." The types are chosen in the order they appear in the list." :version "22.1" :type '(repeat string) - :group 'x -) + :group 'x) ;; Internal variables @@ -163,7 +164,6 @@ types in `x-dnd-known-types'. It always returns the action private." (let ((type (x-dnd-choose-type types))) (when type (cons 'private type)))) - (defun x-dnd-current-type (frame-or-window) "Return the type we want the DND data to be in for the current drop. FRAME-OR-WINDOW is the frame or window that the mouse is over." @@ -896,6 +896,23 @@ Return a vector of atoms containing the selection targets." (member "COMPOUND_TEXT" targets) (member "TEXT" targets))))) +(defvar x-dnd-targets-list) +(defvar x-dnd-native-test-function) + +(defun x-dnd-handle-native-drop (pos action) + "Compute the action for a drop at POS. +Return the appropriate drag-and-drop action for a local drop at POS. +ACTION is the action given to `x-begin-drag'." + (let ((state (funcall x-dnd-test-function + (posn-window pos) + (cdr (assoc (symbol-name action) + x-dnd-xdnd-to-action)) + (apply #'vector x-dnd-targets-list)))) + (when state + (intern (car (rassq (car state) x-dnd-xdnd-to-action)))))) + +(setq x-dnd-native-test-function #'x-dnd-handle-native-drop) + (provide 'x-dnd) ;;; x-dnd.el ends here diff --git a/src/xselect.c b/src/xselect.c index bb5a1447df..490a008dfc 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -112,7 +112,7 @@ selection_quantum (Display *display) : MAX_SELECTION_QUANTUM); } -#define LOCAL_SELECTION(selection_symbol,dpyinfo) \ +#define LOCAL_SELECTION(selection_symbol, dpyinfo) \ assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) @@ -179,7 +179,7 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) /* This converts a server Atom to a Lisp symbol, avoiding server roundtrips and calls to intern whenever possible. */ -static Lisp_Object +Lisp_Object x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) { char *str; diff --git a/src/xterm.c b/src/xterm.c index 81b3b5cbef..d9dd29ca12 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1228,6 +1228,10 @@ static XRectangle x_dnd_mouse_rect; protocol, this is set to the atom XdndActionPrivate. */ static Atom x_dnd_action; +/* The symbol to return from `x-begin-drag' if non-nil. Takes + precedence over `x_dnd_action`. */ +static Lisp_Object x_dnd_action_symbol; + /* The action we want the drop target to perform. The drop target may elect to perform some different action, which is guaranteed to be in `x_dnd_action' upon completion of a drop. */ @@ -1242,7 +1246,7 @@ static uint8_t x_dnd_motif_operations; static uint8_t x_dnd_first_motif_operation; /* Array of selection targets available to the drop target. */ -static Atom *x_dnd_targets = NULL; +static Atom *x_dnd_targets; /* The number of elements in that array. */ static int x_dnd_n_targets; @@ -4298,15 +4302,30 @@ x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target, if (!f) return; + if (NILP (Vx_dnd_native_test_function)) + return; + if (!XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, FRAME_X_WINDOW (f), root_x, root_y, &win_x, &win_y, &dummy)) return; - /* Emacs can't respond to DND events inside the nested event - loop, so when dragging items to itself, always return - XdndActionPrivate. */ - x_dnd_action = dpyinfo->Xatom_XdndActionPrivate; + /* Emacs can't respond to DND events inside the nested event loop, + so when dragging items to itself, call the test function + manually. */ + + XSETFRAME (lval, f); + x_dnd_action = None; + x_dnd_action_symbol + = safe_call2 (Vx_dnd_native_test_function, + Fposn_at_x_y (make_fixnum (win_x), + make_fixnum (win_y), + lval, Qnil), + x_atom_to_symbol (dpyinfo, + x_dnd_wanted_action)); + + if (!SYMBOLP (x_dnd_action_symbol)) + return; EVENT_INIT (ie); @@ -10779,6 +10798,12 @@ x_detect_pending_selection_requests (void) return pending_selection_requests; } +static void +x_clear_dnd_action (void) +{ + x_dnd_action_symbol = Qnil; +} + /* This function is defined far away from the rest of the XDND code so it can utilize `x_any_window_to_frame'. */ @@ -10922,6 +10947,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_set_dnd_targets (target_atoms, ntargets); record_unwind_protect_void (x_free_dnd_targets); + record_unwind_protect_void (x_clear_dnd_action); ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), QXdndSelection); @@ -11042,6 +11068,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; x_dnd_mouse_rect_target = None; x_dnd_action = None; + x_dnd_action_symbol = Qnil; x_dnd_wanted_action = xaction; x_dnd_return_frame = 0; x_dnd_waiting_for_finish = false; @@ -11435,6 +11462,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_return_frame_object = NULL; FRAME_DISPLAY_INFO (f)->grabbed = 0; + if (!NILP (x_dnd_action_symbol)) + return unbind_to (base, x_dnd_action_symbol); + if (x_dnd_action != None) { block_input (); @@ -26942,6 +26972,9 @@ syms_of_xterm (void) x_dnd_monitors = Qnil; staticpro (&x_dnd_monitors); + x_dnd_action_symbol = Qnil; + staticpro (&x_dnd_action_symbol); + DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); DEFSYM (Qlatin_1, "latin-1"); DEFSYM (Qnow, "now"); @@ -27189,4 +27222,15 @@ This variable contains the list of drag-and-drop selection targets during a drag-and-drop operation, in the same format as the TARGET argument to `x-begin-drag'. */); Vx_dnd_targets_list = Qnil; + + DEFVAR_LISP ("x-dnd-native-test-function", Vx_dnd_native_test_function, + doc: /* Function called to determine return when dropping on Emacs itself. +It should accept two arguments POS and ACTION, and return a symbol +describing what to return from `x-begin-drag'. POS is a mouse +position list detailing the location of the drop, and ACTION is the +action specified by the caller of `x-begin-drag'. + +If nil or a non-symbol value is returned, the drop will be +cancelled. */); + Vx_dnd_native_test_function = Qnil; } diff --git a/src/xterm.h b/src/xterm.h index 25d145c6c0..25c2453ee7 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1535,6 +1535,7 @@ extern void x_handle_property_notify (const XPropertyEvent *); extern void x_handle_selection_notify (const XSelectionEvent *); extern void x_handle_selection_event (struct selection_input_event *); extern void x_clear_frame_selections (struct frame *); +extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom); extern bool x_handle_dnd_message (struct frame *, const XClientMessageEvent *, commit 7cd1f432c62d5677fb2d44ed05ed9546c3c292dc Merge: 16df1f4fae d6f080d3de Author: Stefan Kangas Date: Mon Jun 13 06:55:57 2022 +0200 Merge from origin/emacs-28 d6f080d3de ; * doc/man/etags.1: Bump man page date. commit 16df1f4fae5414556e905ec0f1c1c565e17cb7ae Author: Po Lu Date: Mon Jun 13 12:49:12 2022 +0800 Improve DND tooltip updating * src/xterm.c (x_dnd_update_tooltip_now): Add missing part of last change. (x_monitors_changed_cb, handle_one_xevent): Only update if a change in monitor configuration really happened. diff --git a/src/xterm.c b/src/xterm.c index 4bc4c53eea..81b3b5cbef 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15335,7 +15335,7 @@ x_dnd_update_tooltip_now (void) if (!x_dnd_in_progress || !x_dnd_update_tooltip) return; - dpyinfo = FRAME_DISPLAY_INFO (XFRAME (x_dnd_frame)); + dpyinfo = FRAME_DISPLAY_INFO (x_dnd_frame); rc = XQueryPointer (dpyinfo->display, dpyinfo->root_window, @@ -15721,14 +15721,14 @@ x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data) ie.arg = terminal; kbd_buffer_store_event (&ie); - } - dpyinfo->last_monitor_attributes_list = current_monitors; + if (x_dnd_in_progress && x_dnd_update_tooltip) + x_dnd_monitors = current_monitors; - if (x_dnd_in_progress && x_dnd_update_tooltip) - x_dnd_monitors = current_monitors; + x_dnd_update_tooltip_now (); + } - x_dnd_update_tooltip_now (); + dpyinfo->last_monitor_attributes_list = current_monitors; } #endif @@ -21548,7 +21548,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (x_dnd_in_progress && x_dnd_update_tooltip) x_dnd_monitors = current_monitors; - x_dnd_update_tooltip_now (); + if (inev.ie.kind != NO_EVENT) + x_dnd_update_tooltip_now (); } #endif OTHER: commit 1ce0d8d9efee60d7bc6d4b81c7e7d6be508c0b7b Author: Po Lu Date: Mon Jun 13 09:42:12 2022 +0800 Keep tooltip position in sync with monitor changes * src/xterm.c (x_dnd_update_tooltip_now): New function. (x_monitors_changed_cb): (handle_one_xevent): Call that function on monitor change. diff --git a/src/xterm.c b/src/xterm.c index b1e877566f..4bc4c53eea 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15322,6 +15322,31 @@ x_dnd_update_tooltip_position (int root_x, int root_y) } } +static void +x_dnd_update_tooltip_now (void) +{ + int root_x, root_y; + Window root, child; + int win_x, win_y; + unsigned int mask; + Bool rc; + struct x_display_info *dpyinfo; + + if (!x_dnd_in_progress || !x_dnd_update_tooltip) + return; + + dpyinfo = FRAME_DISPLAY_INFO (XFRAME (x_dnd_frame)); + + rc = XQueryPointer (dpyinfo->display, + dpyinfo->root_window, + &root, &child, &root_x, + &root_y, &win_x, &win_y, + &mask); + + if (rc) + x_dnd_update_tooltip_position (root_x, root_y); +} + /* Get the window underneath the pointer, see if it moved, and update the DND state accordingly. */ static void @@ -15702,6 +15727,8 @@ x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data) if (x_dnd_in_progress && x_dnd_update_tooltip) x_dnd_monitors = current_monitors; + + x_dnd_update_tooltip_now (); } #endif @@ -21520,6 +21547,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (x_dnd_in_progress && x_dnd_update_tooltip) x_dnd_monitors = current_monitors; + + x_dnd_update_tooltip_now (); } #endif OTHER: commit 79f50e913d32cb1d1f7757258240147b9234c4d3 Author: Po Lu Date: Mon Jun 13 09:11:08 2022 +0800 Fix special DND event coordinates * src/xterm.c (x_dnd_note_self_drop): Set DND action to XdndActionPrivate. (x_dnd_begin_drag_and_drop): Don't return XdndPrivate specially here. (handle_one_xevent): Fix order of arguments to x_dnd_note_self_drop. diff --git a/src/xterm.c b/src/xterm.c index f2306a6015..b1e877566f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4303,6 +4303,11 @@ x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target, &win_x, &win_y, &dummy)) return; + /* Emacs can't respond to DND events inside the nested event + loop, so when dragging items to itself, always return + XdndActionPrivate. */ + x_dnd_action = dpyinfo->Xatom_XdndActionPrivate; + EVENT_INIT (ie); ie.kind = DRAG_N_DROP_EVENT; @@ -10805,7 +10810,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #endif XWindowAttributes root_window_attrs; struct input_event hold_quit; - struct frame *any; char *atom_name, *ask_actions; Lisp_Object action, ltimestamp; specpdl_ref ref, count, base; @@ -11431,15 +11435,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_return_frame_object = NULL; FRAME_DISPLAY_INFO (f)->grabbed = 0; - /* Emacs can't respond to DND events inside the nested event - loop, so when dragging items to itself, always return - XdndActionPrivate. */ - if (x_dnd_end_window != None - && (any = x_any_window_to_frame (FRAME_DISPLAY_INFO (f), - x_dnd_end_window)) - && (allow_current_frame || any != f)) - return unbind_to (base, QXdndActionPrivate); - if (x_dnd_action != None) { block_input (); @@ -18196,9 +18191,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, && x_dnd_last_window_is_frame) { x_dnd_waiting_for_finish = false; - x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window, - event->xbutton.time, event->xbutton.x_root, - event->xbutton.y_root); + x_dnd_note_self_drop (dpyinfo, + x_dnd_last_seen_window, + event->xbutton.x_root, + event->xbutton.y_root, + event->xbutton.time); } else if (x_dnd_last_seen_window != None && x_dnd_last_protocol_version != -1) @@ -19596,7 +19593,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { x_dnd_waiting_for_finish = false; x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window, - xev->time, xev->root_x, xev->root_y); + xev->root_x, xev->root_y, xev->time); } else if (x_dnd_last_seen_window != None && x_dnd_last_protocol_version != -1) commit 72e0ef74d0ed242cd75226aef887d87391c23f6d Author: Juri Linkov Date: Sun Jun 12 21:24:01 2022 +0300 * lisp/icomplete.el: Consider a list in minibuffer-default (bug#55800) * lisp/icomplete.el (icomplete--sorted-completions): Handle a string value in the first element of the list of default values in minibuffer-default. diff --git a/lisp/icomplete.el b/lisp/icomplete.el index 8802e7565f..be7f6831cc 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -559,7 +559,8 @@ Usually run by inclusion in `minibuffer-setup-hook'." ;; predicates" which may vary depending on specific ;; `completing-read' invocations, described below: for fn in (cond ((and minibuffer-default - (stringp minibuffer-default) ; bug#38992 + (stringp (or (car-safe minibuffer-default) + minibuffer-default)) ; bug#38992 bug#55800 (equal (icomplete--field-string) icomplete--initial-input)) ;; Here, we have a non-nil string default and ;; no input whatsoever. We want to make sure @@ -577,7 +578,9 @@ Usually run by inclusion in `minibuffer-setup-hook'." ;; Has "bar" at the top, so RET will select ;; it, as desired. ,(lambda (comp) - (equal minibuffer-default comp)) + (equal (or (car-safe minibuffer-default) + minibuffer-default) + comp)) ;; Why do we need this second predicate? ;; Because that'll make things like M-x man ;; RET RET, when invoked with point on the @@ -599,7 +602,9 @@ Usually run by inclusion in `minibuffer-setup-hook'." ;; useful for a very broad spectrum of ;; cases. ,(lambda (comp) - (string-prefix-p minibuffer-default comp)))) + (string-prefix-p (or (car-safe minibuffer-default) + minibuffer-default) + comp)))) ((and fido-mode (not minibuffer-default) (eq (icomplete--category) 'file)) commit 2745fc70cf045bf3aa3ffdc98264138aecb8adb5 Author: Eli Zaretskii Date: Sun Jun 12 20:43:24 2022 +0300 ; * lisp/isearch.el (isearch-search-fun-in-text-property): Doc fix. diff --git a/lisp/isearch.el b/lisp/isearch.el index fb52bfe30c..91aaa66a5b 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -4456,12 +4456,11 @@ LAX-WHITESPACE: The value of `isearch-lax-whitespace' and (defun isearch-search-fun-in-text-property (property &optional search-fun) - "Return the function that searches inside text properties. -The arg PROPERTY defines the name of the text property, and the search -will be narrowed to match only inside such text properties in the current -buffer. The optional arg SEARCH-FUN can provide the default search -function which is by default is the same as returned by -`isearch-search-fun-default'." + "Return the function to search inside text that has the specified PROPERTY. +The function will limit the search for matches only inside text which has +this property in the current buffer. +Optional argument SEARCH-FUN provides the function to search text, and +defaults to the value of `isearch-search-fun-default'." (lambda (string &optional bound noerror count) (let* ((old (point)) ;; Check if point is already on the property. commit f1e1392868d282bf1ee7623fcdf3d094509ba8dd Author: Eli Zaretskii Date: Sun Jun 12 19:48:34 2022 +0300 Change the API of 'update_redisplay_ticks' * src/xdisp.c (update_redisplay_ticks): Change the 2nd argument to be 'struct window'; all callers changed. diff --git a/src/dispextern.h b/src/dispextern.h index a919f364c1..0ea3ac8b07 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3505,7 +3505,7 @@ extern unsigned row_hash (struct glyph_row *); extern bool buffer_flipping_blocked_p (void); -extern void update_redisplay_ticks (int, struct it *); +extern void update_redisplay_ticks (int, struct window *); /* Defined in image.c */ diff --git a/src/xdisp.c b/src/xdisp.c index 9eba0ca886..27041cb162 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3222,7 +3222,7 @@ init_iterator (struct it *it, struct window *w, it->cmp_it.id = -1; - update_redisplay_ticks (0, it); + update_redisplay_ticks (0, w); /* Extra space between lines (on window systems only). */ if (base_face_id == DEFAULT_FACE_ID @@ -8177,7 +8177,7 @@ void set_iterator_to_next (struct it *it, bool reseat_p) { - update_redisplay_ticks (1, it); + update_redisplay_ticks (1, it->w); switch (it->method) { @@ -17171,17 +17171,14 @@ redisplay_window_1 (Lisp_Object window) Aborting runaway redisplay ***********************************************************************/ -/* Update the redisplay-tick count for a window, and signal an error +/* Update the redisplay-tick count for window W, and signal an error if the tick count is above some threshold, indicating that redisplay of the window takes "too long". - TICKS is the amount of ticks to add to the window's current count; - zero means to initialize the count to zero. - - IT is the iterator used for redisplay work; it->w is the window we - are working on. */ + TICKS is the amount of ticks to add to the W's current count; zero + means to initialize the count to zero. */ void -update_redisplay_ticks (int ticks, struct it *it) +update_redisplay_ticks (int ticks, struct window *w) { /* This keeps track of the window on which redisplay is working. */ static struct window *cwindow; @@ -17190,16 +17187,16 @@ update_redisplay_ticks (int ticks, struct it *it) /* We only initialize the count if this is a different window. Otherwise, this is a call from init_iterator for the same window we tracked before, and we should keep the count. */ - if (!ticks && it->w != cwindow) + if (!ticks && w != cwindow) { - cwindow = it->w; + cwindow = w; window_ticks = 0; } if (ticks > 0) window_ticks += ticks; if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks) error ("Window showing buffer %s takes too long to redisplay", - SSDATA (BVAR (XBUFFER (it->w->contents), name))); + SSDATA (BVAR (XBUFFER (w->contents), name))); } commit e42d4d2ddf4f193c2e3b9391fd6b4cb4ea3ba4b3 Author: Juri Linkov Date: Sun Jun 12 19:45:15 2022 +0300 * lisp/isearch.el (isearch-search-fun-in-text-property): Handle ^/$ specially. When the regexp contains ^ or $ then use a temporary buffer to find matches at the beginning/end of the region with the given text property (bug#14013). diff --git a/etc/NEWS b/etc/NEWS index 424d1250c3..6f00a51a70 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1575,6 +1575,12 @@ If non-nil (which is the default), hitting 'RET' or 'mouse-1' on the directory components at the directory displayed at the start of the buffer will take you to that directory. +--- +*** Search and replace in Dired/Wdired supports more regexps. +For example, the regexp ".*" will match only characters that are part +of the file name. Also "^.*$" can be used to match at the beginning +of the file name and at the end of the file name. + ** Exif --- diff --git a/lisp/isearch.el b/lisp/isearch.el index 5fbfb724a3..fb52bfe30c 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -4456,12 +4456,12 @@ LAX-WHITESPACE: The value of `isearch-lax-whitespace' and (defun isearch-search-fun-in-text-property (property &optional search-fun) - "Return the function that searches inside fields. -The arg PROPERTY defines the name of the text property that -delimits fields in the current buffer. Then the search will be -narrowed to match only on such text properties. The optional arg -SEARCH-FUN can provide the default search function which is -by default is the same as returned by `isearch-search-fun-default'." + "Return the function that searches inside text properties. +The arg PROPERTY defines the name of the text property, and the search +will be narrowed to match only inside such text properties in the current +buffer. The optional arg SEARCH-FUN can provide the default search +function which is by default is the same as returned by +`isearch-search-fun-default'." (lambda (string &optional bound noerror count) (let* ((old (point)) ;; Check if point is already on the property. @@ -4469,7 +4469,16 @@ by default is the same as returned by `isearch-search-fun-default'." (if isearch-forward old (max (1- old) (point-min))) property) old)) - end found) + end found (i 0) + (subregexp + (and isearch-regexp + (save-match-data + (catch 'subregexp + (while (string-match "\\^\\|\\$" string i) + (setq i (match-end 0)) + (when (subregexp-context-p string (match-beginning 0)) + ;; The ^/$ is not inside a char-range or escaped. + (throw 'subregexp t)))))))) ;; Otherwise, try to search for the next property. (unless beg (setq beg (if isearch-forward @@ -4482,12 +4491,47 @@ by default is the same as returned by `isearch-search-fun-default'." (setq end (if isearch-forward (next-single-property-change beg property) (previous-single-property-change beg property))) - (setq found (funcall (or search-fun (isearch-search-fun-default)) - string (if bound (if isearch-forward - (min bound end) - (max bound end)) - end) + ;; Handle ^/$ specially by matching in a temporary buffer. + (if subregexp + (let* ((prop-beg + (if (or (if isearch-forward (bobp) (eobp)) + (null (get-text-property + (+ (point) (if isearch-forward -1 0)) + property))) + ;; Already at the beginning of the field. + beg + ;; Get the real beginning of the field when + ;; the search was started in the middle. + (if isearch-forward + (previous-single-property-change beg property) + (next-single-property-change beg property)))) + (substring (buffer-substring prop-beg end)) + (offset (if isearch-forward prop-beg end)) + match-data) + (with-temp-buffer + (insert substring) + (goto-char (- beg offset -1)) + ;; Apply ^/$ regexp on the whole extracted substring. + (setq found (funcall + (or search-fun (isearch-search-fun-default)) + string (and bound (max (point-min) + (min (point-max) + (- bound offset -1)))) noerror count)) + ;; Adjust match data as if it's matched in original buffer. + (when found + (setq found (+ found offset -1) + match-data (mapcar (lambda (m) (+ m offset -1)) + (match-data))))) + (when match-data (set-match-data match-data))) + (setq found (funcall + (or search-fun (isearch-search-fun-default)) + string (if bound (if isearch-forward + (min bound end) + (max bound end)) + end) + noerror count))) + ;; Get the next text property. (unless found (setq beg (if isearch-forward (next-single-property-change end property) commit 5a596bbed58774070931fa84a74830e50ed75b3a Author: Eli Zaretskii Date: Sun Jun 12 17:44:35 2022 +0300 Fix a typo in a doc string. diff --git a/src/xdisp.c b/src/xdisp.c index 24f3167e7d..9eba0ca886 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -36723,7 +36723,7 @@ a window is aborted due to this reason, the buffer shown in that window will not have its windows redisplayed until the buffer is modified or until you type \\[recenter-top-bottom] with one of its windows selected. You can also decide to kill the buffer and visit it in some -other way, like udner `so-long-mode' or literally. +other way, like under `so-long-mode' or literally. The default value is zero, which disables this feature. The recommended non-zero value is between 50000 and 200000, commit e1e0315252d9f09ed061950630fe36b96349124e Author: Eli Zaretskii Date: Sun Jun 12 17:25:26 2022 +0300 Initial implementation of "abort-redisplay" feature * src/xdisp.c (update_redisplay_ticks): New function. (init_iterator, set_iterator_to_next): Call 'update_redisplay_ticks'. (syms_of_xdisp) : New variable. : Remove 'void-variable': it is no longer needed, since 'calc_pixel_width_or_height' can no longer signal a void-variable error, and it gets in the way of aborting redisplay via 'redisplay_window_error'. diff --git a/src/dispextern.h b/src/dispextern.h index c7399ca299..a919f364c1 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3505,6 +3505,8 @@ extern unsigned row_hash (struct glyph_row *); extern bool buffer_flipping_blocked_p (void); +extern void update_redisplay_ticks (int, struct it *); + /* Defined in image.c */ #ifdef HAVE_WINDOW_SYSTEM diff --git a/src/xdisp.c b/src/xdisp.c index 2245326b0d..24f3167e7d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -3222,6 +3222,8 @@ init_iterator (struct it *it, struct window *w, it->cmp_it.id = -1; + update_redisplay_ticks (0, it); + /* Extra space between lines (on window systems only). */ if (base_face_id == DEFAULT_FACE_ID && FRAME_WINDOW_P (it->f)) @@ -8175,6 +8177,8 @@ void set_iterator_to_next (struct it *it, bool reseat_p) { + update_redisplay_ticks (1, it); + switch (it->method) { case GET_FROM_BUFFER: @@ -16724,9 +16728,14 @@ redisplay_internal (void) list_of_error, redisplay_window_error); if (update_miniwindow_p) - internal_condition_case_1 (redisplay_window_1, - FRAME_MINIBUF_WINDOW (sf), list_of_error, - redisplay_window_error); + { + Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf); + + displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents); + internal_condition_case_1 (redisplay_window_1, mini_window, + list_of_error, + redisplay_window_error); + } /* Compare desired and current matrices, perform output. */ @@ -17156,6 +17165,43 @@ redisplay_window_1 (Lisp_Object window) redisplay_window (window, true); return Qnil; } + + +/*********************************************************************** + Aborting runaway redisplay + ***********************************************************************/ + +/* Update the redisplay-tick count for a window, and signal an error + if the tick count is above some threshold, indicating that + redisplay of the window takes "too long". + + TICKS is the amount of ticks to add to the window's current count; + zero means to initialize the count to zero. + + IT is the iterator used for redisplay work; it->w is the window we + are working on. */ +void +update_redisplay_ticks (int ticks, struct it *it) +{ + /* This keeps track of the window on which redisplay is working. */ + static struct window *cwindow; + static EMACS_INT window_ticks; + + /* We only initialize the count if this is a different window. + Otherwise, this is a call from init_iterator for the same window + we tracked before, and we should keep the count. */ + if (!ticks && it->w != cwindow) + { + cwindow = it->w; + window_ticks = 0; + } + if (ticks > 0) + window_ticks += ticks; + if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks) + error ("Window showing buffer %s takes too long to redisplay", + SSDATA (BVAR (XBUFFER (it->w->contents), name))); +} + /* Set cursor position of W. PT is assumed to be displayed in ROW. @@ -35777,7 +35823,7 @@ be let-bound around code that needs to disable messages temporarily. */); DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces"); - list_of_error = list1 (list2 (Qerror, Qvoid_variable)); + list_of_error = list1 (Qerror); staticpro (&list_of_error); /* Values of those variables at last redisplay are stored as @@ -36667,6 +36713,22 @@ and display the most important part of the minibuffer. */); This makes it easier to edit character sequences that are composed on display. */); composition_break_at_point = false; + + DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks, + doc: /* Maximum number of redisplay ticks before aborting redisplay of a window. + +This allows to abort the display of a window if the amount of low-level +redisplay operations exceeds the value of this variable. When display of +a window is aborted due to this reason, the buffer shown in that window +will not have its windows redisplayed until the buffer is modified or until +you type \\[recenter-top-bottom] with one of its windows selected. +You can also decide to kill the buffer and visit it in some +other way, like udner `so-long-mode' or literally. + +The default value is zero, which disables this feature. +The recommended non-zero value is between 50000 and 200000, +depending on your patience and the speed of your system. */); + max_redisplay_ticks = 0; } commit 1dd92bb7b8817038577626a13d7464a09e4d8a27 Author: Po Lu Date: Sun Jun 12 22:04:47 2022 +0800 Fix encoding of multibyte ToolTalk filenames * lisp/select.el (xselect-convert-to-dt-netfile): Encode file name before computing its tooltalk name, since the indices work on bytes. * test/lisp/dnd-tests.el (dnd-tests-begin-file-drag): Add test. diff --git a/lisp/select.el b/lisp/select.el index 417968b25c..127a6a5c61 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -783,11 +783,14 @@ VALUE should be SELECTION's local value." (stringp value) (file-exists-p value) (not (file-remote-p value))) - (cons 'STRING - (encode-coding-string (xselect-tt-net-file value) - (or file-name-coding-system - default-file-name-coding-system) - t)))) + (let ((name (encode-coding-string value + (or file-name-coding-system + default-file-name-coding-system)))) + (cons 'STRING + (encode-coding-string (xselect-tt-net-file name) + (or file-name-coding-system + default-file-name-coding-system) + t))))) (setq selection-converter-alist '((TEXT . xselect-convert-to-string) diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index c4b7567f22..dfd441b56d 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -184,10 +184,15 @@ This function only tries to handle strings." (not (eq window-system 'x)))) (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test") temporary-file-directory)) + (normal-multibyte-file (expand-file-name + (make-temp-name "тест-на-перетаскивание") + temporary-file-directory)) (remote-temp-file (dnd-tests-make-temp-name))) ;; Touch those files if they don't exist. (unless (file-exists-p normal-temp-file) (write-region "" 0 normal-temp-file)) + (unless (file-exists-p normal-multibyte-file) + (write-region "" 0 normal-multibyte-file)) (unless (file-exists-p remote-temp-file) (write-region "" 0 remote-temp-file)) (unwind-protect @@ -239,8 +244,20 @@ This function only tries to handle strings." (dnd-begin-file-drag normal-temp-file) (not dnd-last-dragged-remote-file))) ;; Test that links to remote files can't be created. - (should-error (dnd-begin-file-drag remote-temp-file nil 'link))) + (should-error (dnd-begin-file-drag remote-temp-file nil 'link)) + ;; Test dragging a file with a multibyte filename. + (should (eq (dnd-begin-file-drag normal-multibyte-file) 'copy)) + ;; Test that the ToolTalk filename is encodes and decodes correctly. + (let* ((netfile-data (cdr (dnd-tests-verify-selection-data '_DT_NETFILE))) + (parsed (dnd-tests-parse-tt-netfile netfile-data)) + (filename (encode-coding-string normal-multibyte-file + (or file-name-coding-system + default-file-name-coding-system)))) + (should (equal (nth 0 parsed) (system-name))) + (should (equal (nth 1 parsed) filename)) + (should (equal (nth 2 parsed) filename)))) (delete-file normal-temp-file) + (delete-file normal-multibyte-file) (delete-file remote-temp-file)))) (ert-deftest dnd-tests-begin-drag-files () commit 6263f586b87a952e00103a82af1dd0360c1a238d Author: Po Lu Date: Sun Jun 12 13:04:19 2022 +0000 Fix handling of scroll bar clicks on Haiku * src/haiku_support.cc (class EmacsView, BasicMouseDown) (BasicMouseUp): Move MouseDown and MouseUp here. New parameter `scroll_bar'. (MouseDown, MouseUp): Call basic variants. (class EmacsScrollBar): New field `parent'. (BScrollBar_make_for_view): Rename to `be_create_scroll_bar_for_view'. * src/haiku_support.h (struct haiku_button_event): New field `scroll_bar'. * src/haikuterm.c (haiku_scroll_bar_from_widget): Handle NULL widget. (haiku_scroll_bar_create): Update calls. (haiku_mouse_position): Fix scroll bar part. (haiku_read_socket): Handle button events on scroll bars as scroll bar click events. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index bc82069789..182f212847 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1826,10 +1826,10 @@ class EmacsView : public BView } void - MouseDown (BPoint point) + BasicMouseDown (BPoint point, BView *scroll_bar) { struct haiku_button_event rq; - uint32 buttons; + uint32 mods, buttons; this->GetMouse (&point, &buttons, false); @@ -1840,6 +1840,7 @@ class EmacsView : public BView grab_view_locker.Unlock (); rq.window = this->Window (); + rq.scroll_bar = scroll_bar; if (!(previous_buttons & B_PRIMARY_MOUSE_BUTTON) && (buttons & B_PRIMARY_MOUSE_BUTTON)) @@ -1858,7 +1859,7 @@ class EmacsView : public BView rq.x = point.x; rq.y = point.y; - uint32_t mods = modifiers (); + mods = modifiers (); rq.modifiers = 0; if (mods & B_SHIFT_KEY) @@ -1873,18 +1874,25 @@ class EmacsView : public BView if (mods & B_OPTION_KEY) rq.modifiers |= HAIKU_MODIFIER_SUPER; - SetMouseEventMask (B_POINTER_EVENTS, (B_LOCK_WINDOW_FOCUS - | B_NO_POINTER_HISTORY)); + if (!scroll_bar) + SetMouseEventMask (B_POINTER_EVENTS, (B_LOCK_WINDOW_FOCUS + | B_NO_POINTER_HISTORY)); rq.time = system_time (); haiku_write (BUTTON_DOWN, &rq); } void - MouseUp (BPoint point) + MouseDown (BPoint point) + { + BasicMouseDown (point, NULL); + } + + void + BasicMouseUp (BPoint point, BView *scroll_bar) { struct haiku_button_event rq; - uint32 buttons; + uint32 buttons, mods; this->GetMouse (&point, &buttons, false); @@ -1905,6 +1913,7 @@ class EmacsView : public BView } rq.window = this->Window (); + rq.scroll_bar = scroll_bar; if ((previous_buttons & B_PRIMARY_MOUSE_BUTTON) && !(buttons & B_PRIMARY_MOUSE_BUTTON)) @@ -1923,7 +1932,7 @@ class EmacsView : public BView rq.x = point.x; rq.y = point.y; - uint32_t mods = modifiers (); + mods = modifiers (); rq.modifiers = 0; if (mods & B_SHIFT_KEY) @@ -1938,12 +1947,15 @@ class EmacsView : public BView if (mods & B_OPTION_KEY) rq.modifiers |= HAIKU_MODIFIER_SUPER; - if (!buttons) - SetMouseEventMask (0, 0); - rq.time = system_time (); haiku_write (BUTTON_UP, &rq); } + + void + MouseUp (BPoint point) + { + BasicMouseUp (point, NULL); + } }; class EmacsScrollBar : public BScrollBar @@ -1965,15 +1977,18 @@ class EmacsScrollBar : public BScrollBar int max_value, real_max_value; int overscroll_start_value; bigtime_t repeater_start; + EmacsView *parent; - EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p) + EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p, + EmacsView *parent) : BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ? B_HORIZONTAL : B_VERTICAL), dragging (0), handle_button (false), in_overscroll (false), can_overscroll (false), - maybe_overscroll (false) + maybe_overscroll (false), + parent (parent) { BView *vw = (BView *) this; vw->SetResizingMode (B_FOLLOW_NONE); @@ -2174,7 +2189,6 @@ class EmacsScrollBar : public BScrollBar BLooper *looper; BMessage *message; int32 buttons, mods; - BView *parent; looper = Looper (); message = NULL; @@ -2195,8 +2209,9 @@ class EmacsScrollBar : public BScrollBar { /* Allow C-mouse-3 to split the window on a scroll bar. */ handle_button = true; - parent = Parent (); - parent->MouseDown (ConvertToParent (pt)); + SetMouseEventMask (B_POINTER_EVENTS, (B_SUSPEND_VIEW_FOCUS + | B_LOCK_WINDOW_FOCUS)); + parent->BasicMouseDown (ConvertToParent (pt), this); return; } @@ -2259,7 +2274,6 @@ class EmacsScrollBar : public BScrollBar MouseUp (BPoint pt) { struct haiku_scroll_bar_drag_event rq; - BView *parent; in_overscroll = false; maybe_overscroll = false; @@ -2267,8 +2281,7 @@ class EmacsScrollBar : public BScrollBar if (handle_button) { handle_button = false; - parent = Parent (); - parent->MouseUp (ConvertToParent (pt)); + parent->BasicMouseUp (ConvertToParent (pt), this); return; } @@ -3509,20 +3522,22 @@ BWindow_Flush (void *window) /* Make a scrollbar, attach it to VIEW's window, and return it. */ void * -BScrollBar_make_for_view (void *view, int horizontal_p, - int x, int y, int x1, int y1, - void *scroll_bar_ptr) +be_make_scroll_bar_for_view (void *view, int horizontal_p, + int x, int y, int x1, int y1) { - EmacsScrollBar *sb = new EmacsScrollBar (x, y, x1, y1, horizontal_p); + EmacsScrollBar *scroll_bar; BView *vw = (BView *) view; - BView *sv = (BView *) sb; if (!vw->LockLooper ()) gui_abort ("Failed to lock scrollbar owner"); - vw->AddChild ((BView *) sb); - sv->WindowActivated (vw->Window ()->IsActive ()); + + scroll_bar = new EmacsScrollBar (x, y, x1, y1, horizontal_p, + (EmacsView *) vw); + + vw->AddChild (scroll_bar); vw->UnlockLooper (); - return sb; + + return scroll_bar; } void diff --git a/src/haiku_support.h b/src/haiku_support.h index a2ad222f85..7f8d471b65 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -209,6 +209,7 @@ struct haiku_menu_bar_click_event struct haiku_button_event { void *window; + void *scroll_bar; int btn_no; int modifiers; int x; @@ -575,7 +576,7 @@ extern void *be_create_cursor_from_id (int); extern void *be_create_pixmap_cursor (void *, int, int); extern void be_delete_cursor (void *); -extern void *BScrollBar_make_for_view (void *, int, int, int, int, int, void *); +extern void *be_make_scroll_bar_for_view (void *, int, int, int, int, int); extern void BScrollBar_delete (void *); extern int BScrollBar_default_size (int); diff --git a/src/haikuterm.c b/src/haikuterm.c index 55d6a9be27..365b23cd92 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -516,6 +516,9 @@ haiku_scroll_bar_from_widget (void *scroll_bar, void *window) if (!frame) return NULL; + if (!scroll_bar) + return NULL; + if (!NILP (FRAME_SCROLL_BARS (frame))) { for (tem = FRAME_SCROLL_BARS (frame); !NILP (tem); @@ -2527,9 +2530,9 @@ haiku_scroll_bar_create (struct window *w, int left, int top, bar->update = -1; bar->horizontal = horizontal_p; - scroll_bar = BScrollBar_make_for_view (view, horizontal_p, - left, top, left + width - 1, - top + height - 1, bar); + scroll_bar = be_make_scroll_bar_for_view (view, horizontal_p, + left, top, left + width - 1, + top + height - 1); BView_publish_scroll_bar (view, left, top, width, height); bar->next = FRAME_SCROLL_BARS (f); @@ -2884,7 +2887,7 @@ haiku_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, x_display_list->last_mouse_glyph_frame = f1; *bar_window = Qnil; - *part = scroll_bar_above_handle; + *part = scroll_bar_nowhere; /* If track-mouse is `drag-source' and the mouse pointer is certain to not be actually under the chosen frame, return @@ -3471,13 +3474,13 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) Lisp_Object tab_bar_arg = Qnil; int tab_bar_p = 0, tool_bar_p = 0; bool up_okay_p = false; + struct scroll_bar *bar; if (popup_activated_p || !f) continue; - struct haiku_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); - inev.modifiers = haiku_modifiers_to_emacs (b->modifiers); + bar = haiku_scroll_bar_from_widget (b->scroll_bar, b->window); x_display_list->last_mouse_glyph_frame = 0; x_display_list->last_mouse_movement_time = b->time / 1000; @@ -3525,34 +3528,64 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) if (type == BUTTON_UP) { inev.modifiers |= up_modifier; - up_okay_p = (dpyinfo->grabbed & (1 << b->btn_no)); - dpyinfo->grabbed &= ~(1 << b->btn_no); + up_okay_p = (x_display_list->grabbed & (1 << b->btn_no)); + x_display_list->grabbed &= ~(1 << b->btn_no); } else { up_okay_p = true; inev.modifiers |= down_modifier; - dpyinfo->last_mouse_frame = f; - dpyinfo->grabbed |= (1 << b->btn_no); + x_display_list->last_mouse_frame = f; + x_display_list->grabbed |= (1 << b->btn_no); if (f && !tab_bar_p) f->last_tab_bar_item = -1; if (f && !tool_bar_p) f->last_tool_bar_item = -1; } - if (up_okay_p - && !(tab_bar_p && NILP (tab_bar_arg)) - && !tool_bar_p) + if (bar) + { + inev.kind = (bar->horizontal + ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT + : SCROLL_BAR_CLICK_EVENT); + inev.part = (bar->horizontal + ? scroll_bar_horizontal_handle + : scroll_bar_handle); + } + else if (up_okay_p + && !(tab_bar_p && NILP (tab_bar_arg)) + && !tool_bar_p) inev.kind = MOUSE_CLICK_EVENT; + inev.arg = tab_bar_arg; inev.code = b->btn_no; f->mouse_moved = false; - XSETINT (inev.x, b->x); - XSETINT (inev.y, b->y); + if (bar) + { + if (bar->horizontal) + { + XSETINT (inev.x, min (max (0, b->x - bar->left), + bar->width)); + XSETINT (inev.y, bar->width); + } + else + { + XSETINT (inev.x, min (max (0, b->y - bar->top), + bar->height)); + XSETINT (inev.y, bar->height); + } + + inev.frame_or_window = bar->window; + } + else + { + XSETINT (inev.x, b->x); + XSETINT (inev.y, b->y); + XSETFRAME (inev.frame_or_window, f); + } - XSETFRAME (inev.frame_or_window, f); break; } case ICONIFICATION: @@ -3652,8 +3685,9 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) inev.kind = (bar->horizontal ? HORIZONTAL_SCROLL_BAR_CLICK_EVENT : SCROLL_BAR_CLICK_EVENT); - inev.part = bar->horizontal ? - scroll_bar_horizontal_handle : scroll_bar_handle; + inev.part = (bar->horizontal + ? scroll_bar_horizontal_handle + : scroll_bar_handle); if (bar->horizontal) { commit d6f080d3de716fbaf790774aa1ceee1d00bff798 Author: Stefan Kangas Date: Sun Jun 12 12:41:15 2022 +0200 ; * doc/man/etags.1: Bump man page date. diff --git a/doc/man/etags.1 b/doc/man/etags.1 index 96781569fc..4681a9dadb 100644 --- a/doc/man/etags.1 +++ b/doc/man/etags.1 @@ -1,5 +1,5 @@ .\" See section COPYING for copyright and redistribution information. -.TH ETAGS 1 "2021-03-30" "GNU Tools" "GNU" +.TH ETAGS 1 "2022-06-10" "GNU Tools" "GNU" .de BP .sp .ti -.2i commit bab1d412801eead715f1465131aa3734558f35ab Author: Mattias Engdegård Date: Sun Jun 12 12:05:03 2022 +0200 Use BASE_EQ when comparing with Qunbound Qunbound is uninterned and can therefore never be EQ to any symbol with position. * src/buffer.c (Fbuffer_local_value, buffer_lisp_local_variables) (buffer_local_variables_1): * src/bytecode.c (exec_byte_code): * src/comp.c (compile_function, Fcomp__compile_ctxt_to_file): * src/composite.c (composition_gstring_cache_clear_font): * src/data.c (Fboundp, Fsymbol_value, set_internal) (Fdefault_boundp, Fdefault_value, Fmake_variable_buffer_local): * src/emacs-module.c (module_global_reference_p): * src/eval.c (Fdefault_toplevel_value, defvar) (run_hook_with_args): * src/fns.c (hash_put, Fmaphash): * src/font.c (font_put_extra): * src/frame.c (gui_set_frame_parameters) (gui_frame_get_and_record_arg, gui_default_parameter) (gui_figure_window_size): * src/haikufns.c (get_geometry_from_preferences) (haiku_create_frame, haiku_create_tip_frame): * src/haikuterm.c (haiku_draw_text_decoration) (haiku_default_font_parameter): * src/json.c (lisp_to_json_nonscalar_1): * src/keymap.c (access_keymap_1, access_keymap, current_minor_maps): * src/lread.c (readevalloop, define_symbol): * src/minibuf.c (read_minibuf, Ftry_completion): (Fall_completions, Ftest_completion): * src/pgtkfns.c (pgtk_default_font_parameter, Fx_create_frame) (x_create_tip_frame): * src/pgtkselect.c (Fpgtk_own_selection_internal): * src/print.c (print): * src/profiler.c (evict_lower_half, record_backtrace): * src/terminal.c (create_terminal): * src/textprop.c (set_properties): * src/w32fns.c (my_create_window, w32_icon) (w32_default_font_parameter, Fx_create_frame) (w32_create_tip_frame): * src/w32term.c (w32_draw_glyph_string): * src/xdisp.c (handle_single_display_spec) (cursor_row_fully_visible_p, calc_pixel_width_or_height): * src/xfns.c (x_default_scroll_bar_color_parameter, x_icon_verify) (x_icon, x_default_font_parameter, Fx_create_frame) (x_create_tip_frame): * src/xselect.c (x_handle_selection_request): * src/xterm.c (x_draw_glyph_string, x_term_init): Use BASE_EQ instead of EQ when comparing with Qunbound. diff --git a/src/buffer.c b/src/buffer.c index d2b2f25575..a0761f5b59 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -1218,7 +1218,7 @@ is the default binding of the variable. */) { register Lisp_Object result = buffer_local_value (variable, buffer); - if (EQ (result, Qunbound)) + if (BASE_EQ (result, Qunbound)) xsignal1 (Qvoid_variable, variable); return result; @@ -1313,7 +1313,7 @@ buffer_lisp_local_variables (struct buffer *buf, bool clone) if (buf != current_buffer) val = XCDR (elt); - result = Fcons (!clone && EQ (val, Qunbound) + result = Fcons (!clone && BASE_EQ (val, Qunbound) ? XCAR (elt) : Fcons (XCAR (elt), val), result); @@ -1336,7 +1336,7 @@ buffer_local_variables_1 (struct buffer *buf, int offset, Lisp_Object sym) { sym = NILP (sym) ? PER_BUFFER_SYMBOL (offset) : sym; Lisp_Object val = per_buffer_value (buf, offset); - return EQ (val, Qunbound) ? sym : Fcons (sym, val); + return BASE_EQ (val, Qunbound) ? sym : Fcons (sym, val); } return Qnil; } diff --git a/src/bytecode.c b/src/bytecode.c index a0bcbb4848..fa068e1ec6 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -627,7 +627,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, Lisp_Object v1 = vectorp[op], v2; if (!SYMBOLP (v1) || XSYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL - || (v2 = SYMBOL_VAL (XSYMBOL (v1)), EQ (v2, Qunbound))) + || (v2 = SYMBOL_VAL (XSYMBOL (v1)), BASE_EQ (v2, Qunbound))) v2 = Fsymbol_value (v1); PUSH (v2); NEXT; @@ -694,7 +694,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, /* Inline the most common case. */ if (SYMBOLP (sym) - && !EQ (val, Qunbound) + && !BASE_EQ (val, Qunbound) && XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL && !SYMBOL_TRAPPED_WRITE_P (sym)) SET_SYMBOL_VAL (XSYMBOL (sym), val); diff --git a/src/comp.c b/src/comp.c index 97bc6a5f9d..c230536ac5 100644 --- a/src/comp.c +++ b/src/comp.c @@ -4262,7 +4262,7 @@ compile_function (Lisp_Object func) { Lisp_Object block_name = HASH_KEY (ht, i); if (!EQ (block_name, Qentry) - && !EQ (block_name, Qunbound)) + && !BASE_EQ (block_name, Qunbound)) declare_block (block_name); } @@ -4275,7 +4275,7 @@ compile_function (Lisp_Object func) for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (ht); i++) { Lisp_Object block_name = HASH_KEY (ht, i); - if (!EQ (block_name, Qunbound)) + if (!BASE_EQ (block_name, Qunbound)) { Lisp_Object block = HASH_VALUE (ht, i); Lisp_Object insns = CALL1I (comp-block-insns, block); @@ -4890,12 +4890,12 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file, struct Lisp_Hash_Table *func_h = XHASH_TABLE (CALL1I (comp-ctxt-funcs-h, Vcomp_ctxt)); for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++) - if (!EQ (HASH_VALUE (func_h, i), Qunbound)) + if (!BASE_EQ (HASH_VALUE (func_h, i), Qunbound)) declare_function (HASH_VALUE (func_h, i)); /* Compile all functions. Can't be done before because the relocation structs has to be already defined. */ for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (func_h); i++) - if (!EQ (HASH_VALUE (func_h, i), Qunbound)) + if (!BASE_EQ (HASH_VALUE (func_h, i), Qunbound)) compile_function (HASH_VALUE (func_h, i)); /* Work around bug#46495 (GCC PR99126). */ diff --git a/src/composite.c b/src/composite.c index c2ade90d54..4d69702171 100644 --- a/src/composite.c +++ b/src/composite.c @@ -688,7 +688,7 @@ composition_gstring_cache_clear_font (Lisp_Object font_object) { Lisp_Object k = HASH_KEY (h, i); - if (!EQ (k, Qunbound)) + if (!BASE_EQ (k, Qunbound)) { Lisp_Object gstring = HASH_VALUE (h, i); diff --git a/src/data.c b/src/data.c index 46c0c5b6ae..cf180b16fb 100644 --- a/src/data.c +++ b/src/data.c @@ -699,7 +699,7 @@ global value outside of any lexical scope. */) default: emacs_abort (); } - return (EQ (valcontents, Qunbound) ? Qnil : Qt); + return (BASE_EQ (valcontents, Qunbound) ? Qnil : Qt); } /* It has been previously suggested to make this function an alias for @@ -1585,7 +1585,7 @@ global value outside of any lexical scope. */) Lisp_Object val; val = find_symbol_value (symbol); - if (!EQ (val, Qunbound)) + if (!BASE_EQ (val, Qunbound)) return val; xsignal1 (Qvoid_variable, symbol); @@ -1612,7 +1612,7 @@ void set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, enum Set_Internal_Bind bindflag) { - bool voide = EQ (newval, Qunbound); + bool voide = BASE_EQ (newval, Qunbound); /* If restoring in a dead buffer, do nothing. */ /* if (BUFFERP (where) && NILP (XBUFFER (where)->name)) @@ -1947,7 +1947,7 @@ context. Also see `default-value'. */) register Lisp_Object value; value = default_value (symbol); - return (EQ (value, Qunbound) ? Qnil : Qt); + return (BASE_EQ (value, Qunbound) ? Qnil : Qt); } DEFUN ("default-value", Fdefault_value, Sdefault_value, 1, 1, 0, @@ -1958,7 +1958,7 @@ local bindings in certain buffers. */) (Lisp_Object symbol) { Lisp_Object value = default_value (symbol); - if (!EQ (value, Qunbound)) + if (!BASE_EQ (value, Qunbound)) return value; xsignal1 (Qvoid_variable, symbol); @@ -2138,7 +2138,7 @@ See also `defvar-local'. */) case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start; case SYMBOL_PLAINVAL: forwarded = 0; valcontents.value = SYMBOL_VAL (sym); - if (EQ (valcontents.value, Qunbound)) + if (BASE_EQ (valcontents.value, Qunbound)) valcontents.value = Qnil; break; case SYMBOL_LOCALIZED: diff --git a/src/emacs-module.c b/src/emacs-module.c index 0d3cce0276..1c392d65df 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c @@ -411,7 +411,7 @@ module_global_reference_p (emacs_value v, ptrdiff_t *n) reference that's identical to some global reference. */ for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) { - if (!EQ (HASH_KEY (h, i), Qunbound) + if (!BASE_EQ (HASH_KEY (h, i), Qunbound) && &XMODULE_GLOBAL_REFERENCE (HASH_VALUE (h, i))->value == v) return true; } diff --git a/src/eval.c b/src/eval.c index d4d4a6cfdd..1c62b9248e 100644 --- a/src/eval.c +++ b/src/eval.c @@ -707,7 +707,7 @@ DEFUN ("default-toplevel-value", Fdefault_toplevel_value, Sdefault_toplevel_valu union specbinding *binding = default_toplevel_binding (symbol); Lisp_Object value = binding ? specpdl_old_value (binding) : Fdefault_value (symbol); - if (!EQ (value, Qunbound)) + if (!BASE_EQ (value, Qunbound)) return value; xsignal1 (Qvoid_variable, symbol); } @@ -774,7 +774,7 @@ defvar (Lisp_Object sym, Lisp_Object initvalue, Lisp_Object docstring, bool eval { /* Check if there is really a global binding rather than just a let binding that shadows the global unboundness of the var. */ union specbinding *binding = default_toplevel_binding (sym); - if (binding && EQ (specpdl_old_value (binding), Qunbound)) + if (binding && BASE_EQ (specpdl_old_value (binding), Qunbound)) { set_specpdl_old_value (binding, eval ? eval_sub (initvalue) : initvalue); @@ -2765,7 +2765,7 @@ run_hook_with_args (ptrdiff_t nargs, Lisp_Object *args, sym = args[0]; val = find_symbol_value (sym); - if (EQ (val, Qunbound) || NILP (val)) + if (BASE_EQ (val, Qunbound) || NILP (val)) return ret; else if (!CONSP (val) || FUNCTIONP (val)) { diff --git a/src/fns.c b/src/fns.c index ab1d9696a6..6094c00b27 100644 --- a/src/fns.c +++ b/src/fns.c @@ -4478,7 +4478,7 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value, /* Store key/value in the key_and_value vector. */ i = h->next_free; eassert (NILP (HASH_HASH (h, i))); - eassert (EQ (Qunbound, (HASH_KEY (h, i)))); + eassert (BASE_EQ (Qunbound, (HASH_KEY (h, i)))); h->next_free = HASH_NEXT (h, i); set_hash_key_slot (h, i, key); set_hash_value_slot (h, i, value); @@ -5219,7 +5219,7 @@ FUNCTION is called with two arguments, KEY and VALUE. for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) { Lisp_Object k = HASH_KEY (h, i); - if (!EQ (k, Qunbound)) + if (!BASE_EQ (k, Qunbound)) call2 (function, k, HASH_VALUE (h, i)); } diff --git a/src/font.c b/src/font.c index 6297452d3e..702536c1ca 100644 --- a/src/font.c +++ b/src/font.c @@ -731,7 +731,7 @@ font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val) { Lisp_Object prev = Qnil; - if (EQ (val, Qunbound)) + if (BASE_EQ (val, Qunbound)) return val; while (CONSP (extra) && NILP (Fstring_lessp (prop, XCAR (XCAR (extra))))) @@ -745,7 +745,7 @@ font_put_extra (Lisp_Object font, Lisp_Object prop, Lisp_Object val) return val; } XSETCDR (slot, val); - if (EQ (val, Qunbound)) + if (BASE_EQ (val, Qunbound)) ASET (font, FONT_EXTRA_INDEX, Fdelq (slot, extra)); return val; } diff --git a/src/frame.c b/src/frame.c index 46ac54d767..c21461d49f 100644 --- a/src/frame.c +++ b/src/frame.c @@ -4291,7 +4291,7 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) } /* Don't die if just one of these was set. */ - if (EQ (left, Qunbound)) + if (BASE_EQ (left, Qunbound)) { left_no_change = 1; if (f->left_pos < 0) @@ -4299,7 +4299,7 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object alist) else XSETINT (left, f->left_pos); } - if (EQ (top, Qunbound)) + if (BASE_EQ (top, Qunbound)) { top_no_change = 1; if (f->top_pos < 0) @@ -5457,7 +5457,7 @@ gui_frame_get_and_record_arg (struct frame *f, Lisp_Object alist, value = gui_display_get_arg (FRAME_DISPLAY_INFO (f), alist, param, attribute, class, type); - if (! NILP (value) && ! EQ (value, Qunbound)) + if (! NILP (value) && ! BASE_EQ (value, Qunbound)) store_frame_param (f, param, value); return value; @@ -5478,7 +5478,7 @@ gui_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop, Lisp_Object tem; tem = gui_frame_get_arg (f, alist, prop, xprop, xclass, type); - if (EQ (tem, Qunbound)) + if (BASE_EQ (tem, Qunbound)) tem = deflt; AUTO_FRAME_ARG (arg, prop, tem); gui_set_frame_parameters (f, arg); @@ -5740,9 +5740,9 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, height = gui_display_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER); width = gui_display_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER); - if (!EQ (width, Qunbound) || !EQ (height, Qunbound)) + if (!BASE_EQ (width, Qunbound) || !BASE_EQ (height, Qunbound)) { - if (!EQ (width, Qunbound)) + if (!BASE_EQ (width, Qunbound)) { if (CONSP (width) && EQ (XCAR (width), Qtext_pixels)) { @@ -5778,7 +5778,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, } } - if (!EQ (height, Qunbound)) + if (!BASE_EQ (height, Qunbound)) { if (CONSP (height) && EQ (XCAR (height), Qtext_pixels)) { @@ -5816,7 +5816,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, user_size = gui_display_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER); - if (!NILP (user_size) && !EQ (user_size, Qunbound)) + if (!NILP (user_size) && !BASE_EQ (user_size, Qunbound)) window_prompting |= USSize; else window_prompting |= PSize; @@ -5829,7 +5829,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, left = gui_display_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER); user_position = gui_display_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER); - if (! EQ (top, Qunbound) || ! EQ (left, Qunbound)) + if (! BASE_EQ (top, Qunbound) || ! BASE_EQ (left, Qunbound)) { if (EQ (top, Qminus)) { @@ -5852,7 +5852,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, else if (FLOATP (top)) f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done, &outer_done, 0); - else if (EQ (top, Qunbound)) + else if (BASE_EQ (top, Qunbound)) f->top_pos = 0; else { @@ -5882,7 +5882,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, else if (FLOATP (left)) f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done, &outer_done, 0); - else if (EQ (left, Qunbound)) + else if (BASE_EQ (left, Qunbound)) f->left_pos = 0; else { @@ -5891,7 +5891,7 @@ gui_figure_window_size (struct frame *f, Lisp_Object parms, bool tabbar_p, window_prompting |= XNegative; } - if (!NILP (user_position) && ! EQ (user_position, Qunbound)) + if (!NILP (user_position) && ! BASE_EQ (user_position, Qunbound)) window_prompting |= USPosition; else window_prompting |= PPosition; diff --git a/src/haikufns.c b/src/haikufns.c index 0b8bf89d85..b79443203f 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -99,7 +99,7 @@ get_geometry_from_preferences (struct haiku_display_info *dpyinfo, Lisp_Object value = gui_display_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls, RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (r[i].tem, value), parms); } } @@ -687,7 +687,7 @@ haiku_create_frame (Lisp_Object parms) display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING); - if (EQ (display, Qunbound)) + if (BASE_EQ (display, Qunbound)) display = Qnil; dpyinfo = check_haiku_display_info (display); kb = dpyinfo->terminal->kboard; @@ -698,7 +698,7 @@ haiku_create_frame (Lisp_Object parms) name = gui_display_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING); if (!STRINGP (name) - && ! EQ (name, Qunbound) + && ! BASE_EQ (name, Qunbound) && ! NILP (name)) error ("Invalid frame name--not a string or nil"); @@ -746,7 +746,7 @@ haiku_create_frame (Lisp_Object parms) /* Set the name; the functions to which we pass f expect the name to be set. */ - if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name)) + if (BASE_EQ (name, Qunbound) || NILP (name) || ! STRINGP (name)) { fset_name (f, Vinvocation_name); f->explicit_name = 0; @@ -859,7 +859,7 @@ haiku_create_frame (Lisp_Object parms) tem = gui_display_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); - f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !NILP (tem)); + f->no_split = minibuffer_only || (!BASE_EQ (tem, Qunbound) && !NILP (tem)); f->terminal->reference_count++; @@ -879,7 +879,7 @@ haiku_create_frame (Lisp_Object parms) Qparent_frame, NULL, NULL, RES_TYPE_SYMBOL); - if (EQ (parent_frame, Qunbound) + if (BASE_EQ (parent_frame, Qunbound) || NILP (parent_frame) || !FRAMEP (parent_frame) || !FRAME_LIVE_P (XFRAME (parent_frame))) @@ -933,7 +933,7 @@ haiku_create_frame (Lisp_Object parms) visibility = gui_display_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL); - if (EQ (visibility, Qunbound)) + if (BASE_EQ (visibility, Qunbound)) visibility = Qt; if (EQ (visibility, Qicon)) haiku_iconify_frame (f); @@ -1006,7 +1006,7 @@ haiku_create_tip_frame (Lisp_Object parms) name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); if (!STRINGP (name) - && !EQ (name, Qunbound) + && !BASE_EQ (name, Qunbound) && !NILP (name)) error ("Invalid frame name--not a string or nil"); @@ -1035,7 +1035,7 @@ haiku_create_tip_frame (Lisp_Object parms) /* Set the name; the functions to which we pass f expect the name to be set. */ - if (EQ (name, Qunbound) || NILP (name)) + if (BASE_EQ (name, Qunbound) || NILP (name)) f->explicit_name = false; else { @@ -1073,7 +1073,7 @@ haiku_create_tip_frame (Lisp_Object parms) value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, "internalBorder", "internalBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (Qinternal_border_width, value), parms); } diff --git a/src/haikuterm.c b/src/haikuterm.c index d47e61e60d..55d6a9be27 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -852,13 +852,13 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face, val = (WINDOW_BUFFER_LOCAL_VALUE (Qx_underline_at_descent_line, s->w)); underline_at_descent_line - = (!(NILP (val) || EQ (val, Qunbound)) + = (!(NILP (val) || BASE_EQ (val, Qunbound)) || s->face->underline_at_descent_line_p); val = (WINDOW_BUFFER_LOCAL_VALUE (Qx_use_underline_position_properties, s->w)); use_underline_position_properties - = !(NILP (val) || EQ (val, Qunbound)); + = !(NILP (val) || BASE_EQ (val, Qunbound)); /* Get the underline thickness. Default is 1 pixel. */ if (font && font->underline_thickness > 0) @@ -2939,7 +2939,7 @@ haiku_default_font_parameter (struct frame *f, Lisp_Object parms) Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, RES_TYPE_STRING); Lisp_Object font = Qnil; - if (EQ (font_param, Qunbound)) + if (BASE_EQ (font_param, Qunbound)) font_param = Qnil; if (NILP (font_param)) diff --git a/src/json.c b/src/json.c index db1be07f19..763f463aa4 100644 --- a/src/json.c +++ b/src/json.c @@ -364,7 +364,7 @@ lisp_to_json_nonscalar_1 (Lisp_Object lisp, for (ptrdiff_t i = 0; i < HASH_TABLE_SIZE (h); ++i) { Lisp_Object key = HASH_KEY (h, i); - if (!EQ (key, Qunbound)) + if (!BASE_EQ (key, Qunbound)) { CHECK_STRING (key); Lisp_Object ekey = json_encode (key); diff --git a/src/keymap.c b/src/keymap.c index da0a52bd2c..c8b01eed6f 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -395,7 +395,7 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, if (noinherit || NILP (retval)) /* If NOINHERIT, stop here, the rest is inherited. */ break; - else if (!EQ (retval, Qunbound)) + else if (!BASE_EQ (retval, Qunbound)) { Lisp_Object parent_entry; eassert (KEYMAPP (retval)); @@ -454,7 +454,7 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, } /* If we found a binding, clean it up and return it. */ - if (!EQ (val, Qunbound)) + if (!BASE_EQ (val, Qunbound)) { if (EQ (val, Qt)) /* A Qt binding is just like an explicit nil binding @@ -466,12 +466,12 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, if (!KEYMAPP (val)) { - if (NILP (retval) || EQ (retval, Qunbound)) + if (NILP (retval) || BASE_EQ (retval, Qunbound)) retval = val; if (!NILP (val)) break; /* Shadows everything that follows. */ } - else if (NILP (retval) || EQ (retval, Qunbound)) + else if (NILP (retval) || BASE_EQ (retval, Qunbound)) retval = val; else if (CONSP (retval_tail)) { @@ -487,7 +487,8 @@ access_keymap_1 (Lisp_Object map, Lisp_Object idx, maybe_quit (); } - return EQ (Qunbound, retval) ? get_keyelt (t_binding, autoload) : retval; + return BASE_EQ (Qunbound, retval) + ? get_keyelt (t_binding, autoload) : retval; } } @@ -496,7 +497,7 @@ access_keymap (Lisp_Object map, Lisp_Object idx, bool t_ok, bool noinherit, bool autoload) { Lisp_Object val = access_keymap_1 (map, idx, t_ok, noinherit, autoload); - return EQ (val, Qunbound) ? Qnil : val; + return BASE_EQ (val, Qunbound) ? Qnil : val; } static void @@ -1550,7 +1551,7 @@ current_minor_maps (Lisp_Object **modeptr, Lisp_Object **mapptr) for ( ; CONSP (alist); alist = XCDR (alist)) if ((assoc = XCAR (alist), CONSP (assoc)) && (var = XCAR (assoc), SYMBOLP (var)) - && (val = find_symbol_value (var), !EQ (val, Qunbound)) + && (val = find_symbol_value (var), !BASE_EQ (val, Qunbound)) && !NILP (val)) { Lisp_Object temp; diff --git a/src/lread.c b/src/lread.c index 1d20470a8b..77831f028e 100644 --- a/src/lread.c +++ b/src/lread.c @@ -2216,7 +2216,7 @@ readevalloop (Lisp_Object readcharfun, lexical environment, otherwise, turn off lexical binding. */ lex_bound = find_symbol_value (Qlexical_binding); specbind (Qinternal_interpreter_environment, - (NILP (lex_bound) || EQ (lex_bound, Qunbound) + (NILP (lex_bound) || BASE_EQ (lex_bound, Qunbound) ? Qnil : list1 (Qt))); specbind (Qmacroexp__dynvars, Vmacroexp__dynvars); @@ -4667,7 +4667,7 @@ define_symbol (Lisp_Object sym, char const *str) /* Qunbound is uninterned, so that it's not confused with any symbol 'unbound' created by a Lisp program. */ - if (! EQ (sym, Qunbound)) + if (! BASE_EQ (sym, Qunbound)) { Lisp_Object bucket = oblookup (initial_obarray, str, len, len); eassert (FIXNUMP (bucket)); diff --git a/src/minibuf.c b/src/minibuf.c index 2cfc2caa7f..1f77a6cdc1 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -760,7 +760,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, /* If variable is unbound, make it nil. */ histval = find_symbol_value (histvar); - if (EQ (histval, Qunbound)) + if (BASE_EQ (histval, Qunbound)) { Fset (histvar, Qnil); histval = Qnil; @@ -1693,7 +1693,8 @@ or from one of the possible completions. */) else /* if (type == hash_table) */ { while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection)) - && EQ (HASH_KEY (XHASH_TABLE (collection), idx), Qunbound)) + && BASE_EQ (HASH_KEY (XHASH_TABLE (collection), idx), + Qunbound)) idx++; if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection))) break; @@ -1930,7 +1931,8 @@ with a space are ignored unless STRING itself starts with a space. */) else /* if (type == 3) */ { while (idx < HASH_TABLE_SIZE (XHASH_TABLE (collection)) - && EQ (HASH_KEY (XHASH_TABLE (collection), idx), Qunbound)) + && BASE_EQ (HASH_KEY (XHASH_TABLE (collection), idx), + Qunbound)) idx++; if (idx >= HASH_TABLE_SIZE (XHASH_TABLE (collection))) break; @@ -2139,7 +2141,7 @@ the values STRING, PREDICATE and `lambda'. */) for (i = 0; i < HASH_TABLE_SIZE (h); ++i) { tem = HASH_KEY (h, i); - if (EQ (tem, Qunbound)) continue; + if (BASE_EQ (tem, Qunbound)) continue; Lisp_Object strkey = (SYMBOLP (tem) ? Fsymbol_name (tem) : tem); if (!STRINGP (strkey)) continue; if (EQ (Fcompare_strings (string, Qnil, Qnil, diff --git a/src/pgtkfns.c b/src/pgtkfns.c index 35e3c10589..294bdb3791 100644 --- a/src/pgtkfns.c +++ b/src/pgtkfns.c @@ -1068,7 +1068,7 @@ pgtk_default_font_parameter (struct frame *f, Lisp_Object parms) gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, RES_TYPE_STRING); Lisp_Object font = Qnil; - if (EQ (font_param, Qunbound)) + if (BASE_EQ (font_param, Qunbound)) font_param = Qnil; if (NILP (font_param)) @@ -1221,10 +1221,10 @@ This function is an internal primitive--use `make-frame' instead. */ ) display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); - if (EQ (display, Qunbound)) + if (BASE_EQ (display, Qunbound)) display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); - if (EQ (display, Qunbound)) + if (BASE_EQ (display, Qunbound)) display = Qnil; dpyinfo = check_pgtk_display_info (display); kb = dpyinfo->terminal->kboard; @@ -1235,7 +1235,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); - if (!STRINGP (name) && !EQ (name, Qunbound) && !NILP (name)) + if (!STRINGP (name) && !BASE_EQ (name, Qunbound) && !NILP (name)) error ("Invalid frame name--not a string or nil"); if (STRINGP (name)) @@ -1245,7 +1245,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); - if (EQ (parent, Qunbound)) + if (BASE_EQ (parent, Qunbound)) parent = Qnil; if (!NILP (parent)) CHECK_NUMBER (parent); @@ -1271,7 +1271,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) RES_TYPE_SYMBOL); /* Accept parent-frame iff parent-id was not specified. */ if (!NILP (parent) - || EQ (parent_frame, Qunbound) + || BASE_EQ (parent_frame, Qunbound) || NILP (parent_frame) || !FRAMEP (parent_frame) || !FRAME_LIVE_P (XFRAME (parent_frame)) @@ -1285,7 +1285,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) (tem = (gui_display_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN))) - && !(EQ (tem, Qunbound))) + && !(BASE_EQ (tem, Qunbound))) undecorated = true; FRAME_UNDECORATED (f) = undecorated; @@ -1295,7 +1295,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) (tem = (gui_display_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL, RES_TYPE_BOOLEAN))) - && !(EQ (tem, Qunbound))) + && !(BASE_EQ (tem, Qunbound))) override_redirect = true; FRAME_OVERRIDE_REDIRECT (f) = override_redirect; @@ -1371,7 +1371,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) /* Set the name; the functions to which we pass f expect the name to be set. */ - if (EQ (name, Qunbound) || NILP (name)) + if (BASE_EQ (name, Qunbound) || NILP (name)) { fset_name (f, build_string (dpyinfo->x_id_name)); f->explicit_name = false; @@ -1414,7 +1414,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, "internalBorder", "internalBorder", RES_TYPE_NUMBER); - if (!EQ (value, Qunbound)) + if (!BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (Qinternal_border_width, value), parms); } @@ -1431,7 +1431,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width, "childFrameBorder", "childFrameBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (Qchild_frame_border_width, value), parms); @@ -1695,7 +1695,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) } else { - if (EQ (visibility, Qunbound)) + if (BASE_EQ (visibility, Qunbound)) visibility = Qt; if (!NILP (visibility)) @@ -1709,7 +1709,7 @@ This function is an internal primitive--use `make-frame' instead. */ ) from `x-create-frame-with-faces' (see above comment). */ f->was_invisible = (f->was_invisible - && (!EQ (height, Qunbound) || !EQ (width, Qunbound))); + && (!BASE_EQ (height, Qunbound) || !BASE_EQ (width, Qunbound))); store_frame_param (f, Qvisibility, visibility); } @@ -2677,7 +2677,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); if (!STRINGP (name) - && !EQ (name, Qunbound) + && !BASE_EQ (name, Qunbound) && !NILP (name)) error ("Invalid frame name--not a string or nil"); @@ -2728,7 +2728,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct /* Set the name; the functions to which we pass f expect the name to be set. */ - if (EQ (name, Qunbound) || NILP (name)) + if (BASE_EQ (name, Qunbound) || NILP (name)) { fset_name (f, build_string (dpyinfo->x_id_name)); f->explicit_name = false; @@ -2769,7 +2769,7 @@ x_create_tip_frame (struct pgtk_display_info *dpyinfo, Lisp_Object parms, struct value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, "internalBorder", "internalBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (Qinternal_border_width, value), parms); } diff --git a/src/pgtkselect.c b/src/pgtkselect.c index 4c87aaa7ea..76901b9eb1 100644 --- a/src/pgtkselect.c +++ b/src/pgtkselect.c @@ -323,7 +323,7 @@ nil, it defaults to the selected frame. */) gtk_target_list_unref (list); } - if (!EQ (Vpgtk_sent_selection_hooks, Qunbound)) + if (!BASE_EQ (Vpgtk_sent_selection_hooks, Qunbound)) { /* FIXME: Use run-hook-with-args! */ for (rest = Vpgtk_sent_selection_hooks; CONSP (rest); diff --git a/src/print.c b/src/print.c index a82461653f..8f829ba684 100644 --- a/src/print.c +++ b/src/print.c @@ -1266,7 +1266,7 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) for (i = 0; i < HASH_TABLE_SIZE (h); ++i) { Lisp_Object key = HASH_KEY (h, i); - if (!EQ (key, Qunbound) + if (!BASE_EQ (key, Qunbound) && EQ (HASH_VALUE (h, i), Qt)) Fremhash (key, Vprint_number_table); } diff --git a/src/profiler.c b/src/profiler.c index 31a46d1b5e..5cb42d54fa 100644 --- a/src/profiler.c +++ b/src/profiler.c @@ -132,7 +132,7 @@ static void evict_lower_half (log_t *log) XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */ Fremhash (key, tmp); } - eassert (EQ (Qunbound, HASH_KEY (log, i))); + eassert (BASE_EQ (Qunbound, HASH_KEY (log, i))); eassert (log->next_free == i); eassert (VECTORP (key)); @@ -158,7 +158,7 @@ record_backtrace (log_t *log, EMACS_INT count) /* Get a "working memory" vector. */ Lisp_Object backtrace = HASH_VALUE (log, index); - eassert (EQ (Qunbound, HASH_KEY (log, index))); + eassert (BASE_EQ (Qunbound, HASH_KEY (log, index))); get_backtrace (backtrace); { /* We basically do a `gethash+puthash' here, except that we have to be diff --git a/src/terminal.c b/src/terminal.c index 80f3aed700..dcde8e9f55 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -290,13 +290,13 @@ create_terminal (enum output_method type, struct redisplay_interface *rif) keyboard_coding = find_symbol_value (intern ("default-keyboard-coding-system")); if (NILP (keyboard_coding) - || EQ (keyboard_coding, Qunbound) + || BASE_EQ (keyboard_coding, Qunbound) || NILP (Fcoding_system_p (keyboard_coding))) keyboard_coding = Qno_conversion; terminal_coding = find_symbol_value (intern ("default-terminal-coding-system")); if (NILP (terminal_coding) - || EQ (terminal_coding, Qunbound) + || BASE_EQ (terminal_coding, Qunbound) || NILP (Fcoding_system_p (terminal_coding))) terminal_coding = Qundecided; diff --git a/src/textprop.c b/src/textprop.c index 072aac2866..c11ee98f02 100644 --- a/src/textprop.c +++ b/src/textprop.c @@ -341,7 +341,7 @@ set_properties (Lisp_Object properties, INTERVAL interval, Lisp_Object object) for (sym = properties; PLIST_ELT_P (sym, value); sym = XCDR (value)) - if (EQ (property_value (interval->plist, XCAR (sym)), Qunbound)) + if (BASE_EQ (property_value (interval->plist, XCAR (sym)), Qunbound)) { record_property_change (interval->position, LENGTH (interval), XCAR (sym), Qnil, diff --git a/src/w32fns.c b/src/w32fns.c index a03fa3a665..8716b762eb 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -5548,11 +5548,11 @@ my_create_window (struct frame * f) RES_TYPE_NUMBER); top = gui_display_get_arg (dpyinfo, Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER); - if (EQ (left, Qunbound)) + if (BASE_EQ (left, Qunbound)) coords[0] = CW_USEDEFAULT; else coords[0] = XFIXNUM (left); - if (EQ (top, Qunbound)) + if (BASE_EQ (top, Qunbound)) coords[1] = CW_USEDEFAULT; else coords[1] = XFIXNUM (top); @@ -5668,12 +5668,12 @@ w32_icon (struct frame *f, Lisp_Object parms) RES_TYPE_NUMBER); icon_y = gui_display_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); - if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) + if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound)) { CHECK_FIXNUM (icon_x); CHECK_FIXNUM (icon_y); } - else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound)) + else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound)) error ("Both left and top icon corners of icon must be specified"); block_input (); @@ -5768,7 +5768,7 @@ w32_default_font_parameter (struct frame *f, Lisp_Object parms) parms, Qfont, NULL, NULL, RES_TYPE_STRING); Lisp_Object font; - if (EQ (font_param, Qunbound)) + if (BASE_EQ (font_param, Qunbound)) font_param = Qnil; font = !NILP (font_param) ? font_param : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font", @@ -5833,10 +5833,10 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, display = gui_display_get_arg (dpyinfo, parameters, Qterminal, 0, 0, RES_TYPE_NUMBER); - if (EQ (display, Qunbound)) + if (BASE_EQ (display, Qunbound)) display = gui_display_get_arg (dpyinfo, parameters, Qdisplay, 0, 0, RES_TYPE_STRING); - if (EQ (display, Qunbound)) + if (BASE_EQ (display, Qunbound)) display = Qnil; dpyinfo = check_x_display_info (display); kb = dpyinfo->terminal->kboard; @@ -5847,7 +5847,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, name = gui_display_get_arg (dpyinfo, parameters, Qname, "name", "Name", RES_TYPE_STRING); if (!STRINGP (name) - && ! EQ (name, Qunbound) + && ! BASE_EQ (name, Qunbound) && ! NILP (name)) error ("Invalid frame name--not a string or nil"); @@ -5857,7 +5857,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, /* See if parent window is specified. */ parent = gui_display_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); - if (EQ (parent, Qunbound)) + if (BASE_EQ (parent, Qunbound)) parent = Qnil; else if (!NILP (parent)) CHECK_FIXNUM (parent); @@ -5900,14 +5900,14 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, tem = gui_display_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN); - FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound); + FRAME_UNDECORATED (f) = !NILP (tem) && !BASE_EQ (tem, Qunbound); store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil); tem = gui_display_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL, RES_TYPE_BOOLEAN); - FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !EQ (tem, Qunbound); + FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !BASE_EQ (tem, Qunbound); store_frame_param (f, Qskip_taskbar, - (NILP (tem) || EQ (tem, Qunbound)) ? Qnil : Qt); + (NILP (tem) || BASE_EQ (tem, Qunbound)) ? Qnil : Qt); /* By default, make scrollbars the system standard width and height. */ FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); @@ -5963,7 +5963,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, /* Set the name; the functions to which we pass f expect the name to be set. */ - if (EQ (name, Qunbound) || NILP (name)) + if (BASE_EQ (name, Qunbound) || NILP (name)) { fset_name (f, build_string (dpyinfo->w32_id_name)); f->explicit_name = false; @@ -6003,7 +6003,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, value = gui_display_get_arg (dpyinfo, parameters, Qinternal_border_width, "internalBorder", "internalBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parameters = Fcons (Fcons (Qinternal_border_width, value), parameters); } @@ -6020,7 +6020,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, value = gui_display_get_arg (dpyinfo, parameters, Qchild_frame_border_width, "childFrameBorder", "childFrameBorder", RES_TYPE_NUMBER); - if (!EQ (value, Qunbound)) + if (!BASE_EQ (value, Qunbound)) parameters = Fcons (Fcons (Qchild_frame_border_width, value), parameters); } @@ -6219,7 +6219,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, w32_iconify_frame (f); else { - if (EQ (visibility, Qunbound)) + if (BASE_EQ (visibility, Qunbound)) visibility = Qt; if (!NILP (visibility)) @@ -7011,7 +7011,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); if (!STRINGP (name) - && !EQ (name, Qunbound) + && !BASE_EQ (name, Qunbound) && !NILP (name)) error ("Invalid frame name--not a string or nil"); Vx_resource_name = name; @@ -7045,7 +7045,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) /* Set the name; the functions to which we pass f expect the name to be set. */ - if (EQ (name, Qunbound) || NILP (name)) + if (BASE_EQ (name, Qunbound) || NILP (name)) { fset_name (f, build_string (dpyinfo->w32_id_name)); f->explicit_name = false; @@ -7084,7 +7084,7 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, "internalBorder", "internalBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (Qinternal_border_width, value), parms); } diff --git a/src/w32term.c b/src/w32term.c index 373c5b5f78..d0577efccc 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -2682,13 +2682,13 @@ w32_draw_glyph_string (struct glyph_string *s) val = (WINDOW_BUFFER_LOCAL_VALUE (Qx_underline_at_descent_line, s->w)); underline_at_descent_line - = (!(NILP (val) || EQ (val, Qunbound)) + = (!(NILP (val) || BASE_EQ (val, Qunbound)) || s->face->underline_at_descent_line_p); val = (WINDOW_BUFFER_LOCAL_VALUE (Qx_use_underline_position_properties, s->w)); use_underline_position_properties - = !(NILP (val) || EQ (val, Qunbound)); + = !(NILP (val) || BASE_EQ (val, Qunbound)); /* Get the underline thickness. Default is 1 pixel. */ if (font && font->underline_thickness > 0) diff --git a/src/xdisp.c b/src/xdisp.c index 2245326b0d..b02375ab2d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5894,7 +5894,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, location = tem; } - if (EQ (location, Qunbound)) + if (BASE_EQ (location, Qunbound)) { location = Qnil; value = spec; @@ -17852,7 +17852,7 @@ cursor_row_fully_visible_p (struct window *w, bool force_p, buffer_local_value (Qmake_cursor_line_fully_visible, w->contents); /* If no local binding, use the global value. */ - if (EQ (mclfv_p, Qunbound)) + if (BASE_EQ (mclfv_p, Qunbound)) mclfv_p = Vmake_cursor_line_fully_visible; /* Follow mode sets the variable to a Lisp function in buffers that are under Follow mode. */ @@ -28373,7 +28373,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, } prop = buffer_local_value (prop, it->w->contents); - if (EQ (prop, Qunbound)) + if (BASE_EQ (prop, Qunbound)) prop = Qnil; } @@ -28436,7 +28436,7 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, } car = buffer_local_value (car, it->w->contents); - if (EQ (car, Qunbound)) + if (BASE_EQ (car, Qunbound)) car = Qnil; } diff --git a/src/xfns.c b/src/xfns.c index 9882fd7ce1..05023524a7 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2450,7 +2450,7 @@ x_default_scroll_bar_color_parameter (struct frame *f, tem = gui_display_get_arg (dpyinfo, alist, prop, xprop, xclass, RES_TYPE_STRING); - if (EQ (tem, Qunbound)) + if (BASE_EQ (tem, Qunbound)) { #ifdef USE_TOOLKIT_SCROLL_BARS @@ -4224,12 +4224,12 @@ x_icon_verify (struct frame *f, Lisp_Object parms) icons in an icon window. */ icon_x = gui_frame_get_and_record_arg (f, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); icon_y = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); - if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound)) + if (!BASE_EQ (icon_x, Qunbound) && !BASE_EQ (icon_y, Qunbound)) { CHECK_FIXNUM (icon_x); CHECK_FIXNUM (icon_y); } - else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound)) + else if (!BASE_EQ (icon_x, Qunbound) || !BASE_EQ (icon_y, Qunbound)) error ("Both left and top icon corners of icon must be specified"); } @@ -4248,8 +4248,8 @@ x_icon (struct frame *f, Lisp_Object parms) = gui_frame_get_and_record_arg (f, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER); int icon_xval, icon_yval; - bool xgiven = !EQ (icon_x, Qunbound); - bool ygiven = !EQ (icon_y, Qunbound); + bool xgiven = !BASE_EQ (icon_x, Qunbound); + bool ygiven = !BASE_EQ (icon_y, Qunbound); if (xgiven != ygiven) error ("Both left and top icon corners of icon must be specified"); if (xgiven) @@ -4434,7 +4434,7 @@ x_default_font_parameter (struct frame *f, Lisp_Object parms) Lisp_Object font_param = gui_display_get_arg (dpyinfo, parms, Qfont, NULL, NULL, RES_TYPE_STRING); Lisp_Object font = Qnil; - if (EQ (font_param, Qunbound)) + if (BASE_EQ (font_param, Qunbound)) font_param = Qnil; if (NILP (font_param)) @@ -4563,10 +4563,10 @@ This function is an internal primitive--use `make-frame' instead. */) display = gui_display_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_NUMBER); - if (EQ (display, Qunbound)) + if (BASE_EQ (display, Qunbound)) display = gui_display_get_arg (dpyinfo, parms, Qdisplay, 0, 0, RES_TYPE_STRING); - if (EQ (display, Qunbound)) + if (BASE_EQ (display, Qunbound)) display = Qnil; dpyinfo = check_x_display_info (display); kb = dpyinfo->terminal->kboard; @@ -4577,7 +4577,7 @@ This function is an internal primitive--use `make-frame' instead. */) name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); if (!STRINGP (name) - && ! EQ (name, Qunbound) + && ! BASE_EQ (name, Qunbound) && ! NILP (name)) error ("Invalid frame name--not a string or nil"); @@ -4587,7 +4587,7 @@ This function is an internal primitive--use `make-frame' instead. */) /* See if parent window is specified. */ parent = gui_display_get_arg (dpyinfo, parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); - if (EQ (parent, Qunbound)) + if (BASE_EQ (parent, Qunbound)) parent = Qnil; if (! NILP (parent)) CHECK_FIXNUM (parent); @@ -4616,7 +4616,7 @@ This function is an internal primitive--use `make-frame' instead. */) RES_TYPE_SYMBOL); /* Accept parent-frame iff parent-id was not specified. */ if (!NILP (parent) - || EQ (parent_frame, Qunbound) + || BASE_EQ (parent_frame, Qunbound) || NILP (parent_frame) || !FRAMEP (parent_frame) || !FRAME_LIVE_P (XFRAME (parent_frame)) @@ -4632,7 +4632,7 @@ This function is an internal primitive--use `make-frame' instead. */) NULL, NULL, RES_TYPE_BOOLEAN))) - && !(EQ (tem, Qunbound))) + && !(BASE_EQ (tem, Qunbound))) undecorated = true; FRAME_UNDECORATED (f) = undecorated; @@ -4644,7 +4644,7 @@ This function is an internal primitive--use `make-frame' instead. */) NULL, NULL, RES_TYPE_BOOLEAN))) - && !(EQ (tem, Qunbound))) + && !(BASE_EQ (tem, Qunbound))) override_redirect = true; FRAME_OVERRIDE_REDIRECT (f) = override_redirect; @@ -4725,7 +4725,7 @@ This function is an internal primitive--use `make-frame' instead. */) /* Set the name; the functions to which we pass f expect the name to be set. */ - if (EQ (name, Qunbound) || NILP (name)) + if (BASE_EQ (name, Qunbound) || NILP (name)) { fset_name (f, build_string (dpyinfo->x_id_name)); f->explicit_name = false; @@ -4788,7 +4788,7 @@ This function is an internal primitive--use `make-frame' instead. */) value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, "internalBorder", "internalBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (Qinternal_border_width, value), parms); } @@ -4810,7 +4810,7 @@ This function is an internal primitive--use `make-frame' instead. */) value = gui_display_get_arg (dpyinfo, parms, Qchild_frame_border_width, "childFrameBorder", "childFrameBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (Qchild_frame_border_width, value), parms); } @@ -5052,7 +5052,7 @@ This function is an internal primitive--use `make-frame' instead. */) } else { - if (EQ (visibility, Qunbound)) + if (BASE_EQ (visibility, Qunbound)) visibility = Qt; if (!NILP (visibility)) @@ -5066,7 +5066,7 @@ This function is an internal primitive--use `make-frame' instead. */) from `x-create-frame-with-faces' (see above comment). */ f->was_invisible = (f->was_invisible - && (!EQ (height, Qunbound) || !EQ (width, Qunbound))); + && (!BASE_EQ (height, Qunbound) || !BASE_EQ (width, Qunbound))); store_frame_param (f, Qvisibility, visibility); } @@ -7861,7 +7861,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) name = gui_display_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING); if (!STRINGP (name) - && !EQ (name, Qunbound) + && !BASE_EQ (name, Qunbound) && !NILP (name)) error ("Invalid frame name--not a string or nil"); @@ -7928,7 +7928,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) /* Set the name; the functions to which we pass f expect the name to be set. */ - if (EQ (name, Qunbound) || NILP (name)) + if (BASE_EQ (name, Qunbound) || NILP (name)) { fset_name (f, build_string (dpyinfo->x_id_name)); f->explicit_name = false; @@ -7984,7 +7984,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) value = gui_display_get_arg (dpyinfo, parms, Qinternal_border_width, "internalBorder", "internalBorder", RES_TYPE_NUMBER); - if (! EQ (value, Qunbound)) + if (! BASE_EQ (value, Qunbound)) parms = Fcons (Fcons (Qinternal_border_width, value), parms); } diff --git a/src/xselect.c b/src/xselect.c index 17fe7403b2..bb5a1447df 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -870,7 +870,7 @@ x_handle_selection_request (struct selection_input_event *event) /* Run the `x-sent-selection-functions' abnormal hook. */ if (!NILP (Vx_sent_selection_functions) - && !EQ (Vx_sent_selection_functions, Qunbound)) + && !BASE_EQ (Vx_sent_selection_functions, Qunbound)) CALLN (Frun_hook_with_args, Qx_sent_selection_functions, selection_symbol, target_symbol, success ? Qt : Qnil); diff --git a/src/xterm.c b/src/xterm.c index 5ec6912fbd..f2306a6015 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -9376,13 +9376,13 @@ x_draw_glyph_string (struct glyph_string *s) val = (WINDOW_BUFFER_LOCAL_VALUE (Qx_underline_at_descent_line, s->w)); underline_at_descent_line - = (!(NILP (val) || EQ (val, Qunbound)) + = (!(NILP (val) || BASE_EQ (val, Qunbound)) || s->face->underline_at_descent_line_p); val = (WINDOW_BUFFER_LOCAL_VALUE (Qx_use_underline_position_properties, s->w)); use_underline_position_properties - = !(NILP (val) || EQ (val, Qunbound)); + = !(NILP (val) || BASE_EQ (val, Qunbound)); /* Get the underline thickness. Default is 1 pixel. */ if (font && font->underline_thickness > 0) @@ -25700,7 +25700,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) { terminal->kboard = allocate_kboard (Qx); - if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function, Qunbound)) + if (!BASE_EQ (XSYMBOL (Qvendor_specific_keysyms)->u.s.function, + Qunbound)) { char *vendor = ServerVendor (dpy); commit 980009e84c817b9a5357dfe4d735cb5c10b974bb Author: Lars Ingebrigtsen Date: Sun Jun 12 12:08:32 2022 +0200 Make find-sibling-file-search non-private * lisp/files.el (find-sibling-file-search): Rename to be non-private. (find-sibling-file): Adjust call. diff --git a/lisp/files.el b/lisp/files.el index 945b7ef737..eb1b90fc29 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7321,7 +7321,8 @@ The \"sibling\" file is defined by the `find-sibling-rules' variable." (list buffer-file-name))) (unless find-sibling-rules (user-error "The `find-sibling-rules' variable has not been configured")) - (let ((siblings (find-sibling-file--search (expand-file-name file)))) + (let ((siblings (find-sibling-file-search (expand-file-name file) + find-sibling-rules))) (cond ((null siblings) (user-error "Couldn't find any sibling files")) @@ -7336,16 +7337,19 @@ The \"sibling\" file is defined by the `find-sibling-rules' variable." (completing-read (format-prompt "Find file" (car relatives)) relatives nil t nil nil (car relatives)))))))) -(defun find-sibling-file--search (file) +(defun find-sibling-file-search (file &optional rules) + "Return a list of FILE's \"siblings\" +RULES should be a list on the form defined by `find-sibling-rules' (which +see), and if nil, defaults to `find-sibling-rules'." (let ((results nil)) - (pcase-dolist (`(,match . ,expansions) find-sibling-rules) + (pcase-dolist (`(,match . ,expansions) (or rules find-sibling-rules)) ;; Go through the list and find matches. (when (string-match match file) (let ((match-data (match-data))) (dolist (expansion expansions) (let ((start 0)) ;; Expand \\1 forms in the expansions. - (while (string-match "\\\\\\([0-9]+\\)" expansion start) + (while (string-match "\\\\\\([&0-9]+\\)" expansion start) (let ((index (string-to-number (match-string 1 expansion)))) (setq start (match-end 0) expansion commit dc5f6dcee22982906eb09037ee04471b34bb4be7 Author: Eli Zaretskii Date: Sun Jun 12 13:03:32 2022 +0300 Fix "C-x C-d" with wildcard arguments * lisp/files.el (list-directory): Make sure 'default-directory' is set to a valid value if the argument DIRNAME included wildcards. (Bug#55877) diff --git a/lisp/files.el b/lisp/files.el index 75a856c636..945b7ef737 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7406,9 +7406,9 @@ and `list-directory-verbose-switches'." ;; Finishing with-output-to-temp-buffer seems to clobber default-directory. (with-current-buffer buffer (setq default-directory - (if (file-directory-p dirname) + (if (file-accessible-directory-p dirname) (file-name-as-directory dirname) - (file-name-directory dirname)))))) + (file-name-directory (directory-file-name dirname))))))) (defun shell-quote-wildcard-pattern (pattern) "Quote characters special to the shell in PATTERN, leave wildcards alone. commit 5bf409329b1b678c633c79456288a1c4d6f0e804 Author: Po Lu Date: Sun Jun 12 16:41:40 2022 +0800 Fix phantom drag-and-drop targets showing up in some programs * src/xterm.c (x_dnd_cleanup_drag_and_drop) (x_dnd_begin_drag_and_drop): Delete XdndTypeList if it was set after the DND operation completes. Some programs apparently think its presence on the drag source means there are more than 3 targets. diff --git a/src/xterm.c b/src/xterm.c index 842de55e2f..5ec6912fbd 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4240,6 +4240,12 @@ x_dnd_cleanup_drag_and_drop (void *frame) if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + + /* Remove any type list set as well. */ + if (x_dnd_init_type_lists && x_dnd_n_targets > 3) + XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); + unblock_input (); x_dnd_frame = NULL; @@ -11263,6 +11269,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + + /* Remove any type list set as well. */ + if (x_dnd_init_type_lists && x_dnd_n_targets > 3) + XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); + /* Call kbd_buffer_store event, which calls handle_interrupt and sets `last-event-frame' along with various other things. */ @@ -11348,6 +11360,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + + + /* Remove any type list set as well. */ + if (x_dnd_init_type_lists && x_dnd_n_targets > 3) + XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); unblock_input (); quit (); @@ -11386,6 +11404,11 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + + /* Remove any type list set as well. */ + if (x_dnd_init_type_lists && x_dnd_n_targets > 3) + XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), + FRAME_DISPLAY_INFO (f)->Xatom_XdndTypeList); unblock_input (); if (x_dnd_return_frame == 3 commit c1829b307cffce046bec6fcbdff03dbab9f4b562 Author: Richard Hansen Date: Sun Jun 12 01:19:43 2022 -0400 bindat (str, strz): Reject non-ASCII, non-`eight-bit' characters * lisp/emacs-lisp/bindat.el (str) (strz): Signal an error if the user attempts to pack a multibyte string containing characters other than ASCII and `eight-bit' characters (bug#55897). * doc/lispref/processes.texi (Bindat Types): Update documentation. * test/lisp/emacs-lisp/bindat-tests.el (str) (strz): Add tests. diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index aa4d0e3ee4..8c8f8fd6b2 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3486,8 +3486,11 @@ When packing, the first @var{len} bytes of the input string are copied to the packed output. If the input string is shorter than @var{len}, the remaining bytes will be null (zero) unless a pre-allocated string was provided to @code{bindat-pack}, in which case the remaining bytes -are left unmodified. When unpacking, any null bytes in the packed -input string will appear in the unpacked output. +are left unmodified. If the input string is multibyte with only ASCII +and @code{eight-bit} characters, it is converted to unibyte before it +is packed; other multibyte strings signal an error. When unpacking, +any null bytes in the packed input string will appear in the unpacked +output. @item strz &optional @var{len} If @var{len} is not provided: Variable-length null-terminated unibyte @@ -3497,8 +3500,11 @@ null (zero) unless a pre-allocated string was provided to @code{bindat-pack}, in which case that byte is left unmodified. The length of the packed output is the length of the input string plus one (for the null terminator). The input string must not contain any null -bytes. When unpacking, the resulting string contains all bytes up to -(but excluding) the null byte. +bytes. If the input string is multibyte with only ASCII and +@code{eight-bit} characters, it is converted to unibyte before it is +packed; other multibyte strings signal an error. When unpacking, the +resulting string contains all bytes up to (but excluding) the null +byte. @quotation Caution If a pre-allocated string is provided to @code{bindat-pack}, the diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 84d5ea1e3b..2d6589b52d 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -435,12 +435,14 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." (bindat--pack-u32r (ash v -32))) (defun bindat--pack-str (len v) - (dotimes (i (min len (length v))) - (aset bindat-raw (+ bindat-idx i) (aref v i))) - (setq bindat-idx (+ bindat-idx len))) + (let ((v (string-to-unibyte v))) + (dotimes (i (min len (length v))) + (aset bindat-raw (+ bindat-idx i) (aref v i))) + (setq bindat-idx (+ bindat-idx len)))) (defun bindat--pack-strz (v) - (let ((len (length v))) + (let* ((v (string-to-unibyte v)) + (len (length v))) (dotimes (i len) (aset bindat-raw (+ bindat-idx i) (aref v i))) (setq bindat-idx (+ bindat-idx len 1)))) diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el index 1ce402977f..8bb3baa485 100644 --- a/test/lisp/emacs-lisp/bindat-tests.el +++ b/test/lisp/emacs-lisp/bindat-tests.el @@ -188,6 +188,22 @@ (apply #'bindat-pack (append (car tc) (list prealloc))) (should (equal prealloc (cdr tc)))))) +(ert-deftest bindat-test--str-strz-multibyte () + (dolist (spec (list (bindat-type str 2) + (bindat-type strz 2) + (bindat-type strz))) + (should (equal (bindat-pack spec (string-to-multibyte "x")) "x\0")) + (should (equal (bindat-pack spec (string-to-multibyte "\xff")) "\xff\0")) + (should-error (bindat-pack spec "💩")) + (should-error (bindat-pack spec "\N{U+ff}"))) + (dolist (spec (list '((x str 2)) '((x strz 2)))) + (should (equal (bindat-pack spec `((x . ,(string-to-multibyte "x")))) + "x\0")) + (should (equal (bindat-pack spec `((x . ,(string-to-multibyte "\xff")))) + "\xff\0")) + (should-error (bindat-pack spec '((x . "💩")))) + (should-error (bindat-pack spec '((x . "\N{U+ff}")))))) + (let ((spec (bindat-type strz 2))) (ert-deftest bindat-test--strz-fixedlen-len () (should (equal (bindat-length spec "") 2)) commit c2695621fc52aa5eeebc45b82b9b916e30568589 Author: Po Lu Date: Sun Jun 12 13:45:18 2022 +0800 Don't repetitively initialize type lists during DND * src/xterm.c (x_dnd_send_enter): Only set XdndTypeList once. (x_dnd_begin_drag_and_drop): Clear type list flag. diff --git a/src/xterm.c b/src/xterm.c index e282856374..842de55e2f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1162,6 +1162,10 @@ static int x_dnd_waiting_for_finish_proto; where the drag-and-drop operation originated. */ static bool x_dnd_allow_current_frame; +/* Whether or not the `XdndTypeList' property has already been set on + the drag frame. */ +static bool x_dnd_init_type_lists; + /* Whether or not to return a frame from `x_dnd_begin_drag_and_drop'. 0 means to do nothing. 1 means to wait for the mouse to first exit @@ -3987,12 +3991,16 @@ x_dnd_send_enter (struct frame *f, Window target, int supported) for (i = 0; i < min (3, x_dnd_n_targets); ++i) msg.xclient.data.l[i + 2] = x_dnd_targets[i]; - if (x_dnd_n_targets > 3) + if (x_dnd_n_targets > 3 && !x_dnd_init_type_lists) XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), dpyinfo->Xatom_XdndTypeList, XA_ATOM, 32, PropModeReplace, (unsigned char *) x_dnd_targets, x_dnd_n_targets); + /* Now record that the type list has already been set (if required), + so we don't have to set it again. */ + x_dnd_init_type_lists = true; + x_catch_errors (dpyinfo->display); XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg); x_uncatch_errors (); @@ -11036,6 +11044,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_toplevels = NULL; x_dnd_allow_current_frame = allow_current_frame; x_dnd_movement_frame = NULL; + x_dnd_init_type_lists = false; #ifdef HAVE_XKB x_dnd_keyboard_state = 0; commit 0451a76f975ed873f2be1c2bf9f976bf8aab5add Merge: 4a3a73dd32 cbd2c87a5d Author: Stefan Kangas Date: Sun Jun 12 06:30:25 2022 +0200 Merge from origin/emacs-28 cbd2c87a5d ; Fix last change in whitespace.el. 52ad2b53cb Fix doc strings in whitespace.el commit 4a3a73dd32bbb424cc3cbab31adc8a84d0b5916f Author: Stefan Monnier Date: Sat Jun 11 23:50:35 2022 -0400 * lisp/emacs-lisp/find-func.el (find-function-advised-original): Simplify diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index 2dec51dd04..ac84b50b5f 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -269,11 +269,7 @@ defined in C.") If FUNC is not a symbol, return it. Else, if it's not advised, return the symbol's function definition." (or (and (symbolp func) - (featurep 'nadvice) - (let ((ofunc (symbol-function func))) - (if (advice--p ofunc) - (advice--cd*r ofunc) - ofunc))) + (advice--cd*r (symbol-function func))) func)) (defun find-function-C-source (fun-or-var file type) commit 6aa8baaea1b872a9b770d680849b9b1b95eb2840 Author: Po Lu Date: Sun Jun 12 10:17:19 2022 +0800 Use cached monitor info during DND if available * src/xterm.c (x_dnd_begin_drag_and_drop): Use previously cached monitor attributes if they exist. diff --git a/src/xterm.c b/src/xterm.c index f422fc9d40..e282856374 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10988,8 +10988,15 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (follow_tooltip) { +#if defined HAVE_XRANDR || defined USE_GTK x_dnd_monitors - = Fx_display_monitor_attributes_list (frame); + = FRAME_DISPLAY_INFO (f)->last_monitor_attributes_list; + + if (NILP (x_dnd_monitors)) +#endif + x_dnd_monitors + = Fx_display_monitor_attributes_list (frame); + record_unwind_protect_void (x_clear_dnd_monitors); } commit 574c5d1de420b8257b6174b2023219d372f41919 Author: Po Lu Date: Sun Jun 12 10:13:04 2022 +0800 * src/nsfns.m (ns_move_tooltip_to_mouse_location): Handle invisible frames. diff --git a/src/nsfns.m b/src/nsfns.m index add4883e1f..5ab2b2ee35 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -3816,7 +3816,8 @@ - (Lisp_Object)lispString if (ns_tooltip) size = [ns_tooltip frame].size; else if (!FRAMEP (tip_frame) - || !FRAME_LIVE_P (XFRAME (tip_frame))) + || !FRAME_LIVE_P (XFRAME (tip_frame)) + || !FRAME_VISIBLE_P (XFRAME (tip_frame))) return; else { commit 0adbb21ece4af494e7050281dc022d5f7a11f196 Author: Po Lu Date: Sun Jun 12 09:32:30 2022 +0800 Don't rely on XdndAware on frames for dropping to work * src/xterm.c (x_dnd_get_target_window): New parameter WAS_FRAME. If toplevel is a frame, set it and clear proto and motif. (x_dnd_send_enter, x_dnd_send_position, x_dnd_send_leave) (x_dnd_send_drop): Remove special-cased self dropping code. (x_dnd_note_self_position, x_dnd_note_self_drop): New functions. (x_dnd_begin_drag_and_drop, x_dnd_update_state): (handle_one_xevent): Handle our own frames using those functions instead. diff --git a/src/xterm.c b/src/xterm.c index 3ca9149490..f422fc9d40 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1189,6 +1189,10 @@ static Window x_dnd_end_window; did not support XDND. */ static int x_dnd_last_protocol_version; +/* Whether or not the last seen window is actually one of our + frames. */ +static bool x_dnd_last_window_is_frame; + /* The Motif drag and drop protocol style of `x_dnd_last_seen_window'. XM_DRAG_STYLE_NONE means the window does not support the Motif drag or drop protocol. XM_DRAG_STYLE_DROP_ONLY means the window does @@ -3560,7 +3564,8 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo static Window x_dnd_get_target_window (struct x_display_info *dpyinfo, int root_x, int root_y, int *proto_out, - int *motif_out, Window *toplevel_out) + int *motif_out, Window *toplevel_out, + bool *was_frame) { Window child_return, child, proxy; int dest_x_return, dest_y_return, rc, proto, motif; @@ -3571,7 +3576,7 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, XWindowAttributes attrs; #endif int wmstate; - struct frame *tooltip; + struct frame *tooltip, *f; bool unrelated; child_return = dpyinfo->root_window; @@ -3581,6 +3586,7 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, proto = -1; *motif_out = XM_DRAG_STYLE_NONE; *toplevel_out = None; + *was_frame = false; if (x_dnd_use_toplevels) { @@ -3593,10 +3599,21 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, && FRAME_X_WINDOW (x_dnd_frame) == child) *motif_out = XM_DRAG_STYLE_NONE; + f = x_top_window_to_frame (dpyinfo, child); + *toplevel_out = child; if (child != None) { + if (f) + { + *was_frame = true; + *proto_out = -1; + *motif_out = XM_DRAG_STYLE_NONE; + + return child; + } + #ifndef USE_XCB proxy = x_dnd_get_window_proxy (dpyinfo, child); #else @@ -3736,6 +3753,18 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, break; } + f = x_top_window_to_frame (dpyinfo, child_return); + + if (f) + { + *proto_out = -1; + *motif_out = XM_DRAG_STYLE_NONE; + *toplevel_out = child_return; + *was_frame = true; + + return child_return; + } + if (x_dnd_get_wm_state_and_proto (dpyinfo, child_return, &wmstate, &proto, &motif, &proxy) @@ -3943,9 +3972,6 @@ x_dnd_send_enter (struct frame *f, Window target, int supported) int i; XEvent msg; - if (x_top_window_to_frame (dpyinfo, target)) - return; - msg.xclient.type = ClientMessage; msg.xclient.message_type = dpyinfo->Xatom_XdndEnter; msg.xclient.format = 32; @@ -3980,23 +4006,6 @@ x_dnd_send_position (struct frame *f, Window target, int supported, { struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); XEvent msg; - struct frame *target_frame; - int dest_x, dest_y; - Window child_return; - - target_frame = x_top_window_to_frame (dpyinfo, target); - - if (target_frame && XTranslateCoordinates (dpyinfo->display, - dpyinfo->root_window, - FRAME_X_WINDOW (target_frame), - root_x, root_y, &dest_x, - &dest_y, &child_return)) - { - x_dnd_movement_frame = target_frame; - x_dnd_movement_x = dest_x; - x_dnd_movement_y = dest_y; - return; - } if (target == x_dnd_mouse_rect_target && x_dnd_mouse_rect.width @@ -4054,9 +4063,6 @@ x_dnd_send_leave (struct frame *f, Window target) struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); XEvent msg; - if (x_top_window_to_frame (dpyinfo, target)) - return; - msg.xclient.type = ClientMessage; msg.xclient.message_type = dpyinfo->Xatom_XdndLeave; msg.xclient.format = 32; @@ -4076,74 +4082,17 @@ static bool x_dnd_send_drop (struct frame *f, Window target, Time timestamp, int supported) { - struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); + struct x_display_info *dpyinfo; XEvent msg; - struct input_event ie; - struct frame *self_frame; - int root_x, root_y, win_x, win_y, i; - unsigned int mask; - Window root, child; - Lisp_Object lval; - char **atom_names; - char *name; - - self_frame = x_top_window_to_frame (dpyinfo, target); - if (self_frame) - { - if (!x_dnd_allow_current_frame - && self_frame == x_dnd_frame) - return false; - - /* Send a special drag-and-drop event when dropping on top of an - Emacs frame to avoid all the overhead involved with sending - client events. */ - EVENT_INIT (ie); - - if (XQueryPointer (dpyinfo->display, FRAME_X_WINDOW (self_frame), - &root, &child, &root_x, &root_y, &win_x, &win_y, - &mask)) - { - ie.kind = DRAG_N_DROP_EVENT; - XSETFRAME (ie.frame_or_window, self_frame); - - lval = Qnil; - atom_names = alloca (x_dnd_n_targets * sizeof *atom_names); - name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, NULL); - - if (!XGetAtomNames (dpyinfo->display, x_dnd_targets, - x_dnd_n_targets, atom_names)) - { - xfree (name); - return false; - } - - for (i = x_dnd_n_targets; i != 0; --i) - { - lval = Fcons (intern (atom_names[i - 1]), lval); - XFree (atom_names[i - 1]); - } - - lval = Fcons (intern (name), lval); - lval = Fcons (QXdndSelection, lval); - ie.arg = lval; - ie.timestamp = timestamp; - - XSETINT (ie.x, win_x); - XSETINT (ie.y, win_y); - - xfree (name); - kbd_buffer_store_event (&ie); - - return false; - } - } - else if (x_dnd_action == None) + if (x_dnd_action == None) { x_dnd_send_leave (f, target); return false; } + dpyinfo = FRAME_DISPLAY_INFO (f); + msg.xclient.type = ClientMessage; msg.xclient.message_type = dpyinfo->Xatom_XdndDrop; msg.xclient.format = 32; @@ -4288,6 +4237,92 @@ x_dnd_cleanup_drag_and_drop (void *frame) x_dnd_frame = NULL; } +static void +x_dnd_note_self_position (struct x_display_info *dpyinfo, Window target, + unsigned short root_x, unsigned short root_y) +{ + struct frame *f; + int dest_x, dest_y; + Window child_return; + + f = x_top_window_to_frame (dpyinfo, target); + + if (f && XTranslateCoordinates (dpyinfo->display, + dpyinfo->root_window, + FRAME_X_WINDOW (f), + root_x, root_y, &dest_x, + &dest_y, &child_return)) + { + x_dnd_movement_frame = f; + x_dnd_movement_x = dest_x; + x_dnd_movement_y = dest_y; + + return; + } +} + +static void +x_dnd_note_self_drop (struct x_display_info *dpyinfo, Window target, + unsigned short root_x, unsigned short root_y, + Time timestamp) +{ + struct input_event ie; + struct frame *f; + Lisp_Object lval; + char **atom_names; + char *name; + int win_x, win_y, i; + Window dummy; + + if (!x_dnd_allow_current_frame + && (FRAME_OUTER_WINDOW (x_dnd_frame) + == target)) + return; + + f = x_top_window_to_frame (dpyinfo, target); + + if (!f) + return; + + if (!XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, + FRAME_X_WINDOW (f), root_x, root_y, + &win_x, &win_y, &dummy)) + return; + + EVENT_INIT (ie); + + ie.kind = DRAG_N_DROP_EVENT; + XSETFRAME (ie.frame_or_window, f); + + lval = Qnil; + atom_names = alloca (x_dnd_n_targets * sizeof *atom_names); + name = x_get_atom_name (dpyinfo, x_dnd_wanted_action, NULL); + + if (!XGetAtomNames (dpyinfo->display, x_dnd_targets, + x_dnd_n_targets, atom_names)) + { + xfree (name); + return; + } + + for (i = x_dnd_n_targets; i != 0; --i) + { + lval = Fcons (intern (atom_names[i - 1]), lval); + XFree (atom_names[i - 1]); + } + + lval = Fcons (intern (name), lval); + lval = Fcons (QXdndSelection, lval); + ie.arg = lval; + ie.timestamp = timestamp; + + XSETINT (ie.x, win_x); + XSETINT (ie.y, win_y); + + xfree (name); + kbd_buffer_store_event (&ie); +} + /* Flush display of frame F. */ static void @@ -10971,12 +11006,14 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, record_unwind_protect_void (release_xg_select); #endif + /* Initialize most of the state for the drag-and-drop operation. */ x_dnd_in_progress = true; x_dnd_recursion_depth = command_loop_level + minibuf_level; x_dnd_frame = f; x_dnd_last_seen_window = None; x_dnd_last_seen_toplevel = None; x_dnd_last_protocol_version = -1; + x_dnd_last_window_is_frame = false; x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; x_dnd_mouse_rect_target = None; x_dnd_action = None; @@ -15263,6 +15300,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) xm_top_level_enter_message emsg; xm_drag_motion_message dmsg; xm_drop_start_message dsmsg; + bool was_frame; if (XQueryPointer (dpyinfo->display, dpyinfo->root_window, @@ -15273,7 +15311,8 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) { target = x_dnd_get_target_window (dpyinfo, root_x, root_y, &target_proto, - &motif_style, &toplevel); + &motif_style, &toplevel, + &was_frame); if (toplevel != x_dnd_last_seen_toplevel) { @@ -15352,6 +15391,7 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) x_dnd_last_seen_window = target; x_dnd_last_protocol_version = target_proto; x_dnd_last_motif_style = motif_style; + x_dnd_last_window_is_frame = was_frame; if (target != None && x_dnd_last_protocol_version != -1) x_dnd_send_enter (x_dnd_frame, target, @@ -15376,7 +15416,9 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) } } - if (x_dnd_last_protocol_version != -1 && target != None) + if (x_dnd_last_window_is_frame && target != None) + x_dnd_note_self_position (dpyinfo, target, root_x, root_y); + else if (x_dnd_last_protocol_version != -1 && target != None) x_dnd_send_position (x_dnd_frame, target, x_dnd_last_protocol_version, root_x, root_y, @@ -17393,6 +17435,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xm_top_level_enter_message emsg; xm_drag_motion_message dmsg; XRectangle *r; + bool was_frame; /* Always clear mouse face. */ clear_mouse_face (hlinfo); @@ -17431,7 +17474,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, event->xmotion.x_root, event->xmotion.y_root, &target_proto, - &motif_style, &toplevel); + &motif_style, &toplevel, + &was_frame); if (toplevel != x_dnd_last_seen_toplevel) { @@ -17531,6 +17575,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_last_seen_window = target; x_dnd_last_protocol_version = target_proto; x_dnd_last_motif_style = motif_style; + x_dnd_last_window_is_frame = was_frame; if (target != None && x_dnd_last_protocol_version != -1) x_dnd_send_enter (x_dnd_frame, target, @@ -17555,7 +17600,11 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } - if (x_dnd_last_protocol_version != -1 && target != None) + if (x_dnd_last_window_is_frame && target != None) + x_dnd_note_self_position (dpyinfo, target, + event->xbutton.x_root, + event->xbutton.y_root); + else if (x_dnd_last_protocol_version != -1 && target != None) x_dnd_send_position (x_dnd_frame, target, x_dnd_last_protocol_version, event->xmotion.x_root, @@ -18105,6 +18154,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_finish_frame = x_dnd_frame; if (x_dnd_last_seen_window != None + && x_dnd_last_window_is_frame) + { + x_dnd_waiting_for_finish = false; + x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window, + event->xbutton.time, event->xbutton.x_root, + event->xbutton.y_root); + } + else if (x_dnd_last_seen_window != None && x_dnd_last_protocol_version != -1) { x_dnd_pending_finish_target = x_dnd_last_seen_window; @@ -18188,6 +18245,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; x_dnd_last_seen_window = None; x_dnd_last_seen_toplevel = None; + x_dnd_last_window_is_frame = false; x_dnd_frame = NULL; } } @@ -19096,6 +19154,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, Window target, toplevel; int target_proto, motif_style; XRectangle *r; + bool was_frame; /* Always clear mouse face. */ clear_mouse_face (hlinfo); @@ -19136,7 +19195,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, xev->root_y, &target_proto, &motif_style, - &toplevel); + &toplevel, + &was_frame); if (toplevel != x_dnd_last_seen_toplevel) { @@ -19238,6 +19298,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_last_seen_window = target; x_dnd_last_protocol_version = target_proto; x_dnd_last_motif_style = motif_style; + x_dnd_last_window_is_frame = was_frame; if (target != None && x_dnd_last_protocol_version != -1) x_dnd_send_enter (x_dnd_frame, target, @@ -19262,7 +19323,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } - if (x_dnd_last_protocol_version != -1 && target != None) + if (x_dnd_last_window_is_frame && target != None) + x_dnd_note_self_position (dpyinfo, target, + xev->root_x, xev->root_y); + else if (x_dnd_last_protocol_version != -1 && target != None) { dnd_state = xev->mods.effective; @@ -19489,7 +19553,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_finish_frame = x_dnd_frame; if (x_dnd_last_seen_window != None - && x_dnd_last_protocol_version != -1) + && x_dnd_last_window_is_frame) + { + x_dnd_waiting_for_finish = false; + x_dnd_note_self_drop (dpyinfo, x_dnd_last_seen_window, + xev->time, xev->root_x, xev->root_y); + } + else if (x_dnd_last_seen_window != None + && x_dnd_last_protocol_version != -1) { x_dnd_pending_finish_target = x_dnd_last_seen_window; x_dnd_waiting_for_finish_proto = x_dnd_last_protocol_version; @@ -19579,6 +19650,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_last_motif_style = XM_DRAG_STYLE_NONE; x_dnd_last_seen_window = None; x_dnd_last_seen_toplevel = None; + x_dnd_last_window_is_frame = false; x_dnd_frame = NULL; goto XI_OTHER; commit 98365c7b1e1e1d3d5f7185f2d4a2baa1c65b4540 Author: Mattias Engdegård Date: Sat Jun 11 18:44:37 2022 +0200 * src/fns.c (internal_equal): Use BASE_EQ where possible. diff --git a/src/fns.c b/src/fns.c index fceab9ba0c..ab1d9696a6 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2519,7 +2519,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, if (SYMBOL_WITH_POS_P (o2)) o2 = SYMBOL_WITH_POS_SYM (o2); - if (EQ (o1, o2)) + if (BASE_EQ (o1, o2)) return true; if (XTYPE (o1) != XTYPE (o2)) return false; commit e53428994e31f22f4f93eef3da250ac4d6dda93a Author: Basil L. Contovounesios Date: Sat Jun 11 15:50:09 2022 +0300 Recognize processes as a CL type again For discussion, see: https://lists.gnu.org/r/emacs-devel/2022-06/msg00567.html * lisp/emacs-lisp/cl-macs.el (cl-deftype-satisfies): Include process as a type, to avoid cl-typep complaining about process objects. diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index ada4f0344d..10043ba280 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -3422,6 +3422,7 @@ Of course, we really can't know that for sure, so it's just a heuristic." (number . numberp) (null . null) (overlay . overlayp) + (process . processp) (real . numberp) (sequence . sequencep) (subr . subrp) commit eec9919b999837128e910d5774ce7a6588ae8886 Author: Lars Ingebrigtsen Date: Sat Jun 11 18:15:35 2022 +0200 Make new fileio test more reliable * test/src/fileio-tests.el: Use a unibyte buffer to avoid length confusion. diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el index 29f11fc472..c137ce06f1 100644 --- a/test/src/fileio-tests.el +++ b/test/src/fileio-tests.el @@ -196,6 +196,7 @@ Also check that an encoding error can appear in a symlink." (ert-deftest fileio-tests--non-regular-insert () (skip-unless (file-exists-p "/dev/urandom")) (with-temp-buffer + (set-buffer-multibyte nil) (should-error (insert-file-contents "/dev/urandom" nil 5 10)) (insert-file-contents "/dev/urandom" nil nil 10) (should (= (buffer-size) 10)))) commit c3138ba1b1742422c62c889e75a7ddda9319a2c6 Author: Lars Ingebrigtsen Date: Sat Jun 11 18:13:06 2022 +0200 Bump sh-imenu-generic-expression defcustom version * lisp/progmodes/sh-script.el (sh-imenu-generic-expression): Bump the :version since we changed the value. diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index 04f65b8dca..75758fd39a 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -319,7 +319,7 @@ See `sh-feature' and `imenu-generic-expression'." :value-type (repeat :tag "Regexp, index..." sexp))) :group 'sh-script - :version "20.4") + :version "29.1") (defun sh-current-defun-name () "Find the name of function or variable at point. commit ad432c1644e27976c579a998a08752a55ffcafa1 Author: Lars Ingebrigtsen Date: Sat Jun 11 17:59:23 2022 +0200 Fix loaddefs installation of packages with no autoloads * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate): Always generate an output file if we have EXTRA-DATA. This fixes package installation of packages with no ;;;###autoload forms. diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index 5280941cfc..95666ddb2a 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -514,7 +514,9 @@ its autoloads into the specified file instead. The function does NOT recursively descend into subdirectories of the directory or directories specified. -If EXTRA-DATA, include this string at the start of the generated file. +If EXTRA-DATA, include this string at the start of the generated +file. This will also force generation of OUTPUT-FILE even if +there are no autoloads to put into the file. If INCLUDE-PACKAGE-VERSION, include package version data. @@ -562,56 +564,66 @@ If GENERATE-FULL, don't update, but regenerate all the loaddefs files." defs)))) (progress-reporter-done progress)) - ;; Generate the loaddef files. First group per output file. - (dolist (fdefs (seq-group-by #'car defs)) - (let ((loaddefs-file (car fdefs))) + ;; If we have no autoloads data, but we have EXTRA-DATA, then + ;; generate the (almost) empty file anyway. + (if (and (not defs) extra-data) (with-temp-buffer - (if (and updating (file-exists-p loaddefs-file)) - (insert-file-contents loaddefs-file) - (insert (loaddefs-generate--rubric loaddefs-file nil t)) - (search-backward "\f") - (when extra-data - (insert extra-data) - (ensure-empty-lines 1))) - ;; Then group by source file (and sort alphabetically). - (dolist (section (sort (seq-group-by #'cadr (cdr fdefs)) - (lambda (e1 e2) - (string< - (file-name-sans-extension - (file-name-nondirectory (car e1))) - (file-name-sans-extension - (file-name-nondirectory (car e2))))))) - (pop section) - (let* ((relfile (file-relative-name - (cadar section) - (file-name-directory loaddefs-file))) - (head (concat "\n\f\n;;; Generated autoloads from " - relfile "\n\n"))) - (when (file-exists-p loaddefs-file) - ;; If we're updating an old loaddefs file, then see if - ;; there's a section here for this file already. - (goto-char (point-min)) - (if (not (search-forward head nil t)) - ;; It's a new file; put the data at the end. - (progn - (goto-char (point-max)) - (search-backward "\f\n")) - ;; Delete the old version of the section. - (delete-region (match-beginning 0) - (and (search-forward "\n\f\n;;;") - (match-beginning 0))) - (forward-line -2))) - (insert head) - (dolist (def (reverse section)) - (setq def (caddr def)) - (if (stringp def) - (princ def (current-buffer)) - (loaddefs-generate--print-form def)) - (unless (bolp) - (insert "\n"))))) - (write-region (point-min) (point-max) loaddefs-file nil 'silent) - (byte-compile-info (file-relative-name loaddefs-file lisp-directory) - t "GEN")))))) + (insert (loaddefs-generate--rubric output-file nil t)) + (search-backward "\f") + (insert extra-data) + (ensure-empty-lines 1) + (write-region (point-min) (point-max) output-file nil 'silent)) + ;; We have some data, so generate the loaddef files. First + ;; group per output file. + (dolist (fdefs (seq-group-by #'car defs)) + (let ((loaddefs-file (car fdefs))) + (with-temp-buffer + (if (and updating (file-exists-p loaddefs-file)) + (insert-file-contents loaddefs-file) + (insert (loaddefs-generate--rubric loaddefs-file nil t)) + (search-backward "\f") + (when extra-data + (insert extra-data) + (ensure-empty-lines 1))) + ;; Then group by source file (and sort alphabetically). + (dolist (section (sort (seq-group-by #'cadr (cdr fdefs)) + (lambda (e1 e2) + (string< + (file-name-sans-extension + (file-name-nondirectory (car e1))) + (file-name-sans-extension + (file-name-nondirectory (car e2))))))) + (pop section) + (let* ((relfile (file-relative-name + (cadar section) + (file-name-directory loaddefs-file))) + (head (concat "\n\f\n;;; Generated autoloads from " + relfile "\n\n"))) + (when (file-exists-p loaddefs-file) + ;; If we're updating an old loaddefs file, then see if + ;; there's a section here for this file already. + (goto-char (point-min)) + (if (not (search-forward head nil t)) + ;; It's a new file; put the data at the end. + (progn + (goto-char (point-max)) + (search-backward "\f\n")) + ;; Delete the old version of the section. + (delete-region (match-beginning 0) + (and (search-forward "\n\f\n;;;") + (match-beginning 0))) + (forward-line -2))) + (insert head) + (dolist (def (reverse section)) + (setq def (caddr def)) + (if (stringp def) + (princ def (current-buffer)) + (loaddefs-generate--print-form def)) + (unless (bolp) + (insert "\n"))))) + (write-region (point-min) (point-max) loaddefs-file nil 'silent) + (byte-compile-info (file-relative-name loaddefs-file lisp-directory) + t "GEN"))))))) (defun loaddefs-generate--print-form (def) "Print DEF in the way make-docfile.c expects it." commit 36b5050ec436d2703005cc862edc510ff6a3b4cf Author: Stefan Monnier Date: Sat Jun 11 11:57:25 2022 -0400 fileio-tests.el (test-non-regular-insert): Fix thinko * test/src/fileio-tests.el (fileio-tests--non-regular-insert): Rename from `test-non-regular-insert` and make it into a test rather than a broken function. Oh, and make it work while at it. diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el index a9a43781d4..29f11fc472 100644 --- a/test/src/fileio-tests.el +++ b/test/src/fileio-tests.el @@ -138,7 +138,7 @@ Also check that an encoding error can appear in a symlink." (should (and (file-name-absolute-p name) (not (eq (aref name 0) ?~)))))) -(ert-deftest fileio-test--expand-file-name-null-bytes () +(ert-deftest fileio-tests--expand-file-name-null-bytes () "Test that `expand-file-name' checks for null bytes in filenames." (should-error (expand-file-name (concat "file" (char-to-string ?\0) ".txt")) :type 'wrong-type-argument) @@ -193,11 +193,11 @@ Also check that an encoding error can appear in a symlink." (should (equal (file-name-concat "" "bar") "bar")) (should (equal (file-name-concat "" "") ""))) -(defun test-non-regular-insert () +(ert-deftest fileio-tests--non-regular-insert () (skip-unless (file-exists-p "/dev/urandom")) (with-temp-buffer (should-error (insert-file-contents "/dev/urandom" nil 5 10)) (insert-file-contents "/dev/urandom" nil nil 10) - (should (= (point-max) 10)))) + (should (= (buffer-size) 10)))) ;;; fileio-tests.el ends here commit 51def94e9c0ce81511ce1364c9adf2cd047a38bc Author: Stefan Monnier Date: Sat Jun 11 11:55:27 2022 -0400 Bindat: Document `sint`; add `le` arg to `uint`; deprecate `uintr` * lisp/emacs-lisp/bindat.el (bindat--type) : Add `le` optional arg. (bindat--type) : Delete method. (uintr): Re-define as a bindat-macro instead. (bindat-type): Update docstring accordingly. (bindat--primitives): Update. (sint): Simplify. * doc/lispref/processes.texi (Bindat Types): Update `uint`, add `sint`, and remove `uintr`. * test/lisp/emacs-lisp/bindat-tests.el (data-bindat-spec): Use the new `le` arg of `uint` instead of `uintr`. diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 55fb93ec5a..aa4d0e3ee4 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3470,13 +3470,15 @@ type values: @itemx byte Unsigned byte, with length 1. -@item uint @var{bitlen} -Unsigned integer in network byte order, with @var{bitlen} bits. +@item uint @var{bitlen} &optional @var{le} +Unsigned integer in network byte order (big-endian), with @var{bitlen} bits. @var{bitlen} has to be a multiple of 8. +If @var{le} is non-@code{nil}, then use little-endian byte order. -@item uintr @var{bitlen} -Unsigned integer in little endian order, with @var{bitlen} bits. +@item sint @var{bitlen} @var{le} +Signed integer in network byte order (big-endian), with @var{bitlen} bits. @var{bitlen} has to be a multiple of 8. +If @var{le} is non-@code{nil}, then use little-endian byte order. @item str @var{len} Unibyte string (@pxref{Text Representations}) of length @var{len} bytes. diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 5f3c772983..84d5ea1e3b 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -77,7 +77,7 @@ ;; (bindat-type ;; (type u8) ;; (opcode u8) -;; (length uintr 32) ;; little endian order +;; (length uint 32 t) ;; little endian order ;; (id strz 8) ;; (data vec length) ;; (_ align 4))) @@ -663,19 +663,15 @@ is the name of a variable that will hold the value we need to pack.") (`(length . ,_) `(cl-incf bindat-idx 1)) (`(pack . ,args) `(bindat--pack-u8 . ,args)))) -(cl-defmethod bindat--type (op (_ (eql 'uint)) n) +(cl-defmethod bindat--type (op (_ (eql 'uint)) n &optional le) (if (eq n 8) (bindat--type op 'byte) (bindat--pcase op - ('unpack `(bindat--unpack-uint ,n)) - (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8))) - (`(pack . ,args) `(bindat--pack-uint ,n . ,args))))) - -(cl-defmethod bindat--type (op (_ (eql 'uintr)) n) - (if (eq n 8) (bindat--type op 'byte) - (bindat--pcase op - ('unpack `(bindat--unpack-uintr ,n)) + ('unpack + `(if ,le (bindat--unpack-uintr ,n) (bindat--unpack-uint ,n))) (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8))) - (`(pack . ,args) `(bindat--pack-uintr ,n . ,args))))) + (`(pack . ,args) + `(if ,le (bindat--pack-uintr ,n . ,args) + (bindat--pack-uint ,n . ,args)))))) (cl-defmethod bindat--type (op (_ (eql 'str)) len) (bindat--pcase op @@ -829,7 +825,7 @@ is the name of a variable that will hold the value we need to pack.") &optional ":unpack-val" def-form)) (def-edebug-elem-spec 'bindat-type - '(&or ["uint" def-form] + '(&or ["uint" def-form &optional def-form] ["uintr" def-form] ["str" def-form] ["strz" &optional def-form] @@ -849,8 +845,7 @@ is the name of a variable that will hold the value we need to pack.") "Return the Bindat type value to pack&unpack TYPE. TYPE is a Bindat type expression. It can take the following forms: - uint BITLEN - Big-endian unsigned integer - uintr BITLEN - Little-endian unsigned integer + uint BITLEN [LE] - unsigned integer (big-endian if LE is nil) str LEN - Byte string strz [LEN] - Zero-terminated byte-string bits LEN - Bit vector (LEN is counted in bytes) @@ -877,7 +872,7 @@ controlled in the following way: - If the list of fields is preceded with `:pack-var VAR' then the object to be packed is bound to VAR when evaluating the EXPs of `:pack-val'. -All the above BITLEN, LEN, COUNT, and EXP are ELisp expressions evaluated +All the above BITLEN, LEN, LE, COUNT, and EXP are ELisp expressions evaluated in the current lexical context extended with the previous fields. TYPE can additionally be one of the Bindat type macros defined with @@ -891,7 +886,7 @@ a bindat type expression." :pe ,(bindat--toplevel 'pack type)))) (eval-and-compile - (defconst bindat--primitives '(byte uint uintr str strz bits fill align + (defconst bindat--primitives '(byte uint str strz bits fill align struct type vec unit))) (eval-and-compile @@ -935,9 +930,9 @@ a bindat type expression." (if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc))))) (bindat-defmacro u8 () "Unsigned 8bit integer." '(byte)) -(bindat-defmacro sint (bitlen r) +(bindat-defmacro sint (bitlen le) "Signed integer of size BITLEN. -Bigendian if R is nil and little endian if not." +Big-endian if LE is nil and little-endian if not." (let ((bl (make-symbol "bitlen")) (max (make-symbol "max")) (wrap (make-symbol "wrap"))) @@ -945,10 +940,14 @@ Bigendian if R is nil and little endian if not." (,max (ash 1 (1- ,bl))) (,wrap (+ ,max ,max))) (struct :pack-var v - (n if ,r (uintr ,bl) (uint ,bl) + (n uint ,bl ,le :pack-val (if (< v 0) (+ v ,wrap) v)) :unpack-val (if (>= n ,max) (- n ,wrap) n))))) +(bindat-defmacro uintr (bitlen) + "(deprecated since Emacs-29) Little-endian unsigned integer." + `(uint ,bitlen t)) + (bindat-defmacro repeat (count &rest type) "Like `vec', but unpacks to a list rather than a vector." `(:pack-var v diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el index 4817072752..1ce402977f 100644 --- a/test/lisp/emacs-lisp/bindat-tests.el +++ b/test/lisp/emacs-lisp/bindat-tests.el @@ -36,7 +36,7 @@ (bindat-type (type u8) (opcode u8) - (length uintr 16) ;; little endian order + (length uint 16 'le) ;; little endian order (id strz 8) (data vec length) (_ align 4))) @@ -128,18 +128,17 @@ (r (zerop (% kind 2)))) (dotimes (_ 100) (let* ((n (random (ash 1 bitlen))) - (i (- n (ash 1 (1- bitlen))))) + (i (- n (ash 1 (1- bitlen)))) + (stype (bindat-type sint bitlen r)) + (utype (bindat-type if r (uintr bitlen) (uint bitlen)))) (should (equal (bindat-unpack - (bindat-type sint bitlen r) - (bindat-pack (bindat-type sint bitlen r) i)) + stype + (bindat-pack stype i)) i)) (when (>= i 0) - (should (equal (bindat-pack - (bindat-type if r (uintr bitlen) (uint bitlen)) i) - (bindat-pack (bindat-type sint bitlen r) i))) - (should (equal (bindat-unpack - (bindat-type if r (uintr bitlen) (uint bitlen)) - (bindat-pack (bindat-type sint bitlen r) i)) + (should (equal (bindat-pack utype i) + (bindat-pack stype i))) + (should (equal (bindat-unpack utype (bindat-pack stype i)) i)))))))) (defconst bindat-test--LEB128 commit b591a041e37f1a58d8a248f00b7adbf19ed4fa84 Merge: 37e4794b1c eeec16819b Author: Eli Zaretskii Date: Sat Jun 11 16:17:37 2022 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 37e4794b1cffedd4f79ebdc7a35c45bbe4215005 Author: समीर सिंह Sameer Singh Date: Sat Jun 11 16:48:44 2022 +0530 Improve Lepcha composition rules and rename its native name * lisp/language/indian.el ("Lepcha"): Rename lepcha script native name and improve composition rules. (Bug#55869) * etc/HELLO: Rename Lepcha script native name. diff --git a/etc/HELLO b/etc/HELLO index e53bf74f4d..baa8af0f07 100644 --- a/etc/HELLO +++ b/etc/HELLO @@ -76,7 +76,7 @@ Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁 Khmer (ភាសាខ្មែរ) ជំរាបសួរ Lakota (Lakȟotiyapi) Taŋyáŋ yahí! Lao (ພາສາລາວ) ສະບາຍດີ / ຂໍໃຫ້ໂຊກດີ -Lepcha (ᰛᰩᰵ) ᰂᰦᰕᰥᰬ +Lepcha (ᰛᰩᰵᰛᰧᰵᰶ) ᰂᰦᰕᰥᰬ Limbu (ᤕᤰᤌᤢᤱ ᤐᤠᤴ) ᤛᤣᤘᤠᤖᤥ Makasar (𑻪𑻢𑻪𑻢) 𑻦𑻤𑻵𑻱 Malayalam (മലയാളം) നമസ്കാരം diff --git a/lisp/language/indian.el b/lisp/language/indian.el index a6f50962d8..6e0fb10b4f 100644 --- a/lisp/language/indian.el +++ b/lisp/language/indian.el @@ -249,7 +249,7 @@ Grantha script, are supported in this language environment.")) (coding-system utf-8) (coding-priority utf-8) (input-method . "lepcha") - (sample-text . "Lepcha (ᰛᰩᰵ) ᰂᰦᰕᰥᰬ") + (sample-text . "Lepcha (ᰛᰩᰵᰛᰧᰵᰶ) ᰂᰦᰕᰥᰬ") (documentation . "\ Lepcha language and its script are supported in this language environment.")) @@ -756,7 +756,8 @@ language environment.")) (list (vector ;; Consonant based syllables (concat consonant other-signs "?" vowel "?" - consonant-sign "?" subjoined-letter "?") + consonant-sign "?" subjoined-letter "?" + other-signs "?") 1 'font-shape-gstring)))) (provide 'indian) commit eeec16819b954dfbd101ae9925b7cc3bebf923ee Author: Po Lu Date: Sat Jun 11 21:16:30 2022 +0800 Fix timestamp of special drop events * src/xterm.c (x_dnd_send_drop): Set special event timestamp to the timestamp of the drop instead of CurrentTime. diff --git a/src/xterm.c b/src/xterm.c index 55cd5286fe..3ca9149490 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4127,7 +4127,7 @@ x_dnd_send_drop (struct frame *f, Window target, Time timestamp, lval = Fcons (intern (name), lval); lval = Fcons (QXdndSelection, lval); ie.arg = lval; - ie.timestamp = CurrentTime; + ie.timestamp = timestamp; XSETINT (ie.x, win_x); XSETINT (ie.y, win_y); commit 9ea98a68f4325029e68eae1a2a2a948f92c9412b Author: Eli Zaretskii Date: Sat Jun 11 16:12:10 2022 +0300 ; * src/fileio.c (Finsert_file_contents): Fix a typo. (Bug#18370) diff --git a/src/fileio.c b/src/fileio.c index 94cbc14371..e29685e07b 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -4037,7 +4037,7 @@ by calling `format-decode', which see. */) if (!NILP (beg) && !seekable) xsignal2 (Qfile_error, - build_string ("trying to use a start positing in a non-seekable file"), + build_string ("cannot use a start position in a non-seekable file/device"), orig_filename); if (!NILP (replace)) commit cb4579ed6ba45c81ee7ec627bf197e1def121f24 Author: Lars Ingebrigtsen Date: Sat Jun 11 14:39:54 2022 +0200 Allow inserting parts of /dev/urandom with insert-file-contents * doc/lispref/files.texi (Reading from Files): Document it. * src/fileio.c (Finsert_file_contents): Allow specifying END for special files (bug#18370). diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index d473261026..ea8683a6d8 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -581,9 +581,12 @@ contents of the file. This is better than simply deleting the buffer contents and inserting the whole file, because (1) it preserves some marker positions and (2) it puts less data in the undo list. -It is possible to read a special file (such as a FIFO or an I/O device) -with @code{insert-file-contents}, as long as @var{replace} and -@var{visit} are @code{nil}. +It is possible to read a special file (such as a FIFO or an I/O +device) with @code{insert-file-contents}, as long as @var{replace}, +and @var{visit} and @var{beg} are @code{nil}. However, you should +normally use an @var{end} argument for these files to avoid inserting +(potentially) unlimited data into the buffer (for instance, when +inserting data from @file{/dev/urandom}). @end defun @defun insert-file-contents-literally filename &optional visit beg end replace diff --git a/src/fileio.c b/src/fileio.c index 094516bfef..94cbc14371 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -3898,6 +3898,10 @@ The optional third and fourth arguments BEG and END specify what portion of the file to insert. These arguments count bytes in the file, not characters in the buffer. If VISIT is non-nil, BEG and END must be nil. +When inserting data from a special file (e.g., /dev/urandom), you +can't specify VISIT or BEG, and END should be specified to avoid +inserting unlimited data into the buffer. + If optional fifth argument REPLACE is non-nil, replace the current buffer contents (in the accessible portion) with the file contents. This is better than simply deleting and inserting the whole thing @@ -3925,7 +3929,7 @@ by calling `format-decode', which see. */) Lisp_Object handler, val, insval, orig_filename, old_undo; Lisp_Object p; ptrdiff_t total = 0; - bool not_regular = 0; + bool regular = true; int save_errno = 0; char read_buf[READ_BUF_SIZE]; struct coding_system coding; @@ -3948,6 +3952,7 @@ by calling `format-decode', which see. */) /* SAME_AT_END_CHARPOS counts characters, because restore_window_points needs the old character count. */ ptrdiff_t same_at_end_charpos = ZV; + bool seekable = true; if (current_buffer->base_buffer && ! NILP (visit)) error ("Cannot do file visiting in an indirect buffer"); @@ -4021,7 +4026,8 @@ by calling `format-decode', which see. */) least signal an error. */ if (!S_ISREG (st.st_mode)) { - not_regular = 1; + regular = false; + seekable = lseek (fd, 0, SEEK_CUR) < 0; if (! NILP (visit)) { @@ -4029,7 +4035,12 @@ by calling `format-decode', which see. */) goto notfound; } - if (! NILP (replace) || ! NILP (beg) || ! NILP (end)) + if (!NILP (beg) && !seekable) + xsignal2 (Qfile_error, + build_string ("trying to use a start positing in a non-seekable file"), + orig_filename); + + if (!NILP (replace)) xsignal2 (Qfile_error, build_string ("not a regular file"), orig_filename); } @@ -4051,7 +4062,7 @@ by calling `format-decode', which see. */) end_offset = file_offset (end); else { - if (not_regular) + if (!regular) end_offset = TYPE_MAXIMUM (off_t); else { @@ -4073,7 +4084,7 @@ by calling `format-decode', which see. */) /* Check now whether the buffer will become too large, in the likely case where the file's length is not changing. This saves a lot of needless work before a buffer overflow. */ - if (! not_regular) + if (regular) { /* The likely offset where we will stop reading. We could read more (or less), if the file grows (or shrinks) as we read it. */ @@ -4111,7 +4122,7 @@ by calling `format-decode', which see. */) { /* Don't try looking inside a file for a coding system specification if it is not seekable. */ - if (! not_regular && ! NILP (Vset_auto_coding_function)) + if (regular && !NILP (Vset_auto_coding_function)) { /* Find a coding system specified in the heading two lines or in the tailing several lines of the file. @@ -4573,7 +4584,7 @@ by calling `format-decode', which see. */) goto handled; } - if (! not_regular) + if (seekable || !NILP (end)) total = end_offset - beg_offset; else /* For a special file, all we can do is guess. */ @@ -4619,7 +4630,7 @@ by calling `format-decode', which see. */) ptrdiff_t trytry = min (total - how_much, READ_BUF_SIZE); ptrdiff_t this; - if (not_regular) + if (!seekable && NILP (end)) { Lisp_Object nbytes; @@ -4670,7 +4681,7 @@ by calling `format-decode', which see. */) For a special file, where TOTAL is just a buffer size, so don't bother counting in HOW_MUCH. (INSERTED is where we count the number of characters inserted.) */ - if (! not_regular) + if (seekable || !NILP (end)) how_much += this; inserted += this; } @@ -4848,7 +4859,7 @@ by calling `format-decode', which see. */) Funlock_file (BVAR (current_buffer, file_truename)); Funlock_file (filename); } - if (not_regular) + if (!regular) xsignal2 (Qfile_error, build_string ("not a regular file"), orig_filename); } diff --git a/test/src/fileio-tests.el b/test/src/fileio-tests.el index 511490c574..a9a43781d4 100644 --- a/test/src/fileio-tests.el +++ b/test/src/fileio-tests.el @@ -193,4 +193,11 @@ Also check that an encoding error can appear in a symlink." (should (equal (file-name-concat "" "bar") "bar")) (should (equal (file-name-concat "" "") ""))) +(defun test-non-regular-insert () + (skip-unless (file-exists-p "/dev/urandom")) + (with-temp-buffer + (should-error (insert-file-contents "/dev/urandom" nil 5 10)) + (insert-file-contents "/dev/urandom" nil nil 10) + (should (= (point-max) 10)))) + ;;; fileio-tests.el ends here commit 36758096961930baaf0e271522abfb78ff7f656d Author: Po Lu Date: Sat Jun 11 12:01:01 2022 +0000 Fix some drag-and-drop handling on Haiku * lisp/term/haiku-win.el (haiku-drag-and-drop): Don't raise frame for some types of drags. * src/haikuselect.c (haiku_unwind_drag_message): Don't hide tooltip here. (Fhaiku_drag_message): Only clear grab and hide tooltip if the drag was successful. diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index f99d332bd2..5443904a73 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -316,7 +316,6 @@ or a pair of markers) and turns it into a file system reference." ((posn-area (event-start event))) ((assoc "refs" string) (with-selected-window window - (raise-frame) (dolist (filename (cddr (assoc "refs" string))) (dnd-handle-one-url window 'private (concat "file:" filename))))) @@ -327,7 +326,6 @@ or a pair of markers) and turns it into a file system reference." (dnd-handle-one-url window 'private bf))))) ((assoc "text/plain" string) (with-selected-window window - (raise-frame) (dolist (text (cddr (assoc "text/plain" string))) (unless mouse-yank-at-point (goto-char (posn-point (event-start event)))) diff --git a/src/haikuselect.c b/src/haikuselect.c index b319aace96..8a7b6f2e0b 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -755,9 +755,6 @@ haiku_unwind_drag_message (void *message) { haiku_dnd_frame = NULL; BMessage_delete (message); - - if (haiku_dnd_follow_tooltip) - Fx_hide_tip (); } DEFUN ("haiku-drag-message", Fhaiku_drag_message, Shaiku_drag_message, @@ -826,11 +823,17 @@ currently being displayed to move along with the mouse pointer. */) process_pending_signals, haiku_should_quit_drag); - FRAME_DISPLAY_INFO (f)->grabbed = 0; - + /* Don't clear the mouse grab if the user decided to quit instead + of the drop finishing. */ if (rc) quit (); + /* Now dismiss the tooltip, since the drop presumably succeeded. */ + if (!NILP (follow_tooltip)) + Fx_hide_tip (); + + FRAME_DISPLAY_INFO (f)->grabbed = 0; + return unbind_to (idx, Qnil); } commit ab63000b6add129f270bb7787abc75efefa76ffe Author: Po Lu Date: Sat Jun 11 11:55:42 2022 +0000 Fix initializers for Haiku scroll bars * src/haiku_support.cc (class Emacs): (class EmacsScrollBar): Fix initializers. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 3c8e5dc8c2..bc82069789 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -582,10 +582,11 @@ class Emacs : public BApplication { public: BMessage settings; - bool settings_valid_p = false; + bool settings_valid_p; EmacsScreenChangeMonitor *monitor; - Emacs (void) : BApplication ("application/x-vnd.GNU-emacs") + Emacs (void) : BApplication ("application/x-vnd.GNU-emacs"), + settings_valid_p (false) { BPath settings_path; @@ -1948,26 +1949,31 @@ class EmacsView : public BView class EmacsScrollBar : public BScrollBar { public: - int dragging = 0; + int dragging; bool horizontal; enum haiku_scroll_bar_part current_part; float old_value; scroll_bar_info info; /* True if button events should be passed to the parent. */ - bool handle_button = false; - bool in_overscroll = false; - bool can_overscroll = false; - bool maybe_overscroll = false; + bool handle_button; + bool in_overscroll; + bool can_overscroll; + bool maybe_overscroll; BPoint last_overscroll; int last_reported_overscroll_value; int max_value, real_max_value; int overscroll_start_value; bigtime_t repeater_start; - EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p) : - BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ? - B_HORIZONTAL : B_VERTICAL) + EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p) + : BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ? + B_HORIZONTAL : B_VERTICAL), + dragging (0), + handle_button (false), + in_overscroll (false), + can_overscroll (false), + maybe_overscroll (false) { BView *vw = (BView *) this; vw->SetResizingMode (B_FOLLOW_NONE); commit 4881ce7a746d95e702d7328689949b2ae4931692 Author: Visuwesh Date: Sat Jun 11 13:05:17 2022 +0200 Support mksh-specific function names in imenu * lisp/progmodes/sh-script.el (sh-imenu-generic-expression): Add mksh-specific function names to imenu-generic-expression (bug#55889). diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index 4d2554c087..04f65b8dca 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el @@ -286,7 +286,7 @@ naming the shell." :group 'sh-script) (defcustom sh-imenu-generic-expression - '((sh + `((sh . ((nil ;; function FOO ;; function FOO() @@ -295,8 +295,21 @@ naming the shell." ;; FOO() (nil "^\\s-*\\([[:alpha:]_][[:alnum:]_]*\\)\\s-*()" - 1) - ))) + 1))) + (mksh + . ((nil + ;; function FOO + ;; function FOO() + ,(rx bol (* (syntax whitespace)) "function" (+ (syntax whitespace)) + (group (1+ (not (any "\0\t\n \"$&'();<=>\\`|#*?[]/")))) + (* (syntax whitespace)) (? "()")) + 1) + (nil + ;; FOO() + ,(rx bol (* (syntax whitespace)) + (group (1+ (not (any "\0\t\n \"$&'();<=>\\`|#*?[]/")))) + (* (syntax whitespace)) "()") + 1)))) "Alist of regular expressions for recognizing shell function definitions. See `sh-feature' and `imenu-generic-expression'." :type '(alist :key-type (symbol :tag "Shell") commit cbd2c87a5de572583bb1394d35bc9cde8300e1ca Author: Eli Zaretskii Date: Sat Jun 11 14:02:29 2022 +0300 ; Fix last change in whitespace.el. diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 7889a802af..e2c8eecf89 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -276,116 +276,116 @@ It's a list containing some or all of the following values: - face enable all visualization via faces (see below). - - trailing trailing blanks are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - tabs TABs are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - spaces SPACEs and HARD SPACEs are visualized via - faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - lines lines which have columns beyond - `whitespace-line-column' are highlighted via - faces. - Whole line is highlighted. - It has precedence over `lines-tail' (see - below). - It has effect only if `face' (see above) - is present in `whitespace-style'. - - lines-tail lines which have columns beyond - `whitespace-line-column' are highlighted via - faces. - But only the part of line which goes - beyond `whitespace-line-column' column. - It has effect only if `lines' (see above) - is not present in `whitespace-style' - and if `face' (see above) is present in - `whitespace-style'. - - newline NEWLINEs are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. + face enable all visualization via faces (see below). + + trailing trailing blanks are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + tabs TABs are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + spaces SPACEs and HARD SPACEs are visualized via + faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + lines lines which have columns beyond + `whitespace-line-column' are highlighted via + faces. + Whole line is highlighted. + It has precedence over `lines-tail' (see + below). + It has effect only if `face' (see above) + is present in `whitespace-style'. + + lines-tail lines which have columns beyond + `whitespace-line-column' are highlighted via + faces. + But only the part of line which goes + beyond `whitespace-line-column' column. + It has effect only if `lines' (see above) + is not present in `whitespace-style' + and if `face' (see above) is present in + `whitespace-style'. + + newline NEWLINEs are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. missing-newline-at-eof Missing newline at the end of the file is visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - empty empty lines at beginning and/or end of buffer - are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - indentation::tab `tab-width' or more SPACEs at beginning of line - are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - indentation::space TABs at beginning of line are visualized via - faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - indentation `tab-width' or more SPACEs at beginning of line - are visualized, if `indent-tabs-mode' (which - see) is non-nil; otherwise, TABs at beginning - of line are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - big-indent Big indentations are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - space-after-tab::tab `tab-width' or more SPACEs after a TAB - are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - space-after-tab::space TABs are visualized when `tab-width' or - more SPACEs occur after a TAB, via - faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - space-after-tab `tab-width' or more SPACEs after a TAB - are visualized, if `indent-tabs-mode' - (which see) is non-nil; otherwise, - the TABs are visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - space-before-tab::tab SPACEs before TAB are visualized via - faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - space-before-tab::space TABs are visualized when SPACEs occur - before TAB, via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - space-before-tab SPACEs before TAB are visualized, if - `indent-tabs-mode' (which see) is - non-nil; otherwise, the TABs are - visualized via faces. - It has effect only if `face' (see above) - is present in `whitespace-style'. - - space-mark SPACEs and HARD SPACEs are visualized via - display table. - - tab-mark TABs are visualized via display table. - - newline-mark NEWLINEs are visualized via display table. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + empty empty lines at beginning and/or end of buffer + are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + indentation::tab `tab-width' or more SPACEs at beginning of line + are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + indentation::space TABs at beginning of line are visualized via + faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + indentation `tab-width' or more SPACEs at beginning of line + are visualized, if `indent-tabs-mode' (which + see) is non-nil; otherwise, TABs at beginning + of line are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + big-indent Big indentations are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + space-after-tab::tab `tab-width' or more SPACEs after a TAB + are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + space-after-tab::space TABs are visualized when `tab-width' or + more SPACEs occur after a TAB, via + faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + space-after-tab `tab-width' or more SPACEs after a TAB + are visualized, if `indent-tabs-mode' + (which see) is non-nil; otherwise, + the TABs are visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + space-before-tab::tab SPACEs before TAB are visualized via + faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + space-before-tab::space TABs are visualized when SPACEs occur + before TAB, via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + space-before-tab SPACEs before TAB are visualized, if + `indent-tabs-mode' (which see) is + non-nil; otherwise, the TABs are + visualized via faces. + It has effect only if `face' (see above) + is present in `whitespace-style'. + + space-mark SPACEs and HARD SPACEs are visualized via + display table. + + tab-mark TABs are visualized via display table. + + newline-mark NEWLINEs are visualized via display table. Any other value is ignored. @@ -808,21 +808,21 @@ Each element has the following form: Where: -KIND is the kind of character. - It can be one of the following symbols: +KIND is the kind of character. + It can be one of the following symbols: - tab-mark for TAB character + tab-mark for TAB character - space-mark for SPACE or HARD SPACE character + space-mark for SPACE or HARD SPACE character - newline-mark for NEWLINE character + newline-mark for NEWLINE character -CHAR is the character to be mapped. +CHAR is the character to be mapped. -VECTOR is a vector of characters to be displayed in place of CHAR. - The first display vector that can be displayed is used; - if no display vector for a mapping can be displayed, then - that character is displayed unmodified. +VECTOR is a vector of characters to be displayed in place of CHAR. + The first display vector that can be displayed is used; + if no display vector for a mapping can be displayed, then + that character is displayed unmodified. The NEWLINE character is displayed using the face given by `whitespace-newline' variable. commit a6b8bcad58246ed8dcf4674f9df4a6a6859212f3 Author: Lars Ingebrigtsen Date: Sat Jun 11 12:34:18 2022 +0200 Further tweaks to how remapped commands are described * lisp/help.el (describe-map): Rework how remapped commands are output to avoid repetitions. They're now shown as: C-x 4 C-o ido-display-buffer (Remapped via ) C-x 5 C-o ido-display-buffer-other-frame (Remapped via ) C-x x i ido-insert-buffer (Remapped via ) diff --git a/lisp/help.el b/lisp/help.el index abdce46edf..9928b28fb6 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1510,31 +1510,14 @@ in `describe-map-tree'." (let ((vect (sort vect 'help--describe-map-compare)) (columns ()) line-start key-end column) - ;; If we're in a section of the output, then also - ;; display the bindings of the keys that we've remapped from. - ;; This enables the user to actually see what keys to tap to - ;; execute the remapped commands. - (when (equal prefix [remap]) - (dolist (binding (prog1 vect - (setq vect nil))) - (push binding vect) - (when-let ((other (and (not (eq (car binding) 'self-insert-command)) - (car (where-is-internal (car binding)))))) - (push (list (elt other (1- (length other))) - (car binding) - nil - (seq-into (butlast (seq-into other 'list)) 'vector)) - vect))) - (setq vect (nreverse vect))) ;; Now output them in sorted order. (while vect (let* ((elem (car vect)) (start (nth 0 elem)) (definition (nth 1 elem)) (shadowed (nth 2 elem)) - ;; We override the prefix for the extra commands. - (prefix (or (nth 3 elem) prefix)) - (end start)) + (end start) + remapped) ;; Find consecutive chars that are identically defined. (when (fixnump start) (while (and (cdr vect) @@ -1558,7 +1541,19 @@ in `describe-map-tree'." ;; Now START .. END is the range to describe next. ;; Insert the string to describe the event START. (setq line-start (point)) - (insert (help--key-description-fontified (vector start) prefix)) + ;; If we're in a section of the output, then also + ;; display the bindings of the keys that we've remapped from. + ;; This enables the user to actually see what keys to tap to + ;; execute the remapped commands. + (if (setq remapped + (and (equal prefix [remap]) + (not (eq definition 'self-insert-command)) + (car (where-is-internal definition)))) + (insert (help--key-description-fontified + (vector (elt remapped (1- (length remapped)))) + (seq-into (butlast (seq-into remapped 'list)) + 'vector))) + (insert (help--key-description-fontified (vector start) prefix))) (when (not (eq start end)) (insert " .. " (help--key-description-fontified (vector end) prefix))) @@ -1572,9 +1567,15 @@ in `describe-map-tree'." ;; Print a description of the definition of this character. ;; elt_describer will take care of spacing out far enough for ;; alignment purposes. - (when shadowed + (when (or shadowed remapped) (goto-char (max (1- (point)) (point-min))) - (insert "\n (this binding is currently shadowed)") + (when shadowed + (insert "\n (this binding is currently shadowed)")) + (when remapped + (insert (format + "\n (Remapped via %s)" + (help--key-description-fontified + (vector start) prefix)))) (goto-char (min (1+ (point)) (point-max)))))) ;; Next item in list. (setq vect (cdr vect))) commit 52ad2b53cba25e3f9194d26ec5817e8fc3b7d4f5 Author: Eli Zaretskii Date: Sat Jun 11 13:30:07 2022 +0300 Fix doc strings in whitespace.el * lisp/whitespace.el (whitespace-style, whitespace-action): Untabify the doc strings. (Bug#55904) diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 13917206ca..7889a802af 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -880,27 +880,27 @@ C++ modes only." It's a list containing some or all of the following values: - nil no action is taken. + nil no action is taken. - cleanup cleanup any bogus whitespace always when local - whitespace is turned on. - See `whitespace-cleanup' and - `whitespace-cleanup-region'. + cleanup cleanup any bogus whitespace always when local + whitespace is turned on. + See `whitespace-cleanup' and + `whitespace-cleanup-region'. - report-on-bogus report if there is any bogus whitespace always - when local whitespace is turned on. + report-on-bogus report if there is any bogus whitespace always + when local whitespace is turned on. - auto-cleanup cleanup any bogus whitespace when buffer is - written. - See `whitespace-cleanup' and - `whitespace-cleanup-region'. + auto-cleanup cleanup any bogus whitespace when buffer is + written. + See `whitespace-cleanup' and + `whitespace-cleanup-region'. - abort-on-bogus abort if there is any bogus whitespace and the - buffer is written. + abort-on-bogus abort if there is any bogus whitespace and the + buffer is written. - warn-if-read-only give a warning if `cleanup' or `auto-cleanup' - is included in `whitespace-action' and the - buffer is read-only. + warn-if-read-only give a warning if `cleanup' or `auto-cleanup' + is included in `whitespace-action' and the + buffer is read-only. Any other value is treated as nil." :type '(choice :tag "Actions" commit 71b17f1e940eb38e5e797edbe1eae983b6542ba0 Author: समीर सिंह Sameer Singh Date: Thu Jun 9 19:54:10 2022 +0530 Add support for the Lepcha script (bug#55869) * lisp/language/indian.el ("Lepcha"): New language environment. Add composition rules for Lepcha. Add sample text and input method. * lisp/language/misc-lang.el ("Kharoshthi"): Fix whitespace. * lisp/international/fontset.el (script-representative-chars) (setup-default-fontset): Support Lepcha. * lisp/leim/quail/indian.el ("lepcha"): New input method. * etc/HELLO: Add a Lepcha greeting. * etc/NEWS: Announce the new language environment. diff --git a/etc/HELLO b/etc/HELLO index 8787a6e0ae..e53bf74f4d 100644 --- a/etc/HELLO +++ b/etc/HELLO @@ -76,6 +76,7 @@ Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁 Khmer (ភាសាខ្មែរ) ជំរាបសួរ Lakota (Lakȟotiyapi) Taŋyáŋ yahí! Lao (ພາສາລາວ) ສະບາຍດີ / ຂໍໃຫ້ໂຊກດີ +Lepcha (ᰛᰩᰵ) ᰂᰦᰕᰥᰬ Limbu (ᤕᤰᤌᤢᤱ ᤐᤠᤴ) ᤛᤣᤘᤠᤖᤥ Makasar (𑻪𑻢𑻪𑻢) 𑻦𑻤𑻵𑻱 Malayalam (മലയാളം) നമസ്കാരം diff --git a/etc/NEWS b/etc/NEWS index 1789d47351..424d1250c3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -883,6 +883,7 @@ corresponding language environments are: **** Hanifi Rohingya script and language environment **** Grantha script and language environment **** Kharoshthi script and language environment +**** Lepcha script and language environment --- *** The "Oriya" language environment was renamed to "Odia". diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index 44421a96da..273cba8d63 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -193,6 +193,7 @@ (balinese #x1B13 #x1B35 #x1B5E) (sundanese #x1B8A #x1BAB #x1CC4) (batak #x1BC2 #x1BE7 #x1BFF) + (lepcha #x1C00 #x1C24 #x1C40) (tai-le #x1950) (tai-lue #x1980) (tai-tham #x1A20 #x1A55 #x1A61 #x1A80) @@ -767,6 +768,7 @@ balinese sundanese batak + lepcha symbol braille yi diff --git a/lisp/language/indian.el b/lisp/language/indian.el index 9329b43fea..a6f50962d8 100644 --- a/lisp/language/indian.el +++ b/lisp/language/indian.el @@ -244,6 +244,17 @@ Languages such as Sanskrit and Manipravalam, when they use the Grantha script, are supported in this language environment.")) '("Indian")) +(set-language-info-alist + "Lepcha" '((charset unicode) + (coding-system utf-8) + (coding-priority utf-8) + (input-method . "lepcha") + (sample-text . "Lepcha (ᰛᰩᰵ) ᰂᰦᰕᰥᰬ") + (documentation . "\ +Lepcha language and its script are supported in this +language environment.")) + '("Indian")) + ;; Replace mnemonic characters in REGEXP according to TABLE. TABLE is ;; an alist of (MNEMONIC-STRING . REPLACEMENT-STRING). @@ -734,5 +745,19 @@ Grantha script, are supported in this language environment.")) "?" avagraha "?") 1 'font-shape-gstring)))) +;; Lepcha composition rules +(let ((consonant "[\x1C00-\x1C23\x1C4D-\x1C4F]") + (vowel "[\x1C26-\x1C2C]") + (subjoined-letter "[\x1C24\x1C25]") + (consonant-sign "[\x1C2D-\x1C35]") + (other-signs "[\x1C36\x1C37]")) + (set-char-table-range composition-function-table + '(#x1C24 . #x1C37) + (list (vector + ;; Consonant based syllables + (concat consonant other-signs "?" vowel "?" + consonant-sign "?" subjoined-letter "?") + 1 'font-shape-gstring)))) + (provide 'indian) ;;; indian.el ends here diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el index e0e7add158..1e915c2f83 100644 --- a/lisp/language/misc-lang.el +++ b/lisp/language/misc-lang.el @@ -242,11 +242,11 @@ in this language environment."))) (set-language-info-alist "Kharoshthi" '((charset unicode) - (coding-system utf-8) - (coding-priority utf-8) - (input-method . "kharoshthi") - (sample-text . "Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁") - (documentation . "\ + (coding-system utf-8) + (coding-priority utf-8) + (input-method . "kharoshthi") + (sample-text . "Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁") + (documentation . "\ Language environment for Gāndhārī, Sanskrit, and other languages using the Kharoṣṭhī script."))) @@ -255,7 +255,7 @@ using the Kharoṣṭhī script."))) (virama "\U00010A3F") (modifier "[\U00010A0C-\U00010A0F\U00010A38-\U00010A3A]")) (set-char-table-range composition-function-table - '(#x10A3F . #x10A3F) + '(#x10A3F . #x10A3F) (list (vector (concat consonant diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el index 6a3582e83d..bc61a312fa 100644 --- a/lisp/leim/quail/indian.el +++ b/lisp/leim/quail/indian.el @@ -1771,4 +1771,97 @@ Full key sequences are listed below:") ("`m" ?𑌁) ("`M" ?𑌀)) +(quail-define-package + "lepcha" "Lepcha" "ᰛᰩᰵ" t "Lepcha phonetic input method. + + `\\=`' is used to switch levels instead of Alt-Gr." + nil t t t t nil nil nil nil nil t) + +(quail-define-rules + ("``" ?₹) + ("1" ?᱁) + ("`1" ?1) + ("2" ?᱂) + ("`2" ?2) + ("3" ?᱃) + ("`3" ?3) + ("4" ?᱄) + ("`4" ?4) + ("5" ?᱅) + ("`5" ?5) + ("6" ?᱆) + ("`6" ?6) + ("7" ?᱇) + ("`7" ?7) + ("8" ?᱈) + ("`8" ?8) + ("9" ?᱉) + ("`9" ?9) + ("0" ?᱀) + ("`0" ?0) + ("`\\" ?᰻) + ("`|" ?᰼) + ("`" ?ᱍ) + ("q" ?ᱍ) + ("Q" ?ᱎ) + ("`q" ?᰽) + ("`Q" ?᰾) + ("w" ?ᰢ) + ("W" ?ᱏ) + ("`w" ?᰿) + ("e" ?ᰬ) + ("r" ?ᰛ) + ("R" ?ᰥ) + ("`r" ?ᰲ) + ("t" ?ᰊ) + ("T" ?ᰋ) + ("`t" ?ᰳ) + ("y" ?ᰚ) + ("Y" ?ᰤ) + ("u" ?ᰪ) + ("U" ?ᰫ) + ("i" ?ᰧ) + ("o" ?ᰨ) + ("O" ?ᰩ) + ("p" ?ᰎ) + ("P" ?ᰏ) + ("`p" ?ᰐ) + ("`P" ?ᰱ) + ("a" ?ᰦ) + ("A" ?ᰣ) + ("s" ?ᰠ) + ("S" ?ᰡ) + ("d" ?ᰌ) + ("f" ?ᰑ) + ("F" ?ᰒ) + ("g" ?ᰃ) + ("G" ?ᰄ) + ("h" ?ᰝ) + ("H" ?ᰞ) + ("j" ?ᰈ) + ("k" ?ᰀ) + ("K" ?ᰁ) + ("`k" ?ᰂ) + ("`K" ?ᰭ) + ("l" ?ᰜ) + ("L" ?ᰯ) + ("z" ?ᰉ) + ("Z" ?ᰅ) + ("`z" ?ᰴ) + ("`Z" ?ᰵ) + ("x" ?ᰶ) + ("X" ?᰷) + ("c" ?ᰆ) + ("C" ?ᰇ) + ("`c" #x200C) ; ZWNJ + ("v" ?ᰟ) + ("b" ?ᰓ) + ("B" ?ᰔ) + ("n" ?ᰍ) + ("N" ?ᰰ) + ("m" ?ᰕ) + ("M" ?ᰖ) + ("`m" ?ᰮ)) + +(provide 'indian) ;;; indian.el ends here commit 46b9bfb9fc925b8cf20b0a35469f8ff6c3be5a70 Author: Po Lu Date: Sat Jun 11 14:11:28 2022 +0800 Fix queuing already-present selection requests * src/xterm.c (x_defer_selection_requests): Move kbd_fetch_ptr if possible and fix counter increment order. diff --git a/src/xterm.c b/src/xterm.c index 74716dfe40..55cd5286fe 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -795,9 +795,9 @@ static int x_use_pending_selection_requests; static void x_push_selection_request (struct selection_input_event *); -/* Defer selection requests. Any selection requests generated after - this can then be processed by calling - `x_handle_pending_selection_requests'. +/* Defer selection requests. Between this and + x_release_selection_requests, any selection requests can be + processed by calling `x_handle_pending_selection_requests'. Also run through and queue all the selection events already in the keyboard buffer. */ @@ -805,10 +805,11 @@ void x_defer_selection_requests (void) { union buffered_input_event *event; + bool between; - block_input (); - x_use_pending_selection_requests++; + between = false; + block_input (); if (!x_use_pending_selection_requests) { event = kbd_fetch_ptr; @@ -822,13 +823,24 @@ x_defer_selection_requests (void) /* Mark this selection event as invalid. */ SELECTION_EVENT_DPYINFO (&event->sie) = NULL; + + /* Move the kbd_fetch_ptr along if doing so would not + result in any other events being skipped. This + avoids exhausting the keyboard buffer with some + over-enthusiastic clipboard managers. */ + if (!between) + kbd_fetch_ptr = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 + ? kbd_buffer : event + 1); } + else + between = true; event = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : event + 1); } } + x_use_pending_selection_requests++; unblock_input (); } commit 84a588e02846966262be1ea4d0106d9936ccd3b5 Merge: 355d286312 0705705ebf Author: Stefan Kangas Date: Sat Jun 11 06:30:30 2022 +0200 Merge from origin/emacs-28 0705705ebf Improve documentation of "etags -I" 0ad8cd40ce Merge branch 'emacs-28' of git.savannah.gnu.org:/srv/git/e... 22a832ad82 Mention the #f syntax from cl-prin1 3fd0854378 Fix file name quoting in tramp-smb.el (do not merge) commit 355d2863125e0aaf86aa7482cd050368c73b5c5e Merge: 9c27c7f7ce 8436e0bee9 Author: Stefan Kangas Date: Sat Jun 11 06:30:30 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: 8436e0bee9 Update error message to reflect variable rename commit 9c27c7f7ceaf1f2a5120c915732140877cfa9ff0 Author: Po Lu Date: Sat Jun 11 11:13:48 2022 +0800 Handle allocation errors when interning large amounts of atoms * src/xfns.c (Fx_begin_drag): Catch BadAlloc errors around XInternAtoms. diff --git a/src/xfns.c b/src/xfns.c index 43d4d27372..9882fd7ce1 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6982,10 +6982,14 @@ that mouse buttons are being held down, such as immediately after a target_atoms = SAFE_ALLOCA (ntargets * sizeof *target_atoms); - block_input (); + /* Catch errors since interning lots of targets can potentially + generate a BadAlloc error. */ + x_catch_errors (FRAME_X_DISPLAY (f)); XInternAtoms (FRAME_X_DISPLAY (f), target_names, ntargets, False, target_atoms); - unblock_input (); + x_check_errors (FRAME_X_DISPLAY (f), + "Failed to intern target atoms: %s"); + x_uncatch_errors_after_check (); lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time, xaction, return_frame, action_list, commit 46e6b8a1e42849ad55813c9ee387ad8bc95697fb Author: Po Lu Date: Sat Jun 11 09:19:05 2022 +0800 Prevent crash handling keyboard input from non-frame windows * src/xterm.c (handle_one_xevent): Use `dpyinfo' to access xkb desc. (bug#55890) diff --git a/src/xterm.c b/src/xterm.c index ad925755b5..74716dfe40 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -16858,9 +16858,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, memset (&compose_status, 0, sizeof (compose_status)); #ifdef HAVE_XKB - if (FRAME_DISPLAY_INFO (f)->xkb_desc) + if (dpyinfo->xkb_desc) { - XkbDescRec *rec = FRAME_DISPLAY_INFO (f)->xkb_desc; + XkbDescRec *rec = dpyinfo->xkb_desc; if (rec->map->modmap && rec->map->modmap[xkey.keycode]) goto done_keysym; @@ -20109,9 +20109,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers); #ifdef HAVE_XKB - if (FRAME_DISPLAY_INFO (f)->xkb_desc) + if (dpyinfo->xkb_desc) { - XkbDescRec *rec = FRAME_DISPLAY_INFO (f)->xkb_desc; + XkbDescRec *rec = dpyinfo->xkb_desc; if (rec->map->modmap && rec->map->modmap[xev->detail]) goto xi_done_keysym; commit 7def8baa086451450f8bb34b07febb232f9c148d Author: Po Lu Date: Sat Jun 11 09:12:44 2022 +0800 Fix cancelling DND upon a regular X error * src/xterm.c (x_connection_closed): The display isn't dead upon a non-IO error, so don't avoid sending messages to clean stuff up. diff --git a/src/xterm.c b/src/xterm.c index 30322b0c09..ad925755b5 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -22379,51 +22379,55 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) if (x_dnd_in_progress || x_dnd_waiting_for_finish) { - /* Handle display disconnect errors here because this function - is not reentrant at this particular spot. */ - io_error_handler = XSetIOErrorHandler (x_dnd_io_error_handler); - - if (!sigsetjmp (x_dnd_disconnect_handler, 1) - && x_dnd_in_progress - && dpy != (x_dnd_waiting_for_finish - ? x_dnd_finish_display - : FRAME_X_DISPLAY (x_dnd_frame))) + if (!ioerror) { - /* Clean up drag and drop if the drag frame's display isn't - the one being disconnected. */ - f = x_dnd_frame; - - if (x_dnd_last_seen_window != None - && x_dnd_last_protocol_version != -1) - x_dnd_send_leave (x_dnd_frame, - x_dnd_last_seen_window); - else if (x_dnd_last_seen_window != None - && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) - && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE - && x_dnd_motif_setup_p) + /* Handle display disconnect errors here because this function + is not reentrant at this particular spot. */ + io_error_handler = XSetIOErrorHandler (x_dnd_io_error_handler); + + if (!!sigsetjmp (x_dnd_disconnect_handler, 1) + && x_dnd_in_progress + && dpy == (x_dnd_waiting_for_finish + ? x_dnd_finish_display + : FRAME_X_DISPLAY (x_dnd_frame))) { - dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, - XM_DRAG_REASON_DROP_START); - dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; - dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time; - dmsg.side_effects - = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), - x_dnd_wanted_action), - XM_DROP_SITE_VALID, x_dnd_motif_operations, - XM_DROP_ACTION_DROP_CANCEL); - dmsg.x = 0; - dmsg.y = 0; - dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; - dmsg.source_window = FRAME_X_WINDOW (f); - - x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, - x_dnd_last_seen_window, 0); - xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), - x_dnd_last_seen_window, &dmsg); + /* Clean up drag and drop if the drag frame's display isn't + the one being disconnected. */ + f = x_dnd_frame; + + if (x_dnd_last_seen_window != None + && x_dnd_last_protocol_version != -1) + x_dnd_send_leave (x_dnd_frame, + x_dnd_last_seen_window); + else if (x_dnd_last_seen_window != None + && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) + && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE + && x_dnd_motif_setup_p) + { + dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, + XM_DRAG_REASON_DROP_START); + dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; + dmsg.timestamp = FRAME_DISPLAY_INFO (f)->last_user_time; + dmsg.side_effects + = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), + x_dnd_wanted_action), + XM_DROP_SITE_VALID, x_dnd_motif_operations, + XM_DROP_ACTION_DROP_CANCEL); + dmsg.x = 0; + dmsg.y = 0; + dmsg.index_atom = FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection; + dmsg.source_window = FRAME_X_WINDOW (f); + + x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, + x_dnd_last_seen_window, 0); + xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), + x_dnd_last_seen_window, &dmsg); + } } + + XSetIOErrorHandler (io_error_handler); } - XSetIOErrorHandler (io_error_handler); dpyinfo = x_display_info_for_display (dpy); x_dnd_last_seen_window = None; @@ -22432,7 +22436,7 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) x_dnd_waiting_for_finish = false; if (x_dnd_use_toplevels) - x_dnd_free_toplevels (false); + x_dnd_free_toplevels (!ioerror); x_dnd_return_frame_object = NULL; x_dnd_movement_frame = NULL; commit cb0c697e21f710cb8df56c33d951f780a2a1e40e Author: Dmitry Gutov Date: Sat Jun 11 03:45:46 2022 +0300 elisp-completion-at-point: Replace last usage of 'read' * lisp/progmodes/elisp-mode.el (elisp-completion-at-point): Replace the last remaining usage of 'read' (bug#55491). diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 77bf3f1ed1..5989e1161b 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -697,7 +697,10 @@ functions are annotated with \"\" via the (let ((c (char-after))) (if (eq c ?\() ?\( (if (memq (char-syntax c) '(?w ?_)) - (read (current-buffer)))))) + (let ((pt (point))) + (forward-sexp) + (intern-soft + (buffer-substring pt (point)))))))) (error nil)))) (pcase parent ;; FIXME: Rather than hardcode special cases here, commit 3247c31d672e5fed83435150ba62006acaddcf84 Author: Juri Linkov Date: Fri Jun 10 19:43:31 2022 +0300 New function isearch-search-fun-in-text-property (bug#14013). * lisp/dired-aux.el (dired-isearch-search-filenames): Move most of the body to the new function isearch-search-fun-in-text-property. * lisp/isearch.el (isearch-search-fun-in-text-property): New function refactored from dired-isearch-search-filenames. diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 4faf9431aa..d16aee0fa8 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -3208,41 +3208,7 @@ Intended to be added to `isearch-mode-hook'." The returned function narrows the search to match the search string only as part of a file name enclosed by the text property `dired-filename'. It's intended to override the default search function." - (let ((search-fun (funcall orig-fun)) - (property 'dired-filename)) - (lambda (string &optional bound noerror count) - (let* ((old (point)) - ;; Check if point is already on the property. - (beg (when (get-text-property - (if isearch-forward old (max (1- old) (point-min))) - property) - old)) - end found) - ;; Otherwise, try to search for the next property. - (unless beg - (setq beg (if isearch-forward - (next-single-property-change old property) - (previous-single-property-change old property))) - (when beg (goto-char beg))) - ;; Non-nil `beg' means there are more properties. - (while (and beg (not found)) - ;; Search for the end of the current property. - (setq end (if isearch-forward - (next-single-property-change beg property) - (previous-single-property-change beg property))) - (setq found (funcall - search-fun string (if bound (if isearch-forward - (min bound end) - (max bound end)) - end) - noerror count)) - (unless found - (setq beg (if isearch-forward - (next-single-property-change end property) - (previous-single-property-change end property))) - (when beg (goto-char beg)))) - (unless found (goto-char old)) - found)))) + (isearch-search-fun-in-text-property 'dired-filename (funcall orig-fun))) ;;;###autoload (defun dired-isearch-filenames () diff --git a/lisp/isearch.el b/lisp/isearch.el index 31fbdf01bf..5fbfb724a3 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -4454,6 +4454,48 @@ LAX-WHITESPACE: The value of `isearch-lax-whitespace' and (add-function :after-while (local 'isearch-filter-predicate) filter))) (funcall after-change nil nil nil))))) + +(defun isearch-search-fun-in-text-property (property &optional search-fun) + "Return the function that searches inside fields. +The arg PROPERTY defines the name of the text property that +delimits fields in the current buffer. Then the search will be +narrowed to match only on such text properties. The optional arg +SEARCH-FUN can provide the default search function which is +by default is the same as returned by `isearch-search-fun-default'." + (lambda (string &optional bound noerror count) + (let* ((old (point)) + ;; Check if point is already on the property. + (beg (when (get-text-property + (if isearch-forward old (max (1- old) (point-min))) + property) + old)) + end found) + ;; Otherwise, try to search for the next property. + (unless beg + (setq beg (if isearch-forward + (next-single-property-change old property) + (previous-single-property-change old property))) + (when beg (goto-char beg))) + ;; Non-nil `beg' means there are more properties. + (while (and beg (not found)) + ;; Search for the end of the current property. + (setq end (if isearch-forward + (next-single-property-change beg property) + (previous-single-property-change beg property))) + (setq found (funcall (or search-fun (isearch-search-fun-default)) + string (if bound (if isearch-forward + (min bound end) + (max bound end)) + end) + noerror count)) + (unless found + (setq beg (if isearch-forward + (next-single-property-change end property) + (previous-single-property-change end property))) + (when beg (goto-char beg)))) + (unless found (goto-char old)) + found))) + (defun isearch-resume (string regexp word forward message case-fold) "Resume an incremental search. commit 4c31fd166851ebd27a28743c613a4b1833cf2a46 Author: Jim Porter Date: Thu Jun 9 09:50:20 2022 -0700 Don't use 'list' command in Eshell command forms When executed like a command, 'list' looks for external programs named 'list' first before falling back to the Lisp function of the same name. This causes unexpected behavior, since the Lisp function is what we want in these tests. * test/lisp/eshell/esh-var-tests.el (esh-var-test/interp-cmd-indices) (esh-var-test/quoted-interp-cmd-indices): Use 'listify' instead of 'list'. diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index bee495eb6e..3180fe7a5f 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el @@ -147,7 +147,7 @@ (ert-deftest esh-var-test/interp-cmd-indices () "Interpolate command result with index" - (should (equal (eshell-test-command-result "+ ${list 1 2}[1] 3") 5))) + (should (equal (eshell-test-command-result "+ ${listify 1 2}[1] 3") 5))) (ert-deftest esh-var-test/interp-cmd-external () "Interpolate command result from external command" @@ -328,7 +328,8 @@ inside double-quotes" (ert-deftest esh-var-test/quoted-interp-cmd-indices () "Interpolate command result with index inside double-quotes" - (should (equal (eshell-test-command-result "concat \"${list 1 2}[1]\" cool") + (should (equal (eshell-test-command-result + "concat \"${listify 1 2}[1]\" cool") "2cool"))) (ert-deftest esh-var-test/quoted-interp-temp-cmd () commit ac1d45c5ea8041284021ebdd8cf4609c92b83608 Merge: 89e6305b17 f7307f6215 Author: Eli Zaretskii Date: Fri Jun 10 16:13:56 2022 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit 89e6305b17b9f3c9aeebb02e178b7d7635ec2156 Author: Eli Zaretskii Date: Fri Jun 10 16:13:16 2022 +0300 ; * etc/NEWS: Fix last change. diff --git a/etc/NEWS b/etc/NEWS index 2716fde135..1789d47351 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -69,7 +69,7 @@ option '--without-xinput2' to disable this support. support from Lisp programs. --- -** Emacs now doesn't reduce the size of the Japanese dictionary. +** Emacs no longer reduces the size of the Japanese dictionary. Building Emacs includes generation of a Japanese dictionary, which is used by Japanese input methods. Previously, the build included a step of reducing the size of this dictionary's vocabulary. This vocabulary commit 5551ef2c007361966224c2c64d9df93ccbc79305 Author: Eli Zaretskii Date: Fri Jun 10 16:12:00 2022 +0300 ; Minor copyedits of --with-small-ja-dic option * etc/NEWS: Document the new configuration option. * lisp/international/ja-dic-cnv.el (skkdic-convert-okuri-nasi): Fix whitespace. (skkdic-convert): Doc fix. (batch-skkdic-convert): Fix Help message. * configure.ac: Tweak the description of --with-small-ja-dic. diff --git a/configure.ac b/configure.ac index 3e6eab94f8..5b86e90925 100644 --- a/configure.ac +++ b/configure.ac @@ -491,7 +491,7 @@ OPTION_DEFAULT_ON([threads],[don't compile with elisp threading support]) OPTION_DEFAULT_OFF([native-compilation],[compile with Emacs Lisp native compiler support]) OPTION_DEFAULT_OFF([cygwin32-native-compilation],[use native compilation on 32-bit Cygwin]) OPTION_DEFAULT_ON([xinput2],[don't use version 2 of the X Input Extension for input]) -OPTION_DEFAULT_OFF([small-ja-dic],[generate a small-sized Japanese dictionary]) +OPTION_DEFAULT_OFF([small-ja-dic],[generate a smaller-size Japanese dictionary]) AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB], [use a file notification library (LIB one of: yes, inotify, kqueue, gfile, w32, no)])], @@ -6493,7 +6493,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D Which dumping strategy does Emacs use? ${with_dumping} Does Emacs have native lisp compiler? ${HAVE_NATIVE_COMP} Does Emacs use version 2 of the the X Input Extension? ${HAVE_XINPUT2} - Should Emacs use a small-sized Japanese dictionary? ${with_small_ja_dic} + Does Emacs generate a smaller-size Japanese dictionary? ${with_small_ja_dic} "]) if test -n "${EMACSDATA}"; then diff --git a/etc/NEWS b/etc/NEWS index 88758abc64..2716fde135 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -68,6 +68,21 @@ option '--without-xinput2' to disable this support. '(featurep 'xinput2)' can be used to test for the presence of XInput 2 support from Lisp programs. +--- +** Emacs now doesn't reduce the size of the Japanese dictionary. +Building Emacs includes generation of a Japanese dictionary, which is +used by Japanese input methods. Previously, the build included a step +of reducing the size of this dictionary's vocabulary. This vocabulary +reduction is now optional, by default off. If you need the Emacs +build to include the vocabulary reduction, configure Emacs with the +option '--with-small-ja-dic'. In an Emacs source tree already +configured without that option, you can force the vocabulary reduction +by saying + + make -C leim generate-ja-dic JA_DIC_NO_REDUCTION_OPTION='' + +after deleting lisp/leim/ja-dic/ja-dic.el. + +++ ** Emacs now supports being built with pure GTK. To use this option, make sure the GTK 3 (version 3.20 or later) and diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el index 0bad7dea0a..ec68d8c804 100644 --- a/lisp/international/ja-dic-cnv.el +++ b/lisp/international/ja-dic-cnv.el @@ -315,7 +315,7 @@ (if (setq candidates (if no-reduction candidates - (skkdic-reduced-candidates skkbuf kana candidates))) + (skkdic-reduced-candidates skkbuf kana candidates))) (progn (insert "\"" kana) (while candidates @@ -330,8 +330,7 @@ "Generate Emacs Lisp file from Japanese dictionary file FILENAME. The format of the dictionary file should be the same as SKK dictionaries. Saves the output as `ja-dic-filename', in directory DIRNAME (if specified). -When NO-REDUCTION is t, then not reduce dictionary vocabulary. -" +If NO-REDUCTION is non-nil, do not reduce the dictionary vocabulary." (interactive "FSKK dictionary file: ") (let* ((skkbuf (get-buffer-create " *skkdic-unannotated*")) (buf (get-buffer-create "*skkdic-work*"))) @@ -425,7 +424,7 @@ To get complete usage, invoke: (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert SKK-JISYO.L") (message "To convert SKK-JISYO.L into DIR/ja-dic.el:") (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert -dir DIR SKK-JISYO.L") - (message "To convert SKK-JISYO.L into skkdic.el with not reduce dictionary vocabulary:") + (message "To convert SKK-JISYO.L into skkdic.el without reducing dictionary vocabulary:") (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert --no-reduction SKK-JISYO.L")) (let (targetdir filename no-reduction) (if (string= (car command-line-args-left) "-dir") commit f7307f6215d76581a1afb102cfcd2343ea243acd Author: Po Lu Date: Fri Jun 10 20:51:45 2022 +0800 Remove extra call to XTranslateCoordinates when performing "xterm" drop * src/xterm.c (x_dnd_do_unsupported_drop): Signal error when XdndSelection is lost, set subwindow, and simplify XTranslateCoordinates loop. diff --git a/src/xterm.c b/src/xterm.c index 375b345a90..30322b0c09 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3443,7 +3443,6 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, int dest_x, dest_y; Window child_return, child; - event.xbutton.type = ButtonPress; event.xbutton.serial = 0; event.xbutton.send_event = True; event.xbutton.display = dpyinfo->display; @@ -3457,39 +3456,37 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, dest_x = root_x; dest_y = root_y; - while (XTranslateCoordinates (dpyinfo->display, child, - child, root_x, root_y, &dest_x, - &dest_y, &child_return) - && child_return != None - && XTranslateCoordinates (dpyinfo->display, child, - child_return, root_x, root_y, - &dest_x, &dest_y, &child)) - { - child = child_return; - root_x = dest_x; - root_y = dest_y; - } + while (XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, + child, root_x, root_y, &dest_x, &dest_y, + &child_return) + && child_return != None) + child = child_return; if (CONSP (value)) x_own_selection (QPRIMARY, Fnth (make_fixnum (1), value), frame); else - x_own_selection (QPRIMARY, Qnil, frame); + error ("Lost ownership of XdndSelection"); event.xbutton.window = child; + event.xbutton.subwindow = None; event.xbutton.x = dest_x; event.xbutton.y = dest_y; event.xbutton.state = 0; event.xbutton.button = 2; event.xbutton.same_screen = True; - event.xbutton.time = before + 1; - event.xbutton.time = before + 2; x_set_pending_dnd_time (before); + event.xbutton.type = ButtonPress; + event.xbutton.time = before + 1; + XSendEvent (dpyinfo->display, child, True, ButtonPressMask, &event); + event.xbutton.type = ButtonRelease; + event.xbutton.time = before + 2; + XSendEvent (dpyinfo->display, child, True, ButtonReleaseMask, &event); commit afbe7585c448c79f0320839d272742968ee88a55 Author: Taiju HIGASHI Date: Tue Jun 7 21:46:14 2022 +0900 Don't reduce vocabulary in ja-dic.el by default * configure.ac: Add the "--with-small-ja-dic" configure option. * leim/Makefile.in (${leimdir}/ja-dic/ja-dic.el): Change the build method depending on whether or not the --with-small-ja-dic option is specified. * lisp/international/ja-dic-cnv.el (skkdic-convert-okuri-nasi): Add the "no-reduction" optional argument. When it is specified, then generate a Japanese dictionary without reduced vocabulary. (skkdic-convert): Add the "no-reduction" optional argument. (batch-skkdic-convert): Add the "--no-reduction" command line argument. diff --git a/configure.ac b/configure.ac index 313a1436b5..3e6eab94f8 100644 --- a/configure.ac +++ b/configure.ac @@ -491,6 +491,7 @@ OPTION_DEFAULT_ON([threads],[don't compile with elisp threading support]) OPTION_DEFAULT_OFF([native-compilation],[compile with Emacs Lisp native compiler support]) OPTION_DEFAULT_OFF([cygwin32-native-compilation],[use native compilation on 32-bit Cygwin]) OPTION_DEFAULT_ON([xinput2],[don't use version 2 of the X Input Extension for input]) +OPTION_DEFAULT_OFF([small-ja-dic],[generate a small-sized Japanese dictionary]) AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB], [use a file notification library (LIB one of: yes, inotify, kqueue, gfile, w32, no)])], @@ -6492,6 +6493,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D Which dumping strategy does Emacs use? ${with_dumping} Does Emacs have native lisp compiler? ${HAVE_NATIVE_COMP} Does Emacs use version 2 of the the X Input Extension? ${HAVE_XINPUT2} + Should Emacs use a small-sized Japanese dictionary? ${with_small_ja_dic} "]) if test -n "${EMACSDATA}"; then @@ -6590,6 +6592,9 @@ SUBDIR_MAKEFILES_IN=`echo " ${SUBDIR_MAKEFILES}" | sed -e 's| | $(srcdir)/|g' -e AC_SUBST(SUBDIR_MAKEFILES_IN) +SMALL_JA_DIC=$with_small_ja_dic +AC_SUBST(SMALL_JA_DIC) + dnl You might wonder (I did) why epaths.h is generated by running make, dnl rather than just letting configure generate it from epaths.in. dnl One reason is that the various paths are not fully expanded (see above); diff --git a/leim/Makefile.in b/leim/Makefile.in index 3b4216c0b8..29b9f3b2f8 100644 --- a/leim/Makefile.in +++ b/leim/Makefile.in @@ -32,6 +32,12 @@ leimdir = ${srcdir}/../lisp/leim EXEEXT = @EXEEXT@ +SMALL_JA_DIC = @SMALL_JA_DIC@ +JA_DIC_NO_REDUCTION_OPTION = --no-reduction +ifeq ($(SMALL_JA_DIC), yes) + JA_DIC_NO_REDUCTION_OPTION = +endif + -include ${top_builddir}/src/verbose.mk # Prevent any settings in the user environment causing problems. @@ -134,7 +140,7 @@ generate-ja-dic: ${leimdir}/ja-dic/ja-dic.el ${leimdir}/ja-dic/ja-dic.el: $(srcdir)/SKK-DIC/SKK-JISYO.L $(AM_V_GEN)$(RUN_EMACS) -batch -l ja-dic-cnv \ --eval "(setq max-specpdl-size 5000)" \ - -f batch-skkdic-convert -dir "$(leimdir)/ja-dic" "$<" + -f batch-skkdic-convert -dir "$(leimdir)/ja-dic" $(JA_DIC_NO_REDUCTION_OPTION) "$<" ${srcdir}/../lisp/language/pinyin.el: ${srcdir}/MISC-DIC/pinyin.map $(AM_V_GEN)${RUN_EMACS} -l titdic-cnv -f pinyin-convert $< $@ diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el index 1bbc664e75..0bad7dea0a 100644 --- a/lisp/international/ja-dic-cnv.el +++ b/lisp/international/ja-dic-cnv.el @@ -297,7 +297,7 @@ (setq skkdic-okuri-nasi-entries-count (length skkdic-okuri-nasi-entries)) (progress-reporter-done progress)))) -(defun skkdic-convert-okuri-nasi (skkbuf buf) +(defun skkdic-convert-okuri-nasi (skkbuf buf &optional no-reduction) (with-current-buffer buf (insert ";; Setting okuri-nasi entries.\n" "(skkdic-set-okuri-nasi\n") @@ -313,7 +313,9 @@ (setq count (1+ count)) (progress-reporter-update progress count) (if (setq candidates - (skkdic-reduced-candidates skkbuf kana candidates)) + (if no-reduction + candidates + (skkdic-reduced-candidates skkbuf kana candidates))) (progn (insert "\"" kana) (while candidates @@ -324,10 +326,12 @@ (progress-reporter-done progress)) (insert ")\n\n"))) -(defun skkdic-convert (filename &optional dirname) +(defun skkdic-convert (filename &optional dirname no-reduction) "Generate Emacs Lisp file from Japanese dictionary file FILENAME. The format of the dictionary file should be the same as SKK dictionaries. -Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)." +Saves the output as `ja-dic-filename', in directory DIRNAME (if specified). +When NO-REDUCTION is t, then not reduce dictionary vocabulary. +" (interactive "FSKK dictionary file: ") (let* ((skkbuf (get-buffer-create " *skkdic-unannotated*")) (buf (get-buffer-create "*skkdic-work*"))) @@ -388,7 +392,7 @@ Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)." (skkdic-collect-okuri-nasi) ;; Convert okuri-nasi general entries. - (skkdic-convert-okuri-nasi skkbuf buf) + (skkdic-convert-okuri-nasi skkbuf buf no-reduction) ;; Postfix (with-current-buffer buf @@ -420,15 +424,21 @@ To get complete usage, invoke: (message "To convert SKK-JISYO.L into skkdic.el:") (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert SKK-JISYO.L") (message "To convert SKK-JISYO.L into DIR/ja-dic.el:") - (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert -dir DIR SKK-JISYO.L")) - (let (targetdir filename) + (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert -dir DIR SKK-JISYO.L") + (message "To convert SKK-JISYO.L into skkdic.el with not reduce dictionary vocabulary:") + (message " %% emacs -batch -l ja-dic-cnv -f batch-skkdic-convert --no-reduction SKK-JISYO.L")) + (let (targetdir filename no-reduction) (if (string= (car command-line-args-left) "-dir") (progn (setq command-line-args-left (cdr command-line-args-left)) (setq targetdir (expand-file-name (car command-line-args-left))) (setq command-line-args-left (cdr command-line-args-left)))) + (if (string= (car command-line-args-left) "--no-reduction") + (progn + (setq no-reduction t) + (setq command-line-args-left (cdr command-line-args-left)))) (setq filename (expand-file-name (car command-line-args-left))) - (skkdic-convert filename targetdir))) + (skkdic-convert filename targetdir no-reduction))) (kill-emacs 0)) commit dc09759c1d1e7d7c6118fd8e582aaa57454cf001 Author: Eli Zaretskii Date: Fri Jun 10 14:22:18 2022 +0300 ; Fix documentation of 'completing-read' and friends * src/minibuf.c (Fcompleting_read): * lisp/minibuffer.el (read-file-name): * doc/lispref/minibuf.texi (Minibuffer Completion): * etc/NEWS: Fix typos and wording of the description of the REQUIRE-MATCH argument to 'completing-read'. diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index 86e601f8c0..1451e59d05 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -1122,9 +1122,9 @@ completion command (i.e., one of the commands in not an element of @var{collection}. @xref{Completion Commands}. @item -If a function, the function is called with the input as the only -argument. The function should return a non-@code{nil} value of the -input is acceptable. +If a function, it is called with the input as the only argument. The +function should return a non-@code{nil} value if the input is +acceptable. @item Any other value of @var{require-match} behaves like @code{t}, except diff --git a/etc/NEWS b/etc/NEWS index e19d08d51f..88758abc64 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1952,7 +1952,7 @@ Previously it produced a nonsense value, -1, that was never intended. * Lisp Changes in Emacs 29.1 +++ -** 'completing-read' now allows a function as REQUIRE-MATCH. +** 'completing-read' now allows a function as its REQUIRE-MATCH argument. This function is called to see whether what the user has typed in is a match. This is also available from functions that call 'completing-read', like 'read-file-name'. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 332e3fcce9..bf89874ecc 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -3161,8 +3161,8 @@ Fourth arg MUSTMATCH can take the following values: input, but she needs to confirm her choice if she called `minibuffer-complete' right before `minibuffer-complete-and-exit' and the input is not an existing file. -- a function, which will be called with the input as the parameter. - If it returns a non-nil value, we exit with that value. +- a function, which will be called with the input as the argument. + If it returns a non-nil value, the minibuffer is exited with that value. - anything else behaves like t except that typing RET does not exit if it does non-null completion. diff --git a/src/minibuf.c b/src/minibuf.c index 3e984d163d..2cfc2caa7f 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -2010,7 +2010,7 @@ REQUIRE-MATCH can take the following values: `minibuffer-complete' right before `minibuffer-complete-and-exit' and the input is not an element of COLLECTION. - a function, which will be called with the input as the parameter. - If it returns a non-nil value, we exit with that value. + If it returns a non-nil value, the minibuffer is exited with that value. - anything else behaves like t except that typing RET does not exit if it does non-null completion. commit 0afaf53c6ed2c2e915dbe87f062ce851b3f48dce Author: Richard Hansen Date: Thu Jun 2 16:33:16 2022 -0400 ; bindat (bindat--length-group): Fix indentation diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 760c86feb4..5f3c772983 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -320,72 +320,72 @@ e.g. corresponding to STRUCT.FIELD1[INDEX2].FIELD3..." (defun bindat--length-group (struct spec) (if (cl-typep spec 'bindat--type) (funcall (bindat--type-le spec) struct) - (with-suppressed-warnings ((lexical struct last)) - (defvar struct) (defvar last)) - (let ((struct struct) last) - (dolist (item spec) - (let* ((field (car item)) - (type (nth 1 item)) - (len (nth 2 item)) - (vectype (and (eq type 'vec) (nth 3 item))) - (tail 3)) - (if (and type (consp type) (eq (car type) 'eval)) - (setq type (eval (car (cdr type)) t))) - (if (and len (consp len) (eq (car len) 'eval)) - (setq len (eval (car (cdr len)) t))) - (if (memq field '(eval fill align struct union)) - (setq tail 2 - len type - type field - field nil)) - (if (and (consp field) (eq (car field) 'eval)) - (setq field (eval (car (cdr field)) t))) - (if (and (consp len) (not (eq type 'eval))) - (setq len (apply #'bindat-get-field struct len))) - (if (not len) - (setq len 1)) - (while (eq type 'vec) - (if (consp vectype) - (setq len (* len (nth 1 vectype)) - type (nth 2 vectype)) - (setq type (or vectype 'u8) - vectype nil))) - (pcase type - ('eval - (if field - (setq struct (cons (cons field (eval len t)) struct)) - (eval len t))) - ('fill - (setq bindat-idx (+ bindat-idx len))) - ('align - (setq bindat-idx (bindat--align bindat-idx len))) - ('struct - (bindat--length-group - (if field (bindat-get-field struct field) struct) (eval len t))) - ('repeat - (dotimes (index len) - (bindat--length-group - (nth index (bindat-get-field struct field)) - (nthcdr tail item)))) - ('union - (with-suppressed-warnings ((lexical tag)) - (defvar tag)) - (let ((tag len) (cases (nthcdr tail item)) case cc) - (while cases - (setq case (car cases) - cases (cdr cases) - cc (car case)) - (if (or (equal cc tag) (equal cc t) - (and (consp cc) (eval cc t))) - (progn - (bindat--length-group struct (cdr case)) - (setq cases nil)))))) - (_ - (if (setq type (assq type bindat--fixed-length-alist)) - (setq len (* len (cdr type)))) - (if field - (setq last (bindat-get-field struct field))) - (setq bindat-idx (+ bindat-idx len))))))))) + (with-suppressed-warnings ((lexical struct last)) + (defvar struct) (defvar last)) + (let ((struct struct) last) + (dolist (item spec) + (let* ((field (car item)) + (type (nth 1 item)) + (len (nth 2 item)) + (vectype (and (eq type 'vec) (nth 3 item))) + (tail 3)) + (if (and type (consp type) (eq (car type) 'eval)) + (setq type (eval (car (cdr type)) t))) + (if (and len (consp len) (eq (car len) 'eval)) + (setq len (eval (car (cdr len)) t))) + (if (memq field '(eval fill align struct union)) + (setq tail 2 + len type + type field + field nil)) + (if (and (consp field) (eq (car field) 'eval)) + (setq field (eval (car (cdr field)) t))) + (if (and (consp len) (not (eq type 'eval))) + (setq len (apply #'bindat-get-field struct len))) + (if (not len) + (setq len 1)) + (while (eq type 'vec) + (if (consp vectype) + (setq len (* len (nth 1 vectype)) + type (nth 2 vectype)) + (setq type (or vectype 'u8) + vectype nil))) + (pcase type + ('eval + (if field + (setq struct (cons (cons field (eval len t)) struct)) + (eval len t))) + ('fill + (setq bindat-idx (+ bindat-idx len))) + ('align + (setq bindat-idx (bindat--align bindat-idx len))) + ('struct + (bindat--length-group + (if field (bindat-get-field struct field) struct) (eval len t))) + ('repeat + (dotimes (index len) + (bindat--length-group + (nth index (bindat-get-field struct field)) + (nthcdr tail item)))) + ('union + (with-suppressed-warnings ((lexical tag)) + (defvar tag)) + (let ((tag len) (cases (nthcdr tail item)) case cc) + (while cases + (setq case (car cases) + cases (cdr cases) + cc (car case)) + (if (or (equal cc tag) (equal cc t) + (and (consp cc) (eval cc t))) + (progn + (bindat--length-group struct (cdr case)) + (setq cases nil)))))) + (_ + (if (setq type (assq type bindat--fixed-length-alist)) + (setq len (* len (cdr type)))) + (if field + (setq last (bindat-get-field struct field))) + (setq bindat-idx (+ bindat-idx len))))))))) (defun bindat-length (spec struct) "Calculate `bindat-raw' length for STRUCT according to bindat SPEC." commit c7037219b025ea7a53fc57528eaf5e41511f1e92 Author: Richard Hansen Date: Sat May 28 23:53:51 2022 -0400 ; bindat (strz): Consistent length type check, take two Commit 30ec4a7347b2944818c6fc469ae871374ce7caa4 is incorrect -- the length computation logic uses a simple nilness test, not `numberp'. The `numberp' case is just an optimization if `len' is a literal number; it does not affect the behavior. Revert that commit, add some comments to help future readers avoid the same mistake, and update the pack logic to use the same optimization as the length computation for consistency. diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 0725b677cf..760c86feb4 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -688,18 +688,23 @@ is the name of a variable that will hold the value we need to pack.") ('unpack `(bindat--unpack-strz ,len)) (`(length ,val) `(cl-incf bindat-idx ,(cond + ;; Optimizations if len is a literal number or nil. ((null len) `(1+ (length ,val))) ((numberp len) len) + ;; General expression support. (t `(or ,len (1+ (length ,val))))))) (`(pack . ,args) - (macroexp-let2 nil len len - `(if (numberp ,len) - ;; Same as non-zero terminated strings since we don't actually add - ;; the terminating zero anyway (because we rely on the fact that - ;; `bindat-raw' was presumably initialized with all-zeroes before - ;; we started). - (bindat--pack-str ,len . ,args) - (bindat--pack-strz . ,args)))))) + ;; When len is specified, behave the same as the str type since we don't + ;; actually add the terminating zero anyway (because we rely on the fact + ;; that `bindat-raw' was presumably initialized with all-zeroes before we + ;; started). + (cond ; Same optimizations as 'length above. + ((null len) `(bindat--pack-strz . ,args)) + ((numberp len) `(bindat--pack-str ,len . ,args)) + (t (macroexp-let2 nil len len + `(if ,len + (bindat--pack-str ,len . ,args) + (bindat--pack-strz . ,args)))))))) (cl-defmethod bindat--type (op (_ (eql 'bits)) len) (bindat--pcase op commit 4dfa7061588c63158e32d8af2f554c1182618ec0 Author: Richard Hansen Date: Sun May 29 17:15:04 2022 -0400 ; bindat-tests (str, strz): Refine tests str and strz: * Add tests for packing into a pre-allocated string. strz: * Add test cases to probe more boundary conditions. * Delete comments that no longer apply. * Add tests to ensure that truncated packed strings are rejected. * Keep the legacy spec tests in sync with the modern spec tests. diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el index b3850f14f1..4817072752 100644 --- a/test/lisp/emacs-lisp/bindat-tests.el +++ b/test/lisp/emacs-lisp/bindat-tests.el @@ -162,12 +162,40 @@ (bindat-pack bindat-test--LEB128 n)) n))))))) +(ert-deftest bindat-test--str-strz-prealloc () + (dolist (tc `(((,(bindat-type str 1) "") . "xx") + ((,(bindat-type str 2) "") . "xx") + ((,(bindat-type str 2) "a") . "ax") + ((,(bindat-type str 2) "ab") . "ab") + ((,(bindat-type str 2) "abc") . "ab") + ((((x str 1)) ((x . ""))) . "xx") + ((((x str 2)) ((x . ""))) . "xx") + ((((x str 2)) ((x . "a"))) . "ax") + ((((x str 2)) ((x . "ab"))) . "ab") + ((((x str 2)) ((x . "abc"))) . "ab") + ((,(bindat-type strz 1) "") . "xx") + ((,(bindat-type strz 2) "") . "xx") + ((,(bindat-type strz 2) "a") . "ax") + ((,(bindat-type strz 2) "ab") . "ab") + ((,(bindat-type strz 2) "abc") . "ab") + ((((x strz 1)) ((x . ""))) . "xx") + ((((x strz 2)) ((x . ""))) . "xx") + ((((x strz 2)) ((x . "a"))) . "ax") + ((((x strz 2)) ((x . "ab"))) . "ab") + ((((x strz 2)) ((x . "abc"))) . "ab") + ((,(bindat-type strz) "") . "xx") + ((,(bindat-type strz) "a") . "ax"))) + (let ((prealloc (make-string 2 ?x))) + (apply #'bindat-pack (append (car tc) (list prealloc))) + (should (equal prealloc (cdr tc)))))) + (let ((spec (bindat-type strz 2))) (ert-deftest bindat-test--strz-fixedlen-len () (should (equal (bindat-length spec "") 2)) (should (equal (bindat-length spec "a") 2))) (ert-deftest bindat-test--strz-fixedlen-len-overflow () + (should (equal (bindat-length spec "ab") 2)) (should (equal (bindat-length spec "abc") 2))) (ert-deftest bindat-test--strz-fixedlen-pack () @@ -177,17 +205,18 @@ (ert-deftest bindat-test--strz-fixedlen-pack-overflow () ;; This is not the only valid semantic, but it's the one we've ;; offered historically. + (should (equal (bindat-pack spec "ab") "ab")) (should (equal (bindat-pack spec "abc") "ab"))) (ert-deftest bindat-test--strz-fixedlen-unpack () - ;; There are no tests for unpacking "ab" or "ab\0" because those - ;; packed strings cannot be produced from the spec (packing "ab" - ;; should produce "a\0", not "ab" or "ab\0"). (should (equal (bindat-unpack spec "\0\0") "")) (should (equal (bindat-unpack spec "\0X") "")) (should (equal (bindat-unpack spec "a\0") "a")) ;; Same comment as for b-t-s-f-pack-overflow. - (should (equal (bindat-unpack spec "ab") "ab")))) + (should (equal (bindat-unpack spec "ab") "ab")) + ;; Missing null terminator. + (should-error (bindat-unpack spec "")) + (should-error (bindat-unpack spec "a")))) (let ((spec (bindat-type strz))) (ert-deftest bindat-test--strz-varlen-len () @@ -199,11 +228,11 @@ (should (equal (bindat-pack spec "abc") "abc\0"))) (ert-deftest bindat-test--strz-varlen-unpack () - ;; There is no test for unpacking a string without a null - ;; terminator because such packed strings cannot be produced from - ;; the spec (packing "a" should produce "a\0", not "a"). (should (equal (bindat-unpack spec "\0") "")) - (should (equal (bindat-unpack spec "abc\0") "abc")))) + (should (equal (bindat-unpack spec "abc\0") "abc")) + ;; Missing null terminator. + (should-error (bindat-unpack spec "")) + (should-error (bindat-unpack spec "a")))) (let ((spec '((x strz 2)))) (ert-deftest bindat-test--strz-legacy-fixedlen-len () @@ -211,6 +240,7 @@ (should (equal (bindat-length spec '((x . "a"))) 2))) (ert-deftest bindat-test--strz-legacy-fixedlen-len-overflow () + (should (equal (bindat-length spec '((x . "ab"))) 2)) (should (equal (bindat-length spec '((x . "abc"))) 2))) (ert-deftest bindat-test--strz-legacy-fixedlen-pack () @@ -219,13 +249,17 @@ (ert-deftest bindat-test--strz-legacy-fixedlen-pack-overflow () ;; Same comment as for b-t-s-f-pack-overflow. + (should (equal (bindat-pack spec '((x . "ab"))) "ab")) (should (equal (bindat-pack spec '((x . "abc"))) "ab"))) (ert-deftest bindat-test--strz-legacy-fixedlen-unpack () - ;; There are no tests for unpacking "ab" or "ab\0" because those - ;; packed strings cannot be produced from the spec (packing "ab" - ;; should produce "a\0", not "ab" or "ab\0"). (should (equal (bindat-unpack spec "\0\0") '((x . "")))) - (should (equal (bindat-unpack spec "a\0") '((x . "a")))))) + (should (equal (bindat-unpack spec "\0X") '((x . "")))) + (should (equal (bindat-unpack spec "a\0") '((x . "a")))) + ;; Same comment as for b-t-s-f-pack-overflow. + (should (equal (bindat-unpack spec "ab") '((x . "ab")))) + ;; Missing null terminator. + (should-error (bindat-unpack spec "")) + (should-error (bindat-unpack spec "a")))) ;;; bindat-tests.el ends here commit 245ca23196792e2ddf7550b0d7bd42c06c1cc618 Author: Richard Hansen Date: Thu Jun 9 19:58:56 2022 -0400 bindat (strz): Fix documentation for strz with pre-allocated string * doc/lispref/processes.texi (Bindat Types): Document that a null terminator is not written if `bindat-pack' is given a pre-allocated string. diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 7c37853eca..55fb93ec5a 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3490,12 +3490,21 @@ input string will appear in the unpacked output. @item strz &optional @var{len} If @var{len} is not provided: Variable-length null-terminated unibyte string (@pxref{Text Representations}). When packing, the entire input -string is copied to the packed output followed by a null byte. The +string is copied to the packed output. The following byte will be +null (zero) unless a pre-allocated string was provided to +@code{bindat-pack}, in which case that byte is left unmodified. The length of the packed output is the length of the input string plus one -(for the added null byte). The input string must not contain any null +(for the null terminator). The input string must not contain any null bytes. When unpacking, the resulting string contains all bytes up to (but excluding) the null byte. +@quotation Caution +If a pre-allocated string is provided to @code{bindat-pack}, the +packed output will not be properly null-terminated unless the +pre-allocated string already has a null byte at the appropriate +location. +@end quotation + If @var{len} is provided: @code{strz} behaves the same as @code{str} with one difference: When unpacking, the first null byte encountered in the packed string and all subsequent bytes are excluded from the commit 429b80062a62c357cde3d26a36a40da4d9742172 Author: Lars Ingebrigtsen Date: Fri Jun 10 11:48:57 2022 +0200 Link find-sibling-file to ff-find-related-file in manual * doc/emacs/files.texi (Visiting): Link to ff-find-related-file documentation. diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 2c4f1f4619..062185fb4a 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -349,6 +349,9 @@ say: '(("\\([^/]+\\)\\.c\\'" "\\1.h"))) @end lisp +(@code{ff-find-related-file} offers similar functionality especially +geared towards C files, @pxref{Other C Commands}.) + Or, if you want to consider all files under @samp{"src/emacs/DIR/file-name"} to be siblings of other @var{dir}s, you could say: commit 81a586282dc2fe4827a2b60a74aee79d87482ac5 Author: Lars Ingebrigtsen Date: Fri Jun 10 11:45:28 2022 +0200 Fix find-sibling-file doc string * lisp/files.el (find-sibling-file): Remove incorrect statement from doc string (bug#55879). diff --git a/lisp/files.el b/lisp/files.el index 8836ee6fb2..75a856c636 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7312,9 +7312,6 @@ now defined as a sibling." (defun find-sibling-file (file) "Visit a \"sibling\" file of FILE. -By default, return only files that exist, but if ALL is non-nil, -return all matches. - When called interactively, FILE is the currently visited file. The \"sibling\" file is defined by the `find-sibling-rules' variable." commit 15a5c5ce40143edbdd436eeaa4cbb55f025f1771 Author: Lars Ingebrigtsen Date: Fri Jun 10 11:39:51 2022 +0200 Make describe-prefix-bindings say when there are no matches * lisp/help.el (describe-prefix-bindings): Say when there are no bindings under a prefix (bug#55875), for instance in `C-c C-h' in a buffer with no `C-c' commands. diff --git a/lisp/help.el b/lisp/help.el index 4e0d807cb2..abdce46edf 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -392,16 +392,23 @@ If that doesn't give a function, return nil." The prefix described consists of all but the last event of the key sequence that ran this command." (interactive) - (let ((key (this-command-keys))) - (describe-bindings - (if (stringp key) - (substring key 0 (1- (length key))) - (let ((prefix (make-vector (1- (length key)) nil)) - (i 0)) - (while (< i (length prefix)) - (aset prefix i (aref key i)) - (setq i (1+ i))) - prefix))))) + (let* ((key (this-command-keys)) + (prefix + (if (stringp key) + (substring key 0 (1- (length key))) + (let ((prefix (make-vector (1- (length key)) nil)) + (i 0)) + (while (< i (length prefix)) + (aset prefix i (aref key i)) + (setq i (1+ i))) + prefix)))) + (describe-bindings prefix) + (with-current-buffer (help-buffer) + (when (< (buffer-size) 10) + (let ((inhibit-read-only t)) + (insert (format "No commands with a binding that start with %s." + (help--key-description-fontified prefix)))))))) + ;; Make C-h after a prefix, when not specifically bound, ;; run describe-prefix-bindings. (setq prefix-help-command 'describe-prefix-bindings) commit 071722e41120f8894b5482d9eccc663a28f81058 Author: Ignacio Casso Date: Fri Jun 10 11:13:20 2022 +0200 Fix issues with loading autoloaded defcustoms while bound * doc/lispref/customize.texi (Variable Definitions) (Variable Definitions): Update documentation. * lisp/custom.el (custom-initialize-set) (custom-initialize-reset): Update doc string. (custom-initialize-changed): Use set-default-toplevel-value. This fixes issues with (let ((custom-variable ...)) (autoload-function ...)). (custom-set-default): Ditto. * src/data.c (Fdefault_boundp): Update doc string. diff --git a/doc/lispref/customize.texi b/doc/lispref/customize.texi index 54059d7b6e..528421bf3b 100644 --- a/doc/lispref/customize.texi +++ b/doc/lispref/customize.texi @@ -376,7 +376,7 @@ name) and the new value, and should do whatever is necessary to update the value properly for this option (which may not mean simply setting the option as a Lisp variable); preferably, though, it should not modify its value argument destructively. The default for -@var{setfunction} is @code{set-default}. +@var{setfunction} is @code{set-default-toplevel-value}. If you specify this keyword, the variable's documentation string should describe how to do the same job in hand-written Lisp code. @@ -387,7 +387,7 @@ Specify @var{getfunction} as the way to extract the value of this option. The function @var{getfunction} should take one argument, a symbol, and should return whatever customize should use as the current value for that symbol (which need not be the symbol's Lisp -value). The default is @code{default-value}. +value). The default is @code{default-toplevel-value}. You have to really understand the workings of Custom to use @code{:get} correctly. It is meant for values that are treated in @@ -409,11 +409,11 @@ do not reinitialize it if it is already non-void. @item custom-initialize-default Like @code{custom-initialize-set}, but use the function -@code{set-default} to set the variable, instead of the variable's -@code{:set} function. This is the usual choice for a variable whose -@code{:set} function enables or disables a minor mode; with this choice, -defining the variable will not call the minor mode function, but -customizing the variable will do so. +@code{set-default-toplevel-value} to set the variable, instead of the +variable's @code{:set} function. This is the usual choice for a +variable whose @code{:set} function enables or disables a minor mode; +with this choice, defining the variable will not call the minor mode +function, but customizing the variable will do so. @item custom-initialize-reset Always use the @code{:set} function to initialize the variable. If @@ -424,7 +424,7 @@ This is the default @code{:initialize} function. @item custom-initialize-changed Use the @code{:set} function to initialize the variable, if it is already set or has been customized; otherwise, just use -@code{set-default}. +@code{set-default-toplevel-value}. @item custom-initialize-delay This function behaves like @code{custom-initialize-set}, but it diff --git a/lisp/custom.el b/lisp/custom.el index a084304ff8..2b7621229d 100644 --- a/lisp/custom.el +++ b/lisp/custom.el @@ -67,8 +67,10 @@ symbol." (defun custom-initialize-set (symbol exp) "Initialize SYMBOL based on EXP. -If the symbol doesn't have a default binding already, -then set it using its `:set' function (or `set-default' if it has none). +If the symbol doesn't have a default binding already, then set it +using its `:set' function (or `set-default-toplevel-value' if it +has none). + The value is either the value in the symbol's `saved-value' property, if any, or the value of EXP." (condition-case nil @@ -81,7 +83,9 @@ if any, or the value of EXP." (defun custom-initialize-reset (symbol exp) "Initialize SYMBOL based on EXP. -Set the symbol, using its `:set' function (or `set-default' if it has none). +Set the symbol, using its `:set' function (or `set-default-toplevel-value' +if it has none). + The value is either the symbol's current value (as obtained using the `:get' function), if any, or the value in the symbol's `saved-value' property if any, @@ -100,7 +104,7 @@ or (last of all) the value of EXP." "Initialize SYMBOL with EXP. Like `custom-initialize-reset', but only use the `:set' function if not using the standard setting. -For the standard setting, use `set-default'." +For the standard setting, use `set-default-toplevel-value'." (condition-case nil (let ((def (default-toplevel-value symbol))) (funcall (or (get symbol 'custom-set) #'set-default-toplevel-value) @@ -114,7 +118,7 @@ For the standard setting, use `set-default'." symbol (eval (car (get symbol 'saved-value))))) (t - (set-default symbol (eval exp))))))) + (set-default-toplevel-value symbol (eval exp))))))) (defvar custom-delayed-init-variables nil "List of variables whose initialization is pending until startup. @@ -262,11 +266,11 @@ The following keywords are meaningful: when using the Customize user interface. It takes two arguments, the symbol to set and the value to give it. The function should not modify its value argument destructively. The default choice - of function is `set-default'. + of function is `set-default-toplevel-value'. :get VALUE should be a function to extract the value of symbol. The function takes one argument, a symbol, and should return the current value for that symbol. The default choice of function - is `default-value'. + is `default-toplevel-value'. :require VALUE should be a feature symbol. If you save a value for this option, then when your init file loads the value, @@ -717,7 +721,7 @@ this sets the local binding in that buffer instead." (if custom-local-buffer (with-current-buffer custom-local-buffer (set variable value)) - (set-default variable value))) + (set-default-toplevel-value variable value))) (defun custom-set-minor-mode (variable value) ":set function for minor mode variables. diff --git a/src/data.c b/src/data.c index 72dcf6f878..46c0c5b6ae 100644 --- a/src/data.c +++ b/src/data.c @@ -1939,9 +1939,9 @@ default_value (Lisp_Object symbol) DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0, doc: /* Return t if SYMBOL has a non-void default value. -A variable may have a buffer-local or a `let'-bound local value. This -function says whether the variable has a non-void value outside of the -current context. Also see `default-value'. */) +A variable may have a buffer-local value. This function says whether +the variable has a non-void value outside of the current buffer +context. Also see `default-value'. */) (Lisp_Object symbol) { register Lisp_Object value; commit 07fb8d284f8d08f79bb65e764b39180e2b974761 Author: Lars Ingebrigtsen Date: Fri Jun 10 10:51:34 2022 +0200 Don't put trailing optional nil values into `command-history' * src/callint.c (fix_command): Don't put trailing optional nil values into `command-history' (bug#45333). diff --git a/src/callint.c b/src/callint.c index 92bfaf8d39..8283c61da6 100644 --- a/src/callint.c +++ b/src/callint.c @@ -170,7 +170,7 @@ check_mark (bool for_region) of VALUES to do its job. */ static void -fix_command (Lisp_Object input, Lisp_Object values) +fix_command (Lisp_Object input, Lisp_Object function, Lisp_Object values) { /* FIXME: Instead of this ugly hack, we should provide a way for an interactive spec to return an expression/function that will re-build the @@ -230,6 +230,37 @@ fix_command (Lisp_Object input, Lisp_Object values) } } } + + /* If the list contains a bunch of trailing nil values, and they are + optional, remove them from the list. This makes navigating the + history less confusing, since it doesn't contain a lot of + parameters that aren't used. */ + if (CONSP (values)) + { + Lisp_Object arity = Ffunc_arity (function); + /* We don't want to do this simplification if we have an &rest + function, because (cl-defun foo (a &optional (b 'zot)) ..) + etc. */ + if (FIXNUMP (XCAR (arity)) && FIXNUMP (XCDR (arity))) + { + Lisp_Object final = Qnil; + ptrdiff_t final_i = 0, i = 0; + for (Lisp_Object tail = values; + CONSP (tail); + tail = XCDR (tail), ++i) + { + if (!NILP (XCAR (tail))) + { + final = tail; + final_i = i; + } + } + + /* Chop the trailing optional values. */ + if (final_i > 0 && final_i >= XFIXNUM (XCAR (arity)) - 1) + XSETCDR (final, Qnil); + } + } } /* Helper function to call `read-file-name' from C. */ @@ -340,7 +371,7 @@ invoke it (via an `interactive' spec that contains, for instance, an Make a copy of the list of values, for the command history, and turn them into things we can eval. */ Lisp_Object values = quotify_args (Fcopy_sequence (specs)); - fix_command (input, values); + fix_command (input, function, values); call4 (intern ("add-to-history"), intern ("command-history"), Fcons (function, values), Qnil, Qt); } commit 068ce6411d20646ac5a8a80a79167068b3247554 Author: Mattias Engdegård Date: Fri Jun 10 10:22:24 2022 +0200 Fix macOS parallel bootstrap error (bug#55846) * nextstep/Makefile.in (${ns_appdir}): Change to a single-target rule to avoid the same actions being executed in parallel. diff --git a/nextstep/Makefile.in b/nextstep/Makefile.in index 92d7f28fe6..9c7059f2c0 100644 --- a/nextstep/Makefile.in +++ b/nextstep/Makefile.in @@ -47,7 +47,9 @@ ns_check_file = @ns_appdir@/@ns_check_file@ all: ${ns_appdir} ${ns_appbindir}/Emacs ${ns_applibexecdir}/Emacs.pdmp -${ns_check_file} ${ns_appdir}: ${srcdir}/${ns_appsrc} ${ns_appsrc} +${ns_check_file}: ${ns_appdir} + +${ns_appdir}: ${srcdir}/${ns_appsrc} ${ns_appsrc} rm -rf ${ns_appdir} ${MKDIR_P} ${ns_appdir} ( cd ${srcdir}/${ns_appsrc} ; tar cfh - . ) | \ commit 307ef05587be7cec5343799ac28a7581064fb467 Author: Lars Ingebrigtsen Date: Fri Jun 10 10:21:30 2022 +0200 Mention the REQUIRE-MATCH extension in NEWS diff --git a/etc/NEWS b/etc/NEWS index cd4b1b06ec..e19d08d51f 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1951,6 +1951,12 @@ Previously it produced a nonsense value, -1, that was never intended. * Lisp Changes in Emacs 29.1 ++++ +** 'completing-read' now allows a function as REQUIRE-MATCH. +This function is called to see whether what the user has typed in is a +match. This is also available from functions that call +'completing-read', like 'read-file-name'. + +++ ** 'posn-col-row' can now give position data based on windows. Previously, it reported data only based on the frame. commit 7ee736a884766f2017a934d936bfbfa4c70b5099 Author: Lars Ingebrigtsen Date: Fri Jun 10 10:19:15 2022 +0200 Allow specifying a wildcard argument to list-directory again * lisp/files.el (list-directory): Allow specifying a wildcard argument interactively again (bug#55877). diff --git a/lisp/files.el b/lisp/files.el index 5f4c4fa017..8836ee6fb2 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7386,12 +7386,11 @@ and `list-directory-verbose-switches'." (list (read-file-name (if pfx "List directory (verbose): " "List directory (brief): ") - nil default-directory t - nil + nil default-directory (lambda (file) (or (file-directory-p file) (insert-directory-wildcard-in-dir-p - (expand-file-name file))))) + (file-name-as-directory (expand-file-name file)))))) pfx))) (let ((switches (if verbose list-directory-verbose-switches list-directory-brief-switches)) commit 49e06183f5972817d93dad6acf5351c204e61cc5 Author: Lars Ingebrigtsen Date: Fri Jun 10 10:16:57 2022 +0200 Allow REQUIRE-MATCH to be a function * doc/lispref/minibuf.texi (Minibuffer Completion): Document it. * lisp/minibuffer.el (completion--complete-and-exit): Allow REQUIRE-MATCH to be a function. (read-file-name): Mention it. * src/minibuf.c (Fcompleting_read): Mention it. diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index be81b5b3fb..86e601f8c0 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -1121,6 +1121,11 @@ completion command (i.e., one of the commands in @code{minibuffer-confirm-exit-commands}) and the resulting input is not an element of @var{collection}. @xref{Completion Commands}. +@item +If a function, the function is called with the input as the only +argument. The function should return a non-@code{nil} value of the +input is acceptable. + @item Any other value of @var{require-match} behaves like @code{t}, except that the exit commands won't exit if it performs completion. diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index cdbde2d340..332e3fcce9 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -1726,52 +1726,57 @@ If `minibuffer-completion-confirm' is `confirm-after-completion', "Exit from `require-match' minibuffer. COMPLETION-FUNCTION is called if the current buffer's content does not appear to be a match." - (cond - ;; Allow user to specify null string + (cond + ;; Allow user to specify null string ((= beg end) (funcall exit-function)) - ((test-completion (buffer-substring beg end) - minibuffer-completion-table - minibuffer-completion-predicate) - ;; FIXME: completion-ignore-case has various slightly - ;; incompatible meanings. E.g. it can reflect whether the user - ;; wants completion to pay attention to case, or whether the - ;; string will be used in a context where case is significant. - ;; E.g. usually try-completion should obey the first, whereas - ;; test-completion should obey the second. - (when completion-ignore-case - ;; Fixup case of the field, if necessary. - (let* ((string (buffer-substring beg end)) - (compl (try-completion - string - minibuffer-completion-table - minibuffer-completion-predicate))) - (when (and (stringp compl) (not (equal string compl)) - ;; If it weren't for this piece of paranoia, I'd replace - ;; the whole thing with a call to do-completion. - ;; This is important, e.g. when the current minibuffer's - ;; content is a directory which only contains a single - ;; file, so `try-completion' actually completes to - ;; that file. - (= (length string) (length compl))) - (completion--replace beg end compl)))) - (funcall exit-function)) - - ((memq minibuffer-completion-confirm '(confirm confirm-after-completion)) - ;; The user is permitted to exit with an input that's rejected - ;; by test-completion, after confirming her choice. - (if (or (eq last-command this-command) - ;; For `confirm-after-completion' we only ask for confirmation - ;; if trying to exit immediately after typing TAB (this - ;; catches most minibuffer typos). - (and (eq minibuffer-completion-confirm 'confirm-after-completion) - (not (memq last-command minibuffer-confirm-exit-commands)))) + ;; The CONFIRM argument is a predicate. + ((and (functionp minibuffer-completion-confirm) + (funcall minibuffer-completion-confirm + (buffer-substring beg end))) + (funcall exit-function)) + ;; See if we have a completion from the table. + ((test-completion (buffer-substring beg end) + minibuffer-completion-table + minibuffer-completion-predicate) + ;; FIXME: completion-ignore-case has various slightly + ;; incompatible meanings. E.g. it can reflect whether the user + ;; wants completion to pay attention to case, or whether the + ;; string will be used in a context where case is significant. + ;; E.g. usually try-completion should obey the first, whereas + ;; test-completion should obey the second. + (when completion-ignore-case + ;; Fixup case of the field, if necessary. + (let* ((string (buffer-substring beg end)) + (compl (try-completion + string + minibuffer-completion-table + minibuffer-completion-predicate))) + (when (and (stringp compl) (not (equal string compl)) + ;; If it weren't for this piece of paranoia, I'd replace + ;; the whole thing with a call to do-completion. + ;; This is important, e.g. when the current minibuffer's + ;; content is a directory which only contains a single + ;; file, so `try-completion' actually completes to + ;; that file. + (= (length string) (length compl))) + (completion--replace beg end compl)))) + (funcall exit-function)) + ;; The user is permitted to exit with an input that's rejected + ;; by test-completion, after confirming her choice. + ((memq minibuffer-completion-confirm '(confirm confirm-after-completion)) + (if (or (eq last-command this-command) + ;; For `confirm-after-completion' we only ask for confirmation + ;; if trying to exit immediately after typing TAB (this + ;; catches most minibuffer typos). + (and (eq minibuffer-completion-confirm 'confirm-after-completion) + (not (memq last-command minibuffer-confirm-exit-commands)))) (funcall exit-function) - (minibuffer-message "Confirm") - nil)) + (minibuffer-message "Confirm") + nil)) - (t - ;; Call do-completion, but ignore errors. - (funcall completion-function)))) + (t + ;; Call do-completion, but ignore errors. + (funcall completion-function)))) (defun completion--try-word-completion (string table predicate point md) (let ((comp (completion-try-completion string table predicate point md))) @@ -3156,6 +3161,8 @@ Fourth arg MUSTMATCH can take the following values: input, but she needs to confirm her choice if she called `minibuffer-complete' right before `minibuffer-complete-and-exit' and the input is not an existing file. +- a function, which will be called with the input as the parameter. + If it returns a non-nil value, we exit with that value. - anything else behaves like t except that typing RET does not exit if it does non-null completion. diff --git a/src/minibuf.c b/src/minibuf.c index 79985b8d2b..3e984d163d 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -2009,6 +2009,8 @@ REQUIRE-MATCH can take the following values: input, but she needs to confirm her choice if she called `minibuffer-complete' right before `minibuffer-complete-and-exit' and the input is not an element of COLLECTION. +- a function, which will be called with the input as the parameter. + If it returns a non-nil value, we exit with that value. - anything else behaves like t except that typing RET does not exit if it does non-null completion. commit 32aa5c76bdb0236f159f24a7d8a7698b88fcb712 Author: Po Lu Date: Fri Jun 10 15:27:07 2022 +0800 Fix receiving drops from drop-only Motif programs * lisp/x-dnd.el (x-dnd-xm-read-targets-table): Fix doc string. (x-dnd-handle-motif): Recompute types and state on XmDROP_START if no state already exists. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 85b4138f17..7ee20e0fc3 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -624,7 +624,9 @@ describing the selection targets in the current rec." (defun x-dnd-xm-read-targets-table (frame) "Read the Motif targets table on FRAME. -Return a vector of vectors of numbers (the drop targets)." +Return a vector of vectors of numbers, which are the atoms of the +available selection targets for each index into the selection +table." (let* ((drag-window (x-window-property "_MOTIF_DRAG_WINDOW" frame "WINDOW" 0 nil t)) (targets-data (x-window-property "_MOTIF_DRAG_TARGETS" @@ -809,60 +811,71 @@ Return a vector of atoms containing the selection targets." (selection-atom (x-dnd-get-motif-value data 12 4 source-byteorder)) (atom-name (x-get-atom-name selection-atom)) - (dnd-source (x-dnd-get-motif-value - data 16 4 source-byteorder)) - (action-type (x-dnd-maybe-call-test-function - window - source-action)) - (reply-action (and (not (posn-area (event-start event))) - (car (rassoc (car action-type) - x-dnd-motif-to-action)))) - (reply-flags - (x-dnd-motif-value-to-list - (if (posn-area (event-start event)) - (+ ?\x20 ; 20: invalid drop site - ?\x200) ; 200: drop cancel - (if reply-action - (+ reply-action - ?\x30 ; 30: valid drop site - ?\x700) ; 700: can do copy, move or link - (+ ?\x30 ; 30: drop site, but noop. - ?\x200))) ; 200: drop cancel. + (dnd-source (x-dnd-get-motif-value + data 16 4 source-byteorder))) + + ;; This might be a drop from a program that doesn't use + ;; the Motif drag protocol. Compute all the necessary + ;; state here if that is true. + (unless (and (x-dnd-get-state-for-frame frame) + (aref (x-dnd-get-state-for-frame frame) 2)) + (x-dnd-forget-drop frame) + (let ((types (x-dnd-xm-read-targets frame dnd-source + atom-name))) + (x-dnd-save-state window nil nil types dnd-source))) + + (let* ((action-type (x-dnd-maybe-call-test-function + window + source-action)) + (reply-action (and (not (posn-area (event-start event))) + (car (rassoc (car action-type) + x-dnd-motif-to-action)))) + (reply-flags + (x-dnd-motif-value-to-list + (if (posn-area (event-start event)) + (+ ?\x20 ; 20: invalid drop site + ?\x200) ; 200: drop cancel + (if reply-action + (+ reply-action + ?\x30 ; 30: valid drop site + ?\x700) ; 700: can do copy, move or link + (+ ?\x30 ; 30: drop site, but noop. + ?\x200))) ; 200: drop cancel. 2 my-byteorder)) - (reply (append - (list - (+ ?\x80 ; 0x80 indicates a reply. - 5) ; DROP_START. - my-byteorder) - reply-flags - x y)) - (timestamp (x-dnd-get-motif-value - data 4 4 source-byteorder)) - action) - - (x-send-client-message frame - dnd-source - frame - "_MOTIF_DRAG_AND_DROP_MESSAGE" - 8 - reply) - (setq action - (when (and reply-action atom-name) - (let* ((value (x-get-selection-internal - (intern atom-name) - (intern (x-dnd-current-type window))))) - (when value - (condition-case info - (x-dnd-drop-data event frame window value - (x-dnd-current-type window)) - (error - (message "Error: %s" info) - nil)))))) - (x-get-selection-internal - (intern atom-name) - (if action 'XmTRANSFER_SUCCESS 'XmTRANSFER_FAILURE) - timestamp) - (x-dnd-forget-drop frame))) + (reply (append + (list + (+ ?\x80 ; 0x80 indicates a reply. + 5) ; DROP_START. + my-byteorder) + reply-flags + x y)) + (timestamp (x-dnd-get-motif-value + data 4 4 source-byteorder)) + action) + + (x-send-client-message frame + dnd-source + frame + "_MOTIF_DRAG_AND_DROP_MESSAGE" + 8 + reply) + (setq action + (when (and reply-action atom-name) + (let* ((value (x-get-selection-internal + (intern atom-name) + (intern (x-dnd-current-type window))))) + (when value + (condition-case info + (x-dnd-drop-data event frame window value + (x-dnd-current-type window)) + (error + (message "Error: %s" info) + nil)))))) + (x-get-selection-internal + (intern atom-name) + (if action 'XmTRANSFER_SUCCESS 'XmTRANSFER_FAILURE) + timestamp) + (x-dnd-forget-drop frame)))) (t (message "Unknown Motif drag-and-drop message: %s" (logand (aref data 0) #x3f))))))) commit 0705705ebf7d19e30b97b0fab508ffc7ec1bec69 Author: Eli Zaretskii Date: Fri Jun 10 10:06:06 2022 +0300 Improve documentation of "etags -I" * doc/man/etags.1: * doc/emacs/maintaining.texi (Create Tags Table): Elaborate on the importance of the '-I' option to 'etags'. (Bug#45246) diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 0a813a85d4..c23907ddfb 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -2802,6 +2802,13 @@ place of a file name on the command line. @command{etags} will read from standard input and mark the produced tags as belonging to the file @var{file}. + For C and C++, if the source files don't observe the GNU Coding +Standards' convention if having braces (@samp{@{} and @samp{@}}) in +column zero only for top-level definitions, like functions and +@code{struct} definitions, we advise that you use the +@samp{--ignore-indentation} option, to prevent @command{etags} from +incorrectly interpreting closing braces in column zero. + @samp{etags --help} outputs the list of the languages @command{etags} knows, and the file name rules for guessing the language. It also prints a list of all the available @command{etags} options, together with a short diff --git a/doc/man/etags.1 b/doc/man/etags.1 index d345b8bd73..96781569fc 100644 --- a/doc/man/etags.1 +++ b/doc/man/etags.1 @@ -122,7 +122,9 @@ current file. Only \fBetags\fP accepts this option. .B \-I, \-\-ignore\-indentation Don't rely on indentation as much as we normally do. Currently, this means not to assume that a closing brace in the first column is the -final brace of a function or structure definition in C and C++. +final brace of a function or structure definition in C and C++. This +is important for code that doesn't observe the GNU Coding conventions +of placing only top-level braces in column zero. .TP \fB\-l\fP \fIlanguage\fP, \fB\-\-language=\fIlanguage\fP Parse the following files according to the given language. More than commit 0ad8cd40ce74c354d6a81ba08e4c694c01baa00e Merge: 8436e0bee9 22a832ad82 Author: Eli Zaretskii Date: Fri Jun 10 10:04:28 2022 +0300 Merge branch 'emacs-28' of git.savannah.gnu.org:/srv/git/emacs into emacs-28 commit 45bdeb7d9c62dbc4811db85da81993f45b6b9780 Author: Po Lu Date: Fri Jun 10 14:47:40 2022 +0800 Eliminate extra call to XTranslateCoordinates looking for drop target * src/xterm.c (x_dnd_get_target_window): Translate coordinates starting from the root window and avoid extra sync. diff --git a/src/xterm.c b/src/xterm.c index ed8f068136..375b345a90 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3553,7 +3553,7 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, int root_x, int root_y, int *proto_out, int *motif_out, Window *toplevel_out) { - Window child_return, child, dummy, proxy; + Window child_return, child, proxy; int dest_x_return, dest_y_return, rc, proto, motif; int parent_x, parent_y; bool extents_p; @@ -3698,11 +3698,9 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, parent_y = dest_y_return; x_catch_errors (dpyinfo->display); - rc = XTranslateCoordinates (dpyinfo->display, - child_return, child_return, - dest_x_return, dest_y_return, - &dest_x_return, &dest_y_return, - &child_return); + rc = XTranslateCoordinates (dpyinfo->display, dpyinfo->root_window, + child_return, root_x, root_y, &dest_x_return, + &dest_y_return, &child_return); if (x_had_errors_p (dpyinfo->display) || !rc) { @@ -3757,23 +3755,9 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, return proxy; } } - - rc = XTranslateCoordinates (dpyinfo->display, - child, child_return, - dest_x_return, dest_y_return, - &dest_x_return, &dest_y_return, - &dummy); - - if (x_had_errors_p (dpyinfo->display) || !rc) - { - x_uncatch_errors_after_check (); - *proto_out = -1; - *toplevel_out = dpyinfo->root_window; - return None; - } } - x_uncatch_errors_after_check (); + x_uncatch_errors (); } #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) commit e70d82d85529104deae45e5bdfe635d5dd9cd200 Merge: 7d9d5ecf86 22a832ad82 Author: Stefan Kangas Date: Fri Jun 10 08:17:35 2022 +0200 Merge from origin/emacs-28 22a832ad82 Mention the #f syntax from cl-prin1 commit 7d9d5ecf86abfe276ba3e1af4ce21f849eadd604 Merge: 1766609309 3fd0854378 Author: Stefan Kangas Date: Fri Jun 10 08:17:35 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: 3fd0854378 Fix file name quoting in tramp-smb.el (do not merge) commit 17666093097d58466e9581b9ff1d07ec5e3eeebf Merge: 8ac23bf0f6 d02c94090c Author: Stefan Kangas Date: Fri Jun 10 08:17:35 2022 +0200 Merge from origin/emacs-28 d02c94090c Fix error reporting in process-async-https-with-delay 9a4862a973 * doc/misc/org.org: Remove spurious markup. 768ed1476a Make Tramp version check more robust 7f778c6943 Fix debugging with GDB when a breakpoint has multiple loca... 25e53e9391 ; * lisp/files.el (file-expand-wildcards): Doc fix. 3ea9357d10 Update documentation of 'aset' and 'store-substring' # Conflicts: # lisp/files.el commit 8ac23bf0f6d1efc564b7086150cbadc11fba31a2 Author: Po Lu Date: Fri Jun 10 13:11:20 2022 +0800 Add tests for x-dnd Motif value parsing logic * test/lisp/x-dnd-tests.el: New file. diff --git a/test/lisp/x-dnd-tests.el b/test/lisp/x-dnd-tests.el new file mode 100644 index 0000000000..35cda3b10a --- /dev/null +++ b/test/lisp/x-dnd-tests.el @@ -0,0 +1,82 @@ +;;; dnd-tests.el --- Tests for X DND support -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Tests for stuff in x-dnd.el that doesn't require a window system. + +;;; Code: + +(require 'x-dnd) + +(when (display-graphic-p) + (error "This test cannot be run under X")) + +;; Dummy replacements. + +(defconst x-dnd-tests-drag-window-xid 3948573 + "XID of the drag window returned during the test.") + +(defconst x-dnd-tests-targets-table + (base64-decode-string + "bAArAKIBAAAGAB8AAABqAQAANgIAAJMCAAAFAwAABgMAAAEAkMJbAAEAINNbAAUAHwAAAGoBAAA2 +AgAAkwIAANkfAAALAB8AAABqAQAANgIAAJMCAADyAgAA2R8AANwfAADgHwAA4R8AAOIfAADjHwAA +AQDQMAgCAQBQTggCAQCwe5IAAQDQmZIABgDyAgAA9wIAABcRAADgHwAAvSEAAI3AAAABAHC52AAB +AGDY2AABAABq3QABAGBw3QAIAB8AAAA2AgAA8gIAANwfAADgHwAA4R8AAOIfAADjHwAAAQBwBOEA +AQCACuEAAQAwLwUCAQDwPgUCAQBQxoQBAQCQ3YQBAQCQBYoBAQDACYoBAQCgMooBAQCgOIoBAQAf +AAAAAQDATrcDAQAQ1LcDAQCw/sADAQAgBcEDAQBQt7oDAQAAUsIDAQCAc7wDAQAwerwDAQBAIKUE +AQAALKUEAQDwfKUEAQDgg6UEAQCgjesEAQAAmusEAQCA7+sEAQCw9usECAAfAAAAagEAADYCAACT +AgAABQMAAAYDAAATGwAAGhsAAA==") + "Predefined Motif targets table used to test the targets table parser.") + +(defconst x-dnd-tests-lispy-targets-table [[31 362 566 659 773 774] [6013584] [6017824] + [31 362 566 659 8153] + [31 362 566 659 754 8153 8156 8160 8161 8162 8163] + [34091216] [34098768] [9599920] + [9607632] [754 759 4375 8160 8637 49293] + [14203248] [14211168] [14510592] + [14512224] [31 566 754 8156 8160 8161 8162 8163] + [14746736] [14748288] [33894192] [33898224] + [25478736] [25484688] [25822608] [25823680] + [25834144] [25835680] [31] [62344896] [62379024] + [62979760] [62981408] [62568272] [63066624] + [62681984] [62683696] [77930560] [77933568] + [77954288] [77956064] [82546080] [82549248] + [82571136] [82572976] [31 362 566 659 773 774 6931 6938]] + "The expected result of parsing that targets table.") + +(defalias 'x-window-property + (lambda (prop &optional _frame type window-id _delete-p _vector-ret-p) + (cond + ((and (equal prop "_MOTIF_DRAG_WINDOW") + (zerop window-id) (equal type "WINDOW")) + x-dnd-tests-drag-window-xid) + ((and (equal prop "_MOTIF_DRAG_TARGETS") + (equal type "_MOTIF_DRAG_TARGETS") + (equal window-id x-dnd-tests-drag-window-xid)) + x-dnd-tests-targets-table)))) + +;; This test also serves to exercise most of the Motif value +;; extraction code. +(ert-deftest x-dnd-tests-read-xm-targets-table () + (should (equal (x-dnd-xm-read-targets-table nil) + x-dnd-tests-lispy-targets-table))) + +(provide 'x-dnd-tests) +;;; x-dnd-tests.el ends here commit 66aaedffd6b595e03ffcc2bc16c24d7cdd710d40 Author: Po Lu Date: Fri Jun 10 11:45:27 2022 +0800 Don't rely on TARGETS to read selection targets for Motif DND * lisp/x-dnd.el (x-dnd-types-alist): (x-dnd-known-types): Fix formatting. (x-dnd-xm-unpack-targets-table-header): (x-dnd-xm-read-single-rec): (x-dnd-xm-read-targets-table): (x-dnd-xm-read-targets): New functions. (x-dnd-handle-motif): Read targets from the targets table of the drag window instead of the selection's TARGET target. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index 7befea7418..85b4138f17 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -52,8 +52,7 @@ The default value for this variable is `x-dnd-default-test-function'." (defcustom x-dnd-types-alist - `( - (,(purecopy "text/uri-list") . x-dnd-handle-uri-list) + `((,(purecopy "text/uri-list") . x-dnd-handle-uri-list) (,(purecopy "text/x-moz-url") . x-dnd-handle-moz-url) (,(purecopy "_NETSCAPE_URL") . x-dnd-handle-uri-list) (,(purecopy "FILE_NAME") . x-dnd-handle-file-name) @@ -64,8 +63,7 @@ The default value for this variable is `x-dnd-default-test-function'." (,(purecopy "text/plain") . dnd-insert-text) (,(purecopy "COMPOUND_TEXT") . x-dnd-insert-ctext) (,(purecopy "STRING") . dnd-insert-text) - (,(purecopy "TEXT") . dnd-insert-text) - ) + (,(purecopy "TEXT") . dnd-insert-text)) "Which function to call to handle a drop of that type. If the type for the drop is not present, or the function is nil, the drop is rejected. The function takes three arguments, WINDOW, ACTION @@ -91,8 +89,7 @@ if drop is successful, nil if not." "text/plain" "COMPOUND_TEXT" "STRING" - "TEXT" - )) + "TEXT")) "The types accepted by default for dropped data. The types are chosen in the order they appear in the list." :version "22.1" @@ -588,6 +585,86 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (reverse bytes) bytes))) +(defun x-dnd-xm-unpack-targets-table-header (data) + "Decode the header of DATA, a Motif targets table. +Return a list of the following fields with the given types: + + Field name Type + - BYTE_ORDER BYTE + - PROTOCOL BYTE + - TARGET_LIST_COUNT CARD16 + - TOTAL_DATA_SIZE CARD32" + (let* ((byte-order (aref data 0)) + (protocol (aref data 1)) + (target-list-count (x-dnd-get-motif-value + data 2 2 byte-order)) + (total-data-size (x-dnd-get-motif-value + data 4 4 byte-order))) + (list byte-order protocol target-list-count + total-data-size))) + +(defun x-dnd-xm-read-single-rec (data i) + "Read a single rec from DATA, a Motif targets table. +I is the offset into DATA to begin reading at. Return a list +of (CONSUMED NTARGETS TARGETS), where CONSUMED is the number of +bytes read from DATA, NTARGETS is the total number of targets +inside the current rec, and TARGETS is a vector of atoms +describing the selection targets in the current rec." + (let* ((byte-order (aref data 0)) + (n-targets (x-dnd-get-motif-value + data i 2 byte-order)) + (targets (make-vector n-targets nil)) + (consumed 0)) + (while (< consumed n-targets) + (aset targets consumed (x-dnd-get-motif-value + data (+ i 2 (* consumed 4)) + 4 byte-order)) + (setq consumed (1+ consumed))) + (list (+ 2 (* consumed 4)) n-targets targets))) + +(defun x-dnd-xm-read-targets-table (frame) + "Read the Motif targets table on FRAME. +Return a vector of vectors of numbers (the drop targets)." + (let* ((drag-window (x-window-property "_MOTIF_DRAG_WINDOW" + frame "WINDOW" 0 nil t)) + (targets-data (x-window-property "_MOTIF_DRAG_TARGETS" + frame "_MOTIF_DRAG_TARGETS" + drag-window nil t)) + (header (x-dnd-xm-unpack-targets-table-header targets-data)) + (vec (make-vector (nth 2 header) nil)) + (current-byte 8) + (i 0)) + (unless (stringp targets-data) + (error "Expected format 8, got %s" (type-of targets-data))) + (prog1 vec + (while (< i (nth 2 header)) + (let ((rec (x-dnd-xm-read-single-rec targets-data + current-byte))) + (aset vec i (nth 2 rec)) + (setq current-byte (+ current-byte (car rec))) + (setq i (1+ i)))) + (unless (eq current-byte (nth 3 header)) + (error "Targets table header says size is %d, but it is actually %d" + (nth 3 header) current-byte))))) + +(defun x-dnd-xm-read-targets (frame window selection) + "Read targets of SELECTION on FRAME from the targets table. +WINDOW should be the drag-and-drop operation's initiator. +Return a vector of atoms containing the selection targets." + (let* ((targets-table (x-dnd-xm-read-targets-table frame)) + (initiator-info (x-window-property selection frame + "_MOTIF_DRAG_INITIATOR_INFO" + window nil nil)) + (byte-order (aref initiator-info 0)) + (idx (x-dnd-get-motif-value initiator-info + 2 2 byte-order)) + (vector (aref targets-table idx)) + (i 0)) + (prog1 vector + (while (< i (length vector)) + (aset vector i + (intern (x-get-atom-name (aref vector i)))) + (setq i (1+ i)))))) (defvar x-dnd-motif-message-types '((0 . XmTOP_LEVEL_ENTER) @@ -625,14 +702,12 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." data 8 4 source-byteorder)) (selection-atom (x-dnd-get-motif-value data 12 4 source-byteorder)) - (atom-name (x-get-atom-name selection-atom)) - (types (when atom-name - (x-get-selection-internal (intern atom-name) - 'TARGETS)))) + (atom-name (x-get-atom-name selection-atom)) + (types (x-dnd-xm-read-targets frame dnd-source + atom-name))) (x-dnd-forget-drop frame) (when types (x-dnd-save-state window nil nil - types - dnd-source)))) + types dnd-source)))) ;; Can not forget drop here, LEAVE comes before DROP_START and ;; we need the state in DROP_START. commit feb94707a9b1a1e35889ce743783d370fba2e739 Author: Po Lu Date: Fri Jun 10 09:28:45 2022 +0800 Fix crashes in x_tooltip_window_to_frame on GTK * src/xterm.c (x_tooltip_window_to_frame): Ignore all non-X frames instead of trying to get their tooltip window. diff --git a/src/xterm.c b/src/xterm.c index 77dea3ad4d..ed8f068136 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10453,6 +10453,9 @@ x_tooltip_window_to_frame (struct x_display_info *dpyinfo, return f; #ifdef USE_GTK + if (!FRAME_X_P (f)) + continue; + if (FRAME_X_OUTPUT (f)->ttip_window) widget = GTK_WIDGET (FRAME_X_OUTPUT (f)->ttip_window); else commit 6d2bad20bb7778a3f467d66f38ec2d3fb8de5a91 Author: Po Lu Date: Fri Jun 10 01:15:25 2022 +0000 * src/haikuselect.c (haiku_note_drag_motion): Only handle visible tip_f. diff --git a/src/haikuselect.c b/src/haikuselect.c index b69fcfff13..b319aace96 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -995,7 +995,7 @@ haiku_note_drag_motion (void) { tip_f = XFRAME (tip_frame); - if (FRAME_LIVE_P (tip_f)) + if (FRAME_LIVE_P (tip_f) && FRAME_VISIBLE_P (tip_f)) { BView_get_mouse (FRAME_HAIKU_VIEW (haiku_dnd_frame), &x, &y); commit 0e2f94ded0193f8d4eece158e865e21e35aa7aff Author: Po Lu Date: Fri Jun 10 08:58:51 2022 +0800 Fix DND tooltip handling with tooltip-reuse-hidden-frame * src/xterm.c (x_dnd_update_tooltip_position): Don't move window if tip_f is not visible. diff --git a/src/xterm.c b/src/xterm.c index f0cd5e9c8b..77dea3ad4d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15239,6 +15239,7 @@ x_dnd_update_tooltip_position (int root_x, int root_y) tip_f = XFRAME (tip_frame); if (!FRAME_LIVE_P (tip_f) + || !FRAME_VISIBLE_P (tip_f) || (FRAME_X_DISPLAY (tip_f) != FRAME_X_DISPLAY (x_dnd_frame))) return; commit 8ef3862fa0d1aa987d67ec42acf3611a42e2a0fb Author: Eli Zaretskii Date: Thu Jun 9 20:33:43 2022 +0300 Update the 'etags' test suite * ETAGS.good_1: * ETAGS_good_2: * ETAGS_good_3: * ETAGS_good_4: * ETAGS_good_5: * ETAGS_good_6: Adapt to recent changes in test sources. * lib-src/etags.c (C_entries): Add commentary for resetting bracelev. (Bug#45246) diff --git a/lib-src/etags.c b/lib-src/etags.c index f76dda7936..9a60714eca 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -4166,6 +4166,9 @@ C_entries (int c_ext, /* extension of C */ if (definedef != dnone) break; bracelev -= 1; + /* If we see a closing brace in column zero, and we weren't told to + ignore indentation, we assume this the final brace of a function + or struct definition, and reset bracelev to zero. */ if (!ignoreindent && lp == newlb.buffer + 1) { if (bracelev != 0) diff --git a/test/manual/etags/ETAGS.good_1 b/test/manual/etags/ETAGS.good_1 index 1b4f80ceaa..c3d1477d44 100644 --- a/test/manual/etags/ETAGS.good_1 +++ b/test/manual/etags/ETAGS.good_1 @@ -915,277 +915,277 @@ record_auto_save 742,23849 force_auto_save_soon 751,24017 DEFUN ("recursive-edit", Frecursive_edit,759,24138 DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138 -recursive_edit_unwind 804,25748 -any_kboard_state 817,26014 -single_kboard_state 838,26666 -not_single_kboard_state 848,26804 -struct kboard_stack858,27066 -static struct kboard_stack *kboard_stack;kboard_stack864,27139 -push_kboard 867,27187 -pop_kboard 879,27376 -temporarily_switch_to_single_kboard 914,28264 -record_single_kboard_state 943,29438 -restore_kboard_configuration 952,29622 -cmd_error 970,30078 -cmd_error_internal 1024,31511 -DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031 -DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031 -command_loop 1094,33917 -command_loop_2 1134,35136 -top_level_2 1146,35340 -top_level_1 1152,35418 -DEFUN ("top-level", Ftop_level,1164,35788 -DEFUN ("top-level", Ftop_level,top-level1164,35788 -user_error 1183,36289 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820 -tracking_off 1216,37282 -DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817 -DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817 -bool ignore_mouse_drag_p;1256,38393 -some_mouse_moved 1259,38442 -Lisp_Object last_undo_boundary;1287,39033 -command_loop_1 1294,39274 -read_menu_command 1649,50890 -adjust_point_for_property 1678,51618 -safe_run_hooks_1 1831,57340 -safe_run_hooks_error 1841,57570 -safe_run_hook_funcall 1878,58577 -safe_run_hooks 1893,59059 -int poll_suppress_count;1908,59398 -static struct atimer *poll_timer;poll_timer1915,59488 -poll_for_input_1 1919,59590 -poll_for_input 1930,59790 -start_polling 1942,60054 -input_polling_used 1979,61092 -stop_polling 1994,61391 -set_poll_suppress_count 2009,61760 -bind_polling_period 2029,62142 -make_ctrl_char 2048,62493 -show_help_echo 2113,64456 -static Lisp_Object help_form_saved_window_configs;2156,65639 -read_char_help_form_unwind 2158,65702 -#define STOP_POLLING 2166,65960 -#define RESUME_POLLING 2170,66085 -read_event_from_main_queue 2175,66230 -read_decoded_event_from_main_queue 2249,68418 -#define MAX_ENCODED_BYTES 2254,68665 -echo_keystrokes_p 2342,71557 -read_char 2376,72849 -record_menu_key 3225,98950 -help_char_p 3258,99675 -record_char 3273,99954 -save_getcjmp 3412,104236 -restore_getcjmp 3418,104327 -readable_events 3430,104698 -int stop_character EXTERNALLY_VISIBLE;3497,106438 -event_to_kboard 3500,106494 -kbd_buffer_nr_stored 3522,107143 -kbd_buffer_store_event 3534,107484 -kbd_buffer_store_event_hold 3550,108026 -kbd_buffer_unget_event 3684,111618 -#define INPUT_EVENT_POS_MAX 3698,112019 -#define INPUT_EVENT_POS_MIN 3701,112148 -position_to_Time 3706,112288 -Time_to_position 3716,112515 -gen_help_event 3738,113172 -kbd_buffer_store_help_event 3756,113612 -discard_mouse_events 3773,113977 -kbd_buffer_events_waiting 3803,114712 -clear_event 3823,115069 -kbd_buffer_get_event 3836,115409 -process_special_events 4258,127882 -swallow_events 4322,129706 -timer_start_idle 4339,130099 -timer_stop_idle 4355,130577 -timer_resume_idle 4363,130721 -struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913 -Lisp_Object pending_funcalls;4377,131173 -decode_timer 4381,131294 -timer_check_2 4414,132247 -timer_check 4572,136818 -DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663 -DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663 -static Lisp_Object accent_key_syms;4625,138240 -static Lisp_Object func_key_syms;4626,138276 -static Lisp_Object mouse_syms;4627,138310 -static Lisp_Object wheel_syms;4628,138341 -static Lisp_Object drag_n_drop_syms;4629,138372 -static const int lispy_accent_codes[lispy_accent_codes4634,138517 -static const char *const lispy_accent_keys[lispy_accent_keys4741,139879 -#define FUNCTION_KEY_OFFSET 4766,140315 -const char *const lispy_function_keys[lispy_function_keys4768,140348 -static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902 -static const char *const lispy_kana_keys[lispy_kana_keys5026,150136 -#define FUNCTION_KEY_OFFSET 5061,151752 -static const char *const lispy_function_keys[lispy_function_keys5065,151895 -#define ISO_FUNCTION_KEY_OFFSET 5149,154430 -static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470 -static Lisp_Object Vlispy_mouse_stem;5172,155329 -static const char *const lispy_wheel_names[lispy_wheel_names5174,155368 -static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620 -static short const scroll_bar_parts[scroll_bar_parts5189,155886 -static Lisp_Object button_down_location;5210,156911 -static int last_mouse_button;5215,157066 -static int last_mouse_x;5216,157096 -static int last_mouse_y;5217,157121 -static Time button_down_time;5218,157146 -static int double_click_count;5222,157230 -make_lispy_position 5228,157391 -toolkit_menubar_in_use 5456,163954 -make_scroll_bar_position 5469,164322 -make_lispy_event 5485,164968 -make_lispy_movement 6104,183531 -make_lispy_switch_frame 6131,184262 -make_lispy_focus_in 6137,184369 -make_lispy_focus_out 6145,184495 -parse_modifiers_uncached 6163,184945 -#define SINGLE_LETTER_MOD(6185,185465 -#undef SINGLE_LETTER_MOD6212,185906 -#define MULTI_LETTER_MOD(6214,185932 -#undef MULTI_LETTER_MOD6231,186400 -apply_modifiers_uncached 6273,187574 -static const char *const modifier_names[modifier_names6319,189193 -#define NUM_MOD_NAMES 6325,189399 -static Lisp_Object modifier_symbols;6327,189449 -lispy_modifier_list 6331,189586 -#define KEY_TO_CHAR(6353,190252 -parse_modifiers 6356,190328 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517 -apply_modifiers 6422,192391 -reorder_modifiers 6491,194720 -modify_event_symbol 6536,196528 -DEFUN ("event-convert-list", Fevent_convert_list,6628,199244 -DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244 -parse_solitary_modifier 6695,201135 -#define SINGLE_LETTER_MOD(6701,201258 -#define MULTI_LETTER_MOD(6705,201343 -#undef SINGLE_LETTER_MOD6763,202641 -#undef MULTI_LETTER_MOD6764,202666 -lucid_event_type_list_p 6775,202889 -get_input_pending 6814,203960 -record_asynch_buffer_change 6834,204579 -gobble_input 6872,205702 -tty_read_avail_input 6967,208310 -handle_async_input 7149,214039 -process_pending_signals 7165,214359 -unblock_input_to 7177,214645 -unblock_input 7200,215277 -totally_unblock_input 7209,215445 -handle_input_available_signal 7217,215529 -deliver_input_available_signal 7226,215700 -struct user_signal_info7235,215865 -static struct user_signal_info *user_signals user_signals7250,216090 -add_user_signal 7253,216149 -handle_user_signal 7275,216598 -deliver_user_signal 7316,217558 -find_user_signal_name 7322,217659 -store_user_signal_events 7334,217841 -static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416 -static Lisp_Object menu_bar_items_vector;7368,218630 -static int menu_bar_items_index;7369,218672 -static const char *separator_names[separator_names7372,218707 -menu_separator_name_p 7393,219148 -menu_bar_items 7426,219852 -Lisp_Object item_properties;7568,224603 -menu_bar_item 7571,224645 -menu_item_eval_property_1 7647,227175 -eval_dyn 7658,227465 -menu_item_eval_property 7666,227675 -parse_menu_item 7686,228341 -static Lisp_Object tool_bar_items_vector;7965,236336 -static Lisp_Object tool_bar_item_properties;7970,236510 -static int ntool_bar_items;7974,236606 -tool_bar_items 7990,237083 -process_tool_bar_item 8075,239892 -#define PROP(8112,240969 -set_prop 8114,241038 -parse_tool_bar_item 8167,242453 -#undef PROP8379,248844 -init_tool_bar_items 8387,248969 -append_tool_bar_item 8401,249261 -read_char_x_menu_prompt 8443,250771 -read_char_minibuf_menu_prompt 8503,252445 -#define PUSH_C_STR(8527,253014 -follow_key 8726,258553 -active_maps 8733,258695 -typedef struct keyremap8742,259021 -} keyremap;8754,259464 -access_keymap_keyremap 8764,259808 -keyremap_step 8811,261450 -test_undefined 8867,262934 -read_key_sequence 8916,264861 -read_key_sequence_vs 9826,295821 -DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294 -DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982 -detect_input_pending 9950,300488 -detect_input_pending_ignore_squeezables 9959,300654 -detect_input_pending_run_timers 9967,300870 -clear_input_pending 9985,301362 -requeued_events_pending_p 9997,301732 -DEFUN ("input-pending-p", Finput_pending_p,10002,301813 -DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813 -DEFUN ("recent-keys", Frecent_keys,10024,302596 -DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596 -DEFUN ("this-command-keys", Fthis_command_keys,10055,303517 -DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510 -DEFUN ("recursion-depth", Frecursion_depth,10158,307069 -DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069 -DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406 -DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406 -DEFUN ("discard-input", Fdiscard_input,10203,308447 -DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447 -DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949 -DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949 -stuff_buffered_input 10285,311045 -set_waiting_for_input 10323,312016 -clear_waiting_for_input 10337,312390 -handle_interrupt_signal 10351,312754 -deliver_interrupt_signal 10378,313642 -static int volatile force_quit_count;10387,313932 -handle_interrupt 10401,314414 -quit_throw_to_read_char 10541,318711 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288 -DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516 -DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432 -DEFUN ("set-quit-char", Fset_quit_char,10694,322706 -DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706 -DEFUN ("set-input-mode", Fset_input_mode,10729,323570 -DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570 -DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459 -DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459 -DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837 -DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837 -DEFUN ("posn-at-point", Fposn_at_point,10824,327060 -DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060 -init_kboard 10861,328214 -allocate_kboard 10893,329284 -wipe_kboard 10909,329637 -delete_kboard 10917,329751 -init_keyboard 10942,330281 -struct event_head11021,332696 -static const struct event_head head_table[head_table11027,332747 -syms_of_keyboard 11045,333577 -keys_of_keyboard 11841,367115 -mark_kboards 11916,370434 +recursive_edit_unwind 804,25751 +any_kboard_state 817,26017 +single_kboard_state 838,26669 +not_single_kboard_state 848,26807 +struct kboard_stack858,27069 +static struct kboard_stack *kboard_stack;kboard_stack864,27142 +push_kboard 867,27190 +pop_kboard 879,27379 +temporarily_switch_to_single_kboard 914,28267 +record_single_kboard_state 943,29441 +restore_kboard_configuration 952,29625 +cmd_error 970,30081 +cmd_error_internal 1024,31514 +DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034 +DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034 +command_loop 1094,33920 +command_loop_2 1134,35139 +top_level_2 1146,35343 +top_level_1 1152,35421 +DEFUN ("top-level", Ftop_level,1164,35791 +DEFUN ("top-level", Ftop_level,top-level1164,35791 +user_error 1183,36292 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823 +tracking_off 1216,37285 +DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820 +DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820 +bool ignore_mouse_drag_p;1256,38396 +some_mouse_moved 1259,38445 +Lisp_Object last_undo_boundary;1287,39036 +command_loop_1 1294,39277 +read_menu_command 1649,50893 +adjust_point_for_property 1678,51621 +safe_run_hooks_1 1831,57343 +safe_run_hooks_error 1841,57573 +safe_run_hook_funcall 1878,58580 +safe_run_hooks 1893,59062 +int poll_suppress_count;1908,59401 +static struct atimer *poll_timer;poll_timer1915,59491 +poll_for_input_1 1919,59593 +poll_for_input 1930,59793 +start_polling 1942,60057 +input_polling_used 1979,61095 +stop_polling 1994,61394 +set_poll_suppress_count 2009,61763 +bind_polling_period 2029,62145 +make_ctrl_char 2048,62496 +show_help_echo 2113,64459 +static Lisp_Object help_form_saved_window_configs;2156,65642 +read_char_help_form_unwind 2158,65705 +#define STOP_POLLING 2166,65963 +#define RESUME_POLLING 2170,66088 +read_event_from_main_queue 2175,66233 +read_decoded_event_from_main_queue 2249,68421 +#define MAX_ENCODED_BYTES 2254,68668 +echo_keystrokes_p 2342,71560 +read_char 2376,72852 +record_menu_key 3225,98953 +help_char_p 3258,99678 +record_char 3273,99957 +save_getcjmp 3412,104239 +restore_getcjmp 3418,104330 +readable_events 3430,104701 +int stop_character EXTERNALLY_VISIBLE;3497,106441 +event_to_kboard 3500,106497 +kbd_buffer_nr_stored 3522,107146 +kbd_buffer_store_event 3534,107487 +kbd_buffer_store_event_hold 3550,108029 +kbd_buffer_unget_event 3684,111621 +#define INPUT_EVENT_POS_MAX 3698,112022 +#define INPUT_EVENT_POS_MIN 3701,112151 +position_to_Time 3706,112291 +Time_to_position 3716,112518 +gen_help_event 3738,113175 +kbd_buffer_store_help_event 3756,113615 +discard_mouse_events 3773,113980 +kbd_buffer_events_waiting 3803,114715 +clear_event 3823,115072 +kbd_buffer_get_event 3836,115412 +process_special_events 4258,127885 +swallow_events 4322,129709 +timer_start_idle 4339,130102 +timer_stop_idle 4355,130580 +timer_resume_idle 4363,130724 +struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916 +Lisp_Object pending_funcalls;4377,131176 +decode_timer 4381,131297 +timer_check_2 4414,132250 +timer_check 4572,136821 +DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666 +DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666 +static Lisp_Object accent_key_syms;4625,138243 +static Lisp_Object func_key_syms;4626,138279 +static Lisp_Object mouse_syms;4627,138313 +static Lisp_Object wheel_syms;4628,138344 +static Lisp_Object drag_n_drop_syms;4629,138375 +static const int lispy_accent_codes[lispy_accent_codes4634,138520 +static const char *const lispy_accent_keys[lispy_accent_keys4741,139882 +#define FUNCTION_KEY_OFFSET 4766,140318 +const char *const lispy_function_keys[lispy_function_keys4768,140351 +static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905 +static const char *const lispy_kana_keys[lispy_kana_keys5026,150139 +#define FUNCTION_KEY_OFFSET 5061,151755 +static const char *const lispy_function_keys[lispy_function_keys5065,151898 +#define ISO_FUNCTION_KEY_OFFSET 5149,154433 +static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473 +static Lisp_Object Vlispy_mouse_stem;5172,155332 +static const char *const lispy_wheel_names[lispy_wheel_names5174,155371 +static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623 +static short const scroll_bar_parts[scroll_bar_parts5189,155889 +static Lisp_Object button_down_location;5210,156914 +static int last_mouse_button;5215,157069 +static int last_mouse_x;5216,157099 +static int last_mouse_y;5217,157124 +static Time button_down_time;5218,157149 +static int double_click_count;5222,157233 +make_lispy_position 5228,157394 +toolkit_menubar_in_use 5456,163957 +make_scroll_bar_position 5469,164325 +make_lispy_event 5485,164971 +make_lispy_movement 6104,183534 +make_lispy_switch_frame 6131,184265 +make_lispy_focus_in 6137,184372 +make_lispy_focus_out 6145,184498 +parse_modifiers_uncached 6163,184948 +#define SINGLE_LETTER_MOD(6185,185468 +#undef SINGLE_LETTER_MOD6212,185909 +#define MULTI_LETTER_MOD(6214,185935 +#undef MULTI_LETTER_MOD6231,186403 +apply_modifiers_uncached 6273,187577 +static const char *const modifier_names[modifier_names6319,189196 +#define NUM_MOD_NAMES 6325,189402 +static Lisp_Object modifier_symbols;6327,189452 +lispy_modifier_list 6331,189589 +#define KEY_TO_CHAR(6353,190255 +parse_modifiers 6356,190331 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520 +apply_modifiers 6422,192394 +reorder_modifiers 6491,194723 +modify_event_symbol 6536,196531 +DEFUN ("event-convert-list", Fevent_convert_list,6628,199247 +DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247 +parse_solitary_modifier 6695,201138 +#define SINGLE_LETTER_MOD(6701,201261 +#define MULTI_LETTER_MOD(6705,201346 +#undef SINGLE_LETTER_MOD6763,202644 +#undef MULTI_LETTER_MOD6764,202669 +lucid_event_type_list_p 6775,202892 +get_input_pending 6814,203963 +record_asynch_buffer_change 6834,204582 +gobble_input 6872,205705 +tty_read_avail_input 6967,208313 +handle_async_input 7149,214042 +process_pending_signals 7165,214362 +unblock_input_to 7177,214648 +unblock_input 7200,215280 +totally_unblock_input 7209,215448 +handle_input_available_signal 7217,215532 +deliver_input_available_signal 7226,215703 +struct user_signal_info7235,215868 +static struct user_signal_info *user_signals user_signals7250,216093 +add_user_signal 7253,216152 +handle_user_signal 7275,216601 +deliver_user_signal 7316,217561 +find_user_signal_name 7322,217662 +store_user_signal_events 7334,217844 +static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419 +static Lisp_Object menu_bar_items_vector;7368,218633 +static int menu_bar_items_index;7369,218675 +static const char *separator_names[separator_names7372,218710 +menu_separator_name_p 7393,219151 +menu_bar_items 7426,219855 +Lisp_Object item_properties;7568,224606 +menu_bar_item 7571,224648 +menu_item_eval_property_1 7647,227178 +eval_dyn 7658,227468 +menu_item_eval_property 7666,227678 +parse_menu_item 7686,228344 +static Lisp_Object tool_bar_items_vector;7965,236339 +static Lisp_Object tool_bar_item_properties;7970,236513 +static int ntool_bar_items;7974,236609 +tool_bar_items 7990,237086 +process_tool_bar_item 8075,239895 +#define PROP(8112,240972 +set_prop 8114,241041 +parse_tool_bar_item 8167,242456 +#undef PROP8379,248847 +init_tool_bar_items 8387,248972 +append_tool_bar_item 8401,249264 +read_char_x_menu_prompt 8443,250774 +read_char_minibuf_menu_prompt 8503,252448 +#define PUSH_C_STR(8527,253017 +follow_key 8726,258556 +active_maps 8733,258698 +typedef struct keyremap8742,259024 +} keyremap;8754,259467 +access_keymap_keyremap 8764,259811 +keyremap_step 8811,261453 +test_undefined 8867,262937 +read_key_sequence 8916,264864 +read_key_sequence_vs 9826,295824 +DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297 +DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985 +detect_input_pending 9950,300491 +detect_input_pending_ignore_squeezables 9959,300657 +detect_input_pending_run_timers 9967,300873 +clear_input_pending 9985,301365 +requeued_events_pending_p 9997,301735 +DEFUN ("input-pending-p", Finput_pending_p,10002,301816 +DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816 +DEFUN ("recent-keys", Frecent_keys,10024,302599 +DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599 +DEFUN ("this-command-keys", Fthis_command_keys,10055,303520 +DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513 +DEFUN ("recursion-depth", Frecursion_depth,10158,307072 +DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072 +DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409 +DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409 +DEFUN ("discard-input", Fdiscard_input,10203,308450 +DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450 +DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952 +DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952 +stuff_buffered_input 10285,311048 +set_waiting_for_input 10323,312019 +clear_waiting_for_input 10337,312393 +handle_interrupt_signal 10351,312757 +deliver_interrupt_signal 10378,313645 +static int volatile force_quit_count;10387,313935 +handle_interrupt 10401,314417 +quit_throw_to_read_char 10541,318714 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291 +DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519 +DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435 +DEFUN ("set-quit-char", Fset_quit_char,10694,322709 +DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709 +DEFUN ("set-input-mode", Fset_input_mode,10729,323573 +DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573 +DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462 +DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462 +DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840 +DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840 +DEFUN ("posn-at-point", Fposn_at_point,10824,327063 +DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063 +init_kboard 10861,328217 +allocate_kboard 10893,329287 +wipe_kboard 10909,329640 +delete_kboard 10917,329754 +init_keyboard 10942,330284 +struct event_head11021,332699 +static const struct event_head head_table[head_table11027,332750 +syms_of_keyboard 11045,333580 +keys_of_keyboard 11841,367118 +mark_kboards 11916,370437 c-src/emacs/src/lisp.h,20276 #define EMACS_LISP_H22,801 @@ -2166,109 +2166,109 @@ el-src/emacs/lisp/progmodes/etags.el,5069 (defcustom tags-tag-face 148,5700 (defcustom tags-apropos-verbose 154,5835 (defcustom tags-apropos-additional-actions 160,5999 -(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918 -(defvar default-tags-table-function 189,7098 -(defvar tags-location-ring 194,7324 -(defvar tags-table-files 201,7600 -(defvar tags-completion-table 206,7767 -(defvar tags-included-tables 209,7859 -(defvar next-file-list 212,7954 -(defvar tags-table-format-functions 217,8060 -(defvar file-of-tag-function 224,8441 -(defvar tags-table-files-function 228,8635 -(defvar tags-completion-table-function 230,8746 -(defvar snarf-tag-function 232,8841 -(defvar goto-tag-location-function 236,9050 -(defvar find-tag-regexp-search-function 239,9223 -(defvar find-tag-regexp-tag-order 241,9344 -(defvar find-tag-regexp-next-line-after-failure-p 243,9453 -(defvar find-tag-search-function 245,9573 -(defvar find-tag-tag-order 247,9680 -(defvar find-tag-next-line-after-failure-p 249,9775 -(defvar list-tags-function 251,9881 -(defvar tags-apropos-function 253,9969 -(defvar tags-included-tables-function 255,10063 -(defvar verify-tags-table-function 257,10182 -(defun initialize-new-tags-table 260,10293 -(defun tags-table-mode 276,10981 -(defun visit-tags-table 285,11246 -(defun tags-table-check-computed-list 321,12784 -(defun tags-table-extend-computed-list 360,14655 -(defun tags-expand-table-name 400,16368 -(defun tags-table-list-member 409,16711 -(defun tags-verify-table 421,17183 -(defun tags-table-including 470,19303 -(defun tags-next-table 522,21347 -(defun visit-tags-table-buffer 543,22204 -(defun tags-reset-tags-tables 712,28514 -(defun file-of-tag 731,29171 -(defun tags-table-files 740,29521 -(defun tags-included-tables 749,29871 -(defun tags-completion-table 755,30117 -(defun tags-lazy-completion-table 783,31311 -(defun tags-completion-at-point-function 799,31946 -(defun find-tag-tag 818,32696 -(defvar last-tag 837,33369 -(defun find-tag-interactive 840,33428 -(defvar find-tag-history 852,33843 -(defun find-tag-noselect 860,34013 -(defun find-tag 932,37127 -(defun find-tag-other-window 959,38343 -(defun find-tag-other-frame 1000,40271 -(defun find-tag-regexp 1025,41445 -(defalias 'pop-tag-mark pop-tag-mark1049,42607 -(defvar tag-lines-already-matched 1052,42658 -(defun find-tag-in-order 1055,42765 -(defun tag-find-file-of-tag-noselect 1167,47111 -(defun tag-find-file-of-tag 1200,48957 -(defun etags-recognize-tags-table 1208,49183 -(defun etags-verify-tags-table 1241,50814 -(defun etags-file-of-tag 1246,51012 -(defun etags-tags-completion-table 1256,51347 -(defun etags-snarf-tag 1286,52553 -(defun etags-goto-tag-location 1324,54122 -(defun etags-list-tags 1388,56565 -(defmacro tags-with-face 1423,57840 -(defun etags-tags-apropos-additional 1431,58173 -(defun etags-tags-apropos 1465,59410 -(defun etags-tags-table-files 1527,61619 -(defun etags-tags-included-tables 1542,62055 -(defun tags-recognize-empty-tags-table 1559,62595 -(defun tag-exact-file-name-match-p 1587,63741 -(defun tag-file-name-match-p 1596,64134 -(defun tag-exact-match-p 1609,64690 -(defun tag-implicit-name-match-p 1620,65258 -(defun tag-symbol-match-p 1633,65858 -(defun tag-word-match-p 1643,66294 -(defun tag-partial-file-name-match-p 1652,66692 -(defun tag-any-match-p 1662,67136 -(defun tag-re-match-p 1667,67320 -(defcustom tags-loop-revert-buffers 1675,67569 -(defun next-file 1685,67978 -(defvar tags-loop-operate 1760,70892 -(defvar tags-loop-scan1763,70986 -(defun tags-loop-eval 1771,71315 -(defun tags-loop-continue 1782,71644 -(defun tags-search 1850,73950 -(defun tags-query-replace 1871,74776 -(defun tags-complete-tags-table-file 1896,76000 -(defun list-tags 1906,76379 -(defun tags-apropos 1934,77332 -(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158 -(defun select-tags-table 1964,78397 -(defvar select-tags-table-mode-map 2019,80524 -(define-derived-mode select-tags-table-mode 2030,80907 -(defun select-tags-table-select 2034,81091 -(defun select-tags-table-quit 2043,81457 -(defun complete-tag 2049,81612 -(defconst etags--xref-limit 2074,82553 -(defvar etags-xref-find-definitions-tag-order 2076,82588 -(defun etags-xref-find 2082,82878 -(defun etags--xref-find-definitions 2096,83407 -(defclass xref-etags-location 2129,85121 -(defun xref-make-etags-location 2135,85344 -(cl-defmethod xref-location-marker 2139,85499 -(cl-defmethod xref-location-line 2146,85743 +(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921 +(defvar default-tags-table-function 189,7101 +(defvar tags-location-ring 194,7327 +(defvar tags-table-files 201,7603 +(defvar tags-completion-table 206,7770 +(defvar tags-included-tables 209,7862 +(defvar next-file-list 212,7957 +(defvar tags-table-format-functions 217,8063 +(defvar file-of-tag-function 224,8444 +(defvar tags-table-files-function 228,8638 +(defvar tags-completion-table-function 230,8749 +(defvar snarf-tag-function 232,8844 +(defvar goto-tag-location-function 236,9053 +(defvar find-tag-regexp-search-function 239,9226 +(defvar find-tag-regexp-tag-order 241,9347 +(defvar find-tag-regexp-next-line-after-failure-p 243,9456 +(defvar find-tag-search-function 245,9576 +(defvar find-tag-tag-order 247,9683 +(defvar find-tag-next-line-after-failure-p 249,9778 +(defvar list-tags-function 251,9884 +(defvar tags-apropos-function 253,9972 +(defvar tags-included-tables-function 255,10066 +(defvar verify-tags-table-function 257,10185 +(defun initialize-new-tags-table 260,10296 +(defun tags-table-mode 276,10984 +(defun visit-tags-table 285,11249 +(defun tags-table-check-computed-list 321,12787 +(defun tags-table-extend-computed-list 360,14658 +(defun tags-expand-table-name 400,16371 +(defun tags-table-list-member 409,16714 +(defun tags-verify-table 421,17186 +(defun tags-table-including 470,19306 +(defun tags-next-table 522,21350 +(defun visit-tags-table-buffer 543,22207 +(defun tags-reset-tags-tables 712,28517 +(defun file-of-tag 731,29174 +(defun tags-table-files 740,29524 +(defun tags-included-tables 749,29874 +(defun tags-completion-table 755,30120 +(defun tags-lazy-completion-table 783,31314 +(defun tags-completion-at-point-function 799,31949 +(defun find-tag-tag 818,32699 +(defvar last-tag 837,33372 +(defun find-tag-interactive 840,33431 +(defvar find-tag-history 852,33846 +(defun find-tag-noselect 860,34016 +(defun find-tag 932,37130 +(defun find-tag-other-window 959,38346 +(defun find-tag-other-frame 1000,40274 +(defun find-tag-regexp 1025,41448 +(defalias 'pop-tag-mark pop-tag-mark1049,42610 +(defvar tag-lines-already-matched 1052,42661 +(defun find-tag-in-order 1055,42768 +(defun tag-find-file-of-tag-noselect 1167,47114 +(defun tag-find-file-of-tag 1200,48960 +(defun etags-recognize-tags-table 1208,49186 +(defun etags-verify-tags-table 1241,50817 +(defun etags-file-of-tag 1246,51015 +(defun etags-tags-completion-table 1256,51350 +(defun etags-snarf-tag 1286,52556 +(defun etags-goto-tag-location 1324,54125 +(defun etags-list-tags 1388,56568 +(defmacro tags-with-face 1423,57843 +(defun etags-tags-apropos-additional 1431,58176 +(defun etags-tags-apropos 1465,59413 +(defun etags-tags-table-files 1527,61622 +(defun etags-tags-included-tables 1542,62058 +(defun tags-recognize-empty-tags-table 1559,62598 +(defun tag-exact-file-name-match-p 1587,63744 +(defun tag-file-name-match-p 1596,64137 +(defun tag-exact-match-p 1609,64693 +(defun tag-implicit-name-match-p 1620,65261 +(defun tag-symbol-match-p 1633,65861 +(defun tag-word-match-p 1643,66297 +(defun tag-partial-file-name-match-p 1652,66695 +(defun tag-any-match-p 1662,67139 +(defun tag-re-match-p 1667,67323 +(defcustom tags-loop-revert-buffers 1675,67572 +(defun next-file 1685,67981 +(defvar tags-loop-operate 1760,70895 +(defvar tags-loop-scan1763,70989 +(defun tags-loop-eval 1771,71318 +(defun tags-loop-continue 1782,71647 +(defun tags-search 1850,73953 +(defun tags-query-replace 1871,74779 +(defun tags-complete-tags-table-file 1896,76003 +(defun list-tags 1906,76382 +(defun tags-apropos 1934,77335 +(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161 +(defun select-tags-table 1964,78400 +(defvar select-tags-table-mode-map 2019,80527 +(define-derived-mode select-tags-table-mode 2030,80910 +(defun select-tags-table-select 2034,81094 +(defun select-tags-table-quit 2043,81460 +(defun complete-tag 2049,81615 +(defconst etags--xref-limit 2074,82556 +(defvar etags-xref-find-definitions-tag-order 2076,82591 +(defun etags-xref-find 2082,82881 +(defun etags--xref-find-definitions 2096,83410 +(defclass xref-etags-location 2129,85124 +(defun xref-make-etags-location 2135,85347 +(cl-defmethod xref-location-marker 2139,85502 +(cl-defmethod xref-location-line 2146,85746 erl-src/gs_dialog.erl,98 -define(VERSION2,32 diff --git a/test/manual/etags/ETAGS.good_2 b/test/manual/etags/ETAGS.good_2 index 124aa7fc1c..3c611dc8ef 100644 --- a/test/manual/etags/ETAGS.good_2 +++ b/test/manual/etags/ETAGS.good_2 @@ -1098,288 +1098,288 @@ record_auto_save 742,23849 force_auto_save_soon 751,24017 DEFUN ("recursive-edit", Frecursive_edit,759,24138 DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138 -recursive_edit_unwind 804,25748 -any_kboard_state 817,26014 -single_kboard_state 838,26666 -not_single_kboard_state 848,26804 -struct kboard_stack858,27066 -static struct kboard_stack *kboard_stack;kboard_stack864,27139 -push_kboard 867,27187 -pop_kboard 879,27376 -temporarily_switch_to_single_kboard 914,28264 -record_single_kboard_state 943,29438 -restore_kboard_configuration 952,29622 -cmd_error 970,30078 -cmd_error_internal 1024,31511 -DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031 -DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031 -static Lisp_Object command_loop_2 1086,33638 -static Lisp_Object top_level_1 1087,33687 -command_loop 1094,33917 -command_loop_2 1134,35136 -top_level_2 1146,35340 -top_level_1 1152,35418 -DEFUN ("top-level", Ftop_level,1164,35788 -DEFUN ("top-level", Ftop_level,top-level1164,35788 -user_error 1183,36289 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820 -tracking_off 1216,37282 -DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817 -DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817 -bool ignore_mouse_drag_p;1256,38393 -some_mouse_moved 1259,38442 -static int read_key_sequence 1282,38800 -static void adjust_point_for_property 1284,38918 -Lisp_Object last_undo_boundary;1287,39033 -command_loop_1 1294,39274 -read_menu_command 1649,50890 -adjust_point_for_property 1678,51618 -safe_run_hooks_1 1831,57340 -safe_run_hooks_error 1841,57570 -safe_run_hook_funcall 1878,58577 -safe_run_hooks 1893,59059 -int poll_suppress_count;1908,59398 -static struct atimer *poll_timer;poll_timer1915,59488 -poll_for_input_1 1919,59590 -poll_for_input 1930,59790 -start_polling 1942,60054 -input_polling_used 1979,61092 -stop_polling 1994,61391 -set_poll_suppress_count 2009,61760 -bind_polling_period 2029,62142 -make_ctrl_char 2048,62493 -show_help_echo 2113,64456 -static Lisp_Object kbd_buffer_get_event 2152,65485 -static void record_char 2154,65597 -static Lisp_Object help_form_saved_window_configs;2156,65639 -read_char_help_form_unwind 2158,65702 -#define STOP_POLLING 2166,65960 -#define RESUME_POLLING 2170,66085 -read_event_from_main_queue 2175,66230 -read_decoded_event_from_main_queue 2249,68418 -#define MAX_ENCODED_BYTES 2254,68665 -echo_keystrokes_p 2342,71557 -read_char 2376,72849 -record_menu_key 3225,98950 -help_char_p 3258,99675 -record_char 3273,99954 -save_getcjmp 3412,104236 -restore_getcjmp 3418,104327 -readable_events 3430,104698 -int stop_character EXTERNALLY_VISIBLE;3497,106438 -event_to_kboard 3500,106494 -kbd_buffer_nr_stored 3522,107143 -kbd_buffer_store_event 3534,107484 -kbd_buffer_store_event_hold 3550,108026 -kbd_buffer_unget_event 3684,111618 -#define INPUT_EVENT_POS_MAX 3698,112019 -#define INPUT_EVENT_POS_MIN 3701,112148 -position_to_Time 3706,112288 -Time_to_position 3716,112515 -gen_help_event 3738,113172 -kbd_buffer_store_help_event 3756,113612 -discard_mouse_events 3773,113977 -kbd_buffer_events_waiting 3803,114712 -clear_event 3823,115069 -kbd_buffer_get_event 3836,115409 -process_special_events 4258,127882 -swallow_events 4322,129706 -timer_start_idle 4339,130099 -timer_stop_idle 4355,130577 -timer_resume_idle 4363,130721 -struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913 -Lisp_Object pending_funcalls;4377,131173 -decode_timer 4381,131294 -timer_check_2 4414,132247 -timer_check 4572,136818 -DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663 -DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663 -static Lisp_Object accent_key_syms;4625,138240 -static Lisp_Object func_key_syms;4626,138276 -static Lisp_Object mouse_syms;4627,138310 -static Lisp_Object wheel_syms;4628,138341 -static Lisp_Object drag_n_drop_syms;4629,138372 -static const int lispy_accent_codes[lispy_accent_codes4634,138517 -static const char *const lispy_accent_keys[lispy_accent_keys4741,139879 -#define FUNCTION_KEY_OFFSET 4766,140315 -const char *const lispy_function_keys[lispy_function_keys4768,140348 -static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902 -static const char *const lispy_kana_keys[lispy_kana_keys5026,150136 -#define FUNCTION_KEY_OFFSET 5061,151752 -static const char *const lispy_function_keys[lispy_function_keys5065,151895 -#define ISO_FUNCTION_KEY_OFFSET 5149,154430 -static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470 -static Lisp_Object Vlispy_mouse_stem;5172,155329 -static const char *const lispy_wheel_names[lispy_wheel_names5174,155368 -static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620 -static short const scroll_bar_parts[scroll_bar_parts5189,155886 -static Lisp_Object button_down_location;5210,156911 -static int last_mouse_button;5215,157066 -static int last_mouse_x;5216,157096 -static int last_mouse_y;5217,157121 -static Time button_down_time;5218,157146 -static int double_click_count;5222,157230 -make_lispy_position 5228,157391 -toolkit_menubar_in_use 5456,163954 -make_scroll_bar_position 5469,164322 -make_lispy_event 5485,164968 -make_lispy_movement 6104,183531 -make_lispy_switch_frame 6131,184262 -make_lispy_focus_in 6137,184369 -make_lispy_focus_out 6145,184495 -parse_modifiers_uncached 6163,184945 -#define SINGLE_LETTER_MOD(6185,185465 -#undef SINGLE_LETTER_MOD6212,185906 -#define MULTI_LETTER_MOD(6214,185932 -#undef MULTI_LETTER_MOD6231,186400 -apply_modifiers_uncached 6273,187574 -static const char *const modifier_names[modifier_names6319,189193 -#define NUM_MOD_NAMES 6325,189399 -static Lisp_Object modifier_symbols;6327,189449 -lispy_modifier_list 6331,189586 -#define KEY_TO_CHAR(6353,190252 -parse_modifiers 6356,190328 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517 -apply_modifiers 6422,192391 -reorder_modifiers 6491,194720 -modify_event_symbol 6536,196528 -DEFUN ("event-convert-list", Fevent_convert_list,6628,199244 -DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244 -parse_solitary_modifier 6695,201135 -#define SINGLE_LETTER_MOD(6701,201258 -#define MULTI_LETTER_MOD(6705,201343 -#undef SINGLE_LETTER_MOD6763,202641 -#undef MULTI_LETTER_MOD6764,202666 -lucid_event_type_list_p 6775,202889 -get_input_pending 6814,203960 -record_asynch_buffer_change 6834,204579 -gobble_input 6872,205702 -tty_read_avail_input 6967,208310 -handle_async_input 7149,214039 -process_pending_signals 7165,214359 -unblock_input_to 7177,214645 -unblock_input 7200,215277 -totally_unblock_input 7209,215445 -handle_input_available_signal 7217,215529 -deliver_input_available_signal 7226,215700 -struct user_signal_info7235,215865 -static struct user_signal_info *user_signals user_signals7250,216090 -add_user_signal 7253,216149 -handle_user_signal 7275,216598 -deliver_user_signal 7316,217558 -find_user_signal_name 7322,217659 -store_user_signal_events 7334,217841 -static void menu_bar_item 7362,218341 -static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416 -static Lisp_Object menu_bar_items_vector;7368,218630 -static int menu_bar_items_index;7369,218672 -static const char *separator_names[separator_names7372,218707 -menu_separator_name_p 7393,219148 -menu_bar_items 7426,219852 -Lisp_Object item_properties;7568,224603 -menu_bar_item 7571,224645 -menu_item_eval_property_1 7647,227175 -eval_dyn 7658,227465 -menu_item_eval_property 7666,227675 -parse_menu_item 7686,228341 -static Lisp_Object tool_bar_items_vector;7965,236336 -static Lisp_Object tool_bar_item_properties;7970,236510 -static int ntool_bar_items;7974,236606 -static void init_tool_bar_items 7978,236664 -static void process_tool_bar_item 7979,236711 -static bool parse_tool_bar_item 7981,236801 -static void append_tool_bar_item 7982,236861 -tool_bar_items 7990,237083 -process_tool_bar_item 8075,239892 -#define PROP(8112,240969 -set_prop 8114,241038 -parse_tool_bar_item 8167,242453 -#undef PROP8379,248844 -init_tool_bar_items 8387,248969 -append_tool_bar_item 8401,249261 -read_char_x_menu_prompt 8443,250771 -read_char_minibuf_menu_prompt 8503,252445 -#define PUSH_C_STR(8527,253014 -follow_key 8726,258553 -active_maps 8733,258695 -typedef struct keyremap8742,259021 -} keyremap;8754,259464 -access_keymap_keyremap 8764,259808 -keyremap_step 8811,261450 -test_undefined 8867,262934 -read_key_sequence 8916,264861 -read_key_sequence_vs 9826,295821 -DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294 -DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982 -detect_input_pending 9950,300488 -detect_input_pending_ignore_squeezables 9959,300654 -detect_input_pending_run_timers 9967,300870 -clear_input_pending 9985,301362 -requeued_events_pending_p 9997,301732 -DEFUN ("input-pending-p", Finput_pending_p,10002,301813 -DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813 -DEFUN ("recent-keys", Frecent_keys,10024,302596 -DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596 -DEFUN ("this-command-keys", Fthis_command_keys,10055,303517 -DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510 -DEFUN ("recursion-depth", Frecursion_depth,10158,307069 -DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069 -DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406 -DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406 -DEFUN ("discard-input", Fdiscard_input,10203,308447 -DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447 -DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949 -DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949 -stuff_buffered_input 10285,311045 -set_waiting_for_input 10323,312016 -clear_waiting_for_input 10337,312390 -handle_interrupt_signal 10351,312754 -deliver_interrupt_signal 10378,313642 -static int volatile force_quit_count;10387,313932 -handle_interrupt 10401,314414 -quit_throw_to_read_char 10541,318711 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288 -DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516 -DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432 -DEFUN ("set-quit-char", Fset_quit_char,10694,322706 -DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706 -DEFUN ("set-input-mode", Fset_input_mode,10729,323570 -DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570 -DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459 -DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459 -DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837 -DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837 -DEFUN ("posn-at-point", Fposn_at_point,10824,327060 -DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060 -init_kboard 10861,328214 -allocate_kboard 10893,329284 -wipe_kboard 10909,329637 -delete_kboard 10917,329751 -init_keyboard 10942,330281 -struct event_head11021,332696 -static const struct event_head head_table[head_table11027,332747 -syms_of_keyboard 11045,333577 -keys_of_keyboard 11841,367115 -mark_kboards 11916,370434 +recursive_edit_unwind 804,25751 +any_kboard_state 817,26017 +single_kboard_state 838,26669 +not_single_kboard_state 848,26807 +struct kboard_stack858,27069 +static struct kboard_stack *kboard_stack;kboard_stack864,27142 +push_kboard 867,27190 +pop_kboard 879,27379 +temporarily_switch_to_single_kboard 914,28267 +record_single_kboard_state 943,29441 +restore_kboard_configuration 952,29625 +cmd_error 970,30081 +cmd_error_internal 1024,31514 +DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034 +DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034 +static Lisp_Object command_loop_2 1086,33641 +static Lisp_Object top_level_1 1087,33690 +command_loop 1094,33920 +command_loop_2 1134,35139 +top_level_2 1146,35343 +top_level_1 1152,35421 +DEFUN ("top-level", Ftop_level,1164,35791 +DEFUN ("top-level", Ftop_level,top-level1164,35791 +user_error 1183,36292 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823 +tracking_off 1216,37285 +DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820 +DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820 +bool ignore_mouse_drag_p;1256,38396 +some_mouse_moved 1259,38445 +static int read_key_sequence 1282,38803 +static void adjust_point_for_property 1284,38921 +Lisp_Object last_undo_boundary;1287,39036 +command_loop_1 1294,39277 +read_menu_command 1649,50893 +adjust_point_for_property 1678,51621 +safe_run_hooks_1 1831,57343 +safe_run_hooks_error 1841,57573 +safe_run_hook_funcall 1878,58580 +safe_run_hooks 1893,59062 +int poll_suppress_count;1908,59401 +static struct atimer *poll_timer;poll_timer1915,59491 +poll_for_input_1 1919,59593 +poll_for_input 1930,59793 +start_polling 1942,60057 +input_polling_used 1979,61095 +stop_polling 1994,61394 +set_poll_suppress_count 2009,61763 +bind_polling_period 2029,62145 +make_ctrl_char 2048,62496 +show_help_echo 2113,64459 +static Lisp_Object kbd_buffer_get_event 2152,65488 +static void record_char 2154,65600 +static Lisp_Object help_form_saved_window_configs;2156,65642 +read_char_help_form_unwind 2158,65705 +#define STOP_POLLING 2166,65963 +#define RESUME_POLLING 2170,66088 +read_event_from_main_queue 2175,66233 +read_decoded_event_from_main_queue 2249,68421 +#define MAX_ENCODED_BYTES 2254,68668 +echo_keystrokes_p 2342,71560 +read_char 2376,72852 +record_menu_key 3225,98953 +help_char_p 3258,99678 +record_char 3273,99957 +save_getcjmp 3412,104239 +restore_getcjmp 3418,104330 +readable_events 3430,104701 +int stop_character EXTERNALLY_VISIBLE;3497,106441 +event_to_kboard 3500,106497 +kbd_buffer_nr_stored 3522,107146 +kbd_buffer_store_event 3534,107487 +kbd_buffer_store_event_hold 3550,108029 +kbd_buffer_unget_event 3684,111621 +#define INPUT_EVENT_POS_MAX 3698,112022 +#define INPUT_EVENT_POS_MIN 3701,112151 +position_to_Time 3706,112291 +Time_to_position 3716,112518 +gen_help_event 3738,113175 +kbd_buffer_store_help_event 3756,113615 +discard_mouse_events 3773,113980 +kbd_buffer_events_waiting 3803,114715 +clear_event 3823,115072 +kbd_buffer_get_event 3836,115412 +process_special_events 4258,127885 +swallow_events 4322,129709 +timer_start_idle 4339,130102 +timer_stop_idle 4355,130580 +timer_resume_idle 4363,130724 +struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916 +Lisp_Object pending_funcalls;4377,131176 +decode_timer 4381,131297 +timer_check_2 4414,132250 +timer_check 4572,136821 +DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666 +DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666 +static Lisp_Object accent_key_syms;4625,138243 +static Lisp_Object func_key_syms;4626,138279 +static Lisp_Object mouse_syms;4627,138313 +static Lisp_Object wheel_syms;4628,138344 +static Lisp_Object drag_n_drop_syms;4629,138375 +static const int lispy_accent_codes[lispy_accent_codes4634,138520 +static const char *const lispy_accent_keys[lispy_accent_keys4741,139882 +#define FUNCTION_KEY_OFFSET 4766,140318 +const char *const lispy_function_keys[lispy_function_keys4768,140351 +static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905 +static const char *const lispy_kana_keys[lispy_kana_keys5026,150139 +#define FUNCTION_KEY_OFFSET 5061,151755 +static const char *const lispy_function_keys[lispy_function_keys5065,151898 +#define ISO_FUNCTION_KEY_OFFSET 5149,154433 +static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473 +static Lisp_Object Vlispy_mouse_stem;5172,155332 +static const char *const lispy_wheel_names[lispy_wheel_names5174,155371 +static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623 +static short const scroll_bar_parts[scroll_bar_parts5189,155889 +static Lisp_Object button_down_location;5210,156914 +static int last_mouse_button;5215,157069 +static int last_mouse_x;5216,157099 +static int last_mouse_y;5217,157124 +static Time button_down_time;5218,157149 +static int double_click_count;5222,157233 +make_lispy_position 5228,157394 +toolkit_menubar_in_use 5456,163957 +make_scroll_bar_position 5469,164325 +make_lispy_event 5485,164971 +make_lispy_movement 6104,183534 +make_lispy_switch_frame 6131,184265 +make_lispy_focus_in 6137,184372 +make_lispy_focus_out 6145,184498 +parse_modifiers_uncached 6163,184948 +#define SINGLE_LETTER_MOD(6185,185468 +#undef SINGLE_LETTER_MOD6212,185909 +#define MULTI_LETTER_MOD(6214,185935 +#undef MULTI_LETTER_MOD6231,186403 +apply_modifiers_uncached 6273,187577 +static const char *const modifier_names[modifier_names6319,189196 +#define NUM_MOD_NAMES 6325,189402 +static Lisp_Object modifier_symbols;6327,189452 +lispy_modifier_list 6331,189589 +#define KEY_TO_CHAR(6353,190255 +parse_modifiers 6356,190331 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520 +apply_modifiers 6422,192394 +reorder_modifiers 6491,194723 +modify_event_symbol 6536,196531 +DEFUN ("event-convert-list", Fevent_convert_list,6628,199247 +DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247 +parse_solitary_modifier 6695,201138 +#define SINGLE_LETTER_MOD(6701,201261 +#define MULTI_LETTER_MOD(6705,201346 +#undef SINGLE_LETTER_MOD6763,202644 +#undef MULTI_LETTER_MOD6764,202669 +lucid_event_type_list_p 6775,202892 +get_input_pending 6814,203963 +record_asynch_buffer_change 6834,204582 +gobble_input 6872,205705 +tty_read_avail_input 6967,208313 +handle_async_input 7149,214042 +process_pending_signals 7165,214362 +unblock_input_to 7177,214648 +unblock_input 7200,215280 +totally_unblock_input 7209,215448 +handle_input_available_signal 7217,215532 +deliver_input_available_signal 7226,215703 +struct user_signal_info7235,215868 +static struct user_signal_info *user_signals user_signals7250,216093 +add_user_signal 7253,216152 +handle_user_signal 7275,216601 +deliver_user_signal 7316,217561 +find_user_signal_name 7322,217662 +store_user_signal_events 7334,217844 +static void menu_bar_item 7362,218344 +static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419 +static Lisp_Object menu_bar_items_vector;7368,218633 +static int menu_bar_items_index;7369,218675 +static const char *separator_names[separator_names7372,218710 +menu_separator_name_p 7393,219151 +menu_bar_items 7426,219855 +Lisp_Object item_properties;7568,224606 +menu_bar_item 7571,224648 +menu_item_eval_property_1 7647,227178 +eval_dyn 7658,227468 +menu_item_eval_property 7666,227678 +parse_menu_item 7686,228344 +static Lisp_Object tool_bar_items_vector;7965,236339 +static Lisp_Object tool_bar_item_properties;7970,236513 +static int ntool_bar_items;7974,236609 +static void init_tool_bar_items 7978,236667 +static void process_tool_bar_item 7979,236714 +static bool parse_tool_bar_item 7981,236804 +static void append_tool_bar_item 7982,236864 +tool_bar_items 7990,237086 +process_tool_bar_item 8075,239895 +#define PROP(8112,240972 +set_prop 8114,241041 +parse_tool_bar_item 8167,242456 +#undef PROP8379,248847 +init_tool_bar_items 8387,248972 +append_tool_bar_item 8401,249264 +read_char_x_menu_prompt 8443,250774 +read_char_minibuf_menu_prompt 8503,252448 +#define PUSH_C_STR(8527,253017 +follow_key 8726,258556 +active_maps 8733,258698 +typedef struct keyremap8742,259024 +} keyremap;8754,259467 +access_keymap_keyremap 8764,259811 +keyremap_step 8811,261453 +test_undefined 8867,262937 +read_key_sequence 8916,264864 +read_key_sequence_vs 9826,295824 +DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297 +DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985 +detect_input_pending 9950,300491 +detect_input_pending_ignore_squeezables 9959,300657 +detect_input_pending_run_timers 9967,300873 +clear_input_pending 9985,301365 +requeued_events_pending_p 9997,301735 +DEFUN ("input-pending-p", Finput_pending_p,10002,301816 +DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816 +DEFUN ("recent-keys", Frecent_keys,10024,302599 +DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599 +DEFUN ("this-command-keys", Fthis_command_keys,10055,303520 +DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513 +DEFUN ("recursion-depth", Frecursion_depth,10158,307072 +DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072 +DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409 +DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409 +DEFUN ("discard-input", Fdiscard_input,10203,308450 +DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450 +DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952 +DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952 +stuff_buffered_input 10285,311048 +set_waiting_for_input 10323,312019 +clear_waiting_for_input 10337,312393 +handle_interrupt_signal 10351,312757 +deliver_interrupt_signal 10378,313645 +static int volatile force_quit_count;10387,313935 +handle_interrupt 10401,314417 +quit_throw_to_read_char 10541,318714 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291 +DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519 +DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435 +DEFUN ("set-quit-char", Fset_quit_char,10694,322709 +DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709 +DEFUN ("set-input-mode", Fset_input_mode,10729,323573 +DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573 +DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462 +DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462 +DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840 +DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840 +DEFUN ("posn-at-point", Fposn_at_point,10824,327063 +DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063 +init_kboard 10861,328217 +allocate_kboard 10893,329287 +wipe_kboard 10909,329640 +delete_kboard 10917,329754 +init_keyboard 10942,330284 +struct event_head11021,332699 +static const struct event_head head_table[head_table11027,332750 +syms_of_keyboard 11045,333580 +keys_of_keyboard 11841,367118 +mark_kboards 11916,370437 c-src/emacs/src/lisp.h,33840 #define EMACS_LISP_H22,801 @@ -2735,112 +2735,112 @@ el-src/emacs/lisp/progmodes/etags.el,5188 (defcustom tags-tag-face 148,5700 (defcustom tags-apropos-verbose 154,5835 (defcustom tags-apropos-additional-actions 160,5999 -(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918 -(defvar default-tags-table-function 189,7098 -(defvar tags-location-ring 194,7324 -(defvar tags-table-files 201,7600 -(defvar tags-completion-table 206,7767 -(defvar tags-included-tables 209,7859 -(defvar next-file-list 212,7954 -(defvar tags-table-format-functions 217,8060 -(defvar file-of-tag-function 224,8441 -(defvar tags-table-files-function 228,8635 -(defvar tags-completion-table-function 230,8746 -(defvar snarf-tag-function 232,8841 -(defvar goto-tag-location-function 236,9050 -(defvar find-tag-regexp-search-function 239,9223 -(defvar find-tag-regexp-tag-order 241,9344 -(defvar find-tag-regexp-next-line-after-failure-p 243,9453 -(defvar find-tag-search-function 245,9573 -(defvar find-tag-tag-order 247,9680 -(defvar find-tag-next-line-after-failure-p 249,9775 -(defvar list-tags-function 251,9881 -(defvar tags-apropos-function 253,9969 -(defvar tags-included-tables-function 255,10063 -(defvar verify-tags-table-function 257,10182 -(defun initialize-new-tags-table 260,10293 -(defun tags-table-mode 276,10981 -(defun visit-tags-table 285,11246 -(defun tags-table-check-computed-list 321,12784 -(defun tags-table-extend-computed-list 360,14655 -(defun tags-expand-table-name 400,16368 -(defun tags-table-list-member 409,16711 -(defun tags-verify-table 421,17183 -(defun tags-table-including 470,19303 -(defun tags-next-table 522,21347 -(defun visit-tags-table-buffer 543,22204 -(defun tags-reset-tags-tables 712,28514 -(defun file-of-tag 731,29171 -(defun tags-table-files 740,29521 -(defun tags-included-tables 749,29871 -(defun tags-completion-table 755,30117 -(defun tags-lazy-completion-table 783,31311 -(defun tags-completion-at-point-function 799,31946 -(defun find-tag-tag 818,32696 -(defvar last-tag 837,33369 -(defun find-tag-interactive 840,33428 -(defvar find-tag-history 852,33843 -(defvar etags-case-fold-search)855,33908 -(defvar etags-syntax-table)856,33940 -(defvar local-find-tag-hook)857,33968 -(defun find-tag-noselect 860,34013 -(defun find-tag 932,37127 -(defun find-tag-other-window 959,38343 -(defun find-tag-other-frame 1000,40271 -(defun find-tag-regexp 1025,41445 -(defalias 'pop-tag-mark pop-tag-mark1049,42607 -(defvar tag-lines-already-matched 1052,42658 -(defun find-tag-in-order 1055,42765 -(defun tag-find-file-of-tag-noselect 1167,47111 -(defun tag-find-file-of-tag 1200,48957 -(defun etags-recognize-tags-table 1208,49183 -(defun etags-verify-tags-table 1241,50814 -(defun etags-file-of-tag 1246,51012 -(defun etags-tags-completion-table 1256,51347 -(defun etags-snarf-tag 1286,52553 -(defun etags-goto-tag-location 1324,54122 -(defun etags-list-tags 1388,56565 -(defmacro tags-with-face 1423,57840 -(defun etags-tags-apropos-additional 1431,58173 -(defun etags-tags-apropos 1465,59410 -(defun etags-tags-table-files 1527,61619 -(defun etags-tags-included-tables 1542,62055 -(defun tags-recognize-empty-tags-table 1559,62595 -(defun tag-exact-file-name-match-p 1587,63741 -(defun tag-file-name-match-p 1596,64134 -(defun tag-exact-match-p 1609,64690 -(defun tag-implicit-name-match-p 1620,65258 -(defun tag-symbol-match-p 1633,65858 -(defun tag-word-match-p 1643,66294 -(defun tag-partial-file-name-match-p 1652,66692 -(defun tag-any-match-p 1662,67136 -(defun tag-re-match-p 1667,67320 -(defcustom tags-loop-revert-buffers 1675,67569 -(defun next-file 1685,67978 -(defvar tags-loop-operate 1760,70892 -(defvar tags-loop-scan1763,70986 -(defun tags-loop-eval 1771,71315 -(defun tags-loop-continue 1782,71644 -(defun tags-search 1850,73950 -(defun tags-query-replace 1871,74776 -(defun tags-complete-tags-table-file 1896,76000 -(defun list-tags 1906,76379 -(defun tags-apropos 1934,77332 -(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158 -(defun select-tags-table 1964,78397 -(defvar select-tags-table-mode-map 2019,80524 -(define-derived-mode select-tags-table-mode 2030,80907 -(defun select-tags-table-select 2034,81091 -(defun select-tags-table-quit 2043,81457 -(defun complete-tag 2049,81612 -(defconst etags--xref-limit 2074,82553 -(defvar etags-xref-find-definitions-tag-order 2076,82588 -(defun etags-xref-find 2082,82878 -(defun etags--xref-find-definitions 2096,83407 -(defclass xref-etags-location 2129,85121 -(defun xref-make-etags-location 2135,85344 -(cl-defmethod xref-location-marker 2139,85499 -(cl-defmethod xref-location-line 2146,85743 +(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921 +(defvar default-tags-table-function 189,7101 +(defvar tags-location-ring 194,7327 +(defvar tags-table-files 201,7603 +(defvar tags-completion-table 206,7770 +(defvar tags-included-tables 209,7862 +(defvar next-file-list 212,7957 +(defvar tags-table-format-functions 217,8063 +(defvar file-of-tag-function 224,8444 +(defvar tags-table-files-function 228,8638 +(defvar tags-completion-table-function 230,8749 +(defvar snarf-tag-function 232,8844 +(defvar goto-tag-location-function 236,9053 +(defvar find-tag-regexp-search-function 239,9226 +(defvar find-tag-regexp-tag-order 241,9347 +(defvar find-tag-regexp-next-line-after-failure-p 243,9456 +(defvar find-tag-search-function 245,9576 +(defvar find-tag-tag-order 247,9683 +(defvar find-tag-next-line-after-failure-p 249,9778 +(defvar list-tags-function 251,9884 +(defvar tags-apropos-function 253,9972 +(defvar tags-included-tables-function 255,10066 +(defvar verify-tags-table-function 257,10185 +(defun initialize-new-tags-table 260,10296 +(defun tags-table-mode 276,10984 +(defun visit-tags-table 285,11249 +(defun tags-table-check-computed-list 321,12787 +(defun tags-table-extend-computed-list 360,14658 +(defun tags-expand-table-name 400,16371 +(defun tags-table-list-member 409,16714 +(defun tags-verify-table 421,17186 +(defun tags-table-including 470,19306 +(defun tags-next-table 522,21350 +(defun visit-tags-table-buffer 543,22207 +(defun tags-reset-tags-tables 712,28517 +(defun file-of-tag 731,29174 +(defun tags-table-files 740,29524 +(defun tags-included-tables 749,29874 +(defun tags-completion-table 755,30120 +(defun tags-lazy-completion-table 783,31314 +(defun tags-completion-at-point-function 799,31949 +(defun find-tag-tag 818,32699 +(defvar last-tag 837,33372 +(defun find-tag-interactive 840,33431 +(defvar find-tag-history 852,33846 +(defvar etags-case-fold-search)855,33911 +(defvar etags-syntax-table)856,33943 +(defvar local-find-tag-hook)857,33971 +(defun find-tag-noselect 860,34016 +(defun find-tag 932,37130 +(defun find-tag-other-window 959,38346 +(defun find-tag-other-frame 1000,40274 +(defun find-tag-regexp 1025,41448 +(defalias 'pop-tag-mark pop-tag-mark1049,42610 +(defvar tag-lines-already-matched 1052,42661 +(defun find-tag-in-order 1055,42768 +(defun tag-find-file-of-tag-noselect 1167,47114 +(defun tag-find-file-of-tag 1200,48960 +(defun etags-recognize-tags-table 1208,49186 +(defun etags-verify-tags-table 1241,50817 +(defun etags-file-of-tag 1246,51015 +(defun etags-tags-completion-table 1256,51350 +(defun etags-snarf-tag 1286,52556 +(defun etags-goto-tag-location 1324,54125 +(defun etags-list-tags 1388,56568 +(defmacro tags-with-face 1423,57843 +(defun etags-tags-apropos-additional 1431,58176 +(defun etags-tags-apropos 1465,59413 +(defun etags-tags-table-files 1527,61622 +(defun etags-tags-included-tables 1542,62058 +(defun tags-recognize-empty-tags-table 1559,62598 +(defun tag-exact-file-name-match-p 1587,63744 +(defun tag-file-name-match-p 1596,64137 +(defun tag-exact-match-p 1609,64693 +(defun tag-implicit-name-match-p 1620,65261 +(defun tag-symbol-match-p 1633,65861 +(defun tag-word-match-p 1643,66297 +(defun tag-partial-file-name-match-p 1652,66695 +(defun tag-any-match-p 1662,67139 +(defun tag-re-match-p 1667,67323 +(defcustom tags-loop-revert-buffers 1675,67572 +(defun next-file 1685,67981 +(defvar tags-loop-operate 1760,70895 +(defvar tags-loop-scan1763,70989 +(defun tags-loop-eval 1771,71318 +(defun tags-loop-continue 1782,71647 +(defun tags-search 1850,73953 +(defun tags-query-replace 1871,74779 +(defun tags-complete-tags-table-file 1896,76003 +(defun list-tags 1906,76382 +(defun tags-apropos 1934,77335 +(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161 +(defun select-tags-table 1964,78400 +(defvar select-tags-table-mode-map 2019,80527 +(define-derived-mode select-tags-table-mode 2030,80910 +(defun select-tags-table-select 2034,81094 +(defun select-tags-table-quit 2043,81460 +(defun complete-tag 2049,81615 +(defconst etags--xref-limit 2074,82556 +(defvar etags-xref-find-definitions-tag-order 2076,82591 +(defun etags-xref-find 2082,82881 +(defun etags--xref-find-definitions 2096,83410 +(defclass xref-etags-location 2129,85124 +(defun xref-make-etags-location 2135,85347 +(cl-defmethod xref-location-marker 2139,85502 +(cl-defmethod xref-location-line 2146,85746 erl-src/gs_dialog.erl,98 -define(VERSION2,32 diff --git a/test/manual/etags/ETAGS.good_3 b/test/manual/etags/ETAGS.good_3 index 9dca0084de..45507706b3 100644 --- a/test/manual/etags/ETAGS.good_3 +++ b/test/manual/etags/ETAGS.good_3 @@ -1029,289 +1029,289 @@ record_auto_save 742,23849 force_auto_save_soon 751,24017 DEFUN ("recursive-edit", Frecursive_edit,759,24138 DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138 -recursive_edit_unwind 804,25748 -any_kboard_state 817,26014 -single_kboard_state 838,26666 -not_single_kboard_state 848,26804 -struct kboard_stack858,27066 - KBOARD *kboard;kboard860,27088 - struct kboard_stack *next;next861,27106 -static struct kboard_stack *kboard_stack;kboard_stack864,27139 -push_kboard 867,27187 -pop_kboard 879,27376 -temporarily_switch_to_single_kboard 914,28264 -record_single_kboard_state 943,29438 -restore_kboard_configuration 952,29622 -cmd_error 970,30078 -cmd_error_internal 1024,31511 -DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031 -DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031 -command_loop 1094,33917 -command_loop_2 1134,35136 -top_level_2 1146,35340 -top_level_1 1152,35418 -DEFUN ("top-level", Ftop_level,1164,35788 -DEFUN ("top-level", Ftop_level,top-level1164,35788 -user_error 1183,36289 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820 -tracking_off 1216,37282 -DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817 -DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817 -bool ignore_mouse_drag_p;1256,38393 -some_mouse_moved 1259,38442 -Lisp_Object last_undo_boundary;1287,39033 -command_loop_1 1294,39274 -read_menu_command 1649,50890 -adjust_point_for_property 1678,51618 -safe_run_hooks_1 1831,57340 -safe_run_hooks_error 1841,57570 -safe_run_hook_funcall 1878,58577 -safe_run_hooks 1893,59059 -int poll_suppress_count;1908,59398 -static struct atimer *poll_timer;poll_timer1915,59488 -poll_for_input_1 1919,59590 -poll_for_input 1930,59790 -start_polling 1942,60054 -input_polling_used 1979,61092 -stop_polling 1994,61391 -set_poll_suppress_count 2009,61760 -bind_polling_period 2029,62142 -make_ctrl_char 2048,62493 -show_help_echo 2113,64456 -static Lisp_Object help_form_saved_window_configs;2156,65639 -read_char_help_form_unwind 2158,65702 -#define STOP_POLLING 2166,65960 -#define RESUME_POLLING 2170,66085 -read_event_from_main_queue 2175,66230 -read_decoded_event_from_main_queue 2249,68418 -#define MAX_ENCODED_BYTES 2254,68665 -echo_keystrokes_p 2342,71557 -read_char 2376,72849 -record_menu_key 3225,98950 -help_char_p 3258,99675 -record_char 3273,99954 -save_getcjmp 3412,104236 -restore_getcjmp 3418,104327 -readable_events 3430,104698 -int stop_character EXTERNALLY_VISIBLE;3497,106438 -event_to_kboard 3500,106494 -kbd_buffer_nr_stored 3522,107143 -kbd_buffer_store_event 3534,107484 -kbd_buffer_store_event_hold 3550,108026 -kbd_buffer_unget_event 3684,111618 -#define INPUT_EVENT_POS_MAX 3698,112019 -#define INPUT_EVENT_POS_MIN 3701,112148 -position_to_Time 3706,112288 -Time_to_position 3716,112515 -gen_help_event 3738,113172 -kbd_buffer_store_help_event 3756,113612 -discard_mouse_events 3773,113977 -kbd_buffer_events_waiting 3803,114712 -clear_event 3823,115069 -kbd_buffer_get_event 3836,115409 -process_special_events 4258,127882 -swallow_events 4322,129706 -timer_start_idle 4339,130099 -timer_stop_idle 4355,130577 -timer_resume_idle 4363,130721 -struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913 -Lisp_Object pending_funcalls;4377,131173 -decode_timer 4381,131294 -timer_check_2 4414,132247 -timer_check 4572,136818 -DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663 -DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663 -static Lisp_Object accent_key_syms;4625,138240 -static Lisp_Object func_key_syms;4626,138276 -static Lisp_Object mouse_syms;4627,138310 -static Lisp_Object wheel_syms;4628,138341 -static Lisp_Object drag_n_drop_syms;4629,138372 -static const int lispy_accent_codes[lispy_accent_codes4634,138517 -static const char *const lispy_accent_keys[lispy_accent_keys4741,139879 -#define FUNCTION_KEY_OFFSET 4766,140315 -const char *const lispy_function_keys[lispy_function_keys4768,140348 -static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902 -static const char *const lispy_kana_keys[lispy_kana_keys5026,150136 -#define FUNCTION_KEY_OFFSET 5061,151752 -static const char *const lispy_function_keys[lispy_function_keys5065,151895 -#define ISO_FUNCTION_KEY_OFFSET 5149,154430 -static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470 -static Lisp_Object Vlispy_mouse_stem;5172,155329 -static const char *const lispy_wheel_names[lispy_wheel_names5174,155368 -static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620 -static short const scroll_bar_parts[scroll_bar_parts5189,155886 -static Lisp_Object button_down_location;5210,156911 -static int last_mouse_button;5215,157066 -static int last_mouse_x;5216,157096 -static int last_mouse_y;5217,157121 -static Time button_down_time;5218,157146 -static int double_click_count;5222,157230 -make_lispy_position 5228,157391 -toolkit_menubar_in_use 5456,163954 -make_scroll_bar_position 5469,164322 -make_lispy_event 5485,164968 -make_lispy_movement 6104,183531 -make_lispy_switch_frame 6131,184262 -make_lispy_focus_in 6137,184369 -make_lispy_focus_out 6145,184495 -parse_modifiers_uncached 6163,184945 -#define SINGLE_LETTER_MOD(6185,185465 -#undef SINGLE_LETTER_MOD6212,185906 -#define MULTI_LETTER_MOD(6214,185932 -#undef MULTI_LETTER_MOD6231,186400 -apply_modifiers_uncached 6273,187574 -static const char *const modifier_names[modifier_names6319,189193 -#define NUM_MOD_NAMES 6325,189399 -static Lisp_Object modifier_symbols;6327,189449 -lispy_modifier_list 6331,189586 -#define KEY_TO_CHAR(6353,190252 -parse_modifiers 6356,190328 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517 -apply_modifiers 6422,192391 -reorder_modifiers 6491,194720 -modify_event_symbol 6536,196528 -DEFUN ("event-convert-list", Fevent_convert_list,6628,199244 -DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244 -parse_solitary_modifier 6695,201135 -#define SINGLE_LETTER_MOD(6701,201258 -#define MULTI_LETTER_MOD(6705,201343 -#undef SINGLE_LETTER_MOD6763,202641 -#undef MULTI_LETTER_MOD6764,202666 -lucid_event_type_list_p 6775,202889 -get_input_pending 6814,203960 -record_asynch_buffer_change 6834,204579 -gobble_input 6872,205702 -tty_read_avail_input 6967,208310 -handle_async_input 7149,214039 -process_pending_signals 7165,214359 -unblock_input_to 7177,214645 -unblock_input 7200,215277 -totally_unblock_input 7209,215445 -handle_input_available_signal 7217,215529 -deliver_input_available_signal 7226,215700 -struct user_signal_info7235,215865 - int sig;7238,215915 - char *name;name7241,215956 - int npending;7244,216007 - struct user_signal_info *next;next7246,216024 -static struct user_signal_info *user_signals user_signals7250,216090 -add_user_signal 7253,216149 -handle_user_signal 7275,216598 -deliver_user_signal 7316,217558 -find_user_signal_name 7322,217659 -store_user_signal_events 7334,217841 -static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416 -static Lisp_Object menu_bar_items_vector;7368,218630 -static int menu_bar_items_index;7369,218672 -static const char *separator_names[separator_names7372,218707 -menu_separator_name_p 7393,219148 -menu_bar_items 7426,219852 -Lisp_Object item_properties;7568,224603 -menu_bar_item 7571,224645 -menu_item_eval_property_1 7647,227175 -eval_dyn 7658,227465 -menu_item_eval_property 7666,227675 -parse_menu_item 7686,228341 -static Lisp_Object tool_bar_items_vector;7965,236336 -static Lisp_Object tool_bar_item_properties;7970,236510 -static int ntool_bar_items;7974,236606 -tool_bar_items 7990,237083 -process_tool_bar_item 8075,239892 -#define PROP(8112,240969 -set_prop 8114,241038 -parse_tool_bar_item 8167,242453 -#undef PROP8379,248844 -init_tool_bar_items 8387,248969 -append_tool_bar_item 8401,249261 -read_char_x_menu_prompt 8443,250771 -read_char_minibuf_menu_prompt 8503,252445 -#define PUSH_C_STR(8527,253014 -follow_key 8726,258553 -active_maps 8733,258695 -typedef struct keyremap8742,259021 - Lisp_Object parent;8745,259107 - Lisp_Object map;8748,259224 - int start,8753,259446 - int start, end;8753,259446 -} keyremap;8754,259464 -access_keymap_keyremap 8764,259808 -keyremap_step 8811,261450 -test_undefined 8867,262934 -read_key_sequence 8916,264861 -read_key_sequence_vs 9826,295821 -DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294 -DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982 -detect_input_pending 9950,300488 -detect_input_pending_ignore_squeezables 9959,300654 -detect_input_pending_run_timers 9967,300870 -clear_input_pending 9985,301362 -requeued_events_pending_p 9997,301732 -DEFUN ("input-pending-p", Finput_pending_p,10002,301813 -DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813 -DEFUN ("recent-keys", Frecent_keys,10024,302596 -DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596 -DEFUN ("this-command-keys", Fthis_command_keys,10055,303517 -DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510 -DEFUN ("recursion-depth", Frecursion_depth,10158,307069 -DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069 -DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406 -DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406 -DEFUN ("discard-input", Fdiscard_input,10203,308447 -DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447 -DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949 -DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949 -stuff_buffered_input 10285,311045 -set_waiting_for_input 10323,312016 -clear_waiting_for_input 10337,312390 -handle_interrupt_signal 10351,312754 -deliver_interrupt_signal 10378,313642 -static int volatile force_quit_count;10387,313932 -handle_interrupt 10401,314414 -quit_throw_to_read_char 10541,318711 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288 -DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516 -DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432 -DEFUN ("set-quit-char", Fset_quit_char,10694,322706 -DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706 -DEFUN ("set-input-mode", Fset_input_mode,10729,323570 -DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570 -DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459 -DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459 -DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837 -DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837 -DEFUN ("posn-at-point", Fposn_at_point,10824,327060 -DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060 -init_kboard 10861,328214 -allocate_kboard 10893,329284 -wipe_kboard 10909,329637 -delete_kboard 10917,329751 -init_keyboard 10942,330281 -struct event_head11021,332696 - short var;11023,332716 - short kind;11024,332729 -static const struct event_head head_table[head_table11027,332747 -syms_of_keyboard 11045,333577 -keys_of_keyboard 11841,367115 -mark_kboards 11916,370434 +recursive_edit_unwind 804,25751 +any_kboard_state 817,26017 +single_kboard_state 838,26669 +not_single_kboard_state 848,26807 +struct kboard_stack858,27069 + KBOARD *kboard;kboard860,27091 + struct kboard_stack *next;next861,27109 +static struct kboard_stack *kboard_stack;kboard_stack864,27142 +push_kboard 867,27190 +pop_kboard 879,27379 +temporarily_switch_to_single_kboard 914,28267 +record_single_kboard_state 943,29441 +restore_kboard_configuration 952,29625 +cmd_error 970,30081 +cmd_error_internal 1024,31514 +DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034 +DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034 +command_loop 1094,33920 +command_loop_2 1134,35139 +top_level_2 1146,35343 +top_level_1 1152,35421 +DEFUN ("top-level", Ftop_level,1164,35791 +DEFUN ("top-level", Ftop_level,top-level1164,35791 +user_error 1183,36292 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823 +tracking_off 1216,37285 +DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820 +DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820 +bool ignore_mouse_drag_p;1256,38396 +some_mouse_moved 1259,38445 +Lisp_Object last_undo_boundary;1287,39036 +command_loop_1 1294,39277 +read_menu_command 1649,50893 +adjust_point_for_property 1678,51621 +safe_run_hooks_1 1831,57343 +safe_run_hooks_error 1841,57573 +safe_run_hook_funcall 1878,58580 +safe_run_hooks 1893,59062 +int poll_suppress_count;1908,59401 +static struct atimer *poll_timer;poll_timer1915,59491 +poll_for_input_1 1919,59593 +poll_for_input 1930,59793 +start_polling 1942,60057 +input_polling_used 1979,61095 +stop_polling 1994,61394 +set_poll_suppress_count 2009,61763 +bind_polling_period 2029,62145 +make_ctrl_char 2048,62496 +show_help_echo 2113,64459 +static Lisp_Object help_form_saved_window_configs;2156,65642 +read_char_help_form_unwind 2158,65705 +#define STOP_POLLING 2166,65963 +#define RESUME_POLLING 2170,66088 +read_event_from_main_queue 2175,66233 +read_decoded_event_from_main_queue 2249,68421 +#define MAX_ENCODED_BYTES 2254,68668 +echo_keystrokes_p 2342,71560 +read_char 2376,72852 +record_menu_key 3225,98953 +help_char_p 3258,99678 +record_char 3273,99957 +save_getcjmp 3412,104239 +restore_getcjmp 3418,104330 +readable_events 3430,104701 +int stop_character EXTERNALLY_VISIBLE;3497,106441 +event_to_kboard 3500,106497 +kbd_buffer_nr_stored 3522,107146 +kbd_buffer_store_event 3534,107487 +kbd_buffer_store_event_hold 3550,108029 +kbd_buffer_unget_event 3684,111621 +#define INPUT_EVENT_POS_MAX 3698,112022 +#define INPUT_EVENT_POS_MIN 3701,112151 +position_to_Time 3706,112291 +Time_to_position 3716,112518 +gen_help_event 3738,113175 +kbd_buffer_store_help_event 3756,113615 +discard_mouse_events 3773,113980 +kbd_buffer_events_waiting 3803,114715 +clear_event 3823,115072 +kbd_buffer_get_event 3836,115412 +process_special_events 4258,127885 +swallow_events 4322,129709 +timer_start_idle 4339,130102 +timer_stop_idle 4355,130580 +timer_resume_idle 4363,130724 +struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916 +Lisp_Object pending_funcalls;4377,131176 +decode_timer 4381,131297 +timer_check_2 4414,132250 +timer_check 4572,136821 +DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666 +DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666 +static Lisp_Object accent_key_syms;4625,138243 +static Lisp_Object func_key_syms;4626,138279 +static Lisp_Object mouse_syms;4627,138313 +static Lisp_Object wheel_syms;4628,138344 +static Lisp_Object drag_n_drop_syms;4629,138375 +static const int lispy_accent_codes[lispy_accent_codes4634,138520 +static const char *const lispy_accent_keys[lispy_accent_keys4741,139882 +#define FUNCTION_KEY_OFFSET 4766,140318 +const char *const lispy_function_keys[lispy_function_keys4768,140351 +static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905 +static const char *const lispy_kana_keys[lispy_kana_keys5026,150139 +#define FUNCTION_KEY_OFFSET 5061,151755 +static const char *const lispy_function_keys[lispy_function_keys5065,151898 +#define ISO_FUNCTION_KEY_OFFSET 5149,154433 +static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473 +static Lisp_Object Vlispy_mouse_stem;5172,155332 +static const char *const lispy_wheel_names[lispy_wheel_names5174,155371 +static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623 +static short const scroll_bar_parts[scroll_bar_parts5189,155889 +static Lisp_Object button_down_location;5210,156914 +static int last_mouse_button;5215,157069 +static int last_mouse_x;5216,157099 +static int last_mouse_y;5217,157124 +static Time button_down_time;5218,157149 +static int double_click_count;5222,157233 +make_lispy_position 5228,157394 +toolkit_menubar_in_use 5456,163957 +make_scroll_bar_position 5469,164325 +make_lispy_event 5485,164971 +make_lispy_movement 6104,183534 +make_lispy_switch_frame 6131,184265 +make_lispy_focus_in 6137,184372 +make_lispy_focus_out 6145,184498 +parse_modifiers_uncached 6163,184948 +#define SINGLE_LETTER_MOD(6185,185468 +#undef SINGLE_LETTER_MOD6212,185909 +#define MULTI_LETTER_MOD(6214,185935 +#undef MULTI_LETTER_MOD6231,186403 +apply_modifiers_uncached 6273,187577 +static const char *const modifier_names[modifier_names6319,189196 +#define NUM_MOD_NAMES 6325,189402 +static Lisp_Object modifier_symbols;6327,189452 +lispy_modifier_list 6331,189589 +#define KEY_TO_CHAR(6353,190255 +parse_modifiers 6356,190331 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520 +apply_modifiers 6422,192394 +reorder_modifiers 6491,194723 +modify_event_symbol 6536,196531 +DEFUN ("event-convert-list", Fevent_convert_list,6628,199247 +DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247 +parse_solitary_modifier 6695,201138 +#define SINGLE_LETTER_MOD(6701,201261 +#define MULTI_LETTER_MOD(6705,201346 +#undef SINGLE_LETTER_MOD6763,202644 +#undef MULTI_LETTER_MOD6764,202669 +lucid_event_type_list_p 6775,202892 +get_input_pending 6814,203963 +record_asynch_buffer_change 6834,204582 +gobble_input 6872,205705 +tty_read_avail_input 6967,208313 +handle_async_input 7149,214042 +process_pending_signals 7165,214362 +unblock_input_to 7177,214648 +unblock_input 7200,215280 +totally_unblock_input 7209,215448 +handle_input_available_signal 7217,215532 +deliver_input_available_signal 7226,215703 +struct user_signal_info7235,215868 + int sig;7238,215918 + char *name;name7241,215959 + int npending;7244,216010 + struct user_signal_info *next;next7246,216027 +static struct user_signal_info *user_signals user_signals7250,216093 +add_user_signal 7253,216152 +handle_user_signal 7275,216601 +deliver_user_signal 7316,217561 +find_user_signal_name 7322,217662 +store_user_signal_events 7334,217844 +static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419 +static Lisp_Object menu_bar_items_vector;7368,218633 +static int menu_bar_items_index;7369,218675 +static const char *separator_names[separator_names7372,218710 +menu_separator_name_p 7393,219151 +menu_bar_items 7426,219855 +Lisp_Object item_properties;7568,224606 +menu_bar_item 7571,224648 +menu_item_eval_property_1 7647,227178 +eval_dyn 7658,227468 +menu_item_eval_property 7666,227678 +parse_menu_item 7686,228344 +static Lisp_Object tool_bar_items_vector;7965,236339 +static Lisp_Object tool_bar_item_properties;7970,236513 +static int ntool_bar_items;7974,236609 +tool_bar_items 7990,237086 +process_tool_bar_item 8075,239895 +#define PROP(8112,240972 +set_prop 8114,241041 +parse_tool_bar_item 8167,242456 +#undef PROP8379,248847 +init_tool_bar_items 8387,248972 +append_tool_bar_item 8401,249264 +read_char_x_menu_prompt 8443,250774 +read_char_minibuf_menu_prompt 8503,252448 +#define PUSH_C_STR(8527,253017 +follow_key 8726,258556 +active_maps 8733,258698 +typedef struct keyremap8742,259024 + Lisp_Object parent;8745,259110 + Lisp_Object map;8748,259227 + int start,8753,259449 + int start, end;8753,259449 +} keyremap;8754,259467 +access_keymap_keyremap 8764,259811 +keyremap_step 8811,261453 +test_undefined 8867,262937 +read_key_sequence 8916,264864 +read_key_sequence_vs 9826,295824 +DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297 +DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985 +detect_input_pending 9950,300491 +detect_input_pending_ignore_squeezables 9959,300657 +detect_input_pending_run_timers 9967,300873 +clear_input_pending 9985,301365 +requeued_events_pending_p 9997,301735 +DEFUN ("input-pending-p", Finput_pending_p,10002,301816 +DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816 +DEFUN ("recent-keys", Frecent_keys,10024,302599 +DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599 +DEFUN ("this-command-keys", Fthis_command_keys,10055,303520 +DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513 +DEFUN ("recursion-depth", Frecursion_depth,10158,307072 +DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072 +DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409 +DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409 +DEFUN ("discard-input", Fdiscard_input,10203,308450 +DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450 +DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952 +DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952 +stuff_buffered_input 10285,311048 +set_waiting_for_input 10323,312019 +clear_waiting_for_input 10337,312393 +handle_interrupt_signal 10351,312757 +deliver_interrupt_signal 10378,313645 +static int volatile force_quit_count;10387,313935 +handle_interrupt 10401,314417 +quit_throw_to_read_char 10541,318714 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291 +DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519 +DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435 +DEFUN ("set-quit-char", Fset_quit_char,10694,322709 +DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709 +DEFUN ("set-input-mode", Fset_input_mode,10729,323573 +DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573 +DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462 +DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462 +DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840 +DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840 +DEFUN ("posn-at-point", Fposn_at_point,10824,327063 +DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063 +init_kboard 10861,328217 +allocate_kboard 10893,329287 +wipe_kboard 10909,329640 +delete_kboard 10917,329754 +init_keyboard 10942,330284 +struct event_head11021,332699 + short var;11023,332719 + short kind;11024,332732 +static const struct event_head head_table[head_table11027,332750 +syms_of_keyboard 11045,333580 +keys_of_keyboard 11841,367118 +mark_kboards 11916,370437 c-src/emacs/src/lisp.h,27827 #define EMACS_LISP_H22,801 @@ -2543,109 +2543,109 @@ el-src/emacs/lisp/progmodes/etags.el,5069 (defcustom tags-tag-face 148,5700 (defcustom tags-apropos-verbose 154,5835 (defcustom tags-apropos-additional-actions 160,5999 -(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918 -(defvar default-tags-table-function 189,7098 -(defvar tags-location-ring 194,7324 -(defvar tags-table-files 201,7600 -(defvar tags-completion-table 206,7767 -(defvar tags-included-tables 209,7859 -(defvar next-file-list 212,7954 -(defvar tags-table-format-functions 217,8060 -(defvar file-of-tag-function 224,8441 -(defvar tags-table-files-function 228,8635 -(defvar tags-completion-table-function 230,8746 -(defvar snarf-tag-function 232,8841 -(defvar goto-tag-location-function 236,9050 -(defvar find-tag-regexp-search-function 239,9223 -(defvar find-tag-regexp-tag-order 241,9344 -(defvar find-tag-regexp-next-line-after-failure-p 243,9453 -(defvar find-tag-search-function 245,9573 -(defvar find-tag-tag-order 247,9680 -(defvar find-tag-next-line-after-failure-p 249,9775 -(defvar list-tags-function 251,9881 -(defvar tags-apropos-function 253,9969 -(defvar tags-included-tables-function 255,10063 -(defvar verify-tags-table-function 257,10182 -(defun initialize-new-tags-table 260,10293 -(defun tags-table-mode 276,10981 -(defun visit-tags-table 285,11246 -(defun tags-table-check-computed-list 321,12784 -(defun tags-table-extend-computed-list 360,14655 -(defun tags-expand-table-name 400,16368 -(defun tags-table-list-member 409,16711 -(defun tags-verify-table 421,17183 -(defun tags-table-including 470,19303 -(defun tags-next-table 522,21347 -(defun visit-tags-table-buffer 543,22204 -(defun tags-reset-tags-tables 712,28514 -(defun file-of-tag 731,29171 -(defun tags-table-files 740,29521 -(defun tags-included-tables 749,29871 -(defun tags-completion-table 755,30117 -(defun tags-lazy-completion-table 783,31311 -(defun tags-completion-at-point-function 799,31946 -(defun find-tag-tag 818,32696 -(defvar last-tag 837,33369 -(defun find-tag-interactive 840,33428 -(defvar find-tag-history 852,33843 -(defun find-tag-noselect 860,34013 -(defun find-tag 932,37127 -(defun find-tag-other-window 959,38343 -(defun find-tag-other-frame 1000,40271 -(defun find-tag-regexp 1025,41445 -(defalias 'pop-tag-mark pop-tag-mark1049,42607 -(defvar tag-lines-already-matched 1052,42658 -(defun find-tag-in-order 1055,42765 -(defun tag-find-file-of-tag-noselect 1167,47111 -(defun tag-find-file-of-tag 1200,48957 -(defun etags-recognize-tags-table 1208,49183 -(defun etags-verify-tags-table 1241,50814 -(defun etags-file-of-tag 1246,51012 -(defun etags-tags-completion-table 1256,51347 -(defun etags-snarf-tag 1286,52553 -(defun etags-goto-tag-location 1324,54122 -(defun etags-list-tags 1388,56565 -(defmacro tags-with-face 1423,57840 -(defun etags-tags-apropos-additional 1431,58173 -(defun etags-tags-apropos 1465,59410 -(defun etags-tags-table-files 1527,61619 -(defun etags-tags-included-tables 1542,62055 -(defun tags-recognize-empty-tags-table 1559,62595 -(defun tag-exact-file-name-match-p 1587,63741 -(defun tag-file-name-match-p 1596,64134 -(defun tag-exact-match-p 1609,64690 -(defun tag-implicit-name-match-p 1620,65258 -(defun tag-symbol-match-p 1633,65858 -(defun tag-word-match-p 1643,66294 -(defun tag-partial-file-name-match-p 1652,66692 -(defun tag-any-match-p 1662,67136 -(defun tag-re-match-p 1667,67320 -(defcustom tags-loop-revert-buffers 1675,67569 -(defun next-file 1685,67978 -(defvar tags-loop-operate 1760,70892 -(defvar tags-loop-scan1763,70986 -(defun tags-loop-eval 1771,71315 -(defun tags-loop-continue 1782,71644 -(defun tags-search 1850,73950 -(defun tags-query-replace 1871,74776 -(defun tags-complete-tags-table-file 1896,76000 -(defun list-tags 1906,76379 -(defun tags-apropos 1934,77332 -(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158 -(defun select-tags-table 1964,78397 -(defvar select-tags-table-mode-map 2019,80524 -(define-derived-mode select-tags-table-mode 2030,80907 -(defun select-tags-table-select 2034,81091 -(defun select-tags-table-quit 2043,81457 -(defun complete-tag 2049,81612 -(defconst etags--xref-limit 2074,82553 -(defvar etags-xref-find-definitions-tag-order 2076,82588 -(defun etags-xref-find 2082,82878 -(defun etags--xref-find-definitions 2096,83407 -(defclass xref-etags-location 2129,85121 -(defun xref-make-etags-location 2135,85344 -(cl-defmethod xref-location-marker 2139,85499 -(cl-defmethod xref-location-line 2146,85743 +(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921 +(defvar default-tags-table-function 189,7101 +(defvar tags-location-ring 194,7327 +(defvar tags-table-files 201,7603 +(defvar tags-completion-table 206,7770 +(defvar tags-included-tables 209,7862 +(defvar next-file-list 212,7957 +(defvar tags-table-format-functions 217,8063 +(defvar file-of-tag-function 224,8444 +(defvar tags-table-files-function 228,8638 +(defvar tags-completion-table-function 230,8749 +(defvar snarf-tag-function 232,8844 +(defvar goto-tag-location-function 236,9053 +(defvar find-tag-regexp-search-function 239,9226 +(defvar find-tag-regexp-tag-order 241,9347 +(defvar find-tag-regexp-next-line-after-failure-p 243,9456 +(defvar find-tag-search-function 245,9576 +(defvar find-tag-tag-order 247,9683 +(defvar find-tag-next-line-after-failure-p 249,9778 +(defvar list-tags-function 251,9884 +(defvar tags-apropos-function 253,9972 +(defvar tags-included-tables-function 255,10066 +(defvar verify-tags-table-function 257,10185 +(defun initialize-new-tags-table 260,10296 +(defun tags-table-mode 276,10984 +(defun visit-tags-table 285,11249 +(defun tags-table-check-computed-list 321,12787 +(defun tags-table-extend-computed-list 360,14658 +(defun tags-expand-table-name 400,16371 +(defun tags-table-list-member 409,16714 +(defun tags-verify-table 421,17186 +(defun tags-table-including 470,19306 +(defun tags-next-table 522,21350 +(defun visit-tags-table-buffer 543,22207 +(defun tags-reset-tags-tables 712,28517 +(defun file-of-tag 731,29174 +(defun tags-table-files 740,29524 +(defun tags-included-tables 749,29874 +(defun tags-completion-table 755,30120 +(defun tags-lazy-completion-table 783,31314 +(defun tags-completion-at-point-function 799,31949 +(defun find-tag-tag 818,32699 +(defvar last-tag 837,33372 +(defun find-tag-interactive 840,33431 +(defvar find-tag-history 852,33846 +(defun find-tag-noselect 860,34016 +(defun find-tag 932,37130 +(defun find-tag-other-window 959,38346 +(defun find-tag-other-frame 1000,40274 +(defun find-tag-regexp 1025,41448 +(defalias 'pop-tag-mark pop-tag-mark1049,42610 +(defvar tag-lines-already-matched 1052,42661 +(defun find-tag-in-order 1055,42768 +(defun tag-find-file-of-tag-noselect 1167,47114 +(defun tag-find-file-of-tag 1200,48960 +(defun etags-recognize-tags-table 1208,49186 +(defun etags-verify-tags-table 1241,50817 +(defun etags-file-of-tag 1246,51015 +(defun etags-tags-completion-table 1256,51350 +(defun etags-snarf-tag 1286,52556 +(defun etags-goto-tag-location 1324,54125 +(defun etags-list-tags 1388,56568 +(defmacro tags-with-face 1423,57843 +(defun etags-tags-apropos-additional 1431,58176 +(defun etags-tags-apropos 1465,59413 +(defun etags-tags-table-files 1527,61622 +(defun etags-tags-included-tables 1542,62058 +(defun tags-recognize-empty-tags-table 1559,62598 +(defun tag-exact-file-name-match-p 1587,63744 +(defun tag-file-name-match-p 1596,64137 +(defun tag-exact-match-p 1609,64693 +(defun tag-implicit-name-match-p 1620,65261 +(defun tag-symbol-match-p 1633,65861 +(defun tag-word-match-p 1643,66297 +(defun tag-partial-file-name-match-p 1652,66695 +(defun tag-any-match-p 1662,67139 +(defun tag-re-match-p 1667,67323 +(defcustom tags-loop-revert-buffers 1675,67572 +(defun next-file 1685,67981 +(defvar tags-loop-operate 1760,70895 +(defvar tags-loop-scan1763,70989 +(defun tags-loop-eval 1771,71318 +(defun tags-loop-continue 1782,71647 +(defun tags-search 1850,73953 +(defun tags-query-replace 1871,74779 +(defun tags-complete-tags-table-file 1896,76003 +(defun list-tags 1906,76382 +(defun tags-apropos 1934,77335 +(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161 +(defun select-tags-table 1964,78400 +(defvar select-tags-table-mode-map 2019,80527 +(define-derived-mode select-tags-table-mode 2030,80910 +(defun select-tags-table-select 2034,81094 +(defun select-tags-table-quit 2043,81460 +(defun complete-tag 2049,81615 +(defconst etags--xref-limit 2074,82556 +(defvar etags-xref-find-definitions-tag-order 2076,82591 +(defun etags-xref-find 2082,82881 +(defun etags--xref-find-definitions 2096,83410 +(defclass xref-etags-location 2129,85124 +(defun xref-make-etags-location 2135,85347 +(cl-defmethod xref-location-marker 2139,85502 +(cl-defmethod xref-location-line 2146,85746 erl-src/gs_dialog.erl,98 -define(VERSION2,32 diff --git a/test/manual/etags/ETAGS.good_4 b/test/manual/etags/ETAGS.good_4 index 8527ed726e..dee534ae75 100644 --- a/test/manual/etags/ETAGS.good_4 +++ b/test/manual/etags/ETAGS.good_4 @@ -937,417 +937,417 @@ record_auto_save 742,23849 force_auto_save_soon 751,24017 DEFUN ("recursive-edit", Frecursive_edit,759,24138 DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138 -recursive_edit_unwind 804,25748 -any_kboard_state 817,26014 -single_kboard_state 838,26666 -not_single_kboard_state 848,26804 -struct kboard_stack858,27066 -static struct kboard_stack *kboard_stack;kboard_stack864,27139 -push_kboard 867,27187 -pop_kboard 879,27376 -temporarily_switch_to_single_kboard 914,28264 -record_single_kboard_state 943,29438 -restore_kboard_configuration 952,29622 -cmd_error 970,30078 -cmd_error_internal 1024,31511 -DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031 -DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031 -command_loop 1094,33917 -command_loop_2 1134,35136 -top_level_2 1146,35340 -top_level_1 1152,35418 -DEFUN ("top-level", Ftop_level,1164,35788 -DEFUN ("top-level", Ftop_level,top-level1164,35788 -user_error 1183,36289 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820 -tracking_off 1216,37282 -DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817 -DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817 -bool ignore_mouse_drag_p;1256,38393 -some_mouse_moved 1259,38442 -Lisp_Object last_undo_boundary;1287,39033 -command_loop_1 1294,39274 -read_menu_command 1649,50890 -adjust_point_for_property 1678,51618 -safe_run_hooks_1 1831,57340 -safe_run_hooks_error 1841,57570 -safe_run_hook_funcall 1878,58577 -safe_run_hooks 1893,59059 -int poll_suppress_count;1908,59398 -static struct atimer *poll_timer;poll_timer1915,59488 -poll_for_input_1 1919,59590 -poll_for_input 1930,59790 -start_polling 1942,60054 -input_polling_used 1979,61092 -stop_polling 1994,61391 -set_poll_suppress_count 2009,61760 -bind_polling_period 2029,62142 -make_ctrl_char 2048,62493 -show_help_echo 2113,64456 -static Lisp_Object help_form_saved_window_configs;2156,65639 -read_char_help_form_unwind 2158,65702 -#define STOP_POLLING 2166,65960 -#define RESUME_POLLING 2170,66085 -read_event_from_main_queue 2175,66230 -read_decoded_event_from_main_queue 2249,68418 -#define MAX_ENCODED_BYTES 2254,68665 -echo_keystrokes_p 2342,71557 -read_char 2376,72849 -record_menu_key 3225,98950 -help_char_p 3258,99675 -record_char 3273,99954 -save_getcjmp 3412,104236 -restore_getcjmp 3418,104327 -readable_events 3430,104698 -int stop_character EXTERNALLY_VISIBLE;3497,106438 -event_to_kboard 3500,106494 -kbd_buffer_nr_stored 3522,107143 -kbd_buffer_store_event 3534,107484 -kbd_buffer_store_event_hold 3550,108026 -kbd_buffer_unget_event 3684,111618 -#define INPUT_EVENT_POS_MAX 3698,112019 -#define INPUT_EVENT_POS_MIN 3701,112148 -position_to_Time 3706,112288 -Time_to_position 3716,112515 -gen_help_event 3738,113172 -kbd_buffer_store_help_event 3756,113612 -discard_mouse_events 3773,113977 -kbd_buffer_events_waiting 3803,114712 -clear_event 3823,115069 -kbd_buffer_get_event 3836,115409 -process_special_events 4258,127882 -swallow_events 4322,129706 -timer_start_idle 4339,130099 -timer_stop_idle 4355,130577 -timer_resume_idle 4363,130721 -struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913 -Lisp_Object pending_funcalls;4377,131173 -decode_timer 4381,131294 -timer_check_2 4414,132247 -timer_check 4572,136818 -DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663 -DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663 -static Lisp_Object accent_key_syms;4625,138240 -static Lisp_Object func_key_syms;4626,138276 -static Lisp_Object mouse_syms;4627,138310 -static Lisp_Object wheel_syms;4628,138341 -static Lisp_Object drag_n_drop_syms;4629,138372 -static const int lispy_accent_codes[lispy_accent_codes4634,138517 -static const char *const lispy_accent_keys[lispy_accent_keys4741,139879 -#define FUNCTION_KEY_OFFSET 4766,140315 -const char *const lispy_function_keys[lispy_function_keys4768,140348 -static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902 -static const char *const lispy_kana_keys[lispy_kana_keys5026,150136 -#define FUNCTION_KEY_OFFSET 5061,151752 -static const char *const lispy_function_keys[lispy_function_keys5065,151895 -#define ISO_FUNCTION_KEY_OFFSET 5149,154430 -static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470 -static Lisp_Object Vlispy_mouse_stem;5172,155329 -static const char *const lispy_wheel_names[lispy_wheel_names5174,155368 -static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620 -static short const scroll_bar_parts[scroll_bar_parts5189,155886 -static Lisp_Object button_down_location;5210,156911 -static int last_mouse_button;5215,157066 -static int last_mouse_x;5216,157096 -static int last_mouse_y;5217,157121 -static Time button_down_time;5218,157146 -static int double_click_count;5222,157230 -make_lispy_position 5228,157391 -toolkit_menubar_in_use 5456,163954 -make_scroll_bar_position 5469,164322 -make_lispy_event 5485,164968 -make_lispy_movement 6104,183531 -make_lispy_switch_frame 6131,184262 -make_lispy_focus_in 6137,184369 -make_lispy_focus_out 6145,184495 -parse_modifiers_uncached 6163,184945 -#define SINGLE_LETTER_MOD(6185,185465 -#undef SINGLE_LETTER_MOD6212,185906 -#define MULTI_LETTER_MOD(6214,185932 -#undef MULTI_LETTER_MOD6231,186400 -apply_modifiers_uncached 6273,187574 -static const char *const modifier_names[modifier_names6319,189193 -#define NUM_MOD_NAMES 6325,189399 -static Lisp_Object modifier_symbols;6327,189449 -lispy_modifier_list 6331,189586 -#define KEY_TO_CHAR(6353,190252 -parse_modifiers 6356,190328 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517 -apply_modifiers 6422,192391 -reorder_modifiers 6491,194720 -modify_event_symbol 6536,196528 -DEFUN ("event-convert-list", Fevent_convert_list,6628,199244 -DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244 -parse_solitary_modifier 6695,201135 -#define SINGLE_LETTER_MOD(6701,201258 -#define MULTI_LETTER_MOD(6705,201343 -#undef SINGLE_LETTER_MOD6763,202641 -#undef MULTI_LETTER_MOD6764,202666 -lucid_event_type_list_p 6775,202889 -get_input_pending 6814,203960 -record_asynch_buffer_change 6834,204579 -gobble_input 6872,205702 -tty_read_avail_input 6967,208310 -handle_async_input 7149,214039 -process_pending_signals 7165,214359 -unblock_input_to 7177,214645 -unblock_input 7200,215277 -totally_unblock_input 7209,215445 -handle_input_available_signal 7217,215529 -deliver_input_available_signal 7226,215700 -struct user_signal_info7235,215865 -static struct user_signal_info *user_signals user_signals7250,216090 -add_user_signal 7253,216149 -handle_user_signal 7275,216598 -deliver_user_signal 7316,217558 -find_user_signal_name 7322,217659 -store_user_signal_events 7334,217841 -static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416 -static Lisp_Object menu_bar_items_vector;7368,218630 -static int menu_bar_items_index;7369,218672 -static const char *separator_names[separator_names7372,218707 -menu_separator_name_p 7393,219148 -menu_bar_items 7426,219852 -Lisp_Object item_properties;7568,224603 -menu_bar_item 7571,224645 -menu_item_eval_property_1 7647,227175 -eval_dyn 7658,227465 -menu_item_eval_property 7666,227675 -parse_menu_item 7686,228341 -static Lisp_Object tool_bar_items_vector;7965,236336 -static Lisp_Object tool_bar_item_properties;7970,236510 -static int ntool_bar_items;7974,236606 -tool_bar_items 7990,237083 -process_tool_bar_item 8075,239892 -#define PROP(8112,240969 -set_prop 8114,241038 -parse_tool_bar_item 8167,242453 -#undef PROP8379,248844 -init_tool_bar_items 8387,248969 -append_tool_bar_item 8401,249261 -read_char_x_menu_prompt 8443,250771 -read_char_minibuf_menu_prompt 8503,252445 -#define PUSH_C_STR(8527,253014 -follow_key 8726,258553 -active_maps 8733,258695 -typedef struct keyremap8742,259021 -} keyremap;8754,259464 -access_keymap_keyremap 8764,259808 -keyremap_step 8811,261450 -test_undefined 8867,262934 -read_key_sequence 8916,264861 -read_key_sequence_vs 9826,295821 -DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294 -DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982 -detect_input_pending 9950,300488 -detect_input_pending_ignore_squeezables 9959,300654 -detect_input_pending_run_timers 9967,300870 -clear_input_pending 9985,301362 -requeued_events_pending_p 9997,301732 -DEFUN ("input-pending-p", Finput_pending_p,10002,301813 -DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813 -DEFUN ("recent-keys", Frecent_keys,10024,302596 -DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596 -DEFUN ("this-command-keys", Fthis_command_keys,10055,303517 -DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510 -DEFUN ("recursion-depth", Frecursion_depth,10158,307069 -DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069 -DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406 -DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406 -DEFUN ("discard-input", Fdiscard_input,10203,308447 -DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447 -DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949 -DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949 -stuff_buffered_input 10285,311045 -set_waiting_for_input 10323,312016 -clear_waiting_for_input 10337,312390 -handle_interrupt_signal 10351,312754 -deliver_interrupt_signal 10378,313642 -static int volatile force_quit_count;10387,313932 -handle_interrupt 10401,314414 -quit_throw_to_read_char 10541,318711 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288 -DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516 -DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432 -DEFUN ("set-quit-char", Fset_quit_char,10694,322706 -DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706 -DEFUN ("set-input-mode", Fset_input_mode,10729,323570 -DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570 -DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459 -DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459 -DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837 -DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837 -DEFUN ("posn-at-point", Fposn_at_point,10824,327060 -DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060 -init_kboard 10861,328214 -allocate_kboard 10893,329284 -wipe_kboard 10909,329637 -delete_kboard 10917,329751 -init_keyboard 10942,330281 -struct event_head11021,332696 -static const struct event_head head_table[head_table11027,332747 -syms_of_keyboard 11045,333577 - DEFVAR_LISP ("internal--top-level-message"11058,333972 - DEFVAR_LISP ("last-command-event"11312,342173 - DEFVAR_LISP ("last-nonmenu-event"11315,342297 - DEFVAR_LISP ("last-input-event"11321,342636 - DEFVAR_LISP ("unread-command-events"11324,342730 - DEFVAR_LISP ("unread-post-input-method-events"11332,343190 - DEFVAR_LISP ("unread-input-method-events"11338,343529 - DEFVAR_LISP ("meta-prefix-char"11346,343898 - DEFVAR_KBOARD ("last-command"11351,344106 - DEFVAR_KBOARD ("real-last-command"11368,344787 - DEFVAR_KBOARD ("last-repeatable-command"11372,344973 - DEFVAR_LISP ("this-command"11378,345261 - DEFVAR_LISP ("real-this-command"11384,345498 - DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680 - DEFVAR_LISP ("this-original-command"11396,346123 - DEFVAR_INT ("auto-save-interval"11403,346520 - DEFVAR_LISP ("auto-save-timeout"11408,346734 - DEFVAR_LISP ("echo-keystrokes"11415,347079 - DEFVAR_INT ("polling-period"11421,347350 - DEFVAR_LISP ("double-click-time"11428,347693 - DEFVAR_INT ("double-click-fuzz"11435,348029 - DEFVAR_INT ("num-input-keys"11446,348519 - DEFVAR_INT ("num-nonmacro-input-events"11452,348794 - DEFVAR_LISP ("last-event-frame"11457,349032 - DEFVAR_LISP ("tty-erase-char"11463,349311 - DEFVAR_LISP ("help-char"11466,349434 - DEFVAR_LISP ("help-event-list"11472,349717 - DEFVAR_LISP ("help-form"11477,349928 - DEFVAR_LISP ("prefix-help-command"11483,350176 - DEFVAR_LISP ("top-level"11489,350454 - DEFVAR_KBOARD ("keyboard-translate-table"11495,350675 - DEFVAR_BOOL ("cannot-suspend"11511,351488 - DEFVAR_BOOL ("menu-prompting"11516,351715 - DEFVAR_LISP ("menu-prompt-more-char"11526,352145 - DEFVAR_INT ("extra-keyboard-modifiers"11531,352391 - DEFVAR_LISP ("deactivate-mark"11545,353117 - DEFVAR_LISP ("pre-command-hook"11553,353486 - DEFVAR_LISP ("post-command-hook"11560,353841 - DEFVAR_LISP ("echo-area-clear-hook"11568,354204 - DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419 - DEFVAR_LISP ("menu-bar-final-items"11578,354622 - DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872 - DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230 - DEFVAR_LISP ("overriding-local-map"11598,355652 - DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103 - DEFVAR_LISP ("special-event-map"11613,356442 - DEFVAR_LISP ("track-mouse"11617,356630 - DEFVAR_KBOARD ("system-key-alist"11620,356757 - DEFVAR_KBOARD ("local-function-key-map"11629,357138 - DEFVAR_KBOARD ("input-decode-map"11658,358597 - DEFVAR_LISP ("function-key-map"11675,359385 - DEFVAR_LISP ("key-translation-map"11683,359801 - DEFVAR_LISP ("deferred-action-list"11689,360145 - DEFVAR_LISP ("deferred-action-function"11694,360393 - DEFVAR_LISP ("delayed-warnings-list"11700,360692 - DEFVAR_LISP ("timer-list"11708,361100 - DEFVAR_LISP ("timer-idle-list"11712,361252 - DEFVAR_LISP ("input-method-function"11716,361415 - DEFVAR_LISP ("input-method-previous-message"11737,362384 - DEFVAR_LISP ("show-help-function"11744,362745 - DEFVAR_LISP ("disable-point-adjustment"11749,362977 - DEFVAR_LISP ("global-disable-point-adjustment"11761,363527 - DEFVAR_LISP ("minibuffer-message-timeout"11770,363893 - DEFVAR_LISP ("throw-on-input"11775,364171 - DEFVAR_LISP ("command-error-function"11781,364422 - DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909 - DEFVAR_LISP ("select-active-regions"11798,365236 - DEFVAR_LISP ("saved-region-selection"11807,365628 - DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013 - DEFVAR_LISP ("debug-on-event"11825,366554 -keys_of_keyboard 11841,367115 -mark_kboards 11916,370434 - DEFVAR_LISP ("internal--top-level-message",\111058,333972 - DEFVAR_LISP ("last-command-event",\111312,342173 - DEFVAR_LISP ("last-nonmenu-event",\111315,342297 - DEFVAR_LISP ("last-input-event",\111321,342636 - DEFVAR_LISP ("unread-command-events",\111324,342730 - DEFVAR_LISP ("unread-post-input-method-events",\111332,343190 - DEFVAR_LISP ("unread-input-method-events",\111338,343529 - DEFVAR_LISP ("meta-prefix-char",\111346,343898 - DEFVAR_KBOARD ("last-command",\111351,344106 - DEFVAR_KBOARD ("real-last-command",\111368,344787 - DEFVAR_KBOARD ("last-repeatable-command",\111372,344973 - DEFVAR_LISP ("this-command",\111378,345261 - DEFVAR_LISP ("real-this-command",\111384,345498 - DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680 - DEFVAR_LISP ("this-original-command",\111396,346123 - DEFVAR_INT ("auto-save-interval",\111403,346520 - DEFVAR_LISP ("auto-save-timeout",\111408,346734 - DEFVAR_LISP ("echo-keystrokes",\111415,347079 - DEFVAR_INT ("polling-period",\111421,347350 - DEFVAR_LISP ("double-click-time",\111428,347693 - DEFVAR_INT ("double-click-fuzz",\111435,348029 - DEFVAR_INT ("num-input-keys",\111446,348519 - DEFVAR_INT ("num-nonmacro-input-events",\111452,348794 - DEFVAR_LISP ("last-event-frame",\111457,349032 - DEFVAR_LISP ("tty-erase-char",\111463,349311 - DEFVAR_LISP ("help-char",\111466,349434 - DEFVAR_LISP ("help-event-list",\111472,349717 - DEFVAR_LISP ("help-form",\111477,349928 - DEFVAR_LISP ("prefix-help-command",\111483,350176 - DEFVAR_LISP ("top-level",\111489,350454 - DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675 - DEFVAR_BOOL ("cannot-suspend",\111511,351488 - DEFVAR_BOOL ("menu-prompting",\111516,351715 - DEFVAR_LISP ("menu-prompt-more-char",\111526,352145 - DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391 - DEFVAR_LISP ("deactivate-mark",\111545,353117 - DEFVAR_LISP ("pre-command-hook",\111553,353486 - DEFVAR_LISP ("post-command-hook",\111560,353841 - DEFVAR_LISP ("echo-area-clear-hook",\111568,354204 - DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419 - DEFVAR_LISP ("menu-bar-final-items",\111578,354622 - DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872 - DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230 - DEFVAR_LISP ("overriding-local-map",\111598,355652 - DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103 - DEFVAR_LISP ("special-event-map",\111613,356442 - DEFVAR_LISP ("track-mouse",\111617,356630 - DEFVAR_KBOARD ("system-key-alist",\111620,356757 - DEFVAR_KBOARD ("local-function-key-map",\111629,357138 - DEFVAR_KBOARD ("input-decode-map",\111658,358597 - DEFVAR_LISP ("function-key-map",\111675,359385 - DEFVAR_LISP ("key-translation-map",\111683,359801 - DEFVAR_LISP ("deferred-action-list",\111689,360145 - DEFVAR_LISP ("deferred-action-function",\111694,360393 - DEFVAR_LISP ("delayed-warnings-list",\111700,360692 - DEFVAR_LISP ("timer-list",\111708,361100 - DEFVAR_LISP ("timer-idle-list",\111712,361252 - DEFVAR_LISP ("input-method-function",\111716,361415 - DEFVAR_LISP ("input-method-previous-message",\111737,362384 - DEFVAR_LISP ("show-help-function",\111744,362745 - DEFVAR_LISP ("disable-point-adjustment",\111749,362977 - DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527 - DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893 - DEFVAR_LISP ("throw-on-input",\111775,364171 - DEFVAR_LISP ("command-error-function",\111781,364422 - DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909 - DEFVAR_LISP ("select-active-regions",\111798,365236 - DEFVAR_LISP ("saved-region-selection",\111807,365628 - DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013 - DEFVAR_LISP ("debug-on-event",\111825,366554 +recursive_edit_unwind 804,25751 +any_kboard_state 817,26017 +single_kboard_state 838,26669 +not_single_kboard_state 848,26807 +struct kboard_stack858,27069 +static struct kboard_stack *kboard_stack;kboard_stack864,27142 +push_kboard 867,27190 +pop_kboard 879,27379 +temporarily_switch_to_single_kboard 914,28267 +record_single_kboard_state 943,29441 +restore_kboard_configuration 952,29625 +cmd_error 970,30081 +cmd_error_internal 1024,31514 +DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034 +DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034 +command_loop 1094,33920 +command_loop_2 1134,35139 +top_level_2 1146,35343 +top_level_1 1152,35421 +DEFUN ("top-level", Ftop_level,1164,35791 +DEFUN ("top-level", Ftop_level,top-level1164,35791 +user_error 1183,36292 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823 +tracking_off 1216,37285 +DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820 +DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820 +bool ignore_mouse_drag_p;1256,38396 +some_mouse_moved 1259,38445 +Lisp_Object last_undo_boundary;1287,39036 +command_loop_1 1294,39277 +read_menu_command 1649,50893 +adjust_point_for_property 1678,51621 +safe_run_hooks_1 1831,57343 +safe_run_hooks_error 1841,57573 +safe_run_hook_funcall 1878,58580 +safe_run_hooks 1893,59062 +int poll_suppress_count;1908,59401 +static struct atimer *poll_timer;poll_timer1915,59491 +poll_for_input_1 1919,59593 +poll_for_input 1930,59793 +start_polling 1942,60057 +input_polling_used 1979,61095 +stop_polling 1994,61394 +set_poll_suppress_count 2009,61763 +bind_polling_period 2029,62145 +make_ctrl_char 2048,62496 +show_help_echo 2113,64459 +static Lisp_Object help_form_saved_window_configs;2156,65642 +read_char_help_form_unwind 2158,65705 +#define STOP_POLLING 2166,65963 +#define RESUME_POLLING 2170,66088 +read_event_from_main_queue 2175,66233 +read_decoded_event_from_main_queue 2249,68421 +#define MAX_ENCODED_BYTES 2254,68668 +echo_keystrokes_p 2342,71560 +read_char 2376,72852 +record_menu_key 3225,98953 +help_char_p 3258,99678 +record_char 3273,99957 +save_getcjmp 3412,104239 +restore_getcjmp 3418,104330 +readable_events 3430,104701 +int stop_character EXTERNALLY_VISIBLE;3497,106441 +event_to_kboard 3500,106497 +kbd_buffer_nr_stored 3522,107146 +kbd_buffer_store_event 3534,107487 +kbd_buffer_store_event_hold 3550,108029 +kbd_buffer_unget_event 3684,111621 +#define INPUT_EVENT_POS_MAX 3698,112022 +#define INPUT_EVENT_POS_MIN 3701,112151 +position_to_Time 3706,112291 +Time_to_position 3716,112518 +gen_help_event 3738,113175 +kbd_buffer_store_help_event 3756,113615 +discard_mouse_events 3773,113980 +kbd_buffer_events_waiting 3803,114715 +clear_event 3823,115072 +kbd_buffer_get_event 3836,115412 +process_special_events 4258,127885 +swallow_events 4322,129709 +timer_start_idle 4339,130102 +timer_stop_idle 4355,130580 +timer_resume_idle 4363,130724 +struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916 +Lisp_Object pending_funcalls;4377,131176 +decode_timer 4381,131297 +timer_check_2 4414,132250 +timer_check 4572,136821 +DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666 +DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666 +static Lisp_Object accent_key_syms;4625,138243 +static Lisp_Object func_key_syms;4626,138279 +static Lisp_Object mouse_syms;4627,138313 +static Lisp_Object wheel_syms;4628,138344 +static Lisp_Object drag_n_drop_syms;4629,138375 +static const int lispy_accent_codes[lispy_accent_codes4634,138520 +static const char *const lispy_accent_keys[lispy_accent_keys4741,139882 +#define FUNCTION_KEY_OFFSET 4766,140318 +const char *const lispy_function_keys[lispy_function_keys4768,140351 +static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905 +static const char *const lispy_kana_keys[lispy_kana_keys5026,150139 +#define FUNCTION_KEY_OFFSET 5061,151755 +static const char *const lispy_function_keys[lispy_function_keys5065,151898 +#define ISO_FUNCTION_KEY_OFFSET 5149,154433 +static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473 +static Lisp_Object Vlispy_mouse_stem;5172,155332 +static const char *const lispy_wheel_names[lispy_wheel_names5174,155371 +static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623 +static short const scroll_bar_parts[scroll_bar_parts5189,155889 +static Lisp_Object button_down_location;5210,156914 +static int last_mouse_button;5215,157069 +static int last_mouse_x;5216,157099 +static int last_mouse_y;5217,157124 +static Time button_down_time;5218,157149 +static int double_click_count;5222,157233 +make_lispy_position 5228,157394 +toolkit_menubar_in_use 5456,163957 +make_scroll_bar_position 5469,164325 +make_lispy_event 5485,164971 +make_lispy_movement 6104,183534 +make_lispy_switch_frame 6131,184265 +make_lispy_focus_in 6137,184372 +make_lispy_focus_out 6145,184498 +parse_modifiers_uncached 6163,184948 +#define SINGLE_LETTER_MOD(6185,185468 +#undef SINGLE_LETTER_MOD6212,185909 +#define MULTI_LETTER_MOD(6214,185935 +#undef MULTI_LETTER_MOD6231,186403 +apply_modifiers_uncached 6273,187577 +static const char *const modifier_names[modifier_names6319,189196 +#define NUM_MOD_NAMES 6325,189402 +static Lisp_Object modifier_symbols;6327,189452 +lispy_modifier_list 6331,189589 +#define KEY_TO_CHAR(6353,190255 +parse_modifiers 6356,190331 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520 +apply_modifiers 6422,192394 +reorder_modifiers 6491,194723 +modify_event_symbol 6536,196531 +DEFUN ("event-convert-list", Fevent_convert_list,6628,199247 +DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247 +parse_solitary_modifier 6695,201138 +#define SINGLE_LETTER_MOD(6701,201261 +#define MULTI_LETTER_MOD(6705,201346 +#undef SINGLE_LETTER_MOD6763,202644 +#undef MULTI_LETTER_MOD6764,202669 +lucid_event_type_list_p 6775,202892 +get_input_pending 6814,203963 +record_asynch_buffer_change 6834,204582 +gobble_input 6872,205705 +tty_read_avail_input 6967,208313 +handle_async_input 7149,214042 +process_pending_signals 7165,214362 +unblock_input_to 7177,214648 +unblock_input 7200,215280 +totally_unblock_input 7209,215448 +handle_input_available_signal 7217,215532 +deliver_input_available_signal 7226,215703 +struct user_signal_info7235,215868 +static struct user_signal_info *user_signals user_signals7250,216093 +add_user_signal 7253,216152 +handle_user_signal 7275,216601 +deliver_user_signal 7316,217561 +find_user_signal_name 7322,217662 +store_user_signal_events 7334,217844 +static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419 +static Lisp_Object menu_bar_items_vector;7368,218633 +static int menu_bar_items_index;7369,218675 +static const char *separator_names[separator_names7372,218710 +menu_separator_name_p 7393,219151 +menu_bar_items 7426,219855 +Lisp_Object item_properties;7568,224606 +menu_bar_item 7571,224648 +menu_item_eval_property_1 7647,227178 +eval_dyn 7658,227468 +menu_item_eval_property 7666,227678 +parse_menu_item 7686,228344 +static Lisp_Object tool_bar_items_vector;7965,236339 +static Lisp_Object tool_bar_item_properties;7970,236513 +static int ntool_bar_items;7974,236609 +tool_bar_items 7990,237086 +process_tool_bar_item 8075,239895 +#define PROP(8112,240972 +set_prop 8114,241041 +parse_tool_bar_item 8167,242456 +#undef PROP8379,248847 +init_tool_bar_items 8387,248972 +append_tool_bar_item 8401,249264 +read_char_x_menu_prompt 8443,250774 +read_char_minibuf_menu_prompt 8503,252448 +#define PUSH_C_STR(8527,253017 +follow_key 8726,258556 +active_maps 8733,258698 +typedef struct keyremap8742,259024 +} keyremap;8754,259467 +access_keymap_keyremap 8764,259811 +keyremap_step 8811,261453 +test_undefined 8867,262937 +read_key_sequence 8916,264864 +read_key_sequence_vs 9826,295824 +DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297 +DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985 +detect_input_pending 9950,300491 +detect_input_pending_ignore_squeezables 9959,300657 +detect_input_pending_run_timers 9967,300873 +clear_input_pending 9985,301365 +requeued_events_pending_p 9997,301735 +DEFUN ("input-pending-p", Finput_pending_p,10002,301816 +DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816 +DEFUN ("recent-keys", Frecent_keys,10024,302599 +DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599 +DEFUN ("this-command-keys", Fthis_command_keys,10055,303520 +DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513 +DEFUN ("recursion-depth", Frecursion_depth,10158,307072 +DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072 +DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409 +DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409 +DEFUN ("discard-input", Fdiscard_input,10203,308450 +DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450 +DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952 +DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952 +stuff_buffered_input 10285,311048 +set_waiting_for_input 10323,312019 +clear_waiting_for_input 10337,312393 +handle_interrupt_signal 10351,312757 +deliver_interrupt_signal 10378,313645 +static int volatile force_quit_count;10387,313935 +handle_interrupt 10401,314417 +quit_throw_to_read_char 10541,318714 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291 +DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519 +DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435 +DEFUN ("set-quit-char", Fset_quit_char,10694,322709 +DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709 +DEFUN ("set-input-mode", Fset_input_mode,10729,323573 +DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573 +DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462 +DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462 +DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840 +DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840 +DEFUN ("posn-at-point", Fposn_at_point,10824,327063 +DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063 +init_kboard 10861,328217 +allocate_kboard 10893,329287 +wipe_kboard 10909,329640 +delete_kboard 10917,329754 +init_keyboard 10942,330284 +struct event_head11021,332699 +static const struct event_head head_table[head_table11027,332750 +syms_of_keyboard 11045,333580 + DEFVAR_LISP ("internal--top-level-message"11058,333975 + DEFVAR_LISP ("last-command-event"11312,342176 + DEFVAR_LISP ("last-nonmenu-event"11315,342300 + DEFVAR_LISP ("last-input-event"11321,342639 + DEFVAR_LISP ("unread-command-events"11324,342733 + DEFVAR_LISP ("unread-post-input-method-events"11332,343193 + DEFVAR_LISP ("unread-input-method-events"11338,343532 + DEFVAR_LISP ("meta-prefix-char"11346,343901 + DEFVAR_KBOARD ("last-command"11351,344109 + DEFVAR_KBOARD ("real-last-command"11368,344790 + DEFVAR_KBOARD ("last-repeatable-command"11372,344976 + DEFVAR_LISP ("this-command"11378,345264 + DEFVAR_LISP ("real-this-command"11384,345501 + DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683 + DEFVAR_LISP ("this-original-command"11396,346126 + DEFVAR_INT ("auto-save-interval"11403,346523 + DEFVAR_LISP ("auto-save-timeout"11408,346737 + DEFVAR_LISP ("echo-keystrokes"11415,347082 + DEFVAR_INT ("polling-period"11421,347353 + DEFVAR_LISP ("double-click-time"11428,347696 + DEFVAR_INT ("double-click-fuzz"11435,348032 + DEFVAR_INT ("num-input-keys"11446,348522 + DEFVAR_INT ("num-nonmacro-input-events"11452,348797 + DEFVAR_LISP ("last-event-frame"11457,349035 + DEFVAR_LISP ("tty-erase-char"11463,349314 + DEFVAR_LISP ("help-char"11466,349437 + DEFVAR_LISP ("help-event-list"11472,349720 + DEFVAR_LISP ("help-form"11477,349931 + DEFVAR_LISP ("prefix-help-command"11483,350179 + DEFVAR_LISP ("top-level"11489,350457 + DEFVAR_KBOARD ("keyboard-translate-table"11495,350678 + DEFVAR_BOOL ("cannot-suspend"11511,351491 + DEFVAR_BOOL ("menu-prompting"11516,351718 + DEFVAR_LISP ("menu-prompt-more-char"11526,352148 + DEFVAR_INT ("extra-keyboard-modifiers"11531,352394 + DEFVAR_LISP ("deactivate-mark"11545,353120 + DEFVAR_LISP ("pre-command-hook"11553,353489 + DEFVAR_LISP ("post-command-hook"11560,353844 + DEFVAR_LISP ("echo-area-clear-hook"11568,354207 + DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422 + DEFVAR_LISP ("menu-bar-final-items"11578,354625 + DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875 + DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233 + DEFVAR_LISP ("overriding-local-map"11598,355655 + DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106 + DEFVAR_LISP ("special-event-map"11613,356445 + DEFVAR_LISP ("track-mouse"11617,356633 + DEFVAR_KBOARD ("system-key-alist"11620,356760 + DEFVAR_KBOARD ("local-function-key-map"11629,357141 + DEFVAR_KBOARD ("input-decode-map"11658,358600 + DEFVAR_LISP ("function-key-map"11675,359388 + DEFVAR_LISP ("key-translation-map"11683,359804 + DEFVAR_LISP ("deferred-action-list"11689,360148 + DEFVAR_LISP ("deferred-action-function"11694,360396 + DEFVAR_LISP ("delayed-warnings-list"11700,360695 + DEFVAR_LISP ("timer-list"11708,361103 + DEFVAR_LISP ("timer-idle-list"11712,361255 + DEFVAR_LISP ("input-method-function"11716,361418 + DEFVAR_LISP ("input-method-previous-message"11737,362387 + DEFVAR_LISP ("show-help-function"11744,362748 + DEFVAR_LISP ("disable-point-adjustment"11749,362980 + DEFVAR_LISP ("global-disable-point-adjustment"11761,363530 + DEFVAR_LISP ("minibuffer-message-timeout"11770,363896 + DEFVAR_LISP ("throw-on-input"11775,364174 + DEFVAR_LISP ("command-error-function"11781,364425 + DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912 + DEFVAR_LISP ("select-active-regions"11798,365239 + DEFVAR_LISP ("saved-region-selection"11807,365631 + DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016 + DEFVAR_LISP ("debug-on-event"11825,366557 +keys_of_keyboard 11841,367118 +mark_kboards 11916,370437 + DEFVAR_LISP ("internal--top-level-message",\111058,333975 + DEFVAR_LISP ("last-command-event",\111312,342176 + DEFVAR_LISP ("last-nonmenu-event",\111315,342300 + DEFVAR_LISP ("last-input-event",\111321,342639 + DEFVAR_LISP ("unread-command-events",\111324,342733 + DEFVAR_LISP ("unread-post-input-method-events",\111332,343193 + DEFVAR_LISP ("unread-input-method-events",\111338,343532 + DEFVAR_LISP ("meta-prefix-char",\111346,343901 + DEFVAR_KBOARD ("last-command",\111351,344109 + DEFVAR_KBOARD ("real-last-command",\111368,344790 + DEFVAR_KBOARD ("last-repeatable-command",\111372,344976 + DEFVAR_LISP ("this-command",\111378,345264 + DEFVAR_LISP ("real-this-command",\111384,345501 + DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683 + DEFVAR_LISP ("this-original-command",\111396,346126 + DEFVAR_INT ("auto-save-interval",\111403,346523 + DEFVAR_LISP ("auto-save-timeout",\111408,346737 + DEFVAR_LISP ("echo-keystrokes",\111415,347082 + DEFVAR_INT ("polling-period",\111421,347353 + DEFVAR_LISP ("double-click-time",\111428,347696 + DEFVAR_INT ("double-click-fuzz",\111435,348032 + DEFVAR_INT ("num-input-keys",\111446,348522 + DEFVAR_INT ("num-nonmacro-input-events",\111452,348797 + DEFVAR_LISP ("last-event-frame",\111457,349035 + DEFVAR_LISP ("tty-erase-char",\111463,349314 + DEFVAR_LISP ("help-char",\111466,349437 + DEFVAR_LISP ("help-event-list",\111472,349720 + DEFVAR_LISP ("help-form",\111477,349931 + DEFVAR_LISP ("prefix-help-command",\111483,350179 + DEFVAR_LISP ("top-level",\111489,350457 + DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678 + DEFVAR_BOOL ("cannot-suspend",\111511,351491 + DEFVAR_BOOL ("menu-prompting",\111516,351718 + DEFVAR_LISP ("menu-prompt-more-char",\111526,352148 + DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394 + DEFVAR_LISP ("deactivate-mark",\111545,353120 + DEFVAR_LISP ("pre-command-hook",\111553,353489 + DEFVAR_LISP ("post-command-hook",\111560,353844 + DEFVAR_LISP ("echo-area-clear-hook",\111568,354207 + DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422 + DEFVAR_LISP ("menu-bar-final-items",\111578,354625 + DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875 + DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233 + DEFVAR_LISP ("overriding-local-map",\111598,355655 + DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106 + DEFVAR_LISP ("special-event-map",\111613,356445 + DEFVAR_LISP ("track-mouse",\111617,356633 + DEFVAR_KBOARD ("system-key-alist",\111620,356760 + DEFVAR_KBOARD ("local-function-key-map",\111629,357141 + DEFVAR_KBOARD ("input-decode-map",\111658,358600 + DEFVAR_LISP ("function-key-map",\111675,359388 + DEFVAR_LISP ("key-translation-map",\111683,359804 + DEFVAR_LISP ("deferred-action-list",\111689,360148 + DEFVAR_LISP ("deferred-action-function",\111694,360396 + DEFVAR_LISP ("delayed-warnings-list",\111700,360695 + DEFVAR_LISP ("timer-list",\111708,361103 + DEFVAR_LISP ("timer-idle-list",\111712,361255 + DEFVAR_LISP ("input-method-function",\111716,361418 + DEFVAR_LISP ("input-method-previous-message",\111737,362387 + DEFVAR_LISP ("show-help-function",\111744,362748 + DEFVAR_LISP ("disable-point-adjustment",\111749,362980 + DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530 + DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896 + DEFVAR_LISP ("throw-on-input",\111775,364174 + DEFVAR_LISP ("command-error-function",\111781,364425 + DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912 + DEFVAR_LISP ("select-active-regions",\111798,365239 + DEFVAR_LISP ("saved-region-selection",\111807,365631 + DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016 + DEFVAR_LISP ("debug-on-event",\111825,366557 c-src/emacs/src/lisp.h,20276 #define EMACS_LISP_H22,801 @@ -2328,109 +2328,109 @@ el-src/emacs/lisp/progmodes/etags.el,5069 (defcustom tags-tag-face 148,5700 (defcustom tags-apropos-verbose 154,5835 (defcustom tags-apropos-additional-actions 160,5999 -(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918 -(defvar default-tags-table-function 189,7098 -(defvar tags-location-ring 194,7324 -(defvar tags-table-files 201,7600 -(defvar tags-completion-table 206,7767 -(defvar tags-included-tables 209,7859 -(defvar next-file-list 212,7954 -(defvar tags-table-format-functions 217,8060 -(defvar file-of-tag-function 224,8441 -(defvar tags-table-files-function 228,8635 -(defvar tags-completion-table-function 230,8746 -(defvar snarf-tag-function 232,8841 -(defvar goto-tag-location-function 236,9050 -(defvar find-tag-regexp-search-function 239,9223 -(defvar find-tag-regexp-tag-order 241,9344 -(defvar find-tag-regexp-next-line-after-failure-p 243,9453 -(defvar find-tag-search-function 245,9573 -(defvar find-tag-tag-order 247,9680 -(defvar find-tag-next-line-after-failure-p 249,9775 -(defvar list-tags-function 251,9881 -(defvar tags-apropos-function 253,9969 -(defvar tags-included-tables-function 255,10063 -(defvar verify-tags-table-function 257,10182 -(defun initialize-new-tags-table 260,10293 -(defun tags-table-mode 276,10981 -(defun visit-tags-table 285,11246 -(defun tags-table-check-computed-list 321,12784 -(defun tags-table-extend-computed-list 360,14655 -(defun tags-expand-table-name 400,16368 -(defun tags-table-list-member 409,16711 -(defun tags-verify-table 421,17183 -(defun tags-table-including 470,19303 -(defun tags-next-table 522,21347 -(defun visit-tags-table-buffer 543,22204 -(defun tags-reset-tags-tables 712,28514 -(defun file-of-tag 731,29171 -(defun tags-table-files 740,29521 -(defun tags-included-tables 749,29871 -(defun tags-completion-table 755,30117 -(defun tags-lazy-completion-table 783,31311 -(defun tags-completion-at-point-function 799,31946 -(defun find-tag-tag 818,32696 -(defvar last-tag 837,33369 -(defun find-tag-interactive 840,33428 -(defvar find-tag-history 852,33843 -(defun find-tag-noselect 860,34013 -(defun find-tag 932,37127 -(defun find-tag-other-window 959,38343 -(defun find-tag-other-frame 1000,40271 -(defun find-tag-regexp 1025,41445 -(defalias 'pop-tag-mark pop-tag-mark1049,42607 -(defvar tag-lines-already-matched 1052,42658 -(defun find-tag-in-order 1055,42765 -(defun tag-find-file-of-tag-noselect 1167,47111 -(defun tag-find-file-of-tag 1200,48957 -(defun etags-recognize-tags-table 1208,49183 -(defun etags-verify-tags-table 1241,50814 -(defun etags-file-of-tag 1246,51012 -(defun etags-tags-completion-table 1256,51347 -(defun etags-snarf-tag 1286,52553 -(defun etags-goto-tag-location 1324,54122 -(defun etags-list-tags 1388,56565 -(defmacro tags-with-face 1423,57840 -(defun etags-tags-apropos-additional 1431,58173 -(defun etags-tags-apropos 1465,59410 -(defun etags-tags-table-files 1527,61619 -(defun etags-tags-included-tables 1542,62055 -(defun tags-recognize-empty-tags-table 1559,62595 -(defun tag-exact-file-name-match-p 1587,63741 -(defun tag-file-name-match-p 1596,64134 -(defun tag-exact-match-p 1609,64690 -(defun tag-implicit-name-match-p 1620,65258 -(defun tag-symbol-match-p 1633,65858 -(defun tag-word-match-p 1643,66294 -(defun tag-partial-file-name-match-p 1652,66692 -(defun tag-any-match-p 1662,67136 -(defun tag-re-match-p 1667,67320 -(defcustom tags-loop-revert-buffers 1675,67569 -(defun next-file 1685,67978 -(defvar tags-loop-operate 1760,70892 -(defvar tags-loop-scan1763,70986 -(defun tags-loop-eval 1771,71315 -(defun tags-loop-continue 1782,71644 -(defun tags-search 1850,73950 -(defun tags-query-replace 1871,74776 -(defun tags-complete-tags-table-file 1896,76000 -(defun list-tags 1906,76379 -(defun tags-apropos 1934,77332 -(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158 -(defun select-tags-table 1964,78397 -(defvar select-tags-table-mode-map 2019,80524 -(define-derived-mode select-tags-table-mode 2030,80907 -(defun select-tags-table-select 2034,81091 -(defun select-tags-table-quit 2043,81457 -(defun complete-tag 2049,81612 -(defconst etags--xref-limit 2074,82553 -(defvar etags-xref-find-definitions-tag-order 2076,82588 -(defun etags-xref-find 2082,82878 -(defun etags--xref-find-definitions 2096,83407 -(defclass xref-etags-location 2129,85121 -(defun xref-make-etags-location 2135,85344 -(cl-defmethod xref-location-marker 2139,85499 -(cl-defmethod xref-location-line 2146,85743 +(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921 +(defvar default-tags-table-function 189,7101 +(defvar tags-location-ring 194,7327 +(defvar tags-table-files 201,7603 +(defvar tags-completion-table 206,7770 +(defvar tags-included-tables 209,7862 +(defvar next-file-list 212,7957 +(defvar tags-table-format-functions 217,8063 +(defvar file-of-tag-function 224,8444 +(defvar tags-table-files-function 228,8638 +(defvar tags-completion-table-function 230,8749 +(defvar snarf-tag-function 232,8844 +(defvar goto-tag-location-function 236,9053 +(defvar find-tag-regexp-search-function 239,9226 +(defvar find-tag-regexp-tag-order 241,9347 +(defvar find-tag-regexp-next-line-after-failure-p 243,9456 +(defvar find-tag-search-function 245,9576 +(defvar find-tag-tag-order 247,9683 +(defvar find-tag-next-line-after-failure-p 249,9778 +(defvar list-tags-function 251,9884 +(defvar tags-apropos-function 253,9972 +(defvar tags-included-tables-function 255,10066 +(defvar verify-tags-table-function 257,10185 +(defun initialize-new-tags-table 260,10296 +(defun tags-table-mode 276,10984 +(defun visit-tags-table 285,11249 +(defun tags-table-check-computed-list 321,12787 +(defun tags-table-extend-computed-list 360,14658 +(defun tags-expand-table-name 400,16371 +(defun tags-table-list-member 409,16714 +(defun tags-verify-table 421,17186 +(defun tags-table-including 470,19306 +(defun tags-next-table 522,21350 +(defun visit-tags-table-buffer 543,22207 +(defun tags-reset-tags-tables 712,28517 +(defun file-of-tag 731,29174 +(defun tags-table-files 740,29524 +(defun tags-included-tables 749,29874 +(defun tags-completion-table 755,30120 +(defun tags-lazy-completion-table 783,31314 +(defun tags-completion-at-point-function 799,31949 +(defun find-tag-tag 818,32699 +(defvar last-tag 837,33372 +(defun find-tag-interactive 840,33431 +(defvar find-tag-history 852,33846 +(defun find-tag-noselect 860,34016 +(defun find-tag 932,37130 +(defun find-tag-other-window 959,38346 +(defun find-tag-other-frame 1000,40274 +(defun find-tag-regexp 1025,41448 +(defalias 'pop-tag-mark pop-tag-mark1049,42610 +(defvar tag-lines-already-matched 1052,42661 +(defun find-tag-in-order 1055,42768 +(defun tag-find-file-of-tag-noselect 1167,47114 +(defun tag-find-file-of-tag 1200,48960 +(defun etags-recognize-tags-table 1208,49186 +(defun etags-verify-tags-table 1241,50817 +(defun etags-file-of-tag 1246,51015 +(defun etags-tags-completion-table 1256,51350 +(defun etags-snarf-tag 1286,52556 +(defun etags-goto-tag-location 1324,54125 +(defun etags-list-tags 1388,56568 +(defmacro tags-with-face 1423,57843 +(defun etags-tags-apropos-additional 1431,58176 +(defun etags-tags-apropos 1465,59413 +(defun etags-tags-table-files 1527,61622 +(defun etags-tags-included-tables 1542,62058 +(defun tags-recognize-empty-tags-table 1559,62598 +(defun tag-exact-file-name-match-p 1587,63744 +(defun tag-file-name-match-p 1596,64137 +(defun tag-exact-match-p 1609,64693 +(defun tag-implicit-name-match-p 1620,65261 +(defun tag-symbol-match-p 1633,65861 +(defun tag-word-match-p 1643,66297 +(defun tag-partial-file-name-match-p 1652,66695 +(defun tag-any-match-p 1662,67139 +(defun tag-re-match-p 1667,67323 +(defcustom tags-loop-revert-buffers 1675,67572 +(defun next-file 1685,67981 +(defvar tags-loop-operate 1760,70895 +(defvar tags-loop-scan1763,70989 +(defun tags-loop-eval 1771,71318 +(defun tags-loop-continue 1782,71647 +(defun tags-search 1850,73953 +(defun tags-query-replace 1871,74779 +(defun tags-complete-tags-table-file 1896,76003 +(defun list-tags 1906,76382 +(defun tags-apropos 1934,77335 +(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161 +(defun select-tags-table 1964,78400 +(defvar select-tags-table-mode-map 2019,80527 +(define-derived-mode select-tags-table-mode 2030,80910 +(defun select-tags-table-select 2034,81094 +(defun select-tags-table-quit 2043,81460 +(defun complete-tag 2049,81615 +(defconst etags--xref-limit 2074,82556 +(defvar etags-xref-find-definitions-tag-order 2076,82591 +(defun etags-xref-find 2082,82881 +(defun etags--xref-find-definitions 2096,83410 +(defclass xref-etags-location 2129,85124 +(defun xref-make-etags-location 2135,85347 +(cl-defmethod xref-location-marker 2139,85502 +(cl-defmethod xref-location-line 2146,85746 erl-src/gs_dialog.erl,98 -define(VERSION2,32 diff --git a/test/manual/etags/ETAGS.good_5 b/test/manual/etags/ETAGS.good_5 index 6d2e44fbfe..6410685cb3 100644 --- a/test/manual/etags/ETAGS.good_5 +++ b/test/manual/etags/ETAGS.good_5 @@ -1234,440 +1234,440 @@ record_auto_save 742,23849 force_auto_save_soon 751,24017 DEFUN ("recursive-edit", Frecursive_edit,759,24138 DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138 -recursive_edit_unwind 804,25748 -any_kboard_state 817,26014 -single_kboard_state 838,26666 -not_single_kboard_state 848,26804 -struct kboard_stack858,27066 - KBOARD *kboard;kboard860,27088 - struct kboard_stack *next;next861,27106 -static struct kboard_stack *kboard_stack;kboard_stack864,27139 -push_kboard 867,27187 -pop_kboard 879,27376 -temporarily_switch_to_single_kboard 914,28264 -record_single_kboard_state 943,29438 -restore_kboard_configuration 952,29622 -cmd_error 970,30078 -cmd_error_internal 1024,31511 -DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031 -DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031 -static Lisp_Object command_loop_2 1086,33638 -static Lisp_Object top_level_1 1087,33687 -command_loop 1094,33917 -command_loop_2 1134,35136 -top_level_2 1146,35340 -top_level_1 1152,35418 -DEFUN ("top-level", Ftop_level,1164,35788 -DEFUN ("top-level", Ftop_level,top-level1164,35788 -user_error 1183,36289 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820 -tracking_off 1216,37282 -DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817 -DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817 -bool ignore_mouse_drag_p;1256,38393 -some_mouse_moved 1259,38442 -static int read_key_sequence 1282,38800 -static void adjust_point_for_property 1284,38918 -Lisp_Object last_undo_boundary;1287,39033 -command_loop_1 1294,39274 -read_menu_command 1649,50890 -adjust_point_for_property 1678,51618 -safe_run_hooks_1 1831,57340 -safe_run_hooks_error 1841,57570 -safe_run_hook_funcall 1878,58577 -safe_run_hooks 1893,59059 -int poll_suppress_count;1908,59398 -static struct atimer *poll_timer;poll_timer1915,59488 -poll_for_input_1 1919,59590 -poll_for_input 1930,59790 -start_polling 1942,60054 -input_polling_used 1979,61092 -stop_polling 1994,61391 -set_poll_suppress_count 2009,61760 -bind_polling_period 2029,62142 -make_ctrl_char 2048,62493 -show_help_echo 2113,64456 -static Lisp_Object kbd_buffer_get_event 2152,65485 -static void record_char 2154,65597 -static Lisp_Object help_form_saved_window_configs;2156,65639 -read_char_help_form_unwind 2158,65702 -#define STOP_POLLING 2166,65960 -#define RESUME_POLLING 2170,66085 -read_event_from_main_queue 2175,66230 -read_decoded_event_from_main_queue 2249,68418 -#define MAX_ENCODED_BYTES 2254,68665 -echo_keystrokes_p 2342,71557 -read_char 2376,72849 -record_menu_key 3225,98950 -help_char_p 3258,99675 -record_char 3273,99954 -save_getcjmp 3412,104236 -restore_getcjmp 3418,104327 -readable_events 3430,104698 -int stop_character EXTERNALLY_VISIBLE;3497,106438 -event_to_kboard 3500,106494 -kbd_buffer_nr_stored 3522,107143 -kbd_buffer_store_event 3534,107484 -kbd_buffer_store_event_hold 3550,108026 -kbd_buffer_unget_event 3684,111618 -#define INPUT_EVENT_POS_MAX 3698,112019 -#define INPUT_EVENT_POS_MIN 3701,112148 -position_to_Time 3706,112288 -Time_to_position 3716,112515 -gen_help_event 3738,113172 -kbd_buffer_store_help_event 3756,113612 -discard_mouse_events 3773,113977 -kbd_buffer_events_waiting 3803,114712 -clear_event 3823,115069 -kbd_buffer_get_event 3836,115409 -process_special_events 4258,127882 -swallow_events 4322,129706 -timer_start_idle 4339,130099 -timer_stop_idle 4355,130577 -timer_resume_idle 4363,130721 -struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913 -Lisp_Object pending_funcalls;4377,131173 -decode_timer 4381,131294 -timer_check_2 4414,132247 -timer_check 4572,136818 -DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663 -DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663 -static Lisp_Object accent_key_syms;4625,138240 -static Lisp_Object func_key_syms;4626,138276 -static Lisp_Object mouse_syms;4627,138310 -static Lisp_Object wheel_syms;4628,138341 -static Lisp_Object drag_n_drop_syms;4629,138372 -static const int lispy_accent_codes[lispy_accent_codes4634,138517 -static const char *const lispy_accent_keys[lispy_accent_keys4741,139879 -#define FUNCTION_KEY_OFFSET 4766,140315 -const char *const lispy_function_keys[lispy_function_keys4768,140348 -static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902 -static const char *const lispy_kana_keys[lispy_kana_keys5026,150136 -#define FUNCTION_KEY_OFFSET 5061,151752 -static const char *const lispy_function_keys[lispy_function_keys5065,151895 -#define ISO_FUNCTION_KEY_OFFSET 5149,154430 -static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470 -static Lisp_Object Vlispy_mouse_stem;5172,155329 -static const char *const lispy_wheel_names[lispy_wheel_names5174,155368 -static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620 -static short const scroll_bar_parts[scroll_bar_parts5189,155886 -static Lisp_Object button_down_location;5210,156911 -static int last_mouse_button;5215,157066 -static int last_mouse_x;5216,157096 -static int last_mouse_y;5217,157121 -static Time button_down_time;5218,157146 -static int double_click_count;5222,157230 -make_lispy_position 5228,157391 -toolkit_menubar_in_use 5456,163954 -make_scroll_bar_position 5469,164322 -make_lispy_event 5485,164968 -make_lispy_movement 6104,183531 -make_lispy_switch_frame 6131,184262 -make_lispy_focus_in 6137,184369 -make_lispy_focus_out 6145,184495 -parse_modifiers_uncached 6163,184945 -#define SINGLE_LETTER_MOD(6185,185465 -#undef SINGLE_LETTER_MOD6212,185906 -#define MULTI_LETTER_MOD(6214,185932 -#undef MULTI_LETTER_MOD6231,186400 -apply_modifiers_uncached 6273,187574 -static const char *const modifier_names[modifier_names6319,189193 -#define NUM_MOD_NAMES 6325,189399 -static Lisp_Object modifier_symbols;6327,189449 -lispy_modifier_list 6331,189586 -#define KEY_TO_CHAR(6353,190252 -parse_modifiers 6356,190328 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517 -apply_modifiers 6422,192391 -reorder_modifiers 6491,194720 -modify_event_symbol 6536,196528 -DEFUN ("event-convert-list", Fevent_convert_list,6628,199244 -DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244 -parse_solitary_modifier 6695,201135 -#define SINGLE_LETTER_MOD(6701,201258 -#define MULTI_LETTER_MOD(6705,201343 -#undef SINGLE_LETTER_MOD6763,202641 -#undef MULTI_LETTER_MOD6764,202666 -lucid_event_type_list_p 6775,202889 -get_input_pending 6814,203960 -record_asynch_buffer_change 6834,204579 -gobble_input 6872,205702 -tty_read_avail_input 6967,208310 -handle_async_input 7149,214039 -process_pending_signals 7165,214359 -unblock_input_to 7177,214645 -unblock_input 7200,215277 -totally_unblock_input 7209,215445 -handle_input_available_signal 7217,215529 -deliver_input_available_signal 7226,215700 -struct user_signal_info7235,215865 - int sig;7238,215915 - char *name;name7241,215956 - int npending;7244,216007 - struct user_signal_info *next;next7246,216024 -static struct user_signal_info *user_signals user_signals7250,216090 -add_user_signal 7253,216149 -handle_user_signal 7275,216598 -deliver_user_signal 7316,217558 -find_user_signal_name 7322,217659 -store_user_signal_events 7334,217841 -static void menu_bar_item 7362,218341 -static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416 -static Lisp_Object menu_bar_items_vector;7368,218630 -static int menu_bar_items_index;7369,218672 -static const char *separator_names[separator_names7372,218707 -menu_separator_name_p 7393,219148 -menu_bar_items 7426,219852 -Lisp_Object item_properties;7568,224603 -menu_bar_item 7571,224645 -menu_item_eval_property_1 7647,227175 -eval_dyn 7658,227465 -menu_item_eval_property 7666,227675 -parse_menu_item 7686,228341 -static Lisp_Object tool_bar_items_vector;7965,236336 -static Lisp_Object tool_bar_item_properties;7970,236510 -static int ntool_bar_items;7974,236606 -static void init_tool_bar_items 7978,236664 -static void process_tool_bar_item 7979,236711 -static bool parse_tool_bar_item 7981,236801 -static void append_tool_bar_item 7982,236861 -tool_bar_items 7990,237083 -process_tool_bar_item 8075,239892 -#define PROP(8112,240969 -set_prop 8114,241038 -parse_tool_bar_item 8167,242453 -#undef PROP8379,248844 -init_tool_bar_items 8387,248969 -append_tool_bar_item 8401,249261 -read_char_x_menu_prompt 8443,250771 -read_char_minibuf_menu_prompt 8503,252445 -#define PUSH_C_STR(8527,253014 -follow_key 8726,258553 -active_maps 8733,258695 -typedef struct keyremap8742,259021 - Lisp_Object parent;8745,259107 - Lisp_Object map;8748,259224 - int start,8753,259446 - int start, end;8753,259446 -} keyremap;8754,259464 -access_keymap_keyremap 8764,259808 -keyremap_step 8811,261450 -test_undefined 8867,262934 -read_key_sequence 8916,264861 -read_key_sequence_vs 9826,295821 -DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294 -DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982 -detect_input_pending 9950,300488 -detect_input_pending_ignore_squeezables 9959,300654 -detect_input_pending_run_timers 9967,300870 -clear_input_pending 9985,301362 -requeued_events_pending_p 9997,301732 -DEFUN ("input-pending-p", Finput_pending_p,10002,301813 -DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813 -DEFUN ("recent-keys", Frecent_keys,10024,302596 -DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596 -DEFUN ("this-command-keys", Fthis_command_keys,10055,303517 -DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510 -DEFUN ("recursion-depth", Frecursion_depth,10158,307069 -DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069 -DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406 -DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406 -DEFUN ("discard-input", Fdiscard_input,10203,308447 -DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447 -DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949 -DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949 -stuff_buffered_input 10285,311045 -set_waiting_for_input 10323,312016 -clear_waiting_for_input 10337,312390 -handle_interrupt_signal 10351,312754 -deliver_interrupt_signal 10378,313642 -static int volatile force_quit_count;10387,313932 -handle_interrupt 10401,314414 -quit_throw_to_read_char 10541,318711 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288 -DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516 -DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432 -DEFUN ("set-quit-char", Fset_quit_char,10694,322706 -DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706 -DEFUN ("set-input-mode", Fset_input_mode,10729,323570 -DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570 -DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459 -DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459 -DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837 -DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837 -DEFUN ("posn-at-point", Fposn_at_point,10824,327060 -DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060 -init_kboard 10861,328214 -allocate_kboard 10893,329284 -wipe_kboard 10909,329637 -delete_kboard 10917,329751 -init_keyboard 10942,330281 -struct event_head11021,332696 - short var;11023,332716 - short kind;11024,332729 -static const struct event_head head_table[head_table11027,332747 -syms_of_keyboard 11045,333577 - DEFVAR_LISP ("internal--top-level-message"11058,333972 - DEFVAR_LISP ("last-command-event"11312,342173 - DEFVAR_LISP ("last-nonmenu-event"11315,342297 - DEFVAR_LISP ("last-input-event"11321,342636 - DEFVAR_LISP ("unread-command-events"11324,342730 - DEFVAR_LISP ("unread-post-input-method-events"11332,343190 - DEFVAR_LISP ("unread-input-method-events"11338,343529 - DEFVAR_LISP ("meta-prefix-char"11346,343898 - DEFVAR_KBOARD ("last-command"11351,344106 - DEFVAR_KBOARD ("real-last-command"11368,344787 - DEFVAR_KBOARD ("last-repeatable-command"11372,344973 - DEFVAR_LISP ("this-command"11378,345261 - DEFVAR_LISP ("real-this-command"11384,345498 - DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680 - DEFVAR_LISP ("this-original-command"11396,346123 - DEFVAR_INT ("auto-save-interval"11403,346520 - DEFVAR_LISP ("auto-save-timeout"11408,346734 - DEFVAR_LISP ("echo-keystrokes"11415,347079 - DEFVAR_INT ("polling-period"11421,347350 - DEFVAR_LISP ("double-click-time"11428,347693 - DEFVAR_INT ("double-click-fuzz"11435,348029 - DEFVAR_INT ("num-input-keys"11446,348519 - DEFVAR_INT ("num-nonmacro-input-events"11452,348794 - DEFVAR_LISP ("last-event-frame"11457,349032 - DEFVAR_LISP ("tty-erase-char"11463,349311 - DEFVAR_LISP ("help-char"11466,349434 - DEFVAR_LISP ("help-event-list"11472,349717 - DEFVAR_LISP ("help-form"11477,349928 - DEFVAR_LISP ("prefix-help-command"11483,350176 - DEFVAR_LISP ("top-level"11489,350454 - DEFVAR_KBOARD ("keyboard-translate-table"11495,350675 - DEFVAR_BOOL ("cannot-suspend"11511,351488 - DEFVAR_BOOL ("menu-prompting"11516,351715 - DEFVAR_LISP ("menu-prompt-more-char"11526,352145 - DEFVAR_INT ("extra-keyboard-modifiers"11531,352391 - DEFVAR_LISP ("deactivate-mark"11545,353117 - DEFVAR_LISP ("pre-command-hook"11553,353486 - DEFVAR_LISP ("post-command-hook"11560,353841 - DEFVAR_LISP ("echo-area-clear-hook"11568,354204 - DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419 - DEFVAR_LISP ("menu-bar-final-items"11578,354622 - DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872 - DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230 - DEFVAR_LISP ("overriding-local-map"11598,355652 - DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103 - DEFVAR_LISP ("special-event-map"11613,356442 - DEFVAR_LISP ("track-mouse"11617,356630 - DEFVAR_KBOARD ("system-key-alist"11620,356757 - DEFVAR_KBOARD ("local-function-key-map"11629,357138 - DEFVAR_KBOARD ("input-decode-map"11658,358597 - DEFVAR_LISP ("function-key-map"11675,359385 - DEFVAR_LISP ("key-translation-map"11683,359801 - DEFVAR_LISP ("deferred-action-list"11689,360145 - DEFVAR_LISP ("deferred-action-function"11694,360393 - DEFVAR_LISP ("delayed-warnings-list"11700,360692 - DEFVAR_LISP ("timer-list"11708,361100 - DEFVAR_LISP ("timer-idle-list"11712,361252 - DEFVAR_LISP ("input-method-function"11716,361415 - DEFVAR_LISP ("input-method-previous-message"11737,362384 - DEFVAR_LISP ("show-help-function"11744,362745 - DEFVAR_LISP ("disable-point-adjustment"11749,362977 - DEFVAR_LISP ("global-disable-point-adjustment"11761,363527 - DEFVAR_LISP ("minibuffer-message-timeout"11770,363893 - DEFVAR_LISP ("throw-on-input"11775,364171 - DEFVAR_LISP ("command-error-function"11781,364422 - DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909 - DEFVAR_LISP ("select-active-regions"11798,365236 - DEFVAR_LISP ("saved-region-selection"11807,365628 - DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013 - DEFVAR_LISP ("debug-on-event"11825,366554 -keys_of_keyboard 11841,367115 -mark_kboards 11916,370434 - DEFVAR_LISP ("internal--top-level-message",\111058,333972 - DEFVAR_LISP ("last-command-event",\111312,342173 - DEFVAR_LISP ("last-nonmenu-event",\111315,342297 - DEFVAR_LISP ("last-input-event",\111321,342636 - DEFVAR_LISP ("unread-command-events",\111324,342730 - DEFVAR_LISP ("unread-post-input-method-events",\111332,343190 - DEFVAR_LISP ("unread-input-method-events",\111338,343529 - DEFVAR_LISP ("meta-prefix-char",\111346,343898 - DEFVAR_KBOARD ("last-command",\111351,344106 - DEFVAR_KBOARD ("real-last-command",\111368,344787 - DEFVAR_KBOARD ("last-repeatable-command",\111372,344973 - DEFVAR_LISP ("this-command",\111378,345261 - DEFVAR_LISP ("real-this-command",\111384,345498 - DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680 - DEFVAR_LISP ("this-original-command",\111396,346123 - DEFVAR_INT ("auto-save-interval",\111403,346520 - DEFVAR_LISP ("auto-save-timeout",\111408,346734 - DEFVAR_LISP ("echo-keystrokes",\111415,347079 - DEFVAR_INT ("polling-period",\111421,347350 - DEFVAR_LISP ("double-click-time",\111428,347693 - DEFVAR_INT ("double-click-fuzz",\111435,348029 - DEFVAR_INT ("num-input-keys",\111446,348519 - DEFVAR_INT ("num-nonmacro-input-events",\111452,348794 - DEFVAR_LISP ("last-event-frame",\111457,349032 - DEFVAR_LISP ("tty-erase-char",\111463,349311 - DEFVAR_LISP ("help-char",\111466,349434 - DEFVAR_LISP ("help-event-list",\111472,349717 - DEFVAR_LISP ("help-form",\111477,349928 - DEFVAR_LISP ("prefix-help-command",\111483,350176 - DEFVAR_LISP ("top-level",\111489,350454 - DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675 - DEFVAR_BOOL ("cannot-suspend",\111511,351488 - DEFVAR_BOOL ("menu-prompting",\111516,351715 - DEFVAR_LISP ("menu-prompt-more-char",\111526,352145 - DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391 - DEFVAR_LISP ("deactivate-mark",\111545,353117 - DEFVAR_LISP ("pre-command-hook",\111553,353486 - DEFVAR_LISP ("post-command-hook",\111560,353841 - DEFVAR_LISP ("echo-area-clear-hook",\111568,354204 - DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419 - DEFVAR_LISP ("menu-bar-final-items",\111578,354622 - DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872 - DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230 - DEFVAR_LISP ("overriding-local-map",\111598,355652 - DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103 - DEFVAR_LISP ("special-event-map",\111613,356442 - DEFVAR_LISP ("track-mouse",\111617,356630 - DEFVAR_KBOARD ("system-key-alist",\111620,356757 - DEFVAR_KBOARD ("local-function-key-map",\111629,357138 - DEFVAR_KBOARD ("input-decode-map",\111658,358597 - DEFVAR_LISP ("function-key-map",\111675,359385 - DEFVAR_LISP ("key-translation-map",\111683,359801 - DEFVAR_LISP ("deferred-action-list",\111689,360145 - DEFVAR_LISP ("deferred-action-function",\111694,360393 - DEFVAR_LISP ("delayed-warnings-list",\111700,360692 - DEFVAR_LISP ("timer-list",\111708,361100 - DEFVAR_LISP ("timer-idle-list",\111712,361252 - DEFVAR_LISP ("input-method-function",\111716,361415 - DEFVAR_LISP ("input-method-previous-message",\111737,362384 - DEFVAR_LISP ("show-help-function",\111744,362745 - DEFVAR_LISP ("disable-point-adjustment",\111749,362977 - DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527 - DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893 - DEFVAR_LISP ("throw-on-input",\111775,364171 - DEFVAR_LISP ("command-error-function",\111781,364422 - DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909 - DEFVAR_LISP ("select-active-regions",\111798,365236 - DEFVAR_LISP ("saved-region-selection",\111807,365628 - DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013 - DEFVAR_LISP ("debug-on-event",\111825,366554 +recursive_edit_unwind 804,25751 +any_kboard_state 817,26017 +single_kboard_state 838,26669 +not_single_kboard_state 848,26807 +struct kboard_stack858,27069 + KBOARD *kboard;kboard860,27091 + struct kboard_stack *next;next861,27109 +static struct kboard_stack *kboard_stack;kboard_stack864,27142 +push_kboard 867,27190 +pop_kboard 879,27379 +temporarily_switch_to_single_kboard 914,28267 +record_single_kboard_state 943,29441 +restore_kboard_configuration 952,29625 +cmd_error 970,30081 +cmd_error_internal 1024,31514 +DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034 +DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034 +static Lisp_Object command_loop_2 1086,33641 +static Lisp_Object top_level_1 1087,33690 +command_loop 1094,33920 +command_loop_2 1134,35139 +top_level_2 1146,35343 +top_level_1 1152,35421 +DEFUN ("top-level", Ftop_level,1164,35791 +DEFUN ("top-level", Ftop_level,top-level1164,35791 +user_error 1183,36292 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823 +tracking_off 1216,37285 +DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820 +DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820 +bool ignore_mouse_drag_p;1256,38396 +some_mouse_moved 1259,38445 +static int read_key_sequence 1282,38803 +static void adjust_point_for_property 1284,38921 +Lisp_Object last_undo_boundary;1287,39036 +command_loop_1 1294,39277 +read_menu_command 1649,50893 +adjust_point_for_property 1678,51621 +safe_run_hooks_1 1831,57343 +safe_run_hooks_error 1841,57573 +safe_run_hook_funcall 1878,58580 +safe_run_hooks 1893,59062 +int poll_suppress_count;1908,59401 +static struct atimer *poll_timer;poll_timer1915,59491 +poll_for_input_1 1919,59593 +poll_for_input 1930,59793 +start_polling 1942,60057 +input_polling_used 1979,61095 +stop_polling 1994,61394 +set_poll_suppress_count 2009,61763 +bind_polling_period 2029,62145 +make_ctrl_char 2048,62496 +show_help_echo 2113,64459 +static Lisp_Object kbd_buffer_get_event 2152,65488 +static void record_char 2154,65600 +static Lisp_Object help_form_saved_window_configs;2156,65642 +read_char_help_form_unwind 2158,65705 +#define STOP_POLLING 2166,65963 +#define RESUME_POLLING 2170,66088 +read_event_from_main_queue 2175,66233 +read_decoded_event_from_main_queue 2249,68421 +#define MAX_ENCODED_BYTES 2254,68668 +echo_keystrokes_p 2342,71560 +read_char 2376,72852 +record_menu_key 3225,98953 +help_char_p 3258,99678 +record_char 3273,99957 +save_getcjmp 3412,104239 +restore_getcjmp 3418,104330 +readable_events 3430,104701 +int stop_character EXTERNALLY_VISIBLE;3497,106441 +event_to_kboard 3500,106497 +kbd_buffer_nr_stored 3522,107146 +kbd_buffer_store_event 3534,107487 +kbd_buffer_store_event_hold 3550,108029 +kbd_buffer_unget_event 3684,111621 +#define INPUT_EVENT_POS_MAX 3698,112022 +#define INPUT_EVENT_POS_MIN 3701,112151 +position_to_Time 3706,112291 +Time_to_position 3716,112518 +gen_help_event 3738,113175 +kbd_buffer_store_help_event 3756,113615 +discard_mouse_events 3773,113980 +kbd_buffer_events_waiting 3803,114715 +clear_event 3823,115072 +kbd_buffer_get_event 3836,115412 +process_special_events 4258,127885 +swallow_events 4322,129709 +timer_start_idle 4339,130102 +timer_stop_idle 4355,130580 +timer_resume_idle 4363,130724 +struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916 +Lisp_Object pending_funcalls;4377,131176 +decode_timer 4381,131297 +timer_check_2 4414,132250 +timer_check 4572,136821 +DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666 +DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666 +static Lisp_Object accent_key_syms;4625,138243 +static Lisp_Object func_key_syms;4626,138279 +static Lisp_Object mouse_syms;4627,138313 +static Lisp_Object wheel_syms;4628,138344 +static Lisp_Object drag_n_drop_syms;4629,138375 +static const int lispy_accent_codes[lispy_accent_codes4634,138520 +static const char *const lispy_accent_keys[lispy_accent_keys4741,139882 +#define FUNCTION_KEY_OFFSET 4766,140318 +const char *const lispy_function_keys[lispy_function_keys4768,140351 +static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905 +static const char *const lispy_kana_keys[lispy_kana_keys5026,150139 +#define FUNCTION_KEY_OFFSET 5061,151755 +static const char *const lispy_function_keys[lispy_function_keys5065,151898 +#define ISO_FUNCTION_KEY_OFFSET 5149,154433 +static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473 +static Lisp_Object Vlispy_mouse_stem;5172,155332 +static const char *const lispy_wheel_names[lispy_wheel_names5174,155371 +static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623 +static short const scroll_bar_parts[scroll_bar_parts5189,155889 +static Lisp_Object button_down_location;5210,156914 +static int last_mouse_button;5215,157069 +static int last_mouse_x;5216,157099 +static int last_mouse_y;5217,157124 +static Time button_down_time;5218,157149 +static int double_click_count;5222,157233 +make_lispy_position 5228,157394 +toolkit_menubar_in_use 5456,163957 +make_scroll_bar_position 5469,164325 +make_lispy_event 5485,164971 +make_lispy_movement 6104,183534 +make_lispy_switch_frame 6131,184265 +make_lispy_focus_in 6137,184372 +make_lispy_focus_out 6145,184498 +parse_modifiers_uncached 6163,184948 +#define SINGLE_LETTER_MOD(6185,185468 +#undef SINGLE_LETTER_MOD6212,185909 +#define MULTI_LETTER_MOD(6214,185935 +#undef MULTI_LETTER_MOD6231,186403 +apply_modifiers_uncached 6273,187577 +static const char *const modifier_names[modifier_names6319,189196 +#define NUM_MOD_NAMES 6325,189402 +static Lisp_Object modifier_symbols;6327,189452 +lispy_modifier_list 6331,189589 +#define KEY_TO_CHAR(6353,190255 +parse_modifiers 6356,190331 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520 +apply_modifiers 6422,192394 +reorder_modifiers 6491,194723 +modify_event_symbol 6536,196531 +DEFUN ("event-convert-list", Fevent_convert_list,6628,199247 +DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247 +parse_solitary_modifier 6695,201138 +#define SINGLE_LETTER_MOD(6701,201261 +#define MULTI_LETTER_MOD(6705,201346 +#undef SINGLE_LETTER_MOD6763,202644 +#undef MULTI_LETTER_MOD6764,202669 +lucid_event_type_list_p 6775,202892 +get_input_pending 6814,203963 +record_asynch_buffer_change 6834,204582 +gobble_input 6872,205705 +tty_read_avail_input 6967,208313 +handle_async_input 7149,214042 +process_pending_signals 7165,214362 +unblock_input_to 7177,214648 +unblock_input 7200,215280 +totally_unblock_input 7209,215448 +handle_input_available_signal 7217,215532 +deliver_input_available_signal 7226,215703 +struct user_signal_info7235,215868 + int sig;7238,215918 + char *name;name7241,215959 + int npending;7244,216010 + struct user_signal_info *next;next7246,216027 +static struct user_signal_info *user_signals user_signals7250,216093 +add_user_signal 7253,216152 +handle_user_signal 7275,216601 +deliver_user_signal 7316,217561 +find_user_signal_name 7322,217662 +store_user_signal_events 7334,217844 +static void menu_bar_item 7362,218344 +static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419 +static Lisp_Object menu_bar_items_vector;7368,218633 +static int menu_bar_items_index;7369,218675 +static const char *separator_names[separator_names7372,218710 +menu_separator_name_p 7393,219151 +menu_bar_items 7426,219855 +Lisp_Object item_properties;7568,224606 +menu_bar_item 7571,224648 +menu_item_eval_property_1 7647,227178 +eval_dyn 7658,227468 +menu_item_eval_property 7666,227678 +parse_menu_item 7686,228344 +static Lisp_Object tool_bar_items_vector;7965,236339 +static Lisp_Object tool_bar_item_properties;7970,236513 +static int ntool_bar_items;7974,236609 +static void init_tool_bar_items 7978,236667 +static void process_tool_bar_item 7979,236714 +static bool parse_tool_bar_item 7981,236804 +static void append_tool_bar_item 7982,236864 +tool_bar_items 7990,237086 +process_tool_bar_item 8075,239895 +#define PROP(8112,240972 +set_prop 8114,241041 +parse_tool_bar_item 8167,242456 +#undef PROP8379,248847 +init_tool_bar_items 8387,248972 +append_tool_bar_item 8401,249264 +read_char_x_menu_prompt 8443,250774 +read_char_minibuf_menu_prompt 8503,252448 +#define PUSH_C_STR(8527,253017 +follow_key 8726,258556 +active_maps 8733,258698 +typedef struct keyremap8742,259024 + Lisp_Object parent;8745,259110 + Lisp_Object map;8748,259227 + int start,8753,259449 + int start, end;8753,259449 +} keyremap;8754,259467 +access_keymap_keyremap 8764,259811 +keyremap_step 8811,261453 +test_undefined 8867,262937 +read_key_sequence 8916,264864 +read_key_sequence_vs 9826,295824 +DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297 +DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985 +detect_input_pending 9950,300491 +detect_input_pending_ignore_squeezables 9959,300657 +detect_input_pending_run_timers 9967,300873 +clear_input_pending 9985,301365 +requeued_events_pending_p 9997,301735 +DEFUN ("input-pending-p", Finput_pending_p,10002,301816 +DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816 +DEFUN ("recent-keys", Frecent_keys,10024,302599 +DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599 +DEFUN ("this-command-keys", Fthis_command_keys,10055,303520 +DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513 +DEFUN ("recursion-depth", Frecursion_depth,10158,307072 +DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072 +DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409 +DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409 +DEFUN ("discard-input", Fdiscard_input,10203,308450 +DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450 +DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952 +DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952 +stuff_buffered_input 10285,311048 +set_waiting_for_input 10323,312019 +clear_waiting_for_input 10337,312393 +handle_interrupt_signal 10351,312757 +deliver_interrupt_signal 10378,313645 +static int volatile force_quit_count;10387,313935 +handle_interrupt 10401,314417 +quit_throw_to_read_char 10541,318714 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291 +DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519 +DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435 +DEFUN ("set-quit-char", Fset_quit_char,10694,322709 +DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709 +DEFUN ("set-input-mode", Fset_input_mode,10729,323573 +DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573 +DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462 +DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462 +DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840 +DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840 +DEFUN ("posn-at-point", Fposn_at_point,10824,327063 +DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063 +init_kboard 10861,328217 +allocate_kboard 10893,329287 +wipe_kboard 10909,329640 +delete_kboard 10917,329754 +init_keyboard 10942,330284 +struct event_head11021,332699 + short var;11023,332719 + short kind;11024,332732 +static const struct event_head head_table[head_table11027,332750 +syms_of_keyboard 11045,333580 + DEFVAR_LISP ("internal--top-level-message"11058,333975 + DEFVAR_LISP ("last-command-event"11312,342176 + DEFVAR_LISP ("last-nonmenu-event"11315,342300 + DEFVAR_LISP ("last-input-event"11321,342639 + DEFVAR_LISP ("unread-command-events"11324,342733 + DEFVAR_LISP ("unread-post-input-method-events"11332,343193 + DEFVAR_LISP ("unread-input-method-events"11338,343532 + DEFVAR_LISP ("meta-prefix-char"11346,343901 + DEFVAR_KBOARD ("last-command"11351,344109 + DEFVAR_KBOARD ("real-last-command"11368,344790 + DEFVAR_KBOARD ("last-repeatable-command"11372,344976 + DEFVAR_LISP ("this-command"11378,345264 + DEFVAR_LISP ("real-this-command"11384,345501 + DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683 + DEFVAR_LISP ("this-original-command"11396,346126 + DEFVAR_INT ("auto-save-interval"11403,346523 + DEFVAR_LISP ("auto-save-timeout"11408,346737 + DEFVAR_LISP ("echo-keystrokes"11415,347082 + DEFVAR_INT ("polling-period"11421,347353 + DEFVAR_LISP ("double-click-time"11428,347696 + DEFVAR_INT ("double-click-fuzz"11435,348032 + DEFVAR_INT ("num-input-keys"11446,348522 + DEFVAR_INT ("num-nonmacro-input-events"11452,348797 + DEFVAR_LISP ("last-event-frame"11457,349035 + DEFVAR_LISP ("tty-erase-char"11463,349314 + DEFVAR_LISP ("help-char"11466,349437 + DEFVAR_LISP ("help-event-list"11472,349720 + DEFVAR_LISP ("help-form"11477,349931 + DEFVAR_LISP ("prefix-help-command"11483,350179 + DEFVAR_LISP ("top-level"11489,350457 + DEFVAR_KBOARD ("keyboard-translate-table"11495,350678 + DEFVAR_BOOL ("cannot-suspend"11511,351491 + DEFVAR_BOOL ("menu-prompting"11516,351718 + DEFVAR_LISP ("menu-prompt-more-char"11526,352148 + DEFVAR_INT ("extra-keyboard-modifiers"11531,352394 + DEFVAR_LISP ("deactivate-mark"11545,353120 + DEFVAR_LISP ("pre-command-hook"11553,353489 + DEFVAR_LISP ("post-command-hook"11560,353844 + DEFVAR_LISP ("echo-area-clear-hook"11568,354207 + DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422 + DEFVAR_LISP ("menu-bar-final-items"11578,354625 + DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875 + DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233 + DEFVAR_LISP ("overriding-local-map"11598,355655 + DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106 + DEFVAR_LISP ("special-event-map"11613,356445 + DEFVAR_LISP ("track-mouse"11617,356633 + DEFVAR_KBOARD ("system-key-alist"11620,356760 + DEFVAR_KBOARD ("local-function-key-map"11629,357141 + DEFVAR_KBOARD ("input-decode-map"11658,358600 + DEFVAR_LISP ("function-key-map"11675,359388 + DEFVAR_LISP ("key-translation-map"11683,359804 + DEFVAR_LISP ("deferred-action-list"11689,360148 + DEFVAR_LISP ("deferred-action-function"11694,360396 + DEFVAR_LISP ("delayed-warnings-list"11700,360695 + DEFVAR_LISP ("timer-list"11708,361103 + DEFVAR_LISP ("timer-idle-list"11712,361255 + DEFVAR_LISP ("input-method-function"11716,361418 + DEFVAR_LISP ("input-method-previous-message"11737,362387 + DEFVAR_LISP ("show-help-function"11744,362748 + DEFVAR_LISP ("disable-point-adjustment"11749,362980 + DEFVAR_LISP ("global-disable-point-adjustment"11761,363530 + DEFVAR_LISP ("minibuffer-message-timeout"11770,363896 + DEFVAR_LISP ("throw-on-input"11775,364174 + DEFVAR_LISP ("command-error-function"11781,364425 + DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912 + DEFVAR_LISP ("select-active-regions"11798,365239 + DEFVAR_LISP ("saved-region-selection"11807,365631 + DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016 + DEFVAR_LISP ("debug-on-event"11825,366557 +keys_of_keyboard 11841,367118 +mark_kboards 11916,370437 + DEFVAR_LISP ("internal--top-level-message",\111058,333975 + DEFVAR_LISP ("last-command-event",\111312,342176 + DEFVAR_LISP ("last-nonmenu-event",\111315,342300 + DEFVAR_LISP ("last-input-event",\111321,342639 + DEFVAR_LISP ("unread-command-events",\111324,342733 + DEFVAR_LISP ("unread-post-input-method-events",\111332,343193 + DEFVAR_LISP ("unread-input-method-events",\111338,343532 + DEFVAR_LISP ("meta-prefix-char",\111346,343901 + DEFVAR_KBOARD ("last-command",\111351,344109 + DEFVAR_KBOARD ("real-last-command",\111368,344790 + DEFVAR_KBOARD ("last-repeatable-command",\111372,344976 + DEFVAR_LISP ("this-command",\111378,345264 + DEFVAR_LISP ("real-this-command",\111384,345501 + DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683 + DEFVAR_LISP ("this-original-command",\111396,346126 + DEFVAR_INT ("auto-save-interval",\111403,346523 + DEFVAR_LISP ("auto-save-timeout",\111408,346737 + DEFVAR_LISP ("echo-keystrokes",\111415,347082 + DEFVAR_INT ("polling-period",\111421,347353 + DEFVAR_LISP ("double-click-time",\111428,347696 + DEFVAR_INT ("double-click-fuzz",\111435,348032 + DEFVAR_INT ("num-input-keys",\111446,348522 + DEFVAR_INT ("num-nonmacro-input-events",\111452,348797 + DEFVAR_LISP ("last-event-frame",\111457,349035 + DEFVAR_LISP ("tty-erase-char",\111463,349314 + DEFVAR_LISP ("help-char",\111466,349437 + DEFVAR_LISP ("help-event-list",\111472,349720 + DEFVAR_LISP ("help-form",\111477,349931 + DEFVAR_LISP ("prefix-help-command",\111483,350179 + DEFVAR_LISP ("top-level",\111489,350457 + DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678 + DEFVAR_BOOL ("cannot-suspend",\111511,351491 + DEFVAR_BOOL ("menu-prompting",\111516,351718 + DEFVAR_LISP ("menu-prompt-more-char",\111526,352148 + DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394 + DEFVAR_LISP ("deactivate-mark",\111545,353120 + DEFVAR_LISP ("pre-command-hook",\111553,353489 + DEFVAR_LISP ("post-command-hook",\111560,353844 + DEFVAR_LISP ("echo-area-clear-hook",\111568,354207 + DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422 + DEFVAR_LISP ("menu-bar-final-items",\111578,354625 + DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875 + DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233 + DEFVAR_LISP ("overriding-local-map",\111598,355655 + DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106 + DEFVAR_LISP ("special-event-map",\111613,356445 + DEFVAR_LISP ("track-mouse",\111617,356633 + DEFVAR_KBOARD ("system-key-alist",\111620,356760 + DEFVAR_KBOARD ("local-function-key-map",\111629,357141 + DEFVAR_KBOARD ("input-decode-map",\111658,358600 + DEFVAR_LISP ("function-key-map",\111675,359388 + DEFVAR_LISP ("key-translation-map",\111683,359804 + DEFVAR_LISP ("deferred-action-list",\111689,360148 + DEFVAR_LISP ("deferred-action-function",\111694,360396 + DEFVAR_LISP ("delayed-warnings-list",\111700,360695 + DEFVAR_LISP ("timer-list",\111708,361103 + DEFVAR_LISP ("timer-idle-list",\111712,361255 + DEFVAR_LISP ("input-method-function",\111716,361418 + DEFVAR_LISP ("input-method-previous-message",\111737,362387 + DEFVAR_LISP ("show-help-function",\111744,362748 + DEFVAR_LISP ("disable-point-adjustment",\111749,362980 + DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530 + DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896 + DEFVAR_LISP ("throw-on-input",\111775,364174 + DEFVAR_LISP ("command-error-function",\111781,364425 + DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912 + DEFVAR_LISP ("select-active-regions",\111798,365239 + DEFVAR_LISP ("saved-region-selection",\111807,365631 + DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016 + DEFVAR_LISP ("debug-on-event",\111825,366557 c-src/emacs/src/lisp.h,41391 #define EMACS_LISP_H22,801 @@ -3274,112 +3274,112 @@ el-src/emacs/lisp/progmodes/etags.el,5188 (defcustom tags-tag-face 148,5700 (defcustom tags-apropos-verbose 154,5835 (defcustom tags-apropos-additional-actions 160,5999 -(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918 -(defvar default-tags-table-function 189,7098 -(defvar tags-location-ring 194,7324 -(defvar tags-table-files 201,7600 -(defvar tags-completion-table 206,7767 -(defvar tags-included-tables 209,7859 -(defvar next-file-list 212,7954 -(defvar tags-table-format-functions 217,8060 -(defvar file-of-tag-function 224,8441 -(defvar tags-table-files-function 228,8635 -(defvar tags-completion-table-function 230,8746 -(defvar snarf-tag-function 232,8841 -(defvar goto-tag-location-function 236,9050 -(defvar find-tag-regexp-search-function 239,9223 -(defvar find-tag-regexp-tag-order 241,9344 -(defvar find-tag-regexp-next-line-after-failure-p 243,9453 -(defvar find-tag-search-function 245,9573 -(defvar find-tag-tag-order 247,9680 -(defvar find-tag-next-line-after-failure-p 249,9775 -(defvar list-tags-function 251,9881 -(defvar tags-apropos-function 253,9969 -(defvar tags-included-tables-function 255,10063 -(defvar verify-tags-table-function 257,10182 -(defun initialize-new-tags-table 260,10293 -(defun tags-table-mode 276,10981 -(defun visit-tags-table 285,11246 -(defun tags-table-check-computed-list 321,12784 -(defun tags-table-extend-computed-list 360,14655 -(defun tags-expand-table-name 400,16368 -(defun tags-table-list-member 409,16711 -(defun tags-verify-table 421,17183 -(defun tags-table-including 470,19303 -(defun tags-next-table 522,21347 -(defun visit-tags-table-buffer 543,22204 -(defun tags-reset-tags-tables 712,28514 -(defun file-of-tag 731,29171 -(defun tags-table-files 740,29521 -(defun tags-included-tables 749,29871 -(defun tags-completion-table 755,30117 -(defun tags-lazy-completion-table 783,31311 -(defun tags-completion-at-point-function 799,31946 -(defun find-tag-tag 818,32696 -(defvar last-tag 837,33369 -(defun find-tag-interactive 840,33428 -(defvar find-tag-history 852,33843 -(defvar etags-case-fold-search)855,33908 -(defvar etags-syntax-table)856,33940 -(defvar local-find-tag-hook)857,33968 -(defun find-tag-noselect 860,34013 -(defun find-tag 932,37127 -(defun find-tag-other-window 959,38343 -(defun find-tag-other-frame 1000,40271 -(defun find-tag-regexp 1025,41445 -(defalias 'pop-tag-mark pop-tag-mark1049,42607 -(defvar tag-lines-already-matched 1052,42658 -(defun find-tag-in-order 1055,42765 -(defun tag-find-file-of-tag-noselect 1167,47111 -(defun tag-find-file-of-tag 1200,48957 -(defun etags-recognize-tags-table 1208,49183 -(defun etags-verify-tags-table 1241,50814 -(defun etags-file-of-tag 1246,51012 -(defun etags-tags-completion-table 1256,51347 -(defun etags-snarf-tag 1286,52553 -(defun etags-goto-tag-location 1324,54122 -(defun etags-list-tags 1388,56565 -(defmacro tags-with-face 1423,57840 -(defun etags-tags-apropos-additional 1431,58173 -(defun etags-tags-apropos 1465,59410 -(defun etags-tags-table-files 1527,61619 -(defun etags-tags-included-tables 1542,62055 -(defun tags-recognize-empty-tags-table 1559,62595 -(defun tag-exact-file-name-match-p 1587,63741 -(defun tag-file-name-match-p 1596,64134 -(defun tag-exact-match-p 1609,64690 -(defun tag-implicit-name-match-p 1620,65258 -(defun tag-symbol-match-p 1633,65858 -(defun tag-word-match-p 1643,66294 -(defun tag-partial-file-name-match-p 1652,66692 -(defun tag-any-match-p 1662,67136 -(defun tag-re-match-p 1667,67320 -(defcustom tags-loop-revert-buffers 1675,67569 -(defun next-file 1685,67978 -(defvar tags-loop-operate 1760,70892 -(defvar tags-loop-scan1763,70986 -(defun tags-loop-eval 1771,71315 -(defun tags-loop-continue 1782,71644 -(defun tags-search 1850,73950 -(defun tags-query-replace 1871,74776 -(defun tags-complete-tags-table-file 1896,76000 -(defun list-tags 1906,76379 -(defun tags-apropos 1934,77332 -(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158 -(defun select-tags-table 1964,78397 -(defvar select-tags-table-mode-map 2019,80524 -(define-derived-mode select-tags-table-mode 2030,80907 -(defun select-tags-table-select 2034,81091 -(defun select-tags-table-quit 2043,81457 -(defun complete-tag 2049,81612 -(defconst etags--xref-limit 2074,82553 -(defvar etags-xref-find-definitions-tag-order 2076,82588 -(defun etags-xref-find 2082,82878 -(defun etags--xref-find-definitions 2096,83407 -(defclass xref-etags-location 2129,85121 -(defun xref-make-etags-location 2135,85344 -(cl-defmethod xref-location-marker 2139,85499 -(cl-defmethod xref-location-line 2146,85743 +(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921 +(defvar default-tags-table-function 189,7101 +(defvar tags-location-ring 194,7327 +(defvar tags-table-files 201,7603 +(defvar tags-completion-table 206,7770 +(defvar tags-included-tables 209,7862 +(defvar next-file-list 212,7957 +(defvar tags-table-format-functions 217,8063 +(defvar file-of-tag-function 224,8444 +(defvar tags-table-files-function 228,8638 +(defvar tags-completion-table-function 230,8749 +(defvar snarf-tag-function 232,8844 +(defvar goto-tag-location-function 236,9053 +(defvar find-tag-regexp-search-function 239,9226 +(defvar find-tag-regexp-tag-order 241,9347 +(defvar find-tag-regexp-next-line-after-failure-p 243,9456 +(defvar find-tag-search-function 245,9576 +(defvar find-tag-tag-order 247,9683 +(defvar find-tag-next-line-after-failure-p 249,9778 +(defvar list-tags-function 251,9884 +(defvar tags-apropos-function 253,9972 +(defvar tags-included-tables-function 255,10066 +(defvar verify-tags-table-function 257,10185 +(defun initialize-new-tags-table 260,10296 +(defun tags-table-mode 276,10984 +(defun visit-tags-table 285,11249 +(defun tags-table-check-computed-list 321,12787 +(defun tags-table-extend-computed-list 360,14658 +(defun tags-expand-table-name 400,16371 +(defun tags-table-list-member 409,16714 +(defun tags-verify-table 421,17186 +(defun tags-table-including 470,19306 +(defun tags-next-table 522,21350 +(defun visit-tags-table-buffer 543,22207 +(defun tags-reset-tags-tables 712,28517 +(defun file-of-tag 731,29174 +(defun tags-table-files 740,29524 +(defun tags-included-tables 749,29874 +(defun tags-completion-table 755,30120 +(defun tags-lazy-completion-table 783,31314 +(defun tags-completion-at-point-function 799,31949 +(defun find-tag-tag 818,32699 +(defvar last-tag 837,33372 +(defun find-tag-interactive 840,33431 +(defvar find-tag-history 852,33846 +(defvar etags-case-fold-search)855,33911 +(defvar etags-syntax-table)856,33943 +(defvar local-find-tag-hook)857,33971 +(defun find-tag-noselect 860,34016 +(defun find-tag 932,37130 +(defun find-tag-other-window 959,38346 +(defun find-tag-other-frame 1000,40274 +(defun find-tag-regexp 1025,41448 +(defalias 'pop-tag-mark pop-tag-mark1049,42610 +(defvar tag-lines-already-matched 1052,42661 +(defun find-tag-in-order 1055,42768 +(defun tag-find-file-of-tag-noselect 1167,47114 +(defun tag-find-file-of-tag 1200,48960 +(defun etags-recognize-tags-table 1208,49186 +(defun etags-verify-tags-table 1241,50817 +(defun etags-file-of-tag 1246,51015 +(defun etags-tags-completion-table 1256,51350 +(defun etags-snarf-tag 1286,52556 +(defun etags-goto-tag-location 1324,54125 +(defun etags-list-tags 1388,56568 +(defmacro tags-with-face 1423,57843 +(defun etags-tags-apropos-additional 1431,58176 +(defun etags-tags-apropos 1465,59413 +(defun etags-tags-table-files 1527,61622 +(defun etags-tags-included-tables 1542,62058 +(defun tags-recognize-empty-tags-table 1559,62598 +(defun tag-exact-file-name-match-p 1587,63744 +(defun tag-file-name-match-p 1596,64137 +(defun tag-exact-match-p 1609,64693 +(defun tag-implicit-name-match-p 1620,65261 +(defun tag-symbol-match-p 1633,65861 +(defun tag-word-match-p 1643,66297 +(defun tag-partial-file-name-match-p 1652,66695 +(defun tag-any-match-p 1662,67139 +(defun tag-re-match-p 1667,67323 +(defcustom tags-loop-revert-buffers 1675,67572 +(defun next-file 1685,67981 +(defvar tags-loop-operate 1760,70895 +(defvar tags-loop-scan1763,70989 +(defun tags-loop-eval 1771,71318 +(defun tags-loop-continue 1782,71647 +(defun tags-search 1850,73953 +(defun tags-query-replace 1871,74779 +(defun tags-complete-tags-table-file 1896,76003 +(defun list-tags 1906,76382 +(defun tags-apropos 1934,77335 +(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161 +(defun select-tags-table 1964,78400 +(defvar select-tags-table-mode-map 2019,80527 +(define-derived-mode select-tags-table-mode 2030,80910 +(defun select-tags-table-select 2034,81094 +(defun select-tags-table-quit 2043,81460 +(defun complete-tag 2049,81615 +(defconst etags--xref-limit 2074,82556 +(defvar etags-xref-find-definitions-tag-order 2076,82591 +(defun etags-xref-find 2082,82881 +(defun etags--xref-find-definitions 2096,83410 +(defclass xref-etags-location 2129,85124 +(defun xref-make-etags-location 2135,85347 +(cl-defmethod xref-location-marker 2139,85502 +(cl-defmethod xref-location-line 2146,85746 erl-src/gs_dialog.erl,98 -define(VERSION2,32 diff --git a/test/manual/etags/ETAGS.good_6 b/test/manual/etags/ETAGS.good_6 index 9a38e20dce..6f440a7fc9 100644 --- a/test/manual/etags/ETAGS.good_6 +++ b/test/manual/etags/ETAGS.good_6 @@ -1234,440 +1234,440 @@ record_auto_save 742,23849 force_auto_save_soon 751,24017 DEFUN ("recursive-edit", Frecursive_edit,759,24138 DEFUN ("recursive-edit", Frecursive_edit,recursive-edit759,24138 -recursive_edit_unwind 804,25748 -any_kboard_state 817,26014 -single_kboard_state 838,26666 -not_single_kboard_state 848,26804 -struct kboard_stack858,27066 - KBOARD *kboard;kboard860,27088 - struct kboard_stack *next;next861,27106 -static struct kboard_stack *kboard_stack;kboard_stack864,27139 -push_kboard 867,27187 -pop_kboard 879,27376 -temporarily_switch_to_single_kboard 914,28264 -record_single_kboard_state 943,29438 -restore_kboard_configuration 952,29622 -cmd_error 970,30078 -cmd_error_internal 1024,31511 -DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32031 -DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32031 -static Lisp_Object command_loop_2 1086,33638 -static Lisp_Object top_level_1 1087,33687 -command_loop 1094,33917 -command_loop_2 1134,35136 -top_level_2 1146,35340 -top_level_1 1152,35418 -DEFUN ("top-level", Ftop_level,1164,35788 -DEFUN ("top-level", Ftop_level,top-level1164,35788 -user_error 1183,36289 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36430 -DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36430 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36820 -DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36820 -tracking_off 1216,37282 -DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37817 -DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37817 -bool ignore_mouse_drag_p;1256,38393 -some_mouse_moved 1259,38442 -static int read_key_sequence 1282,38800 -static void adjust_point_for_property 1284,38918 -Lisp_Object last_undo_boundary;1287,39033 -command_loop_1 1294,39274 -read_menu_command 1649,50890 -adjust_point_for_property 1678,51618 -safe_run_hooks_1 1831,57340 -safe_run_hooks_error 1841,57570 -safe_run_hook_funcall 1878,58577 -safe_run_hooks 1893,59059 -int poll_suppress_count;1908,59398 -static struct atimer *poll_timer;poll_timer1915,59488 -poll_for_input_1 1919,59590 -poll_for_input 1930,59790 -start_polling 1942,60054 -input_polling_used 1979,61092 -stop_polling 1994,61391 -set_poll_suppress_count 2009,61760 -bind_polling_period 2029,62142 -make_ctrl_char 2048,62493 -show_help_echo 2113,64456 -static Lisp_Object kbd_buffer_get_event 2152,65485 -static void record_char 2154,65597 -static Lisp_Object help_form_saved_window_configs;2156,65639 -read_char_help_form_unwind 2158,65702 -#define STOP_POLLING 2166,65960 -#define RESUME_POLLING 2170,66085 -read_event_from_main_queue 2175,66230 -read_decoded_event_from_main_queue 2249,68418 -#define MAX_ENCODED_BYTES 2254,68665 -echo_keystrokes_p 2342,71557 -read_char 2376,72849 -record_menu_key 3225,98950 -help_char_p 3258,99675 -record_char 3273,99954 -save_getcjmp 3412,104236 -restore_getcjmp 3418,104327 -readable_events 3430,104698 -int stop_character EXTERNALLY_VISIBLE;3497,106438 -event_to_kboard 3500,106494 -kbd_buffer_nr_stored 3522,107143 -kbd_buffer_store_event 3534,107484 -kbd_buffer_store_event_hold 3550,108026 -kbd_buffer_unget_event 3684,111618 -#define INPUT_EVENT_POS_MAX 3698,112019 -#define INPUT_EVENT_POS_MIN 3701,112148 -position_to_Time 3706,112288 -Time_to_position 3716,112515 -gen_help_event 3738,113172 -kbd_buffer_store_help_event 3756,113612 -discard_mouse_events 3773,113977 -kbd_buffer_events_waiting 3803,114712 -clear_event 3823,115069 -kbd_buffer_get_event 3836,115409 -process_special_events 4258,127882 -swallow_events 4322,129706 -timer_start_idle 4339,130099 -timer_stop_idle 4355,130577 -timer_resume_idle 4363,130721 -struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130913 -Lisp_Object pending_funcalls;4377,131173 -decode_timer 4381,131294 -timer_check_2 4414,132247 -timer_check 4572,136818 -DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137663 -DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137663 -static Lisp_Object accent_key_syms;4625,138240 -static Lisp_Object func_key_syms;4626,138276 -static Lisp_Object mouse_syms;4627,138310 -static Lisp_Object wheel_syms;4628,138341 -static Lisp_Object drag_n_drop_syms;4629,138372 -static const int lispy_accent_codes[lispy_accent_codes4634,138517 -static const char *const lispy_accent_keys[lispy_accent_keys4741,139879 -#define FUNCTION_KEY_OFFSET 4766,140315 -const char *const lispy_function_keys[lispy_function_keys4768,140348 -static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148902 -static const char *const lispy_kana_keys[lispy_kana_keys5026,150136 -#define FUNCTION_KEY_OFFSET 5061,151752 -static const char *const lispy_function_keys[lispy_function_keys5065,151895 -#define ISO_FUNCTION_KEY_OFFSET 5149,154430 -static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154470 -static Lisp_Object Vlispy_mouse_stem;5172,155329 -static const char *const lispy_wheel_names[lispy_wheel_names5174,155368 -static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155620 -static short const scroll_bar_parts[scroll_bar_parts5189,155886 -static Lisp_Object button_down_location;5210,156911 -static int last_mouse_button;5215,157066 -static int last_mouse_x;5216,157096 -static int last_mouse_y;5217,157121 -static Time button_down_time;5218,157146 -static int double_click_count;5222,157230 -make_lispy_position 5228,157391 -toolkit_menubar_in_use 5456,163954 -make_scroll_bar_position 5469,164322 -make_lispy_event 5485,164968 -make_lispy_movement 6104,183531 -make_lispy_switch_frame 6131,184262 -make_lispy_focus_in 6137,184369 -make_lispy_focus_out 6145,184495 -parse_modifiers_uncached 6163,184945 -#define SINGLE_LETTER_MOD(6185,185465 -#undef SINGLE_LETTER_MOD6212,185906 -#define MULTI_LETTER_MOD(6214,185932 -#undef MULTI_LETTER_MOD6231,186400 -apply_modifiers_uncached 6273,187574 -static const char *const modifier_names[modifier_names6319,189193 -#define NUM_MOD_NAMES 6325,189399 -static Lisp_Object modifier_symbols;6327,189449 -lispy_modifier_list 6331,189586 -#define KEY_TO_CHAR(6353,190252 -parse_modifiers 6356,190328 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191517 -DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191517 -apply_modifiers 6422,192391 -reorder_modifiers 6491,194720 -modify_event_symbol 6536,196528 -DEFUN ("event-convert-list", Fevent_convert_list,6628,199244 -DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199244 -parse_solitary_modifier 6695,201135 -#define SINGLE_LETTER_MOD(6701,201258 -#define MULTI_LETTER_MOD(6705,201343 -#undef SINGLE_LETTER_MOD6763,202641 -#undef MULTI_LETTER_MOD6764,202666 -lucid_event_type_list_p 6775,202889 -get_input_pending 6814,203960 -record_asynch_buffer_change 6834,204579 -gobble_input 6872,205702 -tty_read_avail_input 6967,208310 -handle_async_input 7149,214039 -process_pending_signals 7165,214359 -unblock_input_to 7177,214645 -unblock_input 7200,215277 -totally_unblock_input 7209,215445 -handle_input_available_signal 7217,215529 -deliver_input_available_signal 7226,215700 -struct user_signal_info7235,215865 - int sig;7238,215915 - char *name;name7241,215956 - int npending;7244,216007 - struct user_signal_info *next;next7246,216024 -static struct user_signal_info *user_signals user_signals7250,216090 -add_user_signal 7253,216149 -handle_user_signal 7275,216598 -deliver_user_signal 7316,217558 -find_user_signal_name 7322,217659 -store_user_signal_events 7334,217841 -static void menu_bar_item 7362,218341 -static Lisp_Object menu_bar_one_keymap_changed_items;7363,218416 -static Lisp_Object menu_bar_items_vector;7368,218630 -static int menu_bar_items_index;7369,218672 -static const char *separator_names[separator_names7372,218707 -menu_separator_name_p 7393,219148 -menu_bar_items 7426,219852 -Lisp_Object item_properties;7568,224603 -menu_bar_item 7571,224645 -menu_item_eval_property_1 7647,227175 -eval_dyn 7658,227465 -menu_item_eval_property 7666,227675 -parse_menu_item 7686,228341 -static Lisp_Object tool_bar_items_vector;7965,236336 -static Lisp_Object tool_bar_item_properties;7970,236510 -static int ntool_bar_items;7974,236606 -static void init_tool_bar_items 7978,236664 -static void process_tool_bar_item 7979,236711 -static bool parse_tool_bar_item 7981,236801 -static void append_tool_bar_item 7982,236861 -tool_bar_items 7990,237083 -process_tool_bar_item 8075,239892 -#define PROP(8112,240969 -set_prop 8114,241038 -parse_tool_bar_item 8167,242453 -#undef PROP8379,248844 -init_tool_bar_items 8387,248969 -append_tool_bar_item 8401,249261 -read_char_x_menu_prompt 8443,250771 -read_char_minibuf_menu_prompt 8503,252445 -#define PUSH_C_STR(8527,253014 -follow_key 8726,258553 -active_maps 8733,258695 -typedef struct keyremap8742,259021 - Lisp_Object parent;8745,259107 - Lisp_Object map;8748,259224 - int start,8753,259446 - int start, end;8753,259446 -} keyremap;8754,259464 -access_keymap_keyremap 8764,259808 -keyremap_step 8811,261450 -test_undefined 8867,262934 -read_key_sequence 8916,264861 -read_key_sequence_vs 9826,295821 -DEFUN ("read-key-sequence", Fread_key_sequence,9885,297294 -DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297294 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299982 -DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299982 -detect_input_pending 9950,300488 -detect_input_pending_ignore_squeezables 9959,300654 -detect_input_pending_run_timers 9967,300870 -clear_input_pending 9985,301362 -requeued_events_pending_p 9997,301732 -DEFUN ("input-pending-p", Finput_pending_p,10002,301813 -DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301813 -DEFUN ("recent-keys", Frecent_keys,10024,302596 -DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302596 -DEFUN ("this-command-keys", Fthis_command_keys,10055,303517 -DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303517 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303958 -DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303958 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304380 -DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304380 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304955 -DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304955 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305495 -DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305495 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306510 -DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306510 -DEFUN ("recursion-depth", Frecursion_depth,10158,307069 -DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307069 -DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307406 -DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307406 -DEFUN ("discard-input", Fdiscard_input,10203,308447 -DEFUN ("discard-input", Fdiscard_input,discard-input10203,308447 -DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308949 -DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308949 -stuff_buffered_input 10285,311045 -set_waiting_for_input 10323,312016 -clear_waiting_for_input 10337,312390 -handle_interrupt_signal 10351,312754 -deliver_interrupt_signal 10378,313642 -static int volatile force_quit_count;10387,313932 -handle_interrupt 10401,314414 -quit_throw_to_read_char 10541,318711 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319288 -DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319288 -DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320516 -DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320516 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321432 -DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321432 -DEFUN ("set-quit-char", Fset_quit_char,10694,322706 -DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322706 -DEFUN ("set-input-mode", Fset_input_mode,10729,323570 -DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323570 -DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324459 -DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324459 -DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325837 -DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325837 -DEFUN ("posn-at-point", Fposn_at_point,10824,327060 -DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327060 -init_kboard 10861,328214 -allocate_kboard 10893,329284 -wipe_kboard 10909,329637 -delete_kboard 10917,329751 -init_keyboard 10942,330281 -struct event_head11021,332696 - short var;11023,332716 - short kind;11024,332729 -static const struct event_head head_table[head_table11027,332747 -syms_of_keyboard 11045,333577 - DEFVAR_LISP ("internal--top-level-message"11058,333972 - DEFVAR_LISP ("last-command-event"11312,342173 - DEFVAR_LISP ("last-nonmenu-event"11315,342297 - DEFVAR_LISP ("last-input-event"11321,342636 - DEFVAR_LISP ("unread-command-events"11324,342730 - DEFVAR_LISP ("unread-post-input-method-events"11332,343190 - DEFVAR_LISP ("unread-input-method-events"11338,343529 - DEFVAR_LISP ("meta-prefix-char"11346,343898 - DEFVAR_KBOARD ("last-command"11351,344106 - DEFVAR_KBOARD ("real-last-command"11368,344787 - DEFVAR_KBOARD ("last-repeatable-command"11372,344973 - DEFVAR_LISP ("this-command"11378,345261 - DEFVAR_LISP ("real-this-command"11384,345498 - DEFVAR_LISP ("this-command-keys-shift-translated"11388,345680 - DEFVAR_LISP ("this-original-command"11396,346123 - DEFVAR_INT ("auto-save-interval"11403,346520 - DEFVAR_LISP ("auto-save-timeout"11408,346734 - DEFVAR_LISP ("echo-keystrokes"11415,347079 - DEFVAR_INT ("polling-period"11421,347350 - DEFVAR_LISP ("double-click-time"11428,347693 - DEFVAR_INT ("double-click-fuzz"11435,348029 - DEFVAR_INT ("num-input-keys"11446,348519 - DEFVAR_INT ("num-nonmacro-input-events"11452,348794 - DEFVAR_LISP ("last-event-frame"11457,349032 - DEFVAR_LISP ("tty-erase-char"11463,349311 - DEFVAR_LISP ("help-char"11466,349434 - DEFVAR_LISP ("help-event-list"11472,349717 - DEFVAR_LISP ("help-form"11477,349928 - DEFVAR_LISP ("prefix-help-command"11483,350176 - DEFVAR_LISP ("top-level"11489,350454 - DEFVAR_KBOARD ("keyboard-translate-table"11495,350675 - DEFVAR_BOOL ("cannot-suspend"11511,351488 - DEFVAR_BOOL ("menu-prompting"11516,351715 - DEFVAR_LISP ("menu-prompt-more-char"11526,352145 - DEFVAR_INT ("extra-keyboard-modifiers"11531,352391 - DEFVAR_LISP ("deactivate-mark"11545,353117 - DEFVAR_LISP ("pre-command-hook"11553,353486 - DEFVAR_LISP ("post-command-hook"11560,353841 - DEFVAR_LISP ("echo-area-clear-hook"11568,354204 - DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354419 - DEFVAR_LISP ("menu-bar-final-items"11578,354622 - DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354872 - DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355230 - DEFVAR_LISP ("overriding-local-map"11598,355652 - DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356103 - DEFVAR_LISP ("special-event-map"11613,356442 - DEFVAR_LISP ("track-mouse"11617,356630 - DEFVAR_KBOARD ("system-key-alist"11620,356757 - DEFVAR_KBOARD ("local-function-key-map"11629,357138 - DEFVAR_KBOARD ("input-decode-map"11658,358597 - DEFVAR_LISP ("function-key-map"11675,359385 - DEFVAR_LISP ("key-translation-map"11683,359801 - DEFVAR_LISP ("deferred-action-list"11689,360145 - DEFVAR_LISP ("deferred-action-function"11694,360393 - DEFVAR_LISP ("delayed-warnings-list"11700,360692 - DEFVAR_LISP ("timer-list"11708,361100 - DEFVAR_LISP ("timer-idle-list"11712,361252 - DEFVAR_LISP ("input-method-function"11716,361415 - DEFVAR_LISP ("input-method-previous-message"11737,362384 - DEFVAR_LISP ("show-help-function"11744,362745 - DEFVAR_LISP ("disable-point-adjustment"11749,362977 - DEFVAR_LISP ("global-disable-point-adjustment"11761,363527 - DEFVAR_LISP ("minibuffer-message-timeout"11770,363893 - DEFVAR_LISP ("throw-on-input"11775,364171 - DEFVAR_LISP ("command-error-function"11781,364422 - DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364909 - DEFVAR_LISP ("select-active-regions"11798,365236 - DEFVAR_LISP ("saved-region-selection"11807,365628 - DEFVAR_LISP ("selection-inhibit-update-commands"11815,366013 - DEFVAR_LISP ("debug-on-event"11825,366554 -keys_of_keyboard 11841,367115 -mark_kboards 11916,370434 - DEFVAR_LISP ("internal--top-level-message",\111058,333972 - DEFVAR_LISP ("last-command-event",\111312,342173 - DEFVAR_LISP ("last-nonmenu-event",\111315,342297 - DEFVAR_LISP ("last-input-event",\111321,342636 - DEFVAR_LISP ("unread-command-events",\111324,342730 - DEFVAR_LISP ("unread-post-input-method-events",\111332,343190 - DEFVAR_LISP ("unread-input-method-events",\111338,343529 - DEFVAR_LISP ("meta-prefix-char",\111346,343898 - DEFVAR_KBOARD ("last-command",\111351,344106 - DEFVAR_KBOARD ("real-last-command",\111368,344787 - DEFVAR_KBOARD ("last-repeatable-command",\111372,344973 - DEFVAR_LISP ("this-command",\111378,345261 - DEFVAR_LISP ("real-this-command",\111384,345498 - DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345680 - DEFVAR_LISP ("this-original-command",\111396,346123 - DEFVAR_INT ("auto-save-interval",\111403,346520 - DEFVAR_LISP ("auto-save-timeout",\111408,346734 - DEFVAR_LISP ("echo-keystrokes",\111415,347079 - DEFVAR_INT ("polling-period",\111421,347350 - DEFVAR_LISP ("double-click-time",\111428,347693 - DEFVAR_INT ("double-click-fuzz",\111435,348029 - DEFVAR_INT ("num-input-keys",\111446,348519 - DEFVAR_INT ("num-nonmacro-input-events",\111452,348794 - DEFVAR_LISP ("last-event-frame",\111457,349032 - DEFVAR_LISP ("tty-erase-char",\111463,349311 - DEFVAR_LISP ("help-char",\111466,349434 - DEFVAR_LISP ("help-event-list",\111472,349717 - DEFVAR_LISP ("help-form",\111477,349928 - DEFVAR_LISP ("prefix-help-command",\111483,350176 - DEFVAR_LISP ("top-level",\111489,350454 - DEFVAR_KBOARD ("keyboard-translate-table",\111495,350675 - DEFVAR_BOOL ("cannot-suspend",\111511,351488 - DEFVAR_BOOL ("menu-prompting",\111516,351715 - DEFVAR_LISP ("menu-prompt-more-char",\111526,352145 - DEFVAR_INT ("extra-keyboard-modifiers",\111531,352391 - DEFVAR_LISP ("deactivate-mark",\111545,353117 - DEFVAR_LISP ("pre-command-hook",\111553,353486 - DEFVAR_LISP ("post-command-hook",\111560,353841 - DEFVAR_LISP ("echo-area-clear-hook",\111568,354204 - DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354419 - DEFVAR_LISP ("menu-bar-final-items",\111578,354622 - DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354872 - DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355230 - DEFVAR_LISP ("overriding-local-map",\111598,355652 - DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356103 - DEFVAR_LISP ("special-event-map",\111613,356442 - DEFVAR_LISP ("track-mouse",\111617,356630 - DEFVAR_KBOARD ("system-key-alist",\111620,356757 - DEFVAR_KBOARD ("local-function-key-map",\111629,357138 - DEFVAR_KBOARD ("input-decode-map",\111658,358597 - DEFVAR_LISP ("function-key-map",\111675,359385 - DEFVAR_LISP ("key-translation-map",\111683,359801 - DEFVAR_LISP ("deferred-action-list",\111689,360145 - DEFVAR_LISP ("deferred-action-function",\111694,360393 - DEFVAR_LISP ("delayed-warnings-list",\111700,360692 - DEFVAR_LISP ("timer-list",\111708,361100 - DEFVAR_LISP ("timer-idle-list",\111712,361252 - DEFVAR_LISP ("input-method-function",\111716,361415 - DEFVAR_LISP ("input-method-previous-message",\111737,362384 - DEFVAR_LISP ("show-help-function",\111744,362745 - DEFVAR_LISP ("disable-point-adjustment",\111749,362977 - DEFVAR_LISP ("global-disable-point-adjustment",\111761,363527 - DEFVAR_LISP ("minibuffer-message-timeout",\111770,363893 - DEFVAR_LISP ("throw-on-input",\111775,364171 - DEFVAR_LISP ("command-error-function",\111781,364422 - DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364909 - DEFVAR_LISP ("select-active-regions",\111798,365236 - DEFVAR_LISP ("saved-region-selection",\111807,365628 - DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366013 - DEFVAR_LISP ("debug-on-event",\111825,366554 +recursive_edit_unwind 804,25751 +any_kboard_state 817,26017 +single_kboard_state 838,26669 +not_single_kboard_state 848,26807 +struct kboard_stack858,27069 + KBOARD *kboard;kboard860,27091 + struct kboard_stack *next;next861,27109 +static struct kboard_stack *kboard_stack;kboard_stack864,27142 +push_kboard 867,27190 +pop_kboard 879,27379 +temporarily_switch_to_single_kboard 914,28267 +record_single_kboard_state 943,29441 +restore_kboard_configuration 952,29625 +cmd_error 970,30081 +cmd_error_internal 1024,31514 +DEFUN ("command-error-default-function", Fcommand_error_default_function,1043,32034 +DEFUN ("command-error-default-function", Fcommand_error_default_function,command-error-default-function1043,32034 +static Lisp_Object command_loop_2 1086,33641 +static Lisp_Object top_level_1 1087,33690 +command_loop 1094,33920 +command_loop_2 1134,35139 +top_level_2 1146,35343 +top_level_1 1152,35421 +DEFUN ("top-level", Ftop_level,1164,35791 +DEFUN ("top-level", Ftop_level,top-level1164,35791 +user_error 1183,36292 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,1189,36433 +DEFUN ("exit-recursive-edit", Fexit_recursive_edit,exit-recursive-edit1189,36433 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,1201,36823 +DEFUN ("abort-recursive-edit", Fabort_recursive_edit,abort-recursive-edit1201,36823 +tracking_off 1216,37285 +DEFUN ("internal--track-mouse", Ftrack_mouse,1234,37820 +DEFUN ("internal--track-mouse", Ftrack_mouse,track-mouse1234,37820 +bool ignore_mouse_drag_p;1256,38396 +some_mouse_moved 1259,38445 +static int read_key_sequence 1282,38803 +static void adjust_point_for_property 1284,38921 +Lisp_Object last_undo_boundary;1287,39036 +command_loop_1 1294,39277 +read_menu_command 1649,50893 +adjust_point_for_property 1678,51621 +safe_run_hooks_1 1831,57343 +safe_run_hooks_error 1841,57573 +safe_run_hook_funcall 1878,58580 +safe_run_hooks 1893,59062 +int poll_suppress_count;1908,59401 +static struct atimer *poll_timer;poll_timer1915,59491 +poll_for_input_1 1919,59593 +poll_for_input 1930,59793 +start_polling 1942,60057 +input_polling_used 1979,61095 +stop_polling 1994,61394 +set_poll_suppress_count 2009,61763 +bind_polling_period 2029,62145 +make_ctrl_char 2048,62496 +show_help_echo 2113,64459 +static Lisp_Object kbd_buffer_get_event 2152,65488 +static void record_char 2154,65600 +static Lisp_Object help_form_saved_window_configs;2156,65642 +read_char_help_form_unwind 2158,65705 +#define STOP_POLLING 2166,65963 +#define RESUME_POLLING 2170,66088 +read_event_from_main_queue 2175,66233 +read_decoded_event_from_main_queue 2249,68421 +#define MAX_ENCODED_BYTES 2254,68668 +echo_keystrokes_p 2342,71560 +read_char 2376,72852 +record_menu_key 3225,98953 +help_char_p 3258,99678 +record_char 3273,99957 +save_getcjmp 3412,104239 +restore_getcjmp 3418,104330 +readable_events 3430,104701 +int stop_character EXTERNALLY_VISIBLE;3497,106441 +event_to_kboard 3500,106497 +kbd_buffer_nr_stored 3522,107146 +kbd_buffer_store_event 3534,107487 +kbd_buffer_store_event_hold 3550,108029 +kbd_buffer_unget_event 3684,111621 +#define INPUT_EVENT_POS_MAX 3698,112022 +#define INPUT_EVENT_POS_MIN 3701,112151 +position_to_Time 3706,112291 +Time_to_position 3716,112518 +gen_help_event 3738,113175 +kbd_buffer_store_help_event 3756,113615 +discard_mouse_events 3773,113980 +kbd_buffer_events_waiting 3803,114715 +clear_event 3823,115072 +kbd_buffer_get_event 3836,115412 +process_special_events 4258,127885 +swallow_events 4322,129709 +timer_start_idle 4339,130102 +timer_stop_idle 4355,130580 +timer_resume_idle 4363,130724 +struct input_event last_timer_event EXTERNALLY_VISIBLE;4372,130916 +Lisp_Object pending_funcalls;4377,131176 +decode_timer 4381,131297 +timer_check_2 4414,132250 +timer_check 4572,136821 +DEFUN ("current-idle-time", Fcurrent_idle_time,4607,137666 +DEFUN ("current-idle-time", Fcurrent_idle_time,current-idle-time4607,137666 +static Lisp_Object accent_key_syms;4625,138243 +static Lisp_Object func_key_syms;4626,138279 +static Lisp_Object mouse_syms;4627,138313 +static Lisp_Object wheel_syms;4628,138344 +static Lisp_Object drag_n_drop_syms;4629,138375 +static const int lispy_accent_codes[lispy_accent_codes4634,138520 +static const char *const lispy_accent_keys[lispy_accent_keys4741,139882 +#define FUNCTION_KEY_OFFSET 4766,140318 +const char *const lispy_function_keys[lispy_function_keys4768,140351 +static const char *const lispy_multimedia_keys[lispy_multimedia_keys4962,148905 +static const char *const lispy_kana_keys[lispy_kana_keys5026,150139 +#define FUNCTION_KEY_OFFSET 5061,151755 +static const char *const lispy_function_keys[lispy_function_keys5065,151898 +#define ISO_FUNCTION_KEY_OFFSET 5149,154433 +static const char *const iso_lispy_function_keys[iso_lispy_function_keys5151,154473 +static Lisp_Object Vlispy_mouse_stem;5172,155332 +static const char *const lispy_wheel_names[lispy_wheel_names5174,155371 +static const char *const lispy_drag_n_drop_names[lispy_drag_n_drop_names5181,155623 +static short const scroll_bar_parts[scroll_bar_parts5189,155889 +static Lisp_Object button_down_location;5210,156914 +static int last_mouse_button;5215,157069 +static int last_mouse_x;5216,157099 +static int last_mouse_y;5217,157124 +static Time button_down_time;5218,157149 +static int double_click_count;5222,157233 +make_lispy_position 5228,157394 +toolkit_menubar_in_use 5456,163957 +make_scroll_bar_position 5469,164325 +make_lispy_event 5485,164971 +make_lispy_movement 6104,183534 +make_lispy_switch_frame 6131,184265 +make_lispy_focus_in 6137,184372 +make_lispy_focus_out 6145,184498 +parse_modifiers_uncached 6163,184948 +#define SINGLE_LETTER_MOD(6185,185468 +#undef SINGLE_LETTER_MOD6212,185909 +#define MULTI_LETTER_MOD(6214,185935 +#undef MULTI_LETTER_MOD6231,186403 +apply_modifiers_uncached 6273,187577 +static const char *const modifier_names[modifier_names6319,189196 +#define NUM_MOD_NAMES 6325,189402 +static Lisp_Object modifier_symbols;6327,189452 +lispy_modifier_list 6331,189589 +#define KEY_TO_CHAR(6353,190255 +parse_modifiers 6356,190331 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,6399,191520 +DEFUN ("internal-event-symbol-parse-modifiers", Fevent_symbol_parse_modifiers,event-symbol-parse-modifiers6399,191520 +apply_modifiers 6422,192394 +reorder_modifiers 6491,194723 +modify_event_symbol 6536,196531 +DEFUN ("event-convert-list", Fevent_convert_list,6628,199247 +DEFUN ("event-convert-list", Fevent_convert_list,event-convert-list6628,199247 +parse_solitary_modifier 6695,201138 +#define SINGLE_LETTER_MOD(6701,201261 +#define MULTI_LETTER_MOD(6705,201346 +#undef SINGLE_LETTER_MOD6763,202644 +#undef MULTI_LETTER_MOD6764,202669 +lucid_event_type_list_p 6775,202892 +get_input_pending 6814,203963 +record_asynch_buffer_change 6834,204582 +gobble_input 6872,205705 +tty_read_avail_input 6967,208313 +handle_async_input 7149,214042 +process_pending_signals 7165,214362 +unblock_input_to 7177,214648 +unblock_input 7200,215280 +totally_unblock_input 7209,215448 +handle_input_available_signal 7217,215532 +deliver_input_available_signal 7226,215703 +struct user_signal_info7235,215868 + int sig;7238,215918 + char *name;name7241,215959 + int npending;7244,216010 + struct user_signal_info *next;next7246,216027 +static struct user_signal_info *user_signals user_signals7250,216093 +add_user_signal 7253,216152 +handle_user_signal 7275,216601 +deliver_user_signal 7316,217561 +find_user_signal_name 7322,217662 +store_user_signal_events 7334,217844 +static void menu_bar_item 7362,218344 +static Lisp_Object menu_bar_one_keymap_changed_items;7363,218419 +static Lisp_Object menu_bar_items_vector;7368,218633 +static int menu_bar_items_index;7369,218675 +static const char *separator_names[separator_names7372,218710 +menu_separator_name_p 7393,219151 +menu_bar_items 7426,219855 +Lisp_Object item_properties;7568,224606 +menu_bar_item 7571,224648 +menu_item_eval_property_1 7647,227178 +eval_dyn 7658,227468 +menu_item_eval_property 7666,227678 +parse_menu_item 7686,228344 +static Lisp_Object tool_bar_items_vector;7965,236339 +static Lisp_Object tool_bar_item_properties;7970,236513 +static int ntool_bar_items;7974,236609 +static void init_tool_bar_items 7978,236667 +static void process_tool_bar_item 7979,236714 +static bool parse_tool_bar_item 7981,236804 +static void append_tool_bar_item 7982,236864 +tool_bar_items 7990,237086 +process_tool_bar_item 8075,239895 +#define PROP(8112,240972 +set_prop 8114,241041 +parse_tool_bar_item 8167,242456 +#undef PROP8379,248847 +init_tool_bar_items 8387,248972 +append_tool_bar_item 8401,249264 +read_char_x_menu_prompt 8443,250774 +read_char_minibuf_menu_prompt 8503,252448 +#define PUSH_C_STR(8527,253017 +follow_key 8726,258556 +active_maps 8733,258698 +typedef struct keyremap8742,259024 + Lisp_Object parent;8745,259110 + Lisp_Object map;8748,259227 + int start,8753,259449 + int start, end;8753,259449 +} keyremap;8754,259467 +access_keymap_keyremap 8764,259811 +keyremap_step 8811,261453 +test_undefined 8867,262937 +read_key_sequence 8916,264864 +read_key_sequence_vs 9826,295824 +DEFUN ("read-key-sequence", Fread_key_sequence,9885,297297 +DEFUN ("read-key-sequence", Fread_key_sequence,read-key-sequence9885,297297 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,9938,299985 +DEFUN ("read-key-sequence-vector", Fread_key_sequence_vector,read-key-sequence-vector9938,299985 +detect_input_pending 9950,300491 +detect_input_pending_ignore_squeezables 9959,300657 +detect_input_pending_run_timers 9967,300873 +clear_input_pending 9985,301365 +requeued_events_pending_p 9997,301735 +DEFUN ("input-pending-p", Finput_pending_p,10002,301816 +DEFUN ("input-pending-p", Finput_pending_p,input-pending-p10002,301816 +DEFUN ("recent-keys", Frecent_keys,10024,302599 +DEFUN ("recent-keys", Frecent_keys,recent-keys10024,302599 +DEFUN ("this-command-keys", Fthis_command_keys,10055,303520 +DEFUN ("this-command-keys", Fthis_command_keys,this-command-keys10055,303520 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,10068,303961 +DEFUN ("this-command-keys-vector", Fthis_command_keys_vector,this-command-keys-vector10068,303961 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,10080,304383 +DEFUN ("this-single-command-keys", Fthis_single_command_keys,this-single-command-keys10080,304383 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,10096,304958 +DEFUN ("this-single-command-raw-keys", Fthis_single_command_raw_keys,this-single-command-raw-keys10096,304958 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,10109,305498 +DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,reset-this-command-lengths10109,305498 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,10136,306513 +DEFUN ("clear-this-command-keys", Fclear_this_command_keys,clear-this-command-keys10136,306513 +DEFUN ("recursion-depth", Frecursion_depth,10158,307072 +DEFUN ("recursion-depth", Frecursion_depth,recursion-depth10158,307072 +DEFUN ("open-dribble-file", Fopen_dribble_file,10169,307409 +DEFUN ("open-dribble-file", Fopen_dribble_file,open-dribble-file10169,307409 +DEFUN ("discard-input", Fdiscard_input,10203,308450 +DEFUN ("discard-input", Fdiscard_input,discard-input10203,308450 +DEFUN ("suspend-emacs", Fsuspend_emacs,10225,308952 +DEFUN ("suspend-emacs", Fsuspend_emacs,suspend-emacs10225,308952 +stuff_buffered_input 10285,311048 +set_waiting_for_input 10323,312019 +clear_waiting_for_input 10337,312393 +handle_interrupt_signal 10351,312757 +deliver_interrupt_signal 10378,313645 +static int volatile force_quit_count;10387,313935 +handle_interrupt 10401,314417 +quit_throw_to_read_char 10541,318714 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,10562,319291 +DEFUN ("set-input-interrupt-mode", Fset_input_interrupt_mode,set-input-interrupt-mode10562,319291 +DEFUN ("set-output-flow-control", Fset_output_flow_control,10609,320519 +DEFUN ("set-output-flow-control", Fset_output_flow_control,set-output-flow-control10609,320519 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,10643,321435 +DEFUN ("set-input-meta-mode", Fset_input_meta_mode,set-input-meta-mode10643,321435 +DEFUN ("set-quit-char", Fset_quit_char,10694,322709 +DEFUN ("set-quit-char", Fset_quit_char,set-quit-char10694,322709 +DEFUN ("set-input-mode", Fset_input_mode,10729,323573 +DEFUN ("set-input-mode", Fset_input_mode,set-input-mode10729,323573 +DEFUN ("current-input-mode", Fcurrent_input_mode,10750,324462 +DEFUN ("current-input-mode", Fcurrent_input_mode,current-input-mode10750,324462 +DEFUN ("posn-at-x-y", Fposn_at_x_y,10787,325840 +DEFUN ("posn-at-x-y", Fposn_at_x_y,posn-at-x-y10787,325840 +DEFUN ("posn-at-point", Fposn_at_point,10824,327063 +DEFUN ("posn-at-point", Fposn_at_point,posn-at-point10824,327063 +init_kboard 10861,328217 +allocate_kboard 10893,329287 +wipe_kboard 10909,329640 +delete_kboard 10917,329754 +init_keyboard 10942,330284 +struct event_head11021,332699 + short var;11023,332719 + short kind;11024,332732 +static const struct event_head head_table[head_table11027,332750 +syms_of_keyboard 11045,333580 + DEFVAR_LISP ("internal--top-level-message"11058,333975 + DEFVAR_LISP ("last-command-event"11312,342176 + DEFVAR_LISP ("last-nonmenu-event"11315,342300 + DEFVAR_LISP ("last-input-event"11321,342639 + DEFVAR_LISP ("unread-command-events"11324,342733 + DEFVAR_LISP ("unread-post-input-method-events"11332,343193 + DEFVAR_LISP ("unread-input-method-events"11338,343532 + DEFVAR_LISP ("meta-prefix-char"11346,343901 + DEFVAR_KBOARD ("last-command"11351,344109 + DEFVAR_KBOARD ("real-last-command"11368,344790 + DEFVAR_KBOARD ("last-repeatable-command"11372,344976 + DEFVAR_LISP ("this-command"11378,345264 + DEFVAR_LISP ("real-this-command"11384,345501 + DEFVAR_LISP ("this-command-keys-shift-translated"11388,345683 + DEFVAR_LISP ("this-original-command"11396,346126 + DEFVAR_INT ("auto-save-interval"11403,346523 + DEFVAR_LISP ("auto-save-timeout"11408,346737 + DEFVAR_LISP ("echo-keystrokes"11415,347082 + DEFVAR_INT ("polling-period"11421,347353 + DEFVAR_LISP ("double-click-time"11428,347696 + DEFVAR_INT ("double-click-fuzz"11435,348032 + DEFVAR_INT ("num-input-keys"11446,348522 + DEFVAR_INT ("num-nonmacro-input-events"11452,348797 + DEFVAR_LISP ("last-event-frame"11457,349035 + DEFVAR_LISP ("tty-erase-char"11463,349314 + DEFVAR_LISP ("help-char"11466,349437 + DEFVAR_LISP ("help-event-list"11472,349720 + DEFVAR_LISP ("help-form"11477,349931 + DEFVAR_LISP ("prefix-help-command"11483,350179 + DEFVAR_LISP ("top-level"11489,350457 + DEFVAR_KBOARD ("keyboard-translate-table"11495,350678 + DEFVAR_BOOL ("cannot-suspend"11511,351491 + DEFVAR_BOOL ("menu-prompting"11516,351718 + DEFVAR_LISP ("menu-prompt-more-char"11526,352148 + DEFVAR_INT ("extra-keyboard-modifiers"11531,352394 + DEFVAR_LISP ("deactivate-mark"11545,353120 + DEFVAR_LISP ("pre-command-hook"11553,353489 + DEFVAR_LISP ("post-command-hook"11560,353844 + DEFVAR_LISP ("echo-area-clear-hook"11568,354207 + DEFVAR_LISP ("lucid-menu-bar-dirty-flag"11574,354422 + DEFVAR_LISP ("menu-bar-final-items"11578,354625 + DEFVAR_LISP ("tool-bar-separator-image-expression"11583,354875 + DEFVAR_KBOARD ("overriding-terminal-local-map"11589,355233 + DEFVAR_LISP ("overriding-local-map"11598,355655 + DEFVAR_LISP ("overriding-local-map-menu-flag"11607,356106 + DEFVAR_LISP ("special-event-map"11613,356445 + DEFVAR_LISP ("track-mouse"11617,356633 + DEFVAR_KBOARD ("system-key-alist"11620,356760 + DEFVAR_KBOARD ("local-function-key-map"11629,357141 + DEFVAR_KBOARD ("input-decode-map"11658,358600 + DEFVAR_LISP ("function-key-map"11675,359388 + DEFVAR_LISP ("key-translation-map"11683,359804 + DEFVAR_LISP ("deferred-action-list"11689,360148 + DEFVAR_LISP ("deferred-action-function"11694,360396 + DEFVAR_LISP ("delayed-warnings-list"11700,360695 + DEFVAR_LISP ("timer-list"11708,361103 + DEFVAR_LISP ("timer-idle-list"11712,361255 + DEFVAR_LISP ("input-method-function"11716,361418 + DEFVAR_LISP ("input-method-previous-message"11737,362387 + DEFVAR_LISP ("show-help-function"11744,362748 + DEFVAR_LISP ("disable-point-adjustment"11749,362980 + DEFVAR_LISP ("global-disable-point-adjustment"11761,363530 + DEFVAR_LISP ("minibuffer-message-timeout"11770,363896 + DEFVAR_LISP ("throw-on-input"11775,364174 + DEFVAR_LISP ("command-error-function"11781,364425 + DEFVAR_LISP ("enable-disabled-menus-and-buttons"11790,364912 + DEFVAR_LISP ("select-active-regions"11798,365239 + DEFVAR_LISP ("saved-region-selection"11807,365631 + DEFVAR_LISP ("selection-inhibit-update-commands"11815,366016 + DEFVAR_LISP ("debug-on-event"11825,366557 +keys_of_keyboard 11841,367118 +mark_kboards 11916,370437 + DEFVAR_LISP ("internal--top-level-message",\111058,333975 + DEFVAR_LISP ("last-command-event",\111312,342176 + DEFVAR_LISP ("last-nonmenu-event",\111315,342300 + DEFVAR_LISP ("last-input-event",\111321,342639 + DEFVAR_LISP ("unread-command-events",\111324,342733 + DEFVAR_LISP ("unread-post-input-method-events",\111332,343193 + DEFVAR_LISP ("unread-input-method-events",\111338,343532 + DEFVAR_LISP ("meta-prefix-char",\111346,343901 + DEFVAR_KBOARD ("last-command",\111351,344109 + DEFVAR_KBOARD ("real-last-command",\111368,344790 + DEFVAR_KBOARD ("last-repeatable-command",\111372,344976 + DEFVAR_LISP ("this-command",\111378,345264 + DEFVAR_LISP ("real-this-command",\111384,345501 + DEFVAR_LISP ("this-command-keys-shift-translated",\111388,345683 + DEFVAR_LISP ("this-original-command",\111396,346126 + DEFVAR_INT ("auto-save-interval",\111403,346523 + DEFVAR_LISP ("auto-save-timeout",\111408,346737 + DEFVAR_LISP ("echo-keystrokes",\111415,347082 + DEFVAR_INT ("polling-period",\111421,347353 + DEFVAR_LISP ("double-click-time",\111428,347696 + DEFVAR_INT ("double-click-fuzz",\111435,348032 + DEFVAR_INT ("num-input-keys",\111446,348522 + DEFVAR_INT ("num-nonmacro-input-events",\111452,348797 + DEFVAR_LISP ("last-event-frame",\111457,349035 + DEFVAR_LISP ("tty-erase-char",\111463,349314 + DEFVAR_LISP ("help-char",\111466,349437 + DEFVAR_LISP ("help-event-list",\111472,349720 + DEFVAR_LISP ("help-form",\111477,349931 + DEFVAR_LISP ("prefix-help-command",\111483,350179 + DEFVAR_LISP ("top-level",\111489,350457 + DEFVAR_KBOARD ("keyboard-translate-table",\111495,350678 + DEFVAR_BOOL ("cannot-suspend",\111511,351491 + DEFVAR_BOOL ("menu-prompting",\111516,351718 + DEFVAR_LISP ("menu-prompt-more-char",\111526,352148 + DEFVAR_INT ("extra-keyboard-modifiers",\111531,352394 + DEFVAR_LISP ("deactivate-mark",\111545,353120 + DEFVAR_LISP ("pre-command-hook",\111553,353489 + DEFVAR_LISP ("post-command-hook",\111560,353844 + DEFVAR_LISP ("echo-area-clear-hook",\111568,354207 + DEFVAR_LISP ("lucid-menu-bar-dirty-flag",\111574,354422 + DEFVAR_LISP ("menu-bar-final-items",\111578,354625 + DEFVAR_LISP ("tool-bar-separator-image-expression",\111583,354875 + DEFVAR_KBOARD ("overriding-terminal-local-map",\111589,355233 + DEFVAR_LISP ("overriding-local-map",\111598,355655 + DEFVAR_LISP ("overriding-local-map-menu-flag",\111607,356106 + DEFVAR_LISP ("special-event-map",\111613,356445 + DEFVAR_LISP ("track-mouse",\111617,356633 + DEFVAR_KBOARD ("system-key-alist",\111620,356760 + DEFVAR_KBOARD ("local-function-key-map",\111629,357141 + DEFVAR_KBOARD ("input-decode-map",\111658,358600 + DEFVAR_LISP ("function-key-map",\111675,359388 + DEFVAR_LISP ("key-translation-map",\111683,359804 + DEFVAR_LISP ("deferred-action-list",\111689,360148 + DEFVAR_LISP ("deferred-action-function",\111694,360396 + DEFVAR_LISP ("delayed-warnings-list",\111700,360695 + DEFVAR_LISP ("timer-list",\111708,361103 + DEFVAR_LISP ("timer-idle-list",\111712,361255 + DEFVAR_LISP ("input-method-function",\111716,361418 + DEFVAR_LISP ("input-method-previous-message",\111737,362387 + DEFVAR_LISP ("show-help-function",\111744,362748 + DEFVAR_LISP ("disable-point-adjustment",\111749,362980 + DEFVAR_LISP ("global-disable-point-adjustment",\111761,363530 + DEFVAR_LISP ("minibuffer-message-timeout",\111770,363896 + DEFVAR_LISP ("throw-on-input",\111775,364174 + DEFVAR_LISP ("command-error-function",\111781,364425 + DEFVAR_LISP ("enable-disabled-menus-and-buttons",\111790,364912 + DEFVAR_LISP ("select-active-regions",\111798,365239 + DEFVAR_LISP ("saved-region-selection",\111807,365631 + DEFVAR_LISP ("selection-inhibit-update-commands",\111815,366016 + DEFVAR_LISP ("debug-on-event",\111825,366557 c-src/emacs/src/lisp.h,41391 #define EMACS_LISP_H22,801 @@ -3274,112 +3274,112 @@ el-src/emacs/lisp/progmodes/etags.el,5188 (defcustom tags-tag-face 148,5700 (defcustom tags-apropos-verbose 154,5835 (defcustom tags-apropos-additional-actions 160,5999 -(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6918 -(defvar default-tags-table-function 189,7098 -(defvar tags-location-ring 194,7324 -(defvar tags-table-files 201,7600 -(defvar tags-completion-table 206,7767 -(defvar tags-included-tables 209,7859 -(defvar next-file-list 212,7954 -(defvar tags-table-format-functions 217,8060 -(defvar file-of-tag-function 224,8441 -(defvar tags-table-files-function 228,8635 -(defvar tags-completion-table-function 230,8746 -(defvar snarf-tag-function 232,8841 -(defvar goto-tag-location-function 236,9050 -(defvar find-tag-regexp-search-function 239,9223 -(defvar find-tag-regexp-tag-order 241,9344 -(defvar find-tag-regexp-next-line-after-failure-p 243,9453 -(defvar find-tag-search-function 245,9573 -(defvar find-tag-tag-order 247,9680 -(defvar find-tag-next-line-after-failure-p 249,9775 -(defvar list-tags-function 251,9881 -(defvar tags-apropos-function 253,9969 -(defvar tags-included-tables-function 255,10063 -(defvar verify-tags-table-function 257,10182 -(defun initialize-new-tags-table 260,10293 -(defun tags-table-mode 276,10981 -(defun visit-tags-table 285,11246 -(defun tags-table-check-computed-list 321,12784 -(defun tags-table-extend-computed-list 360,14655 -(defun tags-expand-table-name 400,16368 -(defun tags-table-list-member 409,16711 -(defun tags-verify-table 421,17183 -(defun tags-table-including 470,19303 -(defun tags-next-table 522,21347 -(defun visit-tags-table-buffer 543,22204 -(defun tags-reset-tags-tables 712,28514 -(defun file-of-tag 731,29171 -(defun tags-table-files 740,29521 -(defun tags-included-tables 749,29871 -(defun tags-completion-table 755,30117 -(defun tags-lazy-completion-table 783,31311 -(defun tags-completion-at-point-function 799,31946 -(defun find-tag-tag 818,32696 -(defvar last-tag 837,33369 -(defun find-tag-interactive 840,33428 -(defvar find-tag-history 852,33843 -(defvar etags-case-fold-search)855,33908 -(defvar etags-syntax-table)856,33940 -(defvar local-find-tag-hook)857,33968 -(defun find-tag-noselect 860,34013 -(defun find-tag 932,37127 -(defun find-tag-other-window 959,38343 -(defun find-tag-other-frame 1000,40271 -(defun find-tag-regexp 1025,41445 -(defalias 'pop-tag-mark pop-tag-mark1049,42607 -(defvar tag-lines-already-matched 1052,42658 -(defun find-tag-in-order 1055,42765 -(defun tag-find-file-of-tag-noselect 1167,47111 -(defun tag-find-file-of-tag 1200,48957 -(defun etags-recognize-tags-table 1208,49183 -(defun etags-verify-tags-table 1241,50814 -(defun etags-file-of-tag 1246,51012 -(defun etags-tags-completion-table 1256,51347 -(defun etags-snarf-tag 1286,52553 -(defun etags-goto-tag-location 1324,54122 -(defun etags-list-tags 1388,56565 -(defmacro tags-with-face 1423,57840 -(defun etags-tags-apropos-additional 1431,58173 -(defun etags-tags-apropos 1465,59410 -(defun etags-tags-table-files 1527,61619 -(defun etags-tags-included-tables 1542,62055 -(defun tags-recognize-empty-tags-table 1559,62595 -(defun tag-exact-file-name-match-p 1587,63741 -(defun tag-file-name-match-p 1596,64134 -(defun tag-exact-match-p 1609,64690 -(defun tag-implicit-name-match-p 1620,65258 -(defun tag-symbol-match-p 1633,65858 -(defun tag-word-match-p 1643,66294 -(defun tag-partial-file-name-match-p 1652,66692 -(defun tag-any-match-p 1662,67136 -(defun tag-re-match-p 1667,67320 -(defcustom tags-loop-revert-buffers 1675,67569 -(defun next-file 1685,67978 -(defvar tags-loop-operate 1760,70892 -(defvar tags-loop-scan1763,70986 -(defun tags-loop-eval 1771,71315 -(defun tags-loop-continue 1782,71644 -(defun tags-search 1850,73950 -(defun tags-query-replace 1871,74776 -(defun tags-complete-tags-table-file 1896,76000 -(defun list-tags 1906,76379 -(defun tags-apropos 1934,77332 -(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78158 -(defun select-tags-table 1964,78397 -(defvar select-tags-table-mode-map 2019,80524 -(define-derived-mode select-tags-table-mode 2030,80907 -(defun select-tags-table-select 2034,81091 -(defun select-tags-table-quit 2043,81457 -(defun complete-tag 2049,81612 -(defconst etags--xref-limit 2074,82553 -(defvar etags-xref-find-definitions-tag-order 2076,82588 -(defun etags-xref-find 2082,82878 -(defun etags--xref-find-definitions 2096,83407 -(defclass xref-etags-location 2129,85121 -(defun xref-make-etags-location 2135,85344 -(cl-defmethod xref-location-marker 2139,85499 -(cl-defmethod xref-location-line 2146,85743 +(defvaralias 'find-tag-marker-ring find-tag-marker-ring183,6921 +(defvar default-tags-table-function 189,7101 +(defvar tags-location-ring 194,7327 +(defvar tags-table-files 201,7603 +(defvar tags-completion-table 206,7770 +(defvar tags-included-tables 209,7862 +(defvar next-file-list 212,7957 +(defvar tags-table-format-functions 217,8063 +(defvar file-of-tag-function 224,8444 +(defvar tags-table-files-function 228,8638 +(defvar tags-completion-table-function 230,8749 +(defvar snarf-tag-function 232,8844 +(defvar goto-tag-location-function 236,9053 +(defvar find-tag-regexp-search-function 239,9226 +(defvar find-tag-regexp-tag-order 241,9347 +(defvar find-tag-regexp-next-line-after-failure-p 243,9456 +(defvar find-tag-search-function 245,9576 +(defvar find-tag-tag-order 247,9683 +(defvar find-tag-next-line-after-failure-p 249,9778 +(defvar list-tags-function 251,9884 +(defvar tags-apropos-function 253,9972 +(defvar tags-included-tables-function 255,10066 +(defvar verify-tags-table-function 257,10185 +(defun initialize-new-tags-table 260,10296 +(defun tags-table-mode 276,10984 +(defun visit-tags-table 285,11249 +(defun tags-table-check-computed-list 321,12787 +(defun tags-table-extend-computed-list 360,14658 +(defun tags-expand-table-name 400,16371 +(defun tags-table-list-member 409,16714 +(defun tags-verify-table 421,17186 +(defun tags-table-including 470,19306 +(defun tags-next-table 522,21350 +(defun visit-tags-table-buffer 543,22207 +(defun tags-reset-tags-tables 712,28517 +(defun file-of-tag 731,29174 +(defun tags-table-files 740,29524 +(defun tags-included-tables 749,29874 +(defun tags-completion-table 755,30120 +(defun tags-lazy-completion-table 783,31314 +(defun tags-completion-at-point-function 799,31949 +(defun find-tag-tag 818,32699 +(defvar last-tag 837,33372 +(defun find-tag-interactive 840,33431 +(defvar find-tag-history 852,33846 +(defvar etags-case-fold-search)855,33911 +(defvar etags-syntax-table)856,33943 +(defvar local-find-tag-hook)857,33971 +(defun find-tag-noselect 860,34016 +(defun find-tag 932,37130 +(defun find-tag-other-window 959,38346 +(defun find-tag-other-frame 1000,40274 +(defun find-tag-regexp 1025,41448 +(defalias 'pop-tag-mark pop-tag-mark1049,42610 +(defvar tag-lines-already-matched 1052,42661 +(defun find-tag-in-order 1055,42768 +(defun tag-find-file-of-tag-noselect 1167,47114 +(defun tag-find-file-of-tag 1200,48960 +(defun etags-recognize-tags-table 1208,49186 +(defun etags-verify-tags-table 1241,50817 +(defun etags-file-of-tag 1246,51015 +(defun etags-tags-completion-table 1256,51350 +(defun etags-snarf-tag 1286,52556 +(defun etags-goto-tag-location 1324,54125 +(defun etags-list-tags 1388,56568 +(defmacro tags-with-face 1423,57843 +(defun etags-tags-apropos-additional 1431,58176 +(defun etags-tags-apropos 1465,59413 +(defun etags-tags-table-files 1527,61622 +(defun etags-tags-included-tables 1542,62058 +(defun tags-recognize-empty-tags-table 1559,62598 +(defun tag-exact-file-name-match-p 1587,63744 +(defun tag-file-name-match-p 1596,64137 +(defun tag-exact-match-p 1609,64693 +(defun tag-implicit-name-match-p 1620,65261 +(defun tag-symbol-match-p 1633,65861 +(defun tag-word-match-p 1643,66297 +(defun tag-partial-file-name-match-p 1652,66695 +(defun tag-any-match-p 1662,67139 +(defun tag-re-match-p 1667,67323 +(defcustom tags-loop-revert-buffers 1675,67572 +(defun next-file 1685,67981 +(defvar tags-loop-operate 1760,70895 +(defvar tags-loop-scan1763,70989 +(defun tags-loop-eval 1771,71318 +(defun tags-loop-continue 1782,71647 +(defun tags-search 1850,73953 +(defun tags-query-replace 1871,74779 +(defun tags-complete-tags-table-file 1896,76003 +(defun list-tags 1906,76382 +(defun tags-apropos 1934,77335 +(define-button-type 'tags-select-tags-tabletags-select-tags-table1957,78161 +(defun select-tags-table 1964,78400 +(defvar select-tags-table-mode-map 2019,80527 +(define-derived-mode select-tags-table-mode 2030,80910 +(defun select-tags-table-select 2034,81094 +(defun select-tags-table-quit 2043,81460 +(defun complete-tag 2049,81615 +(defconst etags--xref-limit 2074,82556 +(defvar etags-xref-find-definitions-tag-order 2076,82591 +(defun etags-xref-find 2082,82881 +(defun etags--xref-find-definitions 2096,83410 +(defclass xref-etags-location 2129,85124 +(defun xref-make-etags-location 2135,85347 +(cl-defmethod xref-location-marker 2139,85502 +(cl-defmethod xref-location-line 2146,85746 erl-src/gs_dialog.erl,98 -define(VERSION2,32 commit 559c276942e4b2d47244802cfb31fb79e61f9a7f Author: Eli Zaretskii Date: Thu Jun 9 19:40:25 2022 +0300 ; * src/window.c (window_body_unit_from_symbol): Fix Lisp EQ. diff --git a/src/window.c b/src/window.c index e5666ce38e..ac8408a9a9 100644 --- a/src/window.c +++ b/src/window.c @@ -1018,9 +1018,11 @@ static enum window_body_unit window_body_unit_from_symbol (Lisp_Object unit) { return - (unit == Qremap ? WINDOW_BODY_IN_REMAPPED_CHARS - : NILP (unit) ? WINDOW_BODY_IN_CANONICAL_CHARS - : WINDOW_BODY_IN_PIXELS); + EQ (unit, Qremap) + ? WINDOW_BODY_IN_REMAPPED_CHARS + : (NILP (unit) + ? WINDOW_BODY_IN_CANONICAL_CHARS + : WINDOW_BODY_IN_PIXELS); } /* Return the number of lines/pixels of W's body. Don't count any mode commit 4ac18cc34a7b1e28f2c3e60acc542830c9bc0090 Author: Lars Ingebrigtsen Date: Thu Jun 9 17:13:58 2022 +0200 Adjust browse-url test after previous browse-url change diff --git a/test/lisp/net/browse-url-tests.el b/test/lisp/net/browse-url-tests.el index c94719c97a..8fcc831d53 100644 --- a/test/lisp/net/browse-url-tests.el +++ b/test/lisp/net/browse-url-tests.el @@ -73,7 +73,7 @@ (should (equal (browse-url-encode-url "\"a\" \"b\"") "%22a%22%20%22b%22")) (should (equal (browse-url-encode-url "(a) (b)") "%28a%29%20%28b%29")) - (should (equal (browse-url-encode-url "a$ b$") "a%24%20b%24"))) + (should (equal (browse-url-encode-url "a$ b$") "a$%20b$"))) (ert-deftest browse-url-tests-url-at-point () (with-temp-buffer commit 835b431639c94489d92a79f6ce54731a0dd0e3e1 Author: Lars Ingebrigtsen Date: Thu Jun 9 17:11:54 2022 +0200 Make browse-url-encode-url encode even less * lisp/net/browse-url.el (browse-url-encode-url): Don't encode dollar signs, because that's out of spec (bug#55873). diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 362dcf25b5..5b58c8ed86 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -635,9 +635,10 @@ CHARS is a regexp that matches a character." The annoying characters are those that can mislead a web browser regarding its parameter treatment." ;; FIXME: Is there an actual example of a web browser getting - ;; confused? (This used to encode commas, but at least Firefox - ;; handles commas correctly and doesn't accept encoded commas.) - (browse-url-url-encode-chars url "[\"()$ ]")) + ;; confused? (This used to encode commas and dollar signs, but at + ;; least Firefox handles commas correctly and doesn't accept those + ;; encoded.) + (browse-url-url-encode-chars url "[\"() ]")) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; URL input commit f0cd91067d5706bfe95f9fc8bb05c8a9e0e2d052 Author: Lars Ingebrigtsen Date: Thu Jun 9 16:41:03 2022 +0200 Improve `C-h b' output for remapped commands. * lisp/help.el (describe-map): Include the bindings of the remapped commands (bug#14084). This will result in output like this, instead of just listing the remapped commands: ido-display-buffer C-x 4 C-o display-buffer ido-display-buffer-other-frame C-x 5 C-o display-buffer-other-frame ido-insert-buffer C-x x i insert-buffer ido-kill-buffer C-x k kill-buffer ido-switch-buffer C-x b switch-to-buffer ido-switch-buffer-other-frame C-x 5 b switch-to-buffer-other-frame ido-switch-buffer-other-window C-x 4 b switch-to-buffer-other-window diff --git a/lisp/help.el b/lisp/help.el index 1faebdf461..4e0d807cb2 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1503,12 +1503,30 @@ in `describe-map-tree'." (let ((vect (sort vect 'help--describe-map-compare)) (columns ()) line-start key-end column) + ;; If we're in a section of the output, then also + ;; display the bindings of the keys that we've remapped from. + ;; This enables the user to actually see what keys to tap to + ;; execute the remapped commands. + (when (equal prefix [remap]) + (dolist (binding (prog1 vect + (setq vect nil))) + (push binding vect) + (when-let ((other (and (not (eq (car binding) 'self-insert-command)) + (car (where-is-internal (car binding)))))) + (push (list (elt other (1- (length other))) + (car binding) + nil + (seq-into (butlast (seq-into other 'list)) 'vector)) + vect))) + (setq vect (nreverse vect))) ;; Now output them in sorted order. (while vect (let* ((elem (car vect)) - (start (car elem)) - (definition (cadr elem)) - (shadowed (caddr elem)) + (start (nth 0 elem)) + (definition (nth 1 elem)) + (shadowed (nth 2 elem)) + ;; We override the prefix for the extra commands. + (prefix (or (nth 3 elem) prefix)) (end start)) ;; Find consecutive chars that are identically defined. (when (fixnump start) commit 8cb7682e885c943228299c4e6b7adb6a398c8aae Author: Lars Ingebrigtsen Date: Thu Jun 9 15:57:04 2022 +0200 New setting for mouse-drag-copy-region to not put "" onto kill ring * doc/emacs/frames.texi (Mouse Commands): Document it. * lisp/mouse.el (mouse-drag-copy-region): Add value (bug#17211) for not putting "" strings onto the kill ring. (mouse-set-region, mouse-save-then-kill): Use the new value. diff --git a/doc/emacs/frames.texi b/doc/emacs/frames.texi index a853c9a228..fa248c1a58 100644 --- a/doc/emacs/frames.texi +++ b/doc/emacs/frames.texi @@ -128,6 +128,12 @@ In addition, the text in the region becomes the primary selection non-@code{nil} value, dragging the mouse over a stretch of text also adds the text to the kill ring. The default is @code{nil}. + If this variable is @code{non-empty}, only copy to the kill ring if +the region is non-empty. For instance, if you mouse drag an area that +is less than a half a character, you'd normally get the empty string +in your kill ring, but with @code{non-empty}, this short mouse drag +won't affect the kill ring. + @vindex mouse-scroll-min-lines If you move the mouse off the top or bottom of the window while dragging, the window scrolls at a steady rate until you move the mouse diff --git a/etc/NEWS b/etc/NEWS index 9fc8a74419..cd4b1b06ec 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -331,6 +331,10 @@ to another program. If non-nil, this option allows scrolling a window while dragging text around without a scroll wheel. ++++ +*** 'mouse-drag-copy-region' can now be 'non-empty'. +This inhibits putting empty strings onto the kill ring. + +++ ** New user options 'dnd-indicate-insertion-point' and 'dnd-scroll-margin'. These options allow adjusting point and scrolling a window when diff --git a/lisp/mouse.el b/lisp/mouse.el index 9cf6635a01..14cb20c234 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -53,9 +53,17 @@ mouse cursor to the echo area." This affects `mouse-save-then-kill' (\\[mouse-save-then-kill]) in addition to mouse drags. +If this variable is `non-empty', only copy to the kill ring if +the region is non-empty. For instance, if you mouse drag an area +that is less than a half a character, you'd normally get the +empty string in your kill ring, but with this value, this short +mouse drag won't affect the kill ring. + This variable applies only to mouse adjustments in Emacs, not selecting and adjusting regions in other windows." - :type 'boolean + :type '(choice (const :tag "No" nil) + (const :tag "Yes" t) + (const :tag "Non-empty" non-empty)) :version "24.1") (defcustom mouse-1-click-follows-link 450 @@ -1423,7 +1431,11 @@ command alters the kill ring or not." (if (< end beg) (setq end (nth 0 range) beg (nth 1 range)) (setq beg (nth 0 range) end (nth 1 range))))) - (and mouse-drag-copy-region (integerp beg) (integerp end) + (when (and mouse-drag-copy-region + (integerp beg) + (integerp end) + (or (not (eq mouse-drag-copy-region 'non-empty)) + (/= beg end))) ;; Don't set this-command to `kill-region', so a following ;; C-w won't double the text in the kill ring. Ignore ;; `last-command' so we don't append to a preceding kill. @@ -2112,7 +2124,9 @@ if `mouse-drag-copy-region' is non-nil)." (if before-scroll (goto-char before-scroll))) (exchange-point-and-mark) (mouse-set-region-1) - (when mouse-drag-copy-region + (when (and mouse-drag-copy-region + (or (not (eq mouse-drag-copy-region 'non-empty)) + (not (/= (mark t) (point))))) (kill-new (filter-buffer-substring (mark t) (point)))) (setq mouse-save-then-kill-posn click-pt))))) commit e99f41f03a97641ee05ba4a27f8b91c190f55df1 Author: Po Lu Date: Thu Jun 9 21:48:19 2022 +0800 Fix recalculation of `icon-title-format' after a frame is iconified Previously it would only happen upon the next mode line redisplay, meaning that just pressing C-z would not update the implicit title, since C-z doesn't cause a redisplay. * src/dispextern.h: Update prototypes. * src/frame.h (SET_FRAME_ICONIFIED): De-slugify. Call `gui_consider_frame_title', since `icon-title-format' might be different from the current frame title. * src/xdisp.c (gui_consider_frame_title): Export (also in dispextern.h). (bug#55850) diff --git a/src/dispextern.h b/src/dispextern.h index 910f630a50..c7399ca299 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3470,6 +3470,7 @@ extern void expose_frame (struct frame *, int, int, int, int); extern bool gui_intersect_rectangles (const Emacs_Rectangle *, const Emacs_Rectangle *, Emacs_Rectangle *); +extern void gui_consider_frame_title (Lisp_Object); #endif /* HAVE_WINDOW_SYSTEM */ extern void note_mouse_highlight (struct frame *, int, int); diff --git a/src/frame.h b/src/frame.h index a164853e09..458b6257e4 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1293,8 +1293,28 @@ SET_FRAME_VISIBLE (struct frame *f, int v) } /* Set iconified status of frame F. */ -#define SET_FRAME_ICONIFIED(f, i) \ - (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i)) +INLINE void +SET_FRAME_ICONIFIED (struct frame *f, int i) +{ +#ifdef HAVE_WINDOW_SYSTEM + Lisp_Object frame; +#endif + + eassert (0 <= (i) && (i) <= 1); + + f->iconified = i; + +#ifdef HAVE_WINDOW_SYSTEM + /* Iconifying a frame might cause the frame title to change if no + title was explicitly specified. Force the frame title to be + recomputed. */ + + XSETFRAME (frame, f); + + if (FRAME_WINDOW_P (f)) + gui_consider_frame_title (frame); +#endif +} extern Lisp_Object selected_frame; extern Lisp_Object old_selected_frame; diff --git a/src/xdisp.c b/src/xdisp.c index 07324815d9..2245326b0d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -13148,7 +13148,7 @@ store_mode_line_noprop (const char *string, int field_width, int precision) Vicon_title_format if FRAME is iconified, otherwise it is frame_title_format. */ -static void +void gui_consider_frame_title (Lisp_Object frame) { struct frame *f = XFRAME (frame); commit 22a832ad82ed7d099e6ee3a947a5841d84e475c4 Author: Lars Ingebrigtsen Date: Thu Jun 9 15:22:11 2022 +0200 Mention the #f syntax from cl-prin1 * doc/lispref/objects.texi (Special Read Syntax): Mention #f, which is in cl-prin1 output (bug#55853). diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index b8e2dc5ab9..a715b45a6c 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi @@ -178,6 +178,12 @@ files. Skip the next @samp{N} characters (@pxref{Comments}). This is used in byte-compiled files, and is not meant to be used in Emacs Lisp source files. + +@item #f +Indicates that the following form isn't readable by the Emacs Lisp +reader. This is only in text for display purposes (when that would +look prettier than alternative ways of indicating an unreadable form) +and will never appear in any Lisp file. @end table commit 3fd08543782d0d417eaa2dda0727ea16b3271710 Author: Michael Albinus Date: Thu Jun 9 14:44:00 2022 +0200 Fix file name quoting in tramp-smb.el (do not merge) * lisp/net/tramp-smb.el (tramp-smb-handle-write-region): Quote tmpfile. (tramp-smb-get-localname): Remove superfluous test. (Bug#55855) * test/lisp/net/tramp-tests.el (tramp-test03-file-name-method-rules): Remove superfluous checks. diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index 2aaa6e8ab3..dfcb7162c8 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -1631,7 +1631,7 @@ errors for shares like \"C$/\", which are common in Microsoft Windows." v 3 (format "Moving tmp file %s to %s" tmpfile filename) (unwind-protect (unless (tramp-smb-send-command - v (format "put %s \"%s\"" + v (format "put \"%s\" \"%s\"" tmpfile (tramp-smb-get-localname v))) (tramp-error v 'file-error "Cannot write `%s'" filename)) (delete-file tmpfile))) @@ -1695,9 +1695,8 @@ If VEC has no cifs capabilities, exchange \"/\" by \"\\\\\"." (when (string-match "\\(\\$\\$\\)\\(/\\|$\\)" localname) (setq localname (replace-match "$" nil nil localname 1))) - ;; A period followed by a space, or trailing periods and spaces, - ;; are not supported. - (when (string-match-p "\\. \\|\\.$\\| $" localname) + ;; A trailing space is not supported. + (when (string-match-p " $" localname) (tramp-error vec 'file-error "Invalid file name %s" (tramp-make-tramp-file-name vec localname))) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 61fa6a5ae4..9071beedf2 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -2028,17 +2028,7 @@ Also see `ignore'." :type 'user-error) (should-error (expand-file-name "/method:user1@host1|ssh:user2@host2:/path/to/file") - :type 'user-error)) - - ;; Samba does not support file names with periods followed by - ;; spaces, and trailing periods or spaces. - (when (tramp--test-smb-p) - (dolist (file '("foo." "foo. bar" "foo ")) - (should-error - (tramp-smb-get-localname - (tramp-dissect-file-name - (expand-file-name file tramp-test-temporary-file-directory))) - :type 'file-error)))) + :type 'user-error))) (ert-deftest tramp-test04-substitute-in-file-name () "Check `substitute-in-file-name'." commit 39d2efbfae1dc081258a764f3c47f5f492f38fec Author: Lars Ingebrigtsen Date: Thu Jun 9 14:42:31 2022 +0200 Make `line-number-at-pos' work more like in earlier Emacs versions * src/fns.c (Fline_number_at_pos): Allow calling with position outside the region if called with ABSOLUTE non-nil (bug#55847). This isn't announced in the doc string, but makes function compatible with the version in earlier Emacs versions. diff --git a/src/fns.c b/src/fns.c index 2c206c62b2..fceab9ba0c 100644 --- a/src/fns.c +++ b/src/fns.c @@ -5869,9 +5869,12 @@ from the absolute start of the buffer, disregarding the narrowing. */) if (!NILP (absolute)) start = BEG_BYTE; - /* Check that POSITION is in the accessible range of the buffer. */ - if (pos < BEGV || pos > ZV) + /* Check that POSITION is in the accessible range of the buffer, or, + if we're reporting absolute positions, in the buffer. */ + if (NILP (absolute) && (pos < BEGV || pos > ZV)) args_out_of_range_3 (make_int (pos), make_int (BEGV), make_int (ZV)); + else if (!NILP (absolute) && (pos < 1 || pos > Z)) + args_out_of_range_3 (make_int (pos), make_int (1), make_int (Z)); return make_int (count_lines (start, CHAR_TO_BYTE (pos)) + 1); } commit 64b5fd2e435312346189852013c7504780f7c1d2 Merge: c29fb3e0d8 06173e6949 Author: Po Lu Date: Thu Jun 9 19:44:31 2022 +0800 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs commit c29fb3e0d8255a0f0e40f70f6a0e290dccfdd302 Author: Po Lu Date: Thu Jun 9 19:42:56 2022 +0800 Never return tooltip frames from ns-begin-drag * src/nsterm.m ([EmacsWindow draggedImage:movedTo:]): ([EmacsWindow beginDrag:forPasteboard...]): Don't return frame if tooltip. diff --git a/src/nsterm.m b/src/nsterm.m index 3b2830e73d..891d52ea3f 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -9651,7 +9651,8 @@ - (void) draggedImage: (NSImage *) dragged_image dnd_mode = RETURN_FRAME_NOW; if (dnd_mode != RETURN_FRAME_NOW - || ![[w delegate] isKindOfClass: [EmacsView class]]) + || ![[w delegate] isKindOfClass: [EmacsView class]] + || ((EmacsView *) [w delegate])->emacsframe->tooltip) goto out; dnd_return_frame = ((EmacsView *) [w delegate])->emacsframe; @@ -9709,7 +9710,8 @@ - (NSDragOperation) beginDrag: (NSDragOperation) op belowWindowWithWindowNumber: 0]; w = [NSApp windowWithWindowNumber: window_number]; - if (w && [[w delegate] isKindOfClass: [EmacsView class]]) + if (w && [[w delegate] isKindOfClass: [EmacsView class]] + && !((EmacsView *) [w delegate])->emacsframe->tooltip) { *frame_return = ((EmacsView *) [w delegate])->emacsframe; [image release]; commit 06173e69496abe28c7db2f3154d050c41d040091 Author: Eli Zaretskii Date: Thu Jun 9 13:27:34 2022 +0300 ; Fix typos in Kharoshthi script support * etc/HELLO: * lisp/leim/quail/misc-lang.el ("kharoshthi"): * lisp/language/misc-lang.el ("Kharoshthi"): Fix typos. diff --git a/etc/HELLO b/etc/HELLO index 746827f9e3..8787a6e0ae 100644 --- a/etc/HELLO +++ b/etc/HELLO @@ -72,7 +72,7 @@ Javanese (ꦧꦱꦗꦮꦶ) console.log("ꦲꦭꦺꦴ"); Kaithi (𑂍𑂶𑂟𑂲) 𑂩𑂰𑂧𑂩𑂰𑂧 Kannada (ಕನ್ನಡ) ನಮಸ್ಕಾರ -Kharoṣṭhī (𐨑𐨪𐨆𐨯𐨠𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁 +Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁 Khmer (ភាសាខ្មែរ) ជំរាបសួរ Lakota (Lakȟotiyapi) Taŋyáŋ yahí! Lao (ພາສາລາວ) ສະບາຍດີ / ຂໍໃຫ້ໂຊກດີ diff --git a/lisp/leim/quail/misc-lang.el b/lisp/leim/quail/misc-lang.el index e4e36b2dee..0c4a0d4ce4 100644 --- a/lisp/leim/quail/misc-lang.el +++ b/lisp/leim/quail/misc-lang.el @@ -101,7 +101,7 @@ ;; conventions for Sanskrit, extended for Kharoṣṭhī special characters. ;; Author: Stefan Baums . (quail-define-package - "kharoshthi" "Kharoshhi" "𐨑" nil + "kharoshthi" "Kharoshthi" "𐨑" nil "Kharoṣṭhī input method." nil t t t t nil nil nil nil nil t) (quail-define-rules commit e563020eea738febed38194d9b0984473c852f3f Author: Po Lu Date: Thu Jun 9 18:20:59 2022 +0800 Handle monitor attribute updates during drag-and-drop * src/xterm.c (x_monitors_changed_cb): (handle_one_xevent): Set x_dnd_monitors during monitor changes. diff --git a/src/xterm.c b/src/xterm.c index 557555e7a4..f0cd5e9c8b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15626,6 +15626,9 @@ x_monitors_changed_cb (GdkScreen *gscr, gpointer user_data) } dpyinfo->last_monitor_attributes_list = current_monitors; + + if (x_dnd_in_progress && x_dnd_update_tooltip) + x_dnd_monitors = current_monitors; } #endif @@ -21409,6 +21412,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, inev.ie.kind = NO_EVENT; dpyinfo->last_monitor_attributes_list = current_monitors; + + if (x_dnd_in_progress && x_dnd_update_tooltip) + x_dnd_monitors = current_monitors; } #endif OTHER: commit 521de5ab626948044f2478245677cd0b801110d9 Author: Stefan Baums Date: Sun Jun 5 19:18:23 2022 +0200 Add support for the Kharoshthi script * etc/NEWS: Announce the new language environment and script. * etc/HELLO: Add Kharoshthi greeting. * lisp/leim/quail/misc-lang.el ("kharoshthi"): New input method. * lisp/language/misc-lang.el ("Kharoshthi"): New language environment. Set up composition rules for Kharoshthi. (Bug#55539) diff --git a/etc/HELLO b/etc/HELLO index 6694501a7d..746827f9e3 100644 --- a/etc/HELLO +++ b/etc/HELLO @@ -72,6 +72,7 @@ Javanese (ꦧꦱꦗꦮꦶ) console.log("ꦲꦭꦺꦴ"); Kaithi (𑂍𑂶𑂟𑂲) 𑂩𑂰𑂧𑂩𑂰𑂧 Kannada (ಕನ್ನಡ) ನಮಸ್ಕಾರ +Kharoṣṭhī (𐨑𐨪𐨆𐨯𐨠𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁 Khmer (ភាសាខ្មែរ) ជំរាបសួរ Lakota (Lakȟotiyapi) Taŋyáŋ yahí! Lao (ພາສາລາວ) ສະບາຍດີ / ຂໍໃຫ້ໂຊກດີ diff --git a/etc/NEWS b/etc/NEWS index 5710c4e50a..9fc8a74419 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -863,6 +863,7 @@ corresponding language environments are: **** Lontara script and language environment **** Hanifi Rohingya script and language environment **** Grantha script and language environment +**** Kharoshthi script and language environment --- *** The "Oriya" language environment was renamed to "Odia". diff --git a/lisp/language/misc-lang.el b/lisp/language/misc-lang.el index 46429a4380..e0e7add158 100644 --- a/lisp/language/misc-lang.el +++ b/lisp/language/misc-lang.el @@ -1,5 +1,6 @@ ;;; misc-lang.el --- support for miscellaneous languages (characters) -*- lexical-binding: t; -*- +;; Copyright (C) 2012-2022 Free Software Foundation, Inc. ;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, ;; 2005, 2006, 2007, 2008, 2009, 2010, 2011 ;; National Institute of Advanced Industrial Science and Technology (AIST) @@ -234,6 +235,37 @@ in this language environment."))) "[\x10D00-\x10D27]+" 1 'font-shape-gstring))) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Kharoṣṭhī +;; Author: Stefan Baums +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(set-language-info-alist + "Kharoshthi" '((charset unicode) + (coding-system utf-8) + (coding-priority utf-8) + (input-method . "kharoshthi") + (sample-text . "Kharoṣṭhī (𐨑𐨪𐨆𐨛𐨁) 𐨣𐨨𐨲𐨪𐨆 𐨐𐨪𐨅𐨨𐨁") + (documentation . "\ +Language environment for Gāndhārī, Sanskrit, and other languages +using the Kharoṣṭhī script."))) + +(let ((consonant "[\U00010A00\U00010A10-\U00010A35]") + (vowel "[\U00010A01-\U00010A06]") + (virama "\U00010A3F") + (modifier "[\U00010A0C-\U00010A0F\U00010A38-\U00010A3A]")) + (set-char-table-range composition-function-table + '(#x10A3F . #x10A3F) + (list + (vector + (concat consonant + "\\(?:" virama consonant "\\)*" + modifier "*" + virama "?" + vowel "*" + modifier "*") + 1 'font-shape-gstring)))) + (provide 'misc-lang) ;;; misc-lang.el ends here diff --git a/lisp/leim/quail/misc-lang.el b/lisp/leim/quail/misc-lang.el index bdb86ab528..e4e36b2dee 100644 --- a/lisp/leim/quail/misc-lang.el +++ b/lisp/leim/quail/misc-lang.el @@ -97,5 +97,1088 @@ ("`N" ?𐴣) ("m" ?𐴔)) +;; The Kharoṣṭhī input method is based on the Kyoto-Harvard input +;; conventions for Sanskrit, extended for Kharoṣṭhī special characters. +;; Author: Stefan Baums . +(quail-define-package + "kharoshthi" "Kharoshhi" "𐨑" nil + "Kharoṣṭhī input method." nil t t t t nil nil nil nil nil t) + +(quail-define-rules + ("a" ["𐨀"]) + ("i" ["𐨀𐨁"]) + ("u" ["𐨀𐨂"]) + ("R" ["𐨀𐨃"]) + ("e" ["𐨀𐨅"]) + ("o" ["𐨀𐨆"]) + + ("k" ["𐨐𐨿"]) + ("ka" ["𐨐"]) + ("ki" ["𐨐𐨁"]) + ("ku" ["𐨐𐨂"]) + ("kR" ["𐨐𐨃"]) + ("ke" ["𐨐𐨅"]) + ("ko" ["𐨐𐨆"]) + ("k_" ["𐨐𐨹𐨿"]) + ("k_a" ["𐨐𐨹"]) + ("k_i" ["𐨐𐨹𐨁"]) + ("k_u" ["𐨐𐨹𐨂"]) + ("k_R" ["𐨐𐨹𐨃"]) + ("k_e" ["𐨐𐨹𐨅"]) + ("k_o" ["𐨐𐨹𐨆"]) + ("k=" ["𐨐𐨿𐨸"]) + ("k=a" ["𐨐𐨸"]) + ("k=i" ["𐨐𐨸𐨁"]) + ("k=u" ["𐨐𐨸𐨂"]) + ("k=R" ["𐨐𐨸𐨃"]) + ("k=e" ["𐨐𐨸𐨅"]) + ("k=o" ["𐨐𐨸𐨆"]) + ("k_=" ["𐨐𐨹𐨿𐨸"]) + ("k_=a" ["𐨐𐨹𐨸"]) + ("k_=i" ["𐨐𐨹𐨸𐨁"]) + ("k_=u" ["𐨐𐨹𐨸𐨂"]) + ("k_=R" ["𐨐𐨹𐨸𐨃"]) + ("k_=e" ["𐨐𐨹𐨸𐨅"]) + ("k_=o" ["𐨐𐨹𐨸𐨆"]) + + ("kh" ["𐨑𐨿"]) + ("kha" ["𐨑"]) + ("khi" ["𐨑𐨁"]) + ("khu" ["𐨑𐨂"]) + ("khR" ["𐨑𐨃"]) + ("khe" ["𐨑𐨅"]) + ("kho" ["𐨑𐨆"]) + ("kh_" ["𐨑𐨹𐨿"]) + ("kh_a" ["𐨑𐨹"]) + ("kh_i" ["𐨑𐨹𐨁"]) + ("kh_u" ["𐨑𐨹𐨂"]) + ("kh_R" ["𐨑𐨹𐨃"]) + ("kh_e" ["𐨑𐨹𐨅"]) + ("kh_o" ["𐨑𐨹𐨆"]) + ("kh=" ["𐨑𐨿𐨸"]) + ("kh=a" ["𐨑𐨸"]) + ("kh=i" ["𐨑𐨸𐨁"]) + ("kh=u" ["𐨑𐨸𐨂"]) + ("kh=R" ["𐨑𐨸𐨃"]) + ("kh=e" ["𐨑𐨸𐨅"]) + ("kh=o" ["𐨑𐨸𐨆"]) + ("kh_=" ["𐨑𐨹𐨿𐨸"]) + ("kh_=a" ["𐨑𐨹𐨸"]) + ("kh_=i" ["𐨑𐨹𐨸𐨁"]) + ("kh_=u" ["𐨑𐨹𐨸𐨂"]) + ("kh_=R" ["𐨑𐨹𐨸𐨃"]) + ("kh_=e" ["𐨑𐨹𐨸𐨅"]) + ("kh_=o" ["𐨑𐨹𐨸𐨆"]) + + ("g" ["𐨒𐨿"]) + ("ga" ["𐨒"]) + ("gi" ["𐨒𐨁"]) + ("gu" ["𐨒𐨂"]) + ("gR" ["𐨒𐨃"]) + ("ge" ["𐨒𐨅"]) + ("go" ["𐨒𐨆"]) + ("g_" ["𐨒𐨹𐨿"]) + ("g_a" ["𐨒𐨹"]) + ("g_i" ["𐨒𐨹𐨁"]) + ("g_u" ["𐨒𐨹𐨂"]) + ("g_R" ["𐨒𐨹𐨃"]) + ("g_e" ["𐨒𐨹𐨅"]) + ("g_o" ["𐨒𐨹𐨆"]) + ("g=" ["𐨒𐨿𐨸"]) + ("g=a" ["𐨒𐨸"]) + ("g=i" ["𐨒𐨸𐨁"]) + ("g=u" ["𐨒𐨸𐨂"]) + ("g=R" ["𐨒𐨸𐨃"]) + ("g=e" ["𐨒𐨸𐨅"]) + ("g=o" ["𐨒𐨸𐨆"]) + ("g_=" ["𐨒𐨹𐨿𐨸"]) + ("g_=a" ["𐨒𐨹𐨸"]) + ("g_=i" ["𐨒𐨹𐨸𐨁"]) + ("g_=u" ["𐨒𐨹𐨸𐨂"]) + ("g_=R" ["𐨒𐨹𐨸𐨃"]) + ("g_=e" ["𐨒𐨹𐨸𐨅"]) + ("g_=o" ["𐨒𐨹𐨸𐨆"]) + + ("gh" ["𐨓𐨿"]) + ("gha" ["𐨓"]) + ("ghi" ["𐨓𐨁"]) + ("ghu" ["𐨓𐨂"]) + ("ghR" ["𐨓𐨃"]) + ("ghe" ["𐨓𐨅"]) + ("gho" ["𐨓𐨆"]) + ("gh_" ["𐨓𐨹𐨿"]) + ("gh_a" ["𐨓𐨹"]) + ("gh_i" ["𐨓𐨹𐨁"]) + ("gh_u" ["𐨓𐨹𐨂"]) + ("gh_R" ["𐨓𐨹𐨃"]) + ("gh_e" ["𐨓𐨹𐨅"]) + ("gh_o" ["𐨓𐨹𐨆"]) + ("gh=" ["𐨓𐨿𐨸"]) + ("gh=a" ["𐨓𐨸"]) + ("gh=i" ["𐨓𐨸𐨁"]) + ("gh=u" ["𐨓𐨸𐨂"]) + ("gh=R" ["𐨓𐨸𐨃"]) + ("gh=e" ["𐨓𐨸𐨅"]) + ("gh=o" ["𐨓𐨸𐨆"]) + ("gh_=" ["𐨓𐨹𐨿𐨸"]) + ("gh_=a" ["𐨓𐨹𐨸"]) + ("gh_=i" ["𐨓𐨹𐨸𐨁"]) + ("gh_=u" ["𐨓𐨹𐨸𐨂"]) + ("gh_=R" ["𐨓𐨹𐨸𐨃"]) + ("gh_=e" ["𐨓𐨹𐨸𐨅"]) + ("gh_=o" ["𐨓𐨹𐨸𐨆"]) + + ("c" ["𐨕𐨿"]) + ("ca" ["𐨕"]) + ("ci" ["𐨕𐨁"]) + ("cu" ["𐨕𐨂"]) + ("cR" ["𐨕𐨃"]) + ("ce" ["𐨕𐨅"]) + ("co" ["𐨕𐨆"]) + ("c_" ["𐨕𐨹𐨿"]) + ("c_a" ["𐨕𐨹"]) + ("c_i" ["𐨕𐨹𐨁"]) + ("c_u" ["𐨕𐨹𐨂"]) + ("c_R" ["𐨕𐨹𐨃"]) + ("c_e" ["𐨕𐨹𐨅"]) + ("c_o" ["𐨕𐨹𐨆"]) + ("c=" ["𐨕𐨿𐨸"]) + ("c=a" ["𐨕𐨸"]) + ("c=i" ["𐨕𐨸𐨁"]) + ("c=u" ["𐨕𐨸𐨂"]) + ("c=R" ["𐨕𐨸𐨃"]) + ("c=e" ["𐨕𐨸𐨅"]) + ("c=o" ["𐨕𐨸𐨆"]) + ("c_=" ["𐨕𐨹𐨿𐨸"]) + ("c_=a" ["𐨕𐨹𐨸"]) + ("c_=i" ["𐨕𐨹𐨸𐨁"]) + ("c_=u" ["𐨕𐨹𐨸𐨂"]) + ("c_=R" ["𐨕𐨹𐨸𐨃"]) + ("c_=e" ["𐨕𐨹𐨸𐨅"]) + ("c_=o" ["𐨕𐨹𐨸𐨆"]) + + ("ch" ["𐨖𐨿"]) + ("cha" ["𐨖"]) + ("chi" ["𐨖𐨁"]) + ("chu" ["𐨖𐨂"]) + ("chR" ["𐨖𐨃"]) + ("che" ["𐨖𐨅"]) + ("cho" ["𐨖𐨆"]) + ("ch_" ["𐨖𐨹𐨿"]) + ("ch_a" ["𐨖𐨹"]) + ("ch_i" ["𐨖𐨹𐨁"]) + ("ch_u" ["𐨖𐨹𐨂"]) + ("ch_R" ["𐨖𐨹𐨃"]) + ("ch_e" ["𐨖𐨹𐨅"]) + ("ch_o" ["𐨖𐨹𐨆"]) + ("ch=" ["𐨖𐨿𐨸"]) + ("ch=a" ["𐨖𐨸"]) + ("ch=i" ["𐨖𐨸𐨁"]) + ("ch=u" ["𐨖𐨸𐨂"]) + ("ch=R" ["𐨖𐨸𐨃"]) + ("ch=e" ["𐨖𐨸𐨅"]) + ("ch=o" ["𐨖𐨸𐨆"]) + ("ch_=" ["𐨖𐨹𐨿𐨸"]) + ("ch_=a" ["𐨖𐨹𐨸"]) + ("ch_=i" ["𐨖𐨹𐨸𐨁"]) + ("ch_=u" ["𐨖𐨹𐨸𐨂"]) + ("ch_=R" ["𐨖𐨹𐨸𐨃"]) + ("ch_=e" ["𐨖𐨹𐨸𐨅"]) + ("ch_=o" ["𐨖𐨹𐨸𐨆"]) + + ("j" ["𐨗𐨿"]) + ("ja" ["𐨗"]) + ("ji" ["𐨗𐨁"]) + ("ju" ["𐨗𐨂"]) + ("jR" ["𐨗𐨃"]) + ("je" ["𐨗𐨅"]) + ("jo" ["𐨗𐨆"]) + ("j_" ["𐨗𐨹𐨿"]) + ("j_a" ["𐨗𐨹"]) + ("j_i" ["𐨗𐨹𐨁"]) + ("j_u" ["𐨗𐨹𐨂"]) + ("j_R" ["𐨗𐨹𐨃"]) + ("j_e" ["𐨗𐨹𐨅"]) + ("j_o" ["𐨗𐨹𐨆"]) + ("j=" ["𐨗𐨿𐨸"]) + ("j=a" ["𐨗𐨸"]) + ("j=i" ["𐨗𐨸𐨁"]) + ("j=u" ["𐨗𐨸𐨂"]) + ("j=R" ["𐨗𐨸𐨃"]) + ("j=e" ["𐨗𐨸𐨅"]) + ("j=o" ["𐨗𐨸𐨆"]) + ("j_=" ["𐨗𐨹𐨿𐨸"]) + ("j_=a" ["𐨗𐨹𐨸"]) + ("j_=i" ["𐨗𐨹𐨸𐨁"]) + ("j_=u" ["𐨗𐨹𐨸𐨂"]) + ("j_=R" ["𐨗𐨹𐨸𐨃"]) + ("j_=e" ["𐨗𐨹𐨸𐨅"]) + ("j_=o" ["𐨗𐨹𐨸𐨆"]) + + ("jh" ["𐨰𐨿"]) + ("jha" ["𐨰"]) + ("jhi" ["𐨰𐨁"]) + ("jhu" ["𐨰𐨂"]) + ("jhR" ["𐨰𐨃"]) + ("jhe" ["𐨰𐨅"]) + ("jho" ["𐨰𐨆"]) + ("jh_" ["𐨰𐨹𐨿"]) + ("jh_a" ["𐨰𐨹"]) + ("jh_i" ["𐨰𐨹𐨁"]) + ("jh_u" ["𐨰𐨹𐨂"]) + ("jh_R" ["𐨰𐨹𐨃"]) + ("jh_e" ["𐨰𐨹𐨅"]) + ("jh_o" ["𐨰𐨹𐨆"]) + ("jh=" ["𐨰𐨿𐨸"]) + ("jh=a" ["𐨰𐨸"]) + ("jh=i" ["𐨰𐨸𐨁"]) + ("jh=u" ["𐨰𐨸𐨂"]) + ("jh=R" ["𐨰𐨸𐨃"]) + ("jh=e" ["𐨰𐨸𐨅"]) + ("jh=o" ["𐨰𐨸𐨆"]) + ("jh_=" ["𐨰𐨹𐨿𐨸"]) + ("jh_=a" ["𐨰𐨹𐨸"]) + ("jh_=i" ["𐨰𐨹𐨸𐨁"]) + ("jh_=u" ["𐨰𐨹𐨸𐨂"]) + ("jh_=R" ["𐨰𐨹𐨸𐨃"]) + ("jh_=e" ["𐨰𐨹𐨸𐨅"]) + ("jh_=o" ["𐨰𐨹𐨸𐨆"]) + + ("J" ["𐨙𐨿"]) + ("Ja" ["𐨙"]) + ("Ji" ["𐨙𐨁"]) + ("Ju" ["𐨙𐨂"]) + ("JR" ["𐨙𐨃"]) + ("Je" ["𐨙𐨅"]) + ("Jo" ["𐨙𐨆"]) + ("J_" ["𐨙𐨹𐨿"]) + ("J_a" ["𐨙𐨹"]) + ("J_i" ["𐨙𐨹𐨁"]) + ("J_u" ["𐨙𐨹𐨂"]) + ("J_R" ["𐨙𐨹𐨃"]) + ("J_e" ["𐨙𐨹𐨅"]) + ("J_o" ["𐨙𐨹𐨆"]) + ("J=" ["𐨙𐨿𐨸"]) + ("J=a" ["𐨙𐨸"]) + ("J=i" ["𐨙𐨸𐨁"]) + ("J=u" ["𐨙𐨸𐨂"]) + ("J=R" ["𐨙𐨸𐨃"]) + ("J=e" ["𐨙𐨸𐨅"]) + ("J=o" ["𐨙𐨸𐨆"]) + ("J_=" ["𐨙𐨹𐨿𐨸"]) + ("J_=a" ["𐨙𐨹𐨸"]) + ("J_=i" ["𐨙𐨹𐨸𐨁"]) + ("J_=u" ["𐨙𐨹𐨸𐨂"]) + ("J_=R" ["𐨙𐨹𐨸𐨃"]) + ("J_=e" ["𐨙𐨹𐨸𐨅"]) + ("J_=o" ["𐨙𐨹𐨸𐨆"]) + + ("T" ["𐨚𐨿"]) + ("Ta" ["𐨚"]) + ("Ti" ["𐨚𐨁"]) + ("Tu" ["𐨚𐨂"]) + ("TR" ["𐨚𐨃"]) + ("Te" ["𐨚𐨅"]) + ("To" ["𐨚𐨆"]) + ("T_" ["𐨚𐨹𐨿"]) + ("T_a" ["𐨚𐨹"]) + ("T_i" ["𐨚𐨹𐨁"]) + ("T_u" ["𐨚𐨹𐨂"]) + ("T_R" ["𐨚𐨹𐨃"]) + ("T_e" ["𐨚𐨹𐨅"]) + ("T_o" ["𐨚𐨹𐨆"]) + ("T=" ["𐨚𐨿𐨸"]) + ("T=a" ["𐨚𐨸"]) + ("T=i" ["𐨚𐨸𐨁"]) + ("T=u" ["𐨚𐨸𐨂"]) + ("T=R" ["𐨚𐨸𐨃"]) + ("T=e" ["𐨚𐨸𐨅"]) + ("T=o" ["𐨚𐨸𐨆"]) + ("T_=" ["𐨚𐨹𐨿𐨸"]) + ("T_=a" ["𐨚𐨹𐨸"]) + ("T_=i" ["𐨚𐨹𐨸𐨁"]) + ("T_=u" ["𐨚𐨹𐨸𐨂"]) + ("T_=R" ["𐨚𐨹𐨸𐨃"]) + ("T_=e" ["𐨚𐨹𐨸𐨅"]) + ("T_=o" ["𐨚𐨹𐨸𐨆"]) + + ("Th" ["𐨛𐨿"]) + ("Tha" ["𐨛"]) + ("Thi" ["𐨛𐨁"]) + ("Thu" ["𐨛𐨂"]) + ("ThR" ["𐨛𐨃"]) + ("The" ["𐨛𐨅"]) + ("Tho" ["𐨛𐨆"]) + ("Th_" ["𐨛𐨹𐨿"]) + ("Th_a" ["𐨛𐨹"]) + ("Th_i" ["𐨛𐨹𐨁"]) + ("Th_u" ["𐨛𐨹𐨂"]) + ("Th_R" ["𐨛𐨹𐨃"]) + ("Th_e" ["𐨛𐨹𐨅"]) + ("Th_o" ["𐨛𐨹𐨆"]) + ("Th=" ["𐨛𐨿𐨸"]) + ("Th=a" ["𐨛𐨸"]) + ("Th=i" ["𐨛𐨸𐨁"]) + ("Th=u" ["𐨛𐨸𐨂"]) + ("Th=R" ["𐨛𐨸𐨃"]) + ("Th=e" ["𐨛𐨸𐨅"]) + ("Th=o" ["𐨛𐨸𐨆"]) + ("Th_=" ["𐨛𐨹𐨿𐨸"]) + ("Th_=a" ["𐨛𐨹𐨸"]) + ("Th_=i" ["𐨛𐨹𐨸𐨁"]) + ("Th_=u" ["𐨛𐨹𐨸𐨂"]) + ("Th_=R" ["𐨛𐨹𐨸𐨃"]) + ("Th_=e" ["𐨛𐨹𐨸𐨅"]) + ("Th_=o" ["𐨛𐨹𐨸𐨆"]) + + ("D" ["𐨜𐨿"]) + ("Da" ["𐨜"]) + ("Di" ["𐨜𐨁"]) + ("Du" ["𐨜𐨂"]) + ("DR" ["𐨜𐨃"]) + ("De" ["𐨜𐨅"]) + ("Do" ["𐨜𐨆"]) + ("D_" ["𐨜𐨹𐨿"]) + ("D_a" ["𐨜𐨹"]) + ("D_i" ["𐨜𐨹𐨁"]) + ("D_u" ["𐨜𐨹𐨂"]) + ("D_R" ["𐨜𐨹𐨃"]) + ("D_e" ["𐨜𐨹𐨅"]) + ("D_o" ["𐨜𐨹𐨆"]) + ("D=" ["𐨜𐨿𐨸"]) + ("D=a" ["𐨜𐨸"]) + ("D=i" ["𐨜𐨸𐨁"]) + ("D=u" ["𐨜𐨸𐨂"]) + ("D=R" ["𐨜𐨸𐨃"]) + ("D=e" ["𐨜𐨸𐨅"]) + ("D=o" ["𐨜𐨸𐨆"]) + ("D_=" ["𐨜𐨹𐨿𐨸"]) + ("D_=a" ["𐨜𐨹𐨸"]) + ("D_=i" ["𐨜𐨹𐨸𐨁"]) + ("D_=u" ["𐨜𐨹𐨸𐨂"]) + ("D_=R" ["𐨜𐨹𐨸𐨃"]) + ("D_=e" ["𐨜𐨹𐨸𐨅"]) + ("D_=o" ["𐨜𐨹𐨸𐨆"]) + + ("Dh" ["𐨝𐨿"]) + ("Dha" ["𐨝"]) + ("Dhi" ["𐨝𐨁"]) + ("Dhu" ["𐨝𐨂"]) + ("DhR" ["𐨝𐨃"]) + ("Dhe" ["𐨝𐨅"]) + ("Dho" ["𐨝𐨆"]) + ("Dh_" ["𐨝𐨹𐨿"]) + ("Dh_a" ["𐨝𐨹"]) + ("Dh_i" ["𐨝𐨹𐨁"]) + ("Dh_u" ["𐨝𐨹𐨂"]) + ("Dh_R" ["𐨝𐨹𐨃"]) + ("Dh_e" ["𐨝𐨹𐨅"]) + ("Dh_o" ["𐨝𐨹𐨆"]) + ("Dh=" ["𐨝𐨿𐨸"]) + ("Dh=a" ["𐨝𐨸"]) + ("Dh=i" ["𐨝𐨸𐨁"]) + ("Dh=u" ["𐨝𐨸𐨂"]) + ("Dh=R" ["𐨝𐨸𐨃"]) + ("Dh=e" ["𐨝𐨸𐨅"]) + ("Dh=o" ["𐨝𐨸𐨆"]) + ("Dh_=" ["𐨝𐨹𐨿𐨸"]) + ("Dh_=a" ["𐨝𐨹𐨸"]) + ("Dh_=i" ["𐨝𐨹𐨸𐨁"]) + ("Dh_=u" ["𐨝𐨹𐨸𐨂"]) + ("Dh_=R" ["𐨝𐨹𐨸𐨃"]) + ("Dh_=e" ["𐨝𐨹𐨸𐨅"]) + ("Dh_=o" ["𐨝𐨹𐨸𐨆"]) + + ("N" ["𐨞𐨿"]) + ("Na" ["𐨞"]) + ("Ni" ["𐨞𐨁"]) + ("Nu" ["𐨞𐨂"]) + ("NR" ["𐨞𐨃"]) + ("Ne" ["𐨞𐨅"]) + ("No" ["𐨞𐨆"]) + ("N_" ["𐨞𐨹𐨿"]) + ("N_a" ["𐨞𐨹"]) + ("N_i" ["𐨞𐨹𐨁"]) + ("N_u" ["𐨞𐨹𐨂"]) + ("N_R" ["𐨞𐨹𐨃"]) + ("N_e" ["𐨞𐨹𐨅"]) + ("N_o" ["𐨞𐨹𐨆"]) + ("N=" ["𐨞𐨿𐨸"]) + ("N=a" ["𐨞𐨸"]) + ("N=i" ["𐨞𐨸𐨁"]) + ("N=u" ["𐨞𐨸𐨂"]) + ("N=R" ["𐨞𐨸𐨃"]) + ("N=e" ["𐨞𐨸𐨅"]) + ("N=o" ["𐨞𐨸𐨆"]) + ("N_=" ["𐨞𐨹𐨿𐨸"]) + ("N_=a" ["𐨞𐨹𐨸"]) + ("N_=i" ["𐨞𐨹𐨸𐨁"]) + ("N_=u" ["𐨞𐨹𐨸𐨂"]) + ("N_=R" ["𐨞𐨹𐨸𐨃"]) + ("N_=e" ["𐨞𐨹𐨸𐨅"]) + ("N_=o" ["𐨞𐨹𐨸𐨆"]) + + ("t" ["𐨟𐨿"]) + ("ta" ["𐨟"]) + ("ti" ["𐨟𐨁"]) + ("tu" ["𐨟𐨂"]) + ("tR" ["𐨟𐨃"]) + ("te" ["𐨟𐨅"]) + ("to" ["𐨟𐨆"]) + ("t_" ["𐨟𐨹𐨿"]) + ("t_a" ["𐨟𐨹"]) + ("t_i" ["𐨟𐨹𐨁"]) + ("t_u" ["𐨟𐨹𐨂"]) + ("t_R" ["𐨟𐨹𐨃"]) + ("t_e" ["𐨟𐨹𐨅"]) + ("t_o" ["𐨟𐨹𐨆"]) + ("t=" ["𐨟𐨿𐨸"]) + ("t=a" ["𐨟𐨸"]) + ("t=i" ["𐨟𐨸𐨁"]) + ("t=u" ["𐨟𐨸𐨂"]) + ("t=R" ["𐨟𐨸𐨃"]) + ("t=e" ["𐨟𐨸𐨅"]) + ("t=o" ["𐨟𐨸𐨆"]) + ("t_=" ["𐨟𐨹𐨿𐨸"]) + ("t_=a" ["𐨟𐨹𐨸"]) + ("t_=i" ["𐨟𐨹𐨸𐨁"]) + ("t_=u" ["𐨟𐨹𐨸𐨂"]) + ("t_=R" ["𐨟𐨹𐨸𐨃"]) + ("t_=e" ["𐨟𐨹𐨸𐨅"]) + ("t_=o" ["𐨟𐨹𐨸𐨆"]) + + ("th" ["𐨠𐨿"]) + ("tha" ["𐨠"]) + ("thi" ["𐨠𐨁"]) + ("thu" ["𐨠𐨂"]) + ("thR" ["𐨠𐨃"]) + ("the" ["𐨠𐨅"]) + ("tho" ["𐨠𐨆"]) + ("th_" ["𐨠𐨹𐨿"]) + ("th_a" ["𐨠𐨹"]) + ("th_i" ["𐨠𐨹𐨁"]) + ("th_u" ["𐨠𐨹𐨂"]) + ("th_R" ["𐨠𐨹𐨃"]) + ("th_e" ["𐨠𐨹𐨅"]) + ("th_o" ["𐨠𐨹𐨆"]) + ("th=" ["𐨠𐨿𐨸"]) + ("th=a" ["𐨠𐨸"]) + ("th=i" ["𐨠𐨸𐨁"]) + ("th=u" ["𐨠𐨸𐨂"]) + ("th=R" ["𐨠𐨸𐨃"]) + ("th=e" ["𐨠𐨸𐨅"]) + ("th=o" ["𐨠𐨸𐨆"]) + ("th_=" ["𐨠𐨹𐨿𐨸"]) + ("th_=a" ["𐨠𐨹𐨸"]) + ("th_=i" ["𐨠𐨹𐨸𐨁"]) + ("th_=u" ["𐨠𐨹𐨸𐨂"]) + ("th_=R" ["𐨠𐨹𐨸𐨃"]) + ("th_=e" ["𐨠𐨹𐨸𐨅"]) + ("th_=o" ["𐨠𐨹𐨸𐨆"]) + + ("d" ["𐨡𐨿"]) + ("da" ["𐨡"]) + ("di" ["𐨡𐨁"]) + ("du" ["𐨡𐨂"]) + ("dR" ["𐨡𐨃"]) + ("de" ["𐨡𐨅"]) + ("do" ["𐨡𐨆"]) + ("d_" ["𐨡𐨹𐨿"]) + ("d_a" ["𐨡𐨹"]) + ("d_i" ["𐨡𐨹𐨁"]) + ("d_u" ["𐨡𐨹𐨂"]) + ("d_R" ["𐨡𐨹𐨃"]) + ("d_e" ["𐨡𐨹𐨅"]) + ("d_o" ["𐨡𐨹𐨆"]) + ("d=" ["𐨡𐨿𐨸"]) + ("d=a" ["𐨡𐨸"]) + ("d=i" ["𐨡𐨸𐨁"]) + ("d=u" ["𐨡𐨸𐨂"]) + ("d=R" ["𐨡𐨸𐨃"]) + ("d=e" ["𐨡𐨸𐨅"]) + ("d=o" ["𐨡𐨸𐨆"]) + ("d_=" ["𐨡𐨹𐨿𐨸"]) + ("d_=a" ["𐨡𐨹𐨸"]) + ("d_=i" ["𐨡𐨹𐨸𐨁"]) + ("d_=u" ["𐨡𐨹𐨸𐨂"]) + ("d_=R" ["𐨡𐨹𐨸𐨃"]) + ("d_=e" ["𐨡𐨹𐨸𐨅"]) + ("d_=o" ["𐨡𐨹𐨸𐨆"]) + + ("dh" ["𐨢𐨿"]) + ("dha" ["𐨢"]) + ("dhi" ["𐨢𐨁"]) + ("dhu" ["𐨢𐨂"]) + ("dhR" ["𐨢𐨃"]) + ("dhe" ["𐨢𐨅"]) + ("dho" ["𐨢𐨆"]) + ("dh_" ["𐨢𐨹𐨿"]) + ("dh_a" ["𐨢𐨹"]) + ("dh_i" ["𐨢𐨹𐨁"]) + ("dh_u" ["𐨢𐨹𐨂"]) + ("dh_R" ["𐨢𐨹𐨃"]) + ("dh_e" ["𐨢𐨹𐨅"]) + ("dh_o" ["𐨢𐨹𐨆"]) + ("dh=" ["𐨢𐨿𐨸"]) + ("dh=a" ["𐨢𐨸"]) + ("dh=i" ["𐨢𐨸𐨁"]) + ("dh=u" ["𐨢𐨸𐨂"]) + ("dh=R" ["𐨢𐨸𐨃"]) + ("dh=e" ["𐨢𐨸𐨅"]) + ("dh=o" ["𐨢𐨸𐨆"]) + ("dh_=" ["𐨢𐨹𐨿𐨸"]) + ("dh_=a" ["𐨢𐨹𐨸"]) + ("dh_=i" ["𐨢𐨹𐨸𐨁"]) + ("dh_=u" ["𐨢𐨹𐨸𐨂"]) + ("dh_=R" ["𐨢𐨹𐨸𐨃"]) + ("dh_=e" ["𐨢𐨹𐨸𐨅"]) + ("dh_=o" ["𐨢𐨹𐨸𐨆"]) + + ("n" ["𐨣𐨿"]) + ("na" ["𐨣"]) + ("ni" ["𐨣𐨁"]) + ("nu" ["𐨣𐨂"]) + ("nR" ["𐨣𐨃"]) + ("ne" ["𐨣𐨅"]) + ("no" ["𐨣𐨆"]) + ("n_" ["𐨣𐨹𐨿"]) + ("n_a" ["𐨣𐨹"]) + ("n_i" ["𐨣𐨹𐨁"]) + ("n_u" ["𐨣𐨹𐨂"]) + ("n_R" ["𐨣𐨹𐨃"]) + ("n_e" ["𐨣𐨹𐨅"]) + ("n_o" ["𐨣𐨹𐨆"]) + ("n=" ["𐨣𐨿𐨸"]) + ("n=a" ["𐨣𐨸"]) + ("n=i" ["𐨣𐨸𐨁"]) + ("n=u" ["𐨣𐨸𐨂"]) + ("n=R" ["𐨣𐨸𐨃"]) + ("n=e" ["𐨣𐨸𐨅"]) + ("n=o" ["𐨣𐨸𐨆"]) + ("n_=" ["𐨣𐨹𐨿𐨸"]) + ("n_=a" ["𐨣𐨹𐨸"]) + ("n_=i" ["𐨣𐨹𐨸𐨁"]) + ("n_=u" ["𐨣𐨹𐨸𐨂"]) + ("n_=R" ["𐨣𐨹𐨸𐨃"]) + ("n_=e" ["𐨣𐨹𐨸𐨅"]) + ("n_=o" ["𐨣𐨹𐨸𐨆"]) + + ("p" ["𐨤𐨿"]) + ("pa" ["𐨤"]) + ("pi" ["𐨤𐨁"]) + ("pu" ["𐨤𐨂"]) + ("pR" ["𐨤𐨃"]) + ("pe" ["𐨤𐨅"]) + ("po" ["𐨤𐨆"]) + ("p_" ["𐨤𐨹𐨿"]) + ("p_a" ["𐨤𐨹"]) + ("p_i" ["𐨤𐨹𐨁"]) + ("p_u" ["𐨤𐨹𐨂"]) + ("p_R" ["𐨤𐨹𐨃"]) + ("p_e" ["𐨤𐨹𐨅"]) + ("p_o" ["𐨤𐨹𐨆"]) + ("p=" ["𐨤𐨿𐨸"]) + ("p=a" ["𐨤𐨸"]) + ("p=i" ["𐨤𐨸𐨁"]) + ("p=u" ["𐨤𐨸𐨂"]) + ("p=R" ["𐨤𐨸𐨃"]) + ("p=e" ["𐨤𐨸𐨅"]) + ("p=o" ["𐨤𐨸𐨆"]) + ("p_=" ["𐨤𐨹𐨿𐨸"]) + ("p_=a" ["𐨤𐨹𐨸"]) + ("p_=i" ["𐨤𐨹𐨸𐨁"]) + ("p_=u" ["𐨤𐨹𐨸𐨂"]) + ("p_=R" ["𐨤𐨹𐨸𐨃"]) + ("p_=e" ["𐨤𐨹𐨸𐨅"]) + ("p_=o" ["𐨤𐨹𐨸𐨆"]) + + ("ph" ["𐨥𐨿"]) + ("pha" ["𐨥"]) + ("phi" ["𐨥𐨁"]) + ("phu" ["𐨥𐨂"]) + ("phR" ["𐨥𐨃"]) + ("phe" ["𐨥𐨅"]) + ("pho" ["𐨥𐨆"]) + ("ph_" ["𐨥𐨹𐨿"]) + ("ph_a" ["𐨥𐨹"]) + ("ph_i" ["𐨥𐨹𐨁"]) + ("ph_u" ["𐨥𐨹𐨂"]) + ("ph_R" ["𐨥𐨹𐨃"]) + ("ph_e" ["𐨥𐨹𐨅"]) + ("ph_o" ["𐨥𐨹𐨆"]) + ("ph=" ["𐨥𐨿𐨸"]) + ("ph=a" ["𐨥𐨸"]) + ("ph=i" ["𐨥𐨸𐨁"]) + ("ph=u" ["𐨥𐨸𐨂"]) + ("ph=R" ["𐨥𐨸𐨃"]) + ("ph=e" ["𐨥𐨸𐨅"]) + ("ph=o" ["𐨥𐨸𐨆"]) + ("ph_=" ["𐨥𐨹𐨿𐨸"]) + ("ph_=a" ["𐨥𐨹𐨸"]) + ("ph_=i" ["𐨥𐨹𐨸𐨁"]) + ("ph_=u" ["𐨥𐨹𐨸𐨂"]) + ("ph_=R" ["𐨥𐨹𐨸𐨃"]) + ("ph_=e" ["𐨥𐨹𐨸𐨅"]) + ("ph_=o" ["𐨥𐨹𐨸𐨆"]) + + ("b" ["𐨦𐨿"]) + ("ba" ["𐨦"]) + ("bi" ["𐨦𐨁"]) + ("bu" ["𐨦𐨂"]) + ("bR" ["𐨦𐨃"]) + ("be" ["𐨦𐨅"]) + ("bo" ["𐨦𐨆"]) + ("b_" ["𐨦𐨹𐨿"]) + ("b_a" ["𐨦𐨹"]) + ("b_i" ["𐨦𐨹𐨁"]) + ("b_u" ["𐨦𐨹𐨂"]) + ("b_R" ["𐨦𐨹𐨃"]) + ("b_e" ["𐨦𐨹𐨅"]) + ("b_o" ["𐨦𐨹𐨆"]) + ("b=" ["𐨦𐨿𐨸"]) + ("b=a" ["𐨦𐨸"]) + ("b=i" ["𐨦𐨸𐨁"]) + ("b=u" ["𐨦𐨸𐨂"]) + ("b=R" ["𐨦𐨸𐨃"]) + ("b=e" ["𐨦𐨸𐨅"]) + ("b=o" ["𐨦𐨸𐨆"]) + ("b_=" ["𐨦𐨹𐨿𐨸"]) + ("b_=a" ["𐨦𐨹𐨸"]) + ("b_=i" ["𐨦𐨹𐨸𐨁"]) + ("b_=u" ["𐨦𐨹𐨸𐨂"]) + ("b_=R" ["𐨦𐨹𐨸𐨃"]) + ("b_=e" ["𐨦𐨹𐨸𐨅"]) + ("b_=o" ["𐨦𐨹𐨸𐨆"]) + + ("bh" ["𐨧𐨿"]) + ("bha" ["𐨧"]) + ("bhi" ["𐨧𐨁"]) + ("bhu" ["𐨧𐨂"]) + ("bhR" ["𐨧𐨃"]) + ("bhe" ["𐨧𐨅"]) + ("bho" ["𐨧𐨆"]) + ("bh_" ["𐨧𐨹𐨿"]) + ("bh_a" ["𐨧𐨹"]) + ("bh_i" ["𐨧𐨹𐨁"]) + ("bh_u" ["𐨧𐨹𐨂"]) + ("bh_R" ["𐨧𐨹𐨃"]) + ("bh_e" ["𐨧𐨹𐨅"]) + ("bh_o" ["𐨧𐨹𐨆"]) + ("bh=" ["𐨧𐨿𐨸"]) + ("bh=a" ["𐨧𐨸"]) + ("bh=i" ["𐨧𐨸𐨁"]) + ("bh=u" ["𐨧𐨸𐨂"]) + ("bh=R" ["𐨧𐨸𐨃"]) + ("bh=e" ["𐨧𐨸𐨅"]) + ("bh=o" ["𐨧𐨸𐨆"]) + ("bh_=" ["𐨧𐨹𐨿𐨸"]) + ("bh_=a" ["𐨧𐨹𐨸"]) + ("bh_=i" ["𐨧𐨹𐨸𐨁"]) + ("bh_=u" ["𐨧𐨹𐨸𐨂"]) + ("bh_=R" ["𐨧𐨹𐨸𐨃"]) + ("bh_=e" ["𐨧𐨹𐨸𐨅"]) + ("bh_=o" ["𐨧𐨹𐨸𐨆"]) + + ("m" ["𐨨𐨿"]) + ("ma" ["𐨨"]) + ("mi" ["𐨨𐨁"]) + ("mu" ["𐨨𐨂"]) + ("mR" ["𐨨𐨃"]) + ("me" ["𐨨𐨅"]) + ("mo" ["𐨨𐨆"]) + ("m_" ["𐨨𐨹𐨿"]) + ("m_a" ["𐨨𐨹"]) + ("m_i" ["𐨨𐨹𐨁"]) + ("m_u" ["𐨨𐨹𐨂"]) + ("m_R" ["𐨨𐨹𐨃"]) + ("m_e" ["𐨨𐨹𐨅"]) + ("m_o" ["𐨨𐨹𐨆"]) + ("m=" ["𐨨𐨿𐨸"]) + ("m=a" ["𐨨𐨸"]) + ("m=i" ["𐨨𐨸𐨁"]) + ("m=u" ["𐨨𐨸𐨂"]) + ("m=R" ["𐨨𐨸𐨃"]) + ("m=e" ["𐨨𐨸𐨅"]) + ("m=o" ["𐨨𐨸𐨆"]) + ("m_=" ["𐨨𐨹𐨿𐨸"]) + ("m_=a" ["𐨨𐨹𐨸"]) + ("m_=i" ["𐨨𐨹𐨸𐨁"]) + ("m_=u" ["𐨨𐨹𐨸𐨂"]) + ("m_=R" ["𐨨𐨹𐨸𐨃"]) + ("m_=e" ["𐨨𐨹𐨸𐨅"]) + ("m_=o" ["𐨨𐨹𐨸𐨆"]) + + ("y" ["𐨩𐨿"]) + ("ya" ["𐨩"]) + ("yi" ["𐨩𐨁"]) + ("yu" ["𐨩𐨂"]) + ("yR" ["𐨩𐨃"]) + ("ye" ["𐨩𐨅"]) + ("yo" ["𐨩𐨆"]) + ("y_" ["𐨩𐨹𐨿"]) + ("y_a" ["𐨩𐨹"]) + ("y_i" ["𐨩𐨹𐨁"]) + ("y_u" ["𐨩𐨹𐨂"]) + ("y_R" ["𐨩𐨹𐨃"]) + ("y_e" ["𐨩𐨹𐨅"]) + ("y_o" ["𐨩𐨹𐨆"]) + ("y=" ["𐨩𐨿𐨸"]) + ("y=a" ["𐨩𐨸"]) + ("y=i" ["𐨩𐨸𐨁"]) + ("y=u" ["𐨩𐨸𐨂"]) + ("y=R" ["𐨩𐨸𐨃"]) + ("y=e" ["𐨩𐨸𐨅"]) + ("y=o" ["𐨩𐨸𐨆"]) + ("y_=" ["𐨩𐨹𐨿𐨸"]) + ("y_=a" ["𐨩𐨹𐨸"]) + ("y_=i" ["𐨩𐨹𐨸𐨁"]) + ("y_=u" ["𐨩𐨹𐨸𐨂"]) + ("y_=R" ["𐨩𐨹𐨸𐨃"]) + ("y_=e" ["𐨩𐨹𐨸𐨅"]) + ("y_=o" ["𐨩𐨹𐨸𐨆"]) + + ("r" ["𐨪𐨿"]) + ("ra" ["𐨪"]) + ("ri" ["𐨪𐨁"]) + ("ru" ["𐨪𐨂"]) + ("rR" ["𐨪𐨃"]) + ("re" ["𐨪𐨅"]) + ("ro" ["𐨪𐨆"]) + ("r_" ["𐨪𐨹𐨿"]) + ("r_a" ["𐨪𐨹"]) + ("r_i" ["𐨪𐨹𐨁"]) + ("r_u" ["𐨪𐨹𐨂"]) + ("r_R" ["𐨪𐨹𐨃"]) + ("r_e" ["𐨪𐨹𐨅"]) + ("r_o" ["𐨪𐨹𐨆"]) + ("r=" ["𐨪𐨿𐨸"]) + ("r=a" ["𐨪𐨸"]) + ("r=i" ["𐨪𐨸𐨁"]) + ("r=u" ["𐨪𐨸𐨂"]) + ("r=R" ["𐨪𐨸𐨃"]) + ("r=e" ["𐨪𐨸𐨅"]) + ("r=o" ["𐨪𐨸𐨆"]) + ("r_=" ["𐨪𐨹𐨿𐨸"]) + ("r_=a" ["𐨪𐨹𐨸"]) + ("r_=i" ["𐨪𐨹𐨸𐨁"]) + ("r_=u" ["𐨪𐨹𐨸𐨂"]) + ("r_=R" ["𐨪𐨹𐨸𐨃"]) + ("r_=e" ["𐨪𐨹𐨸𐨅"]) + ("r_=o" ["𐨪𐨹𐨸𐨆"]) + + ("l" ["𐨫𐨿"]) + ("la" ["𐨫"]) + ("li" ["𐨫𐨁"]) + ("lu" ["𐨫𐨂"]) + ("lR" ["𐨫𐨃"]) + ("le" ["𐨫𐨅"]) + ("lo" ["𐨫𐨆"]) + ("l_" ["𐨫𐨹𐨿"]) + ("l_a" ["𐨫𐨹"]) + ("l_i" ["𐨫𐨹𐨁"]) + ("l_u" ["𐨫𐨹𐨂"]) + ("l_R" ["𐨫𐨹𐨃"]) + ("l_e" ["𐨫𐨹𐨅"]) + ("l_o" ["𐨫𐨹𐨆"]) + ("l=" ["𐨫𐨿𐨸"]) + ("l=a" ["𐨫𐨸"]) + ("l=i" ["𐨫𐨸𐨁"]) + ("l=u" ["𐨫𐨸𐨂"]) + ("l=R" ["𐨫𐨸𐨃"]) + ("l=e" ["𐨫𐨸𐨅"]) + ("l=o" ["𐨫𐨸𐨆"]) + ("l_=" ["𐨫𐨹𐨿𐨸"]) + ("l_=a" ["𐨫𐨹𐨸"]) + ("l_=i" ["𐨫𐨹𐨸𐨁"]) + ("l_=u" ["𐨫𐨹𐨸𐨂"]) + ("l_=R" ["𐨫𐨹𐨸𐨃"]) + ("l_=e" ["𐨫𐨹𐨸𐨅"]) + ("l_=o" ["𐨫𐨹𐨸𐨆"]) + + ("v" ["𐨬𐨿"]) + ("va" ["𐨬"]) + ("vi" ["𐨬𐨁"]) + ("vu" ["𐨬𐨂"]) + ("vR" ["𐨬𐨃"]) + ("ve" ["𐨬𐨅"]) + ("vo" ["𐨬𐨆"]) + ("v_" ["𐨬𐨹𐨿"]) + ("v_a" ["𐨬𐨹"]) + ("v_i" ["𐨬𐨹𐨁"]) + ("v_u" ["𐨬𐨹𐨂"]) + ("v_R" ["𐨬𐨹𐨃"]) + ("v_e" ["𐨬𐨹𐨅"]) + ("v_o" ["𐨬𐨹𐨆"]) + ("v=" ["𐨬𐨿𐨸"]) + ("v=a" ["𐨬𐨸"]) + ("v=i" ["𐨬𐨸𐨁"]) + ("v=u" ["𐨬𐨸𐨂"]) + ("v=R" ["𐨬𐨸𐨃"]) + ("v=e" ["𐨬𐨸𐨅"]) + ("v=o" ["𐨬𐨸𐨆"]) + ("v_=" ["𐨬𐨹𐨿𐨸"]) + ("v_=a" ["𐨬𐨹𐨸"]) + ("v_=i" ["𐨬𐨹𐨸𐨁"]) + ("v_=u" ["𐨬𐨹𐨸𐨂"]) + ("v_=R" ["𐨬𐨹𐨸𐨃"]) + ("v_=e" ["𐨬𐨹𐨸𐨅"]) + ("v_=o" ["𐨬𐨹𐨸𐨆"]) + + ("z" ["𐨭𐨿"]) + ("za" ["𐨭"]) + ("zi" ["𐨭𐨁"]) + ("zu" ["𐨭𐨂"]) + ("z" ["𐨭𐨃"]) + ("ze" ["𐨭𐨅"]) + ("zo" ["𐨭𐨆"]) + ("z_" ["𐨭𐨹𐨿"]) + ("z_a" ["𐨭𐨹"]) + ("z_i" ["𐨭𐨹𐨁"]) + ("z_u" ["𐨭𐨹𐨂"]) + ("z_R" ["𐨭𐨹𐨃"]) + ("z_e" ["𐨭𐨹𐨅"]) + ("z_o" ["𐨭𐨹𐨆"]) + ("z=" ["𐨭𐨿𐨸"]) + ("z=a" ["𐨭𐨸"]) + ("z=i" ["𐨭𐨸𐨁"]) + ("z=u" ["𐨭𐨸𐨂"]) + ("z=R" ["𐨭𐨸𐨃"]) + ("z=e" ["𐨭𐨸𐨅"]) + ("z=o" ["𐨭𐨸𐨆"]) + ("z_=" ["𐨭𐨹𐨿𐨸"]) + ("z_=a" ["𐨭𐨹𐨸"]) + ("z_=i" ["𐨭𐨹𐨸𐨁"]) + ("z_=u" ["𐨭𐨹𐨸𐨂"]) + ("z_=R" ["𐨭𐨹𐨸𐨃"]) + ("z_=e" ["𐨭𐨹𐨸𐨅"]) + ("z_=o" ["𐨭𐨹𐨸𐨆"]) + + ("S" ["𐨮𐨿"]) + ("Sa" ["𐨮"]) + ("Si" ["𐨮𐨁"]) + ("Su" ["𐨮𐨂"]) + ("SR" ["𐨮𐨃"]) + ("Se" ["𐨮𐨅"]) + ("So" ["𐨮𐨆"]) + ("S_" ["𐨮𐨹𐨿"]) + ("S_a" ["𐨮𐨹"]) + ("S_i" ["𐨮𐨹𐨁"]) + ("S_u" ["𐨮𐨹𐨂"]) + ("S_R" ["𐨮𐨹𐨃"]) + ("S_e" ["𐨮𐨹𐨅"]) + ("S_o" ["𐨮𐨹𐨆"]) + ("S=" ["𐨮𐨿𐨸"]) + ("S=a" ["𐨮𐨸"]) + ("S=i" ["𐨮𐨸𐨁"]) + ("S=u" ["𐨮𐨸𐨂"]) + ("S=R" ["𐨮𐨸𐨃"]) + ("S=e" ["𐨮𐨸𐨅"]) + ("S=o" ["𐨮𐨸𐨆"]) + ("S_=" ["𐨮𐨹𐨿𐨸"]) + ("S_=a" ["𐨮𐨹𐨸"]) + ("S_=i" ["𐨮𐨹𐨸𐨁"]) + ("S_=u" ["𐨮𐨹𐨸𐨂"]) + ("S_=R" ["𐨮𐨹𐨸𐨃"]) + ("S_=e" ["𐨮𐨹𐨸𐨅"]) + ("S_=o" ["𐨮𐨹𐨸𐨆"]) + + ("s" ["𐨯𐨿"]) + ("sa" ["𐨯"]) + ("si" ["𐨯𐨁"]) + ("su" ["𐨯𐨂"]) + ("sR" ["𐨯𐨃"]) + ("se" ["𐨯𐨅"]) + ("so" ["𐨯𐨆"]) + ("s_" ["𐨯𐨹𐨿"]) + ("s_a" ["𐨯𐨹"]) + ("s_i" ["𐨯𐨹𐨁"]) + ("s_u" ["𐨯𐨹𐨂"]) + ("s_R" ["𐨯𐨹𐨃"]) + ("s_e" ["𐨯𐨹𐨅"]) + ("s_o" ["𐨯𐨹𐨆"]) + ("s=" ["𐨯𐨿𐨸"]) + ("s=a" ["𐨯𐨸"]) + ("s=i" ["𐨯𐨸𐨁"]) + ("s=u" ["𐨯𐨸𐨂"]) + ("s=R" ["𐨯𐨸𐨃"]) + ("s=e" ["𐨯𐨸𐨅"]) + ("s=o" ["𐨯𐨸𐨆"]) + ("s_=" ["𐨯𐨹𐨿𐨸"]) + ("s_=a" ["𐨯𐨹𐨸"]) + ("s_=i" ["𐨯𐨹𐨸𐨁"]) + ("s_=u" ["𐨯𐨹𐨸𐨂"]) + ("s_=R" ["𐨯𐨹𐨸𐨃"]) + ("s_=e" ["𐨯𐨹𐨸𐨅"]) + ("s_=o" ["𐨯𐨹𐨸𐨆"]) + + ("h" ["𐨱𐨿"]) + ("ha" ["𐨱"]) + ("hi" ["𐨱𐨁"]) + ("hu" ["𐨱𐨂"]) + ("hR" ["𐨱𐨃"]) + ("he" ["𐨱𐨅"]) + ("ho" ["𐨱𐨆"]) + ("h_" ["𐨱𐨹𐨿"]) + ("h_a" ["𐨱𐨹"]) + ("h_i" ["𐨱𐨹𐨁"]) + ("h_u" ["𐨱𐨹𐨂"]) + ("h_R" ["𐨱𐨹𐨃"]) + ("h_e" ["𐨱𐨹𐨅"]) + ("h_o" ["𐨱𐨹𐨆"]) + ("h=" ["𐨱𐨿𐨸"]) + ("h=a" ["𐨱𐨸"]) + ("h=i" ["𐨱𐨸𐨁"]) + ("h=u" ["𐨱𐨸𐨂"]) + ("h=R" ["𐨱𐨸𐨃"]) + ("h=e" ["𐨱𐨸𐨅"]) + ("h=o" ["𐨱𐨸𐨆"]) + ("h_=" ["𐨱𐨹𐨿𐨸"]) + ("h_=a" ["𐨱𐨹𐨸"]) + ("h_=i" ["𐨱𐨹𐨸𐨁"]) + ("h_=u" ["𐨱𐨹𐨸𐨂"]) + ("h_=R" ["𐨱𐨹𐨸𐨃"]) + ("h_=e" ["𐨱𐨹𐨸𐨅"]) + ("h_=o" ["𐨱𐨹𐨸𐨆"]) + + ("k'" ["𐨲𐨿"]) + ("k'a" ["𐨲"]) + ("k'i" ["𐨲𐨁"]) + ("k'u" ["𐨲𐨂"]) + ("k'R" ["𐨲𐨃"]) + ("k'e" ["𐨲𐨅"]) + ("k'o" ["𐨲𐨆"]) + ("k'_" ["𐨲𐨹𐨿"]) + ("k'_a" ["𐨲𐨹"]) + ("k'_i" ["𐨲𐨹𐨁"]) + ("k'_u" ["𐨲𐨹𐨂"]) + ("k'_R" ["𐨲𐨹𐨃"]) + ("k'_e" ["𐨲𐨹𐨅"]) + ("k'_o" ["𐨲𐨹𐨆"]) + ("k'=" ["𐨲𐨿𐨸"]) + ("k'=a" ["𐨲𐨸"]) + ("k'=i" ["𐨲𐨸𐨁"]) + ("k'=u" ["𐨲𐨸𐨂"]) + ("k'=R" ["𐨲𐨸𐨃"]) + ("k'=e" ["𐨲𐨸𐨅"]) + ("k'=o" ["𐨲𐨸𐨆"]) + ("k'_=" ["𐨲𐨹𐨿𐨸"]) + ("k'_=a" ["𐨲𐨹𐨸"]) + ("k'_=i" ["𐨲𐨹𐨸𐨁"]) + ("k'_=u" ["𐨲𐨹𐨸𐨂"]) + ("k'_=R" ["𐨲𐨹𐨸𐨃"]) + ("k'_=e" ["𐨲𐨹𐨸𐨅"]) + ("k'_=o" ["𐨲𐨹𐨸𐨆"]) + + ("T'" ["𐨴𐨿"]) + ("T'a" ["𐨴"]) + ("T'i" ["𐨴𐨁"]) + ("T'u" ["𐨴𐨂"]) + ("T'R" ["𐨴𐨃"]) + ("T'e" ["𐨴𐨅"]) + ("T'o" ["𐨴𐨆"]) + ("T'_" ["𐨴𐨹𐨿"]) + ("T'_a" ["𐨴𐨹"]) + ("T'_i" ["𐨴𐨹𐨁"]) + ("T'_u" ["𐨴𐨹𐨂"]) + ("T'_R" ["𐨴𐨹𐨃"]) + ("T'_e" ["𐨴𐨹𐨅"]) + ("T'_o" ["𐨴𐨹𐨆"]) + ("T'=" ["𐨴𐨿𐨸"]) + ("T'=a" ["𐨴𐨸"]) + ("T'=i" ["𐨴𐨸𐨁"]) + ("T'=u" ["𐨴𐨸𐨂"]) + ("T'=R" ["𐨴𐨸𐨃"]) + ("T'=e" ["𐨴𐨸𐨅"]) + ("T'=o" ["𐨴𐨸𐨆"]) + ("T'_=" ["𐨴𐨹𐨿𐨸"]) + ("T'_=a" ["𐨴𐨹𐨸"]) + ("T'_=i" ["𐨴𐨹𐨸𐨁"]) + ("T'_=u" ["𐨴𐨹𐨸𐨂"]) + ("T'_=R" ["𐨴𐨹𐨸𐨃"]) + ("T'_=e" ["𐨴𐨹𐨸𐨅"]) + ("T'_=o" ["𐨴𐨹𐨸𐨆"]) + + ("Th'" ["𐨳𐨿"]) + ("Th'a" ["𐨳"]) + ("Th'i" ["𐨳𐨁"]) + ("Th'u" ["𐨳𐨂"]) + ("Th'R" ["𐨳𐨃"]) + ("Th'e" ["𐨳𐨅"]) + ("Th'o" ["𐨳𐨆"]) + ("Th'_" ["𐨳𐨹𐨿"]) + ("Th'_a" ["𐨳𐨹"]) + ("Th'_i" ["𐨳𐨹𐨁"]) + ("Th'_u" ["𐨳𐨹𐨂"]) + ("Th'_R" ["𐨳𐨹𐨃"]) + ("Th'_e" ["𐨳𐨹𐨅"]) + ("Th'_o" ["𐨳𐨹𐨆"]) + ("Th'=" ["𐨳𐨿𐨸"]) + ("Th'=a" ["𐨳𐨸"]) + ("Th'=i" ["𐨳𐨸𐨁"]) + ("Th'=u" ["𐨳𐨸𐨂"]) + ("Th'=R" ["𐨳𐨸𐨃"]) + ("Th'=e" ["𐨳𐨸𐨅"]) + ("Th'=o" ["𐨳𐨸𐨆"]) + ("Th'_=" ["𐨳𐨹𐨿𐨸"]) + ("Th'_=a" ["𐨳𐨹𐨸"]) + ("Th'_=i" ["𐨳𐨹𐨸𐨁"]) + ("Th'_=u" ["𐨳𐨹𐨸𐨂"]) + ("Th'_=R" ["𐨳𐨹𐨸𐨃"]) + ("Th'_=e" ["𐨳𐨹𐨸𐨅"]) + ("Th'_=o" ["𐨳𐨹𐨸𐨆"]) + + ("vh" ["𐨵𐨿"]) + ("vha" ["𐨵"]) + ("vhi" ["𐨵𐨁"]) + ("vhu" ["𐨵𐨂"]) + ("vhR" ["𐨵𐨃"]) + ("vhe" ["𐨵𐨅"]) + ("vho" ["𐨵𐨆"]) + ("vh_" ["𐨵𐨹𐨿"]) + ("vh_a" ["𐨵𐨹"]) + ("vh_i" ["𐨵𐨹𐨁"]) + ("vh_u" ["𐨵𐨹𐨂"]) + ("vh_R" ["𐨵𐨹𐨃"]) + ("vh_e" ["𐨵𐨹𐨅"]) + ("vh_o" ["𐨵𐨹𐨆"]) + ("vh=" ["𐨵𐨿𐨸"]) + ("vh=a" ["𐨵𐨸"]) + ("vh=i" ["𐨵𐨸𐨁"]) + ("vh=u" ["𐨵𐨸𐨂"]) + ("vh=R" ["𐨵𐨸𐨃"]) + ("vh=e" ["𐨵𐨸𐨅"]) + ("vh=o" ["𐨵𐨸𐨆"]) + ("vh_=" ["𐨵𐨹𐨿𐨸"]) + ("vh_=a" ["𐨵𐨹𐨸"]) + ("vh_=i" ["𐨵𐨹𐨸𐨁"]) + ("vh_=u" ["𐨵𐨹𐨸𐨂"]) + ("vh_=R" ["𐨵𐨹𐨸𐨃"]) + ("vh_=e" ["𐨵𐨹𐨸𐨅"]) + ("vh_=o" ["𐨵𐨹𐨸𐨆"]) + + ("M" ?𐨎) + ("H" ?𐨏) + ("\\" ?𐨌) + (";;" ?𐨍) + + ("1" ?𐩀) + ("2" ?𐩁) + ("3" ?𐩂) + ("4" ?𐩃) + ("10" ?𐩄) + ("20" ?𐩅) + ("100" ?𐩆) + ("1000" ?𐩇) + + (".." ?𐩐) + (".o" ?𐩑) + (".O" ?𐩒) + (".E" ?𐩓) + (".X" ?𐩔) + (".L" ?𐩕) + (".|" ?𐩖) + (".||" ?𐩗) + (".=" ?𐩘)) + (provide 'misc-lang) ;;; misc-lang.el ends here commit 677367ae655151572561219ac99c4226cb1de207 Author: Po Lu Date: Thu Jun 9 16:48:17 2022 +0800 Satisfy GCC warnings on the GNUstep build * src/nsfns.m (ns_move_tooltip_to_mouse_location): * src/nsterm.m ([EmacsWindow draggedImage:movedTo:]): Pacify GCC. diff --git a/src/nsfns.m b/src/nsfns.m index d4cf4f5ffa..add4883e1f 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -3808,6 +3808,8 @@ - (Lisp_Object)lispString NSWindow *window; struct frame *tip_f; + window = nil; + if (!FIXNUMP (tip_dx) || !FIXNUMP (tip_dy)) return; diff --git a/src/nsterm.m b/src/nsterm.m index b0eb86bfb0..3b2830e73d 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -9660,9 +9660,9 @@ - (void) draggedImage: (NSImage *) dragged_image [NSException raise: @"" format: @"Must return DND frame"]; } -#endif out: +#endif if (dnd_move_tooltip_with_frame) ns_move_tooltip_to_mouse_location (mouse_loc); commit dd8db560c25958f8e3ab9c46d6df560fce7c0a88 Author: Po Lu Date: Thu Jun 9 16:43:29 2022 +0800 Disable tooltip timeouts for drag-and-drop tooltips * lisp/mouse.el (mouse-drag-and-drop-region-display-tooltip): Don't time out the created tooltip. diff --git a/lisp/mouse.el b/lisp/mouse.el index 11014fa1c5..9cf6635a01 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -3056,7 +3056,10 @@ Call `tooltip-show-help-non-mode' instead on non-graphical displays." (setf (alist-get 'border-color params) fg)) (when (stringp bg) (setf (alist-get 'background-color params) bg)) - (x-show-tip tooltip nil params)) + ;; Don't time out: this leads to very confusing behavior when + ;; Emacs isn't visible, and the only indication that the user + ;; is actually dragging something abruptly disappears. + (x-show-tip tooltip nil params most-positive-fixnum)) (tooltip-show-help-non-mode tooltip))) (declare-function x-hide-tip "xfns.c") commit 7e5aab18dd427dee61fd924c16719aea5ce623a7 Merge: b2eb627c0d e7ac2ac4e0 Author: Eli Zaretskii Date: Thu Jun 9 11:38:08 2022 +0300 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit e7ac2ac4e07d3fd6fee4a74a9cfc5bac9310fc18 Author: Po Lu Date: Thu Jun 9 16:34:18 2022 +0800 Implement `follow-tooltip' on NS as well * lisp/term/ns-win.el (x-begin-drag): Pass `follow-tooltip'. * src/nsfns.m (Fx_show_tip): Record last dx and dy. (syms_of_nsfns): New staticpros. * src/nsmenu.m ([EmacsTooltip moveTo:]): New method. * src/nsselect.m (Fns_begin_drag): New parameter `follow-tooltip'. * src/nsterm.h (@interface EmacsWindow): (EmacsTooltip): Update prototypes. * src/nsterm.m ([EmacsWindow draggedImage:movedTo:]): Move any tooltip to the right location. ([EmacsWindow beginDrag:forPasteboard...]): New parameter `followTooltip'. diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index 0d46a895ce..ac1007f94f 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -896,7 +896,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (ns-get-selection selection-symbol target-type)) (defun x-begin-drag (targets &optional action frame return-frame - allow-current-frame _follow-tooltip) + allow-current-frame follow-tooltip) "SKIP: real doc in xfns.c." (unless ns-dnd-selection-value (error "No local value for XdndSelection")) @@ -921,7 +921,8 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (expand-file-name ns-dnd-selection-value)))) pasteboard)))) - (ns-begin-drag frame pasteboard action return-frame allow-current-frame))) + (ns-begin-drag frame pasteboard action return-frame + allow-current-frame follow-tooltip))) (defun ns-handle-drag-motion (frame x y) "Handle mouse movement on FRAME at X and Y during drag-and-drop. diff --git a/src/nsfns.m b/src/nsfns.m index 1593338dc9..d4cf4f5ffa 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -63,6 +63,9 @@ Updated by Christian Limpach (chris@nice.ch) /* The frame of the currently visible tooltip, or nil if none. */ static Lisp_Object tip_frame; +/* The X and Y deltas of the last call to `x-show-tip'. */ +static Lisp_Object tip_dx, tip_dy; + /* The window-system window corresponding to the frame of the currently visible tooltip. */ static NSWindow *tip_window; @@ -3243,6 +3246,9 @@ internalBorderWidth or internalBorder (which is what xterm calls else CHECK_FIXNUM (dy); + tip_dx = dx; + tip_dy = dy; + if (use_system_tooltips) { NSSize size; @@ -3794,6 +3800,45 @@ - (Lisp_Object)lispString } @end +void +ns_move_tooltip_to_mouse_location (NSPoint screen_point) +{ + int root_x, root_y; + NSSize size; + NSWindow *window; + struct frame *tip_f; + + if (!FIXNUMP (tip_dx) || !FIXNUMP (tip_dy)) + return; + + if (ns_tooltip) + size = [ns_tooltip frame].size; + else if (!FRAMEP (tip_frame) + || !FRAME_LIVE_P (XFRAME (tip_frame))) + return; + else + { + tip_f = XFRAME (tip_frame); + window = [FRAME_NS_VIEW (tip_f) window]; + size = [window frame].size; + } + + root_x = screen_point.x; + root_y = screen_point.y; + + /* We can directly use `compute_tip_xy' here, since it doesn't cons + nearly as much as it does on X. */ + compute_tip_xy (NULL, Qnil, tip_dx, tip_dy, (int) size.width, + (int) size.height, &root_x, &root_y); + + if (ns_tooltip) + [ns_tooltip moveTo: NSMakePoint (root_x, root_y)]; + else + [window setFrame: NSMakeRect (root_x, root_y, + size.width, size.height) + display: YES]; +} + /* ========================================================================== Lisp interface declaration @@ -3902,6 +3947,10 @@ - (Lisp_Object)lispString staticpro (&tip_last_string); tip_last_parms = Qnil; staticpro (&tip_last_parms); + tip_dx = Qnil; + staticpro (&tip_dx); + tip_dy = Qnil; + staticpro (&tip_dy); #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 defsubr (&Ssystem_move_file_to_trash); diff --git a/src/nsmenu.m b/src/nsmenu.m index 028d19f597..d02d7bae4b 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1497,6 +1497,15 @@ - (void) showAtX: (int)x Y: (int)y for: (int)seconds [timer retain]; } +- (void) moveTo: (NSPoint) screen_point +{ + [win setFrame: NSMakeRect (screen_point.x, + screen_point.y, + [self frame].size.width, + [self frame].size.height) + display: YES]; +} + - (void) hide { [win close]; diff --git a/src/nsselect.m b/src/nsselect.m index 6831090aa2..c46bfeaf42 100644 --- a/src/nsselect.m +++ b/src/nsselect.m @@ -703,7 +703,7 @@ Updated by Christian Limpach (chris@nice.ch) } } -DEFUN ("ns-begin-drag", Fns_begin_drag, Sns_begin_drag, 3, 5, 0, +DEFUN ("ns-begin-drag", Fns_begin_drag, Sns_begin_drag, 3, 6, 0, doc: /* Begin a drag-and-drop operation on FRAME. FRAME must be a window system frame. PBOARD is an alist of (TYPE @@ -729,9 +729,12 @@ nil if no action was performed (either because there was no drop leave FRAME first. If ALLOW-SAME-FRAME is nil, dropping on FRAME will result in the drop -being ignored. */) +being ignored. + +FOLLOW-TOOLTIP means the same thing it does in `x-begin-drag'. */) (Lisp_Object frame, Lisp_Object pboard, Lisp_Object action, - Lisp_Object return_frame, Lisp_Object allow_same_frame) + Lisp_Object return_frame, Lisp_Object allow_same_frame, + Lisp_Object follow_tooltip) { struct frame *f, *return_to; NSPasteboard *pasteboard; @@ -761,7 +764,8 @@ nil if no action was performed (either because there was no drop forPasteboard: pasteboard withMode: mode returnFrameTo: &return_to - prohibitSame: (BOOL) NILP (allow_same_frame)]; + prohibitSame: (BOOL) NILP (allow_same_frame) + followTooltip: (BOOL) !NILP (follow_tooltip)]; if (return_to) { diff --git a/src/nsterm.h b/src/nsterm.h index 37bff6260a..c4fdc7054f 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -426,6 +426,7 @@ enum ns_return_frame_mode struct frame *dnd_return_frame; enum ns_return_frame_mode dnd_mode; BOOL dnd_allow_same_frame; + BOOL dnd_move_tooltip_with_frame; } #ifdef NS_IMPL_GNUSTEP @@ -446,7 +447,8 @@ enum ns_return_frame_mode forPasteboard: (NSPasteboard *) pasteboard withMode: (enum ns_return_frame_mode) mode returnFrameTo: (struct frame **) frame_return - prohibitSame: (BOOL) prohibit_same_frame; + prohibitSame: (BOOL) prohibit_same_frame + followTooltip: (BOOL) follow_tooltip; - (BOOL) mustNotDropOn: (NSView *) receiver; @end @@ -630,19 +632,21 @@ enum ns_return_frame_mode #else @interface EmacsTooltip : NSObject #endif - { - NSWindow *win; - NSTextField *textField; - NSTimer *timer; - } +{ + NSWindow *win; + NSTextField *textField; + NSTimer *timer; +} + - (instancetype) init; -- (void) setText: (char *)text; -- (void) setBackgroundColor: (NSColor *)col; -- (void) setForegroundColor: (NSColor *)col; -- (void) showAtX: (int)x Y: (int)y for: (int)seconds; +- (void) setText: (char *) text; +- (void) setBackgroundColor: (NSColor *) col; +- (void) setForegroundColor: (NSColor *) col; +- (void) showAtX: (int) x Y: (int) y for: (int) seconds; - (void) hide; - (BOOL) isActive; - (NSRect) frame; +- (void) moveTo: (NSPoint) screen_point; @end @@ -1140,6 +1144,9 @@ extern const char *ns_get_pending_menu_title (void); #endif /* Implemented in nsfns, published in nsterm. */ +#ifdef __OBJC__ +extern void ns_move_tooltip_to_mouse_location (NSPoint); +#endif extern void ns_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval); extern void ns_set_scroll_bar_default_width (struct frame *f); diff --git a/src/nsterm.m b/src/nsterm.m index 4663ac85d8..b0eb86bfb0 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -9629,35 +9629,45 @@ - (void) draggedImage: (NSImage *) image selected_op = operation; } -#ifdef NS_IMPL_COCOA - (void) draggedImage: (NSImage *) dragged_image movedTo: (NSPoint) screen_point { + NSPoint mouse_loc; +#ifdef NS_IMPL_COCOA NSInteger window_number; NSWindow *w; +#endif - if (dnd_mode == RETURN_FRAME_NEVER) - return; + mouse_loc = [NSEvent mouseLocation]; - window_number = [NSWindow windowNumberAtPoint: [NSEvent mouseLocation] - belowWindowWithWindowNumber: 0]; - w = [NSApp windowWithWindowNumber: window_number]; +#ifdef NS_IMPL_COCOA + if (dnd_mode != RETURN_FRAME_NEVER) + { + window_number = [NSWindow windowNumberAtPoint: mouse_loc + belowWindowWithWindowNumber: 0]; + w = [NSApp windowWithWindowNumber: window_number]; - if (!w || w != self) - dnd_mode = RETURN_FRAME_NOW; + if (!w || w != self) + dnd_mode = RETURN_FRAME_NOW; - if (dnd_mode != RETURN_FRAME_NOW - || ![[w delegate] isKindOfClass: [EmacsView class]]) - return; + if (dnd_mode != RETURN_FRAME_NOW + || ![[w delegate] isKindOfClass: [EmacsView class]]) + goto out; - dnd_return_frame = ((EmacsView *) [w delegate])->emacsframe; + dnd_return_frame = ((EmacsView *) [w delegate])->emacsframe; - /* FIXME: there must be a better way to leave the event loop. */ - [NSException raise: @"" - format: @"Must return DND frame"]; -} + /* FIXME: there must be a better way to leave the event loop. */ + [NSException raise: @"" + format: @"Must return DND frame"]; + } #endif + out: + + if (dnd_move_tooltip_with_frame) + ns_move_tooltip_to_mouse_location (mouse_loc); +} + - (BOOL) mustNotDropOn: (NSView *) receiver { return ([receiver window] == self @@ -9669,6 +9679,7 @@ - (NSDragOperation) beginDrag: (NSDragOperation) op withMode: (enum ns_return_frame_mode) mode returnFrameTo: (struct frame **) frame_return prohibitSame: (BOOL) prohibit_same_frame + followTooltip: (BOOL) follow_tooltip { NSImage *image; #ifdef NS_IMPL_COCOA @@ -9681,6 +9692,7 @@ - (NSDragOperation) beginDrag: (NSDragOperation) op dnd_mode = mode; dnd_return_frame = NULL; dnd_allow_same_frame = !prohibit_same_frame; + dnd_move_tooltip_with_frame = follow_tooltip; /* Now draw transparency onto the image. */ [image lockFocus]; @@ -9728,6 +9740,10 @@ - (NSDragOperation) beginDrag: (NSDragOperation) op #endif unblock_input (); + /* The drop happened, so delete the tooltip. */ + if (follow_tooltip) + Fx_hide_tip (); + /* Assume all buttons have been released since the drag-and-drop operation is now over. */ if (!dnd_return_frame) commit 0ba43e15d9c9ffb3df8aeb3a7e446d9a4d62ccff Author: Po Lu Date: Thu Jun 9 15:44:51 2022 +0800 Note caveats of `follow-tooltip' with system tooltips * lisp/mouse.el (mouse-drag-and-drop-region): Turn off system tooltips inside. * src/xfns.c (Fx_begin_drag): Say that follow-tooltip doesn't work with system tooltips. diff --git a/lisp/mouse.el b/lisp/mouse.el index 6a2b1738f7..11014fa1c5 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -3103,6 +3103,9 @@ is copied instead of being cut." ;; tooltip. (mouse-fine-grained-tracking t) (was-tooltip-mode tooltip-mode) + ;; System tooltips tend to flicker and in general work + ;; incorrectly. + (use-system-tooltips nil) ;; Whether or not some text was ``cut'' from Emacs to another ;; program and the cleaanup code should not try modifying the ;; region. diff --git a/src/xfns.c b/src/xfns.c index 15e96183e3..43d4d27372 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6884,7 +6884,8 @@ mouse buttons are released on top of FRAME. If FOLLOW-TOOLTIP is non-nil, any tooltip currently being displayed will be moved to follow the mouse pointer while the drag is in -progress. +progress. Note that this does not work with system tooltips (tooltips +created when `use-system-tooltips' is non-nil). This function will sometimes return immediately if no mouse buttons are currently held down. It should only be called when it is known commit b2eb627c0db2b157fb43e8d2d40b5b2c1dd436f7 Author: Eli Zaretskii Date: Thu Jun 9 10:28:25 2022 +0300 ; * doc/lispref/processes.texi (Bindat Types): Fix wording. (Bug#55815) diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index a93a617c8a..7c37853eca 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3479,7 +3479,7 @@ Unsigned integer in little endian order, with @var{bitlen} bits. @var{bitlen} has to be a multiple of 8. @item str @var{len} -Unibyte string (@pxref{Text Representations}) of length @var{len}. +Unibyte string (@pxref{Text Representations}) of length @var{len} bytes. When packing, the first @var{len} bytes of the input string are copied to the packed output. If the input string is shorter than @var{len}, the remaining bytes will be null (zero) unless a pre-allocated string @@ -3506,7 +3506,7 @@ The packed output will not be null-terminated unless one of the following is true: @itemize @item -The input string is shorter than @var{len} and either no pre-allocated +The input string is shorter than @var{len} bytes and either no pre-allocated string was provided to @code{bindat-pack} or the appropriate byte in the pre-allocated string was already null. @item commit ed9b261ae21ab17b710f2a172d2b12b1c725fd62 Author: Richard Hansen Date: Thu Jun 2 21:05:40 2022 -0400 bindat: Improve str, strz documentation * doc/lispref/processes.texi (Bindat Types): Expand the documentation for the `str' and `strz' types to clarify expectations and explain edge case behavior. diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 668a577870..a93a617c8a 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3479,11 +3479,41 @@ Unsigned integer in little endian order, with @var{bitlen} bits. @var{bitlen} has to be a multiple of 8. @item str @var{len} -String of bytes of length @var{len}. +Unibyte string (@pxref{Text Representations}) of length @var{len}. +When packing, the first @var{len} bytes of the input string are copied +to the packed output. If the input string is shorter than @var{len}, +the remaining bytes will be null (zero) unless a pre-allocated string +was provided to @code{bindat-pack}, in which case the remaining bytes +are left unmodified. When unpacking, any null bytes in the packed +input string will appear in the unpacked output. @item strz &optional @var{len} -Zero-terminated string of bytes, can be of arbitrary length or in a fixed-size -field with length @var{len}. +If @var{len} is not provided: Variable-length null-terminated unibyte +string (@pxref{Text Representations}). When packing, the entire input +string is copied to the packed output followed by a null byte. The +length of the packed output is the length of the input string plus one +(for the added null byte). The input string must not contain any null +bytes. When unpacking, the resulting string contains all bytes up to +(but excluding) the null byte. + +If @var{len} is provided: @code{strz} behaves the same as @code{str} +with one difference: When unpacking, the first null byte encountered +in the packed string and all subsequent bytes are excluded from the +unpacked result. + +@quotation Caution +The packed output will not be null-terminated unless one of the +following is true: +@itemize +@item +The input string is shorter than @var{len} and either no pre-allocated +string was provided to @code{bindat-pack} or the appropriate byte in +the pre-allocated string was already null. +@item +The input string contains a null byte within the first @var{len} +bytes. +@end itemize +@end quotation @item vec @var{len} [@var{type}] Vector of @var{len} elements. The type of the elements is given by commit 0936d6fa20894159d75eb1933325d653e4820d90 Author: Po Lu Date: Thu Jun 9 07:20:22 2022 +0000 Implement `follow-tooltip' for DND on Haiku * lisp/term/haiku-win.el (x-begin-drag): Implement `follow-tooltip'. * src/haikufns.c (Fx_show_tip): Record last dx and dy. (syms_of_haikufns): New staticpros. * src/haikuselect.c (haiku_unwind_drag_message): Clear new flag. (Fhaiku_drag_message): New argument `follow-tooltip'. Set new flag. (haiku_dnd_compute_tip_xy): New function. (haiku_note_drag_motion): Move tooltip if flag is true. * src/haikuterm.c (haiku_read_socket): Don't generate help event if mouse moves onto a tooltip during DND. * src/haikuterm.h: Update prototypes. diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 5821751390..f99d332bd2 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -367,7 +367,7 @@ take effect on menu items until the menu bar is updated again." (setq haiku-drag-track-function #'haiku-dnd-drag-handler) (defun x-begin-drag (targets &optional action frame _return-frame - allow-current-frame _follow-tooltip) + allow-current-frame follow-tooltip) "SKIP: real doc in xfns.c." (unless haiku-dnd-selection-value (error "No local value for XdndSelection")) @@ -409,7 +409,8 @@ take effect on menu items until the menu bar is updated again." action) 'XdndActionCopy) (haiku-drag-message (or frame (selected-frame)) - message allow-current-frame)))) + message allow-current-frame + follow-tooltip)))) (add-variable-watcher 'use-system-tooltips #'haiku-use-system-tooltips-watcher) diff --git a/src/haikufns.c b/src/haikufns.c index 6a79eede0e..0b8bf89d85 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -50,6 +50,9 @@ along with GNU Emacs. If not, see . */ /* The frame of the currently visible tooltip. */ Lisp_Object tip_frame; +/* The X and Y deltas of the last call to `x-show-tip'. */ +Lisp_Object tip_dx, tip_dy; + /* The window-system window corresponding to the frame of the currently visible tooltip. */ static Window tip_window; @@ -2352,6 +2355,9 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, else CHECK_FIXNUM (dy); + tip_dx = dx; + tip_dy = dy; + if (use_system_tooltips) { int root_x, root_y; @@ -3165,6 +3171,10 @@ syms_of_haikufns (void) staticpro (&tip_last_string); tip_last_parms = Qnil; staticpro (&tip_last_parms); + tip_dx = Qnil; + staticpro (&tip_dx); + tip_dy = Qnil; + staticpro (&tip_dy); DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size, doc: /* SKIP: real doc in xfns.c. */); diff --git a/src/haikuselect.c b/src/haikuselect.c index 80604252cb..b69fcfff13 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -33,6 +33,9 @@ along with GNU Emacs. If not, see . */ the nested event loop inside be_drag_message. */ struct frame *haiku_dnd_frame; +/* Whether or not to move the tip frame during drag-and-drop. */ +bool haiku_dnd_follow_tooltip; + static void haiku_lisp_to_message (Lisp_Object, void *); static enum haiku_clipboard @@ -752,10 +755,13 @@ haiku_unwind_drag_message (void *message) { haiku_dnd_frame = NULL; BMessage_delete (message); + + if (haiku_dnd_follow_tooltip) + Fx_hide_tip (); } DEFUN ("haiku-drag-message", Fhaiku_drag_message, Shaiku_drag_message, - 2, 3, 0, + 2, 4, 0, doc: /* Begin dragging MESSAGE from FRAME. MESSAGE an alist of strings, denoting message field names, to a list @@ -789,8 +795,12 @@ FRAME is a window system frame that must be visible, from which the drag will originate. ALLOW-SAME-FRAME, if nil or not specified, means that MESSAGE will be -ignored if it is dropped on top of FRAME. */) - (Lisp_Object frame, Lisp_Object message, Lisp_Object allow_same_frame) +ignored if it is dropped on top of FRAME. + +FOLLOW-TOOLTIP, if non-nil, will cause any non-system tooltip +currently being displayed to move along with the mouse pointer. */) + (Lisp_Object frame, Lisp_Object message, Lisp_Object allow_same_frame, + Lisp_Object follow_tooltip) { specpdl_ref idx; void *be_message; @@ -804,15 +814,18 @@ ignored if it is dropped on top of FRAME. */) error ("Frame is invisible"); haiku_dnd_frame = f; + haiku_dnd_follow_tooltip = !NILP (follow_tooltip); be_message = be_create_simple_message (); record_unwind_protect_ptr (haiku_unwind_drag_message, be_message); haiku_lisp_to_message (message, be_message); + rc = be_drag_message (FRAME_HAIKU_VIEW (f), be_message, !NILP (allow_same_frame), block_input, unblock_input, process_pending_signals, haiku_should_quit_drag); + FRAME_DISPLAY_INFO (f)->grabbed = 0; if (rc) @@ -918,6 +931,44 @@ after it starts. */) return SAFE_FREE_UNBIND_TO (depth, Qnil); } +static void +haiku_dnd_compute_tip_xy (int *root_x, int *root_y) +{ + int min_x, min_y, max_x, max_y; + int width, height; + + width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame)); + height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame)); + + min_x = 0; + min_y = 0; + be_get_screen_dimensions (&max_x, &max_y); + + if (*root_y + XFIXNUM (tip_dy) <= min_y) + *root_y = min_y; /* Can happen for negative dy */ + else if (*root_y + XFIXNUM (tip_dy) + height <= max_y) + /* It fits below the pointer */ + *root_y += XFIXNUM (tip_dy); + else if (height + XFIXNUM (tip_dy) + min_y <= *root_y) + /* It fits above the pointer. */ + *root_y -= height + XFIXNUM (tip_dy); + else + /* Put it on the top. */ + *root_y = min_y; + + if (*root_x + XFIXNUM (tip_dx) <= min_x) + *root_x = 0; /* Can happen for negative dx */ + else if (*root_x + XFIXNUM (tip_dx) + width <= max_x) + /* It fits to the right of the pointer. */ + *root_x += XFIXNUM (tip_dx); + else if (width + XFIXNUM (tip_dx) + min_x <= *root_x) + /* It fits to the left of the pointer. */ + *root_x -= width + XFIXNUM (tip_dx); + else + /* Put it left justified on the screen -- it ought to fit that way. */ + *root_x = min_x; +} + static Lisp_Object haiku_note_drag_motion_1 (void *data) { @@ -936,6 +987,26 @@ haiku_note_drag_motion_2 (enum nonlocal_exit exit, Lisp_Object error) void haiku_note_drag_motion (void) { + struct frame *tip_f; + int x, y; + + if (FRAMEP (tip_frame) && haiku_dnd_follow_tooltip + && FIXNUMP (tip_dx) && FIXNUMP (tip_dy)) + { + tip_f = XFRAME (tip_frame); + + if (FRAME_LIVE_P (tip_f)) + { + BView_get_mouse (FRAME_HAIKU_VIEW (haiku_dnd_frame), + &x, &y); + BView_convert_to_screen (FRAME_HAIKU_VIEW (haiku_dnd_frame), + &x, &y); + + haiku_dnd_compute_tip_xy (&x, &y); + BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f), x, y); + } + } + internal_catch_all (haiku_note_drag_motion_1, NULL, haiku_note_drag_motion_2); } diff --git a/src/haikuterm.c b/src/haikuterm.c index 55e8640ec2..d47e61e60d 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3286,10 +3286,15 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) if (FRAME_TOOLTIP_P (f)) { /* Dismiss the tooltip if the mouse moves onto a - tooltip frame. FIXME: for some reason we don't get - leave notification events for this. */ + tooltip frame (except when drag-and-drop is in + progress and we are trying to move the tooltip + along with the mouse pointer). FIXME: for some + reason we don't get leave notification events for + this. */ if (any_help_event_p + && !(be_drag_and_drop_in_progress () + && haiku_dnd_follow_tooltip) && !((EQ (track_mouse, Qdrag_source) || EQ (track_mouse, Qdropping)) && gui_mouse_grabbed (x_display_list))) diff --git a/src/haikuterm.h b/src/haikuterm.h index 41b1a85b00..ea20289b5d 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -219,7 +219,11 @@ extern struct haiku_display_info *x_display_list; extern struct font_driver const haikufont_driver; extern Lisp_Object tip_frame; +extern Lisp_Object tip_dx; +extern Lisp_Object tip_dy; + extern struct frame *haiku_dnd_frame; +extern bool haiku_dnd_follow_tooltip; extern frame_parm_handler haiku_frame_parm_handlers[]; commit 43f8690ebf3439af90cf72c619e75afb4cff1a83 Author: Jim Porter Date: Thu Jun 2 21:12:04 2022 -0700 Account for remapped faces in $COLUMNS and $LINES in Eshell * src/window.h (window_body_unit): New enum... (window_body_width): ... use it. * src/window.c (window_body_unit_from_symbol): New function. (window_body_height, window_body_width): Make PIXELWISE a 'window_body_unit'. (window-body-height, window-body-width): Accept 'remap' for PIXELWISE. (window-lines-pixel-dimensions, window_change_record_windows) (run_window_change_functions, resize_frame_windows, grow_mini_window) (shrink_mini_window, scroll-left, scroll-right): Update calls to 'window_body_height' and 'window_body_width'. * src/indent.c (compute_motion): Update calls to 'window_body_width'. * lisp/eshell/em-ls.el (eshell-ls-find-column-widths) (eshell-ls-find-column-lengths): Use 'window-body-width'. * lisp/eshell/esh-var.el (eshell-variable-aliases-list): Use 'window-body-width' and 'window-body-height'. * test/lisp/eshell/esh-var-tests.el (esh-var-test/window-height) (esh-var-test/window-width): Rename to... (esh-var-test/lines-var, esh-var-test/columns-var): ... and update expected value. * doc/lispref/windows.texi (Window Sizes): Document new behavior of PIXELWISE argument for 'window-body-width' and 'window-body-height'. * etc/NEWS: Announce this change (bug#55696). diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 0d285b2ad4..704ed30366 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -829,14 +829,18 @@ This function returns the height, in lines, of the body of window @var{window}. If @var{window} is omitted or @code{nil}, it defaults to the selected window; otherwise it must be a live window. -If the optional argument @var{pixelwise} is non-@code{nil}, this -function returns the body height of @var{window} counted in pixels. +The optional argument @var{pixelwise} defines the units to use for the +height. If @code{nil}, return the body height of @var{window} in +characters, rounded down to the nearest integer, if necessary. This +means that if a line at the bottom of the text area is only partially +visible, that line is not counted. It also means that the height of a +window's body can never exceed its total height as returned by +@code{window-total-height}. -If @var{pixelwise} is @code{nil}, the return value is rounded down to -the nearest integer, if necessary. This means that if a line at the -bottom of the text area is only partially visible, that line is not -counted. It also means that the height of a window's body can never -exceed its total height as returned by @code{window-total-height}. +If @var{pixelwise} is @code{remap} and the default face is remapped +(@pxref{Face Remapping}), use the remapped face to determine the +character height. For any other non-@code{nil} value, return the +height in pixels. @end defun @cindex window body width @@ -857,14 +861,18 @@ This function returns the width, in columns, of the body of window @var{window}. If @var{window} is omitted or @code{nil}, it defaults to the selected window; otherwise it must be a live window. -If the optional argument @var{pixelwise} is non-@code{nil}, this -function returns the body width of @var{window} in units of pixels. - -If @var{pixelwise} is @code{nil}, the return value is rounded down to -the nearest integer, if necessary. This means that if a column on the -right of the text area is only partially visible, that column is not -counted. It also means that the width of a window's body can never -exceed its total width as returned by @code{window-total-width}. +The optional argument @var{pixelwise} defines the units to use for the +width. If @code{nil}, return the body width of @var{window} in +characters, rounded down to the nearest integer, if necessary. This +means that if a column on the right of the text area is only partially +visible, that column is not counted. It also means that the width of +a window's body can never exceed its total width as returned by +@code{window-total-width}. + +If @var{pixelwise} is @code{remap} and the default face is remapped +(@pxref{Face Remapping}), use the remapped face to determine the +character width. For any other non-@code{nil} value, return the width +in pixels. @end defun @cindex window body size diff --git a/etc/NEWS b/etc/NEWS index fc9e949d8b..5710c4e50a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2433,6 +2433,12 @@ dimensions. Specifying a cons as the FROM argument allows to start measuring text from a specified amount of pixels above or below a position. ++++ +** 'window-body-width' and 'window-body-height' can use remapped faces. +Specifying 'remap' as the PIXELWISE argument now checks if the default +face was remapped, and if so, uses the remapped face to determine the +character width/height. + +++ ** 'set-window-vscroll' now accepts a new argument PRESERVE-VSCROLL-P. This means the vscroll will not be reset when set on a window that is diff --git a/lisp/eshell/em-ls.el b/lisp/eshell/em-ls.el index 874591d250..bebb0d81b5 100644 --- a/lisp/eshell/em-ls.el +++ b/lisp/eshell/em-ls.el @@ -800,7 +800,7 @@ to use, and each member of which is the width of that column (+ 2 (length (car file)))) files)) ;; must account for the added space... - (max-width (+ (window-width) 2)) + (max-width (+ (window-body-width nil 'remap) 2)) (best-width 0) col-widths) @@ -845,7 +845,7 @@ to use, and each member of which is the width of that column (lambda (file) (+ 2 (length (car file)))) files)) - (max-width (+ (window-width) 2)) + (max-width (+ (window-body-width nil 'remap) 2)) col-widths colw) diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index 27be6e1b1a..17add9b668 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -149,8 +149,8 @@ if they are quoted with a backslash." (defcustom eshell-variable-aliases-list `(;; for eshell.el - ("COLUMNS" ,(lambda (_indices) (window-width)) t) - ("LINES" ,(lambda (_indices) (window-height)) t) + ("COLUMNS" ,(lambda (_indices) (window-body-width nil 'remap)) t) + ("LINES" ,(lambda (_indices) (window-body-height nil 'remap)) t) ;; for eshell-cmd.el ("_" ,(lambda (indices) diff --git a/src/indent.c b/src/indent.c index acbb9dc972..51f6f414de 100644 --- a/src/indent.c +++ b/src/indent.c @@ -1204,7 +1204,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos, /* Negative width means use all available text columns. */ if (width < 0) { - width = window_body_width (win, 0); + width = window_body_width (win, WINDOW_BODY_IN_CANONICAL_CHARS); /* We must make room for continuation marks if we don't have fringes. */ #ifdef HAVE_WINDOW_SYSTEM if (!FRAME_WINDOW_P (XFRAME (win->frame))) @@ -1814,7 +1814,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS. */) ? window_internal_height (w) : XFIXNUM (XCDR (topos))), (NILP (topos) - ? (window_body_width (w, 0) + ? (window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - ( #ifdef HAVE_WINDOW_SYSTEM FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 : diff --git a/src/window.c b/src/window.c index eba1390fed..e5666ce38e 100644 --- a/src/window.c +++ b/src/window.c @@ -1014,11 +1014,20 @@ WINDOW must be a valid window and defaults to the selected one. */) return make_fixnum (decode_valid_window (window)->top_line); } +static enum window_body_unit +window_body_unit_from_symbol (Lisp_Object unit) +{ + return + (unit == Qremap ? WINDOW_BODY_IN_REMAPPED_CHARS + : NILP (unit) ? WINDOW_BODY_IN_CANONICAL_CHARS + : WINDOW_BODY_IN_PIXELS); +} + /* Return the number of lines/pixels of W's body. Don't count any mode or header line or horizontal divider of W. Rounds down to nearest integer when not working pixelwise. */ static int -window_body_height (struct window *w, bool pixelwise) +window_body_height (struct window *w, enum window_body_unit pixelwise) { int height = (w->pixel_height - WINDOW_TAB_LINE_HEIGHT (w) @@ -1029,11 +1038,27 @@ window_body_height (struct window *w, bool pixelwise) - WINDOW_MODE_LINE_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w)); + int denom = 1; + if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS) + { + if (!NILP (Vface_remapping_alist)) + { + struct frame *f = XFRAME (WINDOW_FRAME (w)); + int face_id = lookup_named_face (NULL, f, Qdefault, true); + struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); + if (face && face->font && face->font->height) + denom = face->font->height; + } + /* For performance, use canonical chars if no face remapping. */ + else + pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS; + } + + if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS) + denom = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)); + /* Don't return a negative value. */ - return max (pixelwise - ? height - : height / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)), - 0); + return max (height / denom, 0); } /* Return the number of columns/pixels of W's body. Don't count columns @@ -1042,7 +1067,7 @@ window_body_height (struct window *w, bool pixelwise) fringes either. Round down to nearest integer when not working pixelwise. */ int -window_body_width (struct window *w, bool pixelwise) +window_body_width (struct window *w, enum window_body_unit pixelwise) { struct frame *f = XFRAME (WINDOW_FRAME (w)); @@ -1059,24 +1084,46 @@ window_body_width (struct window *w, bool pixelwise) ? WINDOW_FRINGES_WIDTH (w) : 0)); + int denom = 1; + if (pixelwise == WINDOW_BODY_IN_REMAPPED_CHARS) + { + if (!NILP (Vface_remapping_alist)) + { + int face_id = lookup_named_face (NULL, f, Qdefault, true); + struct face *face = FACE_FROM_ID_OR_NULL (f, face_id); + if (face && face->font) + { + if (face->font->average_width) + denom = face->font->average_width; + else if (face->font->space_width) + denom = face->font->space_width; + } + } + /* For performance, use canonical chars if no face remapping. */ + else + pixelwise = WINDOW_BODY_IN_CANONICAL_CHARS; + } + + if (pixelwise == WINDOW_BODY_IN_CANONICAL_CHARS) + denom = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)); + /* Don't return a negative value. */ - return max (pixelwise - ? width - : width / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)), - 0); + return max (width / denom, 0); } DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0, doc: /* Return the width of WINDOW's text area. -WINDOW must be a live window and defaults to the selected one. Optional -argument PIXELWISE non-nil means return the width in pixels. The return -value does not include any vertical dividers, fringes or marginal areas, -or scroll bars. +WINDOW must be a live window and defaults to the selected one. The +return value does not include any vertical dividers, fringes or +marginal areas, or scroll bars. -If PIXELWISE is nil, return the largest integer smaller than WINDOW's -pixel width divided by the character width of WINDOW's frame. This -means that if a column at the right of the text area is only partially -visible, that column is not counted. +The optional argument PIXELWISE defines the units to use for the +width. If nil, return the largest integer smaller than WINDOW's pixel +width in units of the character width of WINDOW's frame. If PIXELWISE +is `remap' and the default face is remapped (see +`face-remapping-alist'), use the remapped face to determine the +character width. For any other non-nil value, return the width in +pixels. Note that the returned value includes the column reserved for the continuation glyph. @@ -1084,25 +1131,29 @@ continuation glyph. Also see `window-max-chars-per-line'. */) (Lisp_Object window, Lisp_Object pixelwise) { - return make_fixnum (window_body_width (decode_live_window (window), - !NILP (pixelwise))); + return (make_fixnum + (window_body_width (decode_live_window (window), + window_body_unit_from_symbol (pixelwise)))); } DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0, doc: /* Return the height of WINDOW's text area. -WINDOW must be a live window and defaults to the selected one. Optional -argument PIXELWISE non-nil means return the height of WINDOW's text area -in pixels. The return value does not include the mode line or header -line or any horizontal divider. - -If PIXELWISE is nil, return the largest integer smaller than WINDOW's -pixel height divided by the character height of WINDOW's frame. This -means that if a line at the bottom of the text area is only partially -visible, that line is not counted. */) +WINDOW must be a live window and defaults to the selected one. The +return value does not include the mode line or header line or any +horizontal divider. + +The optional argument PIXELWISE defines the units to use for the +height. If nil, return the largest integer smaller than WINDOW's +pixel height in units of the character height of WINDOW's frame. If +PIXELWISE is `remap' and the default face is remapped (see +`face-remapping-alist'), use the remapped face to determine the +character height. For any other non-nil value, return the height in +pixels. */) (Lisp_Object window, Lisp_Object pixelwise) { - return make_fixnum (window_body_height (decode_live_window (window), - !NILP (pixelwise))); + return (make_fixnum + (window_body_height (decode_live_window (window), + window_body_unit_from_symbol (pixelwise)))); } DEFUN ("window-old-body-pixel-width", @@ -2124,7 +2175,8 @@ though when run from an idle timer with a delay of zero seconds. */) struct glyph_row *row, *end_row; int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w); Lisp_Object rows = Qnil; - int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true); + int window_width = NILP (body) + ? w->pixel_width : window_body_width (w, WINDOW_BODY_IN_PIXELS); int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w); int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); int subtract = NILP (body) ? 0 : (tab_line_height + header_line_height); @@ -3657,8 +3709,10 @@ window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number) wset_old_buffer (w, w->contents); w->old_pixel_width = w->pixel_width; w->old_pixel_height = w->pixel_height; - w->old_body_pixel_width = window_body_width (w, true); - w->old_body_pixel_height = window_body_height (w, true); + w->old_body_pixel_width + = window_body_width (w, WINDOW_BODY_IN_PIXELS); + w->old_body_pixel_height + = window_body_height (w, WINDOW_BODY_IN_PIXELS); } w = NILP (w->next) ? 0 : XWINDOW (w->next); @@ -3903,8 +3957,10 @@ run_window_change_functions (void) && (window_buffer_change || w->pixel_width != w->old_pixel_width || w->pixel_height != w->old_pixel_height - || window_body_width (w, true) != w->old_body_pixel_width - || window_body_height (w, true) != w->old_body_pixel_height)); + || (window_body_width (w, WINDOW_BODY_IN_PIXELS) + != w->old_body_pixel_width) + || (window_body_height (w, WINDOW_BODY_IN_PIXELS) + != w->old_body_pixel_height))); /* The following two are needed when running the default values for this frame below. */ @@ -4768,7 +4824,8 @@ resize_frame_windows (struct frame *f, int size, bool horflag) Lisp_Object mini = f->minibuffer_window; struct window *m = WINDOWP (mini) ? XWINDOW (mini) : NULL; int mini_height = ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) - ? unit + m->pixel_height - window_body_height (m, true) + ? (unit + m->pixel_height + - window_body_height (m, WINDOW_BODY_IN_PIXELS)) : 0); new_pixel_size = max (horflag ? size : size - mini_height, unit); @@ -5255,7 +5312,7 @@ void grow_mini_window (struct window *w, int delta) { struct frame *f = XFRAME (w->frame); - int old_height = window_body_height (w, true); + int old_height = window_body_height (w, WINDOW_BODY_IN_PIXELS); int min_height = FRAME_LINE_HEIGHT (f); eassert (MINI_WINDOW_P (w)); @@ -5289,7 +5346,8 @@ void shrink_mini_window (struct window *w) { struct frame *f = XFRAME (w->frame); - int delta = window_body_height (w, true) - FRAME_LINE_HEIGHT (f); + int delta = (window_body_height (w, WINDOW_BODY_IN_PIXELS) + - FRAME_LINE_HEIGHT (f)); eassert (MINI_WINDOW_P (w)); @@ -6356,9 +6414,10 @@ by this function. This happens in an interactive call. */) (register Lisp_Object arg, Lisp_Object set_minimum) { struct window *w = XWINDOW (selected_window); - EMACS_INT requested_arg = (NILP (arg) - ? window_body_width (w, 0) - 2 - : XFIXNUM (Fprefix_numeric_value (arg))); + EMACS_INT requested_arg = + (NILP (arg) + ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2 + : XFIXNUM (Fprefix_numeric_value (arg))); Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg); if (!NILP (set_minimum)) @@ -6381,9 +6440,10 @@ by this function. This happens in an interactive call. */) (register Lisp_Object arg, Lisp_Object set_minimum) { struct window *w = XWINDOW (selected_window); - EMACS_INT requested_arg = (NILP (arg) - ? window_body_width (w, 0) - 2 - : XFIXNUM (Fprefix_numeric_value (arg))); + EMACS_INT requested_arg = + (NILP (arg) + ? window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS) - 2 + : XFIXNUM (Fprefix_numeric_value (arg))); Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg); if (!NILP (set_minimum)) diff --git a/src/window.h b/src/window.h index 7f7de58846..298a80a536 100644 --- a/src/window.h +++ b/src/window.h @@ -1186,7 +1186,13 @@ extern bool window_wants_mode_line (struct window *); extern bool window_wants_header_line (struct window *); extern bool window_wants_tab_line (struct window *); extern int window_internal_height (struct window *); -extern int window_body_width (struct window *w, bool); +enum window_body_unit + { + WINDOW_BODY_IN_CANONICAL_CHARS, + WINDOW_BODY_IN_PIXELS, + WINDOW_BODY_IN_REMAPPED_CHARS + }; +extern int window_body_width (struct window *w, enum window_body_unit); enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; extern int window_scroll_margin (struct window *, enum margin_unit); extern void temp_output_buffer_show (Lisp_Object); diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index 072cdb9b40..bee495eb6e 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el @@ -476,13 +476,15 @@ inside double-quotes" ;; Built-in variables -(ert-deftest esh-var-test/window-height () - "$LINES should equal (window-height)" - (should (eshell-test-command-result "= $LINES (window-height)"))) - -(ert-deftest esh-var-test/window-width () - "$COLUMNS should equal (window-width)" - (should (eshell-test-command-result "= $COLUMNS (window-width)"))) +(ert-deftest esh-var-test/lines-var () + "$LINES should equal (window-body-height nil 'remap)" + (should (equal (eshell-test-command-result "echo $LINES") + (window-body-height nil 'remap)))) + +(ert-deftest esh-var-test/columns-var () + "$COLUMNS should equal (window-body-width nil 'remap)" + (should (equal (eshell-test-command-result "echo $COLUMNS") + (window-body-width nil 'remap)))) (ert-deftest esh-var-test/last-result-var () "Test using the \"last result\" ($$) variable" commit d18e60fef172cf38b92108144f54ed10ddf67488 Author: Eli Zaretskii Date: Thu Jun 9 09:56:59 2022 +0300 Revert "* src/comp.c (Fcomp_el_to_eln_filename): Update error message." This reverts commit ec987e3e1786d06ffd306e5717b4d7fd118f05ac. This change was installed on the emacs-28 branch instead. diff --git a/src/comp.c b/src/comp.c index 05d9fed448..97bc6a5f9d 100644 --- a/src/comp.c +++ b/src/comp.c @@ -4466,7 +4466,7 @@ the latter is supposed to be used by the Emacs build procedure. */) } if (NILP (base_dir)) error ("Cannot find suitable directory for output in " - "`native-comp-eln-load-path'."); + "`comp-native-load-path'."); } if (!file_name_absolute_p (SSDATA (base_dir))) commit d7270b4445778b10a4d8ff9516dfa188ceeecf31 Author: Juri Linkov Date: Thu Jun 9 09:40:52 2022 +0300 Allow C-x 4 4, C-x 5 5, C-x t t to handle commands that use switch-to-buffer * lisp/window.el (display-buffer-override-next-command): Temporarily set switch-to-buffer-obey-display-actions to t, and revert back to the original value afterwards. This allows other-window-prefix, other-frame-prefix, other-tab-prefix, windmove-display-in-direction to override the default behavior of commands that use switch-to-buffer. https://lists.gnu.org/archive/html/emacs-devel/2022-06/msg00483.html diff --git a/lisp/window.el b/lisp/window.el index 1b8fe2b262..eba888a89d 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -8931,6 +8931,7 @@ to deactivate this overriding action." (let* ((old-window (or (minibuffer-selected-window) (selected-window))) (new-window nil) (minibuffer-depth (minibuffer-depth)) + (obey-display switch-to-buffer-obey-display-actions) (clearfun (make-symbol "clear-display-buffer-overriding-action")) (postfun (make-symbol "post-display-buffer-override-next-command")) (action (lambda (buffer alist) @@ -8955,6 +8956,7 @@ to deactivate this overriding action." (funcall post-function old-window new-window))))) (fset clearfun (lambda () + (setq switch-to-buffer-obey-display-actions obey-display) (setcar display-buffer-overriding-action (delq action (car display-buffer-overriding-action))))) (fset postfun @@ -8971,6 +8973,7 @@ to deactivate this overriding action." (add-hook 'post-command-hook postfun) (when echofun (add-hook 'prefix-command-echo-keystrokes-functions echofun)) + (setq switch-to-buffer-obey-display-actions t) (push action (car display-buffer-overriding-action)) exitfun)) commit ec987e3e1786d06ffd306e5717b4d7fd118f05ac Author: Jeff Walsh Date: Thu Jun 9 10:02:01 2022 +1000 * src/comp.c (Fcomp_el_to_eln_filename): Update error message. diff --git a/src/comp.c b/src/comp.c index 97bc6a5f9d..05d9fed448 100644 --- a/src/comp.c +++ b/src/comp.c @@ -4466,7 +4466,7 @@ the latter is supposed to be used by the Emacs build procedure. */) } if (NILP (base_dir)) error ("Cannot find suitable directory for output in " - "`comp-native-load-path'."); + "`native-comp-eln-load-path'."); } if (!file_name_absolute_p (SSDATA (base_dir))) commit 8436e0bee9cf7aa8162036a1d00b385c850069ae Author: Jeff Walsh Date: Thu Jun 9 10:02:01 2022 +1000 Update error message to reflect variable rename * src/comp.c (Fcomp_el_to_eln_filename): Update error message. (Bug#55861) diff --git a/src/comp.c b/src/comp.c index 188dc6ea00..dc0359acda 100644 --- a/src/comp.c +++ b/src/comp.c @@ -4193,7 +4193,7 @@ the latter is supposed to be used by the Emacs build procedure. */) } if (NILP (base_dir)) error ("Cannot find suitable directory for output in " - "`comp-native-load-path'."); + "`native-comp-eln-load-path'."); } if (!file_name_absolute_p (SSDATA (base_dir))) commit 2f31dbeadff0abc38ded5dd072df1ec179c49945 Author: Po Lu Date: Thu Jun 9 13:11:08 2022 +0800 Also show mouse DND tooltip contents during interprogram drag-and-drop * doc/lispref/frames.texi (Drag and Drop): Document new parameter to `x-begin-drag'. * lisp/mouse.el (mouse-drag-and-drop-region): Don't hide tooltip when initiating interprogram drag-and-drop. * lisp/term/haiku-win.el (x-begin-drag): * lisp/term/ns-win.el (x-begin-drag): Add stubs for new parameter. * src/xfns.c (Fx_begin_drag): New parameter `follow-tooltip'. (Fx_show_tip, syms_of_xfns): Add records of the last dx and dy given to `x-show-tip'. * src/xterm.c (x_clear_dnd_monitors): New function. (x_dnd_begin_drag_and_drop): Save monitor attributes list if appropriate. (x_dnd_compute_tip_xy, x_dnd_update_tooltip_position): New function. (x_dnd_update_state, handle_one_xevent): Update tooltip position during DND mouse movement. (syms_of_xterm): Update staticpros. * src/xterm.h: Update prototypes. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 9f7666ac63..16f7ad312a 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4194,7 +4194,7 @@ 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. -@defun x-begin-drag targets &optional action frame return-frame allow-current-frame +@defun x-begin-drag targets &optional action frame return-frame allow-current-frame follow-tooltip This function begins a drag from @var{frame}, and returns when the drag-and-drop operation ends, either because the drop was successful, or because the drop was rejected. The drop occurs when all mouse @@ -4231,6 +4231,12 @@ want to treat dragging content from one frame to another specially, while also being able to drag content to other programs, but it is not guaranteed to work on all systems and with all window managers. +If @var{follow-tooltip} is non-@code{nil}, the position of any tooltip +(such as one shown by @code{tooltip-show}) will follow the location of +the mouse pointer whenever it moves during the drag-and-drop +operation. The tooltip will be hidden once all mouse buttons are +released. + If the drop was rejected or no drop target was found, this function returns @code{nil}. Otherwise, it returns a symbol describing the action the target chose to perform, which can differ from @var{action} diff --git a/lisp/mouse.el b/lisp/mouse.el index 024a018bb9..6a2b1738f7 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -3244,7 +3244,6 @@ is copied instead of being cut." (cdr mouse-position))))))) (not (posn-window (event-end event)))))) (setq drag-again-mouse-position nil) - (mouse-drag-and-drop-region-hide-tooltip) (gui-set-selection 'XdndSelection value-selection) (let ((drag-action-or-frame (condition-case nil @@ -3259,7 +3258,7 @@ is copied instead of being cut." ;; `return-frame' doesn't ;; work, allow dropping on ;; the drop frame. - (eq window-system 'haiku)) + (eq window-system 'haiku) t) (quit nil)))) (when (framep drag-action-or-frame) ;; With some window managers `x-begin-drag' diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 6ddf546ee5..5821751390 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -366,7 +366,8 @@ take effect on menu items until the menu bar is updated again." (setq haiku-drag-track-function #'haiku-dnd-drag-handler) -(defun x-begin-drag (targets &optional action frame _return-frame allow-current-frame) +(defun x-begin-drag (targets &optional action frame _return-frame + allow-current-frame _follow-tooltip) "SKIP: real doc in xfns.c." (unless haiku-dnd-selection-value (error "No local value for XdndSelection")) diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index 2e021b9b29..0d46a895ce 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -895,7 +895,8 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") &context (window-system ns)) (ns-get-selection selection-symbol target-type)) -(defun x-begin-drag (targets &optional action frame return-frame allow-current-frame) +(defun x-begin-drag (targets &optional action frame return-frame + allow-current-frame _follow-tooltip) "SKIP: real doc in xfns.c." (unless ns-dnd-selection-value (error "No local value for XdndSelection")) diff --git a/src/xfns.c b/src/xfns.c index f0a2ec666c..15e96183e3 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6831,7 +6831,7 @@ The coordinates X and Y are interpreted in pixels relative to a position return Qnil; } -DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 5, 0, +DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 6, 0, doc: /* Begin dragging contents on FRAME, with targets TARGETS. TARGETS is a list of strings, which defines the X selection targets that will be available to the drop target. Block until the mouse @@ -6882,12 +6882,17 @@ If ALLOW-CURRENT-FRAME is not specified or nil, then the drop target is allowed to be FRAME. Otherwise, no action will be taken if the mouse buttons are released on top of FRAME. +If FOLLOW-TOOLTIP is non-nil, any tooltip currently being displayed +will be moved to follow the mouse pointer while the drag is in +progress. + This function will sometimes return immediately if no mouse buttons are currently held down. It should only be called when it is known that mouse buttons are being held down, such as immediately after a `down-mouse-1' (or similar) event. */) (Lisp_Object targets, Lisp_Object action, Lisp_Object frame, - Lisp_Object return_frame, Lisp_Object allow_current_frame) + Lisp_Object return_frame, Lisp_Object allow_current_frame, + Lisp_Object follow_tooltip) { struct frame *f = decode_window_system_frame (frame); int ntargets = 0, nnames = 0; @@ -6985,7 +6990,7 @@ that mouse buttons are being held down, such as immediately after a xaction, return_frame, action_list, (const char **) &name_list, nnames, !NILP (allow_current_frame), target_atoms, - ntargets, original); + ntargets, original, !NILP (follow_tooltip)); SAFE_FREE (); return lval; @@ -7787,12 +7792,15 @@ static void compute_tip_xy (struct frame *, Lisp_Object, Lisp_Object, Lisp_Object, int, int, int *, int *); /* The frame of the currently visible tooltip, or nil if none. */ -static Lisp_Object tip_frame; +Lisp_Object tip_frame; /* The window-system window corresponding to the frame of the currently visible tooltip. */ Window tip_window; +/* The X and Y deltas of the last call to `x-show-tip'. */ +Lisp_Object tip_dx, tip_dy; + /* A timer that hides or deletes the currently visible tooltip when it fires. */ static Lisp_Object tip_timer; @@ -8506,6 +8514,9 @@ Text larger than the specified size is clipped. */) else CHECK_FIXNUM (dy); + tip_dx = dx; + tip_dy = dy; + #ifdef USE_GTK if (use_system_tooltips) { @@ -9931,6 +9942,10 @@ eliminated in future versions of Emacs. */); staticpro (&tip_last_string); tip_last_parms = Qnil; staticpro (&tip_last_parms); + tip_dx = Qnil; + staticpro (&tip_dx); + tip_dy = Qnil; + staticpro (&tip_dy); defsubr (&Sx_uses_old_gtk_dialog); #if defined (USE_MOTIF) || defined (USE_GTK) diff --git a/src/xterm.c b/src/xterm.c index 3cc730c4ee..557555e7a4 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1104,6 +1104,13 @@ struct frame *x_dnd_finish_frame; important information. */ bool x_dnd_waiting_for_finish; +/* Whether or not to move the tooltip along with the mouse pointer + during drag-and-drop. */ +static bool x_dnd_update_tooltip; + +/* Monitor attribute list used for updating the tooltip position. */ +static Lisp_Object x_dnd_monitors; + /* The display the drop target that is supposed to send information is on. */ static Display *x_dnd_finish_display; @@ -4189,6 +4196,12 @@ x_free_dnd_targets (void) x_dnd_n_targets = 0; } +static void +x_clear_dnd_monitors (void) +{ + x_dnd_monitors = Qnil; +} + static void x_free_dnd_toplevels (void) { @@ -10738,7 +10751,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, Lisp_Object return_frame, Atom *ask_action_list, const char **ask_action_names, size_t n_ask_actions, bool allow_current_frame, Atom *target_atoms, - int ntargets, Lisp_Object selection_target_list) + int ntargets, Lisp_Object selection_target_list, + bool follow_tooltip) { #ifndef USE_GTK XEvent next_event; @@ -10941,6 +10955,15 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, unblock_input (); } + if (follow_tooltip) + { + x_dnd_monitors + = Fx_display_monitor_attributes_list (frame); + record_unwind_protect_void (x_clear_dnd_monitors); + } + + x_dnd_update_tooltip = follow_tooltip; + /* This shouldn't happen. */ if (x_dnd_toplevels) x_dnd_free_toplevels (true); @@ -15131,6 +15154,106 @@ mouse_or_wdesc_frame (struct x_display_info *dpyinfo, int wdesc) } } +static void +x_dnd_compute_tip_xy (int *root_x, int *root_y, Lisp_Object attributes) +{ + Lisp_Object monitor, geometry; + int min_x, min_y, max_x, max_y; + int width, height; + + width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame)); + height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame)); + + max_y = -1; + + /* Try to determine the monitor where the mouse pointer is and + its geometry. See bug#22549. */ + while (CONSP (attributes)) + { + monitor = XCAR (attributes); + geometry = assq_no_quit (Qgeometry, monitor); + + if (CONSP (geometry)) + { + min_x = XFIXNUM (Fnth (make_fixnum (1), geometry)); + min_y = XFIXNUM (Fnth (make_fixnum (2), geometry)); + max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry)); + max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry)); + + if (min_x <= *root_x && *root_x < max_x + && min_y <= *root_y && *root_y < max_y) + break; + + max_y = -1; + } + + attributes = XCDR (attributes); + } + + /* It was not possible to determine the monitor's geometry, so we + assign some sane defaults here: */ + if (max_y < 0) + { + min_x = 0; + min_y = 0; + max_x = x_display_pixel_width (FRAME_DISPLAY_INFO (x_dnd_frame)); + max_y = x_display_pixel_height (FRAME_DISPLAY_INFO (x_dnd_frame)); + } + + if (*root_y + XFIXNUM (tip_dy) <= min_y) + *root_y = min_y; /* Can happen for negative dy */ + else if (*root_y + XFIXNUM (tip_dy) + height <= max_y) + /* It fits below the pointer */ + *root_y += XFIXNUM (tip_dy); + else if (height + XFIXNUM (tip_dy) + min_y <= *root_y) + /* It fits above the pointer. */ + *root_y -= height + XFIXNUM (tip_dy); + else + /* Put it on the top. */ + *root_y = min_y; + + if (*root_x + XFIXNUM (tip_dx) <= min_x) + *root_x = 0; /* Can happen for negative dx */ + else if (*root_x + XFIXNUM (tip_dx) + width <= max_x) + /* It fits to the right of the pointer. */ + *root_x += XFIXNUM (tip_dx); + else if (width + XFIXNUM (tip_dx) + min_x <= *root_x) + /* It fits to the left of the pointer. */ + *root_x -= width + XFIXNUM (tip_dx); + else + /* Put it left justified on the screen -- it ought to fit that way. */ + *root_x = min_x; +} + +static void +x_dnd_update_tooltip_position (int root_x, int root_y) +{ + struct frame *tip_f; + + if (!x_dnd_in_progress || !x_dnd_update_tooltip) + return; + + if (!FRAMEP (tip_frame)) + return; + + tip_f = XFRAME (tip_frame); + + if (!FRAME_LIVE_P (tip_f) + || (FRAME_X_DISPLAY (tip_f) + != FRAME_X_DISPLAY (x_dnd_frame))) + return; + + if (tip_window != None + && FIXNUMP (tip_dx) && FIXNUMP (tip_dy)) + { + x_dnd_compute_tip_xy (&root_x, &root_y, + x_dnd_monitors); + + XMoveWindow (FRAME_X_DISPLAY (x_dnd_frame), + tip_window, root_x, root_y); + } +} + /* Get the window underneath the pointer, see if it moved, and update the DND state accordingly. */ static void @@ -15292,6 +15415,8 @@ x_dnd_update_state (struct x_display_info *dpyinfo, Time timestamp) xm_send_drag_motion_message (dpyinfo, FRAME_X_WINDOW (x_dnd_frame), target, &dmsg); } + + x_dnd_update_tooltip_position (root_x, root_y); } /* The pointer moved out of the screen. */ else if (x_dnd_last_protocol_version != -1) @@ -17462,6 +17587,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, target, &dmsg); } + x_dnd_update_tooltip_position (event->xmotion.x_root, + event->xmotion.y_root); + goto OTHER; } @@ -17966,6 +18094,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, { x_dnd_end_window = x_dnd_last_seen_window; x_dnd_in_progress = false; + + if (x_dnd_update_tooltip + && FRAMEP (tip_frame) + && FRAME_LIVE_P (XFRAME (tip_frame)) + && (FRAME_X_DISPLAY (XFRAME (tip_frame)) + == FRAME_X_DISPLAY (x_dnd_frame))) + Fx_hide_tip (); + x_dnd_finish_frame = x_dnd_frame; if (x_dnd_last_seen_window != None @@ -19172,6 +19308,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, target, &dmsg); } + x_dnd_update_tooltip_position (xev->root_x, xev->root_y); + goto XI_OTHER; } @@ -19332,6 +19470,16 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_end_window = x_dnd_last_seen_window; x_dnd_in_progress = false; + /* If a tooltip that we're following is + displayed, hide it now. */ + + if (x_dnd_update_tooltip + && FRAMEP (tip_frame) + && FRAME_LIVE_P (XFRAME (tip_frame)) + && (FRAME_X_DISPLAY (XFRAME (tip_frame)) + == FRAME_X_DISPLAY (x_dnd_frame))) + Fx_hide_tip (); + /* This doesn't have to be marked since it is only accessed if x_dnd_waiting_for_finish is true, which @@ -26645,6 +26793,9 @@ syms_of_xterm (void) x_error_message = NULL; PDUMPER_IGNORE (x_error_message); + x_dnd_monitors = Qnil; + staticpro (&x_dnd_monitors); + DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); DEFSYM (Qlatin_1, "latin-1"); DEFSYM (Qnow, "now"); diff --git a/src/xterm.h b/src/xterm.h index 7e91e28ed1..25d145c6c0 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -736,6 +736,9 @@ extern bool x_display_ok (const char *); extern void select_visual (struct x_display_info *); extern Window tip_window; +extern Lisp_Object tip_dx; +extern Lisp_Object tip_dy; +extern Lisp_Object tip_frame; /* Each X frame object points to its own struct x_output object in the output_data.x field. The x_output structure contains @@ -1467,7 +1470,7 @@ extern bool x_detect_pending_selection_requests (void); extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, Lisp_Object, Atom *, const char **, size_t, bool, Atom *, int, - Lisp_Object); + Lisp_Object, bool); extern void x_dnd_do_unsupported_drop (struct x_display_info *, Lisp_Object, Lisp_Object, Lisp_Object, Window, int, int, Time); commit 7e41b4aa231ed094613fe0ea12e7ec37a396240f Author: Po Lu Date: Thu Jun 9 10:22:14 2022 +0800 Fix dnd-tests on builds without X * test/lisp/dnd-tests.el (x-get-selection-internal): New function declaration. diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index c7e537e53f..c4b7567f22 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -72,6 +72,8 @@ (signal 'error (list "invalid selection" data))) (setf (alist-get type dnd-tests-selection-table) data)))) +(declare-function x-get-selection-internal "xselect.c") + (defun dnd-tests-verify-selection-data (type) "Return the data of the drag-and-drop selection converted to TYPE." (if (eq window-system 'x) commit 8d4551cbdb03d74448eafa818005218191621aed Author: Po Lu Date: Thu Jun 9 10:05:54 2022 +0800 Ignore tooltip frames when looking for DND target * src/xterm.c (x_dnd_get_target_window): When not using client lists, look beneath any tooltip frame. diff --git a/src/xterm.c b/src/xterm.c index 00586d66a0..3cc730c4ee 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1077,6 +1077,10 @@ static void x_scroll_bar_end_update (struct x_display_info *, struct scroll_bar static int x_filter_event (struct x_display_info *, XEvent *); #endif +static struct frame *x_tooltip_window_to_frame (struct x_display_info *, + Window, bool *); +static Window x_get_window_below (Display *, Window, int, int, int *, int *); + /* Global state maintained during a drag-and-drop operation. */ /* Flag that indicates if a drag-and-drop operation is in progress. */ @@ -3544,12 +3548,15 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, { Window child_return, child, dummy, proxy; int dest_x_return, dest_y_return, rc, proto, motif; + int parent_x, parent_y; bool extents_p; #if defined HAVE_XCOMPOSITE && (XCOMPOSITE_MAJOR > 0 || XCOMPOSITE_MINOR > 2) Window overlay_window; XWindowAttributes attrs; #endif int wmstate; + struct frame *tooltip; + bool unrelated; child_return = dpyinfo->root_window; dest_x_return = root_x; @@ -3680,6 +3687,8 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, while (child_return != None) { child = child_return; + parent_x = dest_x_return; + parent_y = dest_y_return; x_catch_errors (dpyinfo->display); rc = XTranslateCoordinates (dpyinfo->display, @@ -3696,6 +3705,23 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, if (child_return) { + /* If child_return is a tooltip frame, look beneath it. We + never want to drop anything onto a tooltip frame. */ + + tooltip = x_tooltip_window_to_frame (dpyinfo, child_return, + &unrelated); + + if (tooltip || unrelated) + child_return = x_get_window_below (dpyinfo->display, child_return, + parent_x, parent_y, &dest_x_return, + &dest_y_return); + + if (!child_return) + { + x_uncatch_errors (); + break; + } + if (x_dnd_get_wm_state_and_proto (dpyinfo, child_return, &wmstate, &proto, &motif, &proxy) @@ -11885,7 +11911,7 @@ x_note_mouse_movement (struct frame *frame, const XMotionEvent *event, return false; } -/* Get a sibling of DPY below WINDOW at PARENT_X and PARENT_Y. */ +/* Get a sibling below WINDOW on DPY at PARENT_X and PARENT_Y. */ static Window x_get_window_below (Display *dpy, Window window, int parent_x, int parent_y, commit dcb45946eee85dd8217fdfc4b728db1e24b16ebe Author: Po Lu Date: Thu Jun 9 09:52:21 2022 +0800 Make use of faster atom intern functions in xselect.c * src/xselect.c (symbol_to_x_atom): (x_atom_to_symbol): Use x_get_atom_name and x_intern_cached_atom. diff --git a/src/xselect.c b/src/xselect.c index a234c7188f..17fe7403b2 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -170,7 +170,7 @@ symbol_to_x_atom (struct x_display_info *dpyinfo, Lisp_Object sym) TRACE1 (" XInternAtom %s", SSDATA (SYMBOL_NAME (sym))); block_input (); - val = XInternAtom (dpyinfo->display, SSDATA (SYMBOL_NAME (sym)), False); + val = x_intern_cached_atom (dpyinfo, SSDATA (SYMBOL_NAME (sym)), false); unblock_input (); return val; } @@ -233,18 +233,17 @@ x_atom_to_symbol (struct x_display_info *dpyinfo, Atom atom) if (atom == dpyinfo->Xatom_XmTRANSFER_FAILURE) return QXmTRANSFER_FAILURE; - block_input (); x_catch_errors (dpyinfo->display); - str = XGetAtomName (dpyinfo->display, atom); + str = x_get_atom_name (dpyinfo, atom, NULL); x_uncatch_errors (); - unblock_input (); + + TRACE0 ("XGetAtomName --> NULL"); + if (!str) + return Qnil; TRACE1 ("XGetAtomName --> %s", str); - if (! str) return Qnil; + val = intern (str); - block_input (); - /* This was allocated by Xlib, so use XFree. */ - XFree (str); - unblock_input (); + xfree (str); return val; } commit d02c94090c4dd7c90da9ccd3268a9e02cadf0a45 Author: Ken Brown Date: Wed Jun 8 13:09:21 2022 -0400 Fix error reporting in process-async-https-with-delay * test/src/process-tests.el (process-async-https-with-delay): Use 'plist-get' instead of 'assq' in testing for a connection error. The 'status' variable is a plist, not an alist. (Bug#55849) diff --git a/test/src/process-tests.el b/test/src/process-tests.el index 14092187e0..725da084e7 100644 --- a/test/src/process-tests.el +++ b/test/src/process-tests.el @@ -939,7 +939,7 @@ Return nil if FILENAME doesn't exist." (< (float-time) (+ t0 limit))) (sit-for 0.1))) (should status) - (should-not (assq :error status)) + (should-not (plist-get status ':error)) (should buf) (should (> (buffer-size buf) 0)) ) commit c754f277a67549bb8346c77a4962bcbf03590ece Author: Juri Linkov Date: Wed Jun 8 20:10:12 2022 +0300 * lisp/rect.el: Return correct positions of region-beginning/end (bug#55234) (rectangle-mark-mode): Add advices for region-beginning and region-end. (rectangle--region-beginning, rectangle--region-end): New advices. (rectangle--extract-region): Let-bind rectangle-mark-mode around region-beginning and region-end to use the original functions. diff --git a/lisp/rect.el b/lisp/rect.el index 15d636f074..e717d2ac7e 100644 --- a/lisp/rect.el +++ b/lisp/rect.el @@ -656,6 +656,8 @@ on. Only lasts until the region is next deactivated." :lighter nil (rectangle--reset-crutches) (when rectangle-mark-mode + (advice-add 'region-beginning :around #'rectangle--region-beginning) + (advice-add 'region-end :around #'rectangle--region-end) (add-hook 'deactivate-mark-hook (lambda () (rectangle-mark-mode -1))) (unless (region-active-p) @@ -754,17 +756,38 @@ Ignores `line-move-visual'." (rectangle--col-pos col 'point))) +(defun rectangle--region-beginning (orig) + "Like `region-beginning' but supports rectangular regions." + (cond + ((not rectangle-mark-mode) + (funcall orig)) + (t + (apply #'min (mapcar #'car (region-bounds)))))) + +(defun rectangle--region-end (orig) + "Like `region-end' but supports rectangular regions." + (cond + ((not rectangle-mark-mode) + (funcall orig)) + (t + (apply #'max (mapcar #'cdr (region-bounds)))))) + (defun rectangle--extract-region (orig &optional delete) (cond ((not rectangle-mark-mode) (funcall orig delete)) ((eq delete 'bounds) - (extract-rectangle-bounds (region-beginning) (region-end))) + (extract-rectangle-bounds + ;; Avoid recursive calls from advice + (let (rectangle-mark-mode) (region-beginning)) + (let (rectangle-mark-mode) (region-end)))) (t (let* ((strs (funcall (if delete #'delete-extract-rectangle #'extract-rectangle) - (region-beginning) (region-end))) + ;; Avoid recursive calls from advice + (let (rectangle-mark-mode) (region-beginning)) + (let (rectangle-mark-mode) (region-end)))) (str (mapconcat #'identity strs "\n"))) (when (eq last-command 'kill-region) ;; Try to prevent kill-region from appending this to some commit 4ad75a50a266f24b48031fcf66df0738f66bea9b Author: Robert Pluim Date: Wed Jun 8 14:48:27 2022 +0200 Add more super and subscript characters to latin input methods * lisp/leim/quail/latin-post.el ("latin-postfix", "latin-prefix"): Add mssing super and subscript characters. (Bug#55722) diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el index 53a5dc6371..9573723e45 100644 --- a/lisp/leim/quail/latin-post.el +++ b/lisp/leim/quail/latin-post.el @@ -2247,6 +2247,8 @@ of characters from a single Latin-N charset. stroke | / | d/ -> đ nordic | / | d/ -> ð t/ -> þ a/ -> å e/ -> æ o/ -> ø symbols | ^ | r^ -> ® t^ -> ™ + super | ^ | 0^ -> ⁰ 1^ -> ¹ +^ -> ⁺ -^ -> ⁻ + subscript | _ | 0_ -> ₀ 1_ -> ₁ +_ -> ₊ -_ -> ₋ others | / | s/ -> ß ?/ -> ¿ !/ -> ¡ // -> ° o/ -> œ | / | 2/ -> ½ 3/ -> ¾ 4/ -> ?¼ | various | << -> « >> -> » o_ -> º a_ -> ª @@ -2254,11 +2256,35 @@ of characters from a single Latin-N charset. Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' " nil t nil nil nil nil nil nil nil nil t) -;; Fixme: ¦ § ¨ © ¬ ­ ¯ ± ² ³ ´ µ ¶ · ¸ ¹ × ÷ +;; Fixme: ¦ § ¨ © ¬ ­ ¯ ± ´ µ ¶ · ¸ × ÷ (quail-define-rules ("2/" ?½) ("3/" ?¾) ("4/" ?¼) + ("0^" ?⁰) + ("1^" ?¹) + ("2^" ?²) + ("3^" ?³) + ("4^" ?⁴) + ("5^" ?⁵) + ("6^" ?⁶) + ("7^" ?⁷) + ("8^" ?⁸) + ("9^" ?⁹) + ("+^" ?⁺) + ("-^" ?⁻) + ("0_" ?₀) + ("1_" ?₁) + ("2_" ?₂) + ("3_" ?₃) + ("4_" ?₄) + ("5_" ?₅) + ("6_" ?₆) + ("7_" ?₇) + ("8_" ?₈) + ("9_" ?₉) + ("+_" ?₊) + ("-_" ?₋) (" _" ? ) ("!/" ?¡) ("//" ?°) @@ -2453,6 +2479,30 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("2//" ["2/"]) ("3//" ["3/"]) ("4//" ["4/"]) + ("0^^" ["0^"]) + ("1^^" ["1^"]) + ("2^^" ["2^"]) + ("3^^" ["3^"]) + ("4^^" ["4^"]) + ("5^^" ["5^"]) + ("6^^" ["6^"]) + ("7^^" ["7^"]) + ("8^^" ["8^"]) + ("9^^" ["9^"]) + ("+^^" ["+^"]) + ("-^^" ["-^"]) + ("0__" ["0_"]) + ("1__" ["1_"]) + ("2__" ["2_"]) + ("3__" ["3_"]) + ("4__" ["4_"]) + ("5__" ["5_"]) + ("6__" ["6_"]) + ("7__" ["7_"]) + ("8__" ["8_"]) + ("9__" ["9_"]) + ("+__" ["+_"]) + ("-__" ["-_"]) (" __" [" _"]) ("!//" ["!/"]) ("///" ["//"]) diff --git a/lisp/leim/quail/latin-pre.el b/lisp/leim/quail/latin-pre.el index 868e4d4774..d53da832be 100644 --- a/lisp/leim/quail/latin-pre.el +++ b/lisp/leim/quail/latin-pre.el @@ -1197,9 +1197,16 @@ of characters from a single Latin-N charset. ("\"w" ?ẅ) ("\"y" ?ÿ) ("^ " ?^) + ("^0" ?⁰) ("^1" ?¹) ("^2" ?²) ("^3" ?³) + ("^4" ?⁴) + ("^5" ?⁵) + ("^6" ?⁶) + ("^7" ?⁷) + ("^8" ?⁸) + ("^9" ?⁹) ("^A" ?Â) ("^C" ?Ĉ) ("^E" ?Ê) @@ -1228,6 +1235,20 @@ of characters from a single Latin-N charset. ("^u" ?û) ("^w" ?ŵ) ("^y" ?ŷ) + ("^+" ?⁺) + ("^-" ?⁻) + ("_0" ?₀) + ("_1" ?₁) + ("_2" ?₂) + ("_3" ?₃) + ("_4" ?₄) + ("_5" ?₅) + ("_6" ?₆) + ("_7" ?₇) + ("_8" ?₈) + ("_9" ?₉) + ("_++" ?₊) + ("_-" ?₋) ("_+" ?±) ("_:" ?÷) ("_a" ?ª) commit 1ce34040fafb9a30499b199c8292b92205147f38 Author: Robert Pluim Date: Wed Jun 8 14:40:03 2022 +0200 Add fractions to latin-post input method * lisp/leim/quail/latin-post.el ("latin-postfix"): Add fractions. diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el index 49df3fd2d1..53a5dc6371 100644 --- a/lisp/leim/quail/latin-post.el +++ b/lisp/leim/quail/latin-post.el @@ -2248,13 +2248,17 @@ of characters from a single Latin-N charset. nordic | / | d/ -> ð t/ -> þ a/ -> å e/ -> æ o/ -> ø symbols | ^ | r^ -> ® t^ -> ™ others | / | s/ -> ß ?/ -> ¿ !/ -> ¡ // -> ° o/ -> œ + | / | 2/ -> ½ 3/ -> ¾ 4/ -> ?¼ | various | << -> « >> -> » o_ -> º a_ -> ª Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' " nil t nil nil nil nil nil nil nil nil t) -;; Fixme: ¦ § ¨ © ¬ ­ ¯ ± ² ³ ´ µ ¶ · ¸ ¹ ¼ ½ ¾ × ÷ +;; Fixme: ¦ § ¨ © ¬ ­ ¯ ± ² ³ ´ µ ¶ · ¸ ¹ × ÷ (quail-define-rules + ("2/" ?½) + ("3/" ?¾) + ("4/" ?¼) (" _" ? ) ("!/" ?¡) ("//" ?°) @@ -2446,6 +2450,9 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("z." ?ż) ("z~" ?ž) + ("2//" ["2/"]) + ("3//" ["3/"]) + ("4//" ["4/"]) (" __" [" _"]) ("!//" ["!/"]) ("///" ["//"]) commit 2f6f85de34ec54f79a59600f99d39532564f3e3f Author: Robert Pluim Date: Mon Jun 6 18:30:01 2022 +0200 Add more ways to enter trade mark and registered sign * lisp/international/iso-transl.el (iso-transl-char-map): Add sequence for TRADE MARK. * lisp/leim/quail/latin-post.el ("latin-postfix"): Add REGISTERED SIGN and TRADE MARK. * lisp/leim/quail/latin-pre.el ("latin-prefix"): Add TRADE MARK. diff --git a/lisp/international/iso-transl.el b/lisp/international/iso-transl.el index 3be80e5e6a..0d0ff7f138 100644 --- a/lisp/international/iso-transl.el +++ b/lisp/international/iso-transl.el @@ -161,6 +161,8 @@ ("R" . [?®]) ("*S" . [?§]) ("S" . [?§]) + ("*T" . [?™]) + ("T" . [?™]) ("*Y" . [?¥]) ("Y" . [?¥]) ("^0" . [?⁰]) diff --git a/lisp/leim/quail/latin-post.el b/lisp/leim/quail/latin-post.el index acb3ef8ede..49df3fd2d1 100644 --- a/lisp/leim/quail/latin-post.el +++ b/lisp/leim/quail/latin-post.el @@ -2246,13 +2246,14 @@ of characters from a single Latin-N charset. dot | . | z. -> ż stroke | / | d/ -> đ nordic | / | d/ -> ð t/ -> þ a/ -> å e/ -> æ o/ -> ø + symbols | ^ | r^ -> ® t^ -> ™ others | / | s/ -> ß ?/ -> ¿ !/ -> ¡ // -> ° o/ -> œ | various | << -> « >> -> » o_ -> º a_ -> ª Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' " nil t nil nil nil nil nil nil nil nil t) -;; Fixme: ¦ § ¨ © ¬ ­ ® ¯ ± ² ³ ´ µ ¶ · ¸ ¹ ¼ ½ ¾ × ÷ +;; Fixme: ¦ § ¨ © ¬ ­ ¯ ± ² ³ ´ µ ¶ · ¸ ¹ ¼ ½ ¾ × ÷ (quail-define-rules (" _" ? ) ("!/" ?¡) @@ -2417,6 +2418,7 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("o~" ?õ) ("r'" ?ŕ) ("r," ?ŗ) + ("r^" ?®) ("r~" ?ř) ("s'" ?ś) ("s," ?ş) @@ -2426,6 +2428,7 @@ Doubling the postfix separates the letter and postfix: e.g. a\\='\\=' -> a\\=' ("t," ?ţ) ("t/" ?þ) ("t/" ?ŧ) + ("t^" ?™) ("t~" ?ť) ("u'" ?ú) ("u," ?ų) diff --git a/lisp/leim/quail/latin-pre.el b/lisp/leim/quail/latin-pre.el index b6a26e0b2c..868e4d4774 100644 --- a/lisp/leim/quail/latin-pre.el +++ b/lisp/leim/quail/latin-pre.el @@ -1108,7 +1108,7 @@ of characters from a single Latin-N charset. misc | \" ~ / | \"s -> ß ~d -> ð ~t -> þ /a -> å /e -> æ /o -> ø symbol | ~ | ~> -> » ~< -> « ~! -> ¡ ~? -> ¿ ~~ -> ¸ symbol | _ / | _o -> º _a -> ª // -> ° /\\ -> × _y -> ¥ - symbol | ^ | ^r -> ® ^c -> © ^1 -> ¹ ^2 -> ² ^3 -> ³ + symbol | ^ | ^r -> ® ^t -> ™ ^c -> © ^1 -> ¹ ^2 -> ² ^3 -> ³ " nil t nil nil nil nil nil nil nil nil t) (quail-define-rules @@ -1224,6 +1224,7 @@ of characters from a single Latin-N charset. ("^o" ?ô) ("^r" ?®) ("^s" ?ŝ) + ("^t" ?™) ("^u" ?û) ("^w" ?ŵ) ("^y" ?ŷ) commit 0fd60451bc098b57bdcbddfa98cfa210a6b0ab78 Author: Po Lu Date: Wed Jun 8 20:33:42 2022 +0800 Allow running some DND tests interactively * src/xselect.c (x_get_local_selection): Respect new variable. (syms_of_xselect): New variable `x-treat-local-requests-remotely'. * test/lisp/dnd-tests.el (x-begin-drag, gui-set-selection): Don't redefine these functions under X. (dnd-tests-verify-selection-data): Use `x-get-selection-internal' under X. (dnd-tests-extract-selection-data): New function. (dnd-tests-begin-text-drag): Update accordingly. (dnd-tests-begin-file-drag, dnd-tests-begin-drag-files): Temporarily skip these tests under X. diff --git a/src/xselect.c b/src/xselect.c index 40b6571e0a..a234c7188f 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -353,7 +353,10 @@ x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type, if (!NILP (handler_fn)) value = call3 (handler_fn, selection_symbol, - (local_request ? Qnil : target_type), + ((local_request + && NILP (Vx_treat_local_requests_remotely)) + ? Qnil + : target_type), tem); else value = Qnil; @@ -2798,6 +2801,14 @@ A value of 0 means wait as long as necessary. This is initialized from the \"*selectionTimeout\" resource. */); x_selection_timeout = 0; + DEFVAR_LISP ("x-treat-local-requests-remotely", Vx_treat_local_requests_remotely, + doc: /* Whether to treat local selection requests as remote ones. + +If non-nil, selection converters for string types (`STRING', +`UTF8_STRING', `COMPOUND_TEXT', etc) will encode the strings, even +when Emacs itself is converting the selection. */); + Vx_treat_local_requests_remotely = Qnil; + /* QPRIMARY is defined in keyboard.c. */ DEFSYM (QSECONDARY, "SECONDARY"); DEFSYM (QSTRING, "STRING"); diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index 1e5b1f823f..c7e537e53f 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -22,7 +22,9 @@ ;; Tests for stuff in dnd.el that doesn't require a window system. ;; The drag API tests only check the behavior of the simplified drag -;; APIs in dnd.el. Actual drags are not performed. +;; APIs in dnd.el. Actual drags are not performed during the +;; automated testing process (make check), but some of the tests can +;; also be run under X. ;;; Code: @@ -35,51 +37,59 @@ (defvar dnd-tests-selection-table nil "Alist of selection names to their values.") -;; Substitute for x-begin-drag, which isn't present on all systems. -(defalias 'x-begin-drag - (lambda (_targets &optional action frame &rest _) - ;; Verify that frame is either nil or a valid frame. - (when (and frame (not (frame-live-p frame))) - (signal 'wrong-type-argument frame)) - ;; Verify that the action is valid and pretend the drag succeeded - ;; (by returning the action). - (cl-ecase action - ('XdndActionCopy action) - ('XdndActionMove action) - ('XdndActionLink action) - ;; These two are not technically valid, but x-begin-drag accepts - ;; them anyway. - ('XdndActionPrivate action) - ('XdndActionAsk 'XdndActionPrivate)))) +(defvar x-treat-local-requests-remotely) -;; This doesn't work during tests. -(defalias 'gui-set-selection - (lambda (type data) - (or (gui--valid-simple-selection-p data) - (and (vectorp data) - (let ((valid t)) - (dotimes (i (length data)) - (or (gui--valid-simple-selection-p (aref data i)) - (setq valid nil))) - valid)) - (signal 'error (list "invalid selection" data))) - (setf (alist-get type dnd-tests-selection-table) data))) +;; Define some replacements for functions used by the drag-and-drop +;; code on X when running under something else. +(unless (eq window-system 'x) + ;; Substitute for x-begin-drag, which isn't present on all systems. + (defalias 'x-begin-drag + (lambda (_targets &optional action frame &rest _) + ;; Verify that frame is either nil or a valid frame. + (when (and frame (not (frame-live-p frame))) + (signal 'wrong-type-argument frame)) + ;; Verify that the action is valid and pretend the drag succeeded + ;; (by returning the action). + (cl-ecase action + ('XdndActionCopy action) + ('XdndActionMove action) + ('XdndActionLink action) + ;; These two are not technically valid, but x-begin-drag accepts + ;; them anyway. + ('XdndActionPrivate action) + ('XdndActionAsk 'XdndActionPrivate)))) + + ;; This doesn't work during tests. + (defalias 'gui-set-selection + (lambda (type data) + (or (gui--valid-simple-selection-p data) + (and (vectorp data) + (let ((valid t)) + (dotimes (i (length data)) + (or (gui--valid-simple-selection-p (aref data i)) + (setq valid nil))) + valid)) + (signal 'error (list "invalid selection" data))) + (setf (alist-get type dnd-tests-selection-table) data)))) (defun dnd-tests-verify-selection-data (type) "Return the data of the drag-and-drop selection converted to TYPE." - (let* ((basic-value (cdr (assq 'XdndSelection - dnd-tests-selection-table))) - (local-value (if (stringp basic-value) - (or (get-text-property 0 type basic-value) - basic-value) - basic-value)) - (converter-list (cdr (assq type selection-converter-alist))) - (converter (if (consp converter-list) - (cdr converter-list) - converter-list))) - (if (and local-value converter) - (funcall converter 'XdndSelection type local-value) - (error "No selection converter or local value: %s" type)))) + (if (eq window-system 'x) + (let ((x-treat-local-requests-remotely t)) + (x-get-selection-internal 'XdndSelection type)) + (let* ((basic-value (cdr (assq 'XdndSelection + dnd-tests-selection-table))) + (local-value (if (stringp basic-value) + (or (get-text-property 0 type basic-value) + basic-value) + basic-value)) + (converter-list (cdr (assq type selection-converter-alist))) + (converter (if (consp converter-list) + (cdr converter-list) + converter-list))) + (if (and local-value converter) + (funcall converter 'XdndSelection type local-value) + (error "No selection converter or local value: %s" type))))) (defun dnd-tests-remote-accessible-p () "Return if a test involving remote files can proceed." @@ -119,7 +129,26 @@ Return a list of its hostname, real path, and local path." (+ beg 1 (string-to-number (match-string 5 netfile))))))))) +(defun dnd-tests-extract-selection-data (selection expect-cons) + "Return the selection data in SELECTION. +SELECTION can either be the value of `gui-get-selection', or the +return value of a selection converter. + +If EXPECT-CONS, then expect SELECTION to be a cons (when not +running under X). + +This function only tries to handle strings." + (when (and expect-cons (not (eq window-system 'x))) + (should (and (consp selection) + (stringp (cdr selection))))) + (if (stringp selection) + selection + (cdr selection))) + (ert-deftest dnd-tests-begin-text-drag () + ;; When running this test under X, please make sure to drop onto a + ;; program with reasonably correct behavior, such as dtpad, gedit, + ;; or Mozilla. ;; ASCII Latin-1 UTF-8 (let ((test-text "hello, everyone! sæl öllsömul! всем привет")) ;; Verify that dragging works. @@ -128,26 +157,29 @@ Return a list of its hostname, real path, and local path." ;; Verify that the important data types are converted correctly. (let ((string-data (dnd-tests-verify-selection-data 'STRING))) ;; Check that the Latin-1 target is converted correctly. - (should (equal (cdr string-data) + (should (equal (dnd-tests-extract-selection-data string-data t) (encode-coding-string test-text 'iso-8859-1)))) ;; And that UTF8_STRING and the Xdnd UTF8 string are as well. - (let ((string-data (dnd-tests-verify-selection-data - 'UTF8_STRING)) - (string-data-1 (cdr (dnd-tests-verify-selection-data - 'text/plain\;charset=utf-8)))) - (should (and (stringp (cdr string-data)) - (stringp string-data-1))) - (should (equal (cdr string-data) string-data-1))) + (let* ((string-data (dnd-tests-verify-selection-data + 'UTF8_STRING)) + (string-data-1 (dnd-tests-verify-selection-data + 'text/plain\;charset=utf-8)) + (extracted-1 (dnd-tests-extract-selection-data string-data-1 t)) + (extracted (dnd-tests-extract-selection-data string-data t))) + (should (and (stringp extracted) (stringp extracted-1))) + (should (equal extracted extracted))) ;; Now check text/plain. (let ((string-data (dnd-tests-verify-selection-data 'text/plain))) - (should (equal (cdr string-data) + (should (equal (dnd-tests-extract-selection-data string-data t) (encode-coding-string test-text 'ascii)))))) (ert-deftest dnd-tests-begin-file-drag () ;; These tests also involve handling remote file names. - (skip-unless (dnd-tests-remote-accessible-p)) + (skip-unless (and (dnd-tests-remote-accessible-p) + ;; TODO: make these tests work under X. + (not (eq window-system 'x)))) (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test") temporary-file-directory)) (remote-temp-file (dnd-tests-make-temp-name))) @@ -210,7 +242,9 @@ Return a list of its hostname, real path, and local path." (delete-file remote-temp-file)))) (ert-deftest dnd-tests-begin-drag-files () - (skip-unless (dnd-tests-remote-accessible-p)) + (skip-unless (and (dnd-tests-remote-accessible-p) + ;; TODO: make these tests work under X. + (not (eq window-system 'x)))) (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test") temporary-file-directory)) (normal-temp-file-1 (expand-file-name (make-temp-name "dnd-test") commit efe9940567da259d871432cfda4cdf94542ac98e Author: Lars Ingebrigtsen Date: Wed Jun 8 14:27:14 2022 +0200 Revert "Give ,@ a prefix syntax in elisp-mode" This reverts commit d003848b5e3ad2dfbe84cc62b99776fdc6734325. This leads to hangs in edebug-tests. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 210270bc67..77bf3f1ed1 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -245,9 +245,6 @@ Comments in the form will be lost." ;; Empty symbol. ("##" (0 (unless (nth 8 (syntax-ppss)) (string-to-syntax "_")))) - ;; Give ,@ a prefix syntax. - (",@" (0 (unless (ppss-comment-or-string-start (syntax-ppss)) - (string-to-syntax "'")))) ;; Unicode character names. (The longest name is 88 characters ;; long.) ("\\?\\\\N{[-A-Za-z0-9 ]\\{,100\\}}" commit a8e5e3ce5d7929fa92251359c13da959c3f22771 Author: Jim Porter Date: Mon Jun 6 19:53:39 2022 -0700 Don't split Eshell expansions by line when using split-subscript operator * lisp/eshell/esh-var.el (eshell-apply-indices): Use 'eshell-convert-to-number' instead of 'eshell-convert'. * test/lisp/eshell/esh-var-tests.el (esh-var-test/interp-convert-var-split-indices): Expand test (bug#55838). diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index 186f6358bc..27be6e1b1a 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -582,10 +582,11 @@ Otherwise, each INT-OR-NAME refers to an element of the list value. Integers imply a direct index, and names, an associate lookup using `assoc'. -If QUOTED is non-nil, this was invoked inside double-quotes. This -affects the behavior of splitting strings: without quoting, the -split values are converted to Lisp forms via `eshell-convert'; with -quoting, they're left as strings. +If QUOTED is non-nil, this was invoked inside double-quotes. +This affects the behavior of splitting strings: without quoting, +the split values are converted to numbers via +`eshell-convert-to-number' if possible; with quoting, they're +left as strings. For example, to retrieve the second element of a user's record in '/etc/passwd', the variable reference would look like: @@ -599,9 +600,9 @@ For example, to retrieve the second element of a user's record in (not (get-text-property 0 'number index))) (setq separator index refs (cdr refs))) - (setq value - (mapcar (lambda (i) (eshell-convert i quoted)) - (split-string value separator))))) + (setq value (split-string value separator)) + (unless quoted + (setq value (mapcar #'eshell-convert-to-number value))))) (cond ((< (length refs) 0) (error "Invalid array variable index: %s" diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index 4e2a18861e..072cdb9b40 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el @@ -357,11 +357,18 @@ inside double-quotes" (ert-deftest esh-var-test/interp-convert-var-split-indices () "Interpolate and convert string variable with indices" + ;; Check that numeric forms are converted to numbers. (let ((eshell-test-value "000 010 020 030 040")) (should (equal (eshell-test-command-result "echo $eshell-test-value[0]") 0)) (should (equal (eshell-test-command-result "echo $eshell-test-value[0 2]") - '(0 20))))) + '(0 20)))) + ;; Check that multiline forms are preserved as-is. + (let ((eshell-test-value "foo\nbar:baz\n")) + (should (equal (eshell-test-command-result "echo $eshell-test-value[: 0]") + "foo\nbar")) + (should (equal (eshell-test-command-result "echo $eshell-test-value[: 1]") + "baz\n")))) (ert-deftest esh-var-test/interp-convert-quoted-var-number () "Interpolate numeric quoted numeric variable" commit 33c9572cfeb37edb624eb0d1822df80469cdde3b Author: Nicholas Vollmer Date: Wed Jun 8 14:10:04 2022 +0200 * doc/man/emacs.1.in: Add --init-directory. * doc/man/emacs.1.in: Document --init-directory (bug#55839). diff --git a/doc/man/emacs.1.in b/doc/man/emacs.1.in index 9fdf65e0ff..7b2b553979 100644 --- a/doc/man/emacs.1.in +++ b/doc/man/emacs.1.in @@ -1,5 +1,5 @@ .\" See section COPYING for copyright and redistribution information. -.TH EMACS 1 "2021-09-28" "GNU Emacs @version@" "GNU" +.TH EMACS 1 "2022-06-07" "GNU Emacs @version@" "GNU" . . .SH NAME @@ -117,6 +117,10 @@ Load .IR user 's init file. .TP +.BI \-\-init\-directory= "directory" +Start emacs with user-emacs-directory set to +.IR directory . +.TP .BI \-t " file\fR,\fP " \-\-terminal= "file" Use specified .I file commit b8e0f2e827744da8dc0454c4220c5c9de2ecd368 Author: Po Lu Date: Wed Jun 8 20:04:26 2022 +0800 Simplify XDND toplevel freeing code * src/xterm.c (x_free_dnd_toplevels): New function. (x_dnd_cleanup_drag_and_drop, x_dnd_begin_drag_and_drop): Record an unwind function to free DND toplevels instead of doing that manually everywhere. diff --git a/src/xterm.c b/src/xterm.c index 1f4d301e6a..00586d66a0 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4163,6 +4163,18 @@ x_free_dnd_targets (void) x_dnd_n_targets = 0; } +static void +x_free_dnd_toplevels (void) +{ + if (!x_dnd_use_toplevels || !x_dnd_toplevels) + return; + + /* If the display is deleted, x_dnd_toplevels will already be + NULL, so we can always assume the display is alive here. */ + + x_dnd_free_toplevels (true); +} + static void x_dnd_cleanup_drag_and_drop (void *frame) { @@ -4216,9 +4228,6 @@ x_dnd_cleanup_drag_and_drop (void *frame) x_dnd_waiting_for_finish = false; - if (x_dnd_use_toplevels) - x_dnd_free_toplevels (true); - FRAME_DISPLAY_INFO (f)->grabbed = 0; #ifdef USE_GTK current_hold_quit = NULL; @@ -10960,6 +10969,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_free_toplevels (true); x_dnd_use_toplevels = false; } + else + record_unwind_protect_void (x_free_dnd_toplevels); } if (!NILP (return_frame)) @@ -11132,10 +11143,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, } x_dnd_waiting_for_finish = false; - - if (x_dnd_use_toplevels) - x_dnd_free_toplevels (true); - x_dnd_return_frame_object = NULL; x_dnd_movement_frame = NULL; @@ -11223,10 +11230,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, } x_dnd_waiting_for_finish = false; - - if (x_dnd_use_toplevels) - x_dnd_free_toplevels (true); - x_dnd_return_frame_object = NULL; x_dnd_movement_frame = NULL; @@ -11287,9 +11290,6 @@ 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)) { commit 496e191fc73441a0bee67c04010fed7c7965e25c Author: Manuel Giraud Date: Wed Jun 8 13:51:41 2022 +0200 Fix last-modified meaning in bookmark.el * lisp/bookmark.el (bookmark-update-last-modified): New function to update the last-modified field. (bookmark-send-edited-annotation, bookmark-relocate) (bookmark-rename): Use `bookmark-update-last-modified' in annotations editing, relocation and renaming. diff --git a/lisp/bookmark.el b/lisp/bookmark.el index 849303fac7..b0b54e52d8 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -120,7 +120,7 @@ nil means they will be displayed in LIFO order (that is, most recently created ones come first, oldest ones come last). `last-modified' means that bookmarks will be displayed sorted -from most recently set to least recently set. +from most recently modified to least recently modified. Other values means that bookmarks will be displayed sorted by bookmark name." @@ -468,10 +468,17 @@ In other words, return all information but the name." "Return the handler function for BOOKMARK-NAME-OR-RECORD, or nil if none." (bookmark-prop-get bookmark-name-or-record 'handler)) + (defun bookmark-get-last-modified (bookmark-name-or-record) "Return the last-modified for BOOKMARK-NAME-OR-RECORD, or nil if none." (bookmark-prop-get bookmark-name-or-record 'last-modified)) + +(defun bookmark-update-last-modified (bookmark-name-or-record) + "Update the last-modified date of BOOKMARK-NAME-OR-RECORD to the current time." + (bookmark-prop-set bookmark-name-or-record 'last-modified (current-time))) + + (defvar bookmark-history nil "The history list for bookmark functions.") @@ -1069,6 +1076,7 @@ Lines beginning with `#' are ignored." (from-bookmark-list bookmark--annotation-from-bookmark-list) (old-buffer (current-buffer))) (bookmark-set-annotation bookmark-name annotation) + (bookmark-update-last-modified bookmark-name) (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count)) (message "Annotation updated for \"%s\"" bookmark-name) @@ -1355,6 +1363,7 @@ after a bookmark was set in it." (format "Relocate %s to: " bookmark-name) (file-name-directory bmrk-filename)))))) (bookmark-set-filename bookmark-name newloc) + (bookmark-update-last-modified bookmark-name) (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count)) (if (bookmark-time-to-save-p) @@ -1417,6 +1426,7 @@ name." nil 'bookmark-history)))) (bookmark-set-name old-name final-new-name) + (bookmark-update-last-modified final-new-name) (setq bookmark-current-bookmark final-new-name) (bookmark-bmenu-surreptitiously-rebuild-list) (setq bookmark-alist-modification-count commit c8532a0acf1fce4a84053c5c3ed6f114dff6bb69 Author: Lars Ingebrigtsen Date: Wed Jun 8 13:48:48 2022 +0200 icomplete-in-buffer doc fix * lisp/icomplete.el (icomplete-in-buffer): dabbrev now uses icomplete-in-buffer (bug#45764). diff --git a/lisp/icomplete.el b/lisp/icomplete.el index a0f105a628..8802e7565f 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -141,7 +141,7 @@ See `icomplete-delay-completions-threshold'." (defvar icomplete-in-buffer nil "If non-nil, also use Icomplete when completing in non-mini buffers. This affects commands like `complete-in-region', but not commands -like `dabbrev-completion', which uses its own completion setup.") +that use their own completions setup.") (defcustom icomplete-minibuffer-setup-hook nil "Icomplete-specific customization of minibuffer setup. commit 9a4862a9738c2abab8fb4fb2e4e57b69dea679d7 Author: Stefan Kangas Date: Wed Jun 8 13:16:32 2022 +0200 * doc/misc/org.org: Remove spurious markup. diff --git a/doc/misc/org.org b/doc/misc/org.org index 3dce83c936..baab2efeda 100644 --- a/doc/misc/org.org +++ b/doc/misc/org.org @@ -12442,7 +12442,7 @@ should in principle be exportable as a Beamer presentation. When =ignoreheading= is set, Org export ignores the entry's headline but not its content. This is useful for inserting content between frames. It is also useful for properly closing a =column= - environment. @end itemize + environment. #+cindex: @samp{BEAMER_ACT}, property #+cindex: @samp{BEAMER_OPT}, property commit 768ed1476ae849777457b1eb666a2b0db9eb7374 Author: Michael Albinus Date: Wed Jun 8 12:42:10 2022 +0200 Make Tramp version check more robust * lisp/net/trampver.el (tramp-repository-branch) (tramp-repository-version): Check for "git" executable. diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el index 9c04abc828..5863beb295 100644 --- a/lisp/net/trampver.el +++ b/lisp/net/trampver.el @@ -58,6 +58,7 @@ ;; `emacs-repository-get-branch' has been introduced with Emacs 27.1. (with-no-warnings (and (stringp dir) (file-directory-p dir) + (executable-find "git") (emacs-repository-get-branch dir))))) "The repository branch of the Tramp sources.") @@ -70,6 +71,7 @@ (dir (or (locate-dominating-file (locate-library "tramp") ".git") source-directory))) (and (stringp dir) (file-directory-p dir) + (executable-find "git") (emacs-repository-get-version dir)))) "The repository revision of the Tramp sources.") commit b2ed8a547ace1dade2823d28b60c21d3634d68b2 Author: Michael Albinus Date: Wed Jun 8 12:06:56 2022 +0200 Factor out test configuration for remote files * lisp/emacs-lisp/ert-x.el (tramp-methods) (tramp-default-host-alist): Declare. (ert-remote-temporary-file-directory): New defconst. * test/README: Mention dnd-tests.el. * test/lisp/autorevert-tests.el (auto-revert-test-remote-temporary-file-directory): Remove. Replace all uses by `ert-remote-temporary-file-directory'. * test/lisp/dnd-tests.el (ert-x): Require. (dnd-tests-temporary-file-directory): Remove. Replace all uses by `ert-remote-temporary-file-directory'. * test/lisp/filenotify-tests.el (file-notify-test-remote-temporary-file-directory): Remove. Replace all uses by `ert-remote-temporary-file-directory'. * test/lisp/shadowfile-tests.el (ert-x): Require. (shadow-test-remote-temporary-file-directory): Remove. Replace all uses by `ert-remote-temporary-file-directory'. * test/lisp/net/tramp-tests.el: Don't require ert. (ert-remote-temporary-file-directory): Define if it doesn't exist. (tramp-test-temporary-file-directory): Remove. Replace all uses by `ert-remote-temporary-file-directory'. diff --git a/lisp/emacs-lisp/ert-x.el b/lisp/emacs-lisp/ert-x.el index 0180e9e53c..de18adff5b 100644 --- a/lisp/emacs-lisp/ert-x.el +++ b/lisp/emacs-lisp/ert-x.el @@ -491,6 +491,36 @@ The same keyword arguments are supported as in (string-match "Apple \\(LLVM\\|[Cc]lang\\)\\|Xcode\\.app" (shell-command-to-string "gcc --version"))) + +(defvar tramp-methods) +(defvar tramp-default-host-alist) + +;; If this defconst is used in a test file, `tramp' shall be loaded +;; prior `ert-x'. There is no default value on w32 systems, which +;; could work out of the box. +(defconst ert-remote-temporary-file-directory + (when (featurep 'tramp) + (cond + ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) + ((eq system-type 'windows-nt) null-device) + (t (add-to-list + 'tramp-methods + '("mock" + (tramp-login-program "sh") + (tramp-login-args (("-i"))) + (tramp-remote-shell "/bin/sh") + (tramp-remote-shell-args ("-c")) + (tramp-connection-timeout 10))) + (add-to-list + 'tramp-default-host-alist + `("\\`mock\\'" nil ,(system-name))) + ;; Emacs's Makefile sets $HOME to a nonexistent value. Needed + ;; in batch mode only, therefore. + (unless (and (null noninteractive) (file-directory-p "~/")) + (setenv "HOME" temporary-file-directory)) + (format "/mock::%s" temporary-file-directory)))) + "Temporary directory for remote file tests.") + (provide 'ert-x) ;;; ert-x.el ends here diff --git a/test/README b/test/README index 3d865de78b..17783a4bac 100644 --- a/test/README +++ b/test/README @@ -118,11 +118,12 @@ If the $EMACS_TEST_JUNIT_REPORT environment variable is set to a file name, a JUnit test report is generated under this name. Some of the tests require a remote temporary directory -(autorevert-tests.el, filenotify-tests.el, shadowfile-tests.el and -tramp-tests.el). Per default, a mock-up connection method is used -(this might not be possible when running on MS Windows). If you want -to test a real remote connection, set $REMOTE_TEMPORARY_FILE_DIRECTORY -to a suitable value in order to overwrite the default value: +(autorevert-tests.el, dnd-tests.el, filenotify-tests.el, +shadowfile-tests.el and tramp-tests.el). Per default, a mock-up +connection method is used (this might not be possible when running on +MS Windows). If you want to test a real remote connection, set +$REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to +overwrite the default value: env REMOTE_TEMPORARY_FILE_DIRECTORY=/ssh:host:/tmp make ... diff --git a/test/lisp/autorevert-tests.el b/test/lisp/autorevert-tests.el index d26e0f5a15..54b1a16b5d 100644 --- a/test/lisp/autorevert-tests.el +++ b/test/lisp/autorevert-tests.el @@ -52,10 +52,9 @@ ;;; Code: -(require 'ert) +(require 'tramp) (require 'ert-x) (require 'autorevert) -(require 'tramp) (setq auto-revert-debug nil auto-revert-notify-exclude-dir-regexp "nothing-to-be-excluded" @@ -70,30 +69,6 @@ (defvar auto-revert--messages nil "Used to collect messages issued during a section of a test.") -;; There is no default value on w32 systems, which could work out of the box. -(defconst auto-revert-test-remote-temporary-file-directory - (cond - ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) - ((eq system-type 'windows-nt) null-device) - (t (add-to-list - 'tramp-methods - '("mock" - (tramp-login-program "sh") - (tramp-login-args (("-i"))) - (tramp-remote-shell "/bin/sh") - (tramp-remote-shell-args ("-c")) - (tramp-connection-timeout 10))) - (add-to-list - 'tramp-default-host-alist - `("\\`mock\\'" nil ,(system-name))) - ;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in - ;; batch mode only, therefore. `temporary-file-directory' might - ;; be quoted, so we unquote it just in case. - (unless (and (null noninteractive) (file-directory-p "~/")) - (setenv "HOME" (file-name-unquote temporary-file-directory))) - (format "/mock::%s" temporary-file-directory))) - "Temporary directory for Tramp tests.") - ;; Filter suppressed remote file-notify libraries. (when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY")) (dolist (lib '("inotifywait" "gio-monitor" "gvfs-monitor-dir")) @@ -114,10 +89,9 @@ being the result.") t (ignore-errors (and (not (getenv "EMACS_HYDRA_CI")) - (file-remote-p auto-revert-test-remote-temporary-file-directory) - (file-directory-p auto-revert-test-remote-temporary-file-directory) - (file-writable-p - auto-revert-test-remote-temporary-file-directory)))))) + (file-remote-p ert-remote-temporary-file-directory) + (file-directory-p ert-remote-temporary-file-directory) + (file-writable-p ert-remote-temporary-file-directory)))))) ;; Return result. (cdr auto-revert--test-enabled-remote-checked)) @@ -146,7 +120,7 @@ This expects `auto-revert--messages' to be bound by ,docstring :tags '(:expensive-test :unstable) (let ((temporary-file-directory - auto-revert-test-remote-temporary-file-directory) + ert-remote-temporary-file-directory) (auto-revert-remote-files t) (ert-test (ert-get-test ',test)) vc-handled-backends) diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index 7a12cb8347..1e5b1f823f 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -30,30 +30,7 @@ (require 'cl-lib) (require 'tramp) (require 'select) - -;; This code was taken from tramp-tests.el: perhaps some of it isn't -;; strictly necessary. -(defconst dnd-tests-temporary-file-directory - (cond - ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) - ((eq system-type 'windows-nt) null-device) - (t (add-to-list - 'tramp-methods - '("mock" - (tramp-login-program "sh") - (tramp-login-args (("-i"))) - (tramp-remote-shell "/bin/sh") - (tramp-remote-shell-args ("-c")) - (tramp-connection-timeout 10))) - (add-to-list - 'tramp-default-host-alist - `("\\`mock\\'" nil ,(system-name))) - ;; Emacs's Makefile sets $HOME to a nonexistent value. Needed - ;; in batch mode only, therefore. - (unless (and (null noninteractive) (file-directory-p "~/")) - (setenv "HOME" temporary-file-directory)) - (format "/mock::%s" temporary-file-directory))) - "Temporary directory for drag-and-drop tests involving remote files.") +(require 'ert-x) (defvar dnd-tests-selection-table nil "Alist of selection names to their values.") @@ -108,15 +85,15 @@ "Return if a test involving remote files can proceed." (ignore-errors (and - (file-remote-p dnd-tests-temporary-file-directory) - (file-directory-p dnd-tests-temporary-file-directory) - (file-writable-p dnd-tests-temporary-file-directory)))) + (file-remote-p ert-remote-temporary-file-directory) + (file-directory-p ert-remote-temporary-file-directory) + (file-writable-p ert-remote-temporary-file-directory)))) (defun dnd-tests-make-temp-name () "Return a temporary remote file name for test. The temporary file is not created." (expand-file-name (make-temp-name "dnd-test-remote") - dnd-tests-temporary-file-directory)) + ert-remote-temporary-file-directory)) (defun dnd-tests-parse-tt-netfile (netfile) "Parse NETFILE and return its components. diff --git a/test/lisp/filenotify-tests.el b/test/lisp/filenotify-tests.el index 13bb2cd345..ad0138b2e7 100644 --- a/test/lisp/filenotify-tests.el +++ b/test/lisp/filenotify-tests.el @@ -52,34 +52,9 @@ ;;; Code: -(require 'ert) +(require 'tramp) (require 'ert-x) (require 'filenotify) -(require 'tramp) - -;; There is no default value on w32 systems, which could work out of the box. -(defconst file-notify-test-remote-temporary-file-directory - (cond - ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) - ((eq system-type 'windows-nt) null-device) - (t (add-to-list - 'tramp-methods - '("mock" - (tramp-login-program "sh") - (tramp-login-args (("-i"))) - (tramp-remote-shell "/bin/sh") - (tramp-remote-shell-args ("-c")) - (tramp-connection-timeout 10))) - (add-to-list - 'tramp-default-host-alist - `("\\`mock\\'" nil ,(system-name))) - ;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in - ;; batch mode only, therefore. `temporary-file-directory' might - ;; be quoted, so we unquote it just in case. - (unless (and (null noninteractive) (file-directory-p "~/")) - (setenv "HOME" (file-name-unquote temporary-file-directory))) - (format "/mock::%s" temporary-file-directory))) - "Temporary directory for Tramp tests.") ;; Filter suppressed remote file-notify libraries. (when (stringp (getenv "REMOTE_FILE_NOTIFY_LIBRARY")) @@ -232,12 +207,12 @@ being the result.") (let (desc) (ignore-errors (and - (file-remote-p file-notify-test-remote-temporary-file-directory) - (file-directory-p file-notify-test-remote-temporary-file-directory) - (file-writable-p file-notify-test-remote-temporary-file-directory) + (file-remote-p ert-remote-temporary-file-directory) + (file-directory-p ert-remote-temporary-file-directory) + (file-writable-p ert-remote-temporary-file-directory) (setq desc (file-notify-add-watch - file-notify-test-remote-temporary-file-directory + ert-remote-temporary-file-directory '(change) #'ignore)))) (setq file-notify--test-remote-enabled-checked (cons t desc)) (when desc (file-notify-rm-watch desc)))) @@ -297,8 +272,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." `(ert-deftest ,(intern (concat (symbol-name test) "-remote")) () ,docstring :tags (if ,unstable '(:expensive-test :unstable) '(:expensive-test)) - (let* ((temporary-file-directory - file-notify-test-remote-temporary-file-directory) + (let* ((temporary-file-directory ert-remote-temporary-file-directory) (ert-test (ert-get-test ',test)) vc-handled-backends) (skip-unless (file-notify--test-remote-enabled)) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 621b6ba1c2..87c8eb0ada 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -44,12 +44,11 @@ (require 'cl-lib) (require 'dired) (require 'dired-aux) -(require 'ert) +(require 'tramp) (require 'ert-x) (require 'seq) ; For `seq-random-elt', autoloaded since Emacs 28.1 (require 'tar-mode) (require 'trace) -(require 'tramp) (require 'vc) (require 'vc-bzr) (require 'vc-git) @@ -128,6 +127,33 @@ A resource file is in the resource directory as per `ert-resource-directory'." `(expand-file-name ,file (ert-resource-directory))))) +;; `ert-remote-temporary-file-directory' was introduced in Emacs 29.1. +(unless (boundp 'ert-remote-temporary-file-directory) + (eval-and-compile + ;; There is no default value on w32 systems, which could work out + ;; of the box. + (defconst ert-remote-temporary-file-directory + (cond + ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) + ((eq system-type 'windows-nt) null-device) + (t (add-to-list + 'tramp-methods + '("mock" + (tramp-login-program "sh") + (tramp-login-args (("-i"))) + (tramp-remote-shell "/bin/sh") + (tramp-remote-shell-args ("-c")) + (tramp-connection-timeout 10))) + (add-to-list + 'tramp-default-host-alist + `("\\`mock\\'" nil ,(system-name))) + ;; Emacs's Makefile sets $HOME to a nonexistent value. + ;; Needed in batch mode only, therefore. + (unless (and (null noninteractive) (file-directory-p "~/")) + (setenv "HOME" temporary-file-directory)) + (format "/mock::%s" temporary-file-directory))) + "Temporary directory for remote file tests."))) + ;; Beautify batch mode. (when noninteractive ;; Suppress nasty messages. @@ -137,32 +163,9 @@ A resource file is in the resource directory as per '(fset 'tramp-gvfs-handler-askquestion (lambda (_message _choices) '(t nil 0))))) -;; There is no default value on w32 systems, which could work out of the box. -(defconst tramp-test-temporary-file-directory - (cond - ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) - ((eq system-type 'windows-nt) null-device) - (t (add-to-list - 'tramp-methods - '("mock" - (tramp-login-program "sh") - (tramp-login-args (("-i"))) - (tramp-remote-shell "/bin/sh") - (tramp-remote-shell-args ("-c")) - (tramp-connection-timeout 10))) - (add-to-list - 'tramp-default-host-alist - `("\\`mock\\'" nil ,(system-name))) - ;; Emacs's Makefile sets $HOME to a nonexistent value. Needed - ;; in batch mode only, therefore. - (unless (and (null noninteractive) (file-directory-p "~/")) - (setenv "HOME" temporary-file-directory)) - (format "/mock::%s" temporary-file-directory))) - "Temporary directory for Tramp tests.") - (defconst tramp-test-vec - (and (file-remote-p tramp-test-temporary-file-directory) - (tramp-dissect-file-name tramp-test-temporary-file-directory)) + (and (file-remote-p ert-remote-temporary-file-directory) + (tramp-dissect-file-name ert-remote-temporary-file-directory)) "The used `tramp-file-name' structure.") (setq auth-source-save-behavior nil @@ -192,9 +195,9 @@ being the result.") (cons t (ignore-errors (and - (file-remote-p tramp-test-temporary-file-directory) - (file-directory-p tramp-test-temporary-file-directory) - (file-writable-p tramp-test-temporary-file-directory)))))) + (file-remote-p ert-remote-temporary-file-directory) + (file-directory-p ert-remote-temporary-file-directory) + (file-writable-p ert-remote-temporary-file-directory)))))) (when (cdr tramp--test-enabled-checked) ;; Cleanup connection. @@ -213,7 +216,7 @@ The temporary file is not created." (if quoted #'tramp-compat-file-name-quote #'identity) (expand-file-name (make-temp-name "tramp-test") - (if local temporary-file-directory tramp-test-temporary-file-directory)))) + (if local temporary-file-directory ert-remote-temporary-file-directory)))) ;; Method "smb" supports `make-symbolic-link' only if the remote host ;; has CIFS capabilities. tramp-adb.el, tramp-gvfs.el, tramp-rclone.el @@ -295,12 +298,12 @@ Also see `ignore'." "Test availability of Tramp functions." :expected-result (if (tramp--test-enabled) :passed :failed) (tramp--test-message - "Remote directory: `%s'" tramp-test-temporary-file-directory) + "Remote directory: `%s'" ert-remote-temporary-file-directory) (should (ignore-errors (and - (file-remote-p tramp-test-temporary-file-directory) - (file-directory-p tramp-test-temporary-file-directory) - (file-writable-p tramp-test-temporary-file-directory))))) + (file-remote-p ert-remote-temporary-file-directory) + (file-directory-p ert-remote-temporary-file-directory) + (file-writable-p ert-remote-temporary-file-directory))))) (ert-deftest tramp-test01-file-name-syntax () "Check remote file name syntax." @@ -1997,7 +2000,7 @@ Also see `ignore'." (find-file (format "%s|%s:foo:" - (substring (file-remote-p tramp-test-temporary-file-directory) 0 -1) + (substring (file-remote-p ert-remote-temporary-file-directory) 0 -1) m)) :type 'user-error)))) @@ -2022,7 +2025,7 @@ Also see `ignore'." (should-error (tramp-smb-get-localname (tramp-dissect-file-name - (expand-file-name file tramp-test-temporary-file-directory))) + (expand-file-name file ert-remote-temporary-file-directory))) :type 'file-error)))) (ert-deftest tramp-test04-substitute-in-file-name () @@ -2178,16 +2181,16 @@ Also see `ignore'." (string-equal (let ((default-directory (concat - (file-remote-p tramp-test-temporary-file-directory) "/path"))) + (file-remote-p ert-remote-temporary-file-directory) "/path"))) (expand-file-name ".." "./")) - (concat (file-remote-p tramp-test-temporary-file-directory) "/")))) + (concat (file-remote-p ert-remote-temporary-file-directory) "/")))) (ert-deftest tramp-test05-expand-file-name-top () "Check `expand-file-name'." (skip-unless (tramp--test-enabled)) (skip-unless (not (tramp--test-ange-ftp-p))) - (let ((dir (concat (file-remote-p tramp-test-temporary-file-directory) "/"))) + (let ((dir (concat (file-remote-p ert-remote-temporary-file-directory) "/"))) (dolist (local '("." "..")) (should (string-equal (expand-file-name local dir) dir)) (should (string-equal (expand-file-name (concat dir local)) dir))))) @@ -2250,8 +2253,8 @@ This checks also `file-name-as-directory', `file-name-directory', ;; We must clear `tramp-default-method'. On hydra, it is "ftp", ;; which ruins the tests. (let ((tramp-default-method - (file-remote-p tramp-test-temporary-file-directory 'method)) - (host (file-remote-p tramp-test-temporary-file-directory 'host))) + (file-remote-p ert-remote-temporary-file-directory 'method)) + (host (file-remote-p ert-remote-temporary-file-directory 'host))) (dolist (file `(,(format "/%s::" tramp-default-method) @@ -2278,8 +2281,8 @@ This checks also `file-name-as-directory', `file-name-directory', (skip-unless (tramp--test-emacs29-p)) ;; We must refill the cache. `file-truename' does it. - (file-truename tramp-test-temporary-file-directory) - (let* ((remote-host (file-remote-p tramp-test-temporary-file-directory)) + (file-truename ert-remote-temporary-file-directory) + (let* ((remote-host (file-remote-p ert-remote-temporary-file-directory)) (remote-host-nohop (tramp-make-tramp-file-name (tramp-dissect-file-name remote-host))) ;; Not all methods can expand "~". @@ -2368,7 +2371,7 @@ This checks also `file-name-as-directory', `file-name-directory', (insert-file-contents tmp-name2) (should (string-equal (buffer-string) "foo"))) ;; Check also that a file transfer with compression works. - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) (tramp-copy-size-limit 4) (tramp-inline-compress-start-size 2)) (delete-file tmp-name2) @@ -2568,7 +2571,7 @@ This checks also `file-name-as-directory', `file-name-directory', ;; The function was introduced in Emacs 28.1. (skip-unless (boundp 'tar-goto-file)) - (let* ((default-directory tramp-test-temporary-file-directory) + (let* ((default-directory ert-remote-temporary-file-directory) (archive (ert-resource-file "foo.tar.gz")) (tmp-file (expand-file-name (file-name-nondirectory archive))) (require-final-newline t) @@ -3258,7 +3261,7 @@ This tests also `file-directory-p' and `file-accessible-directory-p'." (ert-deftest tramp-test17-dired-with-wildcards () "Check `dired' with wildcards." ;; `separate' syntax and IPv6 host name syntax do not work. - (skip-unless (not (string-match-p "\\[" tramp-test-temporary-file-directory))) + (skip-unless (not (string-match-p "\\[" ert-remote-temporary-file-directory))) (skip-unless (tramp--test-enabled)) (skip-unless (tramp--test-sh-p)) (skip-unless (not (tramp--test-rsync-p))) @@ -3272,10 +3275,10 @@ This tests also `file-directory-p' and `file-accessible-directory-p'." (expand-file-name (tramp--test-make-temp-name nil quoted))) (tmp-name3 (expand-file-name "foo" tmp-name1)) (tmp-name4 (expand-file-name "bar" tmp-name2)) - (tramp-test-temporary-file-directory + (ert-remote-temporary-file-directory (funcall (if quoted #'tramp-compat-file-name-quote #'identity) - tramp-test-temporary-file-directory)) + ert-remote-temporary-file-directory)) buffer) (unwind-protect (progn @@ -3293,19 +3296,19 @@ This tests also `file-directory-p' and `file-accessible-directory-p'." (setq buffer (dired-noselect (expand-file-name - "tramp-test*" tramp-test-temporary-file-directory))) + "tramp-test*" ert-remote-temporary-file-directory))) (goto-char (point-min)) (should (re-search-forward (regexp-quote (file-relative-name - tmp-name1 tramp-test-temporary-file-directory)))) + tmp-name1 ert-remote-temporary-file-directory)))) (goto-char (point-min)) (should (re-search-forward (regexp-quote (file-relative-name - tmp-name2 tramp-test-temporary-file-directory))))) + tmp-name2 ert-remote-temporary-file-directory))))) (kill-buffer buffer) ;; Check for expanded directory and file names. @@ -3313,20 +3316,20 @@ This tests also `file-directory-p' and `file-accessible-directory-p'." (setq buffer (dired-noselect (expand-file-name - "tramp-test*/*" tramp-test-temporary-file-directory))) + "tramp-test*/*" ert-remote-temporary-file-directory))) (goto-char (point-min)) (should (re-search-forward (regexp-quote (file-relative-name - tmp-name3 tramp-test-temporary-file-directory)))) + tmp-name3 ert-remote-temporary-file-directory)))) (goto-char (point-min)) (should (re-search-forward (regexp-quote (file-relative-name tmp-name4 - tramp-test-temporary-file-directory))))) + ert-remote-temporary-file-directory))))) (kill-buffer buffer) ;; Check for special characters. @@ -3341,20 +3344,20 @@ This tests also `file-directory-p' and `file-accessible-directory-p'." (setq buffer (dired-noselect (expand-file-name - "tramp-test*/*" tramp-test-temporary-file-directory))) + "tramp-test*/*" ert-remote-temporary-file-directory))) (goto-char (point-min)) (should (re-search-forward (regexp-quote (file-relative-name - tmp-name3 tramp-test-temporary-file-directory)))) + tmp-name3 ert-remote-temporary-file-directory)))) (goto-char (point-min)) (should (re-search-forward (regexp-quote (file-relative-name tmp-name4 - tramp-test-temporary-file-directory))))) + ert-remote-temporary-file-directory))))) (kill-buffer buffer)) ;; Cleanup. @@ -3427,8 +3430,8 @@ This tests also `access-file', `file-readable-p', ;; We must use `file-truename' for the temporary directory, ;; because it could be located on a symlinked directory. This ;; would let the test fail. - (let* ((tramp-test-temporary-file-directory - (file-truename tramp-test-temporary-file-directory)) + (let* ((ert-remote-temporary-file-directory + (file-truename ert-remote-temporary-file-directory)) (tmp-name1 (tramp--test-make-temp-name nil quoted)) (tmp-name2 (tramp--test-make-temp-name nil quoted)) ;; File name with "//". @@ -3448,7 +3451,7 @@ This tests also `access-file', `file-readable-p', (and test-file-ownership-preserved-p (zerop (logand #o1000 - (file-modes tramp-test-temporary-file-directory)))) + (file-modes ert-remote-temporary-file-directory)))) (write-region "foo" nil tmp-name1) (setq test-file-ownership-preserved-p (= (file-attribute-group-id (file-attributes tmp-name1)) @@ -3527,7 +3530,7 @@ This tests also `access-file', `file-readable-p', ;; Check, that "//" in symlinks are handled properly. (with-temp-buffer - (let ((default-directory tramp-test-temporary-file-directory)) + (let ((default-directory ert-remote-temporary-file-directory)) (shell-command (format "ln -s %s %s" @@ -3785,8 +3788,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." ;; We must use `file-truename' for the temporary directory, ;; because it could be located on a symlinked directory. This ;; would let the test fail. - (let* ((tramp-test-temporary-file-directory - (file-truename tramp-test-temporary-file-directory)) + (let* ((ert-remote-temporary-file-directory + (file-truename ert-remote-temporary-file-directory)) (tmp-name1 (tramp--test-make-temp-name nil quoted)) (tmp-name2 (tramp--test-make-temp-name nil quoted)) (tmp-name3 (tramp--test-make-temp-name 'local quoted)) @@ -3933,7 +3936,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (should (file-equal-p tmp-name1 tmp-name2)) ;; Check relative symlink file name. (delete-file tmp-name2) - (let ((default-directory tramp-test-temporary-file-directory)) + (let ((default-directory ert-remote-temporary-file-directory)) (make-symbolic-link (file-name-nondirectory tmp-name1) tmp-name2)) (should (file-symlink-p tmp-name2)) (should-not (string-equal tmp-name2 (file-truename tmp-name2))) @@ -3980,7 +3983,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (tramp--test-ignore-make-symbolic-link-error (make-directory tmp-name1) (should (file-directory-p tmp-name1)) - (let* ((tramp-test-temporary-file-directory + (let* ((ert-remote-temporary-file-directory (file-truename tmp-name1)) (tmp-name2 (tramp--test-make-temp-name nil quoted)) (tmp-name3 tmp-name2) @@ -4041,7 +4044,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (directory-file-name (funcall (if quoted #'tramp-compat-file-name-quote #'identity) - tramp-test-temporary-file-directory))) + ert-remote-temporary-file-directory))) (dir2 (file-name-as-directory dir1))) (should (string-equal (file-truename dir1) (expand-file-name dir1))) (should (string-equal (file-truename dir2) (expand-file-name dir2))))))) @@ -4131,7 +4134,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." "Check that `file-acl' and `set-file-acl' work proper." (skip-unless (tramp--test-enabled)) ;; The following test checks also whether `set-file-modes' will work. - (skip-unless (file-acl tramp-test-temporary-file-directory)) + (skip-unless (file-acl ert-remote-temporary-file-directory)) (skip-unless (not (tramp--test-crypt-p))) ;; `filename-non-special' has been fixed in Emacs 27.1, see Bug#29579. @@ -4210,7 +4213,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." "Check `file-selinux-context' and `set-file-selinux-context'." (skip-unless (tramp--test-enabled)) (skip-unless - (not (equal (file-selinux-context tramp-test-temporary-file-directory) + (not (equal (file-selinux-context ert-remote-temporary-file-directory) '(nil nil nil nil)))) (skip-unless (not (tramp--test-crypt-p))) @@ -4271,7 +4274,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (let ((default-directory temporary-file-directory)) (shell-command-to-string "id -Z")) (let ((default-directory - tramp-test-temporary-file-directory)) + ert-remote-temporary-file-directory)) (shell-command-to-string "id -Z")))) ;; Two files with same SELinux context. @@ -4356,8 +4359,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." ;; does not work on MS Windows. (unless (memq system-type '(cygwin windows-nt)) (let ((tramp-fuse-remove-hidden-files t) - (method (file-remote-p tramp-test-temporary-file-directory 'method)) - (host (file-remote-p tramp-test-temporary-file-directory 'host)) + (method (file-remote-p ert-remote-temporary-file-directory 'method)) + (host (file-remote-p ert-remote-temporary-file-directory 'host)) (orig-syntax tramp-syntax)) (when (and (stringp host) (string-match tramp-host-with-port-regexp host)) (setq host (match-string 1 host))) @@ -4509,7 +4512,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil))) (let* ((tmp-name (tramp--test-make-temp-name nil quoted)) (fnnd (file-name-nondirectory tmp-name)) - (default-directory tramp-test-temporary-file-directory) + (default-directory ert-remote-temporary-file-directory) (buffer (get-buffer-create "*tramp-tests*")) kill-buffer-query-functions) (unwind-protect @@ -4643,7 +4646,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (skip-unless (tramp--test-supports-processes-p)) (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil))) - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) (tmp-name (tramp--test-make-temp-name nil quoted)) kill-buffer-query-functions command proc) @@ -4809,7 +4812,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." :tags (append '(:expensive-test :tramp-asynchronous-processes) (and ,unstable '(:unstable))) (skip-unless (tramp--test-enabled)) - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) (ert-test (ert-get-test ',test)) (tramp-connection-properties (cons '(nil "direct-async-process" t) @@ -4822,7 +4825,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." (cl-letf (((symbol-function #'tramp--test-enabled) #'tramp--test-always) ((symbol-function #'internal-default-process-sentinel) #'ignore)) - (file-truename tramp-test-temporary-file-directory) + (file-truename ert-remote-temporary-file-directory) (funcall (ert-test-body ert-test))))))) (tramp--test--deftest-direct-async-process tramp-test29-start-file-process @@ -4839,7 +4842,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." (skip-unless (tramp--test-emacs27-p)) (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil))) - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) (tmp-name (tramp--test-make-temp-name nil quoted)) kill-buffer-query-functions command proc) (with-no-warnings (should-not (make-process))) @@ -5100,7 +5103,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." ;; We must use `file-truename' for the temporary directory, in ;; order to establish the connection prior running an asynchronous ;; process. - (let ((default-directory (file-truename tramp-test-temporary-file-directory)) + (let ((default-directory (file-truename ert-remote-temporary-file-directory)) (delete-exited-processes t) kill-buffer-query-functions command proc) (unwind-protect @@ -5145,7 +5148,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." ;; We must use `file-truename' for the temporary directory, in ;; order to establish the connection prior running an asynchronous ;; process. - (let ((default-directory (file-truename tramp-test-temporary-file-directory)) + (let ((default-directory (file-truename ert-remote-temporary-file-directory)) (delete-exited-processes t) kill-buffer-query-functions command proc) @@ -5207,7 +5210,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." ;; `list-system-processes' is supported since Emacs 29.1. (skip-unless (tramp--test-emacs29-p)) - (let ((default-directory tramp-test-temporary-file-directory)) + (let ((default-directory ert-remote-temporary-file-directory)) (skip-unless (consp (list-system-processes))) (should (not (equal (list-system-processes) (let ((default-directory temporary-file-directory)) @@ -5224,7 +5227,7 @@ If UNSTABLE is non-nil, the test is tagged as `:unstable'." ;; We must use `file-truename' for the temporary directory, in ;; order to establish the connection prior running an asynchronous ;; process. - (let ((default-directory (file-truename tramp-test-temporary-file-directory)) + (let ((default-directory (file-truename ert-remote-temporary-file-directory)) (delete-exited-processes t) kill-buffer-query-functions command proc) (skip-unless (consp (list-system-processes))) @@ -5282,7 +5285,7 @@ INPUT, if non-nil, is a string sent to the process." (dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil))) (let ((tmp-name (tramp--test-make-temp-name nil quoted)) - (default-directory tramp-test-temporary-file-directory) + (default-directory ert-remote-temporary-file-directory) ;; Suppress nasty messages. (inhibit-message t) kill-buffer-query-functions) @@ -5363,7 +5366,7 @@ INPUT, if non-nil, is a string sent to the process." (when (and (tramp--test-asynchronous-processes-p) (tramp--test-sh-p) (tramp--test-emacs27-p)) (let* ((async-shell-command-width 1024) - (default-directory tramp-test-temporary-file-directory) + (default-directory ert-remote-temporary-file-directory) (cols (ignore-errors (read (tramp--test-shell-command-to-string-asynchronously "tput cols"))))) @@ -5415,7 +5418,7 @@ INPUT, if non-nil, is a string sent to the process." ;; We check both the local and remote case, in order to guarantee ;; that they behave similar. (dolist (default-directory - `(,temporary-file-directory ,tramp-test-temporary-file-directory)) + `(,temporary-file-directory ,ert-remote-temporary-file-directory)) ;; These are the possible values of `shell-command-dont-erase-buffer'. ;; `random' is taken as non-nil value without special meaning. (dolist (shell-command-dont-erase-buffer @@ -5515,7 +5518,7 @@ INPUT, if non-nil, is a string sent to the process." (and (tramp--test-asynchronous-processes-p) '(tramp--test-shell-command-to-string-asynchronously)))) - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) (shell-file-name "/bin/sh") (envvar (concat "VAR_" (upcase (md5 (current-time-string))))) kill-buffer-query-functions) @@ -5606,7 +5609,7 @@ Use direct async.") (skip-unless (not (tramp--test-crypt-p))) ;; We force a reconnect, in order to have a clean environment. - (dolist (dir `(,tramp-test-temporary-file-directory + (dolist (dir `(,ert-remote-temporary-file-directory "/mock:localhost#11111:" "/mock:localhost#22222:")) (tramp-cleanup-connection (tramp-dissect-file-name dir) 'keep-debug 'keep-password)) @@ -5640,7 +5643,7 @@ Use direct async.") ;; Since Emacs 27.1. (skip-unless (macrop 'with-connection-local-variables)) - (let* ((default-directory tramp-test-temporary-file-directory) + (let* ((default-directory ert-remote-temporary-file-directory) (tmp-name1 (tramp--test-make-temp-name)) (tmp-name2 (expand-file-name "foo" tmp-name1)) (enable-local-variables :all) @@ -5707,7 +5710,7 @@ Use direct async.") (when (tramp--test-adb-p) (skip-unless (tramp--test-emacs27-p))) - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) explicit-shell-file-name kill-buffer-query-functions connection-local-profile-alist connection-local-criteria-alist) (unwind-protect @@ -5757,7 +5760,7 @@ Use direct async.") (skip-unless (fboundp 'exec-path)) (let ((tmp-name (tramp--test-make-temp-name)) - (default-directory tramp-test-temporary-file-directory)) + (default-directory ert-remote-temporary-file-directory)) (unwind-protect (progn (should (consp (with-no-warnings (exec-path)))) @@ -5802,7 +5805,7 @@ Use direct async.") (skip-unless (fboundp 'exec-path)) (let* ((tmp-name (tramp--test-make-temp-name)) - (default-directory tramp-test-temporary-file-directory) + (default-directory ert-remote-temporary-file-directory) (orig-exec-path (with-no-warnings (exec-path))) (tramp-remote-path tramp-remote-path) (orig-tramp-remote-path tramp-remote-path) @@ -5869,7 +5872,7 @@ Use direct async.") ;; order to establish the connection prior running an asynchronous ;; process. (let* ((default-directory - (file-truename tramp-test-temporary-file-directory)) + (file-truename ert-remote-temporary-file-directory)) (tmp-name1 (tramp--test-make-temp-name nil quoted)) (tmp-name2 (expand-file-name "foo" tmp-name1)) (tramp-remote-process-environment tramp-remote-process-environment) @@ -5973,7 +5976,7 @@ Use direct async.") (if quoted #'tramp-compat-file-name-quote #'identity) (expand-file-name (format "#%s#" (file-name-nondirectory tmp-name1)) - tramp-test-temporary-file-directory)))))) + ert-remote-temporary-file-directory)))))) ;; Use default `tramp-auto-save-directory' mechanism. ;; Ange-FTP doesn't care. @@ -6078,7 +6081,7 @@ Use direct async.") (if quoted #'tramp-compat-file-name-quote #'identity) (expand-file-name (format "%s~" (file-name-nondirectory tmp-name1)) - tramp-test-temporary-file-directory))))))) + ert-remote-temporary-file-directory))))))) (unwind-protect ;; Map `backup-directory-alist'. @@ -6411,7 +6414,7 @@ Use direct async.") (skip-unless (tramp--test-enabled)) (skip-unless (not (tramp--test-ange-ftp-p))) - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) tmp-file) ;; The remote host shall know a temporary file directory. (should (stringp (temporary-file-directory))) @@ -6458,7 +6461,7 @@ variables, so we check the Emacs version directly." (defun tramp--test-adb-p () "Check, whether the remote host runs Android. This requires restrictions of file name syntax." - (tramp-adb-file-name-p tramp-test-temporary-file-directory)) + (tramp-adb-file-name-p ert-remote-temporary-file-directory)) (defun tramp--test-ange-ftp-p () "Check, whether Ange-FTP is used." @@ -6481,13 +6484,13 @@ This is used in tests which we don't want to tag (defun tramp--test-crypt-p () "Check, whether the remote directory is crypted." - (tramp-crypt-file-name-p tramp-test-temporary-file-directory)) + (tramp-crypt-file-name-p ert-remote-temporary-file-directory)) (defun tramp--test-docker-p () "Check, whether the docker method is used. This does not support some special file names." (string-equal - "docker" (file-remote-p tramp-test-temporary-file-directory 'method))) + "docker" (file-remote-p ert-remote-temporary-file-directory 'method))) (defun tramp--test-expensive-test-p () "Whether expensive tests are run. @@ -6503,7 +6506,7 @@ completely." This does not support globbing characters in file names (yet)." ;; Globbing characters are ??, ?* and ?\[. (string-match-p - "ftp$" (file-remote-p tramp-test-temporary-file-directory 'method))) + "ftp$" (file-remote-p ert-remote-temporary-file-directory 'method))) (defun tramp--test-fuse-p () "Check, whether an FUSE file system isused." @@ -6512,20 +6515,20 @@ This does not support globbing characters in file names (yet)." (defun tramp--test-gdrive-p () "Check, whether the gdrive method is used." (string-equal - "gdrive" (file-remote-p tramp-test-temporary-file-directory 'method))) + "gdrive" (file-remote-p ert-remote-temporary-file-directory 'method))) (defun tramp--test-gvfs-p (&optional method) "Check, whether the remote host runs a GVFS based method. This requires restrictions of file name syntax. If optional METHOD is given, it is checked first." (or (member method tramp-gvfs-methods) - (tramp-gvfs-file-name-p tramp-test-temporary-file-directory))) + (tramp-gvfs-file-name-p ert-remote-temporary-file-directory))) (defun tramp--test-hpux-p () "Check, whether the remote host runs HP-UX. Several special characters do not work properly there." ;; We must refill the cache. `file-truename' does it. - (file-truename tramp-test-temporary-file-directory) + (file-truename ert-remote-temporary-file-directory) (ignore-errors (tramp-check-remote-uname tramp-test-vec "^HP-UX"))) (defun tramp--test-ksh-p () @@ -6533,21 +6536,21 @@ Several special characters do not work properly there." ksh93 makes some strange conversions of non-latin characters into a $'' syntax." ;; We must refill the cache. `file-truename' does it. - (file-truename tramp-test-temporary-file-directory) + (file-truename ert-remote-temporary-file-directory) (string-match-p "ksh$" (tramp-get-connection-property tramp-test-vec "remote-shell" ""))) (defun tramp--test-macos-p () "Check, whether the remote host runs macOS." ;; We must refill the cache. `file-truename' does it. - (file-truename tramp-test-temporary-file-directory) + (file-truename ert-remote-temporary-file-directory) (ignore-errors (tramp-check-remote-uname tramp-test-vec "Darwin"))) (defun tramp--test-mock-p () "Check, whether the mock method is used. This does not support external Emacs calls." (string-equal - "mock" (file-remote-p tramp-test-temporary-file-directory 'method))) + "mock" (file-remote-p ert-remote-temporary-file-directory 'method))) (defun tramp--test-out-of-band-p () "Check, whether an out-of-band method is used." @@ -6556,13 +6559,13 @@ This does not support external Emacs calls." (defun tramp--test-rclone-p () "Check, whether the remote host is offered by rclone. This requires restrictions of file name syntax." - (tramp-rclone-file-name-p tramp-test-temporary-file-directory)) + (tramp-rclone-file-name-p ert-remote-temporary-file-directory)) (defun tramp--test-rsync-p () "Check, whether the rsync method is used. This does not support special file names." (string-equal - "rsync" (file-remote-p tramp-test-temporary-file-directory 'method))) + "rsync" (file-remote-p ert-remote-temporary-file-directory 'method))) (defun tramp--test-sh-p () "Check, whether the remote host runs a based method from tramp-sh.el." @@ -6576,7 +6579,7 @@ Additionally, ls does not support \"--dired\"." ;; We must refill the cache. `insert-directory' does it. ;; This fails for tramp-crypt.el, so we ignore that. (ignore-errors - (insert-directory tramp-test-temporary-file-directory "-al")) + (insert-directory ert-remote-temporary-file-directory "-al")) (not (tramp-get-connection-property tramp-test-vec "ls--dired" nil))))) (defun tramp--test-share-p () @@ -6584,22 +6587,22 @@ Additionally, ls does not support \"--dired\"." (and (tramp--test-gvfs-p) (string-match-p "^\\(afp\\|davs?\\|smb\\)$" - (file-remote-p tramp-test-temporary-file-directory 'method)))) + (file-remote-p ert-remote-temporary-file-directory 'method)))) (defun tramp--test-sshfs-p () "Check, whether the remote host is offered by sshfs. This requires restrictions of file name syntax." - (tramp-sshfs-file-name-p tramp-test-temporary-file-directory)) + (tramp-sshfs-file-name-p ert-remote-temporary-file-directory)) (defun tramp--test-sudoedit-p () "Check, whether the sudoedit method is used." - (tramp-sudoedit-file-name-p tramp-test-temporary-file-directory)) + (tramp-sudoedit-file-name-p ert-remote-temporary-file-directory)) (defun tramp--test-telnet-p () "Check, whether the telnet method is used. This does not support special file names." (string-equal - "telnet" (file-remote-p tramp-test-temporary-file-directory 'method))) + "telnet" (file-remote-p ert-remote-temporary-file-directory 'method))) (defun tramp--test-windows-nt-p () "Check, whether the locale host runs MS Windows." @@ -6620,7 +6623,7 @@ This requires restrictions of file name syntax." (defun tramp--test-smb-p () "Check, whether the locale or remote host runs MS Windows. This requires restrictions of file name syntax." - (tramp-smb-file-name-p tramp-test-temporary-file-directory)) + (tramp-smb-file-name-p ert-remote-temporary-file-directory)) (defun tramp--test-supports-processes-p () "Return whether the method under test supports external processes." @@ -6636,7 +6639,7 @@ This requires restrictions of file name syntax." (and (tramp--test-gvfs-p) (string-match-p - "ftp" (file-remote-p tramp-test-temporary-file-directory 'method))))) + "ftp" (file-remote-p ert-remote-temporary-file-directory 'method))))) (defun tramp--test-check-files (&rest files) "Run a simple but comprehensive test over every file in FILES." @@ -6647,8 +6650,8 @@ This requires restrictions of file name syntax." ;; We must use `file-truename' for the temporary directory, ;; because it could be located on a symlinked directory. This ;; would let the test fail. - (let* ((tramp-test-temporary-file-directory - (file-truename tramp-test-temporary-file-directory)) + (let* ((ert-remote-temporary-file-directory + (file-truename ert-remote-temporary-file-directory)) (tramp-fuse-remove-hidden-files t) (tmp-name1 (tramp--test-make-temp-name nil quoted)) (tmp-name2 (tramp--test-make-temp-name 'local quoted)) @@ -6835,7 +6838,7 @@ This requires restrictions of file name syntax." (dolist (elt files) (let ((envvar (concat "VAR_" (upcase (md5 elt)))) (elt (encode-coding-string elt coding-system-for-read)) - (default-directory tramp-test-temporary-file-directory) + (default-directory ert-remote-temporary-file-directory) (process-environment process-environment)) (setenv envvar elt) ;; The value of PS1 could confuse Tramp's detection @@ -6933,12 +6936,12 @@ Use the \"stat\" command." (skip-unless (tramp--test-sh-p)) (skip-unless (not (tramp--test-rsync-p))) ;; We cannot use `tramp-test-vec', because this fails during compilation. - (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil + (with-parsed-tramp-file-name ert-remote-temporary-file-directory nil (skip-unless (tramp-get-remote-stat v))) (let ((tramp-connection-properties (append - `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "perl" nil)) tramp-connection-properties))) (tramp--test-special-characters))) @@ -6952,15 +6955,15 @@ Use the \"perl\" command." (skip-unless (tramp--test-sh-p)) (skip-unless (not (tramp--test-rsync-p))) ;; We cannot use `tramp-test-vec', because this fails during compilation. - (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil + (with-parsed-tramp-file-name ert-remote-temporary-file-directory nil (skip-unless (tramp-get-remote-perl v))) (let ((tramp-connection-properties (append - `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "stat" nil) ;; See `tramp-sh-handle-file-truename'. - (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "readlink" nil)) tramp-connection-properties))) (tramp--test-special-characters))) @@ -6976,12 +6979,12 @@ Use the \"ls\" command." (let ((tramp-connection-properties (append - `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "perl" nil) - (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "stat" nil) ;; See `tramp-sh-handle-file-truename'. - (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "readlink" nil)) tramp-connection-properties))) (tramp--test-special-characters))) @@ -7060,12 +7063,12 @@ Use the \"stat\" command." (skip-unless (not (tramp--test-ksh-p))) (skip-unless (not (tramp--test-crypt-p))) ;; We cannot use `tramp-test-vec', because this fails during compilation. - (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil + (with-parsed-tramp-file-name ert-remote-temporary-file-directory nil (skip-unless (tramp-get-remote-stat v))) (let ((tramp-connection-properties (append - `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "perl" nil)) tramp-connection-properties))) (tramp--test-utf8))) @@ -7083,15 +7086,15 @@ Use the \"perl\" command." (skip-unless (not (tramp--test-ksh-p))) (skip-unless (not (tramp--test-crypt-p))) ;; We cannot use `tramp-test-vec', because this fails during compilation. - (with-parsed-tramp-file-name tramp-test-temporary-file-directory nil + (with-parsed-tramp-file-name ert-remote-temporary-file-directory nil (skip-unless (tramp-get-remote-perl v))) (let ((tramp-connection-properties (append - `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "stat" nil) ;; See `tramp-sh-handle-file-truename'. - (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "readlink" nil)) tramp-connection-properties))) (tramp--test-utf8))) @@ -7111,12 +7114,12 @@ Use the \"ls\" command." (let ((tramp-connection-properties (append - `((,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + `((,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "perl" nil) - (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "stat" nil) ;; See `tramp-sh-handle-file-truename'. - (,(regexp-quote (file-remote-p tramp-test-temporary-file-directory)) + (,(regexp-quote (file-remote-p ert-remote-temporary-file-directory)) "readlink" nil)) tramp-connection-properties))) (tramp--test-utf8))) @@ -7130,7 +7133,7 @@ Use the \"ls\" command." ;; `file-system-info' exists since Emacs 27.1. We don't want to see ;; compiler warnings for older Emacsen. (when-let ((fsi (with-no-warnings - (file-system-info tramp-test-temporary-file-directory)))) + (file-system-info ert-remote-temporary-file-directory)))) (should (consp fsi)) (should (= (length fsi) 3)) (dotimes (i (length fsi)) @@ -7385,7 +7388,7 @@ process sentinels. They shall not disturb each other." ;; default handler. (skip-unless (not (tramp--test-emacs29-p))) - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) (tmp-name (tramp--test-make-temp-name))) (write-region "foo" nil tmp-name) (dired default-directory) @@ -7406,7 +7409,7 @@ process sentinels. They shall not disturb each other." ;; default handler. (skip-unless (not (tramp--test-emacs29-p))) - (let ((default-directory tramp-test-temporary-file-directory) + (let ((default-directory ert-remote-temporary-file-directory) (tmp-name (tramp--test-make-temp-name))) (make-directory tmp-name) (dired default-directory) @@ -7451,17 +7454,17 @@ process sentinels. They shall not disturb each other." (tramp-cleanup-connection tramp-test-vec 'keep-debug) ;; We don't want to invalidate the password. (setq mocked-input `(,(copy-sequence pass))) - (should (file-exists-p tramp-test-temporary-file-directory)) + (should (file-exists-p ert-remote-temporary-file-directory)) ;; Don't entering a password returns in error. (tramp-cleanup-connection tramp-test-vec 'keep-debug) (setq mocked-input nil) - (should-error (file-exists-p tramp-test-temporary-file-directory)) + (should-error (file-exists-p ert-remote-temporary-file-directory)) ;; A wrong password doesn't work either. (tramp-cleanup-connection tramp-test-vec 'keep-debug) (setq mocked-input `(,(concat pass pass))) - (should-error (file-exists-p tramp-test-temporary-file-directory)) + (should-error (file-exists-p ert-remote-temporary-file-directory)) ;; Reading password from auth-source works. We use the netrc ;; backend; the other backends shall behave similar. @@ -7474,9 +7477,9 @@ process sentinels. They shall not disturb each other." :prefix "tramp-test" :suffix "" :text (format "machine %s port mock password %s" - (file-remote-p tramp-test-temporary-file-directory 'host) pass) + (file-remote-p ert-remote-temporary-file-directory 'host) pass) (let ((auth-sources `(,netrc-file))) - (should (file-exists-p tramp-test-temporary-file-directory))))))))) + (should (file-exists-p ert-remote-temporary-file-directory))))))))) ;; This test is inspired by Bug#29163. (ert-deftest tramp-test47-auto-load () @@ -7492,7 +7495,7 @@ process sentinels. They shall not disturb each other." ;; Suppress method name check. "(let ((non-essential t)) \ (message \"Tramp loaded: %%s\" (and (file-remote-p %S) t)))" - tramp-test-temporary-file-directory))) + ert-remote-temporary-file-directory))) (should (string-match-p "Tramp loaded: t[\n\r]+" @@ -7541,10 +7544,10 @@ process sentinels. They shall not disturb each other." (dolist (code (list (format - "(expand-file-name %S)" tramp-test-temporary-file-directory) + "(expand-file-name %S)" ert-remote-temporary-file-directory) (format "(let ((default-directory %S)) (expand-file-name %S))" - tramp-test-temporary-file-directory + ert-remote-temporary-file-directory temporary-file-directory))) (should-not (string-match-p diff --git a/test/lisp/shadowfile-tests.el b/test/lisp/shadowfile-tests.el index 46ab34535d..e822bc9eb6 100644 --- a/test/lisp/shadowfile-tests.el +++ b/test/lisp/shadowfile-tests.el @@ -37,37 +37,9 @@ ;;; Code: -(require 'ert) -(require 'shadowfile) (require 'tramp) - -;; There is no default value on w32 systems, which could work out of the box. -(defconst shadow-test-remote-temporary-file-directory - (cond - ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) - ((eq system-type 'windows-nt) null-device) - (t (add-to-list - 'tramp-methods - '("mock" - (tramp-login-program "sh") - (tramp-login-args (("-i"))) - (tramp-remote-shell "/bin/sh") - (tramp-remote-shell-args ("-c")) - (tramp-connection-timeout 10))) - (add-to-list - 'tramp-default-host-alist - `("\\`mock\\'" nil ,(system-name))) - ;; Emacs' Makefile sets $HOME to a nonexistent value. Needed in - ;; batch mode only, therefore. `shadow-homedir' cannot be - ;; `temporary-directory', because the tests with "~" would fail. - (unless (and (null noninteractive) (file-directory-p "~/")) - (setenv "HOME" (file-name-unquote temporary-file-directory)) - (setq shadow-homedir invocation-directory) - (add-to-list - 'tramp-connection-properties - `(,(file-remote-p "/mock::") "~" ,invocation-directory))) - (format "/mock::%s" temporary-file-directory))) - "Temporary directory for Tramp tests.") +(require 'ert-x) +(require 'shadowfile) (setq auth-source-save-behavior nil password-cache-expiry nil @@ -80,9 +52,8 @@ tramp-verbose 0 ;; On macOS, `temporary-file-directory' is a symlinked directory. temporary-file-directory (file-truename temporary-file-directory) - shadow-test-remote-temporary-file-directory - (ignore-errors - (file-truename shadow-test-remote-temporary-file-directory))) + ert-remote-temporary-file-directory + (ignore-errors (file-truename ert-remote-temporary-file-directory))) ;; This should happen on hydra only. (when (getenv "EMACS_HYDRA_CI") @@ -100,7 +71,7 @@ "Reset all `shadowfile' internals." ;; Cleanup Tramp. (tramp-cleanup-connection - (tramp-dissect-file-name shadow-test-remote-temporary-file-directory) t t) + (tramp-dissect-file-name ert-remote-temporary-file-directory) t t) ;; Delete auto-saved files. (with-current-buffer (find-file-noselect shadow-info-file 'nowarn) (ignore-errors (delete-file (make-auto-save-file-name))) @@ -135,7 +106,7 @@ a cluster (or site). This is not tested here; it must be guaranteed by the originator of a cluster definition." :tags '(:expensive-test) (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) (let ((text-quoting-style 'grave) ;; We inspect the *Messages* buffer! (inhibit-message t) @@ -222,8 +193,7 @@ guaranteed by the originator of a cluster definition." (shadow-cluster-regexp (shadow-get-cluster cluster)) regexp)) ;; Redefine the cluster. - (setq primary - (file-remote-p shadow-test-remote-temporary-file-directory) + (setq primary (file-remote-p ert-remote-temporary-file-directory) regexp (shadow-regexp-superquote primary) mocked-input `(,cluster ,primary ,regexp)) (call-interactively #'shadow-define-cluster) @@ -254,7 +224,7 @@ Per definition, all files are identical on the different hosts of a cluster (or site). This is not tested here; it must be guaranteed by the originator of a cluster definition." (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) (let ((shadow-info-file shadow-test-info-file) (shadow-todo-file shadow-test-todo-file) @@ -286,14 +256,14 @@ guaranteed by the originator of a cluster definition." (should (string-equal (system-name) (shadow-site-name primary1))) (should (string-equal - (file-remote-p shadow-test-remote-temporary-file-directory) + (file-remote-p ert-remote-temporary-file-directory) (shadow-name-site - (file-remote-p shadow-test-remote-temporary-file-directory)))) + (file-remote-p ert-remote-temporary-file-directory)))) (should (string-equal - (file-remote-p shadow-test-remote-temporary-file-directory) + (file-remote-p ert-remote-temporary-file-directory) (shadow-site-name - (file-remote-p shadow-test-remote-temporary-file-directory)))) + (file-remote-p ert-remote-temporary-file-directory)))) (should (equal (shadow-site-cluster cluster1) (shadow-get-cluster cluster1))) @@ -324,8 +294,7 @@ guaranteed by the originator of a cluster definition." ;; Define a second cluster. (setq cluster2 "cluster2" - primary2 - (file-remote-p shadow-test-remote-temporary-file-directory) + primary2 (file-remote-p ert-remote-temporary-file-directory) regexp2 (format "^\\(%s\\|%s\\)$" shadow-system-name primary2)) (shadow-set-cluster cluster2 primary2 regexp2) @@ -356,7 +325,7 @@ guaranteed by the originator of a cluster definition." (ert-deftest shadow-test02-files () "Check file manipulation functions." (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) (let ((shadow-info-file shadow-test-info-file) (shadow-todo-file shadow-test-todo-file) @@ -398,8 +367,7 @@ guaranteed by the originator of a cluster definition." (string-equal (shadow-local-file (concat primary file)) file)) ;; Redefine the cluster. - (setq primary - (file-remote-p shadow-test-remote-temporary-file-directory) + (setq primary (file-remote-p ert-remote-temporary-file-directory) regexp (shadow-regexp-superquote primary)) (shadow-set-cluster cluster primary regexp) @@ -428,7 +396,7 @@ guaranteed by the originator of a cluster definition." (ert-deftest shadow-test03-expand-cluster-in-file-name () "Check canonical file name of a cluster or site." (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) (let ((shadow-info-file shadow-test-info-file) (shadow-todo-file shadow-test-todo-file) @@ -453,8 +421,7 @@ guaranteed by the originator of a cluster definition." file2 (make-temp-name (expand-file-name - "shadowfile-tests" - shadow-test-remote-temporary-file-directory))) + "shadowfile-tests" ert-remote-temporary-file-directory))) ;; A local file name is kept. (should @@ -473,8 +440,7 @@ guaranteed by the originator of a cluster definition." (shadow-expand-cluster-in-file-name (concat primary file1)) file1)) ;; Redefine the cluster. - (setq primary - (file-remote-p shadow-test-remote-temporary-file-directory) + (setq primary (file-remote-p ert-remote-temporary-file-directory) regexp (shadow-regexp-superquote primary)) (shadow-set-cluster cluster primary regexp) @@ -495,7 +461,7 @@ guaranteed by the originator of a cluster definition." (ert-deftest shadow-test04-contract-file-name () "Check canonical file name of a cluster or site." (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) (let ((shadow-info-file shadow-test-info-file) (shadow-todo-file shadow-test-todo-file) @@ -533,8 +499,7 @@ guaranteed by the originator of a cluster definition." (concat "/cluster:" file))) ;; Redefine the cluster. - (setq primary - (file-remote-p shadow-test-remote-temporary-file-directory) + (setq primary (file-remote-p ert-remote-temporary-file-directory) regexp (shadow-regexp-superquote primary)) (shadow-set-cluster cluster primary regexp) @@ -542,8 +507,7 @@ guaranteed by the originator of a cluster definition." (should (string-equal (shadow-contract-file-name - (concat - (file-remote-p shadow-test-remote-temporary-file-directory) file)) + (concat (file-remote-p ert-remote-temporary-file-directory) file)) (concat "/cluster:" file)))) ;; Cleanup. @@ -552,7 +516,7 @@ guaranteed by the originator of a cluster definition." (ert-deftest shadow-test05-file-match () "Check `shadow-same-site' and `shadow-file-match'." (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) (let ((shadow-info-file shadow-test-info-file) (shadow-todo-file shadow-test-todo-file) @@ -588,17 +552,14 @@ guaranteed by the originator of a cluster definition." (should (shadow-file-match (shadow-parse-name file) file)) ;; Redefine the cluster. - (setq primary - (file-remote-p shadow-test-remote-temporary-file-directory) + (setq primary (file-remote-p ert-remote-temporary-file-directory) regexp (shadow-regexp-superquote primary)) (shadow-set-cluster cluster primary regexp) (should (shadow-file-match (shadow-parse-name - (concat - (file-remote-p shadow-test-remote-temporary-file-directory) - file)) + (concat (file-remote-p ert-remote-temporary-file-directory) file)) file))) ;; Cleanup. @@ -607,7 +568,7 @@ guaranteed by the originator of a cluster definition." (ert-deftest shadow-test06-literal-groups () "Check literal group definitions." (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) (let ((shadow-info-file shadow-test-info-file) (shadow-todo-file shadow-test-todo-file) @@ -632,8 +593,7 @@ guaranteed by the originator of a cluster definition." (shadow-set-cluster cluster1 primary regexp) (setq cluster2 "cluster2" - primary - (file-remote-p shadow-test-remote-temporary-file-directory) + primary (file-remote-p ert-remote-temporary-file-directory) regexp (format "^\\(%s\\|%s\\)$" shadow-system-name primary)) (shadow-set-cluster cluster2 primary regexp) @@ -644,8 +604,7 @@ guaranteed by the originator of a cluster definition." file2 (make-temp-name (expand-file-name - "shadowfile-tests" - shadow-test-remote-temporary-file-directory)) + "shadowfile-tests" ert-remote-temporary-file-directory)) mocked-input `(,cluster1 ,file1 ,cluster2 ,file2 ,primary ,file1 ,(kbd "RET"))) @@ -694,7 +653,7 @@ guaranteed by the originator of a cluster definition." (ert-deftest shadow-test07-regexp-groups () "Check regexp group definitions." (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) (let ((shadow-info-file shadow-test-info-file) (shadow-todo-file shadow-test-todo-file) @@ -719,8 +678,7 @@ guaranteed by the originator of a cluster definition." (shadow-set-cluster cluster1 primary regexp) (setq cluster2 "cluster2" - primary - (file-remote-p shadow-test-remote-temporary-file-directory) + primary (file-remote-p ert-remote-temporary-file-directory) regexp (format "^\\(%s\\|%s\\)$" shadow-system-name primary)) (shadow-set-cluster cluster2 primary regexp) @@ -757,8 +715,8 @@ guaranteed by the originator of a cluster definition." (ert-deftest shadow-test08-shadow-todo () "Check that needed shadows are added to todo." (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) - (skip-unless (file-writable-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) + (skip-unless (file-writable-p ert-remote-temporary-file-directory)) (let ((backup-inhibited t) create-lockfiles @@ -778,7 +736,7 @@ guaranteed by the originator of a cluster definition." (message "%s %s %s %s %s" temporary-file-directory - shadow-test-remote-temporary-file-directory + ert-remote-temporary-file-directory shadow-homedir shadow-info-file shadow-todo-file)) ;; Define clusters. @@ -792,8 +750,7 @@ guaranteed by the originator of a cluster definition." cluster1 primary regexp shadow-clusters)) (setq cluster2 "cluster2" - primary - (file-remote-p shadow-test-remote-temporary-file-directory) + primary (file-remote-p ert-remote-temporary-file-directory) regexp (shadow-regexp-superquote primary)) (shadow-set-cluster cluster2 primary regexp) (when shadow-debug @@ -903,8 +860,8 @@ guaranteed by the originator of a cluster definition." "Check that needed shadow files are copied." :tags '(:expensive-test) (skip-unless (not (memq system-type '(windows-nt ms-dos)))) - (skip-unless (file-remote-p shadow-test-remote-temporary-file-directory)) - (skip-unless (file-writable-p shadow-test-remote-temporary-file-directory)) + (skip-unless (file-remote-p ert-remote-temporary-file-directory)) + (skip-unless (file-writable-p ert-remote-temporary-file-directory)) (let ((backup-inhibited t) create-lockfiles @@ -928,8 +885,7 @@ guaranteed by the originator of a cluster definition." (shadow-set-cluster cluster1 primary regexp) (setq cluster2 "cluster2" - primary - (file-remote-p shadow-test-remote-temporary-file-directory) + primary (file-remote-p ert-remote-temporary-file-directory) regexp (shadow-regexp-superquote primary)) (shadow-set-cluster cluster2 primary regexp) commit 493ae66be08a99ea7918ee8210aec3eb925c8fad Author: Mattias Engdegård Date: Wed Jun 8 10:03:55 2022 +0200 Preserve doc string in `byte-compile` (bug#55830) * lisp/emacs-lisp/bytecomp.el (byte-compile--reify-function): Don't transpose doc string and interactive spec, which must come in this order. * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-function-attributes): New test. diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 2e89504e8f..ab21fba8a2 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -2926,6 +2926,7 @@ FUN should be either a `lambda' value or a `closure' value." (push (pop body) preamble)) (when (eq (car-safe (car body)) 'interactive) (push (pop body) preamble)) + (setq preamble (nreverse preamble)) ;; Turn the function's closed vars (if any) into local let bindings. (dolist (binding env) (cond diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 39f053136a..27098d0bb1 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -1553,6 +1553,27 @@ EXPECTED-POINT BINDINGS (MODES \\='\\='(ruby-mode js-mode python-mode)) \ (should (byte-compile--suspicious-defcustom-choice '(choice (const :tag "foo" 'bar))))) +(ert-deftest bytecomp-function-attributes () + ;; Check that `byte-compile' keeps the declarations, interactive spec and + ;; doc string of the function (bug#55830). + (let ((fname 'bytecomp-test-fun)) + (fset fname nil) + (put fname 'pure nil) + (put fname 'lisp-indent-function nil) + (eval `(defun ,fname (x) + "tata" + (declare (pure t) (indent 1)) + (interactive "P") + (list 'toto x)) + t) + (let ((bc (byte-compile fname))) + (should (byte-code-function-p bc)) + (should (equal (funcall bc 'titi) '(toto titi))) + (should (equal (aref bc 5) "P")) + (should (equal (get fname 'pure) t)) + (should (equal (get fname 'lisp-indent-function) 1)) + (should (equal (aref bc 4) "tata\n\n(fn X)"))))) + ;; Local Variables: ;; no-byte-compile: t ;; End: commit 22d3f0e95a5602b2bde763cff185f5b4fed6e53e Author: Po Lu Date: Wed Jun 8 15:08:09 2022 +0800 Make responding to selection requests work inside popups * src/xfns.c (Fx_file_dialog): * src/xmenu.c (x_menu_wait_for_event, create_and_show_popup_menu) (create_and_show_dialog, x_menu_show): Defer selection requests. * src/xselect.c (x_get_foreign_selection) (x_handle_selection_notify): Add some more info to selection trace. * src/xterm.c (x_defer_selection_requests): Make non-static. (x_release_selection_requests_and_flush): New function. (x_dnd_begin_drag_and_drop): Use DEFER_SELECTIONS instead. (x_wait_for_cell_change): Fix initial value of rc for pushed back events. (handle_one_xevent): Allow GTK to respond to selections in its windows too. * src/xterm.h (DEFER_SELECTIONS): New slug of code. diff --git a/src/xfns.c b/src/xfns.c index cffb4a5d96..f0a2ec666c 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -8885,6 +8885,9 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, /* Prevent redisplay. */ specbind (Qinhibit_redisplay, Qt); + /* Defer selection requests. */ + DEFER_SELECTIONS; + block_input (); /* Create the dialog with PROMPT as title, using DIR as initial diff --git a/src/xmenu.c b/src/xmenu.c index e9601981ed..7134bf22c8 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -198,6 +198,10 @@ x_menu_wait_for_event (void *data) struct x_display_info *dpyinfo; int n = 0; + /* ISTM that if timer_check is okay, this should be too, since + both can run random Lisp. */ + x_handle_pending_selection_requests (); + FD_ZERO (&read_fds); for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) { @@ -1579,6 +1583,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, } #endif + DEFER_SELECTIONS; + /* Display the menu. */ gtk_widget_show_all (menu); @@ -1868,6 +1874,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, { specpdl_ref specpdl_count = SPECPDL_INDEX (); + DEFER_SELECTIONS; + record_unwind_protect_int (pop_down_menu, (int) menu_id); #ifdef HAVE_XINPUT2 record_unwind_protect_ptr (leave_toolkit_menu, f); @@ -2199,6 +2207,8 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv) if (menu) { specpdl_ref specpdl_count = SPECPDL_INDEX (); + + DEFER_SELECTIONS; record_unwind_protect_ptr (pop_down_menu, menu); /* Display the menu. */ @@ -2255,6 +2265,8 @@ create_and_show_dialog (struct frame *f, widget_value *first_wv) { specpdl_ref count = SPECPDL_INDEX (); + DEFER_SELECTIONS; + /* xdialog_show_unwind is responsible for popping the dialog box down. */ record_unwind_protect_int (pop_down_menu, (int) dialog_id); @@ -2715,18 +2727,18 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, y = max (y, 1); XMenuLocate (FRAME_X_DISPLAY (f), menu, 0, 0, x, y, &ulx, &uly, &width, &height); - if (ulx+width > dispwidth) + if (ulx + width > dispwidth) { x -= (ulx + width) - dispwidth; ulx = dispwidth - width; } - if (uly+height > dispheight) + if (uly + height > dispheight) { y -= (uly + height) - dispheight; uly = dispheight - height; } #ifndef HAVE_X_WINDOWS - if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 1) + if (FRAME_HAS_MINIBUF_P (f) && uly + height > dispheight - 1) { /* Move the menu away of the echo area, to avoid overwriting the menu with help echo messages or vice versa. */ @@ -2750,8 +2762,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, /* If position was not given by a mouse click, adjust so upper left corner of the menu as a whole ends up at given coordinates. This is what x-popup-menu says in its documentation. */ - x += width/2; - y += 1.5*height/(maxlines+2); + x += width / 2; + y += 1.5 * height/ (maxlines + 2); } XMenuSetAEQ (menu, true); @@ -2759,6 +2771,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, pane = selidx = 0; #ifndef MSDOS + DEFER_SELECTIONS; + XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f)); #ifdef HAVE_XINPUT2 XMenuActivateSetTranslateFunction (x_menu_translate_generic_event); diff --git a/src/xselect.c b/src/xselect.c index d184489cbd..40b6571e0a 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -1252,7 +1252,11 @@ x_get_foreign_selection (Lisp_Object selection_symbol, Lisp_Object target_type, else x_wait_for_cell_change (reading_selection_reply, make_timespec (secs, nsecs)); - TRACE1 (" Got event = %d", !NILP (XCAR (reading_selection_reply))); + TRACE1 (" Got event = %s", (!NILP (XCAR (reading_selection_reply)) + ? (SYMBOLP (XCAR (reading_selection_reply)) + ? SSDATA (SYMBOL_NAME (XCAR (reading_selection_reply))) + : "YES") + : "NO")); if (NILP (XCAR (reading_selection_reply))) error ("Timed out waiting for reply from selection owner"); @@ -1947,7 +1951,7 @@ x_handle_selection_notify (const XSelectionEvent *event) if (event->selection != reading_which_selection) return; - TRACE0 ("Received SelectionNotify"); + TRACE1 ("Received SelectionNotify: %d", (int) event->property); XSETCAR (reading_selection_reply, (event->property != 0 ? Qt : Qlambda)); } diff --git a/src/xterm.c b/src/xterm.c index 444adcf94f..1f4d301e6a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -793,10 +793,43 @@ static struct input_event *current_hold_quit; than 0. */ static int x_use_pending_selection_requests; -static void +static void x_push_selection_request (struct selection_input_event *); + +/* Defer selection requests. Any selection requests generated after + this can then be processed by calling + `x_handle_pending_selection_requests'. + + Also run through and queue all the selection events already in the + keyboard buffer. */ +void x_defer_selection_requests (void) { + union buffered_input_event *event; + + block_input (); x_use_pending_selection_requests++; + + if (!x_use_pending_selection_requests) + { + event = kbd_fetch_ptr; + + while (event != kbd_store_ptr) + { + if (event->ie.kind == SELECTION_REQUEST_EVENT + || event->ie.kind == SELECTION_CLEAR_EVENT) + { + x_push_selection_request (&event->sie); + + /* Mark this selection event as invalid. */ + SELECTION_EVENT_DPYINFO (&event->sie) = NULL; + } + + event = (event == kbd_buffer + KBD_BUFFER_SIZE - 1 + ? kbd_buffer : event + 1); + } + } + + unblock_input (); } static void @@ -805,6 +838,15 @@ x_release_selection_requests (void) x_use_pending_selection_requests--; } +void +x_release_selection_requests_and_flush (void) +{ + x_release_selection_requests (); + + if (!x_use_pending_selection_requests) + x_handle_pending_selection_requests (); +} + struct x_selection_request_event { /* The selection request event. */ @@ -10764,8 +10806,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (x_dnd_in_progress || x_dnd_waiting_for_finish) error ("A drag-and-drop session is already in progress"); - x_defer_selection_requests (); - record_unwind_protect_void (x_release_selection_requests); + DEFER_SELECTIONS; /* If local_value is nil, then we lost ownership of XdndSelection. Signal a more informative error than args-out-of-range. */ @@ -10781,8 +10822,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (popup_activated ()) error ("Trying to drag-and-drop from within a menu-entry"); - record_unwind_protect_void (x_free_dnd_targets); x_set_dnd_targets (target_atoms, ntargets); + record_unwind_protect_void (x_free_dnd_targets); ltimestamp = x_timestamp_for_selection (FRAME_DISPLAY_INFO (f), QXdndSelection); @@ -15306,7 +15347,7 @@ x_wait_for_cell_change (Lisp_Object cell, struct timespec timeout) #ifndef USE_GTK FD_ZERO (&rfds); - rc = 0; + rc = -1; #endif while (true) @@ -15892,18 +15933,18 @@ handle_one_xevent (struct x_display_info *dpyinfo, break; case SelectionNotify: -#ifdef USE_X_TOOLKIT - if (! x_window_to_frame (dpyinfo, event->xselection.requestor)) +#if defined USE_X_TOOLKIT || defined USE_GTK + if (!x_window_to_frame (dpyinfo, event->xselection.requestor)) goto OTHER; -#endif /* not USE_X_TOOLKIT */ +#endif /* not USE_X_TOOLKIT and not USE_GTK */ x_handle_selection_notify (&event->xselection); break; case SelectionClear: /* Someone has grabbed ownership. */ -#ifdef USE_X_TOOLKIT - if (! x_window_to_frame (dpyinfo, event->xselectionclear.window)) +#if defined USE_X_TOOLKIT || defined USE_GTK + if (!x_window_to_frame (dpyinfo, event->xselectionclear.window)) goto OTHER; -#endif /* USE_X_TOOLKIT */ +#endif /* not USE_X_TOOLKIT and not USE_GTK */ { const XSelectionClearEvent *eventp = &event->xselectionclear; diff --git a/src/xterm.h b/src/xterm.h index 1ab65f15d1..7e91e28ed1 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1456,6 +1456,12 @@ extern void x_xr_reset_ext_clip (struct frame *f); extern void x_scroll_bar_configure (GdkEvent *); #endif +#define DEFER_SELECTIONS \ + x_defer_selection_requests (); \ + record_unwind_protect_void (x_release_selection_requests_and_flush) + +extern void x_defer_selection_requests (void); +extern void x_release_selection_requests_and_flush (void); extern void x_handle_pending_selection_requests (void); extern bool x_detect_pending_selection_requests (void); extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, commit 90f3da0ccdb4c58265e9f8c3d9465198d8a2092a Author: Po Lu Date: Wed Jun 8 13:03:57 2022 +0800 Fix quitting in one go out of `mouse-drag-and-drop-region' * src/xterm.c (x_dnd_begin_drag_and_drop): Make sure handle_interrupt is called inside the nested event loop upon a quit event. diff --git a/src/xterm.c b/src/xterm.c index f42f7cb1eb..444adcf94f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11116,6 +11116,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + + /* Call kbd_buffer_store event, which calls + handle_interrupt and sets `last-event-frame' along + with various other things. */ + kbd_buffer_store_event (&hold_quit); + /* Now quit anyway. */ quit (); } commit d1c619372099ba123b7aa485907ed71ec961e9fe Author: Po Lu Date: Wed Jun 8 10:54:07 2022 +0800 Fix crash with outdated selection requests * src/xselect.c (x_handle_selection_request): Don't store into stack if it wasn't previously pushed. diff --git a/src/xselect.c b/src/xselect.c index 0271310d04..d184489cbd 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -762,7 +762,6 @@ static void x_handle_selection_request (struct selection_input_event *event) { Time local_selection_time; - struct x_display_info *dpyinfo = SELECTION_EVENT_DPYINFO (event); Atom selection = SELECTION_EVENT_SELECTION (event); Lisp_Object selection_symbol = x_atom_to_symbol (dpyinfo, selection); @@ -772,8 +771,12 @@ x_handle_selection_request (struct selection_input_event *event) Lisp_Object local_selection_data; bool success = false; specpdl_ref count = SPECPDL_INDEX (); + bool pushed; + + pushed = false; - if (!dpyinfo) goto DONE; + if (!dpyinfo) + goto DONE; /* This is how the XDND protocol recommends dropping text onto a target that doesn't support XDND. */ @@ -794,6 +797,7 @@ x_handle_selection_request (struct selection_input_event *event) goto DONE; block_input (); + pushed = true; x_push_current_selection_request (event, dpyinfo); record_unwind_protect_void (x_pop_current_selection_request); record_unwind_protect_void (x_selection_request_lisp_error); @@ -854,7 +858,8 @@ x_handle_selection_request (struct selection_input_event *event) DONE: - selection_request_stack->converted = true; + if (pushed) + selection_request_stack->converted = true; if (success) x_reply_selection_request (event, dpyinfo); commit 3237d1d6b63c2a299f81dcb8b4f2833e00a7fedf Author: Po Lu Date: Wed Jun 8 10:40:20 2022 +0800 Improve drag-and-drop tests * lisp/dnd.el (dnd-begin-file-drag, dnd-begin-drag-files): Fix type of `x-xdnd-username'. * lisp/select.el (selection-converter-alist): Fix declaration of _DT_NETFILE converter. * test/lisp/dnd-tests.el (dnd-tests-verify-selection-data): Handle "compound" selection converters. (dnd-tests-parse-tt-netfile): New function. (dnd-tests-begin-file-drag, dnd-tests-begin-drag-files): Verify validity of file selection data. diff --git a/lisp/dnd.el b/lisp/dnd.el index 0f65b5228d..7eb43f5baa 100644 --- a/lisp/dnd.el +++ b/lisp/dnd.el @@ -423,7 +423,7 @@ currently being held down. It should only be called upon a (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" + "text/uri-list" "text/x-xdnd-username" ;; Traditional X selection targets used by ;; programs supporting the Motif ;; drag-and-drop protocols. Also used by NS @@ -493,7 +493,7 @@ FILES will be dragged." (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" + "text/uri-list" "text/x-xdnd-username" ;; Traditional X selection targets used by ;; programs supporting the Motif ;; drag-and-drop protocols. Also used by NS diff --git a/lisp/select.el b/lisp/select.el index 706197e027..417968b25c 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -819,8 +819,8 @@ VALUE should be SELECTION's local value." (_EMACS_INTERNAL . xselect-convert-to-identity) (XmTRANSFER_SUCCESS . xselect-convert-xm-special) (XmTRANSFER_FAILURE . xselect-convert-xm-special) - (_DT_NETFILE . (xselect-convert-to-dt-netfile - . xselect-dt-netfile-available-p)))) + (_DT_NETFILE . (xselect-dt-netfile-available-p + . xselect-convert-to-dt-netfile)))) (provide 'select) diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index a714c4a4e5..7a12cb8347 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -96,7 +96,7 @@ (or (get-text-property 0 type basic-value) basic-value) basic-value)) - (converter-list (assq type selection-converter-alist)) + (converter-list (cdr (assq type selection-converter-alist))) (converter (if (consp converter-list) (cdr converter-list) converter-list))) @@ -118,6 +118,30 @@ The temporary file is not created." (expand-file-name (make-temp-name "dnd-test-remote") dnd-tests-temporary-file-directory)) +(defun dnd-tests-parse-tt-netfile (netfile) + "Parse NETFILE and return its components. +NETFILE should be a canonicalized ToolTalk file name. +Return a list of its hostname, real path, and local path." + (save-match-data + (when (string-match (concat "HOST=0-\\([[:digit:]]+\\),RPATH=\\([[:digit:]]+\\)-" + "\\([[:digit:]]+\\),LPATH=\\([[:digit:]]+\\)-" + "\\([[:digit:]]+\\)\\(:\\)") + netfile) + (let ((beg (match-end 6))) + (list (substring netfile beg + (+ beg 1 + (string-to-number (match-string 1 netfile)))) + (substring netfile + (+ beg + (string-to-number (match-string 2 netfile))) + (+ beg 1 + (string-to-number (match-string 3 netfile)))) + (substring netfile + (+ beg + (string-to-number (match-string 4 netfile))) + (+ beg 1 + (string-to-number (match-string 5 netfile))))))))) + (ert-deftest dnd-tests-begin-text-drag () ;; ASCII Latin-1 UTF-8 (let ((test-text "hello, everyone! sæl öllsömul! всем привет")) @@ -159,6 +183,41 @@ The temporary file is not created." (progn ;; Now test dragging a normal file. (should (eq (dnd-begin-file-drag normal-temp-file) 'copy)) + ;; Test that the selection data is correct. + (let ((uri-list-data (cdr (dnd-tests-verify-selection-data 'text/uri-list))) + (username-data (dnd-tests-verify-selection-data 'text/x-xdnd-username)) + (file-name-data (cdr (dnd-tests-verify-selection-data 'FILE_NAME))) + (host-name-data (cdr (dnd-tests-verify-selection-data 'HOST_NAME))) + (netfile-data (cdr (dnd-tests-verify-selection-data '_DT_NETFILE)))) + ;; Check if the URI list is formatted correctly. + (let* ((split-uri-list (split-string uri-list-data "[\0\r\n]" t)) + (decoded (dnd-get-local-file-name (car split-uri-list)))) + (should (equal decoded normal-temp-file))) + ;; Test that the username reported is correct. + (should (equal username-data (user-real-login-name))) + ;; Test that the file name data is correct. + (let* ((split-file-names (split-string file-name-data "\0")) + (file-name (car split-file-names))) + ;; Make sure there are no extra leading or trailing NULL bytes. + (should (and split-file-names (null (cdr split-file-names)))) + ;; Make sure the file name is encoded correctly; + (should-not (multibyte-string-p file-name)) + ;; Make sure decoding the file name results in the + ;; originals. + (should (equal (decode-coding-string file-name + (or file-name-coding-system + default-file-name-coding-system)) + normal-temp-file)) + ;; Also make sure the hostname is correct. + (should (equal host-name-data (system-name)))) + ;; Check that the netfile hostname, rpath and lpath are correct. + (let ((parsed (dnd-tests-parse-tt-netfile netfile-data)) + (filename (encode-coding-string normal-temp-file + (or file-name-coding-system + default-file-name-coding-system)))) + (should (equal (nth 0 parsed) (system-name))) + (should (equal (nth 1 parsed) filename)) + (should (equal (nth 2 parsed) filename)))) ;; And the remote file. (should (eq (dnd-begin-file-drag remote-temp-file) 'copy)) ;; Test that the remote file was added to the list of files @@ -205,12 +264,43 @@ The temporary file is not created." ;; Test that the remote file produced was added to the list ;; of files to remove upon the next call. (should dnd-last-dragged-remote-file) - ;; Two remote files at the same time. + ;; Two local files at the same time. (should (eq (dnd-begin-drag-files (list normal-temp-file normal-temp-file-1)) 'copy)) ;; Test that the remote files were removed. (should-not dnd-last-dragged-remote-file) + ;; Test the selection data is correct. + (let ((uri-list-data (cdr (dnd-tests-verify-selection-data 'text/uri-list))) + (username-data (dnd-tests-verify-selection-data 'text/x-xdnd-username)) + (file-name-data (cdr (dnd-tests-verify-selection-data 'FILE_NAME))) + (host-name-data (cdr (dnd-tests-verify-selection-data 'HOST_NAME)))) + ;; Check if the URI list is formatted correctly. + (let* ((split-uri-list (split-string uri-list-data "[\0\r\n]" t)) + (decoded (mapcar #'dnd-get-local-file-name split-uri-list))) + (should (equal (car decoded) normal-temp-file)) + (should (equal (cadr decoded) normal-temp-file-1))) + ;; Test that the username reported is correct. + (should (equal username-data (user-real-login-name))) + ;; Test that the file name data is correct. + (let ((split-file-names (split-string file-name-data "\0"))) + ;; Make sure there are no extra leading or trailing NULL bytes. + (should (equal (length split-file-names) 2)) + ;; Make sure all file names are encoded correctly; + (dolist (name split-file-names) + (should-not (multibyte-string-p name))) + ;; Make sure decoding the file names result in the + ;; originals. + (should (equal (decode-coding-string (car split-file-names) + (or file-name-coding-system + default-file-name-coding-system)) + normal-temp-file)) + (should (equal (decode-coding-string (cadr split-file-names) + (or file-name-coding-system + default-file-name-coding-system)) + normal-temp-file-1)) + ;; Also make sure the hostname is correct. + (should (equal host-name-data (system-name))))) ;; Multiple local files with some remote files that will ;; fail, and some that won't. (should (and (eq (dnd-begin-drag-files (list normal-temp-file commit f3162b82406f2162a4208c6b626def14ba68a03a Author: Po Lu Date: Wed Jun 8 08:49:51 2022 +0800 More fixes to mouse event reporting during drag-and-drop * src/xterm.c (x_dnd_begin_drag_and_drop): Don't reset dpyinfo->grabbed when quitting. (handle_one_xevent): Keep track of dpyinfo->grabbed as well inside the drag-and-drop event loop. diff --git a/src/xterm.c b/src/xterm.c index 0bf4b15daf..f42f7cb1eb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11030,6 +11030,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_movement_frame = NULL; if (!NILP (Vx_dnd_movement_function) + && FRAME_LIVE_P (XFRAME (frame_object)) && !FRAME_TOOLTIP_P (XFRAME (frame_object)) && x_dnd_movement_x >= 0 && x_dnd_movement_y >= 0 @@ -11097,7 +11098,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, x_dnd_return_frame_object = NULL; x_dnd_movement_frame = NULL; - FRAME_DISPLAY_INFO (f)->grabbed = 0; + /* Don't clear dpyinfo->grabbed if we're quitting. */ + #ifdef USE_GTK current_hold_quit = NULL; #endif @@ -11184,6 +11186,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, FRAME_DISPLAY_INFO (f)->grabbed = 0; current_hold_quit = NULL; + block_input (); /* Restore the old event mask. */ XSelectInput (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, @@ -11197,6 +11200,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (x_dnd_motif_setup_p) XDeleteProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_DISPLAY_INFO (f)->Xatom_XdndSelection); + unblock_input (); + quit (); } #else @@ -17842,6 +17847,22 @@ handle_one_xevent (struct x_display_info *dpyinfo, <= x_dnd_recursion_depth) && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { + f = mouse_or_wdesc_frame (dpyinfo, event->xbutton.window); + + if (event->type == ButtonPress) + { + dpyinfo->grabbed |= (1 << event->xbutton.button); + dpyinfo->last_mouse_frame = f; + if (f && !tab_bar_p) + f->last_tab_bar_item = -1; +#if ! defined (USE_GTK) + if (f && !tool_bar_p) + f->last_tool_bar_item = -1; +#endif /* not USE_GTK */ + } + else + dpyinfo->grabbed &= ~(1 << event->xbutton.button); + if (event->xbutton.type == ButtonPress && x_dnd_last_seen_window != None && x_dnd_last_protocol_version != -1) @@ -19185,6 +19206,22 @@ handle_one_xevent (struct x_display_info *dpyinfo, <= x_dnd_recursion_depth) && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { + f = mouse_or_wdesc_frame (dpyinfo, xev->event); + + if (xev->evtype == XI_ButtonPress) + { + dpyinfo->grabbed |= (1 << xev->detail); + dpyinfo->last_mouse_frame = f; + if (f && !tab_bar_p) + f->last_tab_bar_item = -1; +#if ! defined (USE_GTK) + if (f && !tool_bar_p) + f->last_tool_bar_item = -1; +#endif /* not USE_GTK */ + } + else + dpyinfo->grabbed &= ~(1 << xev->detail); + if (xev->evtype == XI_ButtonPress && x_dnd_last_seen_window != None && x_dnd_last_protocol_version != -1) commit 88b025f8151f5552580b4fe8ace0897aac56ca71 Author: Dmitry Gutov Date: Wed Jun 8 01:08:22 2022 +0300 pcomplete-parse-arguments: Fix last change * lisp/pcomplete.el (pcomplete-parse-arguments): Throw the previous value of 'pcomplete-stub' (a list) rather than the newly constructed one (bug#50470). diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el index 3393c322e3..15b9880df8 100644 --- a/lisp/pcomplete.el +++ b/lisp/pcomplete.el @@ -806,7 +806,7 @@ this is `comint-dynamic-complete-functions'." ;; completions computed during parsing, e.g. Eshell uses ;; that to turn globs into lists of completions. (if (not pcomplete-allow-modifications) - (progn + (let ((completions pcomplete-stub)) ;; FIXME: The mapping from what's in the buffer to the list ;; of completions can be arbitrary and will often fail to be ;; understood by the completion style. See bug#50470. @@ -816,7 +816,7 @@ this is `comint-dynamic-complete-functions'." ;; "~/Down*" completion pattern since the completion ;; is neither told that it's a file nor a global pattern. (setq pcomplete-stub (buffer-substring begin (point))) - (throw 'pcomplete-completions pcomplete-stub)) + (throw 'pcomplete-completions completions)) (let* ((completions pcomplete-stub) (common-prefix (try-completion "" completions)) (len (length common-prefix))) commit ff2ce79f6cb76c8d2cf3a04e85b8059ad00a7436 Author: Juri Linkov Date: Tue Jun 7 21:47:51 2022 +0300 * doc/emacs/vc1-xtra.texi (Customizing VC): Remove deprecated Mtn. diff --git a/doc/emacs/vc1-xtra.texi b/doc/emacs/vc1-xtra.texi index 2d984f4b92..3ccad50715 100644 --- a/doc/emacs/vc1-xtra.texi +++ b/doc/emacs/vc1-xtra.texi @@ -269,7 +269,7 @@ with the file's version control type. @vindex vc-handled-backends The variable @code{vc-handled-backends} determines which version control systems VC should handle. The default value is @code{(RCS CVS -SVN SCCS SRC Bzr Git Hg Mtn)}, so it contains all the version systems +SVN SCCS SRC Bzr Git Hg)}, so it contains all the version systems that are currently supported. If you want VC to ignore one or more of these systems, exclude its name from the list. To disable VC entirely, set this variable to @code{nil}. commit d003848b5e3ad2dfbe84cc62b99776fdc6734325 Author: Lars Ingebrigtsen Date: Tue Jun 7 20:28:05 2022 +0200 Give ,@ a prefix syntax in elisp-mode * lisp/progmodes/elisp-mode.el (elisp-mode-syntax-propertize): Give ,@ a prefix syntax so that we can properly identify symbols that follow it, i.e., ,@foo (bug#44418). diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 77bf3f1ed1..210270bc67 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -245,6 +245,9 @@ Comments in the form will be lost." ;; Empty symbol. ("##" (0 (unless (nth 8 (syntax-ppss)) (string-to-syntax "_")))) + ;; Give ,@ a prefix syntax. + (",@" (0 (unless (ppss-comment-or-string-start (syntax-ppss)) + (string-to-syntax "'")))) ;; Unicode character names. (The longest name is 88 characters ;; long.) ("\\?\\\\N{[-A-Za-z0-9 ]\\{,100\\}}" commit 6a9ff1c6386d8e6d8a245cdcf01038377c25828e Author: Lars Ingebrigtsen Date: Tue Jun 7 20:03:41 2022 +0200 Demote extended attribute errors in basic-save-buffer-2 * lisp/files.el (basic-save-buffer-2): Give demoted errors when reading extended attributes that fail (bug#43723). diff --git a/lisp/files.el b/lisp/files.el index d876a76119..a505f62af8 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -5725,11 +5725,14 @@ Before and after saving the buffer, this function runs (signal (car err) (cdr err)))) ;; Since we have created an entirely new file, ;; make sure it gets the right permission bits set. - (setq setmodes (or setmodes - (list (or (file-modes buffer-file-name) - (logand ?\666 (default-file-modes))) - (file-extended-attributes buffer-file-name) - buffer-file-name))) + (setq setmodes + (or setmodes + (list (or (file-modes buffer-file-name) + (logand ?\666 (default-file-modes))) + (with-demoted-errors + "Error getting extended attributes: %s" + (file-extended-attributes buffer-file-name)) + buffer-file-name))) ;; We succeeded in writing the temp file, ;; so rename it. (rename-file tempname @@ -5746,9 +5749,12 @@ Before and after saving the buffer, this function runs ;; (setmodes is set) because that says we're superseding. (cond ((and tempsetmodes (not setmodes)) ;; Change the mode back, after writing. - (setq setmodes (list (file-modes buffer-file-name) - (file-extended-attributes buffer-file-name) - buffer-file-name)) + (setq setmodes + (list (file-modes buffer-file-name) + (with-demoted-errors + "Error getting extended attributes: %s" + (file-extended-attributes buffer-file-name)) + buffer-file-name)) ;; If set-file-extended-attributes fails, fall back on ;; set-file-modes. (unless commit be02a32f475a5f3c0902a397aaeb5717eaa73c90 Author: Lars Ingebrigtsen Date: Tue Jun 7 18:59:44 2022 +0200 Regenerated ldefs-boot.el This is the first check-in after the loaddefs-gen.el rewrite. diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el index d63c006678..f4e9d2732f 100644 --- a/lisp/ldefs-boot.el +++ b/lisp/ldefs-boot.el @@ -1,13 +1,17 @@ -;;; loaddefs.el --- automatically extracted autoloads -*- lexical-binding: t -*- -;; This file will be copied to ldefs-boot.el and checked in periodically. -;; +;;; loaddefs.el --- automatically extracted autoloads (do not edit) -*- lexical-binding: t -*- +;; Generated by the `loaddefs-generate' function. + +;; This file is part of GNU Emacs. + +;;; Commentary: + +;; This file will be copied to ldefs-boot.el and checked in +;; periodically. + ;;; Code: -(autoload 'loaddefs-generate "loaddefs-gen") -(autoload 'loaddefs-generate-batch "loaddefs-gen") -;;;### (autoloads nil "5x5" "play/5x5.el" (0 0 0 0)) ;;; Generated autoloads from play/5x5.el (autoload '5x5 "5x5" "\ @@ -34,21 +38,16 @@ Rotate left Calc Solutions \\[5x5-solve-rotate-left] Rotate right Calc Solutions \\[5x5-solve-rotate-right] Quit current game \\[5x5-quit-game] -\(fn &optional SIZE)" t nil) - +(fn &optional SIZE)" t nil) (autoload '5x5-crack-randomly "5x5" "\ Attempt to crack 5x5 using random solutions." t nil) - (autoload '5x5-crack-mutating-current "5x5" "\ Attempt to crack 5x5 by mutating the current solution." t nil) - (autoload '5x5-crack-mutating-best "5x5" "\ Attempt to crack 5x5 by mutating the best solution." t nil) - (autoload '5x5-crack-xor-mutate "5x5" "\ Attempt to crack 5x5 by xoring the current and best solution. Mutate the result." t nil) - (autoload '5x5-crack "5x5" "\ Attempt to find a solution for 5x5. @@ -57,50 +56,39 @@ two parameters, the first will be a grid vector array that is the current solution and the second will be the best solution so far. The function should return a grid vector array that is the new solution. -\(fn BREEDER)" t nil) - +(fn BREEDER)" t nil) (register-definition-prefixes "5x5" '("5x5-")) -;;;*** -;;;### (autoloads nil "add-log" "vc/add-log.el" (0 0 0 0)) ;;; Generated autoloads from vc/add-log.el (put 'change-log-default-name 'safe-local-variable #'string-or-null-p) - (defvar add-log-current-defun-function nil "\ If non-nil, function to guess name of surrounding function. It is called by `add-log-current-defun' with no argument, and should return the function's name as a string, or nil if point is outside a function.") - (custom-autoload 'add-log-current-defun-function "add-log" t) - (defvar add-log-full-name nil "\ Full name of user, for inclusion in ChangeLog daily headers. This defaults to the value returned by the function `user-full-name'.") - (custom-autoload 'add-log-full-name "add-log" t) - (defvar add-log-mailing-address nil "\ Email addresses of user, for inclusion in ChangeLog headers. This defaults to the value of `user-mail-address'. In addition to being a simple string, this value can also be a list. All elements will be recognized as referring to the same user; when creating a new ChangeLog entry, one element will be chosen at random.") - (custom-autoload 'add-log-mailing-address "add-log" t) - (autoload 'prompt-for-change-log-name "add-log" "\ Prompt for a change log name." nil nil) - (autoload 'find-change-log "add-log" "\ Find a change log file for \\[add-change-log-entry] and return the name. Optional arg FILE-NAME specifies the file to use. If FILE-NAME is nil, use the value of `change-log-default-name'. If `change-log-default-name' is nil, behave as though it were \"ChangeLog\" -\(or whatever we use on this operating system). +(or whatever we use on this operating system). If `change-log-default-name' contains a leading directory component, then simply find it in the current directory. Otherwise, search in the current @@ -114,8 +102,7 @@ Once a file is found, `change-log-default-name' is set locally in the current buffer to the complete file name. Optional arg BUFFER-FILE overrides `buffer-file-name'. -\(fn &optional FILE-NAME BUFFER-FILE)" nil nil) - +(fn &optional FILE-NAME BUFFER-FILE)" nil nil) (autoload 'add-change-log-entry "add-log" "\ Find ChangeLog buffer, add an entry for today and an item for this file. Optional arg WHOAMI (interactive prefix) non-nil means prompt for @@ -151,15 +138,13 @@ notices. Today's date is calculated according to `add-log-time-zone-rule' if non-nil, otherwise in local time. -\(fn &optional WHOAMI CHANGELOG-FILE-NAME OTHER-WINDOW NEW-ENTRY PUT-NEW-ENTRY-ON-NEW-LINE)" t nil) - +(fn &optional WHOAMI CHANGELOG-FILE-NAME OTHER-WINDOW NEW-ENTRY PUT-NEW-ENTRY-ON-NEW-LINE)" t nil) (autoload 'add-change-log-entry-other-window "add-log" "\ Find change log file in other window and add entry and item. This is just like `add-change-log-entry' except that it displays the change log file in another window. -\(fn &optional WHOAMI FILE-NAME)" t nil) - +(fn &optional WHOAMI FILE-NAME)" t nil) (autoload 'change-log-mode "add-log" "\ Major mode for editing change logs; like Indented Text mode. Prevents numeric backups and sets `left-margin' to 8 and `fill-column' to 74. @@ -169,8 +154,7 @@ Runs `change-log-mode-hook'. \\{change-log-mode-map} -\(fn)" t nil) - +(fn)" t nil) (autoload 'add-log-current-defun "add-log" "\ Return name of function definition point is in, or nil. @@ -184,7 +168,6 @@ identifiers followed by `:' or `='. See variables `add-log-current-defun-function'. Has a preference of looking backwards." nil nil) - (autoload 'change-log-merge "add-log" "\ Merge the contents of change log file OTHER-LOG with this buffer. Both must be found in Change Log mode (since the merging depends on @@ -194,13 +177,10 @@ or a buffer. Entries are inserted in chronological order. Both the current and old-style time formats for entries are supported. -\(fn OTHER-LOG)" t nil) - +(fn OTHER-LOG)" t nil) (register-definition-prefixes "add-log" '("add-log-" "change-log-")) -;;;*** -;;;### (autoloads nil "advice" "emacs-lisp/advice.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/advice.el (defvar ad-redefinition-action 'warn "\ @@ -213,9 +193,7 @@ old original, or keep it and raise an error. The values `accept', `discard', `error' or `warn' govern what will be done. `warn' is just like `accept' but it additionally prints a warning message. All other values will be interpreted as `error'.") - (custom-autoload 'ad-redefinition-action "advice" t) - (defvar ad-default-compilation-action 'maybe "\ Defines whether to compile advised definitions during activation. A value of `always' will result in unconditional compilation, `never' will @@ -224,19 +202,15 @@ loaded, and `like-original' will compile if the original definition of the advised function is compiled or a built-in function. Every other value will be interpreted as `maybe'. This variable will only be considered if the COMPILE argument of `ad-activate' was supplied as nil.") - (custom-autoload 'ad-default-compilation-action "advice" t) - (autoload 'ad-enable-advice "advice" "\ Enables the advice of FUNCTION with CLASS and NAME. -\(fn FUNCTION CLASS NAME)" t nil) - +(fn FUNCTION CLASS NAME)" t nil) (autoload 'ad-disable-advice "advice" "\ Disable the advice of FUNCTION with CLASS and NAME. -\(fn FUNCTION CLASS NAME)" t nil) - +(fn FUNCTION CLASS NAME)" t nil) (autoload 'ad-add-advice "advice" "\ Add a piece of ADVICE to FUNCTION's list of advices in CLASS. @@ -260,8 +234,7 @@ If FUNCTION was not advised already, its advice info will be initialized. Redefining a piece of advice whose name is part of the cache-id will clear the cache. -\(fn FUNCTION ADVICE CLASS POSITION)" nil nil) - +(fn FUNCTION ADVICE CLASS POSITION)" nil nil) (autoload 'ad-activate "advice" "\ Activate all the advice information of an advised FUNCTION. If FUNCTION has a proper original definition then an advised @@ -279,8 +252,7 @@ an advised function that has actual pieces of advice but none of them are enabled is equivalent to a call to `ad-deactivate'. The current advised definition will always be cached for later usage. -\(fn FUNCTION &optional COMPILE)" t nil) - +(fn FUNCTION &optional COMPILE)" t nil) (autoload 'defadvice "advice" "\ Define a piece of advice for FUNCTION (a symbol). The syntax of `defadvice' is as follows: @@ -327,17 +299,12 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...) [DOCSTRING] [INTERACTIVE-FORM] BODY...) -\(fn FUNCTION ARGS &rest BODY)" nil t) - +(fn FUNCTION ARGS &rest BODY)" nil t) (function-put 'defadvice 'doc-string-elt '3) - (function-put 'defadvice 'lisp-indent-function '2) - (register-definition-prefixes "advice" '("ad-")) -;;;*** -;;;### (autoloads nil "align" "align.el" (0 0 0 0)) ;;; Generated autoloads from align.el (autoload 'align "align" "\ @@ -368,8 +335,7 @@ default rule lists defined in `align-rules-list' and `align-exclude-rules-list'. See `align-rules-list' for more details on the format of these lists. -\(fn BEG END &optional SEPARATE RULES EXCLUDE-RULES)" t nil) - +(fn BEG END &optional SEPARATE RULES EXCLUDE-RULES)" t nil) (autoload 'align-regexp "align" "\ Align the current region using an ad-hoc rule read from the minibuffer. BEG and END mark the limits of the region. Interactively, this function @@ -412,8 +378,7 @@ The non-interactive form of the previous example would look something like: This function is a nothing more than a small wrapper that helps you construct a rule to pass to `align-region', which does the real work. -\(fn BEG END REGEXP &optional GROUP SPACING REPEAT)" t nil) - +(fn BEG END REGEXP &optional GROUP SPACING REPEAT)" t nil) (autoload 'align-entire "align" "\ Align the selected region as if it were one alignment section. BEG and END mark the extent of the region. If RULES or EXCLUDE-RULES @@ -421,8 +386,7 @@ is set to a list of rules (see `align-rules-list'), it can be used to override the default alignment rules that would have been used to align that section. -\(fn BEG END &optional RULES EXCLUDE-RULES)" t nil) - +(fn BEG END &optional RULES EXCLUDE-RULES)" t nil) (autoload 'align-current "align" "\ Call `align' on the current alignment section. This function assumes you want to align only the current section, and @@ -431,8 +395,7 @@ EXCLUDE-RULES is set to a list of rules (see `align-rules-list'), it can be used to override the default alignment rules that would have been used to align that section. -\(fn &optional RULES EXCLUDE-RULES)" t nil) - +(fn &optional RULES EXCLUDE-RULES)" t nil) (autoload 'align-highlight-rule "align" "\ Highlight the whitespace which a given rule would have modified. BEG and END mark the extent of the region. TITLE identifies the rule @@ -441,31 +404,25 @@ list of rules (see `align-rules-list'), it can be used to override the default alignment rules that would have been used to identify the text to be colored. -\(fn BEG END TITLE &optional RULES EXCLUDE-RULES)" t nil) - +(fn BEG END TITLE &optional RULES EXCLUDE-RULES)" t nil) (autoload 'align-unhighlight-rule "align" "\ Remove any highlighting that was added by `align-highlight-rule'." t nil) - (autoload 'align-newline-and-indent "align" "\ A replacement function for `newline-and-indent', aligning as it goes. The alignment is done by calling `align' on the region that was indented." t nil) - (register-definition-prefixes "align" '("align-")) -;;;*** -;;;### (autoloads nil "allout" "allout.el" (0 0 0 0)) ;;; Generated autoloads from allout.el -(push (purecopy '(allout 2 3)) package--builtin-versions) +(push (purecopy '(allout 2 3)) package--builtin-versions) (autoload 'allout-auto-activation-helper "allout" "\ Institute `allout-auto-activation'. Intended to be used as the `allout-auto-activation' :set function. -\(fn VAR VALUE)" nil nil) - +(fn VAR VALUE)" nil nil) (autoload 'allout-setup "allout" "\ Do fundamental Emacs session for allout auto-activation. @@ -474,7 +431,6 @@ Establishes allout processing as part of visiting a file if The proper way to use this is through customizing the setting of `allout-auto-activation'." nil nil) - (defvar allout-auto-activation nil "\ Configure allout outline mode auto-activation. @@ -493,40 +449,23 @@ With value \"activate\", only auto-mode-activation is enabled. Auto-layout is not. With value nil, inhibit any automatic allout-mode activation.") - (custom-autoload 'allout-auto-activation "allout" nil) - (put 'allout-use-hanging-indents 'safe-local-variable #'booleanp) - (put 'allout-reindent-bodies 'safe-local-variable (lambda (x) (memq x '(nil t text force)))) - (put 'allout-show-bodies 'safe-local-variable #'booleanp) - (put 'allout-header-prefix 'safe-local-variable #'stringp) - (put 'allout-primary-bullet 'safe-local-variable #'stringp) - (put 'allout-plain-bullets-string 'safe-local-variable #'stringp) - (put 'allout-distinctive-bullets-string 'safe-local-variable #'stringp) - (put 'allout-use-mode-specific-leader 'safe-local-variable (lambda (x) (or (memq x '(t nil allout-mode-leaders comment-start)) (stringp x)))) - (put 'allout-old-style-prefixes 'safe-local-variable #'booleanp) - (put 'allout-stylish-prefixes 'safe-local-variable #'booleanp) - (put 'allout-numbered-bullet 'safe-local-variable #'string-or-null-p) - (put 'allout-file-xref-bullet 'safe-local-variable #'string-or-null-p) - (put 'allout-presentation-padding 'safe-local-variable #'integerp) - (put 'allout-layout 'safe-local-variable (lambda (x) (or (numberp x) (listp x) (memq x '(: * + -))))) - (autoload 'allout-mode-p "allout" "\ Return t if `allout-mode' is active in current buffer." nil t) - (autoload 'allout-mode "allout" "\ Toggle Allout outline mode. @@ -677,7 +616,7 @@ When the text cursor is positioned directly on the bullet character of a topic, regular characters (a to z) invoke the commands of the corresponding allout-mode keymap control chars. For example, \"f\" would invoke the command typically bound to \"C-cC-f\" -\(\\[allout-forward-current-level] `allout-forward-current-level'). +(\\[allout-forward-current-level] `allout-forward-current-level'). Thus, by positioning the cursor on a topic bullet, you can execute the outline navigation and manipulation commands with a @@ -690,7 +629,7 @@ replaced with one that makes it easy to get to the hot-spot. If you repeat it immediately it cycles (if `allout-beginning-of-line-cycles' is set) to the beginning of the item and then, if you hit it again immediately, to the hot-spot. Similarly, `allout-beginning-of-current-entry' -\(\\[allout-beginning-of-current-entry]) moves to the hot-spot when the cursor is already located +(\\[allout-beginning-of-current-entry]) moves to the hot-spot when the cursor is already located at the beginning of the current entry. Extending Allout @@ -804,34 +743,27 @@ evaluate `allout-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (defalias 'outlinify-sticky #'outlineify-sticky) - (autoload 'outlineify-sticky "allout" "\ Activate outline mode and establish file var so it is started subsequently. See `allout-layout' and customization of `allout-auto-activation' for details on preparing Emacs for automatic allout activation. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "allout" '("allout-")) -;;;*** -;;;### (autoloads nil "allout-widgets" "allout-widgets.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from allout-widgets.el -(push (purecopy '(allout-widgets 1 0)) package--builtin-versions) +(push (purecopy '(allout-widgets 1 0)) package--builtin-versions) (autoload 'allout-widgets-setup "allout-widgets" "\ Commission or decommission allout-widgets-mode along with allout-mode. Meant to be used by customization of `allout-widgets-auto-activation'. -\(fn VARNAME VALUE)" nil nil) - +(fn VARNAME VALUE)" nil nil) (defvar allout-widgets-auto-activation nil "\ Activate to enable allout icon graphics wherever allout mode is active. @@ -846,11 +778,8 @@ explicitly invoke `allout-widgets-mode' in allout buffers where you want allout widgets operation. See `allout-widgets-mode' for allout widgets mode features.") - (custom-autoload 'allout-widgets-auto-activation "allout-widgets" nil) - (put 'allout-widgets-mode-inhibit 'safe-local-variable #'booleanp) - (autoload 'allout-widgets-mode "allout-widgets" "\ Toggle Allout Widgets mode. @@ -886,17 +815,18 @@ evaluate `allout-widgets-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "allout-widgets" '("allout-")) -;;;*** -;;;### (autoloads nil "ange-ftp" "net/ange-ftp.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/analyze.el + +(register-definition-prefixes "semantic/analyze" '("semantic-a")) + + ;;; Generated autoloads from net/ange-ftp.el (defalias 'ange-ftp-re-read-dir 'ange-ftp-reread-dir) - (autoload 'ange-ftp-reread-dir "ange-ftp" "\ Reread remote directory DIR to update the directory cache. The implementation of remote FTP file names caches directory contents @@ -904,18 +834,14 @@ for speed. Therefore, when new remote files are created, Emacs may not know they exist. You can use this command to reread a specific directory, so that Emacs will know its current contents. -\(fn &optional DIR)" t nil) - +(fn &optional DIR)" t nil) (autoload 'ange-ftp-hook-function "ange-ftp" "\ -\(fn OPERATION &rest ARGS)" nil nil) - +(fn OPERATION &rest ARGS)" nil nil) (register-definition-prefixes "ange-ftp" '("ange-ftp-" "ftp-error" "internal-ange-ftp-mode")) -;;;*** -;;;### (autoloads nil "animate" "play/animate.el" (0 0 0 0)) ;;; Generated autoloads from play/animate.el (autoload 'animate-string "animate" "\ @@ -926,8 +852,7 @@ passing through `animate-n-steps' positions before the final ones. If HPOS is nil (or omitted), center the string horizontally in the current window. -\(fn STRING VPOS &optional HPOS)" nil nil) - +(fn STRING VPOS &optional HPOS)" nil nil) (autoload 'animate-sequence "animate" "\ Display animation strings from LIST-OF-STRING with buffer *Animation*. Strings will be separated from each other by SPACE lines. @@ -935,27 +860,22 @@ Strings will be separated from each other by SPACE lines. animation in the buffer named by variable's value, creating the buffer if one does not exist. -\(fn LIST-OF-STRINGS SPACE)" nil nil) - +(fn LIST-OF-STRINGS SPACE)" nil nil) (autoload 'animate-birthday-present "animate" "\ Return a birthday present in the buffer *Birthday-Present*. When optional arg NAME is non-nil or called-interactively, prompt for NAME of birthday present receiver and return a birthday present in the buffer *Birthday-Present-for-Name*. -\(fn &optional NAME)" t nil) - +(fn &optional NAME)" t nil) (register-definition-prefixes "animate" '("animat")) -;;;*** -;;;### (autoloads nil "ansi-color" "ansi-color.el" (0 0 0 0)) ;;; Generated autoloads from ansi-color.el -(push (purecopy '(ansi-color 3 4 2)) package--builtin-versions) +(push (purecopy '(ansi-color 3 4 2)) package--builtin-versions) (autoload 'ansi-color-for-comint-mode-on "ansi-color" "\ Set `ansi-color-for-comint-mode' to t." t nil) - (autoload 'ansi-color-process-output "ansi-color" "\ Maybe translate SGR control sequences of comint output into text properties. @@ -969,22 +889,17 @@ The comint output is assumed to lie between the marker This is a good function to put in `comint-output-filter-functions'. -\(fn IGNORED)" nil nil) - +(fn IGNORED)" nil nil) (autoload 'ansi-color-compilation-filter "ansi-color" "\ Maybe translate SGR control sequences into text properties. This function depends on the `ansi-color-for-compilation-mode' variable, and is meant to be used in `compilation-filter-hook'." nil nil) - (register-definition-prefixes "ansi-color" '("ansi-color-")) -;;;*** -;;;### (autoloads nil "antlr-mode" "progmodes/antlr-mode.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from progmodes/antlr-mode.el -(push (purecopy '(antlr-mode 2 2 3)) package--builtin-versions) +(push (purecopy '(antlr-mode 2 2 3)) package--builtin-versions) (autoload 'antlr-show-makefile-rules "antlr-mode" "\ Show Makefile rules for all grammar files in the current directory. If the `major-mode' of the current buffer has the value `makefile-mode', @@ -1001,21 +916,16 @@ If the file for a super-grammar cannot be determined, special file names are used according to variable `antlr-unknown-file-formats' and a commentary with value `antlr-help-unknown-file-text' is added. The *Help* buffer always starts with the text in `antlr-help-rules-intro'." t nil) - (autoload 'antlr-mode "antlr-mode" "\ Major mode for editing ANTLR grammar files. -\(fn)" t nil) - +(fn)" t nil) (autoload 'antlr-set-tabs "antlr-mode" "\ Use ANTLR's convention for TABs according to `antlr-tab-offset-alist'. Used in `antlr-mode'. Also a useful function in `java-mode-hook'." nil nil) - (register-definition-prefixes "antlr-mode" '("antlr-")) -;;;*** -;;;### (autoloads nil "appt" "calendar/appt.el" (0 0 0 0)) ;;; Generated autoloads from calendar/appt.el (autoload 'appt-add "appt" "\ @@ -1025,20 +935,16 @@ Optional argument WARNTIME is an integer (or string) giving the number of minutes before the appointment at which to start warning. The default is `appt-message-warning-time'. -\(fn TIME MSG &optional WARNTIME)" t nil) - +(fn TIME MSG &optional WARNTIME)" t nil) (autoload 'appt-activate "appt" "\ Toggle checking of appointments. With optional numeric argument ARG, turn appointment checking on if ARG is positive, otherwise off. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "appt" '("appt-")) -;;;*** -;;;### (autoloads nil "apropos" "apropos.el" (0 0 0 0)) ;;; Generated autoloads from apropos.el (autoload 'apropos-read-pattern "apropos" "\ @@ -1049,8 +955,7 @@ literally, or a string which is used as a regexp to search for. SUBJECT is a string that is included in the prompt to identify what kind of objects to search. -\(fn SUBJECT)" nil nil) - +(fn SUBJECT)" nil nil) (autoload 'apropos-user-option "apropos" "\ Show user options that match PATTERN. PATTERN can be a word, a list of words (separated by spaces), @@ -1061,16 +966,14 @@ search for matches for any two (or more) of those words. With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil, also show variables, not just user options. -\(fn PATTERN &optional DO-ALL)" t nil) - +(fn PATTERN &optional DO-ALL)" t nil) (autoload 'apropos-variable "apropos" "\ Show variables that match PATTERN. With the optional argument DO-NOT-ALL non-nil (or when called interactively with the prefix \\[universal-argument]), show user options only, i.e. behave like `apropos-user-option'. -\(fn PATTERN &optional DO-NOT-ALL)" t nil) - +(fn PATTERN &optional DO-NOT-ALL)" t nil) (autoload 'apropos-local-variable "apropos" "\ Show buffer-local variables that match PATTERN. Optional arg BUFFER (default: current buffer) is the buffer to check. @@ -1078,8 +981,7 @@ Optional arg BUFFER (default: current buffer) is the buffer to check. The output includes variables that are not yet set in BUFFER, but that will be buffer-local when set. -\(fn PATTERN &optional BUFFER)" t nil) - +(fn PATTERN &optional BUFFER)" t nil) (autoload 'apropos-function "apropos" "\ Show functions that match PATTERN. @@ -1091,10 +993,8 @@ search for matches for any two (or more) of those words. This is the same as running `apropos-command' with a \\[universal-argument] prefix, or a non-nil `apropos-do-all' argument. -\(fn PATTERN)" t nil) - +(fn PATTERN)" t nil) (defalias 'command-apropos #'apropos-command) - (autoload 'apropos-command "apropos" "\ Show commands (interactively callable functions) that match PATTERN. PATTERN can be a word, a list of words (separated by spaces), @@ -1111,13 +1011,11 @@ satisfy the predicate VAR-PREDICATE. When called from a Lisp program, a string PATTERN is used as a regexp, while a list of strings is used as a word list. -\(fn PATTERN &optional DO-ALL VAR-PREDICATE)" t nil) - +(fn PATTERN &optional DO-ALL VAR-PREDICATE)" t nil) (autoload 'apropos-documentation-property "apropos" "\ Like (documentation-property SYMBOL PROPERTY RAW) but handle errors. -\(fn SYMBOL PROPERTY RAW)" nil nil) - +(fn SYMBOL PROPERTY RAW)" nil nil) (autoload 'apropos "apropos" "\ Show all meaningful Lisp symbols whose names match PATTERN. Symbols are shown if they are defined as functions, variables, or @@ -1136,16 +1034,14 @@ Return list of symbols and documentation found. The *Apropos* window will be selected if `help-window-select' is non-nil. -\(fn PATTERN &optional DO-ALL)" t nil) - +(fn PATTERN &optional DO-ALL)" t nil) (autoload 'apropos-library "apropos" "\ List the variables and functions defined by library FILE. FILE should be one of the libraries currently loaded and should thus be found in `load-history'. If `apropos-do-all' is non-nil, the output includes key-bindings of commands. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'apropos-value "apropos" "\ Show all symbols whose value's printed representation matches PATTERN. PATTERN can be a word, a list of words (separated by spaces), @@ -1159,15 +1055,13 @@ names and values of properties. Returns list of symbols and values found. -\(fn PATTERN &optional DO-ALL)" t nil) - +(fn PATTERN &optional DO-ALL)" t nil) (autoload 'apropos-local-value "apropos" "\ Show buffer-local variables whose values match PATTERN. This is like `apropos-value', but only for buffer-local variables. Optional arg BUFFER (default: current buffer) is the buffer to check. -\(fn PATTERN &optional BUFFER)" t nil) - +(fn PATTERN &optional BUFFER)" t nil) (autoload 'apropos-documentation "apropos" "\ Show symbols whose documentation contains matches for PATTERN. PATTERN can be a word, a list of words (separated by spaces), @@ -1182,13 +1076,10 @@ documentation strings. Returns list of symbols and documentation found. -\(fn PATTERN &optional DO-ALL)" t nil) - +(fn PATTERN &optional DO-ALL)" t nil) (register-definition-prefixes "apropos" '("apropos-")) -;;;*** -;;;### (autoloads nil "arc-mode" "arc-mode.el" (0 0 0 0)) ;;; Generated autoloads from arc-mode.el (autoload 'archive-mode "arc-mode" "\ @@ -1204,13 +1095,15 @@ archive. \\{archive-mode-map} -\(fn &optional FORCE)" nil nil) - +(fn &optional FORCE)" nil nil) (register-definition-prefixes "arc-mode" '("arc")) -;;;*** -;;;### (autoloads nil "array" "array.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/args.el + +(register-definition-prefixes "srecode/args" '("srecode-")) + + ;;; Generated autoloads from array.el (autoload 'array-mode "array" "\ @@ -1280,13 +1173,10 @@ take a numeric prefix argument): Entering array mode calls the function `array-mode-hook'. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "array" '("array-" "current-line" "limit-index" "move-to-column-untabify" "untabify-backward")) -;;;*** -;;;### (autoloads nil "artist" "textmodes/artist.el" (0 0 0 0)) ;;; Generated autoloads from textmodes/artist.el (autoload 'artist-mode "artist" "\ @@ -1501,13 +1391,10 @@ evaluate `artist-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "artist" '("artist-")) -;;;*** -;;;### (autoloads nil "asm-mode" "progmodes/asm-mode.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/asm-mode.el (autoload 'asm-mode "asm-mode" "\ @@ -1530,21 +1417,16 @@ Turning on Asm mode runs the hook `asm-mode-hook' at the end of initialization. Special commands: \\{asm-mode-map} -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "asm-mode" '("asm-")) -;;;*** -;;;### (autoloads nil "auth-source" "auth-source.el" (0 0 0 0)) ;;; Generated autoloads from auth-source.el (defvar auth-source-cache-expiry 7200 "\ How many seconds passwords are cached, or nil to disable expiring. Overrides `password-cache-expiry' through a let-binding.") - (custom-autoload 'auth-source-cache-expiry "auth-source" t) - (autoload 'authinfo-mode "auth-source" "\ Mode for editing .authinfo/.netrc files. @@ -1554,20 +1436,15 @@ point is moved into the passwords (see `authinfo-hide-elements'). \\{authinfo-mode-map} -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "auth-source" '("auth")) -;;;*** -;;;### (autoloads nil "auth-source-pass" "auth-source-pass.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from auth-source-pass.el -(push (purecopy '(auth-source-pass 5 0 0)) package--builtin-versions) +(push (purecopy '(auth-source-pass 5 0 0)) package--builtin-versions) (autoload 'auth-source-pass-enable "auth-source-pass" "\ Enable auth-source-password-store." nil nil) - (autoload 'auth-source-pass-get "auth-source-pass" "\ Return the value associated to KEY in the password-store entry ENTRY. @@ -1581,40 +1458,41 @@ secret key1: value1 key2: value2 -\(fn KEY ENTRY)" nil nil) - +(fn KEY ENTRY)" nil nil) (register-definition-prefixes "auth-source-pass" '("auth-source-pass-")) -;;;*** -;;;### (autoloads nil "autoconf" "progmodes/autoconf.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/auto.el + +(register-definition-prefixes "ede/auto" '("ede-")) + + ;;; Generated autoloads from progmodes/autoconf.el (autoload 'autoconf-mode "autoconf" "\ Major mode for editing Autoconf configure.ac files. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "autoconf" '("autoconf-")) -;;;*** -;;;### (autoloads nil "autoinsert" "autoinsert.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/autoconf-edit.el + +(register-definition-prefixes "ede/autoconf-edit" '("autoconf-")) + + ;;; Generated autoloads from autoinsert.el (autoload 'auto-insert "autoinsert" "\ Insert default contents into new files if variable `auto-insert' is non-nil. Matches the visited file name against the elements of `auto-insert-alist'." t nil) - (autoload 'define-auto-insert "autoinsert" "\ Associate CONDITION with (additional) ACTION in `auto-insert-alist'. Optional AFTER means to insert action after all existing actions for CONDITION, or if CONDITION had no actions, after all other CONDITIONs. -\(fn CONDITION ACTION &optional AFTER)" nil nil) - +(fn CONDITION ACTION &optional AFTER)" nil nil) (function-put 'define-auto-insert 'lisp-indent-function 'defun) - (defvar auto-insert-mode nil "\ Non-nil if Auto-Insert mode is enabled. See the `auto-insert-mode' command @@ -1622,9 +1500,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `auto-insert-mode'.") - (custom-autoload 'auto-insert-mode "autoinsert" nil) - (autoload 'auto-insert-mode "autoinsert" "\ Toggle Auto-insert mode, a global minor mode. @@ -1645,22 +1521,13 @@ evaluate `(default-value \\='auto-insert-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "autoinsert" '("auto-insert")) -;;;*** -;;;### (autoloads nil "autoload" "emacs-lisp/autoload.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from emacs-lisp/autoload.el -(put 'generated-autoload-file 'safe-local-variable 'stringp) - -(put 'generated-autoload-load-name 'safe-local-variable 'stringp) - (put 'autoload-ensure-writable 'risky-local-variable t) - (autoload 'update-file-autoloads "autoload" "\ Update the autoloads for FILE. If prefix arg SAVE-AFTER is non-nil, save the buffer too. @@ -1673,8 +1540,7 @@ existing value of `generated-autoload-file'. Return FILE if there was no autoload cookie in it, else nil. -\(fn FILE &optional SAVE-AFTER OUTFILE)" t nil) - +(fn FILE &optional SAVE-AFTER OUTFILE)" t nil) (autoload 'update-directory-autoloads "autoload" "\ Update autoload definitions for Lisp files in the directories DIRS. In an interactive call, you must give one argument, the name of a @@ -1690,10 +1556,8 @@ value of `generated-autoload-file'. If any Lisp file binds `generated-autoload-file' as a file-local variable, write its autoloads into the specified file instead. -\(fn &rest DIRS)" t nil) - +(fn &rest DIRS)" t nil) (make-obsolete 'update-directory-autoloads 'make-directory-autoloads '"28.1") - (autoload 'make-directory-autoloads "autoload" "\ Update autoload definitions for Lisp files in the directories DIRS. DIR can be either a single directory or a list of @@ -1706,19 +1570,15 @@ its autoloads into the specified file instead. The function does NOT recursively descend into subdirectories of the directory or directories specified. -\(fn DIR OUTPUT-FILE)" t nil) - +(fn DIR OUTPUT-FILE)" t nil) (autoload 'batch-update-autoloads "autoload" "\ Update loaddefs.el autoloads in batch mode. Calls `update-directory-autoloads' on the command line arguments. Definitions are written to `generated-autoload-file' (which should be non-nil)." nil nil) +(register-definition-prefixes "autoload" '("autoload-" "batch-update-autoloads--summary" "generate-" "make-autoload" "no-update-autoloads")) -(register-definition-prefixes "autoload" '("autoload-" "batch-update-autoloads--summary" "generate" "make-autoload" "no-update-autoloads")) - -;;;*** -;;;### (autoloads nil "autorevert" "autorevert.el" (0 0 0 0)) ;;; Generated autoloads from autorevert.el (autoload 'auto-revert-mode "autorevert" "\ @@ -1753,14 +1613,12 @@ evaluate `auto-revert-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'turn-on-auto-revert-mode "autorevert" "\ Turn on Auto-Revert Mode. This function is designed to be added to hooks, for example: (add-hook \\='c-mode-hook #\\='turn-on-auto-revert-mode)" nil nil) - (autoload 'auto-revert-tail-mode "autorevert" "\ Toggle reverting tail of buffer when the file grows. @@ -1794,14 +1652,12 @@ evaluate `auto-revert-tail-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'turn-on-auto-revert-tail-mode "autorevert" "\ Turn on Auto-Revert Tail Mode. This function is designed to be added to hooks, for example: (add-hook \\='my-logfile-mode-hook #\\='turn-on-auto-revert-tail-mode)" nil nil) - (defvar global-auto-revert-mode nil "\ Non-nil if Global Auto-Revert mode is enabled. See the `global-auto-revert-mode' command @@ -1809,9 +1665,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `global-auto-revert-mode'.") - (custom-autoload 'global-auto-revert-mode "autorevert" nil) - (autoload 'global-auto-revert-mode "autorevert" "\ Toggle Global Auto-Revert Mode. @@ -1847,21 +1701,15 @@ evaluate `(default-value \\='global-auto-revert-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "autorevert" '("auto-revert-" "global-auto-revert-")) -;;;*** -;;;### (autoloads nil "avl-tree" "emacs-lisp/avl-tree.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from emacs-lisp/avl-tree.el (register-definition-prefixes "avl-tree" '("avl-tree-")) -;;;*** -;;;### (autoloads nil "avoid" "avoid.el" (0 0 0 0)) ;;; Generated autoloads from avoid.el (defvar mouse-avoidance-mode nil "\ @@ -1869,9 +1717,7 @@ Activate Mouse Avoidance mode. See function `mouse-avoidance-mode' for possible values. Setting this variable directly does not take effect; use either \\[customize] or \\[mouse-avoidance-mode].") - (custom-autoload 'mouse-avoidance-mode "avoid" nil) - (autoload 'mouse-avoidance-mode "avoid" "\ Set Mouse Avoidance mode to MODE. MODE should be one of the symbols `banish', `exile', `jump', `animate', @@ -1891,34 +1737,31 @@ Effects of the different modes: * cat-and-mouse: Same as `animate'. * proteus: As `animate', but changes the shape of the mouse pointer too. -\(See `mouse-avoidance-threshold' for definition of \"too close\", +(See `mouse-avoidance-threshold' for definition of \"too close\", and `mouse-avoidance-nudge-dist' and `mouse-avoidance-nudge-var' for definition of \"random distance\".) -\(fn &optional MODE)" t nil) - +(fn &optional MODE)" t nil) (register-definition-prefixes "avoid" '("mouse-avoidance-")) -;;;*** -;;;### (autoloads nil "backtrace" "emacs-lisp/backtrace.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from emacs-lisp/backtrace.el -(push (purecopy '(backtrace 1 0)) package--builtin-versions) +(push (purecopy '(backtrace 1 0)) package--builtin-versions) (autoload 'backtrace "backtrace" "\ Print a trace of Lisp function calls currently active. Output stream used is value of `standard-output'." nil nil) - (register-definition-prefixes "backtrace" '("backtrace-")) -;;;*** -;;;### (autoloads nil "bat-mode" "progmodes/bat-mode.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/base.el + +(register-definition-prefixes "ede/base" '("ede-")) + + ;;; Generated autoloads from progmodes/bat-mode.el (add-to-list 'auto-mode-alist '("\\.\\(bat\\|cmd\\)\\'" . bat-mode)) - (autoload 'bat-mode "bat-mode" "\ Major mode for editing DOS/Windows batch files. Start a new script from `bat-template'. Read help pages for DOS commands @@ -1927,21 +1770,17 @@ Run script using `bat-run' and `bat-run-args'. \\{bat-mode-map} -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "bat-mode" '("bat-")) -;;;*** -;;;### (autoloads nil "battery" "battery.el" (0 0 0 0)) ;;; Generated autoloads from battery.el - (put 'battery-mode-line-string 'risky-local-variable t) + (put 'battery-mode-line-string 'risky-local-variable t) (autoload 'battery "battery" "\ Display battery status information in the echo area. The text being displayed in the echo area is controlled by the variables `battery-echo-area-format' and `battery-status-function'." t nil) - (defvar display-battery-mode nil "\ Non-nil if Display-Battery mode is enabled. See the `display-battery-mode' command @@ -1949,9 +1788,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `display-battery-mode'.") - (custom-autoload 'display-battery-mode "battery" nil) - (autoload 'display-battery-mode "battery" "\ Toggle battery status display in mode line (Display Battery mode). @@ -1960,6 +1797,10 @@ The text displayed in the mode line is controlled by The mode line is be updated every `battery-update-interval' seconds. +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. + This is a global minor mode. If called interactively, toggle the `Display-Battery mode' mode. If the prefix argument is positive, enable the mode, and if it is zero or negative, disable the mode. @@ -1974,14 +1815,10 @@ evaluate `(default-value \\='display-battery-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) +(fn &optional ARG)" t nil) +(register-definition-prefixes "battery" '("battery-" "my-")) -(register-definition-prefixes "battery" '("battery-")) - -;;;*** -;;;### (autoloads nil "benchmark" "emacs-lisp/benchmark.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from emacs-lisp/benchmark.el (autoload 'benchmark-call "benchmark" "\ @@ -1996,8 +1833,7 @@ specifies a minimum number of seconds that the benchmark execution should take. In that case the return value is prepended with the number of repetitions actually used. -\(fn FUNC &optional REPETITIONS)" nil nil) - +(fn FUNC &optional REPETITIONS)" nil nil) (autoload 'benchmark-run "benchmark" "\ Time execution of FORMS. If REPETITIONS is supplied as a number, run FORMS that many times, @@ -2007,20 +1843,16 @@ Return a list of the total elapsed time for execution, the number of garbage collections that ran, and the time taken by garbage collection. See also `benchmark-run-compiled'. -\(fn &optional REPETITIONS &rest FORMS)" nil t) - +(fn &optional REPETITIONS &rest FORMS)" nil t) (function-put 'benchmark-run 'lisp-indent-function '1) - (autoload 'benchmark-run-compiled "benchmark" "\ Time execution of compiled version of FORMS. This is like `benchmark-run', but what is timed is a funcall of the byte code obtained by wrapping FORMS in a `lambda' and compiling the result. The overhead of the `lambda's is accounted for. -\(fn &optional REPETITIONS &rest FORMS)" nil t) - +(fn &optional REPETITIONS &rest FORMS)" nil t) (function-put 'benchmark-run-compiled 'lisp-indent-function '1) - (autoload 'benchmark "benchmark" "\ Print the time taken for REPETITIONS executions of FORM. Interactively, REPETITIONS is taken from the prefix arg, and @@ -2030,28 +1862,21 @@ For non-interactive use see also `benchmark-run' and FORM can also be a function in which case we measure the time it takes to call it without any argument. -\(fn REPETITIONS FORM)" t nil) - +(fn REPETITIONS FORM)" t nil) (autoload 'benchmark-progn "benchmark" "\ Evaluate BODY and message the time taken. The return value is the value of the final form in BODY. -\(fn &rest BODY)" nil t) - +(fn &rest BODY)" nil t) (function-put 'benchmark-progn 'lisp-indent-function '0) - (register-definition-prefixes "benchmark" '("benchmark-")) -;;;*** -;;;### (autoloads nil "bib-mode" "textmodes/bib-mode.el" (0 0 0 0)) ;;; Generated autoloads from textmodes/bib-mode.el (register-definition-prefixes "bib-mode" '("addbib" "bib-" "mark-bib" "return-key-bib" "unread-bib")) -;;;*** -;;;### (autoloads nil "bibtex" "textmodes/bibtex.el" (0 0 0 0)) ;;; Generated autoloads from textmodes/bibtex.el (autoload 'bibtex-initialize "bibtex" "\ @@ -2068,8 +1893,7 @@ When called interactively, FORCE is t, CURRENT is t if current buffer visits a file using `bibtex-mode', and SELECT is t if current buffer does not use `bibtex-mode'. -\(fn &optional CURRENT FORCE SELECT)" t nil) - +(fn &optional CURRENT FORCE SELECT)" t nil) (autoload 'bibtex-mode "bibtex" "\ Major mode for editing BibTeX files. @@ -2123,8 +1947,7 @@ if that value is non-nil. \\{bibtex-mode-map} -\(fn)" t nil) - +(fn)" t nil) (autoload 'bibtex-search-entry "bibtex" "\ Move point to the beginning of BibTeX entry named KEY. Return position of entry if KEY is found or nil if not found. @@ -2138,59 +1961,44 @@ Also, GLOBAL is t if the current mode is not `bibtex-mode' or `bibtex-search-entry-globally' is non-nil. A prefix arg negates the value of `bibtex-search-entry-globally'. -\(fn KEY &optional GLOBAL START DISPLAY)" t nil) - +(fn KEY &optional GLOBAL START DISPLAY)" t nil) (register-definition-prefixes "bibtex" '("bibtex-")) -;;;*** -;;;### (autoloads nil "bibtex-style" "textmodes/bibtex-style.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from textmodes/bibtex-style.el (autoload 'bibtex-style-mode "bibtex-style" "\ Major mode for editing BibTeX style files. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "bibtex-style" '("bibtex-style-")) -;;;*** -;;;### (autoloads nil "bindat" "emacs-lisp/bindat.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/bindat.el (register-definition-prefixes "bindat" '("bindat-")) -;;;*** -;;;### (autoloads nil "binhex" "mail/binhex.el" (0 0 0 0)) ;;; Generated autoloads from mail/binhex.el (defconst binhex-begin-line "^:...............................................................$" "\ Regular expression matching the start of a BinHex encoded region.") - (autoload 'binhex-decode-region-internal "binhex" "\ Binhex decode region between START and END without using an external program. If HEADER-ONLY is non-nil only decode header and return filename. -\(fn START END &optional HEADER-ONLY)" t nil) - +(fn START END &optional HEADER-ONLY)" t nil) (autoload 'binhex-decode-region-external "binhex" "\ Binhex decode region between START and END using external decoder. -\(fn START END)" t nil) - +(fn START END)" t nil) (autoload 'binhex-decode-region "binhex" "\ Binhex decode region between START and END. -\(fn START END)" t nil) - +(fn START END)" t nil) (register-definition-prefixes "binhex" '("binhex-")) -;;;*** -;;;### (autoloads nil "blackbox" "play/blackbox.el" (0 0 0 0)) ;;; Generated autoloads from play/blackbox.el (autoload 'blackbox "blackbox" "\ @@ -2305,22 +2113,23 @@ H * * * O - - - - - - - - - - - - - - - - - - - - Be sure to compare the second example of a hit with the first example of a reflection. -\(fn NUM)" t nil) - +(fn NUM)" t nil) (register-definition-prefixes "blackbox" '("bb-" "blackbox-")) -;;;*** -;;;### (autoloads nil "bookmark" "bookmark.el" (0 0 0 0)) ;;; Generated autoloads from bookmark.el + (define-key ctl-x-r-map "b" 'bookmark-jump) (define-key ctl-x-r-map "m" 'bookmark-set) (define-key ctl-x-r-map "M" 'bookmark-set-no-overwrite) (define-key ctl-x-r-map "l" 'bookmark-bmenu-list) - -(defvar-keymap bookmark-map :doc "Keymap containing bindings to bookmark functions.\nIt is not bound to any key by default: to bind it\nso that you have a bookmark prefix, just use `global-set-key' and bind a\nkey of your choice to variable `bookmark-map'. All interactive bookmark\nfunctions have a binding in this keymap." "x" #'bookmark-set "m" #'bookmark-set "M" #'bookmark-set-no-overwrite "j" #'bookmark-jump "g" #'bookmark-jump "o" #'bookmark-jump-other-window "5" #'bookmark-jump-other-frame "i" #'bookmark-insert "e" #'edit-bookmarks "f" #'bookmark-insert-location "r" #'bookmark-rename "d" #'bookmark-delete "D" #'bookmark-delete-all "l" #'bookmark-load "w" #'bookmark-write "s" #'bookmark-save) +(defvar-keymap bookmark-map :doc "\ +Keymap containing bindings to bookmark functions. +It is not bound to any key by default: to bind it +so that you have a bookmark prefix, just use `global-set-key' and bind a +key of your choice to variable `bookmark-map'. All interactive bookmark +functions have a binding in this keymap." "x" #'bookmark-set "m" #'bookmark-set "M" #'bookmark-set-no-overwrite "j" #'bookmark-jump "g" #'bookmark-jump "o" #'bookmark-jump-other-window "5" #'bookmark-jump-other-frame "i" #'bookmark-insert "e" #'edit-bookmarks "f" #'bookmark-insert-location "r" #'bookmark-rename "d" #'bookmark-delete "D" #'bookmark-delete-all "l" #'bookmark-load "w" #'bookmark-write "s" #'bookmark-save) (fset 'bookmark-map bookmark-map) - (autoload 'bookmark-set "bookmark" "\ Set a bookmark named NAME at the current location. If NAME is nil, then prompt the user. @@ -2346,8 +2155,7 @@ Use \\[bookmark-delete] to remove bookmarks (you give it a name and it removes only the first instance of a bookmark with that name from the list of bookmarks.) -\(fn &optional NAME NO-OVERWRITE)" t nil) - +(fn &optional NAME NO-OVERWRITE)" t nil) (autoload 'bookmark-set-no-overwrite "bookmark" "\ Set a bookmark named NAME at the current location. If NAME is nil, then prompt the user. @@ -2376,8 +2184,7 @@ Use \\[bookmark-delete] to remove bookmarks (you give it a name and it removes only the first instance of a bookmark with that name from the list of bookmarks.) -\(fn &optional NAME PUSH-BOOKMARK)" t nil) - +(fn &optional NAME PUSH-BOOKMARK)" t nil) (autoload 'bookmark-jump "bookmark" "\ Jump to bookmark BOOKMARK (a point in some file). You may have a problem using this function if the value of variable @@ -2397,18 +2204,15 @@ If DISPLAY-FUNC is non-nil, it is a function to invoke to display the bookmark. It defaults to `pop-to-buffer-same-window'. A typical value for DISPLAY-FUNC would be `switch-to-buffer-other-window'. -\(fn BOOKMARK &optional DISPLAY-FUNC)" t nil) - +(fn BOOKMARK &optional DISPLAY-FUNC)" t nil) (autoload 'bookmark-jump-other-window "bookmark" "\ Jump to BOOKMARK in another window. See `bookmark-jump' for more. -\(fn BOOKMARK)" t nil) - +(fn BOOKMARK)" t nil) (autoload 'bookmark-jump-other-frame "bookmark" "\ Jump to BOOKMARK in another frame. See `bookmark-jump' for more. -\(fn BOOKMARK)" t nil) - +(fn BOOKMARK)" t nil) (autoload 'bookmark-relocate "bookmark" "\ Relocate BOOKMARK-NAME to another file, reading file name with minibuffer. @@ -2416,18 +2220,15 @@ This makes an already existing bookmark point to that file, instead of the one it used to point at. Useful when a file has been renamed after a bookmark was set in it. -\(fn BOOKMARK-NAME)" t nil) - +(fn BOOKMARK-NAME)" t nil) (autoload 'bookmark-insert-location "bookmark" "\ Insert the name of the file associated with BOOKMARK-NAME. Optional second arg NO-HISTORY means don't record this in the minibuffer history list `bookmark-history'. -\(fn BOOKMARK-NAME &optional NO-HISTORY)" t nil) - +(fn BOOKMARK-NAME &optional NO-HISTORY)" t nil) (defalias 'bookmark-locate 'bookmark-insert-location) - (autoload 'bookmark-rename "bookmark" "\ Change the name of OLD-NAME bookmark to NEW-NAME name. If called from keyboard, prompt for OLD-NAME and NEW-NAME. @@ -2441,8 +2242,7 @@ While you are entering the new name, consecutive \\\", \"<3>\", etc. -\(fn FILE &optional OVERWRITE NO-MSG DEFAULT)" t nil) - +(fn FILE &optional OVERWRITE NO-MSG DEFAULT)" t nil) (autoload 'bookmark-bmenu-get-buffer "bookmark" "\ Return the Bookmark List, building it if it doesn't exists. Don't affect the buffer ring order." nil nil) - (autoload 'bookmark-bmenu-list "bookmark" "\ Display a list of existing bookmarks. The list is displayed in a buffer named `*Bookmark List*'. The leftmost column displays a D if the bookmark is flagged for deletion, or > if it is flagged for displaying." t nil) - (defalias 'list-bookmarks 'bookmark-bmenu-list) - (defalias 'edit-bookmarks 'bookmark-bmenu-list) - (autoload 'bookmark-bmenu-search "bookmark" "\ Incremental search of bookmarks, hiding the non-matches as we go." '(bookmark-bmenu-mode) nil) - (defvar menu-bar-bookmark-map (let ((map (make-sparse-keymap "Bookmark functions"))) (bindings--define-key map [load] '(menu-item "Load a Bookmark File..." bookmark-load :help "Load bookmarks from a bookmark file)")) (bindings--define-key map [write] '(menu-item "Save Bookmarks As..." bookmark-write :help "Write bookmarks to a file (reading the file name with the minibuffer)")) (bindings--define-key map [save] '(menu-item "Save Bookmarks" bookmark-save :help "Save currently defined bookmarks")) (bindings--define-key map [edit] '(menu-item "Edit Bookmark List" bookmark-bmenu-list :help "Display a list of existing bookmarks")) (bindings--define-key map [delete] '(menu-item "Delete Bookmark..." bookmark-delete :help "Delete a bookmark from the bookmark list")) (bindings--define-key map [delete-all] '(menu-item "Delete all Bookmarks..." bookmark-delete-all :help "Delete all bookmarks from the bookmark list")) (bindings--define-key map [rename] '(menu-item "Rename Bookmark..." bookmark-rename :help "Change the name of a bookmark")) (bindings--define-key map [locate] '(menu-item "Insert Location..." bookmark-locate :help "Insert the name of the file associated with a bookmark")) (bindings--define-key map [insert] '(menu-item "Insert Contents..." bookmark-insert :help "Insert the text of the file pointed to by a bookmark")) (bindings--define-key map [set] '(menu-item "Set Bookmark..." bookmark-set :help "Set a bookmark named inside a file.")) (bindings--define-key map [jump] '(menu-item "Jump to Bookmark..." bookmark-jump :help "Jump to a bookmark (a point in some file)")) map)) - (defalias 'menu-bar-bookmark-map menu-bar-bookmark-map) - (register-definition-prefixes "bookmark" '("bookmark-" "with-buffer-modified-unmodified")) -;;;*** -;;;### (autoloads nil "browse-url" "net/browse-url.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine.el + +(register-definition-prefixes "semantic/bovine" '("semantic-")) + + ;;; Generated autoloads from net/browse-url.el (defvar browse-url-browser-function 'browse-url-default-browser "\ @@ -2549,16 +2338,13 @@ This is used by the `browse-url-at-point', `browse-url-at-mouse', and Also see `browse-url-secondary-browser-function' and `browse-url-handlers'.") - (custom-autoload 'browse-url-browser-function "browse-url" t) - (defvar browse-url-default-handlers '(("\\`mailto:" . browse-url--mailto) ("\\`man:" . browse-url--man) (browse-url--non-html-file-url-p . browse-url-emacs)) "\ Like `browse-url-handlers' but populated by Emacs and packages. Emacs and external packages capable of browsing certain URLs should place their entries in this alist rather than `browse-url-handlers' which is reserved for the user.") - (autoload 'browse-url-select-handler "browse-url" "\ Return a handler of suitable for browsing URL. This searches `browse-url-handlers', and @@ -2573,8 +2359,7 @@ Currently, it also consults `browse-url-browser-function' first if it is set to an alist, although this usage is deprecated since Emacs 28.1 and will be removed in a future release. -\(fn URL &optional KIND)" nil nil) - +(fn URL &optional KIND)" nil nil) (autoload 'browse-url-of-file "browse-url" "\ Use a web browser to display FILE. Display the current buffer's file if FILE is nil or if called @@ -2582,8 +2367,7 @@ interactively. Turn the filename into a URL with function `browse-url-file-url'. Pass the URL to a browser using the `browse-url' function then run `browse-url-of-file-hook'. -\(fn &optional FILE)" t nil) - +(fn &optional FILE)" t nil) (autoload 'browse-url-of-buffer "browse-url" "\ Use a web browser to display BUFFER. See `browse-url' for details. @@ -2592,17 +2376,14 @@ Display the current buffer if BUFFER is nil. Display only the currently visible part of BUFFER (from a temporary file) if buffer is narrowed. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (autoload 'browse-url-of-dired-file "browse-url" "\ In Dired, ask a WWW browser to display the file named on this line." t nil) - (autoload 'browse-url-of-region "browse-url" "\ Use a web browser to display the current region. See `browse-url' for details. -\(fn MIN MAX)" t nil) - +(fn MIN MAX)" t nil) (autoload 'browse-url "browse-url" "\ Open URL using a configurable method. This will typically (by default) open URL with an external web @@ -2624,16 +2405,14 @@ significance of ARGS (most of the functions ignore it). If ARGS are omitted, the default is to pass `browse-url-new-window-flag' as ARGS. -\(fn URL &rest ARGS)" t nil) - +(fn URL &rest ARGS)" t nil) (autoload 'browse-url-at-point "browse-url" "\ Open URL at point using a configurable method. See `browse-url' for details. Optional prefix argument ARG non-nil inverts the value of the option `browse-url-new-window-flag'. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'browse-url-with-browser-kind "browse-url" "\ Browse URL with a browser of the given browser KIND. KIND is either `internal' or `external'. @@ -2641,8 +2420,7 @@ KIND is either `internal' or `external'. When called interactively, the default browser kind is the opposite of the browser kind of `browse-url-browser-function'. -\(fn KIND URL &optional ARG)" t nil) - +(fn KIND URL &optional ARG)" t nil) (autoload 'browse-url-at-mouse "browse-url" "\ Use a web browser to load a URL clicked with the mouse. See `browse-url' for details. @@ -2650,15 +2428,13 @@ See `browse-url' for details. The URL is the one around or before the position of the mouse click but point is not changed. -\(fn EVENT)" t nil) - +(fn EVENT)" t nil) (autoload 'browse-url-xdg-open "browse-url" "\ Pass the specified URL to the \"xdg-open\" command. xdg-open is a desktop utility that calls your preferred web browser. The optional argument IGNORED is not used. -\(fn URL &optional IGNORED)" t nil) - +(fn URL &optional IGNORED)" t nil) (autoload 'browse-url-mozilla "browse-url" "\ Ask the Mozilla WWW browser to load URL. Default to the URL around or before point. The strings in variable @@ -2676,8 +2452,7 @@ new tab in an existing window instead. When called non-interactively, optional second argument NEW-WINDOW is used instead of `browse-url-new-window-flag'. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-firefox "browse-url" "\ Ask the Firefox WWW browser to load URL. Defaults to the URL around or before point. Passes the strings @@ -2694,8 +2469,7 @@ is loaded in a new tab in an existing window instead. Non-interactively, this uses the optional second argument NEW-WINDOW instead of `browse-url-new-window-flag'. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-chromium "browse-url" "\ Ask the Chromium WWW browser to load URL. Default to the URL around or before point. The strings in @@ -2703,28 +2477,24 @@ variable `browse-url-chromium-arguments' are also passed to Chromium. The optional argument NEW-WINDOW is not used. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-webpositive "browse-url" "\ Ask the WebPositive WWW browser to load URL. Default to the URL around or before point. The optional argument NEW-WINDOW is not used. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-default-haiku-browser "browse-url" "\ Browse URL with the system default browser. Default to the URL around or before point. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-emacs "browse-url" "\ Ask Emacs to load URL into a buffer and show it in another window. Optional argument SAME-WINDOW non-nil means show the URL in the currently selected window instead. -\(fn URL &optional SAME-WINDOW)" t nil) - +(fn URL &optional SAME-WINDOW)" t nil) (autoload 'browse-url-gnome-moz "browse-url" "\ Ask Mozilla to load URL via the GNOME program `gnome-moz-remote'. Default to the URL around or before point. The strings in variable @@ -2738,10 +2508,8 @@ effect of `browse-url-new-window-flag'. When called non-interactively, optional second argument NEW-WINDOW is used instead of `browse-url-new-window-flag'. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (make-obsolete 'browse-url-gnome-moz 'nil '"25.1") - (autoload 'browse-url-conkeror "browse-url" "\ Ask the Conkeror WWW browser to load URL. Default to the URL around or before point. Also pass the strings @@ -2760,10 +2528,8 @@ new window, load it in a new buffer in an existing window instead. When called non-interactively, use optional second argument NEW-WINDOW instead of `browse-url-new-window-flag'. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (make-obsolete 'browse-url-conkeror 'nil '"28.1") - (autoload 'browse-url-w3 "browse-url" "\ Ask the w3 WWW browser to load URL. Default to the URL around or before point. @@ -2775,17 +2541,14 @@ prefix argument reverses the effect of `browse-url-new-window-flag'. When called non-interactively, optional second argument NEW-WINDOW is used instead of `browse-url-new-window-flag'. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-w3-gnudoit "browse-url" "\ Ask another Emacs running gnuserv to load the URL using the W3 browser. The `browse-url-gnudoit-program' program is used with options given by `browse-url-gnudoit-args'. Default to the URL around or before point. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (make-obsolete 'browse-url-w3-gnudoit 'nil '"25.1") - (autoload 'browse-url-text-xterm "browse-url" "\ Ask a text browser to load URL. URL defaults to the URL around or before point. @@ -2794,8 +2557,7 @@ in an Xterm window using the Xterm program named by `browse-url-xterm-program' with possible additional arguments `browse-url-xterm-args'. The optional argument NEW-WINDOW is not used. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-text-emacs "browse-url" "\ Ask a text browser to load URL. URL defaults to the URL around or before point. @@ -2810,8 +2572,7 @@ reverses the effect of `browse-url-new-window-flag'. When called non-interactively, optional second argument NEW-WINDOW is used instead of `browse-url-new-window-flag'. -\(fn URL &optional NEW-BUFFER)" t nil) - +(fn URL &optional NEW-BUFFER)" t nil) (autoload 'browse-url-mail "browse-url" "\ Open a new mail message buffer within Emacs for the RFC 2368 URL. Default to using the mailto: URL around or before point as the @@ -2827,8 +2588,7 @@ non-nil interactive prefix argument reverses the effect of When called non-interactively, optional second argument NEW-WINDOW is used instead of `browse-url-new-window-flag'. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-generic "browse-url" "\ Ask the WWW browser defined by `browse-url-generic-program' to load URL. Default to the URL around or before point. A fresh copy of the @@ -2836,15 +2596,13 @@ browser is started up in a new process with possible additional arguments `browse-url-generic-args'. This is appropriate for browsers which don't offer a form of remote control. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-kde "browse-url" "\ Ask the KDE WWW browser to load URL. Default to the URL around or before point. The optional argument NEW-WINDOW is not used. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-elinks "browse-url" "\ Ask the Elinks WWW browser to load URL. Default to the URL around the point. @@ -2855,42 +2613,34 @@ none yet running, a newly started instance. The Elinks command will be prepended by the program+arguments from `browse-url-elinks-wrapper'. -\(fn URL &optional NEW-WINDOW)" t nil) - +(fn URL &optional NEW-WINDOW)" t nil) (autoload 'browse-url-button-open "browse-url" "\ Follow the link under point using `browse-url'. If EXTERNAL (the prefix if used interactively), open with the external browser instead of the default one. -\(fn &optional EXTERNAL MOUSE-EVENT)" t nil) - +(fn &optional EXTERNAL MOUSE-EVENT)" t nil) (autoload 'browse-url-button-open-url "browse-url" "\ Open URL using `browse-url'. If `current-prefix-arg' is non-nil, use `browse-url-secondary-browser-function' instead. -\(fn URL)" nil nil) - +(fn URL)" nil nil) (register-definition-prefixes "browse-url" '("browse-url-")) -;;;*** -;;;### (autoloads nil "bs" "bs.el" (0 0 0 0)) ;;; Generated autoloads from bs.el (autoload 'bs-cycle-next "bs" "\ Select next buffer defined by buffer cycling. The buffers taking part in buffer cycling are defined by buffer configuration `bs-cycle-configuration-name'." t nil) - (autoload 'bs-cycle-previous "bs" "\ Select previous buffer defined by buffer cycling. The buffers taking part in buffer cycling are defined by buffer configuration `bs-cycle-configuration-name'." t nil) - (autoload 'bs-customize "bs" "\ Customization of group bs for Buffer Selection Menu." t nil) - (autoload 'bs-show "bs" "\ Make a menu of buffers so you can manipulate buffers or the buffer list. \\ @@ -2905,13 +2655,10 @@ With prefix argument ARG show a different buffer list. Function `bs--configuration-name-for-prefix-arg' determine accordingly name of buffer configuration. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (register-definition-prefixes "bs" '("bs-")) -;;;*** -;;;### (autoloads nil "bubbles" "play/bubbles.el" (0 0 0 0)) ;;; Generated autoloads from play/bubbles.el (autoload 'bubbles "bubbles" "\ @@ -2927,19 +2674,13 @@ columns on its right towards the left. \\[bubbles-set-game-medium] sets the difficulty to medium. \\[bubbles-set-game-difficult] sets the difficulty to difficult. \\[bubbles-set-game-hard] sets the difficulty to hard." t nil) - (register-definition-prefixes "bubbles" '("bubbles-")) -;;;*** -;;;### (autoloads nil "bug-reference" "progmodes/bug-reference.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from progmodes/bug-reference.el (put 'bug-reference-url-format 'safe-local-variable (lambda (s) (or (stringp s) (and (symbolp s) (get s 'bug-reference-url-format))))) - (put 'bug-reference-bug-regexp 'safe-local-variable 'stringp) - (autoload 'bug-reference-mode "bug-reference" "\ Toggle hyperlinking bug references in the buffer (Bug Reference mode). @@ -2957,8 +2698,7 @@ evaluate `bug-reference-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'bug-reference-prog-mode "bug-reference" "\ Like `bug-reference-mode', but only buttonize in comments and strings. @@ -2977,35 +2717,26 @@ evaluate `bug-reference-prog-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "bug-reference" '("bug-reference-")) -;;;*** -;;;### (autoloads nil "byte-opt" "emacs-lisp/byte-opt.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from emacs-lisp/byte-opt.el (register-definition-prefixes "byte-opt" '("byte-" "disassemble-offset")) -;;;*** -;;;### (autoloads nil "bytecomp" "emacs-lisp/bytecomp.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from emacs-lisp/bytecomp.el + (put 'byte-compile-dynamic 'safe-local-variable 'booleanp) (put 'byte-compile-disable-print-circle 'safe-local-variable 'booleanp) (put 'byte-compile-dynamic-docstrings 'safe-local-variable 'booleanp) (put 'byte-compile-error-on-warn 'safe-local-variable 'booleanp) - (put 'byte-compile-warnings 'safe-local-variable (lambda (v) (or (symbolp v) (null (delq nil (mapcar (lambda (x) (not (symbolp x))) v)))))) - (autoload 'byte-compile-warning-enabled-p "bytecomp" "\ Return non-nil if WARNING is enabled, according to `byte-compile-warnings'. -\(fn WARNING &optional SYMBOL)" nil nil) - +(fn WARNING &optional SYMBOL)" nil nil) (autoload 'byte-compile-disable-warning "bytecomp" "\ Change `byte-compile-warnings' to disable WARNING. If `byte-compile-warnings' is t, set it to `(not WARNING)'. @@ -3013,8 +2744,7 @@ Otherwise, if the first element is `not', add WARNING, else remove it. Normally you should let-bind `byte-compile-warnings' before calling this, else the global value will be modified. -\(fn WARNING)" nil nil) - +(fn WARNING)" nil nil) (autoload 'byte-compile-enable-warning "bytecomp" "\ Change `byte-compile-warnings' to enable WARNING. If `byte-compile-warnings' is t, do nothing. Otherwise, if the @@ -3022,14 +2752,12 @@ first element is `not', remove WARNING, else add it. Normally you should let-bind `byte-compile-warnings' before calling this, else the global value will be modified. -\(fn WARNING)" nil nil) - +(fn WARNING)" nil nil) (autoload 'byte-force-recompile "bytecomp" "\ Recompile every `.el' file in DIRECTORY that already has a `.elc' file. Files in subdirectories of DIRECTORY are processed also. -\(fn DIRECTORY)" t nil) - +(fn DIRECTORY)" t nil) (autoload 'byte-recompile-directory "bytecomp" "\ Recompile every `.el' file in DIRECTORY that needs recompilation. This happens when a `.elc' file exists but is older than the `.el' file. @@ -3049,9 +2777,8 @@ This command will normally not follow symlinks when compiling files. If FOLLOW-SYMLINKS is non-nil, symlinked `.el' files will also be compiled. -\(fn DIRECTORY &optional ARG FORCE FOLLOW-SYMLINKS)" t nil) +(fn DIRECTORY &optional ARG FORCE FOLLOW-SYMLINKS)" t nil) (put 'no-byte-compile 'safe-local-variable 'booleanp) - (autoload 'byte-compile-file "bytecomp" "\ Compile a file of Lisp code named FILENAME into a file of byte code. The output file's name is generated by passing FILENAME to the @@ -3060,23 +2787,19 @@ The value is non-nil if there were no errors, nil if errors. See also `emacs-lisp-byte-compile-and-load'. -\(fn FILENAME &optional LOAD)" t nil) - +(fn FILENAME &optional LOAD)" t nil) (set-advertised-calling-convention 'byte-compile-file '(filename) '"28.1") - (autoload 'compile-defun "bytecomp" "\ Compile and evaluate the current top-level form. Print the result in the echo area. With argument ARG, insert value in current buffer after the form. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'byte-compile "bytecomp" "\ If FORM is a symbol, byte-compile its function definition. If FORM is a lambda or a macro, byte-compile it as a function. -\(fn FORM)" nil nil) - +(fn FORM)" nil nil) (autoload 'display-call-tree "bytecomp" "\ Display a call graph of a specified file. This lists which functions have been called, what functions called @@ -3086,19 +2809,17 @@ all functions called by those functions. The call graph does not include macros, inline functions, or primitives that the byte-code interpreter knows about directly -\(`eq', `cons', etc.). +(`eq', `cons', etc.). The call tree also lists those functions which are not known to be called -\(that is, to which no calls have been compiled), and which cannot be +(that is, to which no calls have been compiled), and which cannot be invoked interactively. -\(fn &optional FILENAME)" t nil) - +(fn &optional FILENAME)" t nil) (autoload 'batch-byte-compile-if-not-done "bytecomp" "\ Like `byte-compile-file' but doesn't recompile if already up to date. Use this from the command line, with `-batch'; it won't work in an interactive Emacs." nil nil) - (autoload 'batch-byte-compile "bytecomp" "\ Run `byte-compile-file' on the files remaining on the command line. Use this from the command line, with `-batch'; @@ -3115,8 +2836,7 @@ For example, invoke \"emacs -batch -f batch-byte-compile $emacs/ ~/*.el\". If NOFORCE is non-nil, don't recompile a file that seems to be already up-to-date. -\(fn &optional NOFORCE)" nil nil) - +(fn &optional NOFORCE)" nil nil) (autoload 'batch-byte-recompile-directory "bytecomp" "\ Run `byte-recompile-directory' on the dirs remaining on the command line. Must be used only with `-batch', and kills Emacs on completion. @@ -3126,61 +2846,44 @@ Optional argument ARG is passed as second argument ARG to `byte-recompile-directory'; see there for its possible values and corresponding effects. -\(fn &optional ARG)" nil nil) - +(fn &optional ARG)" nil nil) (register-definition-prefixes "bytecomp" '("batch-byte-compile-file" "byte" "displaying-byte-compile-warnings" "emacs-lisp-" "no-byte-compile")) -;;;*** -;;;### (autoloads nil "cal-bahai" "calendar/cal-bahai.el" (0 0 0 -;;;;;; 0)) +;;; Generated autoloads from cedet/semantic/bovine/c.el + +(register-definition-prefixes "semantic/bovine/c" '("c-mode" "semantic")) + + ;;; Generated autoloads from calendar/cal-bahai.el (register-definition-prefixes "cal-bahai" '("calendar-bahai-" "diary-bahai-" "holiday-bahai")) -;;;*** -;;;### (autoloads nil "cal-china" "calendar/cal-china.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from calendar/cal-china.el (put 'calendar-chinese-time-zone 'risky-local-variable t) - (register-definition-prefixes "cal-china" '("calendar-chinese-" "diary-chinese-" "holiday-chinese")) -;;;*** -;;;### (autoloads nil "cal-coptic" "calendar/cal-coptic.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from calendar/cal-coptic.el (register-definition-prefixes "cal-coptic" '("calendar-" "diary-")) -;;;*** -;;;### (autoloads nil "cal-dst" "calendar/cal-dst.el" (0 0 0 0)) ;;; Generated autoloads from calendar/cal-dst.el (put 'calendar-daylight-savings-starts 'risky-local-variable t) - (put 'calendar-daylight-savings-ends 'risky-local-variable t) - (put 'calendar-current-time-zone-cache 'risky-local-variable t) - (register-definition-prefixes "cal-dst" '("calendar-" "dst-")) -;;;*** -;;;### (autoloads nil "cal-french" "calendar/cal-french.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from calendar/cal-french.el (register-definition-prefixes "cal-french" '("calendar-french-" "diary-french-date")) -;;;*** -;;;### (autoloads nil "cal-hebrew" "calendar/cal-hebrew.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from calendar/cal-hebrew.el (autoload 'calendar-hebrew-list-yahrzeits "cal-hebrew" "\ @@ -3188,164 +2891,124 @@ List Yahrzeit dates for *Gregorian* DEATH-DATE from START-YEAR to END-YEAR. When called interactively from the calendar window, the date of death is taken from the cursor position. -\(fn DEATH-DATE START-YEAR END-YEAR)" t nil) - +(fn DEATH-DATE START-YEAR END-YEAR)" t nil) (register-definition-prefixes "cal-hebrew" '("calendar-hebrew-" "diary-hebrew-" "holiday-hebrew")) -;;;*** -;;;### (autoloads nil "cal-html" "calendar/cal-html.el" (0 0 0 0)) ;;; Generated autoloads from calendar/cal-html.el (register-definition-prefixes "cal-html" '("cal-html-")) -;;;*** -;;;### (autoloads nil "cal-islam" "calendar/cal-islam.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from calendar/cal-islam.el (register-definition-prefixes "cal-islam" '("calendar-islamic-" "diary-islamic-" "holiday-islamic")) -;;;*** -;;;### (autoloads nil "cal-iso" "calendar/cal-iso.el" (0 0 0 0)) ;;; Generated autoloads from calendar/cal-iso.el (register-definition-prefixes "cal-iso" '("calendar-iso-" "diary-iso-date")) -;;;*** -;;;### (autoloads nil "cal-julian" "calendar/cal-julian.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from calendar/cal-julian.el (register-definition-prefixes "cal-julian" '("calendar-" "diary-" "holiday-julian")) -;;;*** -;;;### (autoloads nil "cal-mayan" "calendar/cal-mayan.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from calendar/cal-mayan.el (register-definition-prefixes "cal-mayan" '("calendar-mayan-" "diary-mayan-date")) -;;;*** -;;;### (autoloads nil "cal-menu" "calendar/cal-menu.el" (0 0 0 0)) ;;; Generated autoloads from calendar/cal-menu.el (register-definition-prefixes "cal-menu" '("cal")) -;;;*** -;;;### (autoloads nil "cal-move" "calendar/cal-move.el" (0 0 0 0)) ;;; Generated autoloads from calendar/cal-move.el (register-definition-prefixes "cal-move" '("calendar-")) -;;;*** -;;;### (autoloads nil "cal-persia" "calendar/cal-persia.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from calendar/cal-persia.el (register-definition-prefixes "cal-persia" '("calendar-persian-" "diary-persian-date")) -;;;*** -;;;### (autoloads nil "cal-tex" "calendar/cal-tex.el" (0 0 0 0)) ;;; Generated autoloads from calendar/cal-tex.el (register-definition-prefixes "cal-tex" '("cal-tex-")) -;;;*** -;;;### (autoloads nil "cal-x" "calendar/cal-x.el" (0 0 0 0)) ;;; Generated autoloads from calendar/cal-x.el (register-definition-prefixes "cal-x" '("calendar-" "diary-frame")) -;;;*** -;;;### (autoloads nil "calc" "calc/calc.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc.el - (define-key ctl-x-map "*" 'calc-dispatch) + (define-key ctl-x-map "*" 'calc-dispatch) (autoload 'calc-dispatch "calc" "\ Invoke the GNU Emacs Calculator. See \\[calc-dispatch-help] for details. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'calc "calc" "\ The Emacs Calculator. Full documentation is listed under `calc-mode'. -\(fn &optional ARG FULL-DISPLAY INTERACTIVE)" t nil) - +(fn &optional ARG FULL-DISPLAY INTERACTIVE)" t nil) (autoload 'full-calc "calc" "\ Invoke the Calculator and give it a full-sized window. -\(fn &optional INTERACTIVE)" t nil) - +(fn &optional INTERACTIVE)" t nil) (autoload 'quick-calc "calc" "\ Do a quick calculation in the minibuffer without invoking full Calculator. With prefix argument INSERT, insert the result in the current buffer. Otherwise, the result is copied into the kill ring. -\(fn &optional INSERT)" t nil) - +(fn &optional INSERT)" t nil) (autoload 'calc-eval "calc" "\ Do a quick calculation and return the result as a string. Return value will either be the formatted result in string form, or a list containing a character position and an error message in string form. -\(fn STR &optional SEPARATOR &rest ARGS)" nil nil) - +(fn STR &optional SEPARATOR &rest ARGS)" nil nil) (autoload 'calc-keypad "calc" "\ Invoke the Calculator in \"visual keypad\" mode. This is most useful in the X window system. In this mode, click on the Calc \"buttons\" using the left mouse button. Or, position the cursor manually and do \\[calc-keypad-press]. -\(fn &optional INTERACTIVE)" t nil) - +(fn &optional INTERACTIVE)" t nil) (autoload 'full-calc-keypad "calc" "\ Invoke the Calculator in full-screen \"visual keypad\" mode. See calc-keypad for details. -\(fn &optional INTERACTIVE)" t nil) - +(fn &optional INTERACTIVE)" t nil) (autoload 'calc-grab-region "calc" "\ Parse the region as a vector of numbers and push it on the Calculator stack. -\(fn TOP BOT ARG)" t nil) - +(fn TOP BOT ARG)" t nil) (autoload 'calc-grab-rectangle "calc" "\ Parse a rectangle as a matrix of numbers and push it on the Calculator stack. -\(fn TOP BOT ARG)" t nil) - +(fn TOP BOT ARG)" t nil) (autoload 'calc-grab-sum-down "calc" "\ Parse a rectangle as a matrix of numbers and sum its columns. -\(fn TOP BOT ARG)" t nil) - +(fn TOP BOT ARG)" t nil) (autoload 'calc-grab-sum-across "calc" "\ Parse a rectangle as a matrix of numbers and sum its rows. -\(fn TOP BOT ARG)" t nil) - +(fn TOP BOT ARG)" t nil) (autoload 'calc-embedded "calc" "\ Start Calc Embedded mode on the formula surrounding point. -\(fn ARG &optional END OBEG OEND)" t nil) - +(fn ARG &optional END OBEG OEND)" t nil) (autoload 'calc-embedded-activate "calc" "\ Scan the current editing buffer for all embedded := and => formulas. Also looks for the equivalent TeX words, \\gets and \\evalto. -\(fn &optional ARG CBUF)" t nil) - +(fn &optional ARG CBUF)" t nil) (autoload 'defmath "calc" "\ Define Calc function. @@ -3358,299 +3021,234 @@ actual Lisp function name. See Info node `(calc)Defining Functions'. -\(fn FUNC ARGS &rest BODY)" nil t) - +(fn FUNC ARGS &rest BODY)" nil t) (function-put 'defmath 'doc-string-elt '3) - (function-put 'defmath 'lisp-indent-function 'defun) - (register-definition-prefixes "calc" '("calc" "defcalcmodevar" "inexact-result" "math-" "var-")) -;;;*** -;;;### (autoloads nil "calc-alg" "calc/calc-alg.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-aent.el + +(register-definition-prefixes "calc-aent" '("calc" "math-")) + + ;;; Generated autoloads from calc/calc-alg.el (register-definition-prefixes "calc-alg" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-arith" "calc/calc-arith.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-arith.el (register-definition-prefixes "calc-arith" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-bin" "calc/calc-bin.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-bin.el (register-definition-prefixes "calc-bin" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-comb" "calc/calc-comb.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-comb.el (register-definition-prefixes "calc-comb" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-cplx" "calc/calc-cplx.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-cplx.el (register-definition-prefixes "calc-cplx" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-ext" "calc/calc-ext.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-embed.el + +(register-definition-prefixes "calc-embed" '("calc-")) + + ;;; Generated autoloads from calc/calc-ext.el (register-definition-prefixes "calc-ext" '("calc" "math-" "var-")) -;;;*** -;;;### (autoloads nil "calc-fin" "calc/calc-fin.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-fin.el (register-definition-prefixes "calc-fin" '("calc" "math-c")) -;;;*** -;;;### (autoloads nil "calc-forms" "calc/calc-forms.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-forms.el (register-definition-prefixes "calc-forms" '("calc" "math-" "var-TimeZone")) -;;;*** -;;;### (autoloads nil "calc-frac" "calc/calc-frac.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-frac.el (register-definition-prefixes "calc-frac" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-funcs" "calc/calc-funcs.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-funcs.el (register-definition-prefixes "calc-funcs" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-graph" "calc/calc-graph.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-graph.el (register-definition-prefixes "calc-graph" '("calc-")) -;;;*** -;;;### (autoloads nil "calc-help" "calc/calc-help.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-help.el (register-definition-prefixes "calc-help" '("calc-")) -;;;*** -;;;### (autoloads nil "calc-incom" "calc/calc-incom.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-incom.el (register-definition-prefixes "calc-incom" '("calc-")) -;;;*** -;;;### (autoloads nil "calc-keypd" "calc/calc-keypd.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-keypd.el (register-definition-prefixes "calc-keypd" '("calc-")) -;;;*** -;;;### (autoloads nil "calc-lang" "calc/calc-lang.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-lang.el (register-definition-prefixes "calc-lang" '("calc-" "math-")) -;;;*** -;;;### (autoloads nil "calc-macs" "calc/calc-macs.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-macs.el (register-definition-prefixes "calc-macs" '("Math-" "calc-" "math-")) -;;;*** -;;;### (autoloads nil "calc-map" "calc/calc-map.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-map.el (register-definition-prefixes "calc-map" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-math" "calc/calc-math.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-math.el (register-definition-prefixes "calc-math" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-menu" "calc/calc-menu.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-menu.el (register-definition-prefixes "calc-menu" '("calc-")) -;;;*** -;;;### (autoloads nil "calc-mode" "calc/calc-mode.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-misc.el + +(register-definition-prefixes "calc-misc" '("math-iipow")) + + ;;; Generated autoloads from calc/calc-mode.el (register-definition-prefixes "calc-mode" '("calc-" "math-get-modes-vec")) -;;;*** -;;;### (autoloads nil "calc-mtx" "calc/calc-mtx.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-mtx.el (register-definition-prefixes "calc-mtx" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-nlfit" "calc/calc-nlfit.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-nlfit.el (register-definition-prefixes "calc-nlfit" '("calc-fit-" "math-nlfit-")) -;;;*** -;;;### (autoloads nil "calc-poly" "calc/calc-poly.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-poly.el (register-definition-prefixes "calc-poly" '("calcFunc-" "math-")) -;;;*** -;;;### (autoloads nil "calc-prog" "calc/calc-prog.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-prog.el (register-definition-prefixes "calc-prog" '("calc" "math-" "var-q")) -;;;*** -;;;### (autoloads nil "calc-rewr" "calc/calc-rewr.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-rewr.el (register-definition-prefixes "calc-rewr" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-rules" "calc/calc-rules.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-rules.el (register-definition-prefixes "calc-rules" '("calc-")) -;;;*** -;;;### (autoloads nil "calc-sel" "calc/calc-sel.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-sel.el (register-definition-prefixes "calc-sel" '("calc-")) -;;;*** -;;;### (autoloads nil "calc-stat" "calc/calc-stat.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-stat.el (register-definition-prefixes "calc-stat" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-store" "calc/calc-store.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-store.el (register-definition-prefixes "calc-store" '("calc")) -;;;*** -;;;### (autoloads nil "calc-stuff" "calc/calc-stuff.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-stuff.el (register-definition-prefixes "calc-stuff" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-trail" "calc/calc-trail.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-trail.el (register-definition-prefixes "calc-trail" '("calc-trail-")) -;;;*** -;;;### (autoloads nil "calc-undo" "calc/calc-undo.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-undo.el (autoload 'calc-undo "calc-undo" "\ -\(fn N)" t nil) - +(fn N)" t nil) (register-definition-prefixes "calc-undo" '("calc-")) -;;;*** -;;;### (autoloads nil "calc-units" "calc/calc-units.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-units.el (register-definition-prefixes "calc-units" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calc-vec" "calc/calc-vec.el" (0 0 0 0)) ;;; Generated autoloads from calc/calc-vec.el (register-definition-prefixes "calc-vec" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calcalg2" "calc/calcalg2.el" (0 0 0 0)) +;;; Generated autoloads from calc/calc-yank.el + +(register-definition-prefixes "calc-yank" '("calc-" "math-number-regexp")) + + ;;; Generated autoloads from calc/calcalg2.el (register-definition-prefixes "calcalg2" '("calc" "math-" "var-IntegLimit")) -;;;*** -;;;### (autoloads nil "calcalg3" "calc/calcalg3.el" (0 0 0 0)) ;;; Generated autoloads from calc/calcalg3.el (register-definition-prefixes "calcalg3" '("calc" "math-")) -;;;*** -;;;### (autoloads nil "calccomp" "calc/calccomp.el" (0 0 0 0)) ;;; Generated autoloads from calc/calccomp.el (register-definition-prefixes "calccomp" '("calcFunc-c" "math-")) -;;;*** -;;;### (autoloads nil "calcsel2" "calc/calcsel2.el" (0 0 0 0)) ;;; Generated autoloads from calc/calcsel2.el (register-definition-prefixes "calcsel2" '("calc-")) -;;;*** -;;;### (autoloads nil "calculator" "calculator.el" (0 0 0 0)) ;;; Generated autoloads from calculator.el (autoload 'calculator "calculator" "\ Run the Emacs calculator. See the documentation for `calculator-mode' for more information." t nil) - (register-definition-prefixes "calculator" '("calculator-")) -;;;*** -;;;### (autoloads nil "calendar" "calendar/calendar.el" (0 0 0 0)) ;;; Generated autoloads from calendar/calendar.el (autoload 'calendar "calendar" "\ @@ -3688,94 +3286,68 @@ Runs the following hooks: This function is suitable for execution in an init file. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "calendar" '("calendar-" "diary-" "holiday-buffer" "lunar-phases-buffer" "solar-sunrises-buffer")) -;;;*** -;;;### (autoloads nil "canlock" "gnus/canlock.el" (0 0 0 0)) ;;; Generated autoloads from gnus/canlock.el (autoload 'canlock-insert-header "canlock" "\ Insert a Cancel-Key and/or a Cancel-Lock header if possible. -\(fn &optional ID-FOR-KEY ID-FOR-LOCK PASSWORD)" nil nil) - +(fn &optional ID-FOR-KEY ID-FOR-LOCK PASSWORD)" nil nil) (autoload 'canlock-verify "canlock" "\ Verify Cancel-Lock or Cancel-Key in BUFFER. If BUFFER is nil, the current buffer is assumed. Signal an error if it fails. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (register-definition-prefixes "canlock" '("canlock-")) -;;;*** -;;;### (autoloads nil "cc-align" "progmodes/cc-align.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-align.el (register-definition-prefixes "cc-align" '("c-")) -;;;*** -;;;### (autoloads nil "cc-awk" "progmodes/cc-awk.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-awk.el (register-definition-prefixes "cc-awk" '("awk-" "c-awk-")) -;;;*** -;;;### (autoloads nil "cc-bytecomp" "progmodes/cc-bytecomp.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from progmodes/cc-bytecomp.el (register-definition-prefixes "cc-bytecomp" '("cc-")) -;;;*** -;;;### (autoloads nil "cc-cmds" "progmodes/cc-cmds.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-cmds.el (register-definition-prefixes "cc-cmds" '("c-")) -;;;*** -;;;### (autoloads nil "cc-defs" "progmodes/cc-defs.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-defs.el (register-definition-prefixes "cc-defs" '("c-" "cc-bytecomp-compiling-or-loading")) -;;;*** -;;;### (autoloads nil "cc-engine" "progmodes/cc-engine.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from progmodes/cc-engine.el (autoload 'c-guess-basic-syntax "cc-engine" "\ Return the syntactic context of the current line." nil nil) - (register-definition-prefixes "cc-engine" '("c-")) -;;;*** -;;;### (autoloads nil "cc-fonts" "progmodes/cc-fonts.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-fonts.el (register-definition-prefixes "cc-fonts" '("autodoc-" "c++-font-lock-keywords" "c-" "doxygen-font-lock-" "gtkdoc-font-lock-" "idl-font-lock-keywords" "java" "objc-font-lock-keywords" "pike-font-lock-keywords")) -;;;*** -;;;### (autoloads nil "cc-guess" "progmodes/cc-guess.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-guess.el (defvar c-guess-guessed-offsets-alist nil "\ Currently guessed offsets-alist.") - (defvar c-guess-guessed-basic-offset nil "\ Currently guessed basic-offset.") - (autoload 'c-guess "cc-guess" "\ Guess the style in the region up to `c-guess-region-max', and install it. @@ -3785,8 +3357,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is non-nil) then the previous guess is extended, otherwise a new guess is made from scratch. -\(fn &optional ACCUMULATE)" t nil) - +(fn &optional ACCUMULATE)" t nil) (autoload 'c-guess-no-install "cc-guess" "\ Guess the style in the region up to `c-guess-region-max'; don't install it. @@ -3794,8 +3365,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is non-nil) then the previous guess is extended, otherwise a new guess is made from scratch. -\(fn &optional ACCUMULATE)" t nil) - +(fn &optional ACCUMULATE)" t nil) (autoload 'c-guess-buffer "cc-guess" "\ Guess the style on the whole current buffer, and install it. @@ -3805,8 +3375,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is non-nil) then the previous guess is extended, otherwise a new guess is made from scratch. -\(fn &optional ACCUMULATE)" t nil) - +(fn &optional ACCUMULATE)" t nil) (autoload 'c-guess-buffer-no-install "cc-guess" "\ Guess the style on the whole current buffer; don't install it. @@ -3814,8 +3383,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is non-nil) then the previous guess is extended, otherwise a new guess is made from scratch. -\(fn &optional ACCUMULATE)" t nil) - +(fn &optional ACCUMULATE)" t nil) (autoload 'c-guess-region "cc-guess" "\ Guess the style on the region and install it. @@ -3825,8 +3393,7 @@ If given a prefix argument (or if the optional argument ACCUMULATE is non-nil) then the previous guess is extended, otherwise a new guess is made from scratch. -\(fn START END &optional ACCUMULATE)" t nil) - +(fn START END &optional ACCUMULATE)" t nil) (autoload 'c-guess-region-no-install "cc-guess" "\ Guess the style on the region; don't install it. @@ -3850,41 +3417,33 @@ guess is made from scratch. Note that the larger the region to guess in, the slower the guessing. So you can limit the region with `c-guess-region-max'. -\(fn START END &optional ACCUMULATE)" t nil) - +(fn START END &optional ACCUMULATE)" t nil) (autoload 'c-guess-install "cc-guess" "\ Install the latest guessed style into the current buffer. -\(This guessed style is a combination of `c-guess-guessed-basic-offset', +(This guessed style is a combination of `c-guess-guessed-basic-offset', `c-guess-guessed-offsets-alist' and `c-offsets-alist'.) The style is entered into CC Mode's style system by `c-add-style'. Its name is either STYLE-NAME, or a name based on the absolute file name of the file if STYLE-NAME is nil. -\(fn &optional STYLE-NAME)" t nil) - +(fn &optional STYLE-NAME)" t nil) (register-definition-prefixes "cc-guess" '("c-guess-")) -;;;*** -;;;### (autoloads nil "cc-langs" "progmodes/cc-langs.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-langs.el (register-definition-prefixes "cc-langs" '("c-")) -;;;*** -;;;### (autoloads nil "cc-menus" "progmodes/cc-menus.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-menus.el (register-definition-prefixes "cc-menus" '("cc-imenu-")) -;;;*** -;;;### (autoloads nil "cc-mode" "progmodes/cc-mode.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-mode.el -(push (purecopy '(cc-mode 5 33 1)) package--builtin-versions) +(push (purecopy '(cc-mode 5 33 1)) package--builtin-versions) (autoload 'c-initialize-cc-mode "cc-mode" "\ Initialize CC Mode for use in the current buffer. If the optional NEW-STYLE-INIT is nil or left out then all necessary @@ -3893,7 +3452,7 @@ only some basic setup is done, and a call to `c-init-language-vars' or `c-init-language-vars-for' is necessary too (which gives more control). See \"cc-mode.el\" for more info. -\(fn &optional NEW-STYLE-INIT)" nil nil) +(fn &optional NEW-STYLE-INIT)" nil nil) (add-to-list 'auto-mode-alist '("\\.\\(cc\\|hh\\)\\'" . c++-mode)) (add-to-list 'auto-mode-alist '("\\.[ch]\\(pp\\|xx\\|\\+\\+\\)\\'" . c++-mode)) (add-to-list 'auto-mode-alist '("\\.\\(CC?\\|HH?\\)\\'" . c++-mode)) @@ -3903,7 +3462,6 @@ control). See \"cc-mode.el\" for more info. (add-to-list 'auto-mode-alist '("\\.lex\\'" . c-mode)) (add-to-list 'auto-mode-alist '("\\.i\\'" . c-mode)) (add-to-list 'auto-mode-alist '("\\.ii\\'" . c++-mode)) - (autoload 'c-mode "cc-mode" "\ Major mode for editing C code. @@ -3920,8 +3478,7 @@ initialization, then `c-mode-hook'. Key bindings: \\{c-mode-map} -\(fn)" t nil) - +(fn)" t nil) (autoload 'c-or-c++-mode "cc-mode" "\ Analyze buffer and enable either C or C++ mode. @@ -3933,7 +3490,6 @@ should be used. This function attempts to use file contents to determine whether the code is C or C++ and based on that chooses whether to enable `c-mode' or `c++-mode'." t nil) - (autoload 'c++-mode "cc-mode" "\ Major mode for editing C++ code. To submit a problem report, enter `\\[c-submit-bug-report]' from a @@ -3950,9 +3506,8 @@ initialization, then `c++-mode-hook'. Key bindings: \\{c++-mode-map} -\(fn)" t nil) +(fn)" t nil) (add-to-list 'auto-mode-alist '("\\.m\\'" . objc-mode)) - (autoload 'objc-mode "cc-mode" "\ Major mode for editing Objective C code. To submit a problem report, enter `\\[c-submit-bug-report]' from an @@ -3969,9 +3524,8 @@ initialization, then `objc-mode-hook'. Key bindings: \\{objc-mode-map} -\(fn)" t nil) +(fn)" t nil) (add-to-list 'auto-mode-alist '("\\.java\\'" . java-mode)) - (autoload 'java-mode "cc-mode" "\ Major mode for editing Java code. To submit a problem report, enter `\\[c-submit-bug-report]' from a @@ -3988,9 +3542,8 @@ initialization, then `java-mode-hook'. Key bindings: \\{java-mode-map} -\(fn)" t nil) +(fn)" t nil) (add-to-list 'auto-mode-alist '("\\.idl\\'" . idl-mode)) - (autoload 'idl-mode "cc-mode" "\ Major mode for editing CORBA's IDL, PSDL and CIDL code. To submit a problem report, enter `\\[c-submit-bug-report]' from an @@ -4007,10 +3560,9 @@ initialization, then `idl-mode-hook'. Key bindings: \\{idl-mode-map} -\(fn)" t nil) +(fn)" t nil) (add-to-list 'auto-mode-alist '("\\.\\(u?lpc\\|pike\\|pmod\\(\\.in\\)?\\)\\'" . pike-mode)) (add-to-list 'interpreter-mode-alist '("pike" . pike-mode)) - (autoload 'pike-mode "cc-mode" "\ Major mode for editing Pike code. To submit a problem report, enter `\\[c-submit-bug-report]' from a @@ -4027,13 +3579,12 @@ initialization, then `pike-mode-hook'. Key bindings: \\{pike-mode-map} -\(fn)" t nil) +(fn)" t nil) (add-to-list 'auto-mode-alist '("\\.awk\\'" . awk-mode)) (add-to-list 'interpreter-mode-alist '("awk" . awk-mode)) (add-to-list 'interpreter-mode-alist '("mawk" . awk-mode)) (add-to-list 'interpreter-mode-alist '("nawk" . awk-mode)) (add-to-list 'interpreter-mode-alist '("gawk" . awk-mode)) - (autoload 'awk-mode "cc-mode" "\ Major mode for editing AWK code. To submit a problem report, enter `\\[c-submit-bug-report]' from an @@ -4049,14 +3600,10 @@ initialization, then `awk-mode-hook'. Key bindings: \\{awk-mode-map} -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "cc-mode" '("awk-mode-map" "c++-mode-" "c-" "idl-mode-" "java-mode-" "objc-mode-" "pike-mode-")) -;;;*** -;;;### (autoloads nil "cc-styles" "progmodes/cc-styles.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from progmodes/cc-styles.el (autoload 'c-set-style "cc-styles" "\ @@ -4082,8 +3629,7 @@ calls c-set-style internally in this way whilst initializing a buffer; if c-set-style is called like this from anywhere else, it will usually behave as a null operation. -\(fn STYLENAME &optional DONT-OVERRIDE)" t nil) - +(fn STYLENAME &optional DONT-OVERRIDE)" t nil) (autoload 'c-add-style "cc-styles" "\ Add a style to `c-style-alist', or update an existing one. STYLE is a string identifying the style to add or update. DESCRIPTION @@ -4095,43 +3641,35 @@ See the variable `c-style-alist' for the semantics of BASESTYLE, VARIABLE and VALUE. This function also sets the current style to STYLE using `c-set-style' if the optional SET-P flag is non-nil. -\(fn STYLE DESCRIPTION &optional SET-P)" t nil) - +(fn STYLE DESCRIPTION &optional SET-P)" t nil) (autoload 'c-set-offset "cc-styles" "\ Change the value of a syntactic element symbol in `c-offsets-alist'. SYMBOL is the syntactic element symbol to change and OFFSET is the new offset for that syntactic element. The optional argument is not used and exists only for compatibility reasons. -\(fn SYMBOL OFFSET &optional IGNORED)" t nil) - +(fn SYMBOL OFFSET &optional IGNORED)" t nil) (register-definition-prefixes "cc-styles" '("c-" "cc-choose-style-for-mode")) -;;;*** -;;;### (autoloads nil "cc-vars" "progmodes/cc-vars.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cc-vars.el + (put 'c-basic-offset 'safe-local-variable 'integerp) (put 'c-backslash-column 'safe-local-variable 'integerp) (put 'c-file-style 'safe-local-variable 'string-or-null-p) - (register-definition-prefixes "cc-vars" '("awk-mode-hook" "c++-" "c-" "defcustom-c-stylevar" "idl-" "java-" "objc-" "pike-")) -;;;*** -;;;### (autoloads nil "ccl" "international/ccl.el" (0 0 0 0)) ;;; Generated autoloads from international/ccl.el (autoload 'ccl-compile "ccl" "\ Return the compiled code of CCL-PROGRAM as a vector of integers. -\(fn CCL-PROGRAM)" nil nil) - +(fn CCL-PROGRAM)" nil nil) (autoload 'ccl-dump "ccl" "\ Disassemble compiled CCL-code CODE. -\(fn CODE)" nil nil) - +(fn CODE)" nil nil) (autoload 'declare-ccl-program "ccl" "\ Declare NAME as a name of CCL program. @@ -4143,8 +3681,7 @@ execution. Optional arg VECTOR is a compiled CCL code of the CCL program. -\(fn NAME &optional VECTOR)" nil t) - +(fn NAME &optional VECTOR)" nil t) (autoload 'define-ccl-program "ccl" "\ Set NAME the compiled code of CCL-PROGRAM. @@ -4389,12 +3926,9 @@ MAP-IDs := MAP-ID ... MAP-SET := MAP-IDs | (MAP-IDs) MAP-SET MAP-ID := integer -\(fn NAME CCL-PROGRAM &optional DOC)" nil t) - +(fn NAME CCL-PROGRAM &optional DOC)" nil t) (function-put 'define-ccl-program 'doc-string-elt '3) - (function-put 'define-ccl-program 'lisp-indent-function 'defun) - (autoload 'check-ccl-program "ccl" "\ Check validity of CCL-PROGRAM. If CCL-PROGRAM is a symbol denoting a CCL program, return @@ -4402,21 +3936,17 @@ CCL-PROGRAM, else return nil. If CCL-PROGRAM is a vector and optional arg NAME (symbol) is supplied, register CCL-PROGRAM by name NAME, and return NAME. -\(fn CCL-PROGRAM &optional NAME)" nil t) - +(fn CCL-PROGRAM &optional NAME)" nil t) (autoload 'ccl-execute-with-args "ccl" "\ Execute CCL-PROGRAM with registers initialized by the remaining args. The return value is a vector of resulting CCL registers. See the documentation of `define-ccl-program' for the detail of CCL program. -\(fn CCL-PROG &rest ARGS)" nil nil) - +(fn CCL-PROG &rest ARGS)" nil nil) (register-definition-prefixes "ccl" '("ccl-")) -;;;*** -;;;### (autoloads nil "cconv" "emacs-lisp/cconv.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/cconv.el (autoload 'cconv-closure-convert "cconv" "\ @@ -4426,63 +3956,44 @@ Main entry point for closure conversion. Returns a form where all lambdas don't have any free variables. -\(fn FORM)" nil nil) - +(fn FORM)" nil nil) (register-definition-prefixes "cconv" '("cconv-")) -;;;*** -;;;### (autoloads nil "cdl" "cdl.el" (0 0 0 0)) ;;; Generated autoloads from cdl.el (register-definition-prefixes "cdl" '("cdl-")) -;;;*** -;;;### (autoloads nil "cedet" "cedet/cedet.el" (0 0 0 0)) ;;; Generated autoloads from cedet/cedet.el -(push (purecopy '(cedet 2 0)) package--builtin-versions) +(push (purecopy '(cedet 2 0)) package--builtin-versions) (register-definition-prefixes "cedet" '("cedet-")) -;;;*** -;;;### (autoloads nil "cedet-cscope" "cedet/cedet-cscope.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from cedet/cedet-cscope.el (register-definition-prefixes "cedet-cscope" '("cedet-cscope-")) -;;;*** -;;;### (autoloads nil "cedet-files" "cedet/cedet-files.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from cedet/cedet-files.el (register-definition-prefixes "cedet-files" '("cedet-")) -;;;*** -;;;### (autoloads nil "cedet-global" "cedet/cedet-global.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from cedet/cedet-global.el (register-definition-prefixes "cedet-global" '("cedet-g")) -;;;*** -;;;### (autoloads nil "cedet-idutils" "cedet/cedet-idutils.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from cedet/cedet-idutils.el (register-definition-prefixes "cedet-idutils" '("cedet-idutils-")) -;;;*** -;;;### (autoloads nil "cfengine" "progmodes/cfengine.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cfengine.el -(push (purecopy '(cfengine 1 4)) package--builtin-versions) +(push (purecopy '(cfengine 1 4)) package--builtin-versions) (autoload 'cfengine3-mode "cfengine" "\ Major mode for editing CFEngine3 input. There are no special keybindings by default. @@ -4490,8 +4001,7 @@ There are no special keybindings by default. Action blocks are treated as defuns, i.e. \\[beginning-of-defun] moves to the action header. -\(fn)" t nil) - +(fn)" t nil) (autoload 'cfengine2-mode "cfengine" "\ Major mode for editing CFEngine2 input. There are no special keybindings by default. @@ -4499,16 +4009,12 @@ There are no special keybindings by default. Action blocks are treated as defuns, i.e. \\[beginning-of-defun] moves to the action header. -\(fn)" t nil) - +(fn)" t nil) (autoload 'cfengine-auto-mode "cfengine" "\ Choose `cfengine2-mode' or `cfengine3-mode' by buffer contents." t nil) - (register-definition-prefixes "cfengine" '("cfengine")) -;;;*** -;;;### (autoloads nil "char-fold" "char-fold.el" (0 0 0 0)) ;;; Generated autoloads from char-fold.el (autoload 'char-fold-to-regexp "char-fold" "\ @@ -4529,42 +4035,37 @@ just return the result of calling `regexp-quote' on STRING. FROM is for internal use. It specifies an index in the STRING from which to start. -\(fn STRING &optional LAX FROM)" nil nil) - +(fn STRING &optional LAX FROM)" nil nil) (register-definition-prefixes "char-fold" '("char-fold-")) -;;;*** -;;;### (autoloads nil "chart" "emacs-lisp/chart.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/chart.el (register-definition-prefixes "chart" '("chart")) -;;;*** -;;;### (autoloads nil "check-declare" "emacs-lisp/check-declare.el" -;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/chart.el + +(register-definition-prefixes "semantic/chart" '("semantic-chart-")) + + ;;; Generated autoloads from emacs-lisp/check-declare.el (autoload 'check-declare-file "check-declare" "\ Check veracity of all `declare-function' statements in FILE. See `check-declare-directory' for more information. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'check-declare-directory "check-declare" "\ Check veracity of all `declare-function' statements under directory ROOT. Returns non-nil if any false statements are found. -\(fn ROOT)" t nil) - +(fn ROOT)" t nil) (register-definition-prefixes "check-declare" '("check-declare-")) -;;;*** -;;;### (autoloads nil "checkdoc" "emacs-lisp/checkdoc.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from emacs-lisp/checkdoc.el + (put 'checkdoc-force-docstrings-flag 'safe-local-variable #'booleanp) (put 'checkdoc-force-history-flag 'safe-local-variable #'booleanp) (put 'checkdoc-permit-comma-termination-flag 'safe-local-variable #'booleanp) @@ -4573,19 +4074,16 @@ Returns non-nil if any false statements are found. (put 'checkdoc-arguments-in-order-flag 'safe-local-variable #'booleanp) (put 'checkdoc-verb-check-experimental-flag 'safe-local-variable #'booleanp) (put 'checkdoc-symbol-words 'safe-local-variable #'checkdoc-list-of-strings-p) - (autoload 'checkdoc-list-of-strings-p "checkdoc" "\ Return t when OBJ is a list of strings. -\(fn OBJ)" nil nil) +(fn OBJ)" nil nil) (put 'checkdoc-proper-noun-regexp 'safe-local-variable 'stringp) (put 'checkdoc-common-verbs-regexp 'safe-local-variable 'stringp) - (autoload 'checkdoc "checkdoc" "\ Interactively check the entire buffer for style errors. The current status of the check will be displayed in a buffer which the users will view as each check is completed." '(emacs-lisp-mode) nil) - (autoload 'checkdoc-interactive "checkdoc" "\ Interactively check the current buffer for doc string errors. Prefix argument START-HERE will start the checking from the current @@ -4595,8 +4093,7 @@ errors. Does not check for comment or space warnings. Optional argument SHOWSTATUS indicates that we should update the checkdoc status window instead of the usual behavior. -\(fn &optional START-HERE SHOWSTATUS)" '(emacs-lisp-mode) nil) - +(fn &optional START-HERE SHOWSTATUS)" '(emacs-lisp-mode) nil) (autoload 'checkdoc-message-interactive "checkdoc" "\ Interactively check the current buffer for message string errors. Prefix argument START-HERE will start the checking from the current @@ -4606,27 +4103,23 @@ errors. Does not check for comment or space warnings. Optional argument SHOWSTATUS indicates that we should update the checkdoc status window instead of the usual behavior. -\(fn &optional START-HERE SHOWSTATUS)" '(emacs-lisp-mode) nil) - +(fn &optional START-HERE SHOWSTATUS)" '(emacs-lisp-mode) nil) (autoload 'checkdoc-eval-current-buffer "checkdoc" "\ Evaluate and check documentation for the current buffer. Evaluation is done first because good documentation for something that doesn't work is just not useful. Comments, doc strings, and rogue spacing are all verified." t nil) - (autoload 'checkdoc-current-buffer "checkdoc" "\ Check current buffer for document, comment, error style, and rogue spaces. With a prefix argument (in Lisp, the argument TAKE-NOTES), store all errors found in a warnings buffer, otherwise stop after the first error. -\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) - +(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) (autoload 'checkdoc-file "checkdoc" "\ Check FILE for document, comment, error style, and rogue spaces. -\(fn FILE)" nil nil) - +(fn FILE)" nil nil) (autoload 'checkdoc-start "checkdoc" "\ Start scanning the current buffer for documentation string style errors. Only documentation strings are checked. @@ -4634,23 +4127,20 @@ Use `checkdoc-continue' to continue checking if an error cannot be fixed. Prefix argument TAKE-NOTES means to collect all the warning messages into a separate buffer. -\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) - +(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) (autoload 'checkdoc-continue "checkdoc" "\ Find the next doc string in the current buffer which has a style error. Prefix argument TAKE-NOTES means to continue through the whole buffer and save warnings in a separate buffer. -\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) - +(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) (autoload 'checkdoc-comments "checkdoc" "\ Find missing comment sections in the current Emacs Lisp file. Prefix argument TAKE-NOTES non-nil means to save warnings in a separate buffer. Otherwise print a message. This returns the error if there is one. -\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) - +(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) (autoload 'checkdoc-rogue-spaces "checkdoc" "\ Find extra spaces at the end of lines in the current file. Prefix argument TAKE-NOTES non-nil means to save warnings in a @@ -4658,20 +4148,17 @@ separate buffer. Otherwise print a message. This returns the error if there is one. Optional argument INTERACT permits more interactive fixing. -\(fn &optional TAKE-NOTES INTERACT)" '(emacs-lisp-mode) nil) - +(fn &optional TAKE-NOTES INTERACT)" '(emacs-lisp-mode) nil) (autoload 'checkdoc-message-text "checkdoc" "\ Scan the buffer for occurrences of the error function, and verify text. Optional argument TAKE-NOTES causes all errors to be logged. -\(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) - +(fn &optional TAKE-NOTES)" '(emacs-lisp-mode) nil) (autoload 'checkdoc-eval-defun "checkdoc" "\ Evaluate the current form with `eval-defun' and check its documentation. Evaluation is done first so the form will be read before the documentation is checked. If there is a documentation error, then the display of what was evaluated will be overwritten by the diagnostic message." t nil) - (autoload 'checkdoc-defun "checkdoc" "\ Examine the doc string of the function or variable under point. Call `error' if the doc string has problems. If NO-ERROR is @@ -4679,61 +4166,50 @@ non-nil, then do not call error, but call `message' instead. If the doc string passes the test, then check the function for rogue white space at the end of each line. -\(fn &optional NO-ERROR)" t nil) - +(fn &optional NO-ERROR)" t nil) (autoload 'checkdoc-dired "checkdoc" "\ In Dired, run `checkdoc' on marked files. Skip anything that doesn't have the Emacs Lisp library file extension (\".el\"). When called from Lisp, FILES is a list of filenames. -\(fn FILES)" '(dired-mode) nil) - +(fn FILES)" '(dired-mode) nil) (autoload 'checkdoc-ispell "checkdoc" "\ Check the style and spelling of everything interactively. Calls `checkdoc' with spell-checking turned on. Prefix argument is the same as for `checkdoc'." t nil) - (autoload 'checkdoc-ispell-current-buffer "checkdoc" "\ Check the style and spelling of the current buffer. Calls `checkdoc-current-buffer' with spell-checking turned on. Prefix argument is the same as for `checkdoc-current-buffer'." t nil) - (autoload 'checkdoc-ispell-interactive "checkdoc" "\ Check the style and spelling of the current buffer interactively. Calls `checkdoc-interactive' with spell-checking turned on. Prefix argument is the same as for `checkdoc-interactive'." t nil) - (autoload 'checkdoc-ispell-message-interactive "checkdoc" "\ Check the style and spelling of message text interactively. Calls `checkdoc-message-interactive' with spell-checking turned on. Prefix argument is the same as for `checkdoc-message-interactive'." t nil) - (autoload 'checkdoc-ispell-message-text "checkdoc" "\ Check the style and spelling of message text interactively. Calls `checkdoc-message-text' with spell-checking turned on. Prefix argument is the same as for `checkdoc-message-text'." t nil) - (autoload 'checkdoc-ispell-start "checkdoc" "\ Check the style and spelling of the current buffer. Calls `checkdoc-start' with spell-checking turned on. Prefix argument is the same as for `checkdoc-start'." t nil) - (autoload 'checkdoc-ispell-continue "checkdoc" "\ Check the style and spelling of the current buffer after point. Calls `checkdoc-continue' with spell-checking turned on. Prefix argument is the same as for `checkdoc-continue'." t nil) - (autoload 'checkdoc-ispell-comments "checkdoc" "\ Check the style and spelling of the current buffer's comments. Calls `checkdoc-comments' with spell-checking turned on. Prefix argument is the same as for `checkdoc-comments'." t nil) - (autoload 'checkdoc-ispell-defun "checkdoc" "\ Check the style and spelling of the current defun with Ispell. Calls `checkdoc-defun' with spell-checking turned on. Prefix argument is the same as for `checkdoc-defun'." t nil) - (autoload 'checkdoc-minor-mode "checkdoc" "\ Toggle automatic docstring checking (Checkdoc minor mode). @@ -4757,52 +4233,39 @@ evaluate `checkdoc-minor-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'checkdoc-package-keywords "checkdoc" "\ Find package keywords that aren't in `finder-known-keywords'." t nil) - (register-definition-prefixes "checkdoc" '("checkdoc-")) -;;;*** -;;;### (autoloads nil "china-util" "language/china-util.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from language/china-util.el (autoload 'decode-hz-region "china-util" "\ Decode HZ/ZW encoded text in the current region. Return the length of resulting text. -\(fn BEG END)" t nil) - +(fn BEG END)" t nil) (autoload 'decode-hz-buffer "china-util" "\ Decode HZ/ZW encoded text in the current buffer." t nil) - (autoload 'encode-hz-region "china-util" "\ Encode the text in the current region to HZ. Return the length of resulting text. -\(fn BEG END)" t nil) - +(fn BEG END)" t nil) (autoload 'encode-hz-buffer "china-util" "\ Encode the text in the current buffer to HZ." t nil) - (autoload 'post-read-decode-hz "china-util" "\ -\(fn LEN)" nil nil) - +(fn LEN)" nil nil) (autoload 'pre-write-encode-hz "china-util" "\ -\(fn FROM TO)" nil nil) - +(fn FROM TO)" nil nil) (register-definition-prefixes "china-util" '("decode-hz-line-continuation" "hz-" "hz/zw-start-gb" "iso2022-" "zw-start-gb")) -;;;*** -;;;### (autoloads nil "chistory" "chistory.el" (0 0 0 0)) ;;; Generated autoloads from chistory.el (autoload 'repeat-matching-complex-command "chistory" "\ @@ -4812,8 +4275,7 @@ a form for evaluation. If PATTERN is empty (or nil), every form in the command history is offered. The form is placed in the minibuffer for editing and the result is evaluated. -\(fn &optional PATTERN)" t nil) - +(fn &optional PATTERN)" t nil) (autoload 'list-command-history "chistory" "\ List history of commands that used the minibuffer. The number of commands listed is controlled by `list-command-history-max'. @@ -4821,7 +4283,6 @@ Calls value of `list-command-history-filter' (if non-nil) on each history element to judge if that element should be excluded from the list. The buffer is left in Command History mode." t nil) - (autoload 'command-history "chistory" "\ Examine commands from variable `command-history' in a buffer. The number of commands listed is controlled by `list-command-history-max'. @@ -4834,13 +4295,14 @@ and digits provide prefix arguments. Tab does not indent. This command always recompiles the Command History listing and runs the normal hook `command-history-hook'." t nil) - (register-definition-prefixes "chistory" '("command-history-" "default-command-history-filter" "list-command-history-")) -;;;*** -;;;### (autoloads nil "cl-font-lock" "progmodes/cl-font-lock.el" -;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cl-extra.el + +(register-definition-prefixes "cl-extra" '("cl-")) + + ;;; Generated autoloads from progmodes/cl-font-lock.el (defvar cl-font-lock-built-in-mode nil "\ @@ -4850,9 +4312,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `cl-font-lock-built-in-mode'.") - (custom-autoload 'cl-font-lock-built-in-mode "cl-font-lock" nil) - (autoload 'cl-font-lock-built-in-mode "cl-font-lock" "\ Highlight built-in functions, variables, and types in `lisp-mode'. @@ -4871,17 +4331,13 @@ evaluate `(default-value \\='cl-font-lock-built-in-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "cl-font-lock" '("cl-font-lock-")) -;;;*** -;;;### (autoloads nil "cl-generic" "emacs-lisp/cl-generic.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from emacs-lisp/cl-generic.el -(push (purecopy '(cl-generic 1 0)) package--builtin-versions) +(push (purecopy '(cl-generic 1 0)) package--builtin-versions) (autoload 'cl-defgeneric "cl-generic" "\ Create a generic function NAME. DOC-STRING is the base documentation for this class. A generic @@ -4895,17 +4351,13 @@ OPTIONS-AND-METHODS currently understands: - (:method [QUALIFIERS...] ARGS &rest BODY) DEFAULT-BODY, if present, is used as the body of a default method. -\(fn NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest DEFAULT-BODY)" nil t) - +(fn NAME ARGS [DOC-STRING] [OPTIONS-AND-METHODS...] &rest DEFAULT-BODY)" nil t) (function-put 'cl-defgeneric 'lisp-indent-function '2) - (function-put 'cl-defgeneric 'doc-string-elt '3) - (autoload 'cl-generic-define "cl-generic" "\ -\(fn NAME ARGS OPTIONS)" nil nil) - +(fn NAME ARGS OPTIONS)" nil nil) (autoload 'cl-defmethod "cl-generic" "\ Define a new method for generic function NAME. This defines an implementation of NAME to use for invocations @@ -4936,7 +4388,7 @@ the method is combined with other methods, including: :around - Method will be called around everything else The absence of QUALIFIER means this is a \"primary\" method. The set of acceptable qualifiers and their meaning is defined -\(and can be extended) by the methods of `cl-generic-combine-methods'. +(and can be extended) by the methods of `cl-generic-combine-methods'. ARGS can also include so-called context specializers, introduced by `&context' (which should appear right after the mandatory arguments, @@ -4945,30 +4397,22 @@ EXPR is an Elisp expression whose value should match TYPE for the method to be applicable. The set of acceptable TYPEs (also called \"specializers\") is defined -\(and can be extended) by the various methods of `cl-generic-generalizers'. - -\(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" nil t) +(and can be extended) by the various methods of `cl-generic-generalizers'. +(fn NAME [EXTRA] [QUALIFIER] ARGS &rest [DOCSTRING] BODY)" nil t) (function-put 'cl-defmethod 'doc-string-elt 'cl--defmethod-doc-pos) - (function-put 'cl-defmethod 'lisp-indent-function 'defun) - (autoload 'cl-generic-define-method "cl-generic" "\ -\(fn NAME QUALIFIERS ARGS CALL-CON FUNCTION)" nil nil) - +(fn NAME QUALIFIERS ARGS CALL-CON FUNCTION)" nil nil) (autoload 'cl-find-method "cl-generic" "\ -\(fn GENERIC QUALIFIERS SPECIALIZERS)" nil nil) - +(fn GENERIC QUALIFIERS SPECIALIZERS)" nil nil) (register-definition-prefixes "cl-generic" '("cl-")) -;;;*** -;;;### (autoloads nil "cl-indent" "emacs-lisp/cl-indent.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from emacs-lisp/cl-indent.el (autoload 'common-lisp-indent-function "cl-indent" "\ @@ -5036,7 +4480,7 @@ property are: specifies how to indent the associated argument. For example, the function `case' has an indent property -\(4 &rest (&whole 2 &rest 1)), meaning: +(4 &rest (&whole 2 &rest 1)), meaning: * indent the first argument by 4. * arguments after the first should be lists, and there may be any number of them. The first list element has an offset of 2, all the rest @@ -5047,18 +4491,15 @@ If the current mode is actually `emacs-lisp-mode', look for a at `common-lisp-indent-function' and, if set, use its value instead. -\(fn INDENT-POINT STATE)" nil nil) - +(fn INDENT-POINT STATE)" nil nil) (register-definition-prefixes "cl-indent" '("common-lisp-" "lisp-")) -;;;*** -;;;### (autoloads nil "cl-lib" "emacs-lisp/cl-lib.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/cl-lib.el -(push (purecopy '(cl-lib 1 0)) package--builtin-versions) - -(define-obsolete-variable-alias 'custom-print-functions 'cl-custom-print-functions "24.3") +(push (purecopy '(cl-lib 1 0)) package--builtin-versions) +(define-obsolete-variable-alias 'custom-print-functions 'cl-custom-print-functions "\ +24.3") (defvar cl-custom-print-functions nil "\ This is a list of functions that format user objects for printing. Each function is called in turn with three arguments: the object, the @@ -5068,7 +4509,6 @@ printer proceeds to the next function on the list. This variable is not used at present, but it is defined in hopes that a future Emacs interpreter will be able to use it.") - (autoload 'cl-incf "cl-lib" "\ Increment PLACE by X (1 by default). PLACE may be a symbol, or any generalized variable allowed by `setf'. @@ -5077,8 +4517,7 @@ The return value is the incremented value of PLACE. If X is specified, it should be an expression that should evaluate to a number. -\(fn PLACE &optional X)" nil t) - +(fn PLACE &optional X)" nil t) (defvar cl-old-struct-compat-mode nil "\ Non-nil if Cl-Old-Struct-Compat mode is enabled. See the `cl-old-struct-compat-mode' command @@ -5086,9 +4525,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `cl-old-struct-compat-mode'.") - (custom-autoload 'cl-old-struct-compat-mode "cl-lib" nil) - (autoload 'cl-old-struct-compat-mode "cl-lib" "\ Enable backward compatibility with old-style structs. @@ -5111,32 +4548,31 @@ evaluate `(default-value \\='cl-old-struct-compat-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "cl-lib" '("cl-")) -;;;*** -;;;### (autoloads nil "cl-print" "emacs-lisp/cl-print.el" (0 0 0 -;;;;;; 0)) +;;; Generated autoloads from emacs-lisp/cl-macs.el + +(register-definition-prefixes "cl-macs" '("cl-" "foo" "function-form")) + + ;;; Generated autoloads from emacs-lisp/cl-print.el -(push (purecopy '(cl-print 1 0)) package--builtin-versions) +(push (purecopy '(cl-print 1 0)) package--builtin-versions) (autoload 'cl-print-object "cl-print" "\ Dispatcher to print OBJECT on STREAM according to its type. You can add methods to it to customize the output. But if you just want to print something, don't call this directly: call other entry points instead, such as `cl-prin1'. -\(fn OBJECT STREAM)" nil nil) - +(fn OBJECT STREAM)" nil nil) (autoload 'cl-print-expand-ellipsis "cl-print" "\ Print the expansion of an ellipsis to STREAM. VALUE should be the value of the `cl-print-ellipsis' text property which was attached to the ellipsis by `cl-prin1'. -\(fn VALUE STREAM)" nil nil) - +(fn VALUE STREAM)" nil nil) (autoload 'cl-prin1 "cl-print" "\ Print OBJECT on STREAM according to its type. Output is further controlled by the variables @@ -5144,13 +4580,11 @@ Output is further controlled by the variables variables for the standard printing functions. See Info node `(elisp)Output Variables'. -\(fn OBJECT &optional STREAM)" nil nil) - +(fn OBJECT &optional STREAM)" nil nil) (autoload 'cl-prin1-to-string "cl-print" "\ Return a string containing the `cl-prin1'-printed representation of OBJECT. -\(fn OBJECT)" nil nil) - +(fn OBJECT)" nil nil) (autoload 'cl-print-to-string-with-limit "cl-print" "\ Return a string containing a printed representation of VALUE. Attempt to get the length of the returned string under LIMIT @@ -5167,13 +4601,15 @@ this function with `cl-prin1-expand-ellipsis' to expand an ellipsis, abbreviating the expansion to stay within a size limit. -\(fn PRINT-FUNCTION VALUE LIMIT)" nil nil) - +(fn PRINT-FUNCTION VALUE LIMIT)" nil nil) (register-definition-prefixes "cl-print" '("cl-print-" "help-byte-code")) -;;;*** -;;;### (autoloads nil "cmacexp" "progmodes/cmacexp.el" (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/cl-seq.el + +(register-definition-prefixes "cl-seq" '("cl--")) + + ;;; Generated autoloads from progmodes/cmacexp.el (autoload 'c-macro-expand "cmacexp" "\ @@ -5189,13 +4625,10 @@ otherwise use `c-macro-cppflags'. Noninteractive args are START, END, SUBST. For use inside Lisp programs, see also `c-macro-expansion'. -\(fn START END SUBST)" t nil) - +(fn START END SUBST)" t nil) (register-definition-prefixes "cmacexp" '("c-macro-")) -;;;*** -;;;### (autoloads nil "cmuscheme" "cmuscheme.el" (0 0 0 0)) ;;; Generated autoloads from cmuscheme.el (autoload 'run-scheme "cmuscheme" "\ @@ -5209,15 +4642,12 @@ Note that this may lose due to a timing error if the Scheme processor discards input when it starts up. Runs the hook `inferior-scheme-mode-hook' (after the `comint-mode-hook' is run). -\(Type \\[describe-mode] in the process buffer for a list of commands.) - -\(fn CMD)" t nil) +(Type \\[describe-mode] in the process buffer for a list of commands.) +(fn CMD)" t nil) (register-definition-prefixes "cmuscheme" '("cmuscheme-load-hook" "inferior-scheme-" "scheme-" "switch-to-scheme")) -;;;*** -;;;### (autoloads nil "color" "color.el" (0 0 0 0)) ;;; Generated autoloads from color.el (autoload 'color-name-to-rgb "color" "\ @@ -5236,13 +4666,10 @@ Optional argument FRAME specifies the frame where the color is to be displayed. If FRAME is omitted or nil, use the selected frame. If FRAME cannot display COLOR, return nil. -\(fn COLOR &optional FRAME)" nil nil) - +(fn COLOR &optional FRAME)" nil nil) (register-definition-prefixes "color" '("color-")) -;;;*** -;;;### (autoloads nil "comint" "comint.el" (0 0 0 0)) ;;; Generated autoloads from comint.el (defvar comint-output-filter-functions '(ansi-color-process-output comint-postoutput-scroll-to-bottom comint-watch-for-password-prompt) "\ @@ -5257,7 +4684,6 @@ See also `comint-preoutput-filter-functions'. You can use `add-hook' to add functions to this list either globally or locally.") - (autoload 'make-comint-in-buffer "comint" "\ Make a Comint process NAME in BUFFER, running PROGRAM. If BUFFER is nil, it defaults to NAME surrounded by `*'s. @@ -5277,8 +4703,7 @@ If PROGRAM is a string, any more args are arguments to PROGRAM. Return the (possibly newly created) process buffer. -\(fn NAME BUFFER PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) - +(fn NAME BUFFER PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) (autoload 'make-comint "comint" "\ Make a Comint process NAME in a buffer, running PROGRAM. The name of the buffer is made by surrounding NAME with `*'s. @@ -5293,8 +4718,7 @@ If PROGRAM is a string, any more args are arguments to PROGRAM. Returns the (possibly newly created) process buffer. -\(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) - +(fn NAME PROGRAM &optional STARTFILE &rest SWITCHES)" nil nil) (autoload 'comint-run "comint" "\ Run PROGRAM in a Comint buffer and switch to that buffer. @@ -5307,79 +4731,66 @@ hooks on this symbol are run in the buffer. See `make-comint' and `comint-exec'. -\(fn PROGRAM &optional SWITCHES)" t nil) - +(fn PROGRAM &optional SWITCHES)" t nil) (function-put 'comint-run 'interactive-only 'make-comint) - (defvar comint-file-name-prefix (purecopy "") "\ Prefix prepended to absolute file names taken from process input. This is used by Comint's and shell's completion functions, and by shell's directory tracking functions.") - (autoload 'comint-redirect-send-command "comint" "\ Send COMMAND to process in current buffer, with output to OUTPUT-BUFFER. With prefix arg ECHO, echo output in process buffer. If NO-DISPLAY is non-nil, do not show the output buffer. -\(fn COMMAND OUTPUT-BUFFER ECHO &optional NO-DISPLAY)" t nil) - +(fn COMMAND OUTPUT-BUFFER ECHO &optional NO-DISPLAY)" t nil) (autoload 'comint-redirect-send-command-to-process "comint" "\ Send COMMAND to PROCESS, with output to OUTPUT-BUFFER. With prefix arg, echo output in process buffer. If NO-DISPLAY is non-nil, do not show the output buffer. -\(fn COMMAND OUTPUT-BUFFER PROCESS ECHO &optional NO-DISPLAY)" t nil) - +(fn COMMAND OUTPUT-BUFFER PROCESS ECHO &optional NO-DISPLAY)" t nil) (autoload 'comint-redirect-results-list "comint" "\ Send COMMAND to current process. Return a list of expressions in the output which match REGEXP. REGEXP-GROUP is the regular expression group in REGEXP to use. -\(fn COMMAND REGEXP REGEXP-GROUP)" nil nil) - +(fn COMMAND REGEXP REGEXP-GROUP)" nil nil) (autoload 'comint-redirect-results-list-from-process "comint" "\ Send COMMAND to PROCESS. Return a list of expressions in the output which match REGEXP. REGEXP-GROUP is the regular expression group in REGEXP to use. -\(fn PROCESS COMMAND REGEXP REGEXP-GROUP)" nil nil) - +(fn PROCESS COMMAND REGEXP REGEXP-GROUP)" nil nil) (register-definition-prefixes "comint" '("comint-")) -;;;*** -;;;### (autoloads nil "comp" "emacs-lisp/comp.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/comp.el -(put 'no-native-compile 'safe-local-variable 'booleanp) +(put 'no-native-compile 'safe-local-variable 'booleanp) (autoload 'comp-subr-trampoline-install "comp" "\ Make SUBR-NAME effectively advice-able when called from native code. -\(fn SUBR-NAME)" nil nil) - +(fn SUBR-NAME)" nil nil) (autoload 'comp-c-func-name "comp" "\ Given NAME, return a name suitable for the native code. Add PREFIX in front of it. If FIRST is not nil, pick the first available name ignoring compilation context and potential name clashes. -\(fn NAME PREFIX &optional FIRST)" nil nil) - +(fn NAME PREFIX &optional FIRST)" nil nil) (autoload 'comp-clean-up-stale-eln "comp" "\ Remove all FILE*.eln* files found in `native-comp-eln-load-path'. The files to be removed are those produced from the original source filename (including FILE). -\(fn FILE)" nil nil) - +(fn FILE)" nil nil) (autoload 'comp-lookup-eln "comp" "\ Given a Lisp source FILENAME return the corresponding .eln file if found. Search happens in `native-comp-eln-load-path'. -\(fn FILENAME)" nil nil) - +(fn FILENAME)" nil nil) (autoload 'native-compile "comp" "\ Compile FUNCTION-OR-FILE into native code. This is the synchronous entry-point for the Emacs Lisp native @@ -5392,8 +4803,7 @@ If FUNCTION-OR-FILE is a filename, return the filename of the compiled object. If FUNCTION-OR-FILE is a function symbol or a form, return the compiled function. -\(fn FUNCTION-OR-FILE &optional OUTPUT)" nil nil) - +(fn FUNCTION-OR-FILE &optional OUTPUT)" nil nil) (autoload 'batch-native-compile "comp" "\ Perform batch native compilation of remaining command-line arguments. @@ -5405,8 +4815,7 @@ as part of building the source tarball, in which case the .eln file will be placed under the native-lisp/ directory (actually, in the last directory in `native-comp-eln-load-path'). -\(fn &optional FOR-TARBALL)" nil nil) - +(fn &optional FOR-TARBALL)" nil nil) (autoload 'batch-byte+native-compile "comp" "\ Like `batch-native-compile', but used for bootstrap. Generate .elc files in addition to the .eln files. @@ -5414,7 +4823,6 @@ Force the produced .eln to be outputted in the eln system directory (the last entry in `native-comp-eln-load-path') unless `native-compile-target-directory' is non-nil. If the environment variable \"NATIVE_DISABLED\" is set, only byte compile." nil nil) - (autoload 'native-compile-async "comp" "\ Compile FILES asynchronously. FILES is one file or a list of filenames or directories. @@ -5434,21 +4842,20 @@ a function -- A function selecting files with matching names. The variable `native-comp-async-jobs-number' specifies the number of (commands) to run simultaneously. -\(fn FILES &optional RECURSIVELY LOAD SELECTOR)" nil nil) - +(fn FILES &optional RECURSIVELY LOAD SELECTOR)" nil nil) (register-definition-prefixes "comp" '("comp-" "make-comp-edge" "native-" "no-native-compile")) -;;;*** -;;;### (autoloads nil "comp-cstr" "emacs-lisp/comp-cstr.el" (0 0 -;;;;;; 0 0)) +;;; Generated autoloads from cedet/semantic/wisent/comp.el + +(register-definition-prefixes "semantic/wisent/comp" '("wisent-")) + + ;;; Generated autoloads from emacs-lisp/comp-cstr.el (register-definition-prefixes "comp-cstr" '("comp-" "with-comp-cstr-accessors")) -;;;*** -;;;### (autoloads nil "compare-w" "vc/compare-w.el" (0 0 0 0)) ;;; Generated autoloads from vc/compare-w.el (autoload 'compare-windows "compare-w" "\ @@ -5480,70 +4887,52 @@ on first call it advances points to the next difference, on second call it synchronizes points by skipping the difference, on third call it again advances points to the next difference and so on. -\(fn IGNORE-WHITESPACE)" t nil) - +(fn IGNORE-WHITESPACE)" t nil) (register-definition-prefixes "compare-w" '("compare-")) -;;;*** -;;;### (autoloads nil "compface" "image/compface.el" (0 0 0 0)) ;;; Generated autoloads from image/compface.el (register-definition-prefixes "compface" '("uncompface")) -;;;*** -;;;### (autoloads nil "compile" "progmodes/compile.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/compile.el (defvar compilation-mode-hook nil "\ List of hook functions run by `compilation-mode'.") - (custom-autoload 'compilation-mode-hook "compile" t) - (defvar compilation-start-hook nil "\ Hook run after starting a new compilation process. The hook is run with one argument, the new process.") - (custom-autoload 'compilation-start-hook "compile" t) - (defvar compilation-window-height nil "\ Number of lines in a compilation window. If nil, use Emacs default.") - (custom-autoload 'compilation-window-height "compile" t) - (defvar compilation-process-setup-function #'ignore "\ Function to call to customize the compilation process. This function is called immediately before the compilation process is started. It can be used to set any variables or functions that are used while processing the output of the compilation process.") - (defvar compilation-buffer-name-function #'compilation--default-buffer-name "\ Function to compute the name of a compilation buffer. The function receives one argument, the name of the major mode of the compilation buffer. It should return a string. By default, it returns `(concat \"*\" (downcase name-of-mode) \"*\")'.") - (defvar compilation-finish-functions nil "\ Functions to call when a compilation process finishes. Each function is called with two arguments: the compilation buffer, and a string describing how the process finished.") (put 'compilation-directory 'safe-local-variable 'stringp) - (defvar compilation-ask-about-save t "\ Non-nil means \\[compile] asks which buffers to save before compiling. Otherwise, it saves all modified buffers without asking.") - (custom-autoload 'compilation-ask-about-save "compile" t) - (defvar compilation-search-path '(nil) "\ List of directories to search for source files named in error messages. Elements should be directory names, not file names of directories. The value nil as an element means to try the default directory.") - (custom-autoload 'compilation-search-path "compile" t) - (defvar compile-command (purecopy "make -k ") "\ Last shell command used to do a compilation; default for next compilation. @@ -5561,17 +4950,13 @@ You might also use mode hooks to specify it in certain modes, like this: (file-name-sans-extension buffer-file-name)))))))) It's often useful to leave a space at the end of the value.") - (custom-autoload 'compile-command "compile" t) (put 'compile-command 'safe-local-variable (lambda (a) (and (stringp a) (or (not (boundp 'compilation-read-command)) compilation-read-command)))) - (defvar compilation-disable-input nil "\ If non-nil, send end-of-file as compilation process input. This only affects platforms that support asynchronous processes (see `start-process'); synchronous compilation processes never accept input.") - (custom-autoload 'compilation-disable-input "compile" t) - (autoload 'compile "compile" "\ Compile the program including the current buffer. Default: run `make'. Runs COMMAND, a shell command, in a separate process asynchronously @@ -5601,8 +4986,7 @@ The name used for the buffer is actually whatever is returned by the function in `compilation-buffer-name-function', so you can set that to a function that generates a unique name. -\(fn COMMAND &optional COMINT)" t nil) - +(fn COMMAND &optional COMINT)" t nil) (autoload 'compilation-start "compile" "\ Run compilation command COMMAND (low level interface). If COMMAND starts with a cd command, that becomes the `default-directory'. @@ -5628,8 +5012,7 @@ point is not changed. Returns the compilation buffer created. -\(fn COMMAND &optional MODE NAME-FUNCTION HIGHLIGHT-REGEXP CONTINUE)" nil nil) - +(fn COMMAND &optional MODE NAME-FUNCTION HIGHLIGHT-REGEXP CONTINUE)" nil nil) (autoload 'compilation-mode "compile" "\ Major mode for compilation log buffers. \\To visit the source for a line-numbered error, @@ -5640,10 +5023,8 @@ Runs `compilation-mode-hook' with `run-mode-hooks' (which see). \\{compilation-mode-map} -\(fn &optional NAME-OF-MODE)" t nil) - +(fn &optional NAME-OF-MODE)" t nil) (put 'define-compilation-mode 'doc-string-elt 3) - (autoload 'compilation-shell-minor-mode "compile" "\ Toggle Compilation Shell minor mode. @@ -5667,8 +5048,7 @@ evaluate `compilation-shell-minor-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'compilation-minor-mode "compile" "\ Toggle Compilation minor mode. @@ -5691,19 +5071,30 @@ evaluate `compilation-minor-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'compilation-next-error-function "compile" "\ Advance to the next error message and visit the file where the error was. This is the value of `next-error-function' in Compilation buffers. -\(fn N &optional RESET)" t nil) - +(fn N &optional RESET)" t nil) (register-definition-prefixes "compile" '("compil" "define-compilation-mode" "kill-compilation" "recompile")) -;;;*** -;;;### (autoloads nil "completion" "completion.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/compile.el + +(register-definition-prefixes "srecode/compile" '("srecode-")) + + +;;; Generated autoloads from cedet/semantic/analyze/complete.el + +(register-definition-prefixes "semantic/analyze/complete" '("semantic-analyze-")) + + +;;; Generated autoloads from cedet/semantic/complete.el + +(register-definition-prefixes "semantic/complete" '("semantic-")) + + ;;; Generated autoloads from completion.el (defvar dynamic-completion-mode nil "\ @@ -5713,9 +5104,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `dynamic-completion-mode'.") - (custom-autoload 'dynamic-completion-mode "completion" nil) - (autoload 'dynamic-completion-mode "completion" "\ Toggle dynamic word-completion on or off. @@ -5734,14 +5123,10 @@ evaluate `(default-value \\='dynamic-completion-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "completion" '("*c-def-regexp*" "*lisp-def-regexp*" "accept-completion" "add-" "cdabbrev-" "check-completion-length" "clear-all-completions" "cmpl-" "complet" "current-completion-source" "delete-completion" "enable-completion" "find-" "inside-locate-completion-entry" "interactive-completion-string-reader" "kill-" "list-all-completions" "load-completions-from-file" "make-c" "next-cdabbrev" "num-cmpl-sources" "reset-cdabbrev" "save" "set-c" "symbol-" "use-completion-")) -;;;*** -;;;### (autoloads nil "conf-mode" "textmodes/conf-mode.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from textmodes/conf-mode.el (autoload 'conf-mode "conf-mode" "\ @@ -5775,14 +5160,12 @@ See also `conf-space-mode', `conf-colon-mode', `conf-javaprop-mode', \\{conf-mode-map} -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-unix-mode "conf-mode" "\ Conf Mode starter for Unix style Conf files. Comments start with `#'. For details see `conf-mode'. -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-windows-mode "conf-mode" "\ Conf Mode starter for Windows style Conf files. Comments start with `;'. @@ -5790,15 +5173,14 @@ For details see `conf-mode'. Example: ; Conf mode font-locks this right on Windows and with \\[conf-windows-mode] -\[ExtShellFolderViews] +[ExtShellFolderViews] Default={5984FFE0-28D4-11CF-AE66-08002B2E1262} {5984FFE0-28D4-11CF-AE66-08002B2E1262}={5984FFE0-28D4-11CF-AE66-08002B2E1262} -\[{5984FFE0-28D4-11CF-AE66-08002B2E1262}] +[{5984FFE0-28D4-11CF-AE66-08002B2E1262}] PersistMoniker=file://Folder.htt -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-javaprop-mode "conf-mode" "\ Conf Mode starter for Java properties files. Comments start with `#' but are also recognized with `//' or @@ -5816,8 +5198,7 @@ x.1 = x.2.y.1.z.1 = x.2.y.1.z.2.zz = -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-space-mode "conf-mode" "\ Conf Mode starter for space separated conf files. \"Assignments\" are with ` '. Keywords before the parameters are @@ -5841,14 +5222,12 @@ class desktop add /dev/audio desktop add /dev/mixer desktop -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-space-keywords "conf-mode" "\ Enter Conf Space mode using regexp KEYWORDS to match the keywords. See `conf-space-mode'. -\(fn KEYWORDS)" t nil) - +(fn KEYWORDS)" t nil) (autoload 'conf-colon-mode "conf-mode" "\ Conf Mode starter for Colon files. \"Assignments\" are with `:'. @@ -5859,8 +5238,7 @@ For details see `conf-mode'. Example: : \"\\241\" exclamdown : \"\\242\" cent -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-ppd-mode "conf-mode" "\ Conf Mode starter for Adobe/CUPS PPD files. Comments start with `*%' and \"assignments\" are with `:'. @@ -5871,8 +5249,7 @@ For details see `conf-mode'. Example: *DefaultTransfer: Null *Transfer Null.Inverse: \"{ 1 exch sub }\" -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-xdefaults-mode "conf-mode" "\ Conf Mode starter for Xdefaults files. Comments start with `!' and \"assignments\" are with `:'. @@ -5883,8 +5260,7 @@ For details see `conf-mode'. Example: *background: gray99 *foreground: black -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-toml-mode "conf-mode" "\ Conf Mode starter for TOML files. Comments start with `#' and \"assignments\" are with `='. @@ -5892,11 +5268,10 @@ For details see `conf-mode'. Example: # Conf mode font-locks this right with \\[conf-toml-mode] -\[entry] +[entry] value = \"some string\" -\(fn)" t nil) - +(fn)" t nil) (autoload 'conf-desktop-mode "conf-mode" "\ Conf Mode started for freedesktop.org Desktop files. Comments start with `#' and \"assignments\" are with `='. @@ -5909,13 +5284,15 @@ For details see `conf-mode'. Exec=gimp-2.8 %U Terminal=false -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "conf-mode" '("conf-")) -;;;*** -;;;### (autoloads nil "cookie1" "play/cookie1.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/config.el + +(register-definition-prefixes "ede/config" '("ede-")) + + ;;; Generated autoloads from play/cookie1.el (autoload 'cookie "cookie1" "\ @@ -5925,33 +5302,27 @@ of load, ENDMSG at the end. Interactively, PHRASE-FILE defaults to `cookie-file', unless that is nil or a prefix argument is used. -\(fn PHRASE-FILE &optional STARTMSG ENDMSG)" t nil) - +(fn PHRASE-FILE &optional STARTMSG ENDMSG)" t nil) (autoload 'cookie-insert "cookie1" "\ Insert random phrases from PHRASE-FILE; COUNT of them. When the phrase file is read in, display STARTMSG at the beginning of load, ENDMSG at the end. -\(fn PHRASE-FILE &optional COUNT STARTMSG ENDMSG)" nil nil) - +(fn PHRASE-FILE &optional COUNT STARTMSG ENDMSG)" nil nil) (autoload 'cookie-snarf "cookie1" "\ Read the PHRASE-FILE, return it as a vector of strings. Emit STARTMSG and ENDMSG before and after. Cache the result; second and subsequent calls on the same file won't go to disk. -\(fn PHRASE-FILE &optional STARTMSG ENDMSG)" nil nil) - +(fn PHRASE-FILE &optional STARTMSG ENDMSG)" nil nil) (register-definition-prefixes "cookie1" '("cookie")) -;;;*** -;;;### (autoloads nil "copyright" "emacs-lisp/copyright.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from emacs-lisp/copyright.el + (put 'copyright-at-end-flag 'safe-local-variable 'booleanp) (put 'copyright-names-regexp 'safe-local-variable 'stringp) (put 'copyright-year-ranges 'safe-local-variable 'booleanp) - (autoload 'copyright-update "copyright" "\ Update copyright notice to indicate the current year. With prefix ARG, replace the years in the notice rather than adding @@ -5961,32 +5332,26 @@ following the copyright are updated as well. If non-nil, INTERACTIVEP tells the function to behave as when it's called interactively. -\(fn &optional ARG INTERACTIVEP)" t nil) - +(fn &optional ARG INTERACTIVEP)" t nil) (autoload 'copyright-fix-years "copyright" "\ Convert 2 digit years to 4 digit years. Uses heuristic: year >= 50 means 19xx, < 50 means 20xx. If `copyright-year-ranges' (which see) is non-nil, also independently replaces consecutive years with a range." t nil) - (autoload 'copyright "copyright" "\ Insert a copyright by $ORGANIZATION notice at cursor. -\(fn &optional STR ARG)" t nil) - +(fn &optional STR ARG)" t nil) (autoload 'copyright-update-directory "copyright" "\ Update copyright notice for all files in DIRECTORY matching MATCH. If FIX is non-nil, run `copyright-fix-years' instead. -\(fn DIRECTORY MATCH &optional FIX)" t nil) - +(fn DIRECTORY MATCH &optional FIX)" t nil) (register-definition-prefixes "copyright" '("copyright-")) -;;;*** -;;;### (autoloads nil "cperl-mode" "progmodes/cperl-mode.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from progmodes/cperl-mode.el + (put 'cperl-indent-level 'safe-local-variable 'integerp) (put 'cperl-brace-offset 'safe-local-variable 'integerp) (put 'cperl-continued-brace-offset 'safe-local-variable 'integerp) @@ -5995,7 +5360,6 @@ If FIX is non-nil, run `copyright-fix-years' instead. (put 'cperl-extra-newline-before-brace 'safe-local-variable 'booleanp) (put 'cperl-merge-trailing-else 'safe-local-variable 'booleanp) (put 'cperl-file-style 'safe-local-variable 'stringp) - (autoload 'cperl-mode "cperl-mode" "\ Major mode for editing Perl code. Expression and list commands understand all C brackets. @@ -6065,10 +5429,10 @@ into \\{cperl-mode-map} Setting the variable `cperl-font-lock' to t switches on `font-lock-mode' -\(even with older Emacsen), `cperl-electric-lbrace-space' to t switches +(even with older Emacsen), `cperl-electric-lbrace-space' to t switches on electric space between $ and {, `cperl-electric-parens-string' is the string that contains parentheses that should be electric in CPerl -\(see also `cperl-electric-parens-mark' and `cperl-electric-parens'), +(see also `cperl-electric-parens-mark' and `cperl-electric-parens'), setting `cperl-electric-keywords' enables electric expansion of control structures in CPerl. `cperl-electric-linefeed' governs which one of two linefeed behavior is preferable. You can enable all these @@ -6083,7 +5447,7 @@ If your site has perl5 documentation in info format, you can use commands These keys run commands `cperl-info-on-current-command' and `cperl-info-on-command', which one is which is controlled by variable `cperl-info-on-command-no-prompt' and `cperl-clobber-lisp-bindings' -\(in turn affected by `cperl-hairy'). +(in turn affected by `cperl-hairy'). Even if you have no info-format documentation, short one-liner-style help is available on \\[cperl-get-help], and one can run perldoc or @@ -6171,21 +5535,16 @@ DO NOT FORGET to read micro-docs (available from `Perl' menu) or as help on variables `cperl-tips', `cperl-problems', `cperl-praise', `cperl-speed'. -\(fn)" t nil) - +(fn)" t nil) (autoload 'cperl-perldoc "cperl-mode" "\ Run `perldoc' on WORD. -\(fn WORD)" t nil) - +(fn WORD)" t nil) (autoload 'cperl-perldoc-at-point "cperl-mode" "\ Run a `perldoc' on the word around point." t nil) - (register-definition-prefixes "cperl-mode" '("cperl-" "pod2man-program")) -;;;*** -;;;### (autoloads nil "cpp" "progmodes/cpp.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cpp.el (autoload 'cpp-highlight-buffer "cpp" "\ @@ -6194,16 +5553,22 @@ This command pops up a buffer which you should edit to specify what kind of highlighting to use, and the criteria for highlighting. A prefix arg suppresses display of that buffer. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (autoload 'cpp-parse-edit "cpp" "\ Edit display information for cpp conditionals." t nil) - (register-definition-prefixes "cpp" '("cpp-")) -;;;*** -;;;### (autoloads nil "crm" "emacs-lisp/crm.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/cpp.el + +(register-definition-prefixes "srecode/cpp" '("srecode-")) + + +;;; Generated autoloads from cedet/ede/cpp-root.el + +(register-definition-prefixes "ede/cpp-root" '("ede-cpp-root-")) + + ;;; Generated autoloads from emacs-lisp/crm.el (autoload 'completing-read-multiple "crm" "\ @@ -6225,13 +5590,15 @@ contents of the minibuffer are \"alice,bob,eve\" and point is between This function returns a list of the strings that were read, with empty strings removed. -\(fn PROMPT TABLE &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)" nil nil) - +(fn PROMPT TABLE &optional PREDICATE REQUIRE-MATCH INITIAL-INPUT HIST DEF INHERIT-INPUT-METHOD)" nil nil) (register-definition-prefixes "crm" '("crm-")) -;;;*** -;;;### (autoloads nil "css-mode" "textmodes/css-mode.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/cscope.el + +(register-definition-prefixes "semantic/symref/cscope" '("semantic-symref-cscope--line-re")) + + ;;; Generated autoloads from textmodes/css-mode.el (autoload 'css-mode "css-mode" "\ @@ -6255,14 +5622,12 @@ be used to fill comments. \\{css-mode-map} -\(fn)" t nil) +(fn)" t nil) (add-to-list 'auto-mode-alist '("\\.scss\\'" . scss-mode)) - (autoload 'scss-mode "css-mode" "\ Major mode to edit \"Sassy CSS\" files. -\(fn)" t nil) - +(fn)" t nil) (autoload 'css-lookup-symbol "css-mode" "\ Display the CSS documentation for SYMBOL, as found on MDN. When this command is used interactively, it picks a default @@ -6270,13 +5635,20 @@ symbol based on the CSS text before point -- either an @-keyword, a property name, a pseudo-class, or a pseudo-element, depending on what is seen near point. -\(fn SYMBOL)" t nil) - +(fn SYMBOL)" t nil) (register-definition-prefixes "css-mode" '("css-" "scss-")) -;;;*** -;;;### (autoloads nil "cua-base" "emulation/cua-base.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/ctxt.el + +(register-definition-prefixes "srecode/ctxt" '("srecode-")) + + +;;; Generated autoloads from cedet/semantic/ctxt.el + +(register-definition-prefixes "semantic/ctxt" '("semantic-")) + + ;;; Generated autoloads from emulation/cua-base.el (defvar cua-mode nil "\ @@ -6286,9 +5658,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `cua-mode'.") - (custom-autoload 'cua-mode "cua-base" nil) - (autoload 'cua-mode "cua-base" "\ Toggle Common User Access style editing (CUA mode). @@ -6324,25 +5694,19 @@ evaluate `(default-value \\='cua-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'cua-selection-mode "cua-base" "\ Enable CUA selection mode without the C-z/C-x/C-c/C-v bindings. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (register-definition-prefixes "cua-base" '("cua-")) -;;;*** -;;;### (autoloads nil "cua-gmrk" "emulation/cua-gmrk.el" (0 0 0 0)) ;;; Generated autoloads from emulation/cua-gmrk.el (register-definition-prefixes "cua-gmrk" '("cua-")) -;;;*** -;;;### (autoloads nil "cua-rect" "emulation/cua-rect.el" (0 0 0 0)) ;;; Generated autoloads from emulation/cua-rect.el (autoload 'cua-rectangle-mark-mode "cua-rect" "\ @@ -6365,21 +5729,16 @@ evaluate `cua-rectangle-mark-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "cua-rect" '("cua-")) -;;;*** -;;;### (autoloads nil "cursor-sensor" "emacs-lisp/cursor-sensor.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/cursor-sensor.el (defvar cursor-sensor-inhibit nil "\ When non-nil, suspend `cursor-sensor-mode' and `cursor-intangible-mode'. By convention, this is a list of symbols where each symbol stands for the \"cause\" of the suspension.") - (autoload 'cursor-intangible-mode "cursor-sensor" "\ Keep cursor outside of any `cursor-intangible' text property. @@ -6398,8 +5757,7 @@ evaluate `cursor-intangible-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'cursor-sensor-mode "cursor-sensor" "\ Handle the `cursor-sensor-functions' text property. @@ -6423,37 +5781,26 @@ evaluate `cursor-sensor-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "cursor-sensor" '("cursor-sensor-")) -;;;*** -;;;### (autoloads nil "cus-dep" "cus-dep.el" (0 0 0 0)) ;;; Generated autoloads from cus-dep.el (register-definition-prefixes "cus-dep" '("custom-" "generated-custom-dependencies-file")) -;;;*** -;;;### (autoloads nil "cus-edit" "cus-edit.el" (0 0 0 0)) ;;; Generated autoloads from cus-edit.el (defvar custom-browse-sort-alphabetically nil "\ If non-nil, sort customization group alphabetically in `custom-browse'.") - (custom-autoload 'custom-browse-sort-alphabetically "cus-edit" t) - (defvar custom-buffer-sort-alphabetically t "\ Whether to sort customization groups alphabetically in Custom buffer.") - (custom-autoload 'custom-buffer-sort-alphabetically "cus-edit" t) - (defvar custom-menu-sort-alphabetically nil "\ If non-nil, sort each customization group alphabetically in menus.") - (custom-autoload 'custom-menu-sort-alphabetically "cus-edit" t) - (autoload 'customize-set-value "cus-edit" "\ Set VARIABLE to VALUE, and return VALUE. VALUE is a Lisp object. @@ -6465,8 +5812,7 @@ If VARIABLE has a `custom-type' property, it must be a widget and the If given a prefix (or a COMMENT argument), also prompt for a comment. -\(fn VARIABLE VALUE &optional COMMENT)" t nil) - +(fn VARIABLE VALUE &optional COMMENT)" t nil) (autoload 'customize-set-variable "cus-edit" "\ Set the default for VARIABLE to VALUE, and return VALUE. VALUE is a Lisp object. @@ -6482,21 +5828,18 @@ If VARIABLE has a `custom-type' property, it must be a widget and the If given a prefix (or a COMMENT argument), also prompt for a comment. -\(fn VARIABLE VALUE &optional COMMENT)" t nil) - +(fn VARIABLE VALUE &optional COMMENT)" t nil) (autoload 'setopt "cus-edit" "\ Set VARIABLE/VALUE pairs, and return the final VALUE. This is like `setq', but is meant for user options instead of plain variables. This means that `setopt' will execute any `custom-set' form associated with VARIABLE. -\(fn [VARIABLE VALUE]...)" nil t) - +(fn [VARIABLE VALUE]...)" nil t) (autoload 'setopt--set "cus-edit" "\ -\(fn VARIABLE VALUE)" nil nil) - +(fn VARIABLE VALUE)" nil nil) (autoload 'customize-save-variable "cus-edit" "\ Set the default for VARIABLE to VALUE, and save it for future sessions. Return VALUE. @@ -6512,8 +5855,7 @@ If VARIABLE has a `custom-type' property, it must be a widget and the If given a prefix (or a COMMENT argument), also prompt for a comment. -\(fn VARIABLE VALUE &optional COMMENT)" t nil) - +(fn VARIABLE VALUE &optional COMMENT)" t nil) (autoload 'customize-push-and-save "cus-edit" "\ Add ELTS to LIST-VAR and save for future sessions, safely. ELTS should be a list. This function adds each entry to the @@ -6523,48 +5865,39 @@ If Emacs is initialized, call `customize-save-variable' to save the resulting list value now. Otherwise, add an entry to `after-init-hook' to save it after initialization. -\(fn LIST-VAR ELTS)" nil nil) - +(fn LIST-VAR ELTS)" nil nil) (autoload 'customize "cus-edit" "\ Select a customization buffer which you can use to set user options. User options are structured into \"groups\". Initially the top-level group `Emacs' and its immediate subgroups are shown; the contents of those subgroups are initially hidden." t nil) - (autoload 'customize-mode "cus-edit" "\ Customize options related to a major or minor mode. By default the current major mode is used. With a prefix argument or if the current major mode has no known group, prompt for the MODE to customize. -\(fn MODE)" t nil) - +(fn MODE)" t nil) (autoload 'customize-group "cus-edit" "\ Customize GROUP, which must be a customization group. If OTHER-WINDOW is non-nil, display in another window. -\(fn &optional GROUP OTHER-WINDOW)" t nil) - +(fn &optional GROUP OTHER-WINDOW)" t nil) (autoload 'customize-group-other-window "cus-edit" "\ Customize GROUP, which must be a customization group, in another window. -\(fn &optional GROUP)" t nil) - +(fn &optional GROUP)" t nil) (defalias 'customize-variable 'customize-option) - (autoload 'customize-option "cus-edit" "\ Customize SYMBOL, which must be a user option. -\(fn SYMBOL)" t nil) - +(fn SYMBOL)" t nil) (defalias 'customize-variable-other-window 'customize-option-other-window) - (autoload 'customize-option-other-window "cus-edit" "\ Customize SYMBOL, which must be a user option. Show the buffer in another window, but don't select it. -\(fn SYMBOL)" t nil) - +(fn SYMBOL)" t nil) (defvar customize-package-emacs-version-alist nil "\ Alist mapping versions of a package to Emacs versions. We use this for packages that have their own names, but are released @@ -6595,9 +5928,8 @@ The value of PACKAGE needs to be unique and it needs to match the PACKAGE value appearing in the :package-version keyword. Since the user might see the value in an error message, a good choice is the official name of the package, such as MH-E or Gnus.") - -(define-obsolete-function-alias 'customize-changed-options #'customize-changed "28.1") - +(define-obsolete-function-alias 'customize-changed-options #'customize-changed "\ +28.1") (autoload 'customize-changed "cus-edit" "\ Customize all settings whose meanings have changed in Emacs itself. This includes new user options and faces, and new customization @@ -6608,8 +5940,7 @@ release. With argument SINCE-VERSION (a string), customize all settings that were added or redefined since that version. -\(fn &optional SINCE-VERSION)" t nil) - +(fn &optional SINCE-VERSION)" t nil) (autoload 'customize-face "cus-edit" "\ Customize FACE, which should be a face name or nil. If FACE is nil, customize all faces. If FACE is actually a @@ -6620,8 +5951,7 @@ If OTHER-WINDOW is non-nil, display in another window. Interactively, when point is on text which has a face specified, suggest to customize that face, if it's customizable. -\(fn &optional FACE OTHER-WINDOW)" t nil) - +(fn &optional FACE OTHER-WINDOW)" t nil) (autoload 'customize-face-other-window "cus-edit" "\ Show customization buffer for face FACE in other window. If FACE is actually a face-alias, customize the face it is aliased to. @@ -6629,17 +5959,13 @@ If FACE is actually a face-alias, customize the face it is aliased to. Interactively, when point is on text which has a face specified, suggest to customize that face, if it's customizable. -\(fn &optional FACE)" t nil) - +(fn &optional FACE)" t nil) (autoload 'customize-unsaved "cus-edit" "\ Customize all options and faces set in this session but not saved." t nil) - (autoload 'customize-rogue "cus-edit" "\ Customize all user variables modified outside customize." t nil) - (autoload 'customize-saved "cus-edit" "\ Customize all saved options and faces." t nil) - (autoload 'customize-apropos "cus-edit" "\ Customize loaded options, faces and groups matching PATTERN. PATTERN can be a word, a list of words (separated by spaces), @@ -6651,28 +5977,23 @@ If TYPE is `options', include only options. If TYPE is `faces', include only faces. If TYPE is `groups', include only groups. -\(fn PATTERN &optional TYPE)" t nil) - +(fn PATTERN &optional TYPE)" t nil) (autoload 'customize-apropos-options "cus-edit" "\ Customize all loaded customizable options matching REGEXP. -\(fn REGEXP &optional IGNORED)" t nil) - +(fn REGEXP &optional IGNORED)" t nil) (autoload 'customize-apropos-faces "cus-edit" "\ Customize all loaded faces matching REGEXP. -\(fn REGEXP)" t nil) - +(fn REGEXP)" t nil) (autoload 'customize-apropos-groups "cus-edit" "\ Customize all loaded groups matching REGEXP. -\(fn REGEXP)" t nil) - +(fn REGEXP)" t nil) (autoload 'custom-prompt-customize-unsaved-options "cus-edit" "\ Prompt user to customize any unsaved customization options. Return nil if user chooses to customize, for use in `kill-emacs-query-functions'." nil nil) - (autoload 'custom-buffer-create "cus-edit" "\ Create a buffer containing OPTIONS. Optional NAME is the name of the buffer. @@ -6681,8 +6002,7 @@ SYMBOL is a customization option, and WIDGET is a widget for editing that option. DESCRIPTION is unused. -\(fn OPTIONS &optional NAME DESCRIPTION)" nil nil) - +(fn OPTIONS &optional NAME DESCRIPTION)" nil nil) (autoload 'custom-buffer-create-other-window "cus-edit" "\ Create a buffer containing OPTIONS, and display it in another window. The result includes selecting that window. @@ -6692,13 +6012,11 @@ SYMBOL is a customization option, and WIDGET is a widget for editing that option. DESCRIPTION is unused. -\(fn OPTIONS &optional NAME DESCRIPTION)" nil nil) - +(fn OPTIONS &optional NAME DESCRIPTION)" nil nil) (autoload 'customize-browse "cus-edit" "\ Create a tree browser for the customize hierarchy. -\(fn &optional GROUP)" t nil) - +(fn &optional GROUP)" t nil) (defvar custom-file nil "\ File used for storing customization information. The default is nil, which means to use your init file @@ -6709,8 +6027,8 @@ You can set this option through Custom, if you carefully read the last paragraph below. However, usually it is simpler to write something like the following in your init file: -\(setq custom-file \"~/.config/emacs-custom.el\") -\(load custom-file) +(setq custom-file \"~/.config/emacs-custom.el\") +(load custom-file) Note that both lines are necessary: the first line tells Custom to save all customizations in this file, but does not load it. @@ -6731,34 +6049,26 @@ want. You also have to put something like (load \"CUSTOM-FILE\") in your init file, where CUSTOM-FILE is the actual name of the file. Otherwise, Emacs will not load the file when it starts up, and hence will not set `custom-file' to that file either.") - (custom-autoload 'custom-file "cus-edit" t) - (autoload 'custom-save-all "cus-edit" "\ Save all customizations in `custom-file'." nil nil) - (autoload 'customize-save-customized "cus-edit" "\ Save all user options which have been set in this session." t nil) - (autoload 'custom-menu-create "cus-edit" "\ Create menu for customization group SYMBOL. The menu is in a format applicable to `easy-menu-define'. -\(fn SYMBOL)" nil nil) - +(fn SYMBOL)" nil nil) (autoload 'customize-menu-create "cus-edit" "\ Return a customize menu for customization group SYMBOL. If optional NAME is given, use that as the name of the menu. Otherwise the menu will be named `Customize'. The format is suitable for use with `easy-menu-define'. -\(fn SYMBOL &optional NAME)" nil nil) - +(fn SYMBOL &optional NAME)" nil nil) (register-definition-prefixes "cus-edit" '("Custom-" "cus" "widget-")) -;;;*** -;;;### (autoloads nil "cus-theme" "cus-theme.el" (0 0 0 0)) ;;; Generated autoloads from cus-theme.el (autoload 'customize-create-theme "cus-theme" "\ @@ -6770,42 +6080,38 @@ from the Custom save file. BUFFER, if non-nil, should be a buffer to use; the default is named *Custom Theme*. -\(fn &optional THEME BUFFER)" t nil) - +(fn &optional THEME BUFFER)" t nil) (autoload 'custom-theme-visit-theme "cus-theme" "\ Set up a Custom buffer to edit custom theme THEME. -\(fn THEME)" t nil) - +(fn THEME)" t nil) (autoload 'describe-theme "cus-theme" "\ Display a description of the Custom theme THEME (a symbol). -\(fn THEME)" t nil) - +(fn THEME)" t nil) (autoload 'customize-themes "cus-theme" "\ Display a selectable list of Custom themes. When called from Lisp, BUFFER should be the buffer to use; if omitted, a buffer named *Custom Themes* is used. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (register-definition-prefixes "cus-theme" '("custom-" "describe-theme-1")) -;;;*** -;;;### (autoloads nil "cvs-status" "vc/cvs-status.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/custom.el + +(register-definition-prefixes "ede/custom" '("ede-" "eieio-ede-old-variables")) + + ;;; Generated autoloads from vc/cvs-status.el (autoload 'cvs-status-mode "cvs-status" "\ Mode used for cvs status output. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "cvs-status" '("cvs-")) -;;;*** -;;;### (autoloads nil "cwarn" "progmodes/cwarn.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/cwarn.el (autoload 'cwarn-mode "cwarn" "\ @@ -6831,12 +6137,10 @@ evaluate `cwarn-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - -(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "24.1") - +(fn &optional ARG)" t nil) +(define-obsolete-function-alias 'turn-on-cwarn-mode 'cwarn-mode "\ +24.1") (put 'global-cwarn-mode 'globalized-minor-mode t) - (defvar global-cwarn-mode nil "\ Non-nil if Global Cwarn mode is enabled. See the `global-cwarn-mode' command @@ -6844,9 +6148,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `global-cwarn-mode'.") - (custom-autoload 'global-cwarn-mode "cwarn" nil) - (autoload 'global-cwarn-mode "cwarn" "\ Toggle Cwarn mode in all buffers. With prefix ARG, enable Global Cwarn mode if ARG is positive; @@ -6861,26 +6163,20 @@ Cwarn mode is enabled in all buffers where See `cwarn-mode' for more information on Cwarn mode. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "cwarn" '("cwarn-" "turn-on-cwarn-mode-if-enabled")) -;;;*** -;;;### (autoloads nil "cyril-util" "language/cyril-util.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from language/cyril-util.el (autoload 'cyrillic-encode-koi8-r-char "cyril-util" "\ Return KOI8-R external character code of CHAR if appropriate. -\(fn CHAR)" nil nil) - +(fn CHAR)" nil nil) (autoload 'cyrillic-encode-alternativnyj-char "cyril-util" "\ Return ALTERNATIVNYJ external character code of CHAR if appropriate. -\(fn CHAR)" nil nil) - +(fn CHAR)" nil nil) (autoload 'standard-display-cyrillic-translit "cyril-util" "\ Display a Cyrillic buffer using a transliteration. For readability, the table is slightly @@ -6892,19 +6188,16 @@ Possible values are listed in `cyrillic-language-alist'. If the argument is t, we use the default cyrillic transliteration. If the argument is nil, we return the display table to its standard state. -\(fn &optional CYRILLIC-LANGUAGE)" t nil) - +(fn &optional CYRILLIC-LANGUAGE)" t nil) (register-definition-prefixes "cyril-util" '("cyrillic-language-alist")) -;;;*** -;;;### (autoloads nil "dabbrev" "dabbrev.el" (0 0 0 0)) ;;; Generated autoloads from dabbrev.el + (put 'dabbrev-case-fold-search 'risky-local-variable t) (put 'dabbrev-case-replace 'risky-local-variable t) (define-key esc-map "/" 'dabbrev-expand) (define-key esc-map [?\C-/] 'dabbrev-completion) - (autoload 'dabbrev-completion "dabbrev" "\ Completion on current word. Like \\[dabbrev-expand] but finds all expansions in the current buffer @@ -6917,8 +6210,7 @@ completions. If the prefix argument is 16 (which comes from \\[universal-argument] \\[universal-argument]), then it searches *all* buffers. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'dabbrev-expand "dabbrev" "\ Expand previous word \"dynamically\". @@ -6943,25 +6235,74 @@ direction of search to backward if set non-nil. See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (register-definition-prefixes "dabbrev" '("dabbrev-")) -;;;*** -;;;### (autoloads nil "data-debug" "cedet/data-debug.el" (0 0 0 0)) ;;; Generated autoloads from cedet/data-debug.el (autoload 'data-debug-new-buffer "data-debug" "\ Create a new data-debug buffer with NAME. -\(fn NAME)" nil nil) - +(fn NAME)" nil nil) (register-definition-prefixes "data-debug" '("data-debug-")) -;;;*** -;;;### (autoloads nil "dbus" "net/dbus.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/db.el + +(register-definition-prefixes "semantic/db" '("semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-debug.el + +(register-definition-prefixes "semantic/db-debug" '("semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-ebrowse.el + +(register-definition-prefixes "semantic/db-ebrowse" '("c++-mode" "semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-el.el + +(register-definition-prefixes "semantic/db-el" '("emacs-lisp-mode" "semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-file.el + +(register-definition-prefixes "semantic/db-file" '("semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-find.el + +(register-definition-prefixes "semantic/db-find" '("semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-global.el + +(register-definition-prefixes "semantic/db-global" '("semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-javascript.el + +(register-definition-prefixes "semantic/db-javascript" '("javascript-mode" "semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-mode.el + +(register-definition-prefixes "semantic/db-mode" '("semanticdb-")) + + +;;; Generated autoloads from cedet/semantic/db-ref.el + +(register-definition-prefixes "semantic/db-ref" '("semanticdb-ref-")) + + +;;; Generated autoloads from cedet/semantic/db-typecache.el + +(register-definition-prefixes "semantic/db-typecache" '("semanticdb-")) + + ;;; Generated autoloads from net/dbus.el (autoload 'dbus-handle-event "dbus" "\ @@ -6970,22 +6311,17 @@ EVENT is a D-Bus event, see `dbus-check-event'. HANDLER, being part of the event, is called with arguments ARGS (without type information). If the HANDLER returns a `dbus-error', it is propagated as return message. -\(fn EVENT)" t nil) - +(fn EVENT)" t nil) (function-put 'dbus-handle-event 'completion-predicate #'ignore) - (autoload 'dbus-monitor "dbus" "\ Invoke `dbus-register-monitor' interactively, and switch to the buffer. BUS is either a Lisp keyword, `:system' or `:session', or a string denoting the bus address. The value nil defaults to `:session'. -\(fn &optional BUS)" t nil) - +(fn &optional BUS)" t nil) (register-definition-prefixes "dbus" '("dbus-")) -;;;*** -;;;### (autoloads nil "dcl-mode" "progmodes/dcl-mode.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/dcl-mode.el (autoload 'dcl-mode "dcl-mode" "\ @@ -7106,17 +6442,13 @@ $ There is some minimal font-lock support (see vars `dcl-font-lock-defaults' and `dcl-font-lock-keywords'). -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "dcl-mode" '("dcl-")) -;;;*** -;;;### (autoloads nil "debug" "emacs-lisp/debug.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/debug.el (setq debugger 'debug) - (autoload 'debug "debug" "\ Enter debugger. \\`\\[debugger-continue]' returns from the debugger. Arguments are mainly for use when this is called from the internals @@ -7129,8 +6461,7 @@ first will be printed into the backtrace buffer. If `inhibit-redisplay' is non-nil when this function is called, the debugger will not be entered. -\(fn &rest ARGS)" t nil) - +(fn &rest ARGS)" t nil) (autoload 'debug-on-entry "debug" "\ Request FUNCTION to invoke debugger each time it is called. @@ -7146,16 +6477,14 @@ primitive functions only works when that function is called from Lisp. Use \\[cancel-debug-on-entry] to cancel the effect of this command. Redefining FUNCTION also cancels it. -\(fn FUNCTION)" t nil) - +(fn FUNCTION)" t nil) (autoload 'cancel-debug-on-entry "debug" "\ Undo effect of \\[debug-on-entry] on FUNCTION. If FUNCTION is nil, cancel `debug-on-entry' for all functions. When called interactively, prompt for FUNCTION in the minibuffer. To specify a nil argument interactively, exit with an empty minibuffer. -\(fn &optional FUNCTION)" t nil) - +(fn &optional FUNCTION)" t nil) (autoload 'debug-on-variable-change "debug" "\ Trigger a debugger invocation when VARIABLE is changed. @@ -7174,30 +6503,38 @@ Use \\[cancel-debug-on-variable-change] to cancel the effect of this command. Uninterning VARIABLE or making it an alias of another symbol also cancels it. -\(fn VARIABLE)" t nil) - +(fn VARIABLE)" t nil) (defalias 'debug-watch #'debug-on-variable-change) - (autoload 'cancel-debug-on-variable-change "debug" "\ Undo effect of \\[debug-on-variable-change] on VARIABLE. If VARIABLE is nil, cancel `debug-on-variable-change' for all variables. When called interactively, prompt for VARIABLE in the minibuffer. To specify a nil argument interactively, exit with an empty minibuffer. -\(fn &optional VARIABLE)" t nil) - +(fn &optional VARIABLE)" t nil) (defalias 'cancel-debug-watch #'cancel-debug-on-variable-change) - (register-definition-prefixes "debug" '("debug" "inhibit-debug-on-entry")) -;;;*** -;;;### (autoloads nil "decipher" "play/decipher.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/debug.el + +(register-definition-prefixes "semantic/bovine/debug" '("semantic-")) + + +;;; Generated autoloads from cedet/semantic/analyze/debug.el + +(register-definition-prefixes "semantic/analyze/debug" '("semantic-analyze")) + + +;;; Generated autoloads from cedet/semantic/debug.el + +(register-definition-prefixes "semantic/debug" '("semantic-debug-")) + + ;;; Generated autoloads from play/decipher.el (autoload 'decipher "decipher" "\ Format a buffer of ciphertext for cryptanalysis and enter Decipher mode." t nil) - (autoload 'decipher-mode "decipher" "\ Major mode for decrypting monoalphabetic substitution ciphers. Lower-case letters enter plaintext. @@ -7214,18 +6551,19 @@ The most useful commands are: \\[decipher-make-checkpoint] Save the current cipher alphabet (checkpoint) \\[decipher-restore-checkpoint] Restore a saved cipher alphabet (checkpoint) -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "decipher" '("decipher-")) -;;;*** -;;;### (autoloads nil "delim-col" "delim-col.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/decorate.el + +(register-definition-prefixes "semantic/decorate" '("semantic-")) + + ;;; Generated autoloads from delim-col.el (autoload 'delimit-columns-customize "delim-col" "\ Customize the `columns' group." t nil) - (autoload 'delimit-columns-region "delim-col" "\ Prettify all columns in a text region. @@ -7249,8 +6587,7 @@ See the `delimit-columns-str-before', `delimit-columns-extra' variables for customization of the look. -\(fn START END)" t nil) - +(fn START END)" t nil) (autoload 'delimit-columns-rectangle "delim-col" "\ Prettify all columns in a text rectangle. @@ -7258,17 +6595,13 @@ See `delimit-columns-region' for what this entails. START and END delimit the corners of the text rectangle. -\(fn START END)" t nil) - +(fn START END)" t nil) (register-definition-prefixes "delim-col" '("delimit-columns-")) -;;;*** -;;;### (autoloads nil "delsel" "delsel.el" (0 0 0 0)) ;;; Generated autoloads from delsel.el (defalias 'pending-delete-mode 'delete-selection-mode) - (defvar delete-selection-mode nil "\ Non-nil if Delete-Selection mode is enabled. See the `delete-selection-mode' command @@ -7276,9 +6609,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `delete-selection-mode'.") - (custom-autoload 'delete-selection-mode "delsel" nil) - (autoload 'delete-selection-mode "delsel" "\ Toggle Delete Selection mode. @@ -7304,20 +6635,21 @@ evaluate `(default-value \\='delete-selection-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'delete-active-region "delsel" "\ Delete the active region. If KILLP is non-nil, or if called interactively with a prefix argument, the active region is killed instead of deleted. -\(fn &optional KILLP)" t nil) - +(fn &optional KILLP)" t nil) (register-definition-prefixes "delsel" '("del" "minibuffer-keyboard-quit")) -;;;*** -;;;### (autoloads nil "derived" "emacs-lisp/derived.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/dep.el + +(register-definition-prefixes "semantic/dep" '("defcustom-mode-local-semantic-dependency-system-include-path" "semantic-")) + + ;;; Generated autoloads from emacs-lisp/derived.el (autoload 'define-derived-mode "derived" "\ @@ -7379,25 +6711,19 @@ the hook will be named `foo-mode-hook'. See Info node `(elisp)Derived Modes' for more details. -\(fn CHILD PARENT NAME [DOCSTRING] [KEYWORD-ARGS...] &rest BODY)" nil t) - +(fn CHILD PARENT NAME [DOCSTRING] [KEYWORD-ARGS...] &rest BODY)" nil t) (function-put 'define-derived-mode 'doc-string-elt '4) - (function-put 'define-derived-mode 'lisp-indent-function 'defun) - (autoload 'derived-mode-init-mode-variables "derived" "\ Initialize variables for a new MODE. Right now, if they don't already exist, set up a blank keymap, an empty syntax table, and an empty abbrev table -- these will be merged the first time the mode is used. -\(fn MODE)" nil nil) - +(fn MODE)" nil nil) (register-definition-prefixes "derived" '("derived-mode-")) -;;;*** -;;;### (autoloads nil "descr-text" "descr-text.el" (0 0 0 0)) ;;; Generated autoloads from descr-text.el (autoload 'describe-text-properties "descr-text" "\ @@ -7408,8 +6734,7 @@ If optional second argument OUTPUT-BUFFER is non-nil, insert the output into that buffer, and don't initialize or clear it otherwise. -\(fn POS &optional OUTPUT-BUFFER BUFFER)" t nil) - +(fn POS &optional OUTPUT-BUFFER BUFFER)" t nil) (autoload 'describe-char "descr-text" "\ Describe position POS (interactively, point) and the char after POS. POS is taken to be in BUFFER, or the current buffer if BUFFER is nil. @@ -7436,8 +6761,7 @@ The character information includes: Unicode Data Base; and widgets, buttons, overlays, and text properties relevant to POS. -\(fn POS &optional BUFFER)" t nil) - +(fn POS &optional BUFFER)" t nil) (autoload 'describe-char-eldoc "descr-text" "\ Return a description of character at point for use by ElDoc mode. @@ -7451,13 +6775,10 @@ minibuffer window for width limit. This function can be used as a value of `eldoc-documentation-functions' variable. -\(fn CALLBACK &rest _)" nil nil) - +(fn CALLBACK &rest _)" nil nil) (register-definition-prefixes "descr-text" '("describe-")) -;;;*** -;;;### (autoloads nil "desktop" "desktop.el" (0 0 0 0)) ;;; Generated autoloads from desktop.el (defvar desktop-save-mode nil "\ @@ -7467,9 +6788,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `desktop-save-mode'.") - (custom-autoload 'desktop-save-mode "desktop" nil) - (autoload 'desktop-save-mode "desktop" "\ Toggle desktop saving (Desktop Save mode). @@ -7502,15 +6821,12 @@ evaluate `(default-value \\='desktop-save-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (defvar desktop-locals-to-save '(desktop-locals-to-save truncate-lines case-fold-search case-replace fill-column overwrite-mode change-log-default-name line-number-mode column-number-mode size-indication-mode buffer-file-coding-system buffer-display-time indent-tabs-mode tab-width indicate-buffer-boundaries indicate-empty-lines show-trailing-whitespace) "\ List of local variables to save for each buffer. The variables are saved only when they really are local. Conventional minor modes are restored automatically; they should not be listed here.") - (custom-autoload 'desktop-locals-to-save "desktop" t) - (defvar-local desktop-save-buffer nil "\ When non-nil, save buffer status in desktop file. @@ -7524,7 +6840,6 @@ When file names are returned, they should be formatted using the call Later, when `desktop-read' evaluates the desktop file, auxiliary information is passed as the argument DESKTOP-BUFFER-MISC to functions in `desktop-buffer-mode-handlers'.") - (defvar desktop-buffer-mode-handlers nil "\ Alist of major mode specific functions to restore a desktop buffer. Functions listed are called by `desktop-create-buffer' when `desktop-read' @@ -7563,9 +6878,7 @@ code like The major mode function must either be autoloaded, or of the form \"foobar-mode\" and defined in library \"foobar\", so that desktop can guess how to load the mode's definition.") - (put 'desktop-buffer-mode-handlers 'risky-local-variable t) - (defvar desktop-minor-mode-handlers nil "\ Alist of functions to restore non-standard minor modes. Functions are called by `desktop-create-buffer' to restore minor modes. @@ -7609,9 +6922,7 @@ The minor mode function must either be autoloaded, or of the form can guess how to load the mode's definition. See also `desktop-minor-mode-table'.") - (put 'desktop-minor-mode-handlers 'risky-local-variable t) - (autoload 'desktop-clear "desktop" "\ Empty the Desktop. This kills all buffers except for internal ones and those with names matched by @@ -7620,7 +6931,6 @@ Furthermore, it clears the variables listed in `desktop-globals-to-clear'. When called interactively and `desktop-restore-frames' is non-nil, it also deletes all frames except the selected one (and its minibuffer frame, if different)." t nil) - (autoload 'desktop-save "desktop" "\ Save the state of Emacs in a desktop file in directory DIRNAME. Optional argument RELEASE non-nil says we're done with this @@ -7656,12 +6966,10 @@ In a non-interactive call, VERSION can be given as an integer, either 206 or 208, to specify the format version in which to save the file, no questions asked. -\(fn DIRNAME &optional RELEASE ONLY-IF-CHANGED VERSION)" t nil) - +(fn DIRNAME &optional RELEASE ONLY-IF-CHANGED VERSION)" t nil) (autoload 'desktop-remove "desktop" "\ Delete desktop file in `desktop-dirname'. This function also sets `desktop-dirname' to nil." t nil) - (autoload 'desktop-read "desktop" "\ Read and process the desktop file in directory DIRNAME. Look for a desktop file in DIRNAME, or if DIRNAME is omitted, look in @@ -7672,27 +6980,26 @@ Interactively, with prefix arg \\[universal-argument], ask for DIRNAME. This function is a no-op when Emacs is running in batch mode. It returns t if a desktop file was loaded, nil otherwise. -\(fn DIRNAME)" t nil) - +(fn DIRNAME)" t nil) (autoload 'desktop-change-dir "desktop" "\ Change to desktop saved in DIRNAME. Kill the desktop as specified by variables `desktop-save-mode' and `desktop-save', then clear the desktop and load the desktop file in directory DIRNAME. -\(fn DIRNAME)" t nil) - +(fn DIRNAME)" t nil) (autoload 'desktop-save-in-desktop-dir "desktop" "\ Save the desktop in directory `desktop-dirname'." t nil) - (autoload 'desktop-revert "desktop" "\ Revert to the last loaded desktop." t nil) - (register-definition-prefixes "desktop" '("desktop-")) -;;;*** -;;;### (autoloads nil "deuglify" "gnus/deuglify.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/detect.el + +(register-definition-prefixes "ede/detect" '("ede-")) + + ;;; Generated autoloads from gnus/deuglify.el (autoload 'gnus-article-outlook-unwrap-lines "deuglify" "\ @@ -7702,44 +7009,34 @@ You can control what lines will be unwrapped by frobbing indicating the minimum and maximum length of an unwrapped citation line. If NODISPLAY is non-nil, don't redisplay the article buffer. -\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil) - +(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil) (autoload 'gnus-article-outlook-repair-attribution "deuglify" "\ Repair a broken attribution line. If NODISPLAY is non-nil, don't redisplay the article buffer. -\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil) - +(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil) (autoload 'gnus-article-outlook-rearrange-citation "deuglify" "\ Repair broken citations. If NODISPLAY is non-nil, don't redisplay the article buffer. -\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil) - +(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil) (autoload 'gnus-outlook-deuglify-article "deuglify" "\ Full deuglify of broken Outlook (Express) articles. Treat \"smartquotes\", unwrap lines, repair attribution and rearrange citation. If NODISPLAY is non-nil, don't redisplay the article buffer. -\(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil) - +(fn &optional NODISPLAY)" '(gnus-article-mode gnus-summary-mode) nil) (autoload 'gnus-article-outlook-deuglify-article "deuglify" "\ Deuglify broken Outlook (Express) articles and redisplay." '(gnus-article-mode gnus-summary-mode) nil) - (register-definition-prefixes "deuglify" '("gnus-outlook-")) -;;;*** -;;;### (autoloads nil "dframe" "dframe.el" (0 0 0 0)) ;;; Generated autoloads from dframe.el (register-definition-prefixes "dframe" '("dframe-")) -;;;*** -;;;### (autoloads nil "diary-lib" "calendar/diary-lib.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from calendar/diary-lib.el (autoload 'diary "diary-lib" "\ @@ -7748,8 +7045,7 @@ If no argument is provided, the number of days of diary entries is governed by the variable `diary-number-of-entries'. A value of ARG less than 1 does nothing. This function is suitable for execution in an init file. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'diary-mail-entries "diary-lib" "\ Send a mail message showing diary entries for next NDAYS days. If no prefix argument is given, NDAYS is set to `diary-mail-days'. @@ -7763,27 +7059,23 @@ ensure that all relevant variables are set. #!/usr/bin/emacs -script ;; diary-rem.el - run the Emacs diary-reminder -\(setq diary-mail-days 3 +(setq diary-mail-days 3 diary-file \"/path/to/diary.file\" calendar-date-style \\='european diary-mail-addr \"user@host.name\") -\(diary-mail-entries) +(diary-mail-entries) # diary-rem.el ends here -\(fn &optional NDAYS)" t nil) - +(fn &optional NDAYS)" t nil) (autoload 'diary-mode "diary-lib" "\ Major mode for editing the diary file. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "diary-lib" '("calendar-mark-" "diary-")) -;;;*** -;;;### (autoloads nil "dictionary" "net/dictionary.el" (0 0 0 0)) ;;; Generated autoloads from net/dictionary.el (autoload 'dictionary-mode "dictionary" "\ @@ -7805,35 +7097,28 @@ This is a quick reference to this mode describing the default key bindings: * \\[dictionary-select-strategy] select the default search strategy * RET or visit that link" nil nil) - (autoload 'dictionary "dictionary" "\ Create a new dictionary buffer and install `dictionary-mode'." t nil) - (autoload 'dictionary-search "dictionary" "\ Search the WORD in DICTIONARY if given or in all if nil. It presents the selection or word at point as default input and allows editing it. -\(fn WORD &optional DICTIONARY)" t nil) - +(fn WORD &optional DICTIONARY)" t nil) (autoload 'dictionary-lookup-definition "dictionary" "\ Unconditionally lookup the word at point." t nil) - (autoload 'dictionary-match-words "dictionary" "\ Search PATTERN in current default dictionary using default strategy. -\(fn &optional PATTERN &rest IGNORED)" t nil) - +(fn &optional PATTERN &rest IGNORED)" t nil) (autoload 'dictionary-mouse-popup-matching-words "dictionary" "\ Display entries matching the word at the cursor retrieved using EVENT. -\(fn EVENT)" t nil) - +(fn EVENT)" t nil) (autoload 'dictionary-popup-matching-words "dictionary" "\ Display entries matching WORD or the current word if not given. -\(fn &optional WORD)" t nil) - +(fn &optional WORD)" t nil) (autoload 'dictionary-tooltip-mode "dictionary" "\ Display tooltips for the current word. @@ -7841,8 +7126,7 @@ This function can be used to enable or disable the tooltip mode for the current buffer (based on ARG). If global-tooltip-mode is active it will overwrite that mode for the current buffer. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'global-dictionary-tooltip-mode "dictionary" "\ Enable/disable `dictionary-tooltip-mode' for all buffers. @@ -7852,29 +7136,27 @@ It can be overwritten for each buffer using `dictionary-tooltip-mode'. Note: (global-dictionary-tooltip-mode 0) will not disable the mode any buffer where (dictionary-tooltip-mode 1) has been called. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'dictionary-context-menu "dictionary" "\ Populate MENU with dictionary commands at CLICK. When you add this function to `context-menu-functions', the context menu will contain an item that searches the word at mouse click. -\(fn MENU CLICK)" nil nil) - +(fn MENU CLICK)" nil nil) (register-definition-prefixes "dictionary" '("dictionary-" "global-dictionary-tooltip-mode")) -;;;*** -;;;### (autoloads nil "dictionary-connection" "net/dictionary-connection.el" -;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/dictionary.el + +(register-definition-prefixes "srecode/dictionary" '("srecode-")) + + ;;; Generated autoloads from net/dictionary-connection.el (register-definition-prefixes "dictionary-connection" '("dictionary-connection-")) -;;;*** -;;;### (autoloads nil "diff" "vc/diff.el" (0 0 0 0)) ;;; Generated autoloads from vc/diff.el (defvar diff-switches (purecopy "-u") "\ @@ -7884,14 +7166,10 @@ This variable is also used in the `vc-diff' command (and related commands) if the backend-specific diff switch variable isn't set (`vc-git-diff-switches' for git, for instance), and `vc-diff-switches' isn't set.") - (custom-autoload 'diff-switches "diff" t) - (defvar diff-command (purecopy "diff") "\ The command to use to run diff.") - (custom-autoload 'diff-command "diff" t) - (autoload 'diff "diff" "\ Find and display the differences between OLD and NEW files. When called interactively, read NEW, then OLD, using the @@ -7906,8 +7184,7 @@ command. Non-interactively, OLD and NEW may each be a file or a buffer. -\(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil) - +(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil) (autoload 'diff-backup "diff" "\ Diff this file with its backup file or vice versa. Uses the latest backup, if there are several numerical backups. @@ -7915,19 +7192,16 @@ If this file is a backup, diff it with its original. The backup file is the first file given to `diff'. With prefix arg SWITCHES, prompt for diff switches. -\(fn FILE &optional SWITCHES)" t nil) - +(fn FILE &optional SWITCHES)" t nil) (autoload 'diff-latest-backup-file "diff" "\ Return the latest existing backup of file FN, or nil. -\(fn FN)" nil nil) - +(fn FN)" nil nil) (autoload 'diff-buffer-with-file "diff" "\ View the differences between BUFFER and its associated file. This requires the external program `diff' to be in your `exec-path'. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (autoload 'diff-buffers "diff" "\ Find and display the differences between OLD and NEW buffers. @@ -7945,13 +7219,10 @@ OLD and NEW may each be a buffer or a buffer name. Also see the `diff-entire-buffers' variable. -\(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil) - +(fn OLD NEW &optional SWITCHES NO-ASYNC)" t nil) (register-definition-prefixes "diff" '("diff-")) -;;;*** -;;;### (autoloads nil "diff-mode" "vc/diff-mode.el" (0 0 0 0)) ;;; Generated autoloads from vc/diff-mode.el (autoload 'diff-mode "diff-mode" "\ @@ -7969,8 +7240,7 @@ a diff with \\[diff-reverse-direction]. \\{diff-mode-map} -\(fn)" t nil) - +(fn)" t nil) (autoload 'diff-minor-mode "diff-mode" "\ Toggle Diff minor mode. @@ -7990,13 +7260,10 @@ evaluate `diff-minor-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "diff-mode" '("diff-")) -;;;*** -;;;### (autoloads nil "dig" "net/dig.el" (0 0 0 0)) ;;; Generated autoloads from net/dig.el (autoload 'dig "dig" "\ @@ -8005,13 +7272,15 @@ See `dig-invoke' for an explanation for the parameters. When called interactively, DOMAIN is prompted for. If given a prefix, also prompt for the QUERY-TYPE parameter. -\(fn DOMAIN &optional QUERY-TYPE QUERY-CLASS QUERY-OPTION DIG-OPTION SERVER)" t nil) - +(fn DOMAIN &optional QUERY-TYPE QUERY-CLASS QUERY-OPTION DIG-OPTION SERVER)" t nil) (register-definition-prefixes "dig" '("dig-" "query-dig")) -;;;*** -;;;### (autoloads nil "dired" "dired.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/dired.el + +(register-definition-prefixes "ede/dired" '("ede-dired-")) + + ;;; Generated autoloads from dired.el (defvar dired-listing-switches (purecopy "-al") "\ @@ -8031,16 +7300,13 @@ each option. On systems such as MS-DOS and MS-Windows, which use `ls' emulation in Lisp, some of the `ls' switches are not supported; see the doc string of `insert-directory' in `ls-lisp.el' for more details.") - (custom-autoload 'dired-listing-switches "dired" t) - (defvar-local dired-directory nil "\ The directory name or wildcard spec that this Dired directory lists. Local to each Dired buffer. May be a list, in which case the car is the directory name and the cdr is the list of files to mention. The directory name must be absolute, but need not be fully expanded.") (define-key ctl-x-map "d" 'dired) - (autoload 'dired "dired" "\ \"Edit\" directory DIRNAME--delete, rename, print, etc. some files in it. Optional second argument SWITCHES specifies the options to be used @@ -8064,31 +7330,26 @@ Type \\[describe-mode] after entering Dired for more info. If DIRNAME is already in a Dired buffer, that buffer is used without refresh. -\(fn DIRNAME &optional SWITCHES)" t nil) +(fn DIRNAME &optional SWITCHES)" t nil) (define-key ctl-x-4-map "d" 'dired-other-window) - (autoload 'dired-other-window "dired" "\ \"Edit\" directory DIRNAME. Like `dired' but select in another window. -\(fn DIRNAME &optional SWITCHES)" t nil) +(fn DIRNAME &optional SWITCHES)" t nil) (define-key ctl-x-5-map "d" 'dired-other-frame) - (autoload 'dired-other-frame "dired" "\ \"Edit\" directory DIRNAME. Like `dired' but make a new frame. -\(fn DIRNAME &optional SWITCHES)" t nil) +(fn DIRNAME &optional SWITCHES)" t nil) (define-key tab-prefix-map "d" 'dired-other-tab) - (autoload 'dired-other-tab "dired" "\ \"Edit\" directory DIRNAME. Like `dired' but make a new tab. -\(fn DIRNAME &optional SWITCHES)" t nil) - +(fn DIRNAME &optional SWITCHES)" t nil) (autoload 'dired-noselect "dired" "\ Like `dired' but return the Dired buffer as value, do not select it. -\(fn DIR-OR-LIST &optional SWITCHES)" nil nil) - +(fn DIR-OR-LIST &optional SWITCHES)" nil nil) (autoload 'dired-mode "dired" "\ Mode for \"editing\" directory listings. In Dired, you are \"editing\" a list of the files in a directory and @@ -8139,9 +7400,8 @@ This mode runs the following hooks: Keybindings: \\{dired-mode-map} -\(fn &optional DIRNAME SWITCHES)" nil nil) +(fn &optional DIRNAME SWITCHES)" nil nil) (put 'dired-find-alternate-file 'disabled t) - (autoload 'dired-jump "dired" "\ Jump to Dired buffer corresponding to current buffer. If in a buffer visiting a file, Dired that file's directory and @@ -8158,18 +7418,24 @@ When OTHER-WINDOW is non-nil, jump to Dired buffer in other window. When FILE-NAME is non-nil, jump to its line in Dired. Interactively with prefix argument, read FILE-NAME. -\(fn &optional OTHER-WINDOW FILE-NAME)" t nil) - +(fn &optional OTHER-WINDOW FILE-NAME)" t nil) (autoload 'dired-jump-other-window "dired" "\ Like \\[dired-jump] (`dired-jump') but in other window. -\(fn &optional FILE-NAME)" t nil) - +(fn &optional FILE-NAME)" t nil) (register-definition-prefixes "dired" '("dired-")) -;;;*** -;;;### (autoloads nil "dirtrack" "dirtrack.el" (0 0 0 0)) +;;; Generated autoloads from dired-aux.el + +(register-definition-prefixes "dired-aux" '("dired-" "minibuffer-default-add-dired-shell-commands")) + + +;;; Generated autoloads from dired-x.el + +(register-definition-prefixes "dired-x" '("dired-" "virtual-dired")) + + ;;; Generated autoloads from dirtrack.el (autoload 'dirtrack-mode "dirtrack" "\ @@ -8197,8 +7463,7 @@ evaluate `dirtrack-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'dirtrack "dirtrack" "\ Determine the current directory from the process output for a prompt. This filter function is used by `dirtrack-mode'. It looks for @@ -8206,58 +7471,47 @@ the prompt specified by `dirtrack-list', and calls `shell-process-cd' if the directory seems to have changed away from `default-directory'. -\(fn INPUT)" nil nil) - +(fn INPUT)" nil nil) (register-definition-prefixes "dirtrack" '("dirtrack-")) -;;;*** -;;;### (autoloads nil "disass" "emacs-lisp/disass.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/disass.el (autoload 'disassemble "disass" "\ Print disassembled code for OBJECT in (optional) BUFFER. OBJECT can be a symbol defined as a function, or a function itself -\(a lambda expression or a compiled-function object). +(a lambda expression or a compiled-function object). If OBJECT is not already compiled, we compile it, but do not redefine OBJECT if it is a symbol. -\(fn OBJECT &optional BUFFER INDENT INTERACTIVE-P)" t nil) - +(fn OBJECT &optional BUFFER INDENT INTERACTIVE-P)" t nil) (register-definition-prefixes "disass" '("disassemble-")) -;;;*** -;;;### (autoloads nil "disp-table" "disp-table.el" (0 0 0 0)) ;;; Generated autoloads from disp-table.el (autoload 'make-display-table "disp-table" "\ Return a new, empty display table." nil nil) - (autoload 'display-table-slot "disp-table" "\ Return the value of the extra slot in DISPLAY-TABLE named SLOT. SLOT may be a number from 0 to 5 inclusive, or a slot name (symbol). Valid symbols are `truncation', `wrap', `escape', `control', `selective-display', and `vertical-border'. -\(fn DISPLAY-TABLE SLOT)" nil nil) - +(fn DISPLAY-TABLE SLOT)" nil nil) (autoload 'set-display-table-slot "disp-table" "\ Set the value of the extra slot in DISPLAY-TABLE named SLOT to VALUE. SLOT may be a number from 0 to 5 inclusive, or a name (symbol). Valid symbols are `truncation', `wrap', `escape', `control', `selective-display', and `vertical-border'. -\(fn DISPLAY-TABLE SLOT VALUE)" nil nil) - +(fn DISPLAY-TABLE SLOT VALUE)" nil nil) (autoload 'describe-display-table "disp-table" "\ Describe the display table DT in a help buffer. -\(fn DT)" nil nil) - +(fn DT)" nil nil) (autoload 'describe-current-display-table "disp-table" "\ Describe the display table in use in the selected window and buffer." t nil) - (autoload 'standard-display-8bit "disp-table" "\ Display characters representing raw bytes in the range L to H literally. @@ -8271,57 +7525,47 @@ byte. Note that ASCII printable characters (SPC to TILDA) are displayed in the default way after this call. -\(fn L H)" nil nil) - +(fn L H)" nil nil) (autoload 'standard-display-default "disp-table" "\ Display characters in the range L to H using the default notation. -\(fn L H)" nil nil) - +(fn L H)" nil nil) (autoload 'standard-display-ascii "disp-table" "\ Display character C using printable string S. -\(fn C S)" nil nil) - +(fn C S)" nil nil) (autoload 'standard-display-g1 "disp-table" "\ Display character C as character SC in the g1 character set. This function assumes that your terminal uses the SO/SI characters; it is meaningless for a graphical frame. -\(fn C SC)" nil nil) - +(fn C SC)" nil nil) (autoload 'standard-display-graphic "disp-table" "\ Display character C as character GC in graphics character set. This function assumes VT100-compatible escapes; it is meaningless for a graphical frame. -\(fn C GC)" nil nil) - +(fn C GC)" nil nil) (autoload 'standard-display-underline "disp-table" "\ Display character C as character UC plus underlining. -\(fn C UC)" nil nil) - +(fn C UC)" nil nil) (autoload 'create-glyph "disp-table" "\ Allocate a glyph code to display by sending STRING to the terminal. -\(fn STRING)" nil nil) - +(fn STRING)" nil nil) (autoload 'make-glyph-code "disp-table" "\ Return a glyph code representing char CHAR with face FACE. -\(fn CHAR &optional FACE)" nil nil) - +(fn CHAR &optional FACE)" nil nil) (autoload 'glyph-char "disp-table" "\ Return the character of glyph code GLYPH. -\(fn GLYPH)" nil nil) - +(fn GLYPH)" nil nil) (autoload 'glyph-face "disp-table" "\ Return the face of glyph code GLYPH, or nil if glyph has default face. -\(fn GLYPH)" nil nil) - +(fn GLYPH)" nil nil) (autoload 'standard-display-european "disp-table" "\ Semi-obsolete way to toggle display of ISO 8859 European characters. @@ -8341,14 +7585,10 @@ from Lisp code also selects Latin-1 as the language environment. This provides increased compatibility for users who call this function in `.emacs'. -\(fn ARG)" nil nil) - +(fn ARG)" nil nil) (register-definition-prefixes "disp-table" '("display-table-print-array")) -;;;*** -;;;### (autoloads nil "display-fill-column-indicator" "display-fill-column-indicator.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from display-fill-column-indicator.el (autoload 'display-fill-column-indicator-mode "display-fill-column-indicator" "\ @@ -8378,10 +7618,8 @@ evaluate `display-fill-column-indicator-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (put 'global-display-fill-column-indicator-mode 'globalized-minor-mode t) - (defvar global-display-fill-column-indicator-mode nil "\ Non-nil if Global Display-Fill-Column-Indicator mode is enabled. See the `global-display-fill-column-indicator-mode' command @@ -8389,9 +7627,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `global-display-fill-column-indicator-mode'.") - (custom-autoload 'global-display-fill-column-indicator-mode "display-fill-column-indicator" nil) - (autoload 'global-display-fill-column-indicator-mode "display-fill-column-indicator" "\ Toggle Display-Fill-Column-Indicator mode in all buffers. With prefix ARG, enable Global Display-Fill-Column-Indicator mode if @@ -8410,8 +7646,7 @@ Display-Fill-Column-Indicator mode. `global-display-fill-column-indicator-modes' is used to control which modes this minor mode is used in. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (defvar global-display-fill-column-indicator-modes '((not special-mode) t) "\ Which major modes `display-fill-column-indicator-mode' is switched on in. This variable can be either t (all major modes), nil (no major modes), @@ -8425,15 +7660,10 @@ modes derived from `message-mode' or `mail-mode', but do use in other modes derived from `text-mode'\". An element with value t means \"use\" and nil means \"don't use\". There's an implicit nil at the end of the list.") - (custom-autoload 'global-display-fill-column-indicator-modes "display-fill-column-indicator" t) - (register-definition-prefixes "display-fill-column-indicator" '("display-fill-column-indicator--turn-on")) -;;;*** -;;;### (autoloads nil "display-line-numbers" "display-line-numbers.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from display-line-numbers.el (autoload 'display-line-numbers-mode "display-line-numbers" "\ @@ -8460,10 +7690,8 @@ evaluate `display-line-numbers-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (put 'global-display-line-numbers-mode 'globalized-minor-mode t) - (defvar global-display-line-numbers-mode nil "\ Non-nil if Global Display-Line-Numbers mode is enabled. See the `global-display-line-numbers-mode' command @@ -8471,9 +7699,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `global-display-line-numbers-mode'.") - (custom-autoload 'global-display-line-numbers-mode "display-line-numbers" nil) - (autoload 'global-display-line-numbers-mode "display-line-numbers" "\ Toggle Display-Line-Numbers mode in all buffers. With prefix ARG, enable Global Display-Line-Numbers mode if ARG is @@ -8489,8 +7715,7 @@ Display-Line-Numbers mode is enabled in all buffers where See `display-line-numbers-mode' for more information on Display-Line-Numbers mode. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (defvar header-line-indent "" "\ String to indent at the start if the header line. This is used in `header-line-indent-mode', and buffers that have @@ -8499,13 +7724,11 @@ this switched on should have a `header-line-format' that look like: (\"\" header-line-indent THE-REST...) Also see `header-line-indent-width'.") - (defvar header-line-indent-width 0 "\ The width of the current line numbers displayed. This is updated when `header-line-indent-mode' is switched on. Also see `header-line-indent'.") - (autoload 'header-line-indent-mode "display-line-numbers" "\ Mode to indent the header line in `display-line-numbers-mode' buffers. @@ -8539,13 +7762,10 @@ evaluate `header-line-indent-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "display-line-numbers" '("display-line-numbers-" "header-line-indent--")) -;;;*** -;;;### (autoloads nil "dissociate" "play/dissociate.el" (0 0 0 0)) ;;; Generated autoloads from play/dissociate.el (autoload 'dissociated-press "dissociate" "\ @@ -8557,11 +7777,9 @@ If ARG is positive, require ARG chars of continuity. If ARG is negative, require -ARG words of continuity. Default is 2. -\(fn &optional ARG)" t nil) +(fn &optional ARG)" t nil) -;;;*** -;;;### (autoloads nil "dnd" "dnd.el" (0 0 0 0)) ;;; Generated autoloads from dnd.el (defvar dnd-protocol-alist `((,(purecopy "^file:///") . dnd-open-local-file) (,(purecopy "^file://") . dnd-open-file) (,(purecopy "^file:") . dnd-open-local-file) (,(purecopy "^\\(https?\\|ftp\\|file\\|nfs\\)://") . dnd-open-file)) "\ @@ -8576,14 +7794,10 @@ is a pair of (REGEXP . FUNCTION), those regexps are tried for a match. If no match is found, the URL is inserted as text by calling `dnd-insert-text'. The function shall return the action done (move, copy, link or private) if some action was made, or nil if the URL is ignored.") - (custom-autoload 'dnd-protocol-alist "dnd" t) - (register-definition-prefixes "dnd" '("dnd-")) -;;;*** -;;;### (autoloads nil "dns" "net/dns.el" (0 0 0 0)) ;;; Generated autoloads from net/dns.el (autoload 'dns-query "dns" "\ @@ -8591,13 +7805,10 @@ Query a DNS server for NAME of TYPE. If FULL, return the entire record returned. If REVERSE, look up an IP address. -\(fn NAME &optional TYPE FULL REVERSE)" nil nil) - +(fn NAME &optional TYPE FULL REVERSE)" nil nil) (register-definition-prefixes "dns" '("dns-")) -;;;*** -;;;### (autoloads nil "dns-mode" "textmodes/dns-mode.el" (0 0 0 0)) ;;; Generated autoloads from textmodes/dns-mode.el (autoload 'dns-mode "dns-mode" "\ @@ -8610,17 +7821,18 @@ table and its own syntax table. Turning on DNS mode runs `dns-mode-hook'. -\(fn)" t nil) +(fn)" t nil) (defalias 'zone-mode 'dns-mode) - (autoload 'dns-mode-soa-increment-serial "dns-mode" "\ Locate SOA record and increment the serial field." t nil) - (register-definition-prefixes "dns-mode" '("dns-mode-")) -;;;*** -;;;### (autoloads nil "doc-view" "doc-view.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/doc.el + +(register-definition-prefixes "semantic/doc" '("semantic-doc")) + + ;;; Generated autoloads from doc-view.el (autoload 'doc-view-mode-p "doc-view" "\ @@ -8628,8 +7840,7 @@ Return non-nil if document type TYPE is available for `doc-view'. Document types are symbols like `dvi', `ps', `pdf', `epub', `cbz', `fb2', `xps', `oxps', or`odf' (any OpenDocument format). -\(fn TYPE)" nil nil) - +(fn TYPE)" nil nil) (autoload 'doc-view-mode "doc-view" "\ Major mode in DocView buffers. @@ -8639,12 +7850,10 @@ and DVI files (as PNG images) in Emacs buffers. You can use \\\\[doc-view-toggle-display] to toggle between displaying the document or editing it as text. \\{doc-view-mode-map}" t nil) - (autoload 'doc-view-mode-maybe "doc-view" "\ Switch to `doc-view-mode' if possible. If the required external tools are not available, then fallback to the next best mode." nil nil) - (autoload 'doc-view-minor-mode "doc-view" "\ Toggle displaying buffer via Doc View (Doc View minor mode). @@ -8664,56 +7873,46 @@ evaluate `doc-view-minor-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'doc-view-bookmark-jump "doc-view" "\ -\(fn BMK)" nil nil) - +(fn BMK)" nil nil) (register-definition-prefixes "doc-view" '("doc-view-")) -;;;*** -;;;### (autoloads nil "doctor" "play/doctor.el" (0 0 0 0)) ;;; Generated autoloads from play/doctor.el (autoload 'doctor "doctor" "\ Switch to *doctor* buffer and start giving psychotherapy." t nil) - (register-definition-prefixes "doctor" '("doc" "make-doctor-variables")) -;;;*** -;;;### (autoloads nil "dom" "dom.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/document.el + +(register-definition-prefixes "srecode/document" '("srecode-document-")) + + ;;; Generated autoloads from dom.el (register-definition-prefixes "dom" '("dom-")) -;;;*** -;;;### (autoloads nil "dos-fns" "dos-fns.el" (0 0 0 0)) ;;; Generated autoloads from dos-fns.el (register-definition-prefixes "dos-fns" '("dos")) -;;;*** -;;;### (autoloads nil "dos-vars" "dos-vars.el" (0 0 0 0)) ;;; Generated autoloads from dos-vars.el (register-definition-prefixes "dos-vars" '("dos-codepage-setup-hook" "msdos-shells")) -;;;*** -;;;### (autoloads nil "dos-w32" "dos-w32.el" (0 0 0 0)) ;;; Generated autoloads from dos-w32.el (register-definition-prefixes "dos-w32" '("file-name-buffer-file-type-alist" "find-" "w32-")) -;;;*** -;;;### (autoloads nil "double" "double.el" (0 0 0 0)) ;;; Generated autoloads from double.el (autoload 'double-mode "double" "\ @@ -8736,36 +7935,25 @@ evaluate `double-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "double" '("double-")) -;;;*** -;;;### (autoloads nil "dunnet" "play/dunnet.el" (0 0 0 0)) ;;; Generated autoloads from play/dunnet.el (autoload 'dunnet "dunnet" "\ Switch to *dungeon* buffer and start game." t nil) - (register-definition-prefixes "dunnet" '("dun" "obj-special")) -;;;*** -;;;### (autoloads nil "dynamic-setting" "dynamic-setting.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from dynamic-setting.el (register-definition-prefixes "dynamic-setting" '("dynamic-setting-handle-config-changed-event" "font-setting-change-default-font")) -;;;*** -;;;### (autoloads nil "easy-mmode" "emacs-lisp/easy-mmode.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from emacs-lisp/easy-mmode.el (defalias 'easy-mmode-define-minor-mode #'define-minor-mode) - (autoload 'define-minor-mode "easy-mmode" "\ Define a new minor mode MODE. This defines the toggle command MODE and (by default) a control variable @@ -8837,16 +8025,11 @@ For backward compatibility with the Emacs<21 calling convention, the keywords can also be preceded by the obsolete triplet INIT-VALUE LIGHTER KEYMAP. -\(fn MODE DOC [KEYWORD VAL ... &rest BODY])" nil t) - +(fn MODE DOC [KEYWORD VAL ... &rest BODY])" nil t) (function-put 'define-minor-mode 'doc-string-elt '2) - (function-put 'define-minor-mode 'lisp-indent-function 'defun) - (defalias 'easy-mmode-define-global-mode #'define-globalized-minor-mode) - (defalias 'define-global-minor-mode #'define-globalized-minor-mode) - (autoload 'define-globalized-minor-mode "easy-mmode" "\ Make a global mode GLOBAL-MODE corresponding to buffer-local minor MODE. TURN-ON is a function that will be called with no args in every buffer @@ -8876,12 +8059,9 @@ When a major mode is initialized, MODE is actually turned on just after running the major mode's hook. However, MODE is not turned on if the hook has explicitly disabled it. -\(fn GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)" nil t) - +(fn GLOBAL-MODE MODE TURN-ON [KEY VALUE]... BODY...)" nil t) (function-put 'define-globalized-minor-mode 'doc-string-elt '2) - (function-put 'define-globalized-minor-mode 'lisp-indent-function 'defun) - (autoload 'easy-mmode-define-keymap "easy-mmode" "\ Return a keymap built from bindings BS. BS must be a list of (KEY . BINDING) where @@ -8899,8 +8079,7 @@ Valid keywords and arguments are: :suppress Non-nil to call `suppress-keymap' on keymap, `nodigits' to suppress digits as prefix arguments. -\(fn BS &optional NAME M ARGS)" nil nil) - +(fn BS &optional NAME M ARGS)" nil nil) (autoload 'easy-mmode-defmap "easy-mmode" "\ Define a constant M whose value is the result of `easy-mmode-define-keymap'. The M, BS, and ARGS arguments are as per that function. DOC is @@ -8908,82 +8087,59 @@ the constant's documentation. This macro is deprecated; use `defvar-keymap' instead. -\(fn M BS DOC &rest ARGS)" nil t) - +(fn M BS DOC &rest ARGS)" nil t) (function-put 'easy-mmode-defmap 'doc-string-elt '3) - (function-put 'easy-mmode-defmap 'lisp-indent-function '1) - (autoload 'easy-mmode-defsyntax "easy-mmode" "\ Define variable ST as a syntax-table. CSS contains a list of syntax specifications of the form (CHAR . SYNTAX). -\(fn ST CSS DOC &rest ARGS)" nil t) - +(fn ST CSS DOC &rest ARGS)" nil t) (function-put 'easy-mmode-defsyntax 'doc-string-elt '3) - (function-put 'easy-mmode-defsyntax 'lisp-indent-function '1) - (register-definition-prefixes "easy-mmode" '("easy-mmode-")) -;;;*** -;;;### (autoloads nil "ebnf-abn" "progmodes/ebnf-abn.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebnf-abn.el (register-definition-prefixes "ebnf-abn" '("ebnf-abn-")) -;;;*** -;;;### (autoloads nil "ebnf-bnf" "progmodes/ebnf-bnf.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebnf-bnf.el (register-definition-prefixes "ebnf-bnf" '("ebnf-")) -;;;*** -;;;### (autoloads nil "ebnf-dtd" "progmodes/ebnf-dtd.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebnf-dtd.el (register-definition-prefixes "ebnf-dtd" '("ebnf-dtd-")) -;;;*** -;;;### (autoloads nil "ebnf-ebx" "progmodes/ebnf-ebx.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebnf-ebx.el (register-definition-prefixes "ebnf-ebx" '("ebnf-ebx-")) -;;;*** -;;;### (autoloads nil "ebnf-iso" "progmodes/ebnf-iso.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebnf-iso.el (register-definition-prefixes "ebnf-iso" '("ebnf-")) -;;;*** -;;;### (autoloads nil "ebnf-otz" "progmodes/ebnf-otz.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebnf-otz.el (register-definition-prefixes "ebnf-otz" '("ebnf-")) -;;;*** -;;;### (autoloads nil "ebnf-yac" "progmodes/ebnf-yac.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebnf-yac.el (register-definition-prefixes "ebnf-yac" '("ebnf-yac-")) -;;;*** -;;;### (autoloads nil "ebnf2ps" "progmodes/ebnf2ps.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebnf2ps.el -(push (purecopy '(ebnf2ps 4 4)) package--builtin-versions) +(push (purecopy '(ebnf2ps 4 4)) package--builtin-versions) (autoload 'ebnf-customize "ebnf2ps" "\ Customization for ebnf group." t nil) - (autoload 'ebnf-print-directory "ebnf2ps" "\ Generate and print a PostScript syntactic chart image of DIRECTORY. @@ -8994,8 +8150,7 @@ processed. See also `ebnf-print-buffer'. -\(fn &optional DIRECTORY)" t nil) - +(fn &optional DIRECTORY)" t nil) (autoload 'ebnf-print-file "ebnf2ps" "\ Generate and print a PostScript syntactic chart image of the file FILE. @@ -9004,8 +8159,7 @@ killed after process termination. See also `ebnf-print-buffer'. -\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) - +(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) (autoload 'ebnf-print-buffer "ebnf2ps" "\ Generate and print a PostScript syntactic chart image of the buffer. @@ -9018,14 +8172,12 @@ is nil, send the image to the printer. If FILENAME is a string, save the PostScript image in a file with that name. If FILENAME is a number, prompt the user for the name of the file to save in. -\(fn &optional FILENAME)" t nil) - +(fn &optional FILENAME)" t nil) (autoload 'ebnf-print-region "ebnf2ps" "\ Generate and print a PostScript syntactic chart image of the region. Like `ebnf-print-buffer', but prints just the current region. -\(fn FROM TO &optional FILENAME)" t nil) - +(fn FROM TO &optional FILENAME)" t nil) (autoload 'ebnf-spool-directory "ebnf2ps" "\ Generate and spool a PostScript syntactic chart image of DIRECTORY. @@ -9036,8 +8188,7 @@ processed. See also `ebnf-spool-buffer'. -\(fn &optional DIRECTORY)" t nil) - +(fn &optional DIRECTORY)" t nil) (autoload 'ebnf-spool-file "ebnf2ps" "\ Generate and spool a PostScript syntactic chart image of the file FILE. @@ -9046,23 +8197,20 @@ killed after process termination. See also `ebnf-spool-buffer'. -\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) - +(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) (autoload 'ebnf-spool-buffer "ebnf2ps" "\ Generate and spool a PostScript syntactic chart image of the buffer. Like `ebnf-print-buffer' except that the PostScript image is saved in a local buffer to be sent to the printer later. Use the command `ebnf-despool' to send the spooled images to the printer." t nil) - (autoload 'ebnf-spool-region "ebnf2ps" "\ Generate a PostScript syntactic chart image of the region and spool locally. Like `ebnf-spool-buffer', but spools just the current region. Use the command `ebnf-despool' to send the spooled images to the printer. -\(fn FROM TO)" t nil) - +(fn FROM TO)" t nil) (autoload 'ebnf-eps-directory "ebnf2ps" "\ Generate EPS files from EBNF files in DIRECTORY. @@ -9073,8 +8221,7 @@ processed. See also `ebnf-eps-buffer'. -\(fn &optional DIRECTORY)" t nil) - +(fn &optional DIRECTORY)" t nil) (autoload 'ebnf-eps-file "ebnf2ps" "\ Generate an EPS file from EBNF file FILE. @@ -9083,8 +8230,7 @@ killed after EPS generation. See also `ebnf-eps-buffer'. -\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) - +(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) (autoload 'ebnf-eps-buffer "ebnf2ps" "\ Generate a PostScript syntactic chart image of the buffer in an EPS file. @@ -9104,7 +8250,6 @@ The EPS file name has the following form: WARNING: This function does *NOT* ask any confirmation to override existing files." t nil) - (autoload 'ebnf-eps-region "ebnf2ps" "\ Generate a PostScript syntactic chart image of the region in an EPS file. @@ -9125,10 +8270,8 @@ The EPS file name has the following form: WARNING: This function does *NOT* ask any confirmation to override existing files. -\(fn FROM TO)" t nil) - +(fn FROM TO)" t nil) (defalias 'ebnf-despool #'ps-despool) - (autoload 'ebnf-syntax-directory "ebnf2ps" "\ Do a syntactic analysis of the files in DIRECTORY. @@ -9139,8 +8282,7 @@ are processed. See also `ebnf-syntax-buffer'. -\(fn &optional DIRECTORY)" t nil) - +(fn &optional DIRECTORY)" t nil) (autoload 'ebnf-syntax-file "ebnf2ps" "\ Do a syntactic analysis of the named FILE. @@ -9149,47 +8291,39 @@ killed after syntax checking. See also `ebnf-syntax-buffer'. -\(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) - +(fn FILE &optional DO-NOT-KILL-BUFFER-WHEN-DONE)" t nil) (autoload 'ebnf-syntax-buffer "ebnf2ps" "\ Do a syntactic analysis of the current buffer." t nil) - (autoload 'ebnf-syntax-region "ebnf2ps" "\ Do a syntactic analysis of a region. -\(fn FROM TO)" t nil) - +(fn FROM TO)" t nil) (autoload 'ebnf-setup "ebnf2ps" "\ Return the current ebnf2ps setup." nil nil) - (autoload 'ebnf-find-style "ebnf2ps" "\ Return style definition if NAME is already defined; otherwise, return nil. See `ebnf-style-database' documentation. -\(fn NAME)" t nil) - +(fn NAME)" t nil) (autoload 'ebnf-insert-style "ebnf2ps" "\ Insert a new style NAME with inheritance INHERITS and values VALUES. See `ebnf-style-database' documentation. -\(fn NAME INHERITS &rest VALUES)" t nil) - +(fn NAME INHERITS &rest VALUES)" t nil) (autoload 'ebnf-delete-style "ebnf2ps" "\ Delete style NAME. See `ebnf-style-database' documentation. -\(fn NAME)" t nil) - +(fn NAME)" t nil) (autoload 'ebnf-merge-style "ebnf2ps" "\ Merge values of style NAME with style VALUES. See `ebnf-style-database' documentation. -\(fn NAME &rest VALUES)" t nil) - +(fn NAME &rest VALUES)" t nil) (autoload 'ebnf-apply-style "ebnf2ps" "\ Set STYLE as the current style. @@ -9197,8 +8331,7 @@ Returns the old style symbol. See `ebnf-style-database' documentation. -\(fn STYLE)" t nil) - +(fn STYLE)" t nil) (autoload 'ebnf-reset-style "ebnf2ps" "\ Reset current style. @@ -9206,8 +8339,7 @@ Returns the old style symbol. See `ebnf-style-database' documentation. -\(fn &optional STYLE)" t nil) - +(fn &optional STYLE)" t nil) (autoload 'ebnf-push-style "ebnf2ps" "\ Push the current style onto a stack and set STYLE as the current style. @@ -9217,8 +8349,7 @@ See also `ebnf-pop-style'. See `ebnf-style-database' documentation. -\(fn &optional STYLE)" t nil) - +(fn &optional STYLE)" t nil) (autoload 'ebnf-pop-style "ebnf2ps" "\ Pop a style from the stack of pushed styles and set it as the current style. @@ -9227,12 +8358,9 @@ Returns the old style symbol. See also `ebnf-push-style'. See `ebnf-style-database' documentation." t nil) - (register-definition-prefixes "ebnf2ps" '("ebnf-")) -;;;*** -;;;### (autoloads nil "ebrowse" "progmodes/ebrowse.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/ebrowse.el (autoload 'ebrowse-tree-mode "ebrowse" "\ @@ -9245,68 +8373,52 @@ E.g.\\[save-buffer] writes the tree to the file it was loaded from. Tree mode key bindings: \\{ebrowse-tree-mode-map} -\(fn)" t nil) - +(fn)" t nil) (autoload 'ebrowse-electric-choose-tree "ebrowse" "\ Return a buffer containing a tree or nil if no tree found or canceled." t nil) - (autoload 'ebrowse-member-mode "ebrowse" "\ Major mode for Ebrowse member buffers. -\(fn)" t nil) - +(fn)" t nil) (autoload 'ebrowse-tags-view-declaration "ebrowse" "\ View declaration of member at point." t nil) - (autoload 'ebrowse-tags-find-declaration "ebrowse" "\ Find declaration of member at point." t nil) - (autoload 'ebrowse-tags-view-definition "ebrowse" "\ View definition of member at point." t nil) - (autoload 'ebrowse-tags-find-definition "ebrowse" "\ Find definition of member at point." t nil) - (autoload 'ebrowse-tags-find-declaration-other-window "ebrowse" "\ Find declaration of member at point in other window." t nil) - (autoload 'ebrowse-tags-view-definition-other-window "ebrowse" "\ View definition of member at point in other window." t nil) - (autoload 'ebrowse-tags-find-definition-other-window "ebrowse" "\ Find definition of member at point in other window." t nil) - (autoload 'ebrowse-tags-find-declaration-other-frame "ebrowse" "\ Find definition of member at point in other frame." t nil) - (autoload 'ebrowse-tags-view-definition-other-frame "ebrowse" "\ View definition of member at point in other frame." t nil) - (autoload 'ebrowse-tags-find-definition-other-frame "ebrowse" "\ Find definition of member at point in other frame." t nil) - (autoload 'ebrowse-tags-complete-symbol "ebrowse" "\ Perform completion on the C++ symbol preceding point. A second call of this function without changing point inserts the next match. A call with prefix PREFIX reads the symbol to insert from the minibuffer with completion. -\(fn PREFIX)" t nil) - +(fn PREFIX)" '("P") nil) (autoload 'ebrowse-tags-loop-continue "ebrowse" "\ Repeat last operation on files in tree. FIRST-TIME non-nil means this is not a repetition, but the first time. TREE-BUFFER if indirectly specifies which files to loop over. -\(fn &optional FIRST-TIME TREE-BUFFER)" t nil) - +(fn &optional FIRST-TIME TREE-BUFFER)" t nil) (autoload 'ebrowse-tags-search "ebrowse" "\ Search for REGEXP in all files in a tree. If marked classes exist, process marked classes, only. If regular expression is nil, repeat last search. -\(fn REGEXP)" t nil) - +(fn REGEXP)" t nil) (autoload 'ebrowse-tags-query-replace "ebrowse" "\ Query replace FROM with TO in all files of a class tree. With prefix arg, process files of marked classes only. @@ -9316,8 +8428,7 @@ what to do with it. Type SPC or `y' to replace the match, DEL or `n' to skip and go to the next match. For more directions, type \\[help-command] at that time. -\(fn FROM TO)" t nil) - +(fn FROM TO)" t nil) (autoload 'ebrowse-tags-search-member-use "ebrowse" "\ Search for call sites of a member. If FIX-NAME is specified, search uses of that member. @@ -9325,41 +8436,32 @@ Otherwise, read a member name from the minibuffer. Searches in all files mentioned in a class tree for something that looks like a function call to the member. -\(fn &optional FIX-NAME)" t nil) - +(fn &optional FIX-NAME)" t nil) (autoload 'ebrowse-back-in-position-stack "ebrowse" "\ Move backward in the position stack. Prefix arg ARG says how much. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (autoload 'ebrowse-forward-in-position-stack "ebrowse" "\ Move forward in the position stack. Prefix arg ARG says how much. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (autoload 'ebrowse-electric-position-menu "ebrowse" "\ List positions in the position stack in an electric buffer." t nil) - (autoload 'ebrowse-save-tree "ebrowse" "\ Save current tree in same file it was loaded from." t nil) - (autoload 'ebrowse-save-tree-as "ebrowse" "\ Write the current tree data structure to a file. Read the file name from the minibuffer if interactive. Otherwise, FILE-NAME specifies the file to save the tree in. -\(fn &optional FILE-NAME)" t nil) - +(fn &optional FILE-NAME)" t nil) (autoload 'ebrowse-statistics "ebrowse" "\ Display statistics for a class tree." t nil) - (register-definition-prefixes "ebrowse" '("ebrowse-" "electric-buffer-menu-mode-hook")) -;;;*** -;;;### (autoloads nil "ebuff-menu" "ebuff-menu.el" (0 0 0 0)) ;;; Generated autoloads from ebuff-menu.el (autoload 'electric-buffer-list "ebuff-menu" "\ @@ -9388,39 +8490,30 @@ Run hooks in `electric-buffer-menu-mode-hook' on entry. \\[Electric-buffer-menu-mode-view-buffer] -- view buffer, returning when done. \\[Buffer-menu-backup-unmark] -- back up a line and remove marks. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (register-definition-prefixes "ebuff-menu" '("Electric-buffer-menu-" "electric-buffer-")) -;;;*** -;;;### (autoloads nil "echistory" "echistory.el" (0 0 0 0)) ;;; Generated autoloads from echistory.el (autoload 'Electric-command-history-redo-expression "echistory" "\ Edit current history line in minibuffer and execute result. With prefix arg NOCONFIRM, execute current line as-is without editing. -\(fn &optional NOCONFIRM)" t nil) - +(fn &optional NOCONFIRM)" t nil) (register-definition-prefixes "echistory" '("Electric-history-" "electric-")) -;;;*** -;;;### (autoloads nil "ecomplete" "ecomplete.el" (0 0 0 0)) ;;; Generated autoloads from ecomplete.el (autoload 'ecomplete-setup "ecomplete" "\ Read the .ecompleterc file." nil nil) - (register-definition-prefixes "ecomplete" '("ecomplete-")) -;;;*** -;;;### (autoloads nil "ede" "cedet/ede.el" (0 0 0 0)) ;;; Generated autoloads from cedet/ede.el -(push (purecopy '(ede 1 2)) package--builtin-versions) +(push (purecopy '(ede 1 2)) package--builtin-versions) (defvar global-ede-mode nil "\ Non-nil if Global Ede mode is enabled. See the `global-ede-mode' command @@ -9428,9 +8521,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `global-ede-mode'.") - (custom-autoload 'global-ede-mode "ede" nil) - (autoload 'global-ede-mode "ede" "\ Toggle global EDE (Emacs Development Environment) mode. @@ -9451,174 +8542,15 @@ evaluate `(default-value \\='global-ede-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "ede" '("ede" "global-ede-mode-map" "project-try-ede")) -;;;*** - -;;;### (autoloads nil "ede/auto" "cedet/ede/auto.el" (0 0 0 0)) -;;; Generated autoloads from cedet/ede/auto.el - -(register-definition-prefixes "ede/auto" '("ede-")) - -;;;*** - -;;;### (autoloads nil "ede/autoconf-edit" "cedet/ede/autoconf-edit.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from cedet/ede/autoconf-edit.el - -(register-definition-prefixes "ede/autoconf-edit" '("autoconf-")) - -;;;*** - -;;;### (autoloads nil "ede/detect" "cedet/ede/detect.el" (0 0 0 0)) -;;; Generated autoloads from cedet/ede/detect.el - -(register-definition-prefixes "ede/detect" '("ede-")) - -;;;*** - -;;;### (autoloads nil "ede/makefile-edit" "cedet/ede/makefile-edit.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from cedet/ede/makefile-edit.el - -(register-definition-prefixes "ede/makefile-edit" '("makefile-")) - -;;;*** - -;;;### (autoloads nil "ede/pconf" "cedet/ede/pconf.el" (0 0 0 0)) -;;; Generated autoloads from cedet/ede/pconf.el - -(register-definition-prefixes "ede/pconf" '("ede-pconf-create-file-query")) - -;;;*** - -;;;### (autoloads nil "ede/pmake" "cedet/ede/pmake.el" (0 0 0 0)) -;;; Generated autoloads from cedet/ede/pmake.el - -(register-definition-prefixes "ede/pmake" '("ede-pmake-")) - -;;;*** - -;;;### (autoloads nil "ede/proj" "cedet/ede/proj.el" (0 0 0 0)) -;;; Generated autoloads from cedet/ede/proj.el - -(register-definition-prefixes "ede/proj" '("ede-proj-")) - -;;;*** - -;;;### (autoloads nil "ede/proj-archive" "cedet/ede/proj-archive.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from cedet/ede/proj-archive.el - -(register-definition-prefixes "ede/proj-archive" '("ede-")) - -;;;*** - -;;;### (autoloads nil "ede/proj-aux" "cedet/ede/proj-aux.el" (0 0 -;;;;;; 0 0)) -;;; Generated autoloads from cedet/ede/proj-aux.el - -(register-definition-prefixes "ede/proj-aux" '("ede-")) - -;;;*** - -;;;### (autoloads nil "ede/proj-comp" "cedet/ede/proj-comp.el" (0 -;;;;;; 0 0 0)) -;;; Generated autoloads from cedet/ede/proj-comp.el - -(register-definition-prefixes "ede/proj-comp" '("ede-" "proj-comp-insert-variable-once")) - -;;;*** - -;;;### (autoloads nil "ede/proj-elisp" "cedet/ede/proj-elisp.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from cedet/ede/proj-elisp.el - -(register-definition-prefixes "ede/proj-elisp" '("ede-")) - -;;;*** - -;;;### (autoloads nil "ede/proj-info" "cedet/ede/proj-info.el" (0 -;;;;;; 0 0 0)) -;;; Generated autoloads from cedet/ede/proj-info.el - -(register-definition-prefixes "ede/proj-info" '("ede-")) - -;;;*** - -;;;### (autoloads nil "ede/proj-misc" "cedet/ede/proj-misc.el" (0 -;;;;;; 0 0 0)) -;;; Generated autoloads from cedet/ede/proj-misc.el - -(register-definition-prefixes "ede/proj-misc" '("ede-")) - -;;;*** -;;;### (autoloads nil "ede/proj-obj" "cedet/ede/proj-obj.el" (0 0 -;;;;;; 0 0)) -;;; Generated autoloads from cedet/ede/proj-obj.el - -(register-definition-prefixes "ede/proj-obj" '("ede-")) - -;;;*** - -;;;### (autoloads nil "ede/proj-prog" "cedet/ede/proj-prog.el" (0 -;;;;;; 0 0 0)) -;;; Generated autoloads from cedet/ede/proj-prog.el - -(register-definition-prefixes "ede/proj-prog" '("ede-proj-target-makefile-program")) - -;;;*** - -;;;### (autoloads nil "ede/proj-scheme" "cedet/ede/proj-scheme.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from cedet/ede/proj-scheme.el - -(register-definition-prefixes "ede/proj-scheme" '("ede-proj-target-scheme")) - -;;;*** - -;;;### (autoloads nil "ede/proj-shared" "cedet/ede/proj-shared.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from cedet/ede/proj-shared.el - -(register-definition-prefixes "ede/proj-shared" '("ede-")) - -;;;*** - -;;;### (autoloads nil "ede/project-am" "cedet/ede/project-am.el" -;;;;;; (0 0 0 0)) -;;; Generated autoloads from cedet/ede/project-am.el - -(register-definition-prefixes "ede/project-am" '("project-am-")) - -;;;*** - -;;;### (autoloads nil "ede/simple" "cedet/ede/simple.el" (0 0 0 0)) -;;; Generated autoloads from cedet/ede/simple.el - -(register-definition-prefixes "ede/simple" '("ede-simple-")) - -;;;*** - -;;;### (autoloads nil "ede/source" "cedet/ede/source.el" (0 0 0 0)) -;;; Generated autoloads from cedet/ede/source.el - -(register-definition-prefixes "ede/source" '("ede-source")) - -;;;*** - -;;;### (autoloads nil "ede/srecode" "cedet/ede/srecode.el" (0 0 0 -;;;;;; 0)) -;;; Generated autoloads from cedet/ede/srecode.el +;;; Generated autoloads from cedet/semantic/ede-grammar.el -(register-definition-prefixes "ede/srecode" '("ede-srecode-")) +(register-definition-prefixes "semantic/ede-grammar" '("semantic-ede-")) -;;;*** -;;;### (autoloads nil "edebug" "emacs-lisp/edebug.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/edebug.el (defvar edebug-all-defs nil "\ @@ -9629,30 +8561,24 @@ This applies to `eval-defun', `eval-region', `eval-buffer', and You can use the command `edebug-all-defs' to toggle the value of this variable. You may wish to make it local to each buffer with -\(make-local-variable \\='edebug-all-defs) in your +(make-local-variable \\='edebug-all-defs) in your `emacs-lisp-mode-hook'. Note that this user option has no effect unless the edebug package has been loaded.") - (custom-autoload 'edebug-all-defs "edebug" t) - (defvar edebug-all-forms nil "\ Non-nil means evaluation of all forms will instrument for Edebug. This doesn't apply to loading or evaluations in the minibuffer. Use the command `edebug-all-forms' to toggle the value of this option.") - (custom-autoload 'edebug-all-forms "edebug" t) - (autoload 'edebug-basic-spec "edebug" "\ Return t if SPEC uses only extant spec symbols. An extant spec symbol is a symbol that is not a function and has a `edebug-form-spec' property. -\(fn SPEC)" nil nil) - +(fn SPEC)" nil nil) (defalias 'edebug-defun 'edebug-eval-top-level-form) - (autoload 'edebug-eval-top-level-form "edebug" "\ Evaluate the top level form point is in, stepping through with Edebug. This is like `eval-defun' except that it steps the code for Edebug @@ -9668,53 +8594,42 @@ instrumented for Edebug. If the current defun is actually a call to `defvar' or `defcustom', evaluating it this way resets the variable using its initial value expression even if the variable already has some other value. -\(Normally `defvar' and `defcustom' do not alter the value if there +(Normally `defvar' and `defcustom' do not alter the value if there already is one.)" t nil) - (autoload 'edebug-all-defs "edebug" "\ Toggle edebugging of all definitions." t nil) - (autoload 'edebug-all-forms "edebug" "\ Toggle edebugging of all forms." t nil) - (register-definition-prefixes "edebug" '("arglist" "backquote-form" "def-declarations" "edebug" "function-form" "interactive" "lambda-" "name" "nested-backquote-form")) -;;;*** -;;;### (autoloads nil "ediff" "vc/ediff.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff.el -(push (purecopy '(ediff 2 81 6)) package--builtin-versions) +(push (purecopy '(ediff 2 81 6)) package--builtin-versions) (autoload 'ediff-files "ediff" "\ Run Ediff on a pair of files, FILE-A and FILE-B. STARTUP-HOOKS is a list of functions that Emacs calls without arguments after setting up the Ediff buffers. -\(fn FILE-A FILE-B &optional STARTUP-HOOKS)" t nil) - +(fn FILE-A FILE-B &optional STARTUP-HOOKS)" t nil) (autoload 'ediff-files3 "ediff" "\ Run Ediff on three files, FILE-A, FILE-B, and FILE-C. STARTUP-HOOKS is a list of functions that Emacs calls without arguments after setting up the Ediff buffers. -\(fn FILE-A FILE-B FILE-C &optional STARTUP-HOOKS)" t nil) - +(fn FILE-A FILE-B FILE-C &optional STARTUP-HOOKS)" t nil) (defalias 'ediff3 #'ediff-files3) - (defalias 'ediff #'ediff-files) - (autoload 'ediff-current-file "ediff" "\ Start ediff between current buffer and its file on disk. This command can be used instead of `revert-buffer'. If there is nothing to revert then this command fails." t nil) - (autoload 'ediff-backup "ediff" "\ Run Ediff on FILE and its backup file. Uses the latest backup, if there are several numerical backups. If this file is a backup, `ediff' it with its original. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'ediff-buffers "ediff" "\ Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B. STARTUP-HOOKS is a list of functions that Emacs calls without @@ -9725,10 +8640,8 @@ symbol describing the Ediff job type; it defaults to `ediff-last-dir-C', `ediff-buffers3', `ediff-merge-buffers', or `ediff-merge-buffers-with-ancestor'. -\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME)" t nil) - +(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME)" t nil) (defalias 'ebuffers #'ediff-buffers) - (autoload 'ediff-buffers3 "ediff" "\ Run Ediff on three buffers, BUFFER-A, BUFFER-B, and BUFFER-C. STARTUP-HOOKS is a list of functions that Emacs calls without @@ -9739,10 +8652,8 @@ symbol describing the Ediff job type; it defaults to `ediff-last-dir-C', `ediff-buffers', `ediff-merge-buffers', or `ediff-merge-buffers-with-ancestor'. -\(fn BUFFER-A BUFFER-B BUFFER-C &optional STARTUP-HOOKS JOB-NAME)" t nil) - +(fn BUFFER-A BUFFER-B BUFFER-C &optional STARTUP-HOOKS JOB-NAME)" t nil) (defalias 'ebuffers3 #'ediff-buffers3) - (autoload 'ediff-directories "ediff" "\ Run Ediff on directories DIR1 and DIR2, comparing files. Consider only files that have the same name in both directories. @@ -9750,19 +8661,15 @@ Consider only files that have the same name in both directories. REGEXP is nil or a regular expression; only file names that match the regexp are considered. -\(fn DIR1 DIR2 REGEXP)" t nil) - +(fn DIR1 DIR2 REGEXP)" t nil) (defalias 'edirs #'ediff-directories) - (autoload 'ediff-directory-revisions "ediff" "\ Run Ediff on a directory, DIR1, comparing its files with their revisions. The second argument, REGEXP, is a regular expression that filters the file names. Only the files that are under revision control are taken into account. -\(fn DIR1 REGEXP)" t nil) - +(fn DIR1 REGEXP)" t nil) (defalias 'edir-revisions #'ediff-directory-revisions) - (autoload 'ediff-directories3 "ediff" "\ Run Ediff on directories DIR1, DIR2, and DIR3, comparing files. Consider only files that have the same name in all three directories. @@ -9770,20 +8677,16 @@ Consider only files that have the same name in all three directories. REGEXP is nil or a regular expression; only file names that match the regexp are considered. -\(fn DIR1 DIR2 DIR3 REGEXP)" t nil) - +(fn DIR1 DIR2 DIR3 REGEXP)" t nil) (defalias 'edirs3 #'ediff-directories3) - (autoload 'ediff-merge-directories "ediff" "\ Run Ediff on a pair of directories, DIR1 and DIR2, merging files that have the same name in both. The third argument, REGEXP, is nil or a regular expression; only file names that match the regexp are considered. MERGE-AUTOSTORE-DIR is the directory in which to store merged files. -\(fn DIR1 DIR2 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) - +(fn DIR1 DIR2 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) (defalias 'edirs-merge #'ediff-merge-directories) - (autoload 'ediff-merge-directories-with-ancestor "ediff" "\ Merge files in DIR1 and DIR2 using files in ANCESTOR-DIR as ancestors. Ediff merges files that have identical names in DIR1, DIR2. If a pair of files @@ -9792,30 +8695,24 @@ without ancestor. The fourth argument, REGEXP, is nil or a regular expression; only file names that match the regexp are considered. MERGE-AUTOSTORE-DIR is the directory in which to store merged files. -\(fn DIR1 DIR2 ANCESTOR-DIR REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) - +(fn DIR1 DIR2 ANCESTOR-DIR REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) (autoload 'ediff-merge-directory-revisions "ediff" "\ Run Ediff on a directory, DIR1, merging its files with their revisions. The second argument, REGEXP, is a regular expression that filters the file names. Only the files that are under revision control are taken into account. MERGE-AUTOSTORE-DIR is the directory in which to store merged files. -\(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) - +(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) (defalias 'edir-merge-revisions #'ediff-merge-directory-revisions) - (autoload 'ediff-merge-directory-revisions-with-ancestor "ediff" "\ Run Ediff on DIR1 and merge its files with their revisions and ancestors. The second argument, REGEXP, is a regular expression that filters the file names. Only the files that are under revision control are taken into account. MERGE-AUTOSTORE-DIR is the directory in which to store merged files. -\(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) - +(fn DIR1 REGEXP &optional MERGE-AUTOSTORE-DIR)" t nil) (defalias 'edir-merge-revisions-with-ancestor 'ediff-merge-directory-revisions-with-ancestor) - (defalias 'edirs-merge-with-ancestor 'ediff-merge-directories-with-ancestor) - (autoload 'ediff-windows-wordwise "ediff" "\ Compare WIND-A and WIND-B, which are selected by clicking, wordwise. This compares the portions of text visible in each of the two windows. @@ -9826,8 +8723,7 @@ If WIND-B is nil, use window next to WIND-A. STARTUP-HOOKS is a list of functions that Emacs calls without arguments after setting up the Ediff buffers. -\(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil) - +(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil) (autoload 'ediff-windows-linewise "ediff" "\ Compare WIND-A and WIND-B, which are selected by clicking, linewise. This compares the portions of text visible in each of the two windows. @@ -9838,8 +8734,7 @@ If WIND-B is nil, use window next to WIND-A. STARTUP-HOOKS is a list of functions that Emacs calls without arguments after setting up the Ediff buffers. -\(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil) - +(fn DUMB-MODE &optional WIND-A WIND-B STARTUP-HOOKS)" t nil) (autoload 'ediff-regions-wordwise "ediff" "\ Run Ediff on a pair of regions in specified buffers. BUFFER-A and BUFFER-B are the buffers to be compared. @@ -9849,8 +8744,7 @@ use `ediff-regions-linewise' instead. STARTUP-HOOKS is a list of functions that Emacs calls without arguments after setting up the Ediff buffers. -\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil) - +(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil) (autoload 'ediff-regions-linewise "ediff" "\ Run Ediff on a pair of regions in specified buffers. BUFFER-A and BUFFER-B are the buffers to be compared. @@ -9861,10 +8755,8 @@ lines. For small regions, use `ediff-regions-wordwise'. STARTUP-HOOKS is a list of functions that Emacs calls without arguments after setting up the Ediff buffers. -\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil) - +(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS)" t nil) (defalias 'ediff-merge 'ediff-merge-files) - (autoload 'ediff-merge-files "ediff" "\ Merge two files without ancestor. FILE-A and FILE-B are the names of the files to be merged. @@ -9872,8 +8764,7 @@ STARTUP-HOOKS is a list of functions that Emacs calls without arguments after setting up the Ediff buffers. MERGE-BUFFER-FILE is the name of the file to be associated with the merge buffer.. -\(fn FILE-A FILE-B &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) - +(fn FILE-A FILE-B &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) (autoload 'ediff-merge-files-with-ancestor "ediff" "\ Merge two files with ancestor. FILE-A and FILE-B are the names of the files to be merged, and @@ -9882,10 +8773,8 @@ a list of functions that Emacs calls without arguments after setting up the Ediff buffers. MERGE-BUFFER-FILE is the name of the file to be associated with the merge buffer. -\(fn FILE-A FILE-B FILE-ANCESTOR &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) - +(fn FILE-A FILE-B FILE-ANCESTOR &optional STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) (defalias 'ediff-merge-with-ancestor 'ediff-merge-files-with-ancestor) - (autoload 'ediff-merge-buffers "ediff" "\ Merge buffers without ancestor. BUFFER-A and BUFFER-B are the buffers to be merged. @@ -9898,8 +8787,7 @@ symbol describing the Ediff job type; it defaults to `ediff-merge-buffers-with-ancestor'. MERGE-BUFFER-FILE is the name of the file to be associated with the merge buffer. -\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil) - +(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil) (autoload 'ediff-merge-buffers-with-ancestor "ediff" "\ Merge buffers with ancestor. BUFFER-A and BUFFER-B are the buffers to be merged, and @@ -9912,8 +8800,7 @@ also be one of `ediff-merge-files-with-ancestor', `ediff-buffers3', or `ediff-merge-buffers'. MERGE-BUFFER-FILE is the name of the file to be associated with the merge buffer. -\(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil) - +(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS JOB-NAME MERGE-BUFFER-FILE)" t nil) (autoload 'ediff-merge-revisions "ediff" "\ Run Ediff by merging two revisions of a file. The file is the optional FILE argument or the file visited by the @@ -9922,8 +8809,7 @@ calls without arguments after setting up the Ediff buffers. MERGE-BUFFER-FILE is the name of the file to be associated with the merge buffer. -\(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) - +(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) (autoload 'ediff-merge-revisions-with-ancestor "ediff" "\ Run Ediff by merging two revisions of a file with a common ancestor. The file is the optional FILE argument or the file visited by the @@ -9932,8 +8818,7 @@ calls without arguments after setting up the Ediff buffers. MERGE-BUFFER-FILE is the name of the file to be associated with the merge buffer. -\(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) - +(fn &optional FILE STARTUP-HOOKS MERGE-BUFFER-FILE)" t nil) (autoload 'ediff-patch-file "ediff" "\ Query for a file name, and then run Ediff by patching that file. If optional PATCH-BUF is given, use the patch in that buffer @@ -9941,8 +8826,7 @@ and don't ask the user. If prefix argument ARG, then: if even argument, assume that the patch is in a buffer. If odd -- assume it is in a file. -\(fn &optional ARG PATCH-BUF)" t nil) - +(fn &optional ARG PATCH-BUF)" t nil) (autoload 'ediff-patch-buffer "ediff" "\ Run Ediff by patching the buffer specified at prompt. Without the optional prefix ARG, asks if the patch is in some buffer and @@ -9952,12 +8836,9 @@ With ARG=2, assumes the patch is in a buffer and prompts for the buffer. PATCH-BUF is an optional argument, which specifies the buffer that contains the patch. If not given, the user is prompted according to the prefix argument. -\(fn &optional ARG PATCH-BUF)" t nil) - +(fn &optional ARG PATCH-BUF)" t nil) (defalias 'epatch 'ediff-patch-file) - (defalias 'epatch-buffer 'ediff-patch-buffer) - (autoload 'ediff-revision "ediff" "\ Run Ediff by comparing versions of a file. The file is an optional FILE argument or the file entered at the prompt. @@ -9966,130 +8847,98 @@ Uses `vc.el' or `rcs.el' depending on `ediff-version-control-package'. STARTUP-HOOKS is a list of functions that Emacs calls without arguments after setting up the Ediff buffers. -\(fn &optional FILE STARTUP-HOOKS)" t nil) - +(fn &optional FILE STARTUP-HOOKS)" t nil) (defalias 'erevision 'ediff-revision) - (autoload 'ediff-version "ediff" "\ Return string describing the version of Ediff. When called interactively, displays the version." t nil) - (autoload 'ediff-documentation "ediff" "\ Display Ediff's manual. With optional NODE, goes to that node. -\(fn &optional NODE)" t nil) - +(fn &optional NODE)" t nil) (autoload 'ediff-files-command "ediff" "\ Call `ediff-files' with the next two command line arguments." nil nil) - (autoload 'ediff3-files-command "ediff" "\ Call `ediff3-files' with the next three command line arguments." nil nil) - (autoload 'ediff-merge-command "ediff" "\ Call `ediff-merge-files' with the next two command line arguments." nil nil) - (autoload 'ediff-merge-with-ancestor-command "ediff" "\ Call `ediff-merge-files-with-ancestor' with next three command line arguments." nil nil) - (autoload 'ediff-directories-command "ediff" "\ Call `ediff-directories' with the next three command line arguments." nil nil) - (autoload 'ediff-directories3-command "ediff" "\ Call `ediff-directories3' with the next four command line arguments." nil nil) - (autoload 'ediff-merge-directories-command "ediff" "\ Call `ediff-merge-directories' with the next three command line arguments." nil nil) - (autoload 'ediff-merge-directories-with-ancestor-command "ediff" "\ Call `ediff-merge-directories-with-ancestor' with the next four command line arguments." nil nil) - (register-definition-prefixes "ediff" '("ediff-")) -;;;*** -;;;### (autoloads nil "ediff-diff" "vc/ediff-diff.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-diff.el (register-definition-prefixes "ediff-diff" '("ediff-")) -;;;*** -;;;### (autoloads nil "ediff-help" "vc/ediff-help.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-help.el (autoload 'ediff-customize "ediff-help" nil t nil) - (register-definition-prefixes "ediff-help" '("ediff-")) -;;;*** -;;;### (autoloads nil "ediff-init" "vc/ediff-init.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-init.el (register-definition-prefixes "ediff-init" '("ediff-" "stipple-pixmap")) -;;;*** -;;;### (autoloads nil "ediff-merg" "vc/ediff-merg.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-merg.el (register-definition-prefixes "ediff-merg" '("ediff-")) -;;;*** -;;;### (autoloads nil "ediff-mult" "vc/ediff-mult.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-mult.el (autoload 'ediff-show-registry "ediff-mult" "\ Display Ediff's registry." t nil) - (defalias 'eregistry #'ediff-show-registry) - (register-definition-prefixes "ediff-mult" '("ediff-")) -;;;*** -;;;### (autoloads nil "ediff-ptch" "vc/ediff-ptch.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-ptch.el (register-definition-prefixes "ediff-ptch" '("ediff-")) -;;;*** -;;;### (autoloads nil "ediff-util" "vc/ediff-util.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-util.el (autoload 'ediff-toggle-multiframe "ediff-util" "\ Switch from multiframe display to single-frame display and back. To change the default, set the variable `ediff-window-setup-function', which see." t nil) - (autoload 'ediff-toggle-use-toolbar "ediff-util" "\ Enable or disable Ediff toolbar. Works only in versions of Emacs that support toolbars. To change the default, set the variable `ediff-use-toolbar-p', which see." t nil) - (register-definition-prefixes "ediff-util" '("ediff-")) -;;;*** -;;;### (autoloads nil "ediff-vers" "vc/ediff-vers.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-vers.el (register-definition-prefixes "ediff-vers" '("ediff-" "rcs-ediff-view-revision")) -;;;*** -;;;### (autoloads nil "ediff-wind" "vc/ediff-wind.el" (0 0 0 0)) ;;; Generated autoloads from vc/ediff-wind.el (register-definition-prefixes "ediff-wind" '("ediff-")) -;;;*** -;;;### (autoloads nil "edmacro" "edmacro.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/edit.el + +(register-definition-prefixes "semantic/edit" '("semantic-")) + + ;;; Generated autoloads from edmacro.el (autoload 'edit-kbd-macro "edmacro" "\ @@ -10101,18 +8950,15 @@ keystrokes as a keyboard macro, or `\\[execute-extended-command]' to edit a macro by its command name. With a prefix argument, format the macro in a more concise way. -\(fn KEYS &optional PREFIX FINISH-HOOK STORE-HOOK)" t nil) - +(fn KEYS &optional PREFIX FINISH-HOOK STORE-HOOK)" t nil) (autoload 'edit-last-kbd-macro "edmacro" "\ Edit the most recently defined keyboard macro. -\(fn &optional PREFIX)" t nil) - +(fn &optional PREFIX)" t nil) (autoload 'edit-named-kbd-macro "edmacro" "\ Edit a keyboard macro which has been given a name by `name-last-kbd-macro'. -\(fn &optional PREFIX)" t nil) - +(fn &optional PREFIX)" t nil) (autoload 'read-kbd-macro "edmacro" "\ Read the region as a keyboard macro definition. The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\". @@ -10125,8 +8971,7 @@ the result is returned rather than being installed as the current macro. The result will be a string if possible, otherwise an event vector. Second argument NEED-VECTOR means to return an event vector always. -\(fn START &optional END)" t nil) - +(fn START &optional END)" t nil) (autoload 'format-kbd-macro "edmacro" "\ Return the keyboard macro MACRO as a human-readable string. This string is suitable for passing to `read-kbd-macro'. @@ -10134,13 +8979,10 @@ Second argument VERBOSE means to put one command per line with comments. If VERBOSE is `1', put everything on one line. If VERBOSE is omitted or nil, use a compact 80-column format. -\(fn &optional MACRO VERBOSE)" nil nil) - +(fn &optional MACRO VERBOSE)" nil nil) (register-definition-prefixes "edmacro" '("edmacro-")) -;;;*** -;;;### (autoloads nil "edt" "emulation/edt.el" (0 0 0 0)) ;;; Generated autoloads from emulation/edt.el (autoload 'edt-set-scroll-margins "edt" "\ @@ -10148,47 +8990,32 @@ Set scroll margins. Argument TOP is the top margin in number of lines or percent of window. Argument BOTTOM is the bottom margin in number of lines or percent of window. -\(fn TOP BOTTOM)" t nil) - +(fn TOP BOTTOM)" t nil) (autoload 'edt-emulation-on "edt" "\ Turn on EDT Emulation." t nil) - (register-definition-prefixes "edt" '("edt-")) -;;;*** -;;;### (autoloads nil "edt-lk201" "emulation/edt-lk201.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from emulation/edt-lk201.el (register-definition-prefixes "edt-lk201" '("*EDT-keys*")) -;;;*** -;;;### (autoloads nil "edt-mapper" "emulation/edt-mapper.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from emulation/edt-mapper.el (register-definition-prefixes "edt-mapper" '("edt-")) -;;;*** -;;;### (autoloads nil "edt-pc" "emulation/edt-pc.el" (0 0 0 0)) ;;; Generated autoloads from emulation/edt-pc.el (register-definition-prefixes "edt-pc" '("*EDT-keys*")) -;;;*** -;;;### (autoloads nil "edt-vt100" "emulation/edt-vt100.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from emulation/edt-vt100.el (register-definition-prefixes "edt-vt100" '("edt-set-term-width-")) -;;;*** -;;;### (autoloads nil "ehelp" "ehelp.el" (0 0 0 0)) ;;; Generated autoloads from ehelp.el (autoload 'with-electric-help "ehelp" "\ @@ -10215,38 +9042,28 @@ When the user exits (with `electric-help-exit', or otherwise), the help buffer's window disappears (i.e., we use `save-window-excursion'), and BUFFER is put back into its original major mode. -\(fn THUNK &optional BUFFER NOERASE MINHEIGHT)" nil nil) - +(fn THUNK &optional BUFFER NOERASE MINHEIGHT)" nil nil) (autoload 'electric-helpify "ehelp" "\ -\(fn FUN &optional NAME)" nil nil) - +(fn FUN &optional NAME)" nil nil) (register-definition-prefixes "ehelp" '("ehelp-" "electric-")) -;;;*** -;;;### (autoloads nil "eieio" "emacs-lisp/eieio.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/eieio.el -(push (purecopy '(eieio 1 4)) package--builtin-versions) +(push (purecopy '(eieio 1 4)) package--builtin-versions) (register-definition-prefixes "eieio" '("child-of-class-p" "defclass" "eieio-" "find-class" "obj" "oref" "oset" "same-class-p" "set-slot-value" "slot-" "with-slots")) -;;;*** -;;;### (autoloads nil "eieio-base" "emacs-lisp/eieio-base.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from emacs-lisp/eieio-base.el (register-definition-prefixes "eieio-base" '("eieio-")) -;;;*** -;;;### (autoloads nil "eieio-core" "emacs-lisp/eieio-core.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from emacs-lisp/eieio-core.el -(push (purecopy '(eieio-core 1 4)) package--builtin-versions) +(push (purecopy '(eieio-core 1 4)) package--builtin-versions) (autoload 'eieio-defclass-autoload "eieio-core" "\ Create autoload symbols for the EIEIO class CNAME. SUPERCLASSES are the superclasses that CNAME inherits from. @@ -10255,35 +9072,45 @@ This function creates a mock-class for CNAME and adds it into SUPERCLASSES as children. It creates an autoload function for CNAME's constructor. -\(fn CNAME SUPERCLASSES FILENAME DOC)" nil nil) - +(fn CNAME SUPERCLASSES FILENAME DOC)" nil nil) (register-definition-prefixes "eieio-core" '("class-" "eieio-" "inconsistent-class-hierarchy" "invalid-slot-" "unbound-slot")) -;;;*** -;;;### (autoloads nil "eieio-datadebug" "emacs-lisp/eieio-datadebug.el" -;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-custom.el + +(register-definition-prefixes "eieio-custom" '("eieio-")) + + ;;; Generated autoloads from emacs-lisp/eieio-datadebug.el (register-definition-prefixes "eieio-datadebug" '("data-debug-insert-object-")) -;;;*** -;;;### (autoloads nil "eieio-speedbar" "emacs-lisp/eieio-speedbar.el" -;;;;;; (0 0 0 0)) +;;; Generated autoloads from emacs-lisp/eieio-opt.el + +(register-definition-prefixes "eieio-opt" '("eieio-")) + + ;;; Generated autoloads from emacs-lisp/eieio-speedbar.el (register-definition-prefixes "eieio-speedbar" '("eieio-speedbar")) -;;;*** -;;;### (autoloads nil "eldoc" "emacs-lisp/eldoc.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/el.el + +(register-definition-prefixes "srecode/el" '("srecode-semantic-apply-tag-to-dict")) + + +;;; Generated autoloads from cedet/semantic/bovine/el.el + +(register-definition-prefixes "semantic/bovine/el" '("emacs-lisp-mode" "semantic-")) + + ;;; Generated autoloads from emacs-lisp/eldoc.el + (push (purecopy '(eldoc 1 12 0)) package--builtin-versions) -;;;*** -;;;### (autoloads nil "elec-pair" "elec-pair.el" (0 0 0 0)) ;;; Generated autoloads from elec-pair.el (defvar electric-pair-mode nil "\ @@ -10293,9 +9120,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `electric-pair-mode'.") - (custom-autoload 'electric-pair-mode "elec-pair" nil) - (autoload 'electric-pair-mode "elec-pair" "\ Toggle automatic parens pairing (Electric Pair mode). @@ -10321,8 +9146,7 @@ evaluate `(default-value \\='electric-pair-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'electric-pair-local-mode "elec-pair" "\ Toggle `electric-pair-mode' only in this buffer. @@ -10337,18 +9161,15 @@ Disable the mode if ARG is a negative number. To check whether the minor mode is enabled in the current buffer, evaluate `(buffer-local-value \\='electric-pair-mode -\(current-buffer))'. +(current-buffer))'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "elec-pair" '("electric-pair-")) -;;;*** -;;;### (autoloads nil "elide-head" "elide-head.el" (0 0 0 0)) ;;; Generated autoloads from elide-head.el (autoload 'elide-head-mode "elide-head" "\ @@ -10374,8 +9195,7 @@ evaluate `elide-head-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'elide-head "elide-head" "\ Hide header material in buffer according to `elide-head-headers-to-hide'. @@ -10384,64 +9204,51 @@ an elided material again. This is suitable as an entry on `find-file-hook' or appropriate mode hooks. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (make-obsolete 'elide-head 'elide-head-mode '"29.1") - (register-definition-prefixes "elide-head" '("elide-head-")) -;;;*** -;;;### (autoloads nil "elint" "emacs-lisp/elint.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/elint.el (autoload 'elint-file "elint" "\ Lint the file FILE. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'elint-directory "elint" "\ Lint all the .el files in DIRECTORY. A complicated directory may require a lot of memory. -\(fn DIRECTORY)" t nil) - +(fn DIRECTORY)" t nil) (autoload 'elint-current-buffer "elint" "\ Lint the current buffer. If necessary, this first calls `elint-initialize'." t nil) - (autoload 'elint-defun "elint" "\ Lint the function at point. If necessary, this first calls `elint-initialize'." t nil) - (autoload 'elint-initialize "elint" "\ Initialize elint. If elint is already initialized, this does nothing, unless optional prefix argument REINIT is non-nil. -\(fn &optional REINIT)" t nil) - +(fn &optional REINIT)" t nil) (register-definition-prefixes "elint" '("elint-")) -;;;*** -;;;### (autoloads nil "elp" "emacs-lisp/elp.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/elp.el (autoload 'elp-instrument-function "elp" "\ Instrument FUNSYM for profiling. FUNSYM must be a symbol of a defined function. -\(fn FUNSYM)" t nil) - +(fn FUNSYM)" t nil) (autoload 'elp-instrument-list "elp" "\ Instrument, for profiling, all functions in `elp-function-list'. Use optional LIST if provided instead. If called interactively, prompt for LIST in the minibuffer; type \"nil\" to use `elp-function-list'. -\(fn &optional LIST)" t nil) - +(fn &optional LIST)" t nil) (autoload 'elp-instrument-package "elp" "\ Instrument for profiling, all functions which start with PREFIX. For example, to instrument all ELP functions, do the following: @@ -10453,27 +9260,115 @@ instrumented. If you run this function, and then later load further functions that start with PREFIX, they will not be instrumented automatically. -\(fn PREFIX)" t nil) - +(fn PREFIX)" t nil) (autoload 'elp-results "elp" "\ Display current profiling results. If `elp-reset-after-results' is non-nil, then current profiling information for all instrumented functions is reset after results are displayed." t nil) - (register-definition-prefixes "elp" '("elp-")) -;;;*** -;;;### (autoloads nil "em-extpipe" "eshell/em-extpipe.el" (0 0 0 -;;;;;; 0)) +;;; Generated autoloads from eshell/em-alias.el + +(register-definition-prefixes "em-alias" '("eshell" "pcomplete/eshell-mode/alias")) + + +;;; Generated autoloads from eshell/em-banner.el + +(register-definition-prefixes "em-banner" '("eshell-banner-")) + + +;;; Generated autoloads from eshell/em-basic.el + +(register-definition-prefixes "em-basic" '("eshell")) + + +;;; Generated autoloads from eshell/em-cmpl.el + +(register-definition-prefixes "em-cmpl" '("eshell-")) + + +;;; Generated autoloads from eshell/em-dirs.el + +(register-definition-prefixes "em-dirs" '("eshell")) + + +;;; Generated autoloads from eshell/em-elecslash.el + +(register-definition-prefixes "em-elecslash" '("eshell-elec")) + + ;;; Generated autoloads from eshell/em-extpipe.el (register-definition-prefixes "em-extpipe" '("em-extpipe--or-with-catch" "eshell-")) -;;;*** -;;;### (autoloads nil "emacs-lock" "emacs-lock.el" (0 0 0 0)) +;;; Generated autoloads from eshell/em-glob.el + +(register-definition-prefixes "em-glob" '("eshell-")) + + +;;; Generated autoloads from eshell/em-hist.el + +(register-definition-prefixes "em-hist" '("eshell")) + + +;;; Generated autoloads from eshell/em-ls.el + +(register-definition-prefixes "em-ls" '("eshell")) + + +;;; Generated autoloads from eshell/em-pred.el + +(register-definition-prefixes "em-pred" '("eshell-")) + + +;;; Generated autoloads from eshell/em-prompt.el + +(register-definition-prefixes "em-prompt" '("eshell-")) + + +;;; Generated autoloads from eshell/em-rebind.el + +(register-definition-prefixes "em-rebind" '("eshell-")) + + +;;; Generated autoloads from eshell/em-script.el + +(register-definition-prefixes "em-script" '("eshell")) + + +;;; Generated autoloads from eshell/em-smart.el + +(register-definition-prefixes "em-smart" '("eshell-")) + + +;;; Generated autoloads from eshell/em-term.el + +(register-definition-prefixes "em-term" '("eshell-")) + + +;;; Generated autoloads from eshell/em-tramp.el + +(register-definition-prefixes "em-tramp" '("eshell")) + + +;;; Generated autoloads from eshell/em-unix.el + +(register-definition-prefixes "em-unix" '("eshell" "nil-blank-string")) + + +;;; Generated autoloads from eshell/em-xtra.el + +(register-definition-prefixes "em-xtra" '("eshell/")) + + +;;; Generated autoloads from cedet/ede/emacs.el + +(register-definition-prefixes "ede/emacs" '("ede-emacs-")) + + ;;; Generated autoloads from emacs-lock.el (autoload 'emacs-lock-mode "emacs-lock" "\ @@ -10497,31 +9392,23 @@ Other values are interpreted as usual. See also `emacs-lock-unlockable-modes', which exempts buffers under some major modes from being locked under some circumstances. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "emacs-lock" '("emacs-lock-" "toggle-emacs-lock")) -;;;*** -;;;### (autoloads nil "emacs-news-mode" "textmodes/emacs-news-mode.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from textmodes/emacs-news-mode.el (autoload 'emacs-news-mode "emacs-news-mode" "\ Major mode for editing the Emacs NEWS file. -\(fn)" t nil) - +(fn)" t nil) (autoload 'emacs-news-view-mode "emacs-news-mode" "\ Major mode for viewing the Emacs NEWS file. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "emacs-news-mode" '("emacs-news-")) -;;;*** -;;;### (autoloads nil "emacsbug" "mail/emacsbug.el" (0 0 0 0)) ;;; Generated autoloads from mail/emacsbug.el (autoload 'report-emacs-bug "emacsbug" "\ @@ -10532,79 +9419,61 @@ Already submitted bugs can be found in the Emacs bug tracker: https://debbugs.gnu.org/cgi/pkgreport.cgi?package=emacs;max-bugs=100;base-order=1;bug-rev=1 -\(fn TOPIC &optional UNUSED)" t nil) - +(fn TOPIC &optional UNUSED)" t nil) (set-advertised-calling-convention 'report-emacs-bug '(topic) '"24.5") - (autoload 'submit-emacs-patch "emacsbug" "\ Send an Emacs patch to the Emacs maintainers. Interactively, you will be prompted for SUBJECT and a patch FILE name (which will be attached to the mail). You will end up in a Message buffer where you can explain more about the patch. -\(fn SUBJECT FILE)" t nil) - +(fn SUBJECT FILE)" t nil) (register-definition-prefixes "emacsbug" '("emacs-bug--system-description" "report-emacs-bug-")) -;;;*** -;;;### (autoloads nil "emerge" "vc/emerge.el" (0 0 0 0)) ;;; Generated autoloads from vc/emerge.el (autoload 'emerge-files "emerge" "\ Run Emerge on two files FILE-A and FILE-B. -\(fn ARG FILE-A FILE-B FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) - +(fn ARG FILE-A FILE-B FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) (autoload 'emerge-files-with-ancestor "emerge" "\ Run Emerge on two files, giving another file as the ancestor. -\(fn ARG FILE-A FILE-B FILE-ANCESTOR FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) - +(fn ARG FILE-A FILE-B FILE-ANCESTOR FILE-OUT &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) (autoload 'emerge-buffers "emerge" "\ Run Emerge on two buffers BUFFER-A and BUFFER-B. -\(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) - +(fn BUFFER-A BUFFER-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) (autoload 'emerge-buffers-with-ancestor "emerge" "\ Run Emerge on two buffers, giving another buffer as the ancestor. -\(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) - +(fn BUFFER-A BUFFER-B BUFFER-ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) (autoload 'emerge-files-command "emerge" nil nil nil) - (autoload 'emerge-files-with-ancestor-command "emerge" nil nil nil) - (autoload 'emerge-files-remote "emerge" "\ -\(fn FILE-A FILE-B FILE-OUT)" nil nil) - +(fn FILE-A FILE-B FILE-OUT)" nil nil) (autoload 'emerge-files-with-ancestor-remote "emerge" "\ -\(fn FILE-A FILE-B FILE-ANC FILE-OUT)" nil nil) - +(fn FILE-A FILE-B FILE-ANC FILE-OUT)" nil nil) (autoload 'emerge-revisions "emerge" "\ Emerge two RCS revisions of a file. -\(fn ARG FILE REVISION-A REVISION-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) - +(fn ARG FILE REVISION-A REVISION-B &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) (autoload 'emerge-revisions-with-ancestor "emerge" "\ Emerge two RCS revisions of a file, with another revision as ancestor. -\(fn ARG FILE REVISION-A REVISION-B ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) - +(fn ARG FILE REVISION-A REVISION-B ANCESTOR &optional STARTUP-HOOKS QUIT-HOOKS)" t nil) (autoload 'emerge-merge-directories "emerge" "\ -\(fn A-DIR B-DIR ANCESTOR-DIR OUTPUT-DIR)" t nil) - +(fn A-DIR B-DIR ANCESTOR-DIR OUTPUT-DIR)" t nil) (register-definition-prefixes "emerge" '("emerge-")) -;;;*** -;;;### (autoloads nil "emoji" "international/emoji.el" (0 0 0 0)) ;;; Generated autoloads from international/emoji.el (autoload 'emoji-insert "emoji" "\ @@ -10613,23 +9482,19 @@ If TEXT (interactively, the prefix argument), choose the emoji by typing its Unicode Standard name (with completion), instead of selecting from emoji display. -\(fn &optional TEXT)" t nil) - +(fn &optional TEXT)" t nil) (autoload 'emoji-recent "emoji" "\ Choose and insert one of the recently-used emoji glyphs." t nil) - (autoload 'emoji-search "emoji" "\ Choose and insert an emoji glyph by typing its Unicode name. This command prompts for an emoji name, with completion, and inserts it. It recognizes the Unicode Standard names of emoji, and also consults the `emoji-alternate-names' alist." t nil) - (autoload 'emoji-list "emoji" "\ List emojis and insert the one that's selected. Select the emoji by typing \\\\[emoji-list-select] on its picture. The glyph will be inserted into the buffer that was current when the command was invoked." t nil) - (autoload 'emoji-describe "emoji" "\ Display the name of the grapheme cluster composed from GLYPH. GLYPH should be a string of one or more characters which together @@ -10639,13 +9504,10 @@ could also be any character, not just emoji). If called from Lisp, return the name as a string; return nil if the name is not known. -\(fn GLYPH &optional INTERACTIVE)" t nil) - +(fn GLYPH &optional INTERACTIVE)" t nil) (register-definition-prefixes "emoji" '("emoji-")) -;;;*** -;;;### (autoloads nil "enriched" "textmodes/enriched.el" (0 0 0 0)) ;;; Generated autoloads from textmodes/enriched.el (autoload 'enriched-mode "enriched" "\ @@ -10677,35 +9539,28 @@ evaluate `enriched-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'enriched-encode "enriched" "\ -\(fn FROM TO ORIG-BUF)" nil nil) - +(fn FROM TO ORIG-BUF)" nil nil) (autoload 'enriched-decode "enriched" "\ -\(fn FROM TO)" nil nil) - +(fn FROM TO)" nil nil) (register-definition-prefixes "enriched" '("enriched-")) -;;;*** -;;;### (autoloads nil "epa" "epa.el" (0 0 0 0)) ;;; Generated autoloads from epa.el (autoload 'epa-list-keys "epa" "\ List all keys matched with NAME from the public keyring. -\(fn &optional NAME)" t nil) - +(fn &optional NAME)" t nil) (autoload 'epa-list-secret-keys "epa" "\ List all keys matched with NAME from the private keyring. -\(fn &optional NAME)" t nil) - +(fn &optional NAME)" t nil) (autoload 'epa-select-keys "epa" "\ Display a user's keyring and ask him to select keys. CONTEXT is an `epg-context'. @@ -10714,29 +9569,24 @@ NAMES is a list of strings to be matched with keys. If it is nil, all the keys are listed. If SECRET is non-nil, list secret keys instead of public keys. -\(fn CONTEXT PROMPT &optional NAMES SECRET)" nil nil) - +(fn CONTEXT PROMPT &optional NAMES SECRET)" nil nil) (autoload 'epa-decrypt-file "epa" "\ Decrypt DECRYPT-FILE into PLAIN-FILE. If you do not specify PLAIN-FILE, this functions prompts for the value to use. -\(fn DECRYPT-FILE &optional PLAIN-FILE)" t nil) - +(fn DECRYPT-FILE &optional PLAIN-FILE)" t nil) (autoload 'epa-verify-file "epa" "\ Verify FILE. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'epa-sign-file "epa" "\ Sign FILE by SIGNERS keys selected. -\(fn FILE SIGNERS MODE)" t nil) - +(fn FILE SIGNERS MODE)" t nil) (autoload 'epa-encrypt-file "epa" "\ Encrypt FILE for RECIPIENTS. -\(fn FILE RECIPIENTS)" t nil) - +(fn FILE RECIPIENTS)" t nil) (autoload 'epa-decrypt-region "epa" "\ Decrypt the current region between START and END. @@ -10755,23 +9605,20 @@ should consider using the string based counterpart For example: -\(let ((context (epg-make-context \\='OpenPGP))) +(let ((context (epg-make-context \\='OpenPGP))) (decode-coding-string (epg-decrypt-string context (buffer-substring start end)) \\='utf-8)) -\(fn START END &optional MAKE-BUFFER-FUNCTION)" t nil) - +(fn START END &optional MAKE-BUFFER-FUNCTION)" t nil) (autoload 'epa-decrypt-armor-in-region "epa" "\ Decrypt OpenPGP armors in the current region between START and END. Don't use this command in Lisp programs! See the reason described in the `epa-decrypt-region' documentation. -\(fn START END)" t nil) - +(fn START END)" t nil) (function-put 'epa-decrypt-armor-in-region 'interactive-only 't) - (autoload 'epa-verify-region "epa" "\ Verify the current region between START and END. @@ -10785,25 +9632,21 @@ should consider using the string based counterpart For example: -\(let ((context (epg-make-context \\='OpenPGP))) +(let ((context (epg-make-context \\='OpenPGP))) (decode-coding-string (epg-verify-string context (buffer-substring start end)) \\='utf-8)) -\(fn START END)" t nil) - +(fn START END)" t nil) (function-put 'epa-verify-region 'interactive-only 't) - (autoload 'epa-verify-cleartext-in-region "epa" "\ Verify OpenPGP cleartext signed messages in current region from START to END. Don't use this command in Lisp programs! See the reason described in the `epa-verify-region' documentation. -\(fn START END)" t nil) - +(fn START END)" t nil) (function-put 'epa-verify-cleartext-in-region 'interactive-only 't) - (autoload 'epa-sign-region "epa" "\ Sign the current region between START and END by SIGNERS keys selected. @@ -10816,15 +9659,13 @@ based counterpart `epg-sign-file' instead. For example: -\(let ((context (epg-make-context \\='OpenPGP))) +(let ((context (epg-make-context \\='OpenPGP))) (epg-sign-string context (encode-coding-string (buffer-substring start end) \\='utf-8))) -\(fn START END SIGNERS MODE)" t nil) - +(fn START END SIGNERS MODE)" t nil) (function-put 'epa-sign-region 'interactive-only 't) - (autoload 'epa-encrypt-region "epa" "\ Encrypt the current region between START and END for RECIPIENTS. @@ -10837,84 +9678,64 @@ file based counterpart `epg-encrypt-file' instead. For example: -\(let ((context (epg-make-context \\='OpenPGP))) +(let ((context (epg-make-context \\='OpenPGP))) (epg-encrypt-string context (encode-coding-string (buffer-substring start end) \\='utf-8) nil)) -\(fn START END RECIPIENTS SIGN SIGNERS)" t nil) - +(fn START END RECIPIENTS SIGN SIGNERS)" t nil) (function-put 'epa-encrypt-region 'interactive-only 't) - (autoload 'epa-delete-keys "epa" "\ Delete selected KEYS. -\(fn KEYS &optional ALLOW-SECRET)" t nil) - +(fn KEYS &optional ALLOW-SECRET)" t nil) (autoload 'epa-import-keys "epa" "\ Import keys from FILE. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'epa-import-keys-region "epa" "\ Import keys from the region. -\(fn START END)" t nil) - +(fn START END)" t nil) (autoload 'epa-import-armor-in-region "epa" "\ Import keys in the OpenPGP armor format in the current region from START to END. -\(fn START END)" t nil) - +(fn START END)" t nil) (autoload 'epa-export-keys "epa" "\ Export selected KEYS to FILE. -\(fn KEYS FILE)" t nil) - +(fn KEYS FILE)" t nil) (autoload 'epa-insert-keys "epa" "\ Insert selected KEYS after the point. -\(fn KEYS)" t nil) - +(fn KEYS)" t nil) (register-definition-prefixes "epa" '("epa-")) -;;;*** -;;;### (autoloads nil "epa-dired" "epa-dired.el" (0 0 0 0)) ;;; Generated autoloads from epa-dired.el (autoload 'epa-dired-do-decrypt "epa-dired" "\ Decrypt marked files." t nil) - (autoload 'epa-dired-do-verify "epa-dired" "\ Verify marked files." t nil) - (autoload 'epa-dired-do-sign "epa-dired" "\ Sign marked files." t nil) - (autoload 'epa-dired-do-encrypt "epa-dired" "\ Encrypt marked files." t nil) -;;;*** -;;;### (autoloads nil "epa-file" "epa-file.el" (0 0 0 0)) ;;; Generated autoloads from epa-file.el (autoload 'epa-file-handler "epa-file" "\ -\(fn OPERATION &rest ARGS)" nil nil) - +(fn OPERATION &rest ARGS)" nil nil) (autoload 'epa-file-enable "epa-file" nil t nil) - (autoload 'epa-file-disable "epa-file" nil t nil) - (register-definition-prefixes "epa-file" '("epa-")) -;;;*** -;;;### (autoloads nil "epa-ks" "epa-ks.el" (0 0 0 0)) ;;; Generated autoloads from epa-ks.el (autoload 'epa-search-keys "epa-ks" "\ @@ -10928,13 +9749,10 @@ exact matches. Note that the request may fail if the query is not specific enough, since keyservers have strict timeout settings. -\(fn QUERY EXACT)" t nil) - +(fn QUERY EXACT)" t nil) (register-definition-prefixes "epa-ks" '("epa-k")) -;;;*** -;;;### (autoloads nil "epa-mail" "epa-mail.el" (0 0 0 0)) ;;; Generated autoloads from epa-mail.el (autoload 'epa-mail-mode "epa-mail" "\ @@ -10954,20 +9772,15 @@ evaluate `epa-mail-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'epa-mail-decrypt "epa-mail" "\ Decrypt OpenPGP armors in the current buffer. The buffer is expected to contain a mail message." t nil) - (function-put 'epa-mail-decrypt 'interactive-only 't) - (autoload 'epa-mail-verify "epa-mail" "\ Verify OpenPGP cleartext signed messages in the current buffer. The buffer is expected to contain a mail message." t nil) - (function-put 'epa-mail-verify 'interactive-only 't) - (autoload 'epa-mail-sign "epa-mail" "\ Sign the current buffer. The buffer is expected to contain a mail message, and signing is @@ -10975,10 +9788,8 @@ performed with your default key. With prefix argument, asks you to select interactively the key to use from your key ring. -\(fn START END SIGNERS MODE)" t nil) - +(fn START END SIGNERS MODE)" t nil) (function-put 'epa-mail-sign 'interactive-only 't) - (autoload 'epa-mail-encrypt "epa-mail" "\ Encrypt the outgoing mail message in the current buffer. Takes the recipients from the text in the header in the buffer @@ -10992,14 +9803,11 @@ or nil meaning use the defaults. SIGNERS is a list of keys to sign the message with. -\(fn &optional RECIPIENTS SIGNERS)" t nil) - +(fn &optional RECIPIENTS SIGNERS)" t nil) (autoload 'epa-mail-import-keys "epa-mail" "\ Import keys in the OpenPGP armor format in the current buffer. The buffer is expected to contain a mail message." t nil) - (function-put 'epa-mail-import-keys 'interactive-only 't) - (defvar epa-global-mail-mode nil "\ Non-nil if Epa-Global-Mail mode is enabled. See the `epa-global-mail-mode' command @@ -11007,9 +9815,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `epa-global-mail-mode'.") - (custom-autoload 'epa-global-mail-mode "epa-mail" nil) - (autoload 'epa-global-mail-mode "epa-mail" "\ Minor mode to hook EasyPG into Mail mode. @@ -11027,26 +9833,20 @@ evaluate `(default-value \\='epa-global-mail-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "epa-mail" '("epa-mail-")) -;;;*** -;;;### (autoloads nil "epg" "epg.el" (0 0 0 0)) ;;; Generated autoloads from epg.el -(push (purecopy '(epg 1 0 0)) package--builtin-versions) +(push (purecopy '(epg 1 0 0)) package--builtin-versions) (autoload 'epg-make-context "epg" "\ Return a context object. -\(fn &optional PROTOCOL ARMOR TEXTMODE INCLUDE-CERTS CIPHER-ALGORITHM DIGEST-ALGORITHM COMPRESS-ALGORITHM)" nil nil) - +(fn &optional PROTOCOL ARMOR TEXTMODE INCLUDE-CERTS CIPHER-ALGORITHM DIGEST-ALGORITHM COMPRESS-ALGORITHM)" nil nil) (register-definition-prefixes "epg" '("epg-")) -;;;*** -;;;### (autoloads nil "epg-config" "epg-config.el" (0 0 0 0)) ;;; Generated autoloads from epg-config.el (autoload 'epg-find-configuration "epg-config" "\ @@ -11060,13 +9860,10 @@ Then it walks through PROGRAM-ALIST or Otherwise, it tries the programs listed in the entry until the version requirement is met. -\(fn PROTOCOL &optional NO-CACHE PROGRAM-ALIST)" nil nil) - +(fn PROTOCOL &optional NO-CACHE PROGRAM-ALIST)" nil nil) (autoload 'epg-configuration "epg-config" "\ Return a list of internal configuration parameters of `epg-gpg-program'." nil nil) - (make-obsolete 'epg-configuration 'epg-find-configuration '"25.1") - (autoload 'epg-check-configuration "epg-config" "\ Verify that a sufficient version of GnuPG is installed. CONFIG should be a `epg-configuration' object (a plist). @@ -11075,24 +9872,19 @@ REQ-VERSIONS should be a list with elements of the form (MIN semi-open range of acceptable versions. REQ-VERSIONS may also be a single minimum version string. -\(fn CONFIG &optional REQ-VERSIONS)" nil nil) - +(fn CONFIG &optional REQ-VERSIONS)" nil nil) (autoload 'epg-expand-group "epg-config" "\ Look at CONFIG and try to expand GROUP. -\(fn CONFIG GROUP)" nil nil) - +(fn CONFIG GROUP)" nil nil) (register-definition-prefixes "epg-config" '("epg-")) -;;;*** -;;;### (autoloads nil "erc" "erc/erc.el" (0 0 0 0)) ;;; Generated autoloads from erc/erc.el -(push (purecopy '(erc 5 4 1)) package--builtin-versions) +(push (purecopy '(erc 5 4 1)) package--builtin-versions) (autoload 'erc-select-read-args "erc" "\ Prompt the user for values of nick, server, port, and password." nil nil) - (autoload 'erc "erc" "\ ERC is a powerful, modular, and extensible IRC client. This function is the main entry point for ERC. @@ -11114,10 +9906,8 @@ then the server and full-name will be set to those values, whereas `erc-compute-port' and `erc-compute-nick' will be invoked for the values of the other parameters. -\(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)))" t nil) - +(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)))" '((erc-select-read-args)) nil) (defalias 'erc-select #'erc) - (autoload 'erc-tls "erc" "\ ERC is a powerful, modular, and extensible IRC client. This function is the main entry point for ERC over TLS. @@ -11156,64 +9946,197 @@ Example usage: \\='(\"/home/bandali/my-cert.key\" \"/home/bandali/my-cert.crt\")) -\(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)) CLIENT-CERTIFICATE)" t nil) - +(fn &key (SERVER (erc-compute-server)) (PORT (erc-compute-port)) (NICK (erc-compute-nick)) PASSWORD (FULL-NAME (erc-compute-full-name)) CLIENT-CERTIFICATE)" '((let ((erc-default-port erc-default-port-tls)) (erc-select-read-args))) nil) (autoload 'erc-handle-irc-url "erc" "\ Use ERC to IRC on HOST:PORT in CHANNEL as USER with PASSWORD. If ERC is already connected to HOST:PORT, simply /join CHANNEL. Otherwise, connect to HOST:PORT as USER and /join CHANNEL. -\(fn HOST PORT CHANNEL USER PASSWORD)" nil nil) - +(fn HOST PORT CHANNEL USER PASSWORD)" nil nil) (register-definition-prefixes "erc" '("define-erc-module" "erc-")) -;;;*** -;;;### (autoloads nil "erc-backend" "erc/erc-backend.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-autoaway.el + +(register-definition-prefixes "erc-autoaway" '("erc-auto")) + + ;;; Generated autoloads from erc/erc-backend.el (register-definition-prefixes "erc-backend" '("erc-")) -;;;*** -;;;### (autoloads nil "erc-goodies" "erc/erc-goodies.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-button.el + +(register-definition-prefixes "erc-button" '("erc-")) + + +;;; Generated autoloads from erc/erc-capab.el + +(register-definition-prefixes "erc-capab" '("erc-capab-identify-")) + + +;;; Generated autoloads from erc/erc-compat.el + +(register-definition-prefixes "erc-compat" '("erc-")) + + +;;; Generated autoloads from erc/erc-dcc.el + +(register-definition-prefixes "erc-dcc" '("erc-" "pcomplete/erc-mode/")) + + +;;; Generated autoloads from erc/erc-desktop-notifications.el + +(register-definition-prefixes "erc-desktop-notifications" '("erc-notifications-")) + + +;;; Generated autoloads from erc/erc-ezbounce.el + +(register-definition-prefixes "erc-ezbounce" '("erc-ezb-")) + + +;;; Generated autoloads from erc/erc-fill.el + +(register-definition-prefixes "erc-fill" '("erc-")) + + ;;; Generated autoloads from erc/erc-goodies.el (register-definition-prefixes "erc-goodies" '("erc-")) -;;;*** -;;;### (autoloads nil "erc-ibuffer" "erc/erc-ibuffer.el" (0 0 0 0)) ;;; Generated autoloads from erc/erc-ibuffer.el (register-definition-prefixes "erc-ibuffer" '("erc-")) -;;;*** -;;;### (autoloads nil "erc-lang" "erc/erc-lang.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-identd.el + +(register-definition-prefixes "erc-identd" '("erc-identd-")) + + +;;; Generated autoloads from erc/erc-imenu.el + +(register-definition-prefixes "erc-imenu" '("erc-unfill-notice")) + + +;;; Generated autoloads from erc/erc-join.el + +(register-definition-prefixes "erc-join" '("erc-")) + + ;;; Generated autoloads from erc/erc-lang.el (register-definition-prefixes "erc-lang" '("erc-cmd-LANG" "iso-639-1-languages" "language")) -;;;*** -;;;### (autoloads nil "erc-networks" "erc/erc-networks.el" (0 0 0 -;;;;;; 0)) +;;; Generated autoloads from erc/erc-list.el + +(register-definition-prefixes "erc-list" '("erc-")) + + +;;; Generated autoloads from erc/erc-log.el + +(register-definition-prefixes "erc-log" '("erc-")) + + +;;; Generated autoloads from erc/erc-match.el + +(register-definition-prefixes "erc-match" '("erc-")) + + +;;; Generated autoloads from erc/erc-menu.el + +(register-definition-prefixes "erc-menu" '("erc-menu-")) + + +;;; Generated autoloads from erc/erc-netsplit.el + +(register-definition-prefixes "erc-netsplit" '("erc-")) + + ;;; Generated autoloads from erc/erc-networks.el (autoload 'erc-determine-network "erc-networks" "\ Return the name of the network or \"Unknown\" as a symbol. Use the server parameter NETWORK if provided, otherwise parse the server name and search for a match in `erc-networks-alist'." nil nil) - (autoload 'erc-server-select "erc-networks" "\ Interactively select a server to connect to using `erc-server-alist'." t nil) - (register-definition-prefixes "erc-networks" '("erc-")) -;;;*** -;;;### (autoloads nil "ert" "emacs-lisp/ert.el" (0 0 0 0)) +;;; Generated autoloads from erc/erc-notify.el + +(register-definition-prefixes "erc-notify" '("erc-")) + + +;;; Generated autoloads from erc/erc-page.el + +(register-definition-prefixes "erc-page" '("erc-")) + + +;;; Generated autoloads from erc/erc-pcomplete.el + +(register-definition-prefixes "erc-pcomplete" '("erc-pcomplet" "pcomplete")) + + +;;; Generated autoloads from erc/erc-replace.el + +(register-definition-prefixes "erc-replace" '("erc-replace-")) + + +;;; Generated autoloads from erc/erc-ring.el + +(register-definition-prefixes "erc-ring" '("erc-")) + + +;;; Generated autoloads from erc/erc-services.el + +(register-definition-prefixes "erc-services" '("erc-")) + + +;;; Generated autoloads from erc/erc-sound.el + +(register-definition-prefixes "erc-sound" '("erc-")) + + +;;; Generated autoloads from erc/erc-speedbar.el + +(register-definition-prefixes "erc-speedbar" '("erc-")) + + +;;; Generated autoloads from erc/erc-spelling.el + +(register-definition-prefixes "erc-spelling" '("erc-spelling-")) + + +;;; Generated autoloads from erc/erc-stamp.el + +(register-definition-prefixes "erc-stamp" '("erc-")) + + +;;; Generated autoloads from erc/erc-status-sidebar.el + +(register-definition-prefixes "erc-status-sidebar" '("erc-status-sidebar-")) + + +;;; Generated autoloads from erc/erc-track.el + +(register-definition-prefixes "erc-track" '("erc-")) + + +;;; Generated autoloads from erc/erc-truncate.el + +(register-definition-prefixes "erc-truncate" '("erc-max-buffer-size")) + + +;;; Generated autoloads from erc/erc-xdcc.el + +(register-definition-prefixes "erc-xdcc" '("erc-")) + + ;;; Generated autoloads from emacs-lisp/ert.el (autoload 'ert-deftest "ert" "\ @@ -11238,12 +10161,7 @@ it has to be wrapped in `(eval (quote ...))'. If NAME is already defined as a test and Emacs is running in batch mode, an error is signalled. -\(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil t) - -(function-put 'ert-deftest 'doc-string-elt '3) - -(function-put 'ert-deftest 'lisp-indent-function '2) - +(fn NAME () [DOCSTRING] [:expected-result RESULT-TYPE] [:tags \\='(TAG...)] BODY...)" nil 'macro) (autoload 'ert-run-tests-batch "ert" "\ Run the tests specified by SELECTOR, printing results to the terminal. @@ -11254,8 +10172,7 @@ ert-run-tests-batch-and-exit\" useful. Returns the stats object. -\(fn &optional SELECTOR)" nil nil) - +(fn &optional SELECTOR)" nil nil) (autoload 'ert-run-tests-batch-and-exit "ert" "\ Like `ert-run-tests-batch', but exits Emacs when done. @@ -11264,38 +10181,28 @@ on unexpected results, or 2 if the tool detected an error outside of the tests (e.g. invalid SELECTOR or bug in the code that runs the tests). -\(fn &optional SELECTOR)" nil nil) - +(fn &optional SELECTOR)" nil nil) (autoload 'ert-run-tests-interactively "ert" "\ Run the tests specified by SELECTOR and display the results in a buffer. SELECTOR works as described in `ert-select-tests'. -\(fn SELECTOR)" t nil) - +(fn SELECTOR)" t nil) (defalias 'ert #'ert-run-tests-interactively) - (autoload 'ert-describe-test "ert" "\ Display the documentation for TEST-OR-TEST-NAME (a symbol or ert-test). -\(fn TEST-OR-TEST-NAME)" t nil) - +(fn TEST-OR-TEST-NAME)" t nil) (register-definition-prefixes "ert" '("ert-")) -;;;*** -;;;### (autoloads nil "ert-x" "emacs-lisp/ert-x.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/ert-x.el (autoload 'ert-kill-all-test-buffers "ert-x" "\ Kill all test buffers that are still live." t nil) - (register-definition-prefixes "ert-x" '("ert-")) -;;;*** -;;;### (autoloads nil "erts-mode" "progmodes/erts-mode.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from progmodes/erts-mode.el (autoload 'erts-mode "erts-mode" "\ @@ -11304,97 +10211,71 @@ This mode mainly provides some font locking. \\{erts-mode-map} -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "erts-mode" '("erts-")) -;;;*** -;;;### (autoloads nil "esh-arg" "eshell/esh-arg.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-arg.el (register-definition-prefixes "esh-arg" '("eshell-")) -;;;*** -;;;### (autoloads nil "esh-cmd" "eshell/esh-cmd.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-cmd.el (register-definition-prefixes "esh-cmd" '("eshell" "pcomplete/eshell-mode/eshell-debug")) -;;;*** -;;;### (autoloads nil "esh-ext" "eshell/esh-ext.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-ext.el (register-definition-prefixes "esh-ext" '("eshell")) -;;;*** -;;;### (autoloads nil "esh-io" "eshell/esh-io.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-io.el (register-definition-prefixes "esh-io" '("eshell-")) -;;;*** -;;;### (autoloads nil "esh-mode" "eshell/esh-mode.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-mode.el (autoload 'eshell-mode "esh-mode" "\ Emacs shell interactive mode. -\(fn)" t nil) - +(fn)" t nil) (autoload 'eshell-bookmark-jump "esh-mode" "\ Default bookmark handler for Eshell buffers. -\(fn BOOKMARK)" nil nil) - +(fn BOOKMARK)" nil nil) (register-definition-prefixes "esh-mode" '("eshell")) -;;;*** -;;;### (autoloads nil "esh-module" "eshell/esh-module.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from eshell/esh-module.el (register-definition-prefixes "esh-module" '("eshell-")) -;;;*** -;;;### (autoloads nil "esh-opt" "eshell/esh-opt.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-opt.el (register-definition-prefixes "esh-opt" '("eshell-")) -;;;*** -;;;### (autoloads nil "esh-proc" "eshell/esh-proc.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-proc.el (register-definition-prefixes "esh-proc" '("eshell")) -;;;*** -;;;### (autoloads nil "esh-util" "eshell/esh-util.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-util.el (register-definition-prefixes "esh-util" '("eshell-")) -;;;*** -;;;### (autoloads nil "esh-var" "eshell/esh-var.el" (0 0 0 0)) ;;; Generated autoloads from eshell/esh-var.el (register-definition-prefixes "esh-var" '("eshell" "pcomplete/eshell-mode/")) -;;;*** -;;;### (autoloads nil "eshell" "eshell/eshell.el" (0 0 0 0)) ;;; Generated autoloads from eshell/eshell.el -(push (purecopy '(eshell 2 4 2)) package--builtin-versions) +(push (purecopy '(eshell 2 4 2)) package--builtin-versions) (autoload 'eshell "eshell" "\ Create an interactive Eshell buffer. Start a new Eshell session, or switch to an already active @@ -11412,14 +10293,12 @@ value of `eshell-buffer-name', which see. Eshell is a shell-like command interpreter. For more information on Eshell, see Info node `(eshell)Top'. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'eshell-command "eshell" "\ Execute the Eshell command string COMMAND. With prefix ARG, insert output into the current buffer at point. -\(fn &optional COMMAND ARG)" t nil) - +(fn &optional COMMAND ARG)" t nil) (autoload 'eshell-command-result "eshell" "\ Execute the given Eshell COMMAND, and return the result. The result might be any Lisp object. @@ -11427,13 +10306,10 @@ If STATUS-VAR is a symbol, it will be set to the exit status of the command. This is the only way to determine whether the value returned corresponding to a successful execution. -\(fn COMMAND &optional STATUS-VAR)" nil nil) - +(fn COMMAND &optional STATUS-VAR)" nil nil) (register-definition-prefixes "eshell" '("eshell-")) -;;;*** -;;;### (autoloads nil "etags" "progmodes/etags.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/etags.el (defvar tags-file-name nil "\ @@ -11444,59 +10320,44 @@ setting the value of this variable, whether buffer-local or global. Use the `etags' program to make a tags table file.") (put 'tags-file-name 'variable-interactive (purecopy "fVisit tags table: ")) (put 'tags-file-name 'safe-local-variable 'stringp) - (defvar tags-case-fold-search 'default "\ Whether tags operations should be case-sensitive. A value of t means case-insensitive, a value of nil means case-sensitive. Any other value means use the setting of `case-fold-search'.") - (custom-autoload 'tags-case-fold-search "etags" t) - (put 'tags-case-fold-search 'safe-local-variable 'symbolp) - (defvar tags-table-list nil "\ List of file names of tags tables to search. An element that is a directory means the file \"TAGS\" in that directory. To switch to a new list of tags tables, setting this variable is sufficient. If you set this variable, do not also set `tags-file-name'. Use the `etags' program to make a tags table file.") - (custom-autoload 'tags-table-list "etags" t) - (defvar tags-compression-info-list (purecopy '("" ".Z" ".bz2" ".gz" ".xz" ".tgz")) "\ List of extensions tried by etags when `auto-compression-mode' is on. An empty string means search the non-compressed file.") - (custom-autoload 'tags-compression-info-list "etags" t) - (defvar tags-add-tables 'ask-user "\ Control whether to add a new tags table to the current list. t means do; nil means don't (always start a new list). Any other value means ask the user whether to add a new tags table to the current list (as opposed to starting a new list).") - (custom-autoload 'tags-add-tables "etags" t) - (defvar find-tag-hook nil "\ Hook to be run by \\[find-tag] after finding a tag. See `run-hooks'. The value in the buffer in which \\[find-tag] is done is used, not the value in the buffer \\[find-tag] goes to.") - (custom-autoload 'find-tag-hook "etags" t) - (defvar find-tag-default-function nil "\ A function of no arguments used by \\[find-tag] to pick a default tag. If nil, and the symbol that is the value of `major-mode' has a `find-tag-default-function' property (see `put'), that is used. Otherwise, `find-tag-default' is used.") - (custom-autoload 'find-tag-default-function "etags" t) - (autoload 'tags-table-mode "etags" "\ Major mode for tags table file buffers. -\(fn)" t nil) - +(fn)" t nil) (autoload 'visit-tags-table "etags" "\ Tell tags commands to use tags table file FILE. FILE should be the name of a file created with the `etags' program. @@ -11509,8 +10370,7 @@ When you find a tag with \\[find-tag], the buffer it finds the tag in is given a local value of this variable which is the name of the tags file the tag was in. -\(fn FILE &optional LOCAL)" t nil) - +(fn FILE &optional LOCAL)" t nil) (autoload 'visit-tags-table-buffer "etags" "\ Select the buffer containing the current tags table. Optional arg CONT specifies which tags table to visit. @@ -11524,21 +10384,18 @@ Optional second arg CBUF, if non-nil, specifies the initial buffer, which is important if that buffer has a local value of `tags-file-name'. Returns t if it visits a tags table, or nil if there are no more in the list. -\(fn &optional CONT CBUF)" nil nil) - +(fn &optional CONT CBUF)" nil nil) (autoload 'tags-table-files "etags" "\ Return a list of files in the current tags table. Assumes the tags table is the current buffer. The file names are returned as they appeared in the `etags' command that created the table, usually without directory names." nil nil) - (autoload 'tags-lazy-completion-table "etags" nil nil nil) (defun tags-completion-at-point-function () (if (or tags-table-list tags-file-name) (progn (load "etags") (tags-completion-at-point-function)))) - (autoload 'find-tag-noselect "etags" "\ Find tag (in current tags table) whose name contains TAGNAME. Returns the buffer containing the tag's definition and moves its point there, @@ -11559,8 +10416,7 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. -\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) - +(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) (autoload 'find-tag "etags" "\ Find tag (in current tags table) whose name contains TAGNAME. Select the buffer containing the tag's definition, and move point there. @@ -11580,10 +10436,8 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. -\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) - +(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) (make-obsolete 'find-tag 'xref-find-definitions '"25.1") - (autoload 'find-tag-other-window "etags" "\ Find tag (in current tags table) whose name contains TAGNAME. Select the buffer containing the tag's definition in another window, and @@ -11604,10 +10458,8 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. -\(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) - +(fn TAGNAME &optional NEXT-P REGEXP-P)" t nil) (make-obsolete 'find-tag-other-window 'xref-find-definitions-other-window '"25.1") - (autoload 'find-tag-other-frame "etags" "\ Find tag (in current tags table) whose name contains TAGNAME. Select the buffer containing the tag's definition in another frame, and @@ -11628,10 +10480,8 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. -\(fn TAGNAME &optional NEXT-P)" t nil) - +(fn TAGNAME &optional NEXT-P)" t nil) (make-obsolete 'find-tag-other-frame 'xref-find-definitions-other-frame '"25.1") - (autoload 'find-tag-regexp "etags" "\ Find tag (in current tags table) whose name matches REGEXP. Select the buffer containing the tag's definition and move point there. @@ -11650,14 +10500,10 @@ Contrast this with the ring of marks gone to by the command. See documentation of variable `tags-file-name'. -\(fn REGEXP &optional NEXT-P OTHER-WINDOW)" t nil) - +(fn REGEXP &optional NEXT-P OTHER-WINDOW)" t nil) (make-obsolete 'find-tag-regexp 'xref-find-apropos '"25.1") - (defalias 'pop-tag-mark 'xref-go-back) - (defalias 'next-file 'tags-next-file) - (autoload 'tags-next-file "etags" "\ Select next file among files in current tags table. @@ -11671,17 +10517,14 @@ Non-nil second argument NOVISIT means use a temporary buffer Value is nil if the file was already visited; if the file was newly read in, the value is the filename. -\(fn &optional INITIALIZE NOVISIT)" t nil) - +(fn &optional INITIALIZE NOVISIT)" t nil) (autoload 'tags-loop-continue "etags" "\ Continue last \\[tags-search] or \\[tags-query-replace] command. Used noninteractively with non-nil argument to begin such a command (the argument is passed to `next-file', which see). -\(fn &optional FIRST-TIME)" t nil) - +(fn &optional FIRST-TIME)" t nil) (make-obsolete 'tags-loop-continue 'fileloop-continue '"27.1") - (autoload 'tags-search "etags" "\ Search through all files listed in tags table for match for REGEXP. Stops when a match is found. @@ -11692,8 +10535,7 @@ files to search. The search will be restricted to these files. Also see the documentation of the `tags-file-name' variable. -\(fn REGEXP &optional FILES)" t nil) - +(fn REGEXP &optional FILES)" t nil) (autoload 'tags-query-replace "etags" "\ Do `query-replace-regexp' of FROM with TO on all files listed in tags table. Third arg DELIMITED (prefix arg) means replace only word-delimited matches. @@ -11707,10 +10549,8 @@ type \\[help-command] at that time. For non-interactive use, this is superseded by `fileloop-initialize-replace'. -\(fn FROM TO &optional DELIMITED FILES)" t nil) - +(fn FROM TO &optional DELIMITED FILES)" t nil) (set-advertised-calling-convention 'tags-query-replace '(from to &optional delimited) '"27.1") - (autoload 'list-tags "etags" "\ Display list of tags in file FILE. This searches only the first table in the list, and no included @@ -11719,52 +10559,38 @@ usually without a directory specification. If called interactively, FILE defaults to the file name of the current buffer. -\(fn FILE &optional NEXT-MATCH)" t nil) - +(fn FILE &optional NEXT-MATCH)" t nil) (autoload 'tags-apropos "etags" "\ Display list of all tags in tags table REGEXP matches. -\(fn REGEXP)" t nil) - +(fn REGEXP)" t nil) (make-obsolete 'tags-apropos 'xref-find-apropos '"25.1") - (autoload 'select-tags-table "etags" "\ Select a tags table file from a menu of those you have already used. The list of tags tables to select from is stored in `tags-table-set-list'; see the doc of that variable if you want to add names to the list." t nil) - (autoload 'complete-tag "etags" "\ Perform tags completion on the text around point. Completes to the set of names listed in the current tags table. The string to complete is chosen in the same way as the default for \\[find-tag] (which see)." t nil) - (autoload 'etags--xref-backend "etags" nil nil nil) - (register-definition-prefixes "etags" '("default-tags-table-function" "etags-" "file-of-tag" "find-tag-" "goto-tag-location-function" "initialize-new-tags-table" "last-tag" "list-tags-function" "select-tags-table-" "snarf-tag-function" "tag" "verify-tags-table-function")) -;;;*** -;;;### (autoloads nil "etc-authors-mode" "textmodes/etc-authors-mode.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from textmodes/etc-authors-mode.el (autoload 'etc-authors-mode "etc-authors-mode" "\ Major mode for viewing \"etc/AUTHORS\" from the Emacs distribution. Provides some basic font locking and not much else. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "etc-authors-mode" '("etc-authors-")) -;;;*** -;;;### (autoloads nil "ethio-util" "language/ethio-util.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from language/ethio-util.el (autoload 'setup-ethiopic-environment-internal "ethio-util" nil nil nil) - (autoload 'ethio-sera-to-fidel-buffer "ethio-util" "\ Convert the current buffer from SERA to FIDEL. @@ -11781,8 +10607,7 @@ even if the buffer is read-only. See also the descriptions of the variables `ethio-use-colon-for-colon' and `ethio-use-three-dot-question'. -\(fn &optional SECONDARY FORCE)" t nil) - +(fn &optional SECONDARY FORCE)" t nil) (autoload 'ethio-sera-to-fidel-region "ethio-util" "\ Convert the characters in region from SERA to FIDEL. @@ -11799,15 +10624,13 @@ conversion even if the buffer is read-only. See also the descriptions of the variables `ethio-use-colon-for-colon' and `ethio-use-three-dot-question'. -\(fn BEGIN END &optional SECONDARY FORCE)" t nil) - +(fn BEGIN END &optional SECONDARY FORCE)" t nil) (autoload 'ethio-sera-to-fidel-marker "ethio-util" "\ Convert the regions surrounded by \"\" and \"\" from SERA to FIDEL. Assume that each region begins with `ethio-primary-language'. The markers \"\" and \"\" themselves are not deleted. -\(fn &optional FORCE)" t nil) - +(fn &optional FORCE)" t nil) (autoload 'ethio-fidel-to-sera-buffer "ethio-util" "\ Replace all the FIDEL characters in the current buffer to the SERA format. The variable `ethio-primary-language' specifies the primary @@ -11824,8 +10647,7 @@ See also the descriptions of the variables `ethio-use-colon-for-colon', `ethio-use-three-dot-question', `ethio-quote-vowel-always' and `ethio-numeric-reduction'. -\(fn &optional SECONDARY FORCE)" t nil) - +(fn &optional SECONDARY FORCE)" t nil) (autoload 'ethio-fidel-to-sera-region "ethio-util" "\ Replace all the FIDEL characters in the region to the SERA format. @@ -11843,17 +10665,14 @@ See also the descriptions of the variables `ethio-use-colon-for-colon', `ethio-use-three-dot-question', `ethio-quote-vowel-always' and `ethio-numeric-reduction'. -\(fn BEGIN END &optional SECONDARY FORCE)" t nil) - +(fn BEGIN END &optional SECONDARY FORCE)" t nil) (autoload 'ethio-fidel-to-sera-marker "ethio-util" "\ Convert the regions surrounded by \"\" and \"\" from FIDEL to SERA. The markers \"\" and \"\" themselves are not deleted. -\(fn &optional FORCE)" t nil) - +(fn &optional FORCE)" t nil) (autoload 'ethio-modify-vowel "ethio-util" "\ Modify the vowel of the FIDEL that is under the cursor." t nil) - (autoload 'ethio-replace-space "ethio-util" "\ Replace ASCII spaces with Ethiopic word separators in the region. @@ -11867,19 +10686,15 @@ If CH = 3, with the Ethiopic colon-like word separator. The 2nd and 3rd arguments BEGIN and END specify the region. -\(fn CH BEGIN END)" t nil) - +(fn CH BEGIN END)" t nil) (autoload 'ethio-input-special-character "ethio-util" "\ This function is deprecated. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (autoload 'ethio-fidel-to-tex-buffer "ethio-util" "\ Convert each fidel characters in the current buffer into a fidel-tex command." t nil) - (autoload 'ethio-tex-to-fidel-buffer "ethio-util" "\ Convert fidel-tex commands in the current buffer into fidel chars." t nil) - (autoload 'ethio-fidel-to-java-buffer "ethio-util" "\ Convert Ethiopic characters into the Java escape sequences. @@ -11888,32 +10703,29 @@ character's codepoint (in hex) in Unicode. If `ethio-java-save-lowercase' is non-nil, use [0-9a-f]. Otherwise, [0-9A-F]." nil nil) - (autoload 'ethio-java-to-fidel-buffer "ethio-util" "\ Convert the Java escape sequences into corresponding Ethiopic characters." nil nil) - (autoload 'ethio-find-file "ethio-util" "\ Transliterate file content into Ethiopic depending on filename suffix." nil nil) - (autoload 'ethio-write-file "ethio-util" "\ Transliterate Ethiopic characters in ASCII depending on the file extension." nil nil) - (autoload 'ethio-insert-ethio-space "ethio-util" "\ Insert the Ethiopic word delimiter (the colon-like character). With ARG, insert that many delimiters. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (autoload 'ethio-composition-function "ethio-util" "\ -\(fn POS TO FONT-OBJECT STRING DIRECTION)" nil nil) - +(fn POS TO FONT-OBJECT STRING DIRECTION)" nil nil) (register-definition-prefixes "ethio-util" '("ethio-" "exit-ethiopic-environment")) -;;;*** -;;;### (autoloads nil "eudc" "net/eudc.el" (0 0 0 0)) +;;; Generated autoloads from leim/quail/ethiopic.el + +(register-definition-prefixes "quail/ethiopic" '("ethio-select-a-translation")) + + ;;; Generated autoloads from net/eudc.el (autoload 'eudc-set-server "eudc" "\ @@ -11921,20 +10733,17 @@ Set the directory server to SERVER using PROTOCOL. Unless NO-SAVE is non-nil, the server is saved as the default server for future sessions. -\(fn SERVER PROTOCOL &optional NO-SAVE)" t nil) - +(fn SERVER PROTOCOL &optional NO-SAVE)" t nil) (autoload 'eudc-get-email "eudc" "\ Get the email field of NAME from the directory server. If ERROR is non-nil, report an error if there is none. -\(fn NAME &optional ERROR)" t nil) - +(fn NAME &optional ERROR)" t nil) (autoload 'eudc-get-phone "eudc" "\ Get the phone field of NAME from the directory server. If ERROR is non-nil, report an error if there is none. -\(fn NAME &optional ERROR)" t nil) - +(fn NAME &optional ERROR)" t nil) (autoload 'eudc-expand-try-all "eudc" "\ Wrap `eudc-expand-inline' with a prefix argument. If TRY-ALL-SERVERS -- the prefix argument when called @@ -11942,8 +10751,7 @@ interactively -- is non-nil, collect results from all servers. If TRY-ALL-SERVERS is nil, do not try subsequent servers after one server returns any match. -\(fn &optional TRY-ALL-SERVERS)" t nil) - +(fn &optional TRY-ALL-SERVERS)" t nil) (autoload 'eudc-expand-inline "eudc" "\ Query the directory server, and expand the query string before point. The query string consists of the buffer substring from the point back to @@ -11959,13 +10767,11 @@ Multiple servers can be tried with the same query until one finds a match, see `eudc-inline-expansion-servers'. If TRY-ALL-SERVERS is non-nil, collect results from all servers. -\(fn &optional SAVE-QUERY-AS-KILL TRY-ALL-SERVERS)" t nil) - +(fn &optional SAVE-QUERY-AS-KILL TRY-ALL-SERVERS)" t nil) (autoload 'eudc-format-inline-expansion-result "eudc" "\ Format a query result according to `eudc-inline-expansion-format'. -\(fn RES QUERY-ATTRS)" nil nil) - +(fn RES QUERY-ATTRS)" nil nil) (autoload 'eudc-query-with-words "eudc" "\ Query the directory server, and return the matching responses. The variable `eudc-inline-query-format' controls how to associate the @@ -11977,65 +10783,50 @@ Multiple servers can be tried with the same query until one finds a match, see `eudc-inline-expansion-servers'. When TRY-ALL-SERVERS is non-nil, keep collecting results from subsequent servers after the first match. -\(fn QUERY-WORDS &optional TRY-ALL-SERVERS)" nil nil) - +(fn QUERY-WORDS &optional TRY-ALL-SERVERS)" nil nil) (autoload 'eudc-query-form "eudc" "\ Display a form to query the directory server. If given a non-nil argument GET-FIELDS-FROM-SERVER, the function first queries the server for the existing fields and displays a corresponding form. -\(fn &optional GET-FIELDS-FROM-SERVER)" t nil) - +(fn &optional GET-FIELDS-FROM-SERVER)" t nil) (autoload 'eudc-load-eudc "eudc" "\ Load the Emacs Unified Directory Client. This does nothing except loading eudc by autoload side-effect." t nil) - (defvar eudc-tools-menu (let ((map (make-sparse-keymap "Directory Servers"))) (define-key map [phone] `(menu-item ,(purecopy "Get Phone") eudc-get-phone :help ,(purecopy "Get the phone field of name from the directory server"))) (define-key map [email] `(menu-item ,(purecopy "Get Email") eudc-get-email :help ,(purecopy "Get the email field of NAME from the directory server"))) (define-key map [separator-eudc-email] menu-bar-separator) (define-key map [expand-inline] `(menu-item ,(purecopy "Expand Inline Query") eudc-expand-inline :help ,(purecopy "Query the directory server, and expand the query string before point"))) (define-key map [query] `(menu-item ,(purecopy "Query with Form") eudc-query-form :help ,(purecopy "Display a form to query the directory server"))) (define-key map [separator-eudc-query] menu-bar-separator) (define-key map [new] `(menu-item ,(purecopy "New Server") eudc-set-server :help ,(purecopy "Set the directory server to SERVER using PROTOCOL"))) (define-key map [load] `(menu-item ,(purecopy "Load Hotlist of Servers") eudc-load-eudc :help ,(purecopy "Load the Emacs Unified Directory Client"))) map)) - (fset 'eudc-tools-menu (symbol-value 'eudc-tools-menu)) - (register-definition-prefixes "eudc" '("eudc-")) -;;;*** -;;;### (autoloads nil "eudc-bob" "net/eudc-bob.el" (0 0 0 0)) ;;; Generated autoloads from net/eudc-bob.el (autoload 'eudc-display-generic-binary "eudc-bob" "\ Display a button for unidentified binary DATA. -\(fn DATA)" nil nil) - +(fn DATA)" nil nil) (autoload 'eudc-display-url "eudc-bob" "\ Display URL and make it clickable. -\(fn URL)" nil nil) - +(fn URL)" nil nil) (autoload 'eudc-display-mail "eudc-bob" "\ Display e-mail address and make it clickable. -\(fn MAIL)" nil nil) - +(fn MAIL)" nil nil) (autoload 'eudc-display-sound "eudc-bob" "\ Display a button to play the sound DATA. -\(fn DATA)" nil nil) - +(fn DATA)" nil nil) (autoload 'eudc-display-jpeg-inline "eudc-bob" "\ Display the JPEG DATA inline at point if possible. -\(fn DATA)" nil nil) - +(fn DATA)" nil nil) (autoload 'eudc-display-jpeg-as-button "eudc-bob" "\ Display a button for the JPEG DATA. -\(fn DATA)" nil nil) - +(fn DATA)" nil nil) (register-definition-prefixes "eudc-bob" '("eudc-bob-")) -;;;*** -;;;### (autoloads nil "eudc-capf" "net/eudc-capf.el" (0 0 0 0)) ;;; Generated autoloads from net/eudc-capf.el (autoload 'eudc-capf-complete "eudc-capf" "\ @@ -12051,7 +10842,6 @@ words before point. The return value is either nil when no match is found, or a completion table as required for functions listed in `completion-at-point-functions'." nil nil) - (autoload 'eudc-capf-message-expand-name "eudc-capf" "\ Email address completion function for `message-completion-alist'. @@ -12061,73 +10851,51 @@ with an appropriate regular expression such as for example `message-email-recipient-header-regexp', then EUDC will be queried for email addresses, and the results delivered to `completion-at-point'." nil nil) - (register-definition-prefixes "eudc-capf" '("eudc-capf-modes")) -;;;*** -;;;### (autoloads nil "eudc-export" "net/eudc-export.el" (0 0 0 0)) ;;; Generated autoloads from net/eudc-export.el (autoload 'eudc-insert-record-at-point-into-bbdb "eudc-export" "\ Insert record at point into the BBDB database. This function can only be called from a directory query result buffer." t nil) - (autoload 'eudc-try-bbdb-insert "eudc-export" "\ Call `eudc-insert-record-at-point-into-bbdb' if on a record." t nil) - (register-definition-prefixes "eudc-export" '("eudc-")) -;;;*** -;;;### (autoloads nil "eudc-hotlist" "net/eudc-hotlist.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from net/eudc-hotlist.el (autoload 'eudc-edit-hotlist "eudc-hotlist" "\ Edit the hotlist of directory servers in a specialized buffer." t nil) - (register-definition-prefixes "eudc-hotlist" '("eudc-hotlist-")) -;;;*** -;;;### (autoloads nil "eudc-vars" "net/eudc-vars.el" (0 0 0 0)) ;;; Generated autoloads from net/eudc-vars.el (register-definition-prefixes "eudc-vars" '("eudc-")) -;;;*** -;;;### (autoloads nil "eudcb-bbdb" "net/eudcb-bbdb.el" (0 0 0 0)) ;;; Generated autoloads from net/eudcb-bbdb.el (register-definition-prefixes "eudcb-bbdb" '("eudc-bbdb-")) -;;;*** -;;;### (autoloads nil "eudcb-ldap" "net/eudcb-ldap.el" (0 0 0 0)) ;;; Generated autoloads from net/eudcb-ldap.el (register-definition-prefixes "eudcb-ldap" '("eudc-")) -;;;*** -;;;### (autoloads nil "eudcb-mab" "net/eudcb-mab.el" (0 0 0 0)) ;;; Generated autoloads from net/eudcb-mab.el (register-definition-prefixes "eudcb-mab" '("eudc-")) -;;;*** -;;;### (autoloads nil "eudcb-macos-contacts" "net/eudcb-macos-contacts.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from net/eudcb-macos-contacts.el (register-definition-prefixes "eudcb-macos-contacts" '("eudc-macos-contacts-")) -;;;*** -;;;### (autoloads nil "ewoc" "emacs-lisp/ewoc.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/ewoc.el (autoload 'ewoc-create "ewoc" "\ @@ -12149,13 +10917,10 @@ Normally, a newline is automatically inserted after the header, the footer and every node's printed representation. Optional fourth arg NOSEP non-nil inhibits this. -\(fn PRETTY-PRINTER &optional HEADER FOOTER NOSEP)" nil nil) - +(fn PRETTY-PRINTER &optional HEADER FOOTER NOSEP)" nil nil) (register-definition-prefixes "ewoc" '("ewoc-")) -;;;*** -;;;### (autoloads nil "eww" "net/eww.el" (0 0 0 0)) ;;; Generated autoloads from net/eww.el (defvar eww-suggest-uris '(eww-links-at-point thing-at-point-url-at-point eww-current-url) "\ @@ -12163,9 +10928,7 @@ List of functions called to form the list of default URIs for `eww'. Each of the elements is a function returning either a string or a list of strings. The results will be joined into a single list with duplicate entries (if any) removed.") - (custom-autoload 'eww-suggest-uris "eww" t) - (autoload 'eww-browse "eww" "\ Function to be run to parse command line URLs. This is meant to be used for MIME handlers or command line use. @@ -12179,7 +10942,6 @@ This can also be used on the command line directly: emacs -f eww-browse https://gnu.org will start Emacs and browse the GNU web site." t nil) - (autoload 'eww "eww" "\ Fetch URL and render the page. If the input doesn't look like an URL or a domain name, the @@ -12192,28 +10954,24 @@ If BUFFER, the data to be rendered is in that buffer. In that case, this function doesn't actually fetch URL. BUFFER will be killed after rendering. -\(fn URL &optional NEW-BUFFER BUFFER)" t nil) +(fn URL &optional NEW-BUFFER BUFFER)" t nil) (defalias 'browse-web 'eww) - (autoload 'eww-open-file "eww" "\ Render FILE using EWW. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'eww-search-words "eww" "\ Search the web for the text in the region. If region is active (and not whitespace), search the web for the text between region beginning and end. Else, prompt the user for a search string. See the variable `eww-search-prefix' for the search engine used." t nil) - (autoload 'eww-mode "eww" "\ Mode for browsing the web. \\{eww-mode-map} -\(fn)" t nil) - +(fn)" t nil) (autoload 'eww-browse-url "eww" "\ Ask the EWW browser to load URL. @@ -12229,38 +10987,30 @@ in the tab-bar on an existing frame. See more options in Non-interactively, this uses the optional second argument NEW-WINDOW instead of `browse-url-new-window-flag'. -\(fn URL &optional NEW-WINDOW)" nil nil) - +(fn URL &optional NEW-WINDOW)" nil nil) (autoload 'eww-list-bookmarks "eww" "\ Display the bookmarks." t nil) - (autoload 'eww-bookmark-jump "eww" "\ Default bookmark handler for EWW buffers. -\(fn BOOKMARK)" nil nil) - +(fn BOOKMARK)" nil nil) (register-definition-prefixes "eww" '("erc--download-directory" "eww-")) -;;;*** -;;;### (autoloads nil "executable" "progmodes/executable.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from progmodes/executable.el (autoload 'executable-command-find-posix-p "executable" "\ Check if PROGRAM handles arguments Posix-style. If PROGRAM is non-nil, use that instead of \"find\". -\(fn &optional PROGRAM)" nil nil) - +(fn &optional PROGRAM)" nil nil) (autoload 'executable-interpret "executable" "\ Run script with user-specified args, and collect output in a buffer. While script runs asynchronously, you can use the \\[next-error] command to find the next error. The buffer is also in `comint-mode' and `compilation-shell-minor-mode', so that you can answer any prompts. -\(fn COMMAND)" t nil) - +(fn COMMAND)" t nil) (autoload 'executable-set-magic "executable" "\ Set this buffer's interpreter to INTERPRETER with optional ARGUMENT. The variables `executable-magicless-file-regexp', `executable-prefix-env', @@ -12268,25 +11018,19 @@ The variables `executable-magicless-file-regexp', `executable-prefix-env', when and how magic numbers are inserted or replaced and scripts made executable. -\(fn INTERPRETER &optional ARGUMENT NO-QUERY-FLAG INSERT-FLAG)" t nil) - +(fn INTERPRETER &optional ARGUMENT NO-QUERY-FLAG INSERT-FLAG)" t nil) (autoload 'executable-make-buffer-file-executable-if-script-p "executable" "\ Make file executable according to umask if not already executable. If file already has any execute bits set at all, do not change existing file modes." nil nil) - (register-definition-prefixes "executable" '("executable-")) -;;;*** -;;;### (autoloads nil "exif" "image/exif.el" (0 0 0 0)) ;;; Generated autoloads from image/exif.el (register-definition-prefixes "exif" '("exif-")) -;;;*** -;;;### (autoloads nil "expand" "expand.el" (0 0 0 0)) ;;; Generated autoloads from expand.el (autoload 'expand-add-abbrevs "expand" "\ @@ -12311,34 +11055,36 @@ cyclically with the functions `expand-jump-to-previous-slot' and If ARG is omitted, point is placed at the end of the expanded text. -\(fn TABLE ABBREVS)" nil nil) - +(fn TABLE ABBREVS)" nil nil) (autoload 'expand-abbrev-hook "expand" "\ Abbrev hook used to do the expansion job of expand abbrevs. See `expand-add-abbrevs'. Value is non-nil if expansion was done." nil nil) - (autoload 'expand-jump-to-previous-slot "expand" "\ Move the cursor to the previous slot in the last abbrev expansion. This is used only in conjunction with `expand-add-abbrevs'." t nil) - (autoload 'expand-jump-to-next-slot "expand" "\ Move the cursor to the next slot in the last abbrev expansion. This is used only in conjunction with `expand-add-abbrevs'." t nil) (define-key abbrev-map "p" 'expand-jump-to-previous-slot) (define-key abbrev-map "n" 'expand-jump-to-next-slot) - (register-definition-prefixes "expand" '("expand-")) -;;;*** -;;;### (autoloads nil "ezimage" "ezimage.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/expandproto.el + +(register-definition-prefixes "srecode/expandproto" '("srecode-")) + + +;;; Generated autoloads from cedet/srecode/extract.el + +(register-definition-prefixes "srecode/extract" '("srecode-extract")) + + ;;; Generated autoloads from ezimage.el (register-definition-prefixes "ezimage" '("defezimage" "ezimage-")) -;;;*** -;;;### (autoloads nil "f90" "progmodes/f90.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/f90.el (autoload 'f90-mode "f90" "\ @@ -12401,13 +11147,10 @@ Variables controlling indentation style and extra features: Turning on F90 mode calls the value of the variable `f90-mode-hook' with no args, if that value is non-nil. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "f90" '("f90-")) -;;;*** -;;;### (autoloads nil "face-remap" "face-remap.el" (0 0 0 0)) ;;; Generated autoloads from face-remap.el (autoload 'face-remap-add-relative "face-remap" "\ @@ -12432,15 +11175,13 @@ attributes. The base (lowest priority) remapping may be set to something other than the normal definition of FACE via `face-remap-set-base'. -\(fn FACE &rest SPECS)" nil nil) - +(fn FACE &rest SPECS)" nil nil) (autoload 'face-remap-reset-base "face-remap" "\ Set the base remapping of FACE to the normal definition of FACE. This causes the remappings specified by `face-remap-add-relative' to apply on top of the normal definition of FACE. -\(fn FACE)" nil nil) - +(fn FACE)" nil nil) (autoload 'face-remap-set-base "face-remap" "\ Set the base remapping of FACE in the current buffer to SPECS. This causes the remappings specified by `face-remap-add-relative' @@ -12455,8 +11196,7 @@ to use the normal definition of FACE as the base remapping; note that this is different from SPECS containing a single value nil, which means not to inherit from the global definition of FACE at all. -\(fn FACE &rest SPECS)" nil nil) - +(fn FACE &rest SPECS)" nil nil) (autoload 'text-scale-set "face-remap" "\ Set the scale factor of the default face in the current buffer to LEVEL. If LEVEL is non-zero, `text-scale-mode' is enabled, otherwise it is disabled. @@ -12466,8 +11206,7 @@ Each step scales the height of the default face by the variable `text-scale-mode-step' (a negative number decreases the height by the same amount). -\(fn LEVEL)" t nil) - +(fn LEVEL)" t nil) (autoload 'text-scale-increase "face-remap" "\ Increase the height of the default face in the current buffer by INC steps. If the new height is other than the default, `text-scale-mode' is enabled. @@ -12477,18 +11216,16 @@ Each step scales the height of the default face by the variable height by the same amount). As a special case, an argument of 0 will remove any scaling currently active. -\(fn INC)" t nil) - +(fn INC)" t nil) (autoload 'text-scale-decrease "face-remap" "\ Decrease the height of the default face in the current buffer by DEC steps. See `text-scale-increase' for more details. -\(fn DEC)" t nil) +(fn DEC)" t nil) (define-key ctl-x-map [(control ?+)] 'text-scale-adjust) (define-key ctl-x-map [(control ?-)] 'text-scale-adjust) (define-key ctl-x-map [(control ?=)] 'text-scale-adjust) (define-key ctl-x-map [(control ?0)] 'text-scale-adjust) - (autoload 'text-scale-adjust "face-remap" "\ Adjust the height of the default face by INC. @@ -12503,7 +11240,7 @@ keybinding used to invoke the command, with all modifiers removed: After adjusting, continue to read input events and further adjust the face height as long as the input event read -\(with all modifiers removed) is one of the above characters. +(with all modifiers removed) is one of the above characters. Each step scales the height of the default face by the variable `text-scale-mode-step' (a negative number of steps decreases the @@ -12516,14 +11253,12 @@ even when it is bound in a non-top-level keymap. For binding in a top-level keymap, `text-scale-increase' or `text-scale-decrease' may be more appropriate. -\(fn INC)" t nil) +(fn INC)" t nil) (define-key global-map [pinch] 'text-scale-pinch) - (autoload 'text-scale-pinch "face-remap" "\ Adjust the height of the default face by the scale in the pinch event EVENT. -\(fn EVENT)" t nil) - +(fn EVENT)" t nil) (autoload 'buffer-face-mode "face-remap" "\ Minor mode for a buffer-specific default face. @@ -12544,8 +11279,7 @@ evaluate `buffer-face-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'buffer-face-set "face-remap" "\ Enable `buffer-face-mode', using face specs SPECS. Each argument in SPECS should be a face, i.e. either a face name @@ -12557,8 +11291,7 @@ one face is listed, that specifies an aggregate face, like in a This function makes the variable `buffer-face-mode-face' buffer local, and sets it to FACE. -\(fn &rest SPECS)" t nil) - +(fn &rest SPECS)" t nil) (autoload 'buffer-face-toggle "face-remap" "\ Toggle `buffer-face-mode', using face specs SPECS. Each argument in SPECS should be a face, i.e. either a face name @@ -12574,25 +11307,20 @@ face, then is left enabled, but the face changed to reflect SPECS. This function will make the variable `buffer-face-mode-face' buffer local, and set it to SPECS. -\(fn &rest SPECS)" t nil) - +(fn &rest SPECS)" t nil) (autoload 'variable-pitch-mode "face-remap" "\ Variable-pitch default-face mode. An interface to `buffer-face-mode' which uses the `variable-pitch' face. Besides the choice of face, it is the same as `buffer-face-mode'. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "face-remap" '("buffer-face-mode-" "face-" "internal-lisp-face-attributes" "text-scale-")) -;;;*** -;;;### (autoloads nil "facemenu" "facemenu.el" (0 0 0 0)) ;;; Generated autoloads from facemenu.el - (autoload 'facemenu-menu "facemenu" nil nil 'keymap) + (autoload 'facemenu-menu "facemenu" nil nil 'keymap) (define-key global-map [C-down-mouse-2] 'facemenu-menu) - (autoload 'list-colors-display "facemenu" "\ Display names of defined colors, and show what they look like. If the optional argument LIST is non-nil, it should be a list of @@ -12608,19 +11336,15 @@ If the optional argument CALLBACK is non-nil, it should be a function to call each time the user types RET or clicks on a color. The function should accept a single argument, the color name. -\(fn &optional LIST BUFFER-NAME CALLBACK)" t nil) - +(fn &optional LIST BUFFER-NAME CALLBACK)" t nil) (register-definition-prefixes "facemenu" '("facemenu-" "list-colors-")) -;;;*** -;;;### (autoloads nil "faceup" "emacs-lisp/faceup.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/faceup.el -(push (purecopy '(faceup 0 0 6)) package--builtin-versions) +(push (purecopy '(faceup 0 0 6)) package--builtin-versions) (autoload 'faceup-view-buffer "faceup" "\ Display the faceup representation of the current buffer." t nil) - (autoload 'faceup-write-file "faceup" "\ Save the faceup representation of the current buffer to the file FILE-NAME. @@ -12631,57 +11355,52 @@ If optional second arg CONFIRM is non-nil, this function asks for confirmation before overwriting an existing file. Interactively, confirmation is required unless you supply a prefix argument. -\(fn &optional FILE-NAME CONFIRM)" t nil) - +(fn &optional FILE-NAME CONFIRM)" t nil) (autoload 'faceup-render-view-buffer "faceup" "\ Convert BUFFER containing Faceup markup to a new buffer and display it. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (autoload 'faceup-clean-buffer "faceup" "\ Remove faceup markup from buffer." t nil) - (autoload 'faceup-defexplainer "faceup" "\ Define an Ert explainer function for FUNCTION. FUNCTION must return an explanation when the test fails and `faceup-test-explain' is set. -\(fn FUNCTION)" nil t) - +(fn FUNCTION)" nil t) (register-definition-prefixes "faceup" '("faceup-")) -;;;*** -;;;### (autoloads nil "feedmail" "mail/feedmail.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/analyze/fcn.el + +(register-definition-prefixes "semantic/analyze/fcn" '("semantic-analyze-")) + + ;;; Generated autoloads from mail/feedmail.el -(push (purecopy '(feedmail 11)) package--builtin-versions) +(push (purecopy '(feedmail 11)) package--builtin-versions) (autoload 'feedmail-send-it "feedmail" "\ Send the current mail buffer using the Feedmail package. This is a suitable value for `send-mail-function'. It can be used with various lower-level mechanisms to provide features such as queueing." nil nil) - (autoload 'feedmail-run-the-queue-no-prompts "feedmail" "\ Like `feedmail-run-the-queue', but suppress confirmation prompts. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'feedmail-run-the-queue-global-prompt "feedmail" "\ Like `feedmail-run-the-queue', but with a global confirmation prompt. This is generally most useful if run non-interactively, since you can bail out with an appropriate answer to the global confirmation prompt. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'feedmail-run-the-queue "feedmail" "\ Visit each message in the feedmail queue directory and send it out. Return value is a list of three things: number of messages sent, number of messages skipped, and number of non-message things in the queue (commonly backup file names and the like). -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'feedmail-queue-reminder "feedmail" "\ Perform some kind of reminder activity about queued and draft messages. Called with an optional symbol argument which says what kind of event @@ -12701,20 +11420,15 @@ expected to perform the reminder activity. You can supply your own reminder functions by redefining `feedmail-queue-reminder-alist'. If you don't want any reminders, you can set `feedmail-queue-reminder-alist' to nil. -\(fn &optional WHAT-EVENT)" t nil) - +(fn &optional WHAT-EVENT)" t nil) (register-definition-prefixes "feedmail" '("feedmail-")) -;;;*** -;;;### (autoloads nil "ffap" "ffap.el" (0 0 0 0)) ;;; Generated autoloads from ffap.el (defvar ffap-file-finder 'find-file "\ The command called by `find-file-at-point' to find a file.") - (custom-autoload 'ffap-file-finder "ffap" t) - (autoload 'ffap-next "ffap" "\ Search buffer for next file or URL, and run ffap. Optional argument BACK says to search backwards. @@ -12723,8 +11437,7 @@ Interactively: use a single prefix \\[universal-argument] to search backwards, double prefix to wrap forward, triple to wrap backwards. Actual search is done by the function `ffap-next-guess'. -\(fn &optional BACK WRAP)" t nil) - +(fn &optional BACK WRAP)" t nil) (autoload 'find-file-at-point "ffap" "\ Find FILENAME, guessing a default from text around point. If `ffap-url-regexp' is not nil, the FILENAME may also be an URL. @@ -12735,10 +11448,8 @@ See also the variables `ffap-dired-wildcards', `ffap-newfile-prompt', `ffap-file-name-with-spaces', and the functions `ffap-file-at-point' and `ffap-url-at-point'. -\(fn &optional FILENAME)" t nil) - +(fn &optional FILENAME)" t nil) (defalias 'ffap 'find-file-at-point) - (autoload 'ffap-menu "ffap" "\ Put up a menu of files and URLs mentioned in this buffer. Then set mark, jump to choice, and try to fetch it. The menu is @@ -12746,8 +11457,7 @@ cached in `ffap-menu-alist', and rebuilt by `ffap-menu-rescan'. The optional RESCAN argument (a prefix, interactively) forces a rebuild. Searches with `ffap-menu-regexp'. -\(fn &optional RESCAN)" t nil) - +(fn &optional RESCAN)" t nil) (autoload 'ffap-at-mouse "ffap" "\ Find file or URL guessed from text around mouse click. Interactively, calls `ffap-at-mouse-fallback' if no guess is found. @@ -12756,26 +11466,25 @@ Return value: * if the fallback is called, return whatever it returns * otherwise, nil -\(fn E)" t nil) - +(fn E)" t nil) (autoload 'dired-at-point "ffap" "\ Start Dired, defaulting to file at point. See `ffap'. If `dired-at-point-require-prefix' is set, the prefix meaning is reversed. -\(fn &optional FILENAME)" t nil) - +(fn &optional FILENAME)" t nil) (autoload 'ffap-guess-file-name-at-point "ffap" "\ Try to get a file name at point. This hook is intended to be put in `file-name-at-point-functions'." nil nil) - (autoload 'ffap-bindings "ffap" "\ Evaluate the forms in variable `ffap-bindings'." t nil) - (register-definition-prefixes "ffap" '("dired-at-point-" "ffap-" "find-file-literally-at-point")) -;;;*** -;;;### (autoloads nil "filecache" "filecache.el" (0 0 0 0)) +;;; Generated autoloads from cedet/srecode/fields.el + +(register-definition-prefixes "srecode/fields" '("srecode-")) + + ;;; Generated autoloads from filecache.el (autoload 'file-cache-add-directory "filecache" "\ @@ -12783,8 +11492,7 @@ Add all files in DIRECTORY to the file cache. If called from Lisp with a non-nil REGEXP argument is non-nil, only add files whose names match REGEXP. -\(fn DIRECTORY &optional REGEXP)" t nil) - +(fn DIRECTORY &optional REGEXP)" t nil) (autoload 'file-cache-add-directory-list "filecache" "\ Add DIRECTORIES (a list of directory names) to the file cache. If called interactively, read the directory names one by one. @@ -12792,25 +11500,21 @@ If the optional REGEXP argument is non-nil, only files which match it will be added to the cache. Note that the REGEXP is applied to the files in each directory, not to the directory list itself. -\(fn DIRECTORIES &optional REGEXP)" t nil) - +(fn DIRECTORIES &optional REGEXP)" t nil) (autoload 'file-cache-add-file "filecache" "\ Add FILE to the file cache. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'file-cache-add-directory-using-find "filecache" "\ Use the `find' command to add files to the file cache. Find is run in DIRECTORY. -\(fn DIRECTORY)" t nil) - +(fn DIRECTORY)" t nil) (autoload 'file-cache-add-directory-using-locate "filecache" "\ Use the `locate' command to add files to the file cache. STRING is passed as an argument to the locate command. -\(fn STRING)" t nil) - +(fn STRING)" t nil) (autoload 'file-cache-add-directory-recursively "filecache" "\ Add DIR and any subdirectories to the file-cache. This function does not use any external programs. @@ -12818,23 +11522,19 @@ If the optional REGEXP argument is non-nil, only files which match it will be added to the cache. Note that the REGEXP is applied to the files in each directory, not to the directory list itself. -\(fn DIR &optional REGEXP)" t nil) - +(fn DIR &optional REGEXP)" t nil) (autoload 'file-cache-minibuffer-complete "filecache" "\ Complete a filename in the minibuffer using a preloaded cache. Filecache does two kinds of substitution: it completes on names in the cache, and, once it has found a unique name, it cycles through the directories that the name is available in. With a prefix argument, the name is considered already unique; only the second substitution -\(directories) is done. - -\(fn ARG)" t nil) +(directories) is done. +(fn ARG)" t nil) (register-definition-prefixes "filecache" '("file-cache-")) -;;;*** -;;;### (autoloads nil "fileloop" "fileloop.el" (0 0 0 0)) ;;; Generated autoloads from fileloop.el (autoload 'fileloop-initialize "fileloop" "\ @@ -12848,13 +11548,11 @@ to perform the operation on the current file buffer and when done should return non-nil to mean that we should immediately continue operating on the next file and nil otherwise. -\(fn FILES SCAN-FUNCTION OPERATE-FUNCTION)" nil nil) - +(fn FILES SCAN-FUNCTION OPERATE-FUNCTION)" nil nil) (autoload 'fileloop-initialize-search "fileloop" "\ -\(fn REGEXP FILES CASE-FOLD)" nil nil) - +(fn REGEXP FILES CASE-FOLD)" nil nil) (autoload 'fileloop-initialize-replace "fileloop" "\ Initialize a new round of query&replace on several files. FROM is a regexp and TO is the replacement to use. @@ -12868,13 +11566,10 @@ CASE-FOLD can be t, nil, or `default': `case-fold-search' instead. DELIMITED if non-nil means replace only word-delimited matches. -\(fn FROM TO FILES CASE-FOLD &optional DELIMITED)" nil nil) - +(fn FROM TO FILES CASE-FOLD &optional DELIMITED)" nil nil) (register-definition-prefixes "fileloop" '("fileloop-")) -;;;*** -;;;### (autoloads nil "filenotify" "filenotify.el" (0 0 0 0)) ;;; Generated autoloads from filenotify.el (autoload 'file-notify-handle-event "filenotify" "\ @@ -12882,15 +11577,16 @@ Handle a file system monitoring event, coming from backends. If OBJECT is a filewatch event, call its callback. Otherwise, signal a `file-notify-error'. -\(fn OBJECT)" t nil) - +(fn OBJECT)" t nil) (function-put 'file-notify-handle-event 'completion-predicate #'ignore) - (register-definition-prefixes "filenotify" '("file-notify-")) -;;;*** -;;;### (autoloads nil "files-x" "files-x.el" (0 0 0 0)) +;;; Generated autoloads from cedet/ede/files.el + +(register-definition-prefixes "ede/files" '("ede-")) + + ;;; Generated autoloads from files-x.el (autoload 'add-file-local-variable "files-x" "\ @@ -12904,13 +11600,11 @@ If there is no Local Variables list in the current file buffer then this function adds the first line containing the string `Local Variables:' and the last line containing the string `End:'. -\(fn VARIABLE VALUE &optional INTERACTIVE)" t nil) - +(fn VARIABLE VALUE &optional INTERACTIVE)" t nil) (autoload 'delete-file-local-variable "files-x" "\ Delete all settings of file-local VARIABLE from the Local Variables list. -\(fn VARIABLE &optional INTERACTIVE)" t nil) - +(fn VARIABLE &optional INTERACTIVE)" t nil) (autoload 'add-file-local-variable-prop-line "files-x" "\ Add file-local VARIABLE with its VALUE to the -*- line. @@ -12921,35 +11615,27 @@ the -*- line. If there is no -*- line at the beginning of the current file buffer then this function adds it. -\(fn VARIABLE VALUE &optional INTERACTIVE)" t nil) - +(fn VARIABLE VALUE &optional INTERACTIVE)" t nil) (autoload 'delete-file-local-variable-prop-line "files-x" "\ Delete all settings of file-local VARIABLE from the -*- line. -\(fn VARIABLE &optional INTERACTIVE)" t nil) - +(fn VARIABLE &optional INTERACTIVE)" t nil) (autoload 'add-dir-local-variable "files-x" "\ Add directory-local VARIABLE with its VALUE and MODE to .dir-locals.el. -\(fn MODE VARIABLE VALUE)" t nil) - +(fn MODE VARIABLE VALUE)" t nil) (autoload 'delete-dir-local-variable "files-x" "\ Delete all MODE settings of file-local VARIABLE from .dir-locals.el. -\(fn MODE VARIABLE)" t nil) - +(fn MODE VARIABLE)" t nil) (autoload 'copy-file-locals-to-dir-locals "files-x" "\ Copy file-local variables to .dir-locals.el." t nil) - (autoload 'copy-dir-locals-to-file-locals "files-x" "\ Copy directory-local variables to the Local Variables list." t nil) - (autoload 'copy-dir-locals-to-file-locals-prop-line "files-x" "\ Copy directory-local variables to the -*- line." t nil) - (defvar enable-connection-local-variables t "\ Non-nil means enable use of connection-local variables.") - (autoload 'connection-local-set-profiles "files-x" "\ Add PROFILES for CRITERIA. CRITERIA is a plist identifying a connection and the application @@ -12962,8 +11648,7 @@ PROFILES are applied to the corresponding process buffer. The variables for a connection profile are defined using `connection-local-set-profile-variables'. -\(fn CRITERIA &rest PROFILES)" nil nil) - +(fn CRITERIA &rest PROFILES)" nil nil) (autoload 'connection-local-set-profile-variables "files-x" "\ Map the symbol PROFILE to a list of variable settings. VARIABLES is a list that declares connection-local variables for @@ -12977,57 +11662,66 @@ variables are set in the server's process buffer according to the VARIABLES list of the connection profile. The list is processed in order. -\(fn PROFILE VARIABLES)" nil nil) - +(fn PROFILE VARIABLES)" nil nil) (autoload 'hack-connection-local-variables-apply "files-x" "\ Apply connection-local variables identified by CRITERIA. Other local variables, like file-local and dir-local variables, will not be changed. -\(fn CRITERIA)" nil nil) - +(fn CRITERIA)" nil nil) (autoload 'with-connection-local-variables "files-x" "\ Apply connection-local variables according to `default-directory'. Execute BODY, and unwind connection-local variables. -\(fn &rest BODY)" nil t) - +(fn &rest BODY)" nil t) (autoload 'with-connection-local-variables-1 "files-x" "\ Apply connection-local variables according to `default-directory'. Call BODY-FUN with no args, and then unwind connection-local variables. -\(fn BODY-FUN)" nil nil) - +(fn BODY-FUN)" nil nil) (autoload 'path-separator "files-x" "\ The connection-local value of `path-separator'." nil nil) - (autoload 'null-device "files-x" "\ The connection-local value of `null-device'." nil nil) - (register-definition-prefixes "files-x" '("connection-local-" "dir-locals-to-string" "hack-connection-local-variables" "modify-" "read-file-local-variable")) -;;;*** -;;;### (autoloads nil "filesets" "filesets.el" (0 0 0 0)) ;;; Generated autoloads from filesets.el (autoload 'filesets-init "filesets" "\ Filesets initialization. Set up hooks, load the cache file -- if existing -- and build the menu." nil nil) - (register-definition-prefixes "filesets" '("filesets-")) -;;;*** -;;;### (autoloads nil "find-cmd" "find-cmd.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/filter.el + +(register-definition-prefixes "semantic/symref/filter" '("semantic-symref-")) + + +;;; Generated autoloads from cedet/srecode/filters.el + +(register-definition-prefixes "srecode/filters" '("srecode-comment-prefix")) + + +;;; Generated autoloads from cedet/srecode/find.el + +(register-definition-prefixes "srecode/find" '("srecode-")) + + +;;; Generated autoloads from cedet/semantic/find.el + +(register-definition-prefixes "semantic/find" '("semantic-")) + + ;;; Generated autoloads from find-cmd.el -(push (purecopy '(find-cmd 0 6)) package--builtin-versions) +(push (purecopy '(find-cmd 0 6)) package--builtin-versions) (autoload 'find-cmd "find-cmd" "\ Initiate the building of a find command. For example: -\(find-cmd \\='(prune (name \".svn\" \".git\" \".CVS\")) +(find-cmd \\='(prune (name \".svn\" \".git\" \".CVS\")) \\='(and (or (name \"*.pl\" \"*.pm\" \"*.t\") (mtime \"+1\")) (fstype \"nfs\" \"ufs\")))) @@ -13035,13 +11729,10 @@ For example: `default-directory' is used as the initial search path. The result is a string that should be ready for the command line. -\(fn &rest SUBFINDS)" nil nil) - +(fn &rest SUBFINDS)" nil nil) (register-definition-prefixes "find-cmd" '("find-")) -;;;*** -;;;### (autoloads nil "find-dired" "find-dired.el" (0 0 0 0)) ;;; Generated autoloads from find-dired.el (autoload 'find-dired "find-dired" "\ @@ -13056,8 +11747,7 @@ use in place of \"-ls\" as the final argument. Collect output in the \"*Find*\" buffer. To kill the job before it finishes, type \\[kill-find]. -\(fn DIR ARGS)" t nil) - +(fn DIR ARGS)" t nil) (autoload 'find-name-dired "find-dired" "\ Search DIR recursively for files matching the globbing PATTERN, and run Dired on those files. @@ -13068,8 +11758,7 @@ The default command run (after changing into DIR) is See `find-name-arg' to customize the arguments. -\(fn DIR PATTERN)" t nil) - +(fn DIR PATTERN)" t nil) (autoload 'find-grep-dired "find-dired" "\ Find files in DIR that contain matches for REGEXP and start Dired on output. The command run (after changing into DIR) is @@ -13080,13 +11769,10 @@ The command run (after changing into DIR) is where the first string in the value of the variable `find-ls-option' specifies what to use in place of \"-ls\" as the final argument. -\(fn DIR REGEXP)" t nil) - +(fn DIR REGEXP)" t nil) (register-definition-prefixes "find-dired" '("find-" "kill-find" "lookfor-dired")) -;;;*** -;;;### (autoloads nil "find-file" "find-file.el" (0 0 0 0)) ;;; Generated autoloads from find-file.el (defvar ff-special-constructs `((,(purecopy "^#\\s *\\(include\\|import\\)\\s +[<\"]\\(.*\\)[>\"]") \, (lambda nil (match-string 2)))) "\ @@ -13096,19 +11782,15 @@ If REGEXP matches the current line (from the beginning of the line), `ff-treat-as-special' calls function EXTRACT with no args. If EXTRACT returns nil, keep trying. Otherwise, return the filename that EXTRACT returned.") - (custom-autoload 'ff-special-constructs "find-file" t) - (autoload 'ff-get-other-file "find-file" "\ Find the header or source file corresponding to this file. See also the documentation for `ff-find-other-file'. If optional IN-OTHER-WINDOW is non-nil, find the file in another window. -\(fn &optional IN-OTHER-WINDOW)" t nil) - +(fn &optional IN-OTHER-WINDOW)" t nil) (defalias 'ff-find-related-file #'ff-find-other-file) - (autoload 'ff-find-other-file "find-file" "\ Find the header or source file corresponding to this file. Being on a `#include' line pulls in that file. @@ -13166,23 +11848,18 @@ Variables of interest include: - `ff-file-created-hook' List of functions to be called if the other file has been created. -\(fn &optional IN-OTHER-WINDOW IGNORE-INCLUDE EVENT)" t nil) - -(define-obsolete-function-alias 'ff-mouse-find-other-file #'ff-find-other-file "28.1") - -(define-obsolete-function-alias 'ff-mouse-find-other-file-other-window #'ff-find-other-file-other-window "28.1") - +(fn &optional IN-OTHER-WINDOW IGNORE-INCLUDE EVENT)" t nil) +(define-obsolete-function-alias 'ff-mouse-find-other-file #'ff-find-other-file "\ +28.1") +(define-obsolete-function-alias 'ff-mouse-find-other-file-other-window #'ff-find-other-file-other-window "\ +28.1") (autoload 'ff-find-other-file-other-window "find-file" "\ Visit the file you point at in another window. -\(fn EVENT)" t nil) - +(fn EVENT)" t nil) (register-definition-prefixes "find-file" '("cc-" "ff-" "modula2-other-file-alist")) -;;;*** -;;;### (autoloads nil "find-func" "emacs-lisp/find-func.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from emacs-lisp/find-func.el (autoload 'find-library "find-func" "\ @@ -13196,29 +11873,25 @@ This function searches `find-library-source-path' if non-nil, and See the `find-library-include-other-files' user option for customizing the candidate completions. -\(fn LIBRARY)" t nil) - +(fn LIBRARY)" t nil) (autoload 'read-library-name "find-func" "\ Read and return a library name, defaulting to the one near point. A library name is the filename of an Emacs Lisp library located in a directory under `load-path' (or `find-library-source-path', if non-nil)." nil nil) - (autoload 'find-library-other-window "find-func" "\ Find the Emacs Lisp source of LIBRARY in another window. See `find-library' for more details. -\(fn LIBRARY)" t nil) - +(fn LIBRARY)" t nil) (autoload 'find-library-other-frame "find-func" "\ Find the Emacs Lisp source of LIBRARY in another frame. See `find-library' for more details. -\(fn LIBRARY)" t nil) - +(fn LIBRARY)" t nil) (autoload 'find-function-search-for-symbol "find-func" "\ Search for SYMBOL's definition of type TYPE in LIBRARY. Visit the library in a buffer, and return a cons cell (BUFFER . POSITION), @@ -13229,8 +11902,7 @@ Otherwise, TYPE specifies the kind of definition, and it is interpreted via `find-function-regexp-alist'. The search is done in the source for library LIBRARY. -\(fn SYMBOL TYPE LIBRARY)" nil nil) - +(fn SYMBOL TYPE LIBRARY)" nil nil) (autoload 'find-function-noselect "find-func" "\ Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION. @@ -13243,8 +11915,7 @@ If FUNCTION is a built-in function, this function normally attempts to find it in the Emacs C sources; however, if LISP-ONLY is non-nil, signal an error instead. -\(fn FUNCTION &optional LISP-ONLY)" nil nil) - +(fn FUNCTION &optional LISP-ONLY)" nil nil) (autoload 'find-function "find-func" "\ Find the definition of the FUNCTION near point. @@ -13255,22 +11926,19 @@ Set mark before moving, if the buffer already existed. See also `find-function-recenter-line' and `find-function-after-hook'. -\(fn FUNCTION)" t nil) - +(fn FUNCTION)" t nil) (autoload 'find-function-other-window "find-func" "\ Find, in another window, the definition of FUNCTION near point. See `find-function' for more details. -\(fn FUNCTION)" t nil) - +(fn FUNCTION)" t nil) (autoload 'find-function-other-frame "find-func" "\ Find, in another frame, the definition of FUNCTION near point. See `find-function' for more details. -\(fn FUNCTION)" t nil) - +(fn FUNCTION)" t nil) (autoload 'find-variable-noselect "find-func" "\ Return a pair `(BUFFER . POINT)' pointing to the definition of VARIABLE. @@ -13278,8 +11946,7 @@ Finds the library containing the definition of VARIABLE in a buffer and the point of the definition. The buffer is not selected. If the variable's definition can't be found in the buffer, return (BUFFER). -\(fn VARIABLE &optional FILE)" nil nil) - +(fn VARIABLE &optional FILE)" nil nil) (autoload 'find-variable "find-func" "\ Find the definition of the VARIABLE at or before point. @@ -13291,22 +11958,19 @@ Set mark before moving, if the buffer already existed. See also `find-function-recenter-line' and `find-function-after-hook'. -\(fn VARIABLE)" t nil) - +(fn VARIABLE)" t nil) (autoload 'find-variable-other-window "find-func" "\ Find, in another window, the definition of VARIABLE near point. See `find-variable' for more details. -\(fn VARIABLE)" t nil) - +(fn VARIABLE)" t nil) (autoload 'find-variable-other-frame "find-func" "\ Find, in another frame, the definition of VARIABLE near point. See `find-variable' for more details. -\(fn VARIABLE)" t nil) - +(fn VARIABLE)" t nil) (autoload 'find-definition-noselect "find-func" "\ Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL. If the definition can't be found in the buffer, return (BUFFER). @@ -13314,8 +11978,7 @@ TYPE says what type of definition: nil for a function, `defvar' for a variable, `defface' for a face. This function does not switch to the buffer nor display it. -\(fn SYMBOL TYPE &optional FILE)" nil nil) - +(fn SYMBOL TYPE &optional FILE)" nil nil) (autoload 'find-face-definition "find-func" "\ Find the definition of FACE. FACE defaults to the name near point. @@ -13327,81 +11990,62 @@ Set mark before moving, if the buffer already existed. See also `find-function-recenter-line' and `find-function-after-hook'. -\(fn FACE)" t nil) - +(fn FACE)" t nil) (autoload 'find-function-on-key "find-func" "\ Find the function that KEY invokes. KEY is a string. Set mark before moving, if the buffer already existed. -\(fn KEY)" t nil) - +(fn KEY)" t nil) (autoload 'find-function-on-key-other-window "find-func" "\ Find, in the other window, the function that KEY invokes. See `find-function-on-key'. -\(fn KEY)" t nil) - +(fn KEY)" t nil) (autoload 'find-function-on-key-other-frame "find-func" "\ Find, in the other frame, the function that KEY invokes. See `find-function-on-key'. -\(fn KEY)" t nil) - +(fn KEY)" t nil) (autoload 'find-function-at-point "find-func" "\ Find directly the function at point in the other window." t nil) - (autoload 'find-variable-at-point "find-func" "\ Find directly the variable at point in the other window." t nil) - (autoload 'find-function-setup-keys "find-func" "\ Define some key bindings for the `find-function' family of functions." nil nil) - (register-definition-prefixes "find-func" '("find-" "read-library-name--find-files")) -;;;*** -;;;### (autoloads nil "find-lisp" "find-lisp.el" (0 0 0 0)) ;;; Generated autoloads from find-lisp.el (autoload 'find-lisp-find-dired "find-lisp" "\ Find files in DIR, matching REGEXP. -\(fn DIR REGEXP)" t nil) - +(fn DIR REGEXP)" t nil) (autoload 'find-lisp-find-dired-subdirectories "find-lisp" "\ Find all subdirectories of DIR. -\(fn DIR)" t nil) - +(fn DIR)" t nil) (autoload 'find-lisp-find-dired-filter "find-lisp" "\ Change the filter on a `find-lisp-find-dired' buffer to REGEXP. -\(fn REGEXP)" t nil) - +(fn REGEXP)" t nil) (register-definition-prefixes "find-lisp" '("find-lisp-")) -;;;*** -;;;### (autoloads nil "finder" "finder.el" (0 0 0 0)) ;;; Generated autoloads from finder.el (autoload 'finder-list-keywords "finder" "\ Display descriptions of the keywords in the Finder buffer." t nil) - (autoload 'finder-commentary "finder" "\ Display FILE's commentary section. FILE should be in a form suitable for passing to `locate-library'. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'finder-by-keyword "finder" "\ Find packages matching a given keyword." t nil) - (register-definition-prefixes "finder" '("finder-" "generated-finder-keywords-file")) -;;;*** -;;;### (autoloads nil "flow-ctrl" "flow-ctrl.el" (0 0 0 0)) ;;; Generated autoloads from flow-ctrl.el (autoload 'enable-flow-control "flow-ctrl" "\ @@ -13409,8 +12053,7 @@ Toggle flow control handling. When handling is enabled, user can type C-s as C-\\, and C-q as C-^. With arg, enable flow control mode if arg is positive, otherwise disable. -\(fn &optional ARGUMENT)" t nil) - +(fn &optional ARGUMENT)" t nil) (autoload 'enable-flow-control-on "flow-ctrl" "\ Enable flow control if using one of a specified set of terminal types. Use `(enable-flow-control-on \"vt100\" \"h19\")' to enable flow control @@ -13418,20 +12061,16 @@ on VT-100 and H19 terminals. When flow control is enabled, you must type C-\\ to get the effect of a C-s, and type C-^ to get the effect of a C-q. -\(fn &rest LOSING-TERMINAL-TYPES)" nil nil) - +(fn &rest LOSING-TERMINAL-TYPES)" nil nil) (register-definition-prefixes "flow-ctrl" '("flow-control-c-")) -;;;*** -;;;### (autoloads nil "flow-fill" "mail/flow-fill.el" (0 0 0 0)) ;;; Generated autoloads from mail/flow-fill.el (autoload 'fill-flowed-encode "flow-fill" "\ -\(fn &optional BUFFER)" nil nil) - +(fn &optional BUFFER)" nil nil) (autoload 'fill-flowed "flow-fill" "\ Apply RFC2646 decoding to BUFFER. If BUFFER is nil, default to the current buffer. @@ -13439,16 +12078,13 @@ If BUFFER is nil, default to the current buffer. If DELETE-SPACE, delete RFC2646 spaces padding at the end of lines. -\(fn &optional BUFFER DELETE-SPACE)" nil nil) - +(fn &optional BUFFER DELETE-SPACE)" nil nil) (register-definition-prefixes "flow-fill" '("fill-flowed-")) -;;;*** -;;;### (autoloads nil "flymake" "progmodes/flymake.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/flymake.el -(push (purecopy '(flymake 1 2 2)) package--builtin-versions) +(push (purecopy '(flymake 1 2 2)) package--builtin-versions) (autoload 'flymake-log "flymake" "\ Log, at level LEVEL, the message MSG formatted with ARGS. LEVEL is passed to `display-warning', which is used to display @@ -13456,8 +12092,7 @@ the warning. If this form is included in a file, the generated warning contains an indication of the file that generated it. -\(fn LEVEL MSG &rest ARGS)" nil t) - +(fn LEVEL MSG &rest ARGS)" nil t) (autoload 'flymake-make-diagnostic "flymake" "\ Make a Flymake diagnostic for LOCUS's region from BEG to END. LOCUS is a buffer object or a string designating a file name. @@ -13479,8 +12114,7 @@ created diagnostic, overriding the default properties and any properties listed in the `flymake-overlay-control' property of the diagnostic's type symbol. -\(fn LOCUS BEG END TYPE TEXT &optional DATA OVERLAY-PROPERTIES)" nil nil) - +(fn LOCUS BEG END TYPE TEXT &optional DATA OVERLAY-PROPERTIES)" nil nil) (autoload 'flymake-diagnostics "flymake" "\ Get Flymake diagnostics in region determined by BEG and END. @@ -13488,15 +12122,13 @@ If neither BEG or END is supplied, use whole accessible buffer, otherwise if BEG is non-nil and END is nil, consider only diagnostics at BEG. -\(fn &optional BEG END)" nil nil) - +(fn &optional BEG END)" nil nil) (autoload 'flymake-diag-region "flymake" "\ Compute BUFFER's region (BEG . END) corresponding to LINE and COL. If COL is nil, return a region just for LINE. Return nil if the region is invalid. This function saves match data. -\(fn BUFFER LINE &optional COL)" nil nil) - +(fn BUFFER LINE &optional COL)" nil nil) (autoload 'flymake-mode "flymake" "\ Toggle Flymake mode on or off. @@ -13551,20 +12183,14 @@ evaluate `flymake-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'flymake-mode-on "flymake" "\ Turn Flymake mode on." nil nil) - (autoload 'flymake-mode-off "flymake" "\ Turn Flymake mode off." nil nil) - (register-definition-prefixes "flymake" '("flymake-")) -;;;*** -;;;### (autoloads nil "flymake-cc" "progmodes/flymake-cc.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from progmodes/flymake-cc.el (autoload 'flymake-cc "flymake-cc" "\ @@ -13573,28 +12199,21 @@ This backend uses `flymake-cc-command' (which see) to launch a process that is passed the current buffer's contents via stdin. REPORT-FN is Flymake's callback. -\(fn REPORT-FN &rest ARGS)" nil nil) - +(fn REPORT-FN &rest ARGS)" nil nil) (register-definition-prefixes "flymake-cc" '("flymake-cc-")) -;;;*** -;;;### (autoloads nil "flymake-proc" "progmodes/flymake-proc.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from progmodes/flymake-proc.el -(push (purecopy '(flymake-proc 1 0)) package--builtin-versions) +(push (purecopy '(flymake-proc 1 0)) package--builtin-versions) (register-definition-prefixes "flymake-proc" '("flymake-proc-")) -;;;*** -;;;### (autoloads nil "flyspell" "textmodes/flyspell.el" (0 0 0 0)) ;;; Generated autoloads from textmodes/flyspell.el (autoload 'flyspell-prog-mode "flyspell" "\ Turn on `flyspell-mode' for comments and strings." t nil) (defvar flyspell-mode nil "Non-nil if Flyspell mode is enabled.") - (autoload 'flyspell-mode "flyspell" "\ Toggle on-the-fly spell checking (Flyspell mode). @@ -13621,7 +12240,7 @@ invoking `ispell-change-dictionary'. Consider using the `ispell-parser' to check your text. For instance consider adding: -\(add-hook \\='tex-mode-hook (lambda () (setq ispell-parser \\='tex))) +(add-hook \\='tex-mode-hook (lambda () (setq ispell-parser \\='tex))) in your init file. \\[flyspell-region] checks all words inside a region. @@ -13641,49 +12260,37 @@ evaluate `flyspell-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'turn-on-flyspell "flyspell" "\ Unconditionally turn on Flyspell mode." nil nil) - (autoload 'turn-off-flyspell "flyspell" "\ Unconditionally turn off Flyspell mode." nil nil) - (autoload 'flyspell-mode-off "flyspell" "\ Turn Flyspell mode off." nil nil) - (autoload 'flyspell-region "flyspell" "\ Flyspell text between BEG and END. Make sure `flyspell-mode' is turned on if you want the highlight of a misspelled word removed when you've corrected it. -\(fn BEG END)" t nil) - +(fn BEG END)" t nil) (autoload 'flyspell-buffer "flyspell" "\ Flyspell whole buffer." t nil) - (register-definition-prefixes "flyspell" '("flyspell-" "mail-mode-flyspell-verify" "make-flyspell-overlay" "sgml-mode-flyspell-verify" "tex")) -;;;*** -;;;### (autoloads nil "foldout" "foldout.el" (0 0 0 0)) ;;; Generated autoloads from foldout.el -(push (purecopy '(foldout 1 10)) package--builtin-versions) +(push (purecopy '(foldout 1 10)) package--builtin-versions) (register-definition-prefixes "foldout" '("foldout-")) -;;;*** -;;;### (autoloads nil "follow" "follow.el" (0 0 0 0)) ;;; Generated autoloads from follow.el (autoload 'turn-on-follow-mode "follow" "\ Turn on Follow mode. Please see the function `follow-mode'." nil nil) - (autoload 'turn-off-follow-mode "follow" "\ Turn off Follow mode. Please see the function `follow-mode'." nil nil) - (autoload 'follow-mode "follow" "\ Toggle Follow mode. @@ -13730,8 +12337,7 @@ evaluate `follow-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'follow-scroll-up-window "follow" "\ Scroll text in a Follow mode window up by that window's size. The other windows in the window chain will scroll synchronously. @@ -13744,8 +12350,7 @@ Negative ARG means scroll downward. Works like `scroll-up' when not in Follow mode. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'follow-scroll-down-window "follow" "\ Scroll text in a Follow mode window down by that window's size. The other windows in the window chain will scroll synchronously. @@ -13758,8 +12363,7 @@ Negative ARG means scroll upward. Works like `scroll-down' when not in Follow mode. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'follow-scroll-up "follow" "\ Scroll text in a Follow mode window chain up. @@ -13771,8 +12375,7 @@ Negative ARG means scroll downward. Works like `scroll-up' when not in Follow mode. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'follow-scroll-down "follow" "\ Scroll text in a Follow mode window chain down. @@ -13784,8 +12387,7 @@ Negative ARG means scroll upward. Works like `scroll-down' when not in Follow mode. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'follow-delete-other-windows-and-split "follow" "\ Create two side by side windows and enter Follow mode. @@ -13794,27 +12396,21 @@ in the selected window. All other windows, in the current frame, are deleted and the selected window is split in two side-by-side windows. Follow mode is activated, hence the two windows always will display two successive pages. -\(If one window is moved, the other one will follow.) +(If one window is moved, the other one will follow.) If ARG is positive, the leftmost window is selected. If negative, the rightmost is selected. If ARG is nil, the leftmost window is selected if the original window is the first one in the frame. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "follow" '("follow-")) -;;;*** -;;;### (autoloads nil "fontset" "international/fontset.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from international/fontset.el -(register-definition-prefixes "fontset" '("charset-script-alist" "create-" "fontset-" "generate-fontset-menu" "set" "standard-fontset-spec" "x-" "xlfd-")) +(register-definition-prefixes "fontset" '("build-default-fontset-data" "charset-script-alist" "create-" "fontset-" "generate-fontset-menu" "set" "standard-fontset-spec" "x-" "xlfd-")) -;;;*** -;;;### (autoloads nil "footnote" "mail/footnote.el" (0 0 0 0)) ;;; Generated autoloads from mail/footnote.el (autoload 'footnote-mode "footnote" "\ @@ -13839,13 +12435,15 @@ evaluate `footnote-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "footnote" '("footnote-")) -;;;*** -;;;### (autoloads nil "format-spec" "format-spec.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/format.el + +(register-definition-prefixes "semantic/format" '("semantic-")) + + ;;; Generated autoloads from format-spec.el (autoload 'format-spec "format-spec" "\ @@ -13896,13 +12494,10 @@ any occurrences of \"%%\" in FORMAT verbatim in the result. If SPLIT, instead of returning a single string, a list of strings is returned, where each format spec is its own element. -\(fn FORMAT SPECIFICATION &optional IGNORE-MISSING SPLIT)" nil nil) - +(fn FORMAT SPECIFICATION &optional IGNORE-MISSING SPLIT)" nil nil) (register-definition-prefixes "format-spec" '("format-spec-")) -;;;*** -;;;### (autoloads nil "forms" "forms.el" (0 0 0 0)) ;;; Generated autoloads from forms.el (autoload 'forms-mode "forms" "\ @@ -13924,23 +12519,18 @@ Commands: Equivalent keys in read-only mode: C-c C-s forms-search-forward s C-c C-x forms-exit x -\(fn &optional PRIMARY)" t nil) - +(fn &optional PRIMARY)" t nil) (autoload 'forms-find-file "forms" "\ Visit a file in Forms mode. -\(fn FN)" t nil) - +(fn FN)" t nil) (autoload 'forms-find-file-other-window "forms" "\ Visit a file in Forms mode in other window. -\(fn FN)" t nil) - +(fn FN)" t nil) (register-definition-prefixes "forms" '("forms-")) -;;;*** -;;;### (autoloads nil "fortran" "progmodes/fortran.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/fortran.el (autoload 'fortran-mode "fortran" "\ @@ -14013,13 +12603,10 @@ Variables controlling indentation style and extra features: Turning on Fortran mode calls the value of the variable `fortran-mode-hook' with no args, if that value is non-nil. -\(fn)" t nil) - +(fn)" t nil) (register-definition-prefixes "fortran" '("fortran-")) -;;;*** -;;;### (autoloads nil "fortune" "play/fortune.el" (0 0 0 0)) ;;; Generated autoloads from play/fortune.el (autoload 'fortune-add-fortune "fortune" "\ @@ -14028,24 +12615,21 @@ Add STRING to a fortune file FILE. Interactively, if called with a prefix argument, read the file name to use. Otherwise use the value of `fortune-file'. -\(fn STRING FILE)" t nil) - +(fn STRING FILE)" t nil) (autoload 'fortune-from-region "fortune" "\ Append the current region to a local fortune-like data file. Interactively, if called with a prefix argument, read the file name to use. Otherwise use the value of `fortune-file'. -\(fn BEG END FILE)" t nil) - +(fn BEG END FILE)" t nil) (autoload 'fortune-compile "fortune" "\ Compile fortune file. If called with a prefix asks for the FILE to compile, otherwise uses the value of `fortune-file'. This currently cannot handle directories. -\(fn &optional FILE)" t nil) - +(fn &optional FILE)" t nil) (autoload 'fortune-to-signature "fortune" "\ Create signature from output of the fortune program. @@ -14054,15 +12638,13 @@ otherwise uses the value of `fortune-file'. If you want to have fortune choose from a set of files in a directory, call interactively with prefix and choose the directory as the fortune-file. -\(fn &optional FILE)" t nil) - +(fn &optional FILE)" t nil) (autoload 'fortune-message "fortune" "\ Display a fortune cookie to the mini-buffer. If called with a prefix, it has the same behavior as `fortune'. Optional FILE is a fortune file from which a cookie will be selected. -\(fn &optional FILE)" t nil) - +(fn &optional FILE)" t nil) (autoload 'fortune "fortune" "\ Display a fortune cookie. If called with a prefix asks for the FILE to choose the fortune from, @@ -14070,23 +12652,18 @@ otherwise uses the value of `fortune-file'. If you want to have fortune choose from a set of files in a directory, call interactively with prefix and choose the directory as the fortune-file. -\(fn &optional FILE)" t nil) - +(fn &optional FILE)" t nil) (register-definition-prefixes "fortune" '("fortune-")) -;;;*** -;;;### (autoloads nil "frameset" "frameset.el" (0 0 0 0)) ;;; Generated autoloads from frameset.el (defvar frameset-session-filter-alist (append '((left . frameset-filter-iconified) (minibuffer . frameset-filter-minibuffer) (top . frameset-filter-iconified)) (mapcar (lambda (p) (cons p :never)) frame-internal-parameters)) "\ Minimum set of parameters to filter for live (on-session) framesets. DO NOT MODIFY. See `frameset-filter-alist' for a full description.") - (defvar frameset-persistent-filter-alist (append '((background-color . frameset-filter-sanitize-color) (bottom . frameset-filter-shelve-param) (buffer-list . :never) (buffer-predicate . :never) (buried-buffer-list . :never) (client . :never) (delete-before . :never) (font . frameset-filter-font-param) (font-backend . :never) (foreground-color . frameset-filter-sanitize-color) (frameset--text-pixel-height . :save) (frameset--text-pixel-width . :save) (fullscreen . frameset-filter-shelve-param) (GUI:bottom . frameset-filter-unshelve-param) (GUI:font . frameset-filter-unshelve-param) (GUI:fullscreen . frameset-filter-unshelve-param) (GUI:height . frameset-filter-unshelve-param) (GUI:left . frameset-filter-unshelve-param) (GUI:right . frameset-filter-unshelve-param) (GUI:top . frameset-filter-unshelve-param) (GUI:width . frameset-filter-unshelve-param) (height . frameset-filter-shelve-param) (left . frameset-filter-shelve-param) (parent-frame . :never) (mouse-wheel-frame . :never) (right . frameset-filter-shelve-param) (top . frameset-filter-shelve-param) (tty . frameset-filter-tty-to-GUI) (tty-type . frameset-filter-tty-to-GUI) (width . frameset-filter-shelve-param) (window-system . :never)) frameset-session-filter-alist) "\ Parameters to filter for persistent framesets. DO NOT MODIFY. See `frameset-filter-alist' for a full description.") - (defvar frameset-filter-alist frameset-persistent-filter-alist "\ Alist of frame parameters and filtering functions. @@ -14142,7 +12719,6 @@ It must return: Frame parameters not on this alist are passed intact, as if they were defined with ACTION = nil.") - (autoload 'frameset-frame-id "frameset" "\ Return the frame id of FRAME, if it has one; else, return nil. A frame id is a string that uniquely identifies a frame. @@ -14151,20 +12727,17 @@ invocations, and once assigned is never changed unless the same frame is duplicated (via `frameset-restore'), in which case the newest frame keeps the id and the old frame's is set to nil. -\(fn FRAME)" nil nil) - +(fn FRAME)" nil nil) (autoload 'frameset-frame-id-equal-p "frameset" "\ Return non-nil if FRAME's id matches ID. -\(fn FRAME ID)" nil nil) - +(fn FRAME ID)" nil nil) (autoload 'frameset-frame-with-id "frameset" "\ Return the live frame with id ID, if exists; else nil. If FRAME-LIST is a list of frames, check these frames only. If nil, check all live frames. -\(fn ID &optional FRAME-LIST)" nil nil) - +(fn ID &optional FRAME-LIST)" nil nil) (autoload 'frameset-save "frameset" "\ Return a frameset for FRAME-LIST, a list of frames. Dead frames and non-frame objects are silently removed from the list. @@ -14177,8 +12750,7 @@ PREDICATE is a predicate function, which must return non-nil for frames that should be saved; if PREDICATE is nil, all frames from FRAME-LIST are saved. PROPERTIES is a user-defined property list to add to the frameset. -\(fn FRAME-LIST &key APP NAME DESCRIPTION FILTERS PREDICATE PROPERTIES)" nil nil) - +(fn FRAME-LIST &key APP NAME DESCRIPTION FILTERS PREDICATE PROPERTIES)" nil nil) (autoload 'frameset-restore "frameset" "\ Restore a FRAMESET into the current display(s). @@ -14238,8 +12810,7 @@ restoration, including those that have been reused or created anew. All keyword parameters default to nil. -\(fn FRAMESET &key PREDICATE FILTERS REUSE-FRAMES FORCE-DISPLAY FORCE-ONSCREEN CLEANUP-FRAMES)" nil nil) - +(fn FRAMESET &key PREDICATE FILTERS REUSE-FRAMES FORCE-DISPLAY FORCE-ONSCREEN CLEANUP-FRAMES)" nil nil) (autoload 'frameset-to-register "frameset" "\ Store the current frameset in register REGISTER. Use \\[jump-to-register] to restore the frameset. @@ -14247,45 +12818,53 @@ Argument is a character, naming the register. Interactively, reads the register using `register-read-with-preview'. -\(fn REGISTER)" t nil) - +(fn REGISTER)" t nil) (register-definition-prefixes "frameset" '("frameset-")) -;;;*** -;;;### (autoloads nil "fringe" "fringe.el" (0 0 0 0)) ;;; Generated autoloads from fringe.el -(unless (fboundp 'define-fringe-bitmap) (defun define-fringe-bitmap (_bitmap _bits &optional _height _width _align) "Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH.\nBITMAP is a symbol identifying the new fringe bitmap.\nBITS is either a string or a vector of integers.\nHEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS.\nWIDTH must be an integer between 1 and 16, or nil which defaults to 8.\nOptional fifth arg ALIGN may be one of `top', `center', or `bottom',\nindicating the positioning of the bitmap relative to the rows where it\nis used; the default is to center the bitmap. Fifth arg may also be a\nlist (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap\nshould be repeated.\nIf BITMAP already exists, the existing definition is replaced.")) - +(unless (fboundp 'define-fringe-bitmap) (defun define-fringe-bitmap (_bitmap _bits &optional _height _width _align) "Define fringe bitmap BITMAP from BITS of size HEIGHT x WIDTH. +BITMAP is a symbol identifying the new fringe bitmap. +BITS is either a string or a vector of integers. +HEIGHT is height of bitmap. If HEIGHT is nil, use length of BITS. +WIDTH must be an integer between 1 and 16, or nil which defaults to 8. +Optional fifth arg ALIGN may be one of `top', `center', or `bottom', +indicating the positioning of the bitmap relative to the rows where it +is used; the default is to center the bitmap. Fifth arg may also be a +list (ALIGN PERIODIC) where PERIODIC non-nil specifies that the bitmap +should be repeated. +If BITMAP already exists, the existing definition is replaced.")) (register-definition-prefixes "fringe" '("fringe-" "set-fringe-")) -;;;*** -;;;### (autoloads nil "gamegrid" "play/gamegrid.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/fw.el + +(register-definition-prefixes "semantic/fw" '("semantic")) + + ;;; Generated autoloads from play/gamegrid.el (register-definition-prefixes "gamegrid" '("gamegrid-")) -;;;*** -;;;### (autoloads nil "gametree" "play/gametree.el" (0 0 0 0)) ;;; Generated autoloads from play/gametree.el (register-definition-prefixes "gametree" '("gametree-")) -;;;*** -;;;### (autoloads nil "gdb-mi" "progmodes/gdb-mi.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/bovine/gcc.el + +(register-definition-prefixes "semantic/bovine/gcc" '("semantic-")) + + ;;; Generated autoloads from progmodes/gdb-mi.el (defvar gdb-enable-debug nil "\ Non-nil if Gdb-Enable-Debug mode is enabled. See the `gdb-enable-debug' command for a description of this minor mode.") - (custom-autoload 'gdb-enable-debug "gdb-mi" nil) - (autoload 'gdb-enable-debug "gdb-mi" "\ Toggle logging of transaction between Emacs and Gdb. @@ -14310,8 +12889,7 @@ evaluate `(default-value \\='gdb-enable-debug)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'gdb "gdb-mi" "\ Run gdb passing it COMMAND-LINE as arguments. @@ -14370,28 +12948,21 @@ detailed description of this mode. | | D gdb-delete-breakpoint | +-----------------------------------+----------------------------------+ -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (register-definition-prefixes "gdb-mi" '("breakpoint" "def-gdb-" "gdb" "gud-" "hollow-right-triangle" "nil")) -;;;*** -;;;### (autoloads nil "generator" "emacs-lisp/generator.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from emacs-lisp/generator.el (register-definition-prefixes "generator" '("cps-" "iter-")) -;;;*** -;;;### (autoloads nil "generic" "emacs-lisp/generic.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/generic.el (defvar generic-mode-list nil "\ A list of mode names for `generic-mode'. Do not add entries to this list directly; use `define-generic-mode' instead (which see).") - (autoload 'define-generic-mode "generic" "\ Create a new generic mode MODE. @@ -14430,17 +13001,13 @@ mode hook `MODE-hook'. See the file generic-x.el for some examples of `define-generic-mode'. -\(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST AUTO-MODE-LIST FUNCTION-LIST &optional DOCSTRING)" nil t) - +(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST AUTO-MODE-LIST FUNCTION-LIST &optional DOCSTRING)" nil t) (function-put 'define-generic-mode 'lisp-indent-function '1) - (function-put 'define-generic-mode 'doc-string-elt '7) - (autoload 'generic-mode-internal "generic" "\ Go into the generic mode MODE. -\(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST FUNCTION-LIST)" nil nil) - +(fn MODE COMMENT-LIST KEYWORD-LIST FONT-LOCK-LIST FUNCTION-LIST)" nil nil) (autoload 'generic-mode "generic" "\ Enter generic mode MODE. @@ -14451,8 +13018,7 @@ own mode, but have comment characters, keywords, and the like.) To define a generic-mode, use the function `define-generic-mode'. Some generic modes are defined in `generic-x.el'. -\(fn MODE)" t nil) - +(fn MODE)" t nil) (autoload 'generic-make-keywords-list "generic" "\ Return a `font-lock-keywords' construct that highlights KEYWORD-LIST. KEYWORD-LIST is a list of keyword strings that should be @@ -14462,22 +13028,21 @@ PREFIX and SUFFIX. Then it returns a construct based on this regular expression that can be used as an element of `font-lock-keywords'. -\(fn KEYWORD-LIST FACE &optional PREFIX SUFFIX)" nil nil) - +(fn KEYWORD-LIST FACE &optional PREFIX SUFFIX)" nil nil) (make-obsolete 'generic-make-keywords-list 'regexp-opt '"24.4") - (register-definition-prefixes "generic" '("generic-")) -;;;*** -;;;### (autoloads nil "generic-x" "generic-x.el" (0 0 0 0)) -;;; Generated autoloads from generic-x.el +;;; Generated autoloads from cedet/ede/generic.el + +(register-definition-prefixes "ede/generic" '("ede-generic-")) + + +;;; Generated autoloads from cedet/srecode/getset.el -(register-definition-prefixes "generic-x" '("default-generic-mode" "generic-")) +(register-definition-prefixes "srecode/getset" '("srecode-")) -;;;*** -;;;### (autoloads nil "glasses" "progmodes/glasses.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/glasses.el (autoload 'glasses-mode "glasses" "\ @@ -14500,14 +13065,15 @@ evaluate `glasses-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "glasses" '("glasses-")) -;;;*** -;;;### (autoloads nil "glyphless-mode" "textmodes/glyphless-mode.el" -;;;;;; (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/global.el + +(register-definition-prefixes "semantic/symref/global" '("semantic-symref-global--line-re")) + + ;;; Generated autoloads from textmodes/glyphless-mode.el (autoload 'glyphless-display-mode "glyphless-mode" "\ @@ -14531,21 +13097,17 @@ evaluate `glyphless-display-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "glyphless-mode" '("glyphless-mode-")) -;;;*** -;;;### (autoloads nil "gmm-utils" "gnus/gmm-utils.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gmm-utils.el (autoload 'gmm-regexp-concat "gmm-utils" "\ Potentially concat a list of regexps into a single one. The concatenation is done with logical ORs. -\(fn REGEXP)" nil nil) - +(fn REGEXP)" nil nil) (autoload 'gmm-message "gmm-utils" "\ If LEVEL is lower than `gmm-verbose' print ARGS using `message'. @@ -14556,19 +13118,16 @@ Guideline for numbers: 7 - not very important messages on stuff 9 - messages inside loops. -\(fn LEVEL &rest ARGS)" nil nil) - +(fn LEVEL &rest ARGS)" nil nil) (autoload 'gmm-error "gmm-utils" "\ Beep an error if LEVEL is equal to or less than `gmm-verbose'. ARGS are passed to `message'. -\(fn LEVEL &rest ARGS)" nil nil) - +(fn LEVEL &rest ARGS)" nil nil) (autoload 'gmm-widget-p "gmm-utils" "\ Non-nil if SYMBOL is a widget. -\(fn SYMBOL)" nil nil) - +(fn SYMBOL)" nil nil) (autoload 'gmm-tool-bar-from-list "gmm-utils" "\ Make a tool bar from ICON-LIST. @@ -14587,27 +13146,22 @@ runs the command find-file\", then use `new-file' in ZAP-LIST. DEFAULT-MAP specifies the default key map for ICON-LIST. -\(fn ICON-LIST ZAP-LIST DEFAULT-MAP)" nil nil) - +(fn ICON-LIST ZAP-LIST DEFAULT-MAP)" nil nil) (register-definition-prefixes "gmm-utils" '("defun-gmm" "gmm-")) -;;;*** -;;;### (autoloads nil "gnus" "gnus/gnus.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus.el + (push (purecopy '(gnus 5 13)) package--builtin-versions) (custom-autoload 'gnus-select-method "gnus") - (autoload 'gnus-child-no-server "gnus" "\ Read network news as a child, without connecting to the local server. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'gnus-slave-no-server "gnus" "\ Read network news as a child, without connecting to the local server. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'gnus-no-server "gnus" "\ Read network news. If ARG is a positive number, Gnus will use that as the startup level. @@ -14617,18 +13171,15 @@ an NNTP server to use. As opposed to `gnus', this command will not connect to the local server. -\(fn &optional ARG CHILD)" t nil) - +(fn &optional ARG CHILD)" t nil) (autoload 'gnus-child "gnus" "\ Read news as a child. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'gnus-slave "gnus" "\ Read news as a child. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'gnus-other-frame "gnus" "\ Pop up a frame to read news. This will call one of the Gnus commands which is specified by the user @@ -14640,39 +13191,31 @@ such as \"unix:0\" to specify where to pop up a frame. If DISPLAY is omitted or the function `make-frame-on-display' is not available, the current display is used. -\(fn &optional ARG DISPLAY)" t nil) - +(fn &optional ARG DISPLAY)" t nil) (autoload 'gnus "gnus" "\ Read network news. If ARG is non-nil and a positive number, Gnus will use that as the startup level. If ARG is non-nil and not a positive number, Gnus will prompt the user for the name of an NNTP server to use. -\(fn &optional ARG DONT-CONNECT CHILD)" t nil) - +(fn &optional ARG DONT-CONNECT CHILD)" t nil) (register-definition-prefixes "gnus" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-agent" "gnus/gnus-agent.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-agent.el (autoload 'gnus-unplugged "gnus-agent" "\ Start Gnus unplugged." t nil) - (autoload 'gnus-plugged "gnus-agent" "\ Start Gnus plugged." t nil) - (autoload 'gnus-child-unplugged "gnus-agent" "\ Read news as a child unplugged. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'gnus-slave-unplugged "gnus-agent" "\ Read news as a child unplugged. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'gnus-agentize "gnus-agent" "\ Allow Gnus to be an offline newsreader. @@ -14683,10 +13226,8 @@ customize `gnus-agent' to nil. This will modify the `gnus-setup-news-hook', and `message-send-mail-real-function' variables, and install the Gnus agent minor mode in all Gnus buffers." t nil) - (autoload 'gnus-agent-possibly-save-gcc "gnus-agent" "\ Save GCC if Gnus is unplugged." nil nil) - (autoload 'gnus-agent-rename-group "gnus-agent" "\ Rename fully-qualified OLD-GROUP as NEW-GROUP. Always updates the agent, even when disabled, as the old agent @@ -14694,8 +13235,7 @@ files would corrupt gnus when the agent was next enabled. Depends upon the caller to determine whether group renaming is supported. -\(fn OLD-GROUP NEW-GROUP)" nil nil) - +(fn OLD-GROUP NEW-GROUP)" nil nil) (autoload 'gnus-agent-delete-group "gnus-agent" "\ Delete fully-qualified GROUP. Always updates the agent, even when disabled, as the old agent @@ -14703,87 +13243,65 @@ files would corrupt gnus when the agent was next enabled. Depends upon the caller to determine whether group deletion is supported. -\(fn GROUP)" nil nil) - +(fn GROUP)" nil nil) (autoload 'gnus-agent-get-undownloaded-list "gnus-agent" "\ Construct list of articles that have not been downloaded." nil nil) - (autoload 'gnus-agent-possibly-alter-active "gnus-agent" "\ Possibly expand a group's active range to include articles downloaded into the agent. -\(fn GROUP ACTIVE &optional INFO)" nil nil) - +(fn GROUP ACTIVE &optional INFO)" nil nil) (autoload 'gnus-agent-find-parameter "gnus-agent" "\ Search for GROUPs SYMBOL in the group's parameters, the group's topic parameters, the group's category, or the customizable variables. Returns the first non-nil value found. -\(fn GROUP SYMBOL)" nil nil) - +(fn GROUP SYMBOL)" nil nil) (autoload 'gnus-agent-batch-fetch "gnus-agent" "\ Start Gnus and fetch session." t nil) - (autoload 'gnus-agent-batch "gnus-agent" "\ Start Gnus, send queue and fetch session." t nil) - (autoload 'gnus-agent-regenerate "gnus-agent" "\ Regenerate all agent covered files. CLEAN is obsolete and ignored. -\(fn &optional CLEAN REREAD)" t nil) - +(fn &optional CLEAN REREAD)" t nil) (register-definition-prefixes "gnus-agent" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-art" "gnus/gnus-art.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-art.el (autoload 'gnus-article-prepare-display "gnus-art" "\ Make the current buffer look like a nice article." nil nil) - (register-definition-prefixes "gnus-art" '(":keymap" "article-" "gnus-")) -;;;*** -;;;### (autoloads nil "gnus-async" "gnus/gnus-async.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-async.el (register-definition-prefixes "gnus-async" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-bcklg" "gnus/gnus-bcklg.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-bcklg.el (register-definition-prefixes "gnus-bcklg" '("gnus-backlog-")) -;;;*** -;;;### (autoloads nil "gnus-bookmark" "gnus/gnus-bookmark.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from gnus/gnus-bookmark.el (autoload 'gnus-bookmark-set "gnus-bookmark" "\ Set a bookmark for this article." '(gnus-article-mode gnus-summary-mode) nil) - (autoload 'gnus-bookmark-jump "gnus-bookmark" "\ Jump to a Gnus bookmark (BMK-NAME). -\(fn &optional BMK-NAME)" t nil) - +(fn &optional BMK-NAME)" t nil) (autoload 'gnus-bookmark-bmenu-list "gnus-bookmark" "\ Display a list of existing Gnus bookmarks. The list is displayed in a buffer named `*Gnus Bookmark List*'. The leftmost column displays a D if the bookmark is flagged for deletion, or > if it is flagged for displaying." t nil) - (register-definition-prefixes "gnus-bookmark" '("gnus-bookmark-")) -;;;*** -;;;### (autoloads nil "gnus-cache" "gnus/gnus-cache.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-cache.el (autoload 'gnus-jog-cache "gnus-cache" "\ @@ -14791,17 +13309,14 @@ Go through all groups and put the articles into the cache. Usage: $ emacs -batch -l ~/.emacs -l gnus -f gnus-jog-cache" t nil) - (autoload 'gnus-cache-generate-active "gnus-cache" "\ Generate the cache active file. -\(fn &optional DIRECTORY)" t nil) - +(fn &optional DIRECTORY)" t nil) (autoload 'gnus-cache-generate-nov-databases "gnus-cache" "\ Generate NOV files recursively starting in DIR. -\(fn DIR)" t nil) - +(fn DIR)" t nil) (autoload 'gnus-cache-rename-group "gnus-cache" "\ Rename OLD-GROUP as NEW-GROUP. Always updates the cache, even when disabled, as the old cache @@ -14809,8 +13324,7 @@ files would corrupt Gnus when the cache was next enabled. It depends on the caller to determine whether group renaming is supported. -\(fn OLD-GROUP NEW-GROUP)" nil nil) - +(fn OLD-GROUP NEW-GROUP)" nil nil) (autoload 'gnus-cache-delete-group "gnus-cache" "\ Delete GROUP from the cache. Always updates the cache, even when disabled, as the old cache @@ -14818,41 +13332,30 @@ files would corrupt gnus when the cache was next enabled. Depends upon the caller to determine whether group deletion is supported. -\(fn GROUP)" nil nil) - +(fn GROUP)" nil nil) (register-definition-prefixes "gnus-cache" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-cite" "gnus/gnus-cite.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-cite.el (register-definition-prefixes "gnus-cite" '("gnus-" "turn-o")) -;;;*** -;;;### (autoloads nil "gnus-cloud" "gnus/gnus-cloud.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-cloud.el (register-definition-prefixes "gnus-cloud" '("gnus-cloud-")) -;;;*** -;;;### (autoloads nil "gnus-cus" "gnus/gnus-cus.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-cus.el (register-definition-prefixes "gnus-cus" '("category-fields" "gnus-")) -;;;*** -;;;### (autoloads nil "gnus-dbus" "gnus/gnus-dbus.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-dbus.el (register-definition-prefixes "gnus-dbus" '("gnus-dbus-")) -;;;*** -;;;### (autoloads nil "gnus-delay" "gnus/gnus-delay.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-delay.el (autoload 'gnus-delay-article "gnus-delay" "\ @@ -14872,11 +13375,9 @@ The value of `message-draft-headers' determines which headers are generated when the article is delayed. Remaining headers are generated when the article is sent. -\(fn DELAY)" '(message-mode) nil) - +(fn DELAY)" '(message-mode) nil) (autoload 'gnus-delay-send-queue "gnus-delay" "\ Send all the delayed messages that are due now." t nil) - (autoload 'gnus-delay-initialize "gnus-delay" "\ Initialize the gnus-delay package. This sets up a key binding in `message-mode' to delay a message. @@ -14885,151 +13386,115 @@ This tells Gnus to look for delayed messages after getting new news. The optional arg NO-KEYMAP is ignored. Checking delayed messages is skipped if optional arg NO-CHECK is non-nil. -\(fn &optional NO-KEYMAP NO-CHECK)" nil nil) - +(fn &optional NO-KEYMAP NO-CHECK)" nil nil) (register-definition-prefixes "gnus-delay" '("gnus-delay-")) -;;;*** -;;;### (autoloads nil "gnus-demon" "gnus/gnus-demon.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-demon.el (register-definition-prefixes "gnus-demon" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-diary" "gnus/gnus-diary.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-diary.el (autoload 'gnus-user-format-function-d "gnus-diary" "\ -\(fn HEADER)" nil nil) - +(fn HEADER)" nil nil) (autoload 'gnus-user-format-function-D "gnus-diary" "\ -\(fn HEADER)" nil nil) - +(fn HEADER)" nil nil) (register-definition-prefixes "gnus-diary" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-dired" "gnus/gnus-dired.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-dired.el (autoload 'turn-on-gnus-dired-mode "gnus-dired" "\ Convenience method to turn on `gnus-dired-mode'." t nil) - (register-definition-prefixes "gnus-dired" '("gnus-dired-")) -;;;*** -;;;### (autoloads nil "gnus-draft" "gnus/gnus-draft.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-draft.el (autoload 'gnus-draft-reminder "gnus-draft" "\ Reminder user if there are unsent drafts." t nil) - (register-definition-prefixes "gnus-draft" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-dup" "gnus/gnus-dup.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-dup.el (register-definition-prefixes "gnus-dup" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-eform" "gnus/gnus-eform.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-eform.el (register-definition-prefixes "gnus-eform" '("gnus-edit-form")) -;;;*** -;;;### (autoloads nil "gnus-fun" "gnus/gnus-fun.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-fun.el (autoload 'gnus--random-face-with-type "gnus-fun" "\ Return file from DIR with extension EXT. Omit matches of OMIT, and process them by FUN. -\(fn DIR EXT OMIT FUN)" nil nil) - +(fn DIR EXT OMIT FUN)" nil nil) (autoload 'message-goto-eoh "message" nil t) - (autoload 'gnus-random-x-face "gnus-fun" "\ Return X-Face header data chosen randomly from `gnus-x-face-directory'. Files matching `gnus-x-face-omit-files' are not considered." t nil) - (autoload 'gnus-insert-random-x-face-header "gnus-fun" "\ Insert a random X-Face header from `gnus-x-face-directory'." t nil) - (autoload 'gnus-x-face-from-file "gnus-fun" "\ Insert an X-Face header based on an image FILE. Depending on `gnus-convert-image-to-x-face-command' it may accept different input formats. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'gnus-face-from-file "gnus-fun" "\ Return a Face header based on an image FILE. Depending on `gnus-convert-image-to-face-command' it may accept different input formats. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'gnus-convert-face-to-png "gnus-fun" "\ Convert FACE (which is base64-encoded) to a PNG. The PNG is returned as a string. -\(fn FACE)" nil nil) - +(fn FACE)" nil nil) (autoload 'gnus-convert-png-to-face "gnus-fun" "\ Convert FILE to a Face. FILE should be a PNG file that's 48x48 and smaller than or equal to 726 bytes. -\(fn FILE)" nil nil) - +(fn FILE)" nil nil) (autoload 'gnus-random-face "gnus-fun" "\ Return randomly chosen Face from `gnus-face-directory'. Files matching `gnus-face-omit-files' are not considered." t nil) - (autoload 'gnus-insert-random-face-header "gnus-fun" "\ Insert a random Face header from `gnus-face-directory'." nil nil) - (register-definition-prefixes "gnus-fun" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-gravatar" "gnus/gnus-gravatar.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from gnus/gnus-gravatar.el (autoload 'gnus-treat-from-gravatar "gnus-gravatar" "\ Display gravatar in the From header. If gravatar is already displayed, remove it. -\(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil) - +(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil) (autoload 'gnus-treat-mail-gravatar "gnus-gravatar" "\ Display gravatars in the Cc and To headers. If gravatars are already displayed, remove them. -\(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil) - +(fn &optional FORCE)" '(gnus-article-mode gnus-summary-mode) nil) (register-definition-prefixes "gnus-gravatar" '("gnus-gravatar-")) -;;;*** -;;;### (autoloads nil "gnus-group" "gnus/gnus-group.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-group.el (autoload 'gnus-fetch-group "gnus-group" "\ @@ -15037,99 +13502,74 @@ Start Gnus if necessary and enter GROUP. If ARTICLES, display those articles. Returns whether the fetching was successful or not. -\(fn GROUP &optional ARTICLES)" t nil) - +(fn GROUP &optional ARTICLES)" t nil) (autoload 'gnus-fetch-group-other-frame "gnus-group" "\ Pop up a frame and enter GROUP. -\(fn GROUP)" t nil) - +(fn GROUP)" t nil) (autoload 'gnus-read-ephemeral-emacs-bug-group "gnus-group" "\ Browse Emacs bug reports with IDS in an ephemeral group. The arguments have the same meaning as those of `gnus-read-ephemeral-bug-group', which see. -\(fn IDS &optional WINDOW-CONF)" t nil) - +(fn IDS &optional WINDOW-CONF)" t nil) (register-definition-prefixes "gnus-group" '(":keymap" "gnus-")) -;;;*** -;;;### (autoloads nil "gnus-html" "gnus/gnus-html.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-html.el (autoload 'gnus-article-html "gnus-html" "\ -\(fn &optional HANDLE)" nil nil) - +(fn &optional HANDLE)" nil nil) (autoload 'gnus-html-prefetch-images "gnus-html" "\ -\(fn SUMMARY)" nil nil) - +(fn SUMMARY)" nil nil) (register-definition-prefixes "gnus-html" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-icalendar" "gnus/gnus-icalendar.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from gnus/gnus-icalendar.el (autoload 'gnus-icalendar-mm-inline "gnus-icalendar" "\ -\(fn HANDLE)" nil nil) - +(fn HANDLE)" nil nil) (register-definition-prefixes "gnus-icalendar" '("gnus-icalendar")) -;;;*** -;;;### (autoloads nil "gnus-int" "gnus/gnus-int.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-int.el (register-definition-prefixes "gnus-int" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-kill" "gnus/gnus-kill.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-kill.el (defalias 'gnus-batch-kill 'gnus-batch-score) - (autoload 'gnus-batch-score "gnus-kill" "\ Run batched scoring. Usage: emacs -batch -l ~/.emacs -l gnus -f gnus-batch-score" t nil) - (register-definition-prefixes "gnus-kill" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-logic" "gnus/gnus-logic.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-logic.el (register-definition-prefixes "gnus-logic" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-mh" "gnus/gnus-mh.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-mh.el (register-definition-prefixes "gnus-mh" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-ml" "gnus/gnus-ml.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-ml.el (autoload 'turn-on-gnus-mailing-list-mode "gnus-ml" nil nil nil) - (autoload 'gnus-mailing-list-insinuate "gnus-ml" "\ Setup group parameters from List-Post header. If FORCE is non-nil, replace the old ones. -\(fn &optional FORCE)" t nil) - +(fn &optional FORCE)" t nil) (autoload 'gnus-mailing-list-mode "gnus-ml" "\ Minor mode for providing mailing-list commands. @@ -15150,13 +13590,10 @@ evaluate `gnus-mailing-list-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "gnus-ml" '("gnus-mailing-list-")) -;;;*** -;;;### (autoloads nil "gnus-mlspl" "gnus/gnus-mlspl.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-mlspl.el (autoload 'gnus-group-split-setup "gnus-mlspl" "\ @@ -15181,8 +13618,7 @@ elaborate fancy splits may also be useful to split mail that doesn't match any of the group-specified splitting rules. See `gnus-group-split-fancy' for details. -\(fn &optional AUTO-UPDATE CATCH-ALL)" t nil) - +(fn &optional AUTO-UPDATE CATCH-ALL)" t nil) (autoload 'gnus-group-split-update "gnus-mlspl" "\ Computes `nnmail-split-fancy' from group params and CATCH-ALL. It does this by calling (gnus-group-split-fancy nil nil CATCH-ALL). @@ -15190,19 +13626,17 @@ It does this by calling (gnus-group-split-fancy nil nil CATCH-ALL). If CATCH-ALL is nil, `gnus-group-split-default-catch-all-group' is used instead. This variable is set by `gnus-group-split-setup'. -\(fn &optional CATCH-ALL)" t nil) - +(fn &optional CATCH-ALL)" t nil) (autoload 'gnus-group-split "gnus-mlspl" "\ Use information from group parameters in order to split mail. See `gnus-group-split-fancy' for more information. `gnus-group-split' is a valid value for `nnmail-split-methods'." nil nil) - (autoload 'gnus-group-split-fancy "gnus-mlspl" "\ Uses information from group parameters in order to split mail. It can be embedded into `nnmail-split-fancy' lists with the SPLIT -\(: gnus-group-split-fancy GROUPS NO-CROSSPOST CATCH-ALL) +(: gnus-group-split-fancy GROUPS NO-CROSSPOST CATCH-ALL) GROUPS may be a regular expression or a list of group names, that will be used to select candidate groups. If it is omitted or nil, all @@ -15231,31 +13665,28 @@ as the last element of a `|' SPLIT. For example, given the following group parameters: nnml:mail.bar: -\((to-address . \"bar@femail.com\") +((to-address . \"bar@femail.com\") (split-regexp . \".*@femail\\\\.com\")) nnml:mail.foo: -\((to-list . \"foo@nowhere.gov\") +((to-list . \"foo@nowhere.gov\") (extra-aliases \"foo@localhost\" \"foo-redist@home\") (split-exclude \"bugs-foo\" \"rambling-foo\") (admin-address . \"foo-request@nowhere.gov\")) nnml:mail.others: -\((split-spec . catch-all)) +((split-spec . catch-all)) Calling (gnus-group-split-fancy nil nil \"mail.others\") returns: -\(| (& (any \"\\\\(bar@femail\\\\.com\\\\|.*@femail\\\\.com\\\\)\" +(| (& (any \"\\\\(bar@femail\\\\.com\\\\|.*@femail\\\\.com\\\\)\" \"mail.bar\") (any \"\\\\(foo@nowhere\\\\.gov\\\\|foo@localhost\\\\|foo-redist@home\\\\)\" - \"bugs-foo\" - \"rambling-foo\" \"mail.foo\")) \"mail.others\") -\(fn &optional GROUPS NO-CROSSPOST CATCH-ALL)" nil nil) - +(fn &optional GROUPS NO-CROSSPOST CATCH-ALL)" nil nil) (register-definition-prefixes "gnus-mlspl" '("gnus-group-split-")) -;;;*** -;;;### (autoloads nil "gnus-msg" "gnus/gnus-msg.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-msg.el (autoload 'gnus-msg-mail "gnus-msg" "\ @@ -15265,26 +13696,19 @@ Gcc: header for archiving purposes. If Gnus isn't running, a plain `message-mail' setup is used instead. -\(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-ACTION YANK-ACTION SEND-ACTIONS RETURN-ACTION)" t nil) - +(fn &optional TO SUBJECT OTHER-HEADERS CONTINUE SWITCH-ACTION YANK-ACTION SEND-ACTIONS RETURN-ACTION)" t nil) (autoload 'gnus-button-mailto "gnus-msg" "\ Mail to ADDRESS. -\(fn ADDRESS)" nil nil) - +(fn ADDRESS)" nil nil) (autoload 'gnus-button-reply "gnus-msg" "\ Like `message-reply'. -\(fn &optional TO-ADDRESS WIDE)" t nil) - +(fn &optional TO-ADDRESS WIDE)" t nil) (define-mail-user-agent 'gnus-user-agent 'gnus-msg-mail 'message-send-and-exit 'message-kill-buffer 'message-send-hook) - (register-definition-prefixes "gnus-msg" '(":prefix" "gnus-")) -;;;*** -;;;### (autoloads nil "gnus-notifications" "gnus/gnus-notifications.el" -;;;;;; (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-notifications.el (autoload 'gnus-notifications "gnus-notifications" "\ @@ -15295,31 +13719,23 @@ notification using `notifications-notify' for it. This is typically a function to add in `gnus-after-getting-new-news-hook'" nil nil) - (register-definition-prefixes "gnus-notifications" '("gnus-notifications-")) -;;;*** -;;;### (autoloads nil "gnus-picon" "gnus/gnus-picon.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-picon.el (autoload 'gnus-treat-from-picon "gnus-picon" "\ Display picons in the From header. If picons are already displayed, remove them." '(gnus-article-mode gnus-summary-mode) nil) - (autoload 'gnus-treat-mail-picon "gnus-picon" "\ Display picons in the Cc and To headers. If picons are already displayed, remove them." '(gnus-article-mode gnus-summary-mode) nil) - (autoload 'gnus-treat-newsgroups-picon "gnus-picon" "\ Display picons in the Newsgroups and Followup-To headers. If picons are already displayed, remove them." '(gnus-article-mode gnus-summary-mode) nil) - (register-definition-prefixes "gnus-picon" '("gnus-picon-")) -;;;*** -;;;### (autoloads nil "gnus-range" "gnus/gnus-range.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-range.el (autoload 'gnus-sorted-difference "gnus-range" "\ @@ -15327,232 +13743,172 @@ Return a list of elements of LIST1 that do not appear in LIST2. Both lists have to be sorted over <. The tail of LIST1 is not copied. -\(fn LIST1 LIST2)" nil nil) - +(fn LIST1 LIST2)" nil nil) (autoload 'gnus-sorted-ndifference "gnus-range" "\ Return a list of elements of LIST1 that do not appear in LIST2. Both lists have to be sorted over <. LIST1 is modified. -\(fn LIST1 LIST2)" nil nil) - +(fn LIST1 LIST2)" nil nil) (autoload 'gnus-sorted-complement "gnus-range" "\ Return a list of elements that are in LIST1 or LIST2 but not both. Both lists have to be sorted over <. -\(fn LIST1 LIST2)" nil nil) - +(fn LIST1 LIST2)" nil nil) (autoload 'gnus-intersection "gnus-range" "\ -\(fn LIST1 LIST2)" nil nil) - +(fn LIST1 LIST2)" nil nil) (make-obsolete 'gnus-intersection 'seq-intersection '"28.1") - (autoload 'gnus-sorted-intersection "gnus-range" "\ Return intersection of LIST1 and LIST2. LIST1 and LIST2 have to be sorted over <. -\(fn LIST1 LIST2)" nil nil) - +(fn LIST1 LIST2)" nil nil) (defalias 'gnus-set-sorted-intersection 'gnus-sorted-nintersection) - (autoload 'gnus-sorted-nintersection "gnus-range" "\ Return intersection of LIST1 and LIST2 by modifying cdr pointers of LIST1. LIST1 and LIST2 have to be sorted over <. -\(fn LIST1 LIST2)" nil nil) - +(fn LIST1 LIST2)" nil nil) (autoload 'gnus-sorted-union "gnus-range" "\ Return union of LIST1 and LIST2. LIST1 and LIST2 have to be sorted over <. -\(fn LIST1 LIST2)" nil nil) - +(fn LIST1 LIST2)" nil nil) (autoload 'gnus-sorted-nunion "gnus-range" "\ Return union of LIST1 and LIST2 by modifying cdr pointers of LIST1. LIST1 and LIST2 have to be sorted over <. -\(fn LIST1 LIST2)" nil nil) - +(fn LIST1 LIST2)" nil nil) (autoload 'gnus-add-to-sorted-list "gnus-range" "\ Add NUM into sorted LIST by side effect. -\(fn LIST NUM)" nil nil) - +(fn LIST NUM)" nil nil) (register-definition-prefixes "gnus-range" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-registry" "gnus/gnus-registry.el" (0 -;;;;;; 0 0 0)) ;;; Generated autoloads from gnus/gnus-registry.el (autoload 'gnus-registry-initialize "gnus-registry" "\ Initialize the Gnus registry." t nil) - (register-definition-prefixes "gnus-registry" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-rfc1843" "gnus/gnus-rfc1843.el" (0 0 -;;;;;; 0 0)) ;;; Generated autoloads from gnus/gnus-rfc1843.el (register-definition-prefixes "gnus-rfc1843" '("rfc1843-")) -;;;*** -;;;### (autoloads nil "gnus-rmail" "gnus/gnus-rmail.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-rmail.el (register-definition-prefixes "gnus-rmail" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-salt" "gnus/gnus-salt.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-salt.el (register-definition-prefixes "gnus-salt" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-score" "gnus/gnus-score.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-score.el (register-definition-prefixes "gnus-score" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-search" "gnus/gnus-search.el" (0 0 0 -;;;;;; 0)) ;;; Generated autoloads from gnus/gnus-search.el (register-definition-prefixes "gnus-search" '("gnus-search-")) -;;;*** -;;;### (autoloads nil "gnus-sieve" "gnus/gnus-sieve.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-sieve.el (autoload 'gnus-sieve-update "gnus-sieve" "\ Update the Sieve script in gnus-sieve-file, by replacing the region between gnus-sieve-region-start and gnus-sieve-region-end with -\(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost), then +(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost), then execute gnus-sieve-update-shell-command. See the documentation for these variables and functions for details." t nil) - (autoload 'gnus-sieve-generate "gnus-sieve" "\ Generate the Sieve script in gnus-sieve-file, by replacing the region between gnus-sieve-region-start and gnus-sieve-region-end with -\(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost). +(gnus-sieve-script gnus-sieve-select-method gnus-sieve-crosspost). See the documentation for these variables and functions for details." t nil) - (autoload 'gnus-sieve-article-add-rule "gnus-sieve" nil '(gnus-article-mode gnus-summary-mode) nil) - (register-definition-prefixes "gnus-sieve" '("gnus-sieve-")) -;;;*** -;;;### (autoloads nil "gnus-spec" "gnus/gnus-spec.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-spec.el (autoload 'gnus-update-format "gnus-spec" "\ Update the format specification near point. -\(fn VAR)" t nil) - +(fn VAR)" t nil) (register-definition-prefixes "gnus-spec" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-srvr" "gnus/gnus-srvr.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-srvr.el (register-definition-prefixes "gnus-srvr" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-start" "gnus/gnus-start.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-start.el (autoload 'gnus-declare-backend "gnus-start" "\ Declare back end NAME with ABILITIES as a Gnus back end. -\(fn NAME &rest ABILITIES)" nil nil) - +(fn NAME &rest ABILITIES)" nil nil) (register-definition-prefixes "gnus-start" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-sum" "gnus/gnus-sum.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-sum.el (autoload 'gnus-summary-bookmark-jump "gnus-sum" "\ Handler function for record returned by `gnus-summary-bookmark-make-record'. BOOKMARK is a bookmark name or a bookmark record. -\(fn BOOKMARK)" nil nil) - +(fn BOOKMARK)" nil nil) (register-definition-prefixes "gnus-sum" '(":keymap" "gnus-")) -;;;*** -;;;### (autoloads nil "gnus-topic" "gnus/gnus-topic.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-topic.el (register-definition-prefixes "gnus-topic" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-undo" "gnus/gnus-undo.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-undo.el (register-definition-prefixes "gnus-undo" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-util" "gnus/gnus-util.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-util.el (register-definition-prefixes "gnus-util" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-uu" "gnus/gnus-uu.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-uu.el (register-definition-prefixes "gnus-uu" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-vm" "gnus/gnus-vm.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-vm.el (register-definition-prefixes "gnus-vm" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnus-win" "gnus/gnus-win.el" (0 0 0 0)) ;;; Generated autoloads from gnus/gnus-win.el (autoload 'gnus-add-configuration "gnus-win" "\ Add the window configuration CONF to `gnus-buffer-configuration'. -\(fn CONF)" nil nil) - +(fn CONF)" nil nil) (register-definition-prefixes "gnus-win" '("gnus-")) -;;;*** -;;;### (autoloads nil "gnutls" "net/gnutls.el" (0 0 0 0)) ;;; Generated autoloads from net/gnutls.el (register-definition-prefixes "gnutls" '("gnutls-" "open-gnutls-stream")) -;;;*** -;;;### (autoloads nil "gomoku" "play/gomoku.el" (0 0 0 0)) ;;; Generated autoloads from play/gomoku.el (autoload 'gomoku "gomoku" "\ @@ -15574,13 +13930,10 @@ Gomoku game, and ought to be upgraded to use the full modern rules. Use \\[describe-mode] for more info. -\(fn &optional N M)" t nil) - +(fn &optional N M)" t nil) (register-definition-prefixes "gomoku" '("gomoku-")) -;;;*** -;;;### (autoloads nil "goto-addr" "net/goto-addr.el" (0 0 0 0)) ;;; Generated autoloads from net/goto-addr.el (autoload 'goto-address-at-point "goto-addr" "\ @@ -15589,8 +13942,7 @@ Send mail to address at point. See documentation for `goto-address-find-address-at-point'. If no address is found there, then load the URL at or before point. -\(fn &optional EVENT)" t nil) - +(fn &optional EVENT)" t nil) (autoload 'goto-address "goto-addr" "\ Sets up goto-address functionality in the current buffer. Allows user to use mouse/keyboard command to click to go to a URL @@ -15601,7 +13953,6 @@ only on URLs and e-mail addresses. Also fontifies the buffer appropriately (see `goto-address-fontify-p' and `goto-address-highlight-p' for more information)." t nil) (put 'goto-address 'safe-local-eval-function t) - (autoload 'goto-address-mode "goto-addr" "\ Minor mode to buttonize URLs and e-mail addresses in the current buffer. @@ -15619,10 +13970,8 @@ evaluate `goto-address-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (put 'global-goto-address-mode 'globalized-minor-mode t) - (defvar global-goto-address-mode nil "\ Non-nil if Global Goto-Address mode is enabled. See the `global-goto-address-mode' command @@ -15630,9 +13979,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `global-goto-address-mode'.") - (custom-autoload 'global-goto-address-mode "goto-addr" nil) - (autoload 'global-goto-address-mode "goto-addr" "\ Toggle Goto-Address mode in all buffers. With prefix ARG, enable Global Goto-Address mode if ARG is positive; @@ -15647,8 +13994,7 @@ Goto-Address mode is enabled in all buffers where See `goto-address-mode' for more information on Goto-Address mode. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'goto-address-prog-mode "goto-addr" "\ Like `goto-address-mode', but only for comments and strings. @@ -15667,13 +14013,33 @@ evaluate `goto-address-prog-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "goto-addr" '("goto-addr")) -;;;*** -;;;### (autoloads nil "gravatar" "image/gravatar.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/wisent/grammar.el + +(autoload 'wisent-grammar-mode "semantic/wisent/grammar" "\ +Major mode for editing Wisent grammars. + +(fn)" t nil) +(register-definition-prefixes "semantic/wisent/grammar" '("semantic-grammar-" "wisent-")) + + +;;; Generated autoloads from cedet/semantic/bovine/grammar.el + +(autoload 'bovine-grammar-mode "semantic/bovine/grammar" "\ +Major mode for editing Bovine grammars. + +(fn)" t nil) +(register-definition-prefixes "semantic/bovine/grammar" '("bovine-" "semantic-grammar-")) + + +;;; Generated autoloads from cedet/semantic/grammar.el + +(register-definition-prefixes "semantic/grammar" '("semantic-")) + + ;;; Generated autoloads from image/gravatar.el (autoload 'gravatar-retrieve "gravatar" "\ @@ -15682,27 +14048,21 @@ When finished, call CALLBACK as (apply CALLBACK GRAVATAR CBARGS), where GRAVATAR is either an image descriptor, or the symbol `error' if the retrieval failed. -\(fn MAIL-ADDRESS CALLBACK &optional CBARGS)" nil nil) - +(fn MAIL-ADDRESS CALLBACK &optional CBARGS)" nil nil) (autoload 'gravatar-retrieve-synchronously "gravatar" "\ Synchronously retrieve a gravatar for MAIL-ADDRESS. Value is either an image descriptor, or the symbol `error' if the retrieval failed. -\(fn MAIL-ADDRESS)" nil nil) - +(fn MAIL-ADDRESS)" nil nil) (register-definition-prefixes "gravatar" '("gravatar-")) -;;;*** -;;;### (autoloads nil "grep" "progmodes/grep.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/grep.el (defvar grep-window-height nil "\ Number of lines in a grep window. If nil, use `compilation-window-height'.") - (custom-autoload 'grep-window-height "grep" t) - (defvar grep-command nil "\ The default grep command for \\[grep]. If the grep program used supports an option to always include file names @@ -15712,9 +14072,7 @@ include it when specifying `grep-command'. In interactive usage, the actual value of this variable is set up by `grep-compute-defaults'; to change the default value, use \\[customize] or call the function `grep-apply-setting'.") - (custom-autoload 'grep-command "grep" nil) - (defvar grep-find-command nil "\ The default find command for \\[grep-find]. In interactive usage, the actual value of this variable is set up @@ -15725,32 +14083,24 @@ This variable can either be a string, or a cons of the form (COMMAND . POSITION). In the latter case, COMMAND will be used as the default command, and point will be placed at POSITION for easier editing.") - (custom-autoload 'grep-find-command "grep" nil) - (defvar grep-setup-hook nil "\ List of hook functions run by `grep-process-setup' (see `run-hooks').") - (custom-autoload 'grep-setup-hook "grep" t) - (defconst grep-regexp-alist `((,(concat "^\\(?:" "\\(?1:[^\0\n]+\\)\\(?3:\0\\)\\(?2:[0-9]+\\):" "\\|" "\\(?1:" "\\(?:[a-zA-Z]:\\)?" "[^\n:]+?[^\n/:]\\):[\11 ]*\\(?2:[1-9][0-9]*\\)[\11 ]*:" "\\)") 1 2 (,(lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face grep-match-face))) (when mbeg (- mbeg beg))))) \, (lambda nil (when grep-highlight-matches (let* ((beg (match-end 0)) (end (save-excursion (goto-char beg) (line-end-position))) (mbeg (text-property-any beg end 'font-lock-face grep-match-face)) (mend (and mbeg (next-single-property-change mbeg 'font-lock-face nil end)))) (when mend (- mend beg 1)))))) nil nil (3 '(face nil display ":"))) ("^Binary file \\(.+\\) matches" 1 nil nil 0 1)) "\ Regexp used to match grep hits. See `compilation-error-regexp-alist' for format details.") - (defvar grep-program (purecopy "grep") "\ The default grep program for `grep-command' and `grep-find-command'. This variable's value takes effect when `grep-compute-defaults' is called.") - (defvar find-program (purecopy "find") "\ The default find program. This is used by commands like `grep-find-command', `find-dired' and others.") - (defvar xargs-program (purecopy "xargs") "\ The default xargs program for `grep-find-command'. See `grep-find-use-xargs'. This variable's value takes effect when `grep-compute-defaults' is called.") - (defvar grep-find-use-xargs nil "\ How to invoke find and grep. If `exec', use `find -exec {} ;'. @@ -15760,31 +14110,24 @@ If `gnu-sort', use `find -print0', `sort -z' and `xargs -0'. Any other value means to use `find -print' and `xargs'. This variable's value takes effect when `grep-compute-defaults' is called.") - (custom-autoload 'grep-find-use-xargs "grep" nil) - (defvar grep-history nil "\ History list for grep.") - (defvar grep-find-history nil "\ History list for `grep-find'.") - (autoload 'grep-process-setup "grep" "\ Setup compilation variables and buffer for `grep'. Set up `compilation-exit-message-function' and run `grep-setup-hook'." nil nil) - (autoload 'grep-compute-defaults "grep" "\ Compute the defaults for the `grep' command. The value depends on `grep-command', `grep-template', `grep-use-null-device', `grep-find-command', `grep-find-template', `grep-use-null-filename-separator', `grep-find-use-xargs', `grep-highlight-matches', and `grep-quoting-style'." nil nil) - (autoload 'grep-mode "grep" "\ Sets `grep-last-buffer' and `compilation-window-height'. -\(fn)" nil nil) - +(fn)" nil nil) (autoload 'grep "grep" "\ Run Grep with user-specified COMMAND-ARGS. The output from the command goes to the \"*grep*\" buffer. @@ -15807,8 +14150,7 @@ tag the cursor is over, substituting it into the last Grep command in the Grep command history (or into `grep-command' if that history list is empty). -\(fn COMMAND-ARGS)" t nil) - +(fn COMMAND-ARGS)" t nil) (autoload 'grep-find "grep" "\ Run grep via find, with user-specified args COMMAND-ARGS. Collect output in the \"*grep*\" buffer. @@ -15818,10 +14160,8 @@ to find the text that grep hits refer to. This command uses a special history list for its arguments, so you can easily repeat a find command. -\(fn COMMAND-ARGS)" t nil) - +(fn COMMAND-ARGS)" t nil) (defalias 'find-grep #'grep-find) - (autoload 'lgrep "grep" "\ Run grep, searching for REGEXP in FILES in directory DIR. The search is limited to file names matching shell pattern FILES. @@ -15843,8 +14183,7 @@ This command shares argument histories with \\[rgrep] and \\[grep]. If CONFIRM is non-nil, the user will be given an opportunity to edit the command before it's run. -\(fn REGEXP &optional FILES DIR CONFIRM)" t nil) - +(fn REGEXP &optional FILES DIR CONFIRM)" t nil) (autoload 'rgrep "grep" "\ Recursively grep for REGEXP in FILES in directory tree rooted at DIR. The search is limited to file names matching shell pattern FILES. @@ -15870,8 +14209,7 @@ to specify a command to run. If CONFIRM is non-nil, the user will be given an opportunity to edit the command before it's run. -\(fn REGEXP &optional FILES DIR CONFIRM)" t nil) - +(fn REGEXP &optional FILES DIR CONFIRM)" t nil) (autoload 'zrgrep "grep" "\ Recursively grep for REGEXP in gzipped FILES in tree rooted at DIR. Like `rgrep' but uses `zgrep' for `grep-program', sets the default @@ -15880,22 +14218,21 @@ file name to `*.gz', and sets `grep-highlight-matches' to `always'. If CONFIRM is non-nil, the user will be given an opportunity to edit the command before it's run. -\(fn REGEXP &optional FILES DIR CONFIRM TEMPLATE)" t nil) - +(fn REGEXP &optional FILES DIR CONFIRM TEMPLATE)" t nil) (defalias 'rzgrep #'zrgrep) - (register-definition-prefixes "grep" '("grep-" "kill-grep" "rgrep-")) -;;;*** -;;;### (autoloads nil "gssapi" "gnus/gssapi.el" (0 0 0 0)) +;;; Generated autoloads from cedet/semantic/symref/grep.el + +(register-definition-prefixes "semantic/symref/grep" '("semantic-symref-")) + + ;;; Generated autoloads from gnus/gssapi.el (register-definition-prefixes "gssapi" '("gssapi-program" "open-gssapi-stream")) -;;;*** -;;;### (autoloads nil "gud" "progmodes/gud.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/gud.el (autoload 'gud-gdb "gud" "\ @@ -15909,22 +14246,19 @@ will run in *gud-PID*, otherwise it will run in *gud*; in these cases the initial working directory is the `default-directory' of the buffer in which this command was invoked. -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (autoload 'sdb "gud" "\ Run sdb on program FILE in buffer *gud-FILE*. The directory containing FILE becomes the initial working directory and source-file directory for your debugger. -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (autoload 'dbx "gud" "\ Run dbx on program FILE in buffer *gud-FILE*. The directory containing FILE becomes the initial working directory and source-file directory for your debugger. -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (autoload 'xdb "gud" "\ Run xdb on program FILE in buffer *gud-FILE*. The directory containing FILE becomes the initial working directory @@ -15933,8 +14267,7 @@ and source-file directory for your debugger. You can set the variable `gud-xdb-directories' to a list of program source directories if your program contains sources from more than one directory. -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (autoload 'perldb "gud" "\ Debug a perl program with gud. Interactively, this will prompt you for a command line. @@ -15945,8 +14278,7 @@ Noninteractively, COMMAND-LINE should be on the form The directory containing the perl program becomes the initial working directory and source-file directory for your debugger. -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (autoload 'pdb "gud" "\ Run COMMAND-LINE in the `*gud-FILE*' buffer to debug Python programs. @@ -15958,15 +14290,13 @@ If called interactively, the command line will be prompted for. The directory containing this file becomes the initial working directory and source-file directory for your debugger. -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (autoload 'guiler "gud" "\ Run guiler on program FILE in buffer `*gud-FILE*'. The directory containing FILE becomes the initial working directory and source-file directory for your debugger. -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (autoload 'jdb "gud" "\ Run jdb with command line COMMAND-LINE in a buffer. The buffer is named \"*gud*\" if no initial class is given or @@ -15981,13 +14311,11 @@ original source file access method. For general information about commands available to control jdb from gud, see `gud-mode'. -\(fn COMMAND-LINE)" t nil) - +(fn COMMAND-LINE)" t nil) (autoload 'gdb-script-mode "gud" "\ Major mode for editing GDB scripts. -\(fn)" t nil) - +(fn)" t nil) (defvar gud-tooltip-mode nil "\ Non-nil if Gud-Tooltip mode is enabled. See the `gud-tooltip-mode' command @@ -15995,9 +14323,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `gud-tooltip-mode'.") - (custom-autoload 'gud-tooltip-mode "gud" nil) - (autoload 'gud-tooltip-mode "gud" "\ Toggle the display of GUD tooltips. @@ -16015,13 +14341,10 @@ evaluate `(default-value \\='gud-tooltip-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "gud" '("gdb-" "gud-")) -;;;*** -;;;### (autoloads nil "gv" "emacs-lisp/gv.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/gv.el (autoload 'gv-get "gv" "\ @@ -16034,8 +14357,7 @@ with a (not necessarily copyable) Elisp expression that returns the value to set it to. DO must return an Elisp expression. -\(fn PLACE DO)" nil nil) - +(fn PLACE DO)" nil nil) (autoload 'gv-letplace "gv" "\ Build the code manipulating the generalized variable PLACE. GETTER will be bound to a copyable expression that returns the value @@ -16047,35 +14369,25 @@ and SETTER. The returned value will then be an Elisp expression that first evaluates all the parts of PLACE that can be evaluated and then runs E. -\(fn (GETTER SETTER) PLACE &rest BODY)" nil t) - +(fn (GETTER SETTER) PLACE &rest BODY)" nil t) (function-put 'gv-letplace 'lisp-indent-function '2) - (autoload 'gv-define-expander "gv" "\ Use HANDLER to handle NAME as a generalized var. NAME is a symbol: the name of a function, macro, or special form. HANDLER is a function which takes an argument DO followed by the same arguments as NAME. DO is a function as defined in `gv-get'. -\(fn NAME HANDLER)" nil t) - +(fn NAME HANDLER)" nil t) (function-put 'gv-define-expander 'lisp-indent-function '1) - (autoload 'gv--defun-declaration "gv" "\ -\(fn SYMBOL NAME ARGS HANDLER &optional FIX)" nil nil) - +(fn SYMBOL NAME ARGS HANDLER &optional FIX)" nil nil) (defsubst gv--expander-defun-declaration (&rest args) (apply #'gv--defun-declaration 'gv-expander args)) - (defsubst gv--setter-defun-declaration (&rest args) (apply #'gv--defun-declaration 'gv-setter args)) - (or (assq 'gv-expander defun-declarations-alist) (let ((x (list 'gv-expander #'gv--expander-defun-declaration))) (push x macro-declarations-alist) (push x defun-declarations-alist))) - (or (assq 'gv-setter defun-declarations-alist) (push (list 'gv-setter #'gv--setter-defun-declaration) defun-declarations-alist)) - (let ((spec (get 'compiler-macro 'edebug-declaration-spec))) (put 'gv-expander 'edebug-declaration-spec spec) (put 'gv-setter 'edebug-declaration-spec spec)) - (autoload 'gv-define-setter "gv" "\ Define a setter method for generalized variable NAME. This macro is an easy-to-use substitute for `gv-define-expander' that works @@ -16088,10 +14400,8 @@ which can do arbitrary things, whereas the other arguments are all guaranteed to be pure and copyable. Example use: (gv-define-setter aref (v a i) \\=`(aset ,a ,i ,v)) -\(fn NAME ARGLIST &rest BODY)" nil t) - +(fn NAME ARGLIST &rest BODY)" nil t) (function-put 'gv-define-setter 'lisp-indent-function '2) - (autoload 'gv-define-simple-setter "gv" "\ Define a simple setter method for generalized variable NAME. This macro is an easy-to-use substitute for `gv-define-expander' that works @@ -16105,8 +14415,7 @@ instead the assignment is turned into something equivalent to temp) so as to preserve the semantics of `setf'. -\(fn NAME SETTER &optional FIX-RETURN)" nil t) - +(fn NAME SETTER &optional FIX-RETURN)" nil t) (autoload 'setf "gv" "\ Set each PLACE to the value of its VAL. This is a generalized version of `setq'; the PLACEs may be symbolic @@ -16114,10 +14423,8 @@ references such as (car x) or (aref x i), as well as plain symbols. For example, (setf (cadr x) y) is equivalent to (setcar (cdr x) y). The return value is the last VAL in the list. -\(fn PLACE VAL PLACE VAL ...)" nil t) - +(fn PLACE VAL PLACE VAL ...)" nil t) (def-edebug-elem-spec 'gv-place '(form)) - (autoload 'gv-ref "gv" "\ Return a reference to PLACE. This is like the `&' operator of the C language. @@ -16125,13 +14432,10 @@ Note: this only works reliably with lexical binding mode, except for very simple PLACEs such as (symbol-function \\='foo) which will also work in dynamic binding mode. -\(fn PLACE)" nil t) - +(fn PLACE)" nil t) (register-definition-prefixes "gv" '("gv-")) -;;;*** -;;;### (autoloads nil "handwrite" "play/handwrite.el" (0 0 0 0)) ;;; Generated autoloads from play/handwrite.el (autoload 'handwrite "handwrite" "\ @@ -16143,89 +14447,81 @@ Variables: `handwrite-linespace' (default 12) `handwrite-fontsize' (default 11) `handwrite-numlines' (default 60) `handwrite-pagenumbering' (default nil)" t nil) - (register-definition-prefixes "handwrite" '("handwrite-" "menu-bar-handwrite-map")) -;;;*** -;;;### (autoloads nil "hanja-util" "language/hanja-util.el" (0 0 -;;;;;; 0 0)) +;;; Generated autoloads from leim/quail/hangul.el + +(autoload 'hangul-input-method-activate "quail/hangul" "\ +Activate Hangul input method INPUT-METHOD. +FUNC is a function to handle input key. +HELP-TEXT is a text set in `hangul-input-method-help-text'. + +(fn INPUT-METHOD FUNC HELP-TEXT &rest ARGS)" nil nil) +(register-definition-prefixes "quail/hangul" '("alphabetp" "hangul" "notzerop")) + + ;;; Generated autoloads from language/hanja-util.el (register-definition-prefixes "hanja-util" '("han")) -;;;*** -;;;### (autoloads nil "hanoi" "play/hanoi.el" (0 0 0 0)) ;;; Generated autoloads from play/hanoi.el (autoload 'hanoi "hanoi" "\ Towers of Hanoi diversion. Use NRINGS rings. -\(fn NRINGS)" t nil) - +(fn NRINGS)" t nil) (autoload 'hanoi-unix "hanoi" "\ Towers of Hanoi, UNIX doomsday version. Displays 32-ring towers that have been progressing at one move per second since 1970-01-01 00:00:00 GMT. Repent before ring 31 moves." t nil) - (autoload 'hanoi-unix-64 "hanoi" "\ Like `hanoi-unix', but pretend to have a 64-bit clock. This is, necessarily (as of Emacs 20.3), a crock. When the `current-time' interface is made s2G-compliant, hanoi.el will need to be updated." t nil) - (register-definition-prefixes "hanoi" '("hanoi-")) -;;;*** -;;;### (autoloads nil "hashcash" "mail/hashcash.el" (0 0 0 0)) ;;; Generated autoloads from mail/hashcash.el (autoload 'hashcash-insert-payment "hashcash" "\ Insert X-Payment and X-Hashcash headers with a payment for ARG. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (autoload 'hashcash-insert-payment-async "hashcash" "\ Insert X-Payment and X-Hashcash headers with a payment for ARG Only start calculation. Results are inserted when ready. -\(fn ARG)" t nil) - +(fn ARG)" t nil) (autoload 'hashcash-verify-payment "hashcash" "\ Verify a hashcash payment. -\(fn TOKEN &optional RESOURCE AMOUNT)" nil nil) - +(fn TOKEN &optional RESOURCE AMOUNT)" nil nil) (autoload 'mail-add-payment "hashcash" "\ Add X-Payment: and X-Hashcash: headers with a hashcash payment for each recipient address. Prefix arg sets default payment temporarily. Set ASYNC to t to start asynchronous calculation. (See `mail-add-payment-async'). -\(fn &optional ARG ASYNC)" t nil) - +(fn &optional ARG ASYNC)" t nil) (autoload 'mail-add-payment-async "hashcash" "\ Add X-Payment: and X-Hashcash: headers with a hashcash payment for each recipient address. Prefix arg sets default payment temporarily. Calculation is asynchronous. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'mail-check-payment "hashcash" "\ Look for a valid X-Payment: or X-Hashcash: header. Prefix arg sets default accept amount temporarily. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "hashcash" '("hashcash-")) -;;;*** -;;;### (autoloads nil "help-at-pt" "help-at-pt.el" (0 0 0 0)) ;;; Generated autoloads from help-at-pt.el (autoload 'help-at-pt-string "help-at-pt" "\ @@ -16236,14 +14532,12 @@ If KBD is non-nil, `kbd-help' is used instead, and any `help-echo' property is ignored. In this case, the return value can also be t, if that is the value of the `kbd-help' property. -\(fn &optional KBD)" nil nil) - +(fn &optional KBD)" nil nil) (autoload 'help-at-pt-kbd-string "help-at-pt" "\ Return the keyboard help string at point. If the `kbd-help' text or overlay property at point produces a string, return it. Otherwise, use the `help-echo' property. If this produces no string either, return nil." nil nil) - (autoload 'display-local-help "help-at-pt" "\ Display local help in the echo area. This command, by default, displays a short help message, namely @@ -16261,16 +14555,13 @@ If DESCRIBE-BUTTON in non-nil (interactively, the prefix arg), and there's a button/widget at point, pop a buffer describing that button/widget instead. -\(fn &optional INHIBIT-WARNING DESCRIBE-BUTTON)" t nil) - +(fn &optional INHIBIT-WARNING DESCRIBE-BUTTON)" t nil) (autoload 'help-at-pt-cancel-timer "help-at-pt" "\ Cancel any timer set by `help-at-pt-set-timer'. This disables `help-at-pt-display-when-idle'." t nil) - (autoload 'help-at-pt-set-timer "help-at-pt" "\ Enable `help-at-pt-display-when-idle'. This is done by setting a timer, if none is currently active." t nil) - (defvar help-at-pt-display-when-idle 'never "\ Automatically show local help on point-over. If the value is t, the string obtained from any `kbd-help' or @@ -16301,9 +14592,7 @@ enabling buffer local values. It sets the actual value to nil. Thus, Custom distinguishes between a nil value and other values that disable the feature, which Custom identifies with `never'. The default is `never'.") - (custom-autoload 'help-at-pt-display-when-idle "help-at-pt" nil) - (autoload 'scan-buf-move-to-region "help-at-pt" "\ Go to the start of the next region with non-nil PROP property. Then run HOOK, which should be a quoted symbol that is a normal @@ -16321,8 +14610,7 @@ do not run HOOK. If there are not enough regions to move over, an error results and the number of available regions is mentioned in the error message. Point is not moved and HOOK is not run. -\(fn PROP &optional ARG HOOK)" nil nil) - +(fn PROP &optional ARG HOOK)" nil nil) (autoload 'scan-buf-next-region "help-at-pt" "\ Go to the start of the next region with non-nil help-echo. Print the help found there using `display-local-help'. Adjacent @@ -16343,8 +14631,7 @@ help-echo region without any local help being available. This is because `help-echo' can be a function evaluating to nil. This rarely happens in practice. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'scan-buf-previous-region "help-at-pt" "\ Go to the start of the previous region with non-nil help-echo. Print the help found there using `display-local-help'. Adjacent @@ -16352,13 +14639,10 @@ areas with different non-nil help-echo properties are considered different regions. With numeric argument ARG, behaves like `scan-buf-next-region' with argument -ARG. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "help-at-pt" '("help-at-pt-" "scan-buf-move-hook")) -;;;*** -;;;### (autoloads nil "help-fns" "help-fns.el" (0 0 0 0)) ;;; Generated autoloads from help-fns.el (autoload 'describe-function "help-fns" "\ @@ -16368,21 +14652,18 @@ When called from Lisp, FUNCTION may also be a function object. See the `help-enable-symbol-autoload' variable for special handling of autoloaded functions. -\(fn FUNCTION)" t nil) - +(fn FUNCTION)" t nil) (autoload 'describe-command "help-fns" "\ Display the full documentation of COMMAND (a symbol). When called from Lisp, COMMAND may also be a function object. -\(fn COMMAND)" t nil) - +(fn COMMAND)" t nil) (autoload 'help-C-file-name "help-fns" "\ Return the name of the C file where SUBR-OR-VAR is defined. KIND should be `var' for a variable or `subr' for a subroutine. If we can't find the file name, nil is returned. -\(fn SUBR-OR-VAR KIND)" nil nil) - +(fn SUBR-OR-VAR KIND)" nil nil) (autoload 'find-lisp-object-file-name "help-fns" "\ Guess the file that defined the Lisp object OBJECT, of type TYPE. OBJECT should be a symbol associated with a function, variable, or face; @@ -16402,29 +14683,25 @@ If ALSO-C-SOURCE is non-nil, instead of returning `C-source', this function will attempt to locate the definition of OBJECT in the C sources, too. -\(fn OBJECT TYPE &optional ALSO-C-SOURCE)" nil nil) - +(fn OBJECT TYPE &optional ALSO-C-SOURCE)" nil nil) (autoload 'describe-function-1 "help-fns" "\ -\(fn FUNCTION)" nil nil) - +(fn FUNCTION)" nil nil) (autoload 'variable-at-point "help-fns" "\ Return the bound variable symbol found at or before point. Return 0 if there is no such symbol. If ANY-SYMBOL is non-nil, don't insist the symbol be bound. -\(fn &optional ANY-SYMBOL)" nil nil) - +(fn &optional ANY-SYMBOL)" nil nil) (autoload 'describe-variable "help-fns" "\ Display the full documentation of VARIABLE (a symbol). Returns the documentation as a string, also. If VARIABLE has a buffer-local value in BUFFER or FRAME -\(default to the current buffer and current frame), +(default to the current buffer and current frame), it is displayed along with the global value. -\(fn VARIABLE &optional BUFFER FRAME)" t nil) - +(fn VARIABLE &optional BUFFER FRAME)" t nil) (autoload 'describe-face "help-fns" "\ Display the properties of face FACE on FRAME. Interactively, FACE defaults to the faces of the character after point @@ -16434,8 +14711,7 @@ If the optional argument FRAME is given, report on face FACE in that frame. If FRAME is t, report on the defaults for face FACE (for new frames). If FRAME is omitted or nil, use the selected frame. -\(fn FACE &optional FRAME)" t nil) - +(fn FACE &optional FRAME)" t nil) (autoload 'describe-symbol "help-fns" "\ Display the full documentation of SYMBOL. Will show the info of SYMBOL as a function, variable, and/or face. @@ -16443,30 +14719,26 @@ Optional arguments BUFFER and FRAME specify for which buffer and frame to show the information about SYMBOL; they default to the current buffer and the selected frame, respectively. -\(fn SYMBOL &optional BUFFER FRAME)" t nil) - +(fn SYMBOL &optional BUFFER FRAME)" t nil) (autoload 'describe-syntax "help-fns" "\ Describe the syntax specifications in the syntax table of BUFFER. The descriptions are inserted in a help buffer, which is then displayed. BUFFER defaults to the current buffer. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (autoload 'describe-categories "help-fns" "\ Describe the category specifications in the current category table. The descriptions are inserted in a buffer, which is then displayed. If BUFFER is non-nil, then describe BUFFER's category table instead. BUFFER should be a buffer or a buffer name. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (autoload 'describe-keymap "help-fns" "\ Describe key bindings in KEYMAP. When called interactively, prompt for a variable that has a keymap value. -\(fn KEYMAP)" t nil) - +(fn KEYMAP)" t nil) (autoload 'describe-mode "help-fns" "\ Display documentation of current major mode and minor modes. A brief summary of the minor modes comes first, followed by the @@ -16480,8 +14752,7 @@ whose documentation describes the minor mode. If called from Lisp with a non-nil BUFFER argument, display documentation for the major and minor modes of that buffer. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (autoload 'describe-widget "help-fns" "\ Display a buffer with information about a widget. You can use this command to describe buttons (e.g., the links in a *Help* @@ -16495,23 +14766,18 @@ When called from Lisp, POS may be a buffer position or a mouse position list. Calls each function of the list `describe-widget-functions' in turn, until one of them returns non-nil. -\(fn &optional POS)" t nil) - +(fn &optional POS)" t nil) (autoload 'doc-file-to-man "help-fns" "\ Produce an nroff buffer containing the doc-strings from the DOC file. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (autoload 'doc-file-to-info "help-fns" "\ Produce a texinfo buffer with sorted doc-strings from the DOC file. -\(fn FILE)" t nil) - +(fn FILE)" t nil) (register-definition-prefixes "help-fns" '("describe-" "help-" "keymap-name-history")) -;;;*** -;;;### (autoloads nil "help-macro" "help-macro.el" (0 0 0 0)) ;;; Generated autoloads from help-macro.el (defvar three-step-help nil "\ @@ -16520,21 +14786,16 @@ The three steps are simple prompt, prompt with all options, and window listing and describing the options. A value of nil means skip the middle step, so that \\[help-command] \\[help-command] gives the window that lists the options.") - (custom-autoload 'three-step-help "help-macro" t) - (register-definition-prefixes "help-macro" '("make-help-screen")) -;;;*** -;;;### (autoloads nil "help-mode" "help-mode.el" (0 0 0 0)) ;;; Generated autoloads from help-mode.el (autoload 'help-mode--add-function-link "help-mode" "\ -\(fn STR FUN)" nil nil) - +(fn STR FUN)" nil nil) (autoload 'help-mode "help-mode" "\ Major mode for viewing help text and navigating references in it. Also see the `help-enable-variable-value-editing' variable. @@ -16542,18 +14803,13 @@ Also see the `help-enable-variable-value-editing' variable. Commands: \\{help-mode-map} -\(fn)" t nil) - +(fn)" t nil) (autoload 'help-mode-setup "help-mode" "\ Enter Help mode in the current buffer." nil nil) - (make-obsolete 'help-mode-setup 'nil '"29.1") - (autoload 'help-mode-finish "help-mode" "\ Finalize Help mode setup in current buffer." nil nil) - (make-obsolete 'help-mode-finish 'nil '"29.1") - (autoload 'help-setup-xref "help-mode" "\ Invoked from commands using the \"*Help*\" buffer to install some xref info. @@ -16566,16 +14822,14 @@ This should be called very early, before the output buffer is cleared, because we want to record the \"previous\" position of point so we can restore it properly when going back. -\(fn ITEM INTERACTIVE-P)" nil nil) - +(fn ITEM INTERACTIVE-P)" nil nil) (autoload 'help-buffer "help-mode" "\ Return the name of a buffer for inserting help. -If `help-xref-following' is non-nil, this is the name of the -current buffer. Signal an error if this buffer is not derived -from `help-mode'. +If `help-xref-following' is non-nil and the current buffer is +derived from `help-mode', this is the name of the current buffer. + Otherwise, return \"*Help*\", creating a buffer with that name if it does not already exist." nil nil) - (autoload 'help-make-xrefs "help-mode" "\ Parse and hyperlink documentation cross-references in the given BUFFER. @@ -16590,15 +14844,14 @@ preceded by the word `variable' or `option'. If the variable `help-xref-mule-regexp' is non-nil, find also cross-reference information related to multilingual environment -\(e.g., coding-systems). This variable is also used to disambiguate +(e.g., coding-systems). This variable is also used to disambiguate the type of reference as the same way as `help-xref-symbol-regexp'. A special reference `back' is made to return back through a stack of help buffers. Variable `help-back-label' specifies the text for that. -\(fn &optional BUFFER)" t nil) - +(fn &optional BUFFER)" t nil) (autoload 'help-xref-button "help-mode" "\ Make a hyperlink for cross-reference text previously matched. MATCH-NUMBER is the subexpression of interest in the last matched @@ -16606,55 +14859,43 @@ regexp. TYPE is the type of button to use. Any remaining arguments are passed to the button's help-function when it is invoked. See `help-make-xrefs'. -\(fn MATCH-NUMBER TYPE &rest ARGS)" nil nil) - +(fn MATCH-NUMBER TYPE &rest ARGS)" nil nil) (autoload 'help-insert-xref-button "help-mode" "\ Insert STRING and make a hyperlink from cross-reference text on it. TYPE is the type of button to use. Any remaining arguments are passed to the button's help-function when it is invoked. See `help-make-xrefs'. -\(fn STRING TYPE &rest ARGS)" nil nil) - +(fn STRING TYPE &rest ARGS)" nil nil) (autoload 'help-xref-on-pp "help-mode" "\ Add xrefs for symbols in `pp's output between FROM and TO. -\(fn FROM TO)" nil nil) - -(define-obsolete-function-alias 'help-xref-interned 'describe-symbol "25.1") - +(fn FROM TO)" nil nil) +(define-obsolete-function-alias 'help-xref-interned 'describe-symbol "\ +25.1") (autoload 'help-bookmark-jump "help-mode" "\ Jump to `help-mode' bookmark BOOKMARK. Handler function for record returned by `help-bookmark-make-record'. BOOKMARK is a bookmark name or a bookmark record. -\(fn BOOKMARK)" nil nil) - +(fn BOOKMARK)" nil nil) (register-definition-prefixes "help-mode" '("describe-symbol-backends" "help-")) -;;;*** -;;;### (autoloads nil "helper" "emacs-lisp/helper.el" (0 0 0 0)) ;;; Generated autoloads from emacs-lisp/helper.el (autoload 'Helper-describe-bindings "helper" "\ Describe local key bindings of current mode." t nil) - (autoload 'Helper-help "helper" "\ Provide help for current mode." t nil) - (register-definition-prefixes "helper" '("Helper-")) -;;;*** -;;;### (autoloads nil "hex-util" "hex-util.el" (0 0 0 0)) ;;; Generated autoloads from hex-util.el (register-definition-prefixes "hex-util" '("decode-hex-string" "encode-hex-string")) -;;;*** -;;;### (autoloads nil "hexl" "hexl.el" (0 0 0 0)) ;;; Generated autoloads from hexl.el (autoload 'hexl-mode "hexl" "\ @@ -16739,25 +14980,36 @@ You can use \\[hexl-find-file] to visit a file in Hexl mode. \\[describe-bindings] for advanced commands. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (autoload 'hexl-find-file "hexl" "\ Edit file FILENAME as a binary file in hex dump format. Switch to a buffer visiting file FILENAME, creating one if none exists, and edit the file in `hexl-mode'. The buffer's coding-system will be no-conversion, unlike if you visit it normally and then invoke `hexl-mode'. -\(fn FILENAME)" t nil) - +(fn FILENAME)" t nil) (autoload 'hexlify-buffer "hexl" "\ Convert a binary buffer to hexl format. This discards the buffer's undo information." t nil) - (register-definition-prefixes "hexl" '("dehexlify-buffer" "hexl-")) -;;;*** -;;;### (autoloads nil "hi-lock" "hi-lock.el" (0 0 0 0)) +;;; Generated autoloads from hfy-cmap.el + +(autoload 'htmlfontify-load-rgb-file "hfy-cmap" "\ +Load an X11 style rgb.txt FILE. +Search `hfy-rgb-load-path' if FILE is not specified. +Loads the variable `hfy-rgb-txt-color-map', which is used by +`hfy-fallback-color-values'. + +(fn &optional FILE)" t nil) +(autoload 'hfy-fallback-color-values "hfy-cmap" "\ +Use a fallback method for obtaining the rgb values for a color. + +(fn COLOR-STRING)" nil nil) +(register-definition-prefixes "hfy-cmap" '("hfy-" "htmlfontify-unload-rgb-file")) + + ;;; Generated autoloads from hi-lock.el (autoload 'hi-lock-mode "hi-lock" "\ @@ -16837,10 +15089,8 @@ evaluate `hi-lock-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (put 'global-hi-lock-mode 'globalized-minor-mode t) - (defvar global-hi-lock-mode nil "\ Non-nil if Global Hi-Lock mode is enabled. See the `global-hi-lock-mode' command @@ -16848,9 +15098,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `global-hi-lock-mode'.") - (custom-autoload 'global-hi-lock-mode "hi-lock" nil) - (autoload 'global-hi-lock-mode "hi-lock" "\ Toggle Hi-Lock mode in all buffers. With prefix ARG, enable Global Hi-Lock mode if ARG is positive; @@ -16865,10 +15113,8 @@ Hi-Lock mode is enabled in all buffers where See `hi-lock-mode' for more information on Hi-Lock mode. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (defalias 'highlight-lines-matching-regexp 'hi-lock-line-face-buffer) - (autoload 'hi-lock-line-face-buffer "hi-lock" "\ Highlight all lines that match REGEXP using FACE. The lines that match REGEXP will be displayed by merging @@ -16885,10 +15131,8 @@ Use Font lock mode, if enabled, to highlight REGEXP. Otherwise, use overlays for highlighting. If overlays are used, the highlighting will not update as you type. -\(fn REGEXP &optional FACE)" t nil) - +(fn REGEXP &optional FACE)" t nil) (defalias 'highlight-regexp 'hi-lock-face-buffer) - (autoload 'hi-lock-face-buffer "hi-lock" "\ Set face of each match of REGEXP to FACE. Interactively, prompt for REGEXP using `read-regexp', then FACE. @@ -16910,10 +15154,8 @@ is considered \"enabled\" in a buffer if its `major-mode' causes `font-lock-specified-p' to return non-nil, which means the major mode specifies support for Font Lock. -\(fn REGEXP &optional FACE SUBEXP LIGHTER)" t nil) - +(fn REGEXP &optional FACE SUBEXP LIGHTER)" t nil) (defalias 'highlight-phrase 'hi-lock-face-phrase-buffer) - (autoload 'hi-lock-face-phrase-buffer "hi-lock" "\ Set face of each match of phrase REGEXP to FACE. Interactively, prompt for REGEXP using `read-regexp', then FACE. @@ -16930,10 +15172,8 @@ is considered \"enabled\" in a buffer if its `major-mode' causes `font-lock-specified-p' to return non-nil, which means the major mode specifies support for Font Lock. -\(fn REGEXP &optional FACE)" t nil) - +(fn REGEXP &optional FACE)" t nil) (defalias 'highlight-symbol-at-point 'hi-lock-face-symbol-at-point) - (autoload 'hi-lock-face-symbol-at-point "hi-lock" "\ Highlight each instance of the symbol at point. Uses the next face from `hi-lock-face-defaults' without prompting, @@ -16948,9 +15188,7 @@ in which case the highlighting will not update as you type. The Font Lock mode is considered \"enabled\" in a buffer if its `major-mode' causes `font-lock-specified-p' to return non-nil, which means the major mode specifies support for Font Lock." t nil) - (defalias 'unhighlight-regexp 'hi-lock-unface-buffer) - (autoload 'hi-lock-unface-buffer "hi-lock" "\ Remove highlighting of each match to REGEXP set by hi-lock. Interactively, prompt for REGEXP, accepting only regexps @@ -16958,28 +15196,22 @@ previously inserted by hi-lock interactive functions. If REGEXP is t (or if \\[universal-argument] was specified interactively), then remove all hi-lock highlighting. -\(fn REGEXP)" t nil) - +(fn REGEXP)" t nil) (autoload 'hi-lock-write-interactive-patterns "hi-lock" "\ Write interactively added patterns, if any, into buffer at point. Interactively added patterns are those normally specified using `highlight-regexp' and `highlight-lines-matching-regexp'; they can be found in variable `hi-lock-interactive-patterns'." t nil) - (autoload 'hi-lock-find-patterns "hi-lock" "\ Add patterns from the current buffer to the list of hi-lock patterns." t nil) - (autoload 'hi-lock-context-menu "hi-lock" "\ Populate MENU with a menu item to highlight symbol at CLICK. -\(fn MENU CLICK)" nil nil) - +(fn MENU CLICK)" nil nil) (register-definition-prefixes "hi-lock" '("hi-lock-" "highlight-symbol-at-mouse" "turn-on-hi-lock-if-enabled")) -;;;*** -;;;### (autoloads nil "hideif" "progmodes/hideif.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/hideif.el (autoload 'hide-ifdef-mode "hideif" "\ @@ -17033,13 +15265,10 @@ evaluate `hide-ifdef-mode'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "hideif" '("backward-ifdef" "down-ifdef" "forward-ifdef" "hide-ifdef" "hif-" "intern-safe" "next-ifdef" "previous-ifdef" "show-ifdef" "up-ifdef")) -;;;*** -;;;### (autoloads nil "hideshow" "progmodes/hideshow.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/hideshow.el (defvar hs-special-modes-alist (mapcar 'purecopy '((c-mode "{" "}" "/[*/]" nil nil) (c++-mode "{" "}" "/[*/]" nil nil) (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) (java-mode "{" "}" "/[*/]" nil nil) (js-mode "{" "}" "/[*/]" nil) (mhtml-mode "{\\|<[^/>]*?" "}\\|]*[^/]>" " markers will be removed. -\(fn BEG END)" nil nil) - +(fn BEG END)" nil nil) (register-definition-prefixes "xml" '("xml-")) -;;;*** -;;;### (autoloads nil "xmltok" "nxml/xmltok.el" (0 0 0 0)) ;;; Generated autoloads from nxml/xmltok.el (autoload 'xmltok-get-declared-encoding-position "xmltok" "\ @@ -40151,40 +35561,31 @@ If there is XML that is not well-formed that looks like an XML declaration, return nil. Otherwise, return t. If LIMIT is non-nil, then do not consider characters beyond LIMIT. -\(fn &optional LIMIT)" nil nil) - +(fn &optional LIMIT)" nil nil) (register-definition-prefixes "xmltok" '("xmltok-")) -;;;*** -;;;### (autoloads nil "xref" "progmodes/xref.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/xref.el -(push (purecopy '(xref 1 4 1)) package--builtin-versions) +(push (purecopy '(xref 1 4 1)) package--builtin-versions) (autoload 'xref-find-backend "xref" nil nil nil) - -(define-obsolete-function-alias 'xref-pop-marker-stack #'xref-go-back "29.1") - +(define-obsolete-function-alias 'xref-pop-marker-stack #'xref-go-back "\ +29.1") (autoload 'xref-go-back "xref" "\ Go back to the previous position in xref history. To undo, use \\[xref-go-forward]." t nil) - (autoload 'xref-go-forward "xref" "\ Got to the point where a previous \\[xref-go-back] was invoked." t nil) - (autoload 'xref-marker-stack-empty-p "xref" "\ Whether the xref back-history is empty." nil nil) - (autoload 'xref-forward-history-empty-p "xref" "\ Whether the xref forward-history is empty." nil nil) - (autoload 'xref-show-xrefs "xref" "\ Display some Xref values produced by FETCHER using DISPLAY-ACTION. The meanings of both arguments are the same as documented in `xref-show-xrefs-function'. -\(fn FETCHER DISPLAY-ACTION)" nil nil) - +(fn FETCHER DISPLAY-ACTION)" nil nil) (autoload 'xref-find-definitions "xref" "\ Find the definition of the identifier at point. With prefix argument or when there's no identifier at point, @@ -40197,18 +35598,15 @@ buffer where the user can select from the list. Use \\[xref-go-back] to return back to where you invoked this command. -\(fn IDENTIFIER)" t nil) - +(fn IDENTIFIER)" t nil) (autoload 'xref-find-definitions-other-window "xref" "\ Like `xref-find-definitions' but switch to the other window. -\(fn IDENTIFIER)" t nil) - +(fn IDENTIFIER)" t nil) (autoload 'xref-find-definitions-other-frame "xref" "\ Like `xref-find-definitions' but switch to the other frame. -\(fn IDENTIFIER)" t nil) - +(fn IDENTIFIER)" t nil) (autoload 'xref-find-references "xref" "\ Find references to the identifier at point. This command might prompt for the identifier as needed, perhaps @@ -40217,27 +35615,24 @@ With prefix argument, or if `xref-prompt-for-identifier' is t, always prompt for the identifier. If `xref-prompt-for-identifier' is nil, prompt only if there's no usable symbol at point. -\(fn IDENTIFIER)" t nil) - +(fn IDENTIFIER)" t nil) (autoload 'xref-find-definitions-at-mouse "xref" "\ Find the definition of identifier at or around mouse click. This command is intended to be bound to a mouse event. -\(fn EVENT)" t nil) - +(fn EVENT)" t nil) (autoload 'xref-find-references-at-mouse "xref" "\ Find references to the identifier at or around mouse click. This command is intended to be bound to a mouse event. -\(fn EVENT)" t nil) - +(fn EVENT)" t nil) (autoload 'xref-find-apropos "xref" "\ Find all meaningful symbols that match PATTERN. The argument has the same meaning as in `apropos'. See `tags-apropos-additional-actions' for how to augment the output of this command when the backend is etags. -\(fn PATTERN)" t nil) +(fn PATTERN)" t nil) (define-key esc-map "." #'xref-find-definitions) (define-key esc-map "," #'xref-go-back) (define-key esc-map [?\C-,] #'xref-go-forward) @@ -40245,7 +35640,6 @@ output of this command when the backend is etags. (define-key esc-map [?\C-.] #'xref-find-apropos) (define-key ctl-x-4-map "." #'xref-find-definitions-other-window) (define-key ctl-x-5-map "." #'xref-find-definitions-other-frame) - (autoload 'xref-references-in-directory "xref" "\ Find all references to SYMBOL in directory DIR. Return a list of xref values. @@ -40254,8 +35648,7 @@ This function uses the Semantic Symbol Reference API, see `semantic-symref-tool-alist' for details on which tools are used, and when. -\(fn SYMBOL DIR)" nil nil) - +(fn SYMBOL DIR)" nil nil) (autoload 'xref-matches-in-directory "xref" "\ Find all matches for REGEXP in directory DIR. Return a list of xref values. @@ -40263,8 +35656,7 @@ Only files matching some of FILES and none of IGNORES are searched. FILES is a string with glob patterns separated by spaces. IGNORES is a list of glob patterns for files to ignore. -\(fn REGEXP FILES DIR IGNORES)" nil nil) - +(fn REGEXP FILES DIR IGNORES)" nil nil) (autoload 'xref-matches-in-files "xref" "\ Find all matches for REGEXP in FILES. Return a list of xref values. @@ -40273,27 +35665,20 @@ FILES must be a list of absolute file names. See `xref-search-program' and `xref-search-program-alist' for how to control which program to use when looking for matches. -\(fn REGEXP FILES)" nil nil) - +(fn REGEXP FILES)" nil nil) (register-definition-prefixes "xref" '("xref-")) -;;;*** -;;;### (autoloads nil "xscheme" "progmodes/xscheme.el" (0 0 0 0)) ;;; Generated autoloads from progmodes/xscheme.el (register-definition-prefixes "xscheme" '("default-xscheme-runlight" "exit-scheme-interaction-mode" "global-set-scheme-interaction-buffer" "local-" "reset-scheme" "run-scheme" "scheme-" "start-scheme" "verify-xscheme-buffer" "xscheme-")) -;;;*** -;;;### (autoloads nil "xsd-regexp" "nxml/xsd-regexp.el" (0 0 0 0)) ;;; Generated autoloads from nxml/xsd-regexp.el (register-definition-prefixes "xsd-regexp" '("xsdre-")) -;;;*** -;;;### (autoloads nil "xt-mouse" "xt-mouse.el" (0 0 0 0)) ;;; Generated autoloads from xt-mouse.el (defvar xterm-mouse-mode nil "\ @@ -40303,9 +35688,7 @@ for a description of this minor mode. Setting this variable directly does not take effect; either customize it (see the info node `Easy Customization') or call the function `xterm-mouse-mode'.") - (custom-autoload 'xterm-mouse-mode "xt-mouse" nil) - (autoload 'xterm-mouse-mode "xt-mouse" "\ Toggle XTerm mouse mode. @@ -40330,13 +35713,10 @@ evaluate `(default-value \\='xterm-mouse-mode)'. The mode's hook is called both when the mode is enabled and when it is disabled. -\(fn &optional ARG)" t nil) - +(fn &optional ARG)" t nil) (register-definition-prefixes "xt-mouse" '("turn-o" "xt-mouse-epoch" "xterm-mouse-")) -;;;*** -;;;### (autoloads nil "xwidget" "xwidget.el" (0 0 0 0)) ;;; Generated autoloads from xwidget.el (autoload 'xwidget-webkit-browse-url "xwidget" "\ @@ -40344,20 +35724,16 @@ Ask xwidget-webkit to browse URL. NEW-SESSION specifies whether to create a new xwidget-webkit session. Interactively, URL defaults to the string looking like a url around point. -\(fn URL &optional NEW-SESSION)" t nil) - +(fn URL &optional NEW-SESSION)" t nil) (autoload 'xwidget-webkit-bookmark-jump-handler "xwidget" "\ Jump to the web page bookmarked by the bookmark record BOOKMARK. If `xwidget-webkit-bookmark-jump-new-session' is non-nil, create a new xwidget-webkit session, otherwise use an existing session. -\(fn BOOKMARK)" nil nil) - +(fn BOOKMARK)" nil nil) (register-definition-prefixes "xwidget" '("xwidget-")) -;;;*** -;;;### (autoloads nil "yank-media" "yank-media.el" (0 0 0 0)) ;;; Generated autoloads from yank-media.el (autoload 'yank-media "yank-media" "\ @@ -40368,7 +35744,6 @@ the `yank-media-handler' mechanism. Also see `yank-media-types' for a command that lets you explore all the different selection types." t nil) - (autoload 'yank-media-handler "yank-media" "\ Register HANDLER for dealing with `yank-media' actions for TYPES. TYPES should be a MIME media type symbol, a regexp, or a list @@ -40378,185 +35753,41 @@ HANDLER is a function that will be called with two arguments: The MIME type (a symbol on the form `image/png') and the selection data (a string). -\(fn TYPES HANDLER)" nil nil) - +(fn TYPES HANDLER)" nil nil) (register-definition-prefixes "yank-media" '("yank-media-")) -;;;*** -;;;### (autoloads nil "yenc" "mail/yenc.el" (0 0 0 0)) ;;; Generated autoloads from mail/yenc.el (autoload 'yenc-decode-region "yenc" "\ Yenc decode region between START and END using an internal decoder. -\(fn START END)" t nil) - +(fn START END)" t nil) (autoload 'yenc-extract-filename "yenc" "\ Extract file name from an yenc header." nil nil) - (register-definition-prefixes "yenc" '("yenc-")) -;;;*** -;;;### (autoloads nil "zeroconf" "net/zeroconf.el" (0 0 0 0)) ;;; Generated autoloads from net/zeroconf.el (register-definition-prefixes "zeroconf" '("zeroconf-")) -;;;*** -;;;### (autoloads nil "zone" "play/zone.el" (0 0 0 0)) ;;; Generated autoloads from play/zone.el (autoload 'zone "zone" "\ Zone out, completely." t nil) - (register-definition-prefixes "zone" '("zone-")) - -;;;*** - -;;;### (autoloads nil nil ("abbrev.el" "bindings.el" "buff-menu.el" -;;;;;; "button.el" "calc/calc-aent.el" "calc/calc-embed.el" "calc/calc-misc.el" -;;;;;; "calc/calc-yank.el" "case-table.el" "cedet/ede/cpp-root.el" -;;;;;; "cedet/ede/custom.el" "cedet/ede/dired.el" "cedet/ede/emacs.el" -;;;;;; "cedet/ede/files.el" "cedet/ede/generic.el" "cedet/ede/linux.el" -;;;;;; "cedet/ede/locate.el" "cedet/ede/make.el" "cedet/ede/speedbar.el" -;;;;;; "cedet/ede/system.el" "cedet/ede/util.el" "cedet/semantic/analyze.el" -;;;;;; "cedet/semantic/analyze/complete.el" "cedet/semantic/analyze/refs.el" -;;;;;; "cedet/semantic/bovine.el" "cedet/semantic/bovine/c-by.el" -;;;;;; "cedet/semantic/bovine/c.el" "cedet/semantic/bovine/el.el" -;;;;;; "cedet/semantic/bovine/gcc.el" "cedet/semantic/bovine/make-by.el" -;;;;;; "cedet/semantic/bovine/make.el" "cedet/semantic/bovine/scm-by.el" -;;;;;; "cedet/semantic/bovine/scm.el" "cedet/semantic/complete.el" -;;;;;; "cedet/semantic/ctxt.el" "cedet/semantic/db-file.el" "cedet/semantic/db-find.el" -;;;;;; "cedet/semantic/db-global.el" "cedet/semantic/db-mode.el" -;;;;;; "cedet/semantic/db-typecache.el" "cedet/semantic/db.el" "cedet/semantic/debug.el" -;;;;;; "cedet/semantic/decorate/include.el" "cedet/semantic/decorate/mode.el" -;;;;;; "cedet/semantic/dep.el" "cedet/semantic/doc.el" "cedet/semantic/edit.el" -;;;;;; "cedet/semantic/find.el" "cedet/semantic/format.el" "cedet/semantic/grammar-wy.el" -;;;;;; "cedet/semantic/grm-wy-boot.el" "cedet/semantic/html.el" -;;;;;; "cedet/semantic/ia-sb.el" "cedet/semantic/ia.el" "cedet/semantic/idle.el" -;;;;;; "cedet/semantic/imenu.el" "cedet/semantic/lex-spp.el" "cedet/semantic/lex.el" -;;;;;; "cedet/semantic/mru-bookmark.el" "cedet/semantic/scope.el" -;;;;;; "cedet/semantic/senator.el" "cedet/semantic/sort.el" "cedet/semantic/symref.el" -;;;;;; "cedet/semantic/symref/cscope.el" "cedet/semantic/symref/global.el" -;;;;;; "cedet/semantic/symref/grep.el" "cedet/semantic/symref/idutils.el" -;;;;;; "cedet/semantic/symref/list.el" "cedet/semantic/tag-file.el" -;;;;;; "cedet/semantic/tag-ls.el" "cedet/semantic/tag-write.el" -;;;;;; "cedet/semantic/tag.el" "cedet/semantic/texi.el" "cedet/semantic/util-modes.el" -;;;;;; "cedet/semantic/wisent/java-tags.el" "cedet/semantic/wisent/javascript.el" -;;;;;; "cedet/semantic/wisent/javat-wy.el" "cedet/semantic/wisent/js-wy.el" -;;;;;; "cedet/semantic/wisent/python-wy.el" "cedet/semantic/wisent/python.el" -;;;;;; "cedet/srecode/compile.el" "cedet/srecode/cpp.el" "cedet/srecode/document.el" -;;;;;; "cedet/srecode/el.el" "cedet/srecode/expandproto.el" "cedet/srecode/getset.el" -;;;;;; "cedet/srecode/insert.el" "cedet/srecode/java.el" "cedet/srecode/map.el" -;;;;;; "cedet/srecode/mode.el" "cedet/srecode/srt-wy.el" "cedet/srecode/srt.el" -;;;;;; "cedet/srecode/template.el" "cedet/srecode/texi.el" "composite.el" -;;;;;; "cus-face.el" "cus-load.el" "cus-start.el" "custom.el" "dired-aux.el" -;;;;;; "dired-x.el" "electric.el" "emacs-lisp/backquote.el" "emacs-lisp/byte-run.el" -;;;;;; "emacs-lisp/cl-extra.el" "emacs-lisp/cl-macs.el" "emacs-lisp/cl-preloaded.el" -;;;;;; "emacs-lisp/cl-seq.el" "emacs-lisp/debug-early.el" "emacs-lisp/easymenu.el" -;;;;;; "emacs-lisp/eieio-custom.el" "emacs-lisp/eieio-opt.el" "emacs-lisp/float-sup.el" -;;;;;; "emacs-lisp/lisp-mode.el" "emacs-lisp/lisp.el" "emacs-lisp/macroexp.el" -;;;;;; "emacs-lisp/map-ynp.el" "emacs-lisp/nadvice.el" "emacs-lisp/oclosure.el" -;;;;;; "emacs-lisp/shorthands.el" "emacs-lisp/syntax.el" "emacs-lisp/timer.el" -;;;;;; "env.el" "epa-hook.el" "erc/erc-autoaway.el" "erc/erc-button.el" -;;;;;; "erc/erc-capab.el" "erc/erc-compat.el" "erc/erc-dcc.el" "erc/erc-desktop-notifications.el" -;;;;;; "erc/erc-ezbounce.el" "erc/erc-fill.el" "erc/erc-identd.el" -;;;;;; "erc/erc-imenu.el" "erc/erc-join.el" "erc/erc-list.el" "erc/erc-log.el" -;;;;;; "erc/erc-match.el" "erc/erc-menu.el" "erc/erc-netsplit.el" -;;;;;; "erc/erc-notify.el" "erc/erc-page.el" "erc/erc-pcomplete.el" -;;;;;; "erc/erc-replace.el" "erc/erc-ring.el" "erc/erc-services.el" -;;;;;; "erc/erc-sound.el" "erc/erc-speedbar.el" "erc/erc-spelling.el" -;;;;;; "erc/erc-stamp.el" "erc/erc-status-sidebar.el" "erc/erc-track.el" -;;;;;; "erc/erc-truncate.el" "erc/erc-xdcc.el" "eshell/em-alias.el" -;;;;;; "eshell/em-banner.el" "eshell/em-basic.el" "eshell/em-cmpl.el" -;;;;;; "eshell/em-dirs.el" "eshell/em-elecslash.el" "eshell/em-glob.el" -;;;;;; "eshell/em-hist.el" "eshell/em-ls.el" "eshell/em-pred.el" -;;;;;; "eshell/em-prompt.el" "eshell/em-rebind.el" "eshell/em-script.el" -;;;;;; "eshell/em-smart.el" "eshell/em-term.el" "eshell/em-tramp.el" -;;;;;; "eshell/em-unix.el" "eshell/em-xtra.el" "eshell/esh-groups.el" -;;;;;; "faces.el" "files.el" "finder-inf.el" "font-core.el" "font-lock.el" -;;;;;; "format.el" "frame.el" "help.el" "hfy-cmap.el" "ibuf-ext.el" -;;;;;; "indent.el" "international/characters.el" "international/charprop.el" -;;;;;; "international/charscript.el" "international/cp51932.el" -;;;;;; "international/emoji-labels.el" "international/emoji-zwj.el" -;;;;;; "international/eucjp-ms.el" "international/idna-mapping.el" -;;;;;; "international/iso-transl.el" "international/mule-cmds.el" -;;;;;; "international/mule-conf.el" "international/mule.el" "international/uni-bidi.el" -;;;;;; "international/uni-brackets.el" "international/uni-category.el" -;;;;;; "international/uni-combining.el" "international/uni-comment.el" -;;;;;; "international/uni-confusable.el" "international/uni-decimal.el" -;;;;;; "international/uni-decomposition.el" "international/uni-digit.el" -;;;;;; "international/uni-lowercase.el" "international/uni-mirrored.el" -;;;;;; "international/uni-name.el" "international/uni-numeric.el" -;;;;;; "international/uni-old-name.el" "international/uni-scripts.el" -;;;;;; "international/uni-special-lowercase.el" "international/uni-special-titlecase.el" -;;;;;; "international/uni-special-uppercase.el" "international/uni-titlecase.el" -;;;;;; "international/uni-uppercase.el" "isearch.el" "jit-lock.el" -;;;;;; "jka-cmpr-hook.el" "keymap.el" "language/burmese.el" "language/cham.el" -;;;;;; "language/chinese.el" "language/cyrillic.el" "language/czech.el" -;;;;;; "language/english.el" "language/ethiopic.el" "language/european.el" -;;;;;; "language/georgian.el" "language/greek.el" "language/hebrew.el" -;;;;;; "language/indian.el" "language/indonesian.el" "language/japanese.el" -;;;;;; "language/khmer.el" "language/korean.el" "language/lao.el" -;;;;;; "language/misc-lang.el" "language/philippine.el" "language/romanian.el" -;;;;;; "language/sinhala.el" "language/slovak.el" "language/tai-viet.el" -;;;;;; "language/thai.el" "language/tibetan.el" "language/utf-8-lang.el" -;;;;;; "language/vietnamese.el" "ldefs-boot.el" "leim/ja-dic/ja-dic.el" -;;;;;; "leim/leim-list.el" "leim/quail/4Corner.el" "leim/quail/ARRAY30.el" -;;;;;; "leim/quail/CCDOSPY.el" "leim/quail/CTLau-b5.el" "leim/quail/CTLau.el" -;;;;;; "leim/quail/ECDICT.el" "leim/quail/ETZY.el" "leim/quail/PY-b5.el" -;;;;;; "leim/quail/PY.el" "leim/quail/Punct-b5.el" "leim/quail/Punct.el" -;;;;;; "leim/quail/QJ-b5.el" "leim/quail/QJ.el" "leim/quail/SW.el" -;;;;;; "leim/quail/TONEPY.el" "leim/quail/ZIRANMA.el" "leim/quail/ZOZY.el" -;;;;;; "leim/quail/arabic.el" "leim/quail/cham.el" "leim/quail/compose.el" -;;;;;; "leim/quail/croatian.el" "leim/quail/cyril-jis.el" "leim/quail/cyrillic.el" -;;;;;; "leim/quail/czech.el" "leim/quail/emoji.el" "leim/quail/georgian.el" -;;;;;; "leim/quail/greek.el" "leim/quail/hanja-jis.el" "leim/quail/hanja.el" -;;;;;; "leim/quail/hanja3.el" "leim/quail/hebrew.el" "leim/quail/indonesian.el" -;;;;;; "leim/quail/ipa-praat.el" "leim/quail/latin-alt.el" "leim/quail/latin-ltx.el" -;;;;;; "leim/quail/latin-post.el" "leim/quail/latin-pre.el" "leim/quail/persian.el" -;;;;;; "leim/quail/philippine.el" "leim/quail/programmer-dvorak.el" -;;;;;; "leim/quail/py-punct.el" "leim/quail/pypunct-b5.el" "leim/quail/quick-b5.el" -;;;;;; "leim/quail/quick-cns.el" "leim/quail/rfc1345.el" "leim/quail/sami.el" -;;;;;; "leim/quail/sgml-input.el" "leim/quail/slovak.el" "leim/quail/symbol-ksc.el" -;;;;;; "leim/quail/tamil-dvorak.el" "leim/quail/tsang-b5.el" "leim/quail/tsang-cns.el" -;;;;;; "leim/quail/vntelex.el" "leim/quail/vnvni.el" "leim/quail/welsh.el" -;;;;;; "loadup.el" "mail/blessmail.el" "mail/undigest.el" "menu-bar.el" -;;;;;; "mh-e/mh-gnus.el" "minibuffer.el" "mouse.el" "newcomment.el" -;;;;;; "obarray.el" "org/ob-core.el" "org/ob-lob.el" "org/ob-matlab.el" -;;;;;; "org/ob-tangle.el" "org/ob.el" "org/ol-bbdb.el" "org/ol-irc.el" -;;;;;; "org/ol.el" "org/org-archive.el" "org/org-attach.el" "org/org-clock.el" -;;;;;; "org/org-colview.el" "org/org-compat.el" "org/org-datetree.el" -;;;;;; "org/org-duration.el" "org/org-element.el" "org/org-feed.el" -;;;;;; "org/org-footnote.el" "org/org-goto.el" "org/org-id.el" "org/org-indent.el" -;;;;;; "org/org-install.el" "org/org-keys.el" "org/org-lint.el" -;;;;;; "org/org-list.el" "org/org-macs.el" "org/org-mobile.el" "org/org-num.el" -;;;;;; "org/org-plot.el" "org/org-refile.el" "org/org-table.el" -;;;;;; "org/org-timer.el" "org/ox-ascii.el" "org/ox-beamer.el" "org/ox-html.el" -;;;;;; "org/ox-icalendar.el" "org/ox-latex.el" "org/ox-md.el" "org/ox-odt.el" -;;;;;; "org/ox-org.el" "org/ox-publish.el" "org/ox-texinfo.el" "org/ox.el" -;;;;;; "paren.el" "progmodes/elisp-mode.el" "progmodes/prog-mode.el" -;;;;;; "ps-mule.el" "register.el" "replace.el" "rfn-eshadow.el" -;;;;;; "select.el" "simple.el" "startup.el" "subdirs.el" "subr.el" -;;;;;; "tab-bar.el" "textmodes/fill.el" "textmodes/makeinfo.el" -;;;;;; "textmodes/page.el" "textmodes/paragraphs.el" "textmodes/reftex-auc.el" -;;;;;; "textmodes/reftex-cite.el" "textmodes/reftex-dcr.el" "textmodes/reftex-global.el" -;;;;;; "textmodes/reftex-index.el" "textmodes/reftex-parse.el" "textmodes/reftex-ref.el" -;;;;;; "textmodes/reftex-sel.el" "textmodes/reftex-toc.el" "textmodes/texnfo-upd.el" -;;;;;; "textmodes/text-mode.el" "uniquify.el" "vc/ediff-hook.el" -;;;;;; "vc/vc-hooks.el" "version.el" "widget.el" "window.el") (0 -;;;;;; 0 0 0)) - -;;;*** +;;; End of scraped data + (provide 'loaddefs) + ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t ;; coding: utf-8-emacs-unix ;; End: + ;;; loaddefs.el ends here commit f0238d8bd347070f48ff04830a8b06f9721b0056 Author: Lars Ingebrigtsen Date: Tue Jun 7 18:59:04 2022 +0200 Remove Mtn from vc-handled-backends * lisp/vc/vc-hooks.el (vc-handled-backends): Remove the deprecate vc-mtn backend. diff --git a/lisp/vc/vc-hooks.el b/lisp/vc/vc-hooks.el index 76d9771672..cc08767ade 100644 --- a/lisp/vc/vc-hooks.el +++ b/lisp/vc/vc-hooks.el @@ -99,7 +99,7 @@ interpreted as hostnames." :type 'regexp :group 'vc) -(defcustom vc-handled-backends '(RCS CVS SVN SCCS SRC Bzr Git Hg Mtn) +(defcustom vc-handled-backends '(RCS CVS SVN SCCS SRC Bzr Git Hg) ;; RCS, CVS, SVN, SCCS, and SRC come first because they are per-dir ;; rather than per-tree. RCS comes first because of the multibackend ;; support intended to use RCS for local commits (with a remote CVS server). commit 7815ebd25f77ffdc61ac0af4a9eb0a6cadc85e2b Author: Lars Ingebrigtsen Date: Tue Jun 7 18:51:15 2022 +0200 Fix loaddefs-generate--rubric recorded name * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--rubric): Fix the name that's recorded in the file -- this is only used by loaddefs-gen now, I think. diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index a6a4baffba..5280941cfc 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -466,7 +466,7 @@ FILE's name." (let ((lp (and (equal type "package") (setq type "autoloads")))) (with-temp-buffer (generate-lisp-file-heading - file 'loaddefs-generate--rubric + file 'loaddefs-generate :title (concat "automatically extracted " (or type "autoloads")) :commentary (and (string-match "/lisp/loaddefs\\.el\\'" file) "This file will be copied to ldefs-boot.el and checked in periodically.")) commit 5ab66afa34a11839238505054b5e4a2f5da69957 Author: Lars Ingebrigtsen Date: Tue Jun 7 18:35:00 2022 +0200 Make artist-mode work in zoomed buffers * lisp/textmodes/artist.el (artist-mouse-draw-continously): (artist-mouse-draw-continously): (artist-mouse-draw-poly): (artist-mouse-draw-1point): (artist-mouse-draw-2points): (artist-mouse-draw-2points): Work better when the window is zoomed (bug#46035). diff --git a/lisp/textmodes/artist.el b/lisp/textmodes/artist.el index 686d5f494c..ff4311c3ac 100644 --- a/lisp/textmodes/artist.el +++ b/lisp/textmodes/artist.el @@ -4919,7 +4919,7 @@ The event, EV, is the mouse event." (arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op)) (ev-start (event-start ev)) (initial-win (posn-window ev-start)) - (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start))) + (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start t))) (x1 (artist--adjust-x (car ev-start-pos))) (y1 (cdr ev-start-pos)) (timer nil)) @@ -4935,7 +4935,7 @@ The event, EV, is the mouse event." (while (or (mouse-movement-p ev) (member 'down (event-modifiers ev))) (setq ev-start-pos (artist-coord-win-to-buf - (posn-col-row (event-start ev)))) + (posn-col-row (event-start ev) t))) (setq x1 (artist--adjust-x (car ev-start-pos))) (setq y1 (cdr ev-start-pos)) @@ -5015,7 +5015,7 @@ The event, EV, is the mouse event." (arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op)) (ev-start (event-start ev)) (initial-win (posn-window ev-start)) - (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start))) + (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start t))) (x1-last (artist--adjust-x (car ev-start-pos))) (y1-last (cdr ev-start-pos)) (x2 x1-last) @@ -5107,7 +5107,7 @@ The event, EV, is the mouse event." ;; set x2 and y2 ;; (setq ev-start-pos (artist-coord-win-to-buf - (posn-col-row (event-start ev)))) + (posn-col-row (event-start ev) t))) (setq x2 (artist--adjust-x (car ev-start-pos))) (setq y2 (cdr ev-start-pos)) @@ -5134,7 +5134,7 @@ The event, EV, is the mouse event." ;; ;; set x2 and y2 (setq ev-start-pos (artist-coord-win-to-buf - (posn-col-row (event-start ev)))) + (posn-col-row (event-start ev) t))) (setq x2 (artist--adjust-x (car ev-start-pos))) (setq y2 (cdr ev-start-pos)) @@ -5218,7 +5218,8 @@ Operation is done once. The event, EV, is the mouse event." (arrow-pred (artist-go-get-arrow-pred-from-symbol op)) (arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op)) (ev-start (event-start ev)) - (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start))) + (ev-start-pos (artist-coord-win-to-buf + (posn-col-row ev-start t))) (x1 (artist--adjust-x (car ev-start-pos))) (y1 (cdr ev-start-pos))) (select-window (posn-window ev-start)) @@ -5252,7 +5253,8 @@ The event, EV, is the mouse event." (arrow-set-fn (artist-go-get-arrow-set-fn-from-symbol op)) (ev-start (event-start ev)) (initial-win (posn-window ev-start)) - (ev-start-pos (artist-coord-win-to-buf (posn-col-row ev-start))) + (ev-start-pos (artist-coord-win-to-buf + (posn-col-row ev-start t))) (x1 (artist--adjust-x (car ev-start-pos))) (y1 (cdr ev-start-pos)) (x2) @@ -5266,7 +5268,7 @@ The event, EV, is the mouse event." (while (or (mouse-movement-p ev) (member 'down (event-modifiers ev))) (setq ev-start-pos (artist-coord-win-to-buf - (posn-col-row (event-start ev)))) + (posn-col-row (event-start ev) t))) (setq x2 (artist--adjust-x (car ev-start-pos))) (setq y2 (cdr ev-start-pos)) commit 17ed9a803987d7441c64ee1a205322d99766b1da Author: Lars Ingebrigtsen Date: Tue Jun 7 18:34:20 2022 +0200 Allow posn-col-row to return data on a per-window basis * doc/lispref/commands.texi (Accessing Mouse): Document it. * lisp/subr.el (posn-col-row): Extend to use window data. diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 6c60216796..0a82bba3bc 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2615,7 +2615,7 @@ POSITION is assumed to lie in a window text area." @end example @end defun -@defun posn-col-row position +@defun posn-col-row position &optional use-window This function returns a cons cell @w{@code{(@var{col} . @var{row})}}, containing the estimated column and row corresponding to buffer position described by @var{position}. The return value is given in @@ -2623,7 +2623,11 @@ units of the frame's default character width and default line height (including spacing), as computed from the @var{x} and @var{y} values corresponding to @var{position}. (So, if the actual characters have non-default sizes, the actual row and column may differ from these -computed values.) +computed values.) If the optional @var{window} argument is +non-@code{nil}, use the default character width in the window +indicated by @var{position} instead of the frame. (This makes a +difference if that window is showing a buffer with a non-default +zooming level, for instance.) Note that @var{row} is counted from the top of the text area. If the window given by @var{position} possesses a header line (@pxref{Header diff --git a/etc/NEWS b/etc/NEWS index b75c1c9f6c..fc9e949d8b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1946,6 +1946,10 @@ Previously it produced a nonsense value, -1, that was never intended. * Lisp Changes in Emacs 29.1 ++++ +** 'posn-col-row' can now give position data based on windows. +Previously, it reported data only based on the frame. + +++ ** 'file-expand-wildcards' can now also take a regexp as PATTERN argument. diff --git a/lisp/subr.el b/lisp/subr.el index 8afba2b341..50ae357a13 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1705,13 +1705,19 @@ pixels. POSITION should be a list of the form returned by (declare-function scroll-bar-scale "scroll-bar" (num-denom whole)) -(defun posn-col-row (position) +(defun posn-col-row (position &optional use-window) "Return the nominal column and row in POSITION, measured in characters. The column and row values are approximations calculated from the x and y coordinates in POSITION and the frame's default character width and default line height, including spacing. + +If USE-WINDOW is non-nil, use the typical width of a character in +the window indicated by POSITION instead of the frame. (This +makes a difference is a window has a zoom level.) + For a scroll-bar event, the result column is 0, and the row corresponds to the vertical position of the click in the scroll bar. + POSITION should be a list of the form returned by the `event-start' and `event-end' functions." (let* ((pair (posn-x-y position)) @@ -1729,20 +1735,23 @@ and `event-end' functions." ((eq area 'horizontal-scroll-bar) (cons (scroll-bar-scale pair (window-width window)) 0)) (t - ;; FIXME: This should take line-spacing properties on - ;; newlines into account. - (let* ((spacing (when (display-graphic-p frame) - (or (with-current-buffer - (window-buffer (frame-selected-window frame)) - line-spacing) - (frame-parameter frame 'line-spacing))))) - (cond ((floatp spacing) - (setq spacing (truncate (* spacing - (frame-char-height frame))))) - ((null spacing) - (setq spacing 0))) - (cons (/ (car pair) (frame-char-width frame)) - (/ (cdr pair) (+ (frame-char-height frame) spacing)))))))) + (if use-window + (cons (/ (car pair) (window-font-width window)) + (/ (cdr pair) (window-font-height window))) + ;; FIXME: This should take line-spacing properties on + ;; newlines into account. + (let* ((spacing (when (display-graphic-p frame) + (or (with-current-buffer + (window-buffer (frame-selected-window frame)) + line-spacing) + (frame-parameter frame 'line-spacing))))) + (cond ((floatp spacing) + (setq spacing (truncate (* spacing + (frame-char-height frame))))) + ((null spacing) + (setq spacing 0))) + (cons (/ (car pair) (frame-char-width frame)) + (/ (cdr pair) (+ (frame-char-height frame) spacing))))))))) (defun posn-actual-col-row (position) "Return the window row number in POSITION and character number in that row. commit 00a0226ba53598bbe71d12d877121fdcb194e2c9 Author: Lars Ingebrigtsen Date: Tue Jun 7 16:38:55 2022 +0200 Allow hooks to alter the process in prolog-ensure-process * lisp/progmodes/prolog.el (prolog-ensure-process): Start the mode after starting the process, so that the mode hook can talk to the process (bug#46003). diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el index 8382c4bd09..9598209f5e 100644 --- a/lisp/progmodes/prolog.el +++ b/lisp/progmodes/prolog.el @@ -1355,8 +1355,6 @@ the variable `prolog-prompt-regexp'." (error "This Prolog system has defined no interpreter")) (unless (comint-check-proc "*prolog*") (with-current-buffer (get-buffer-create "*prolog*") - (prolog-inferior-mode) - ;; The "INFERIOR=yes" hack is for SWI-Prolog 7.2.3 and earlier, ;; which assumes it is running under Emacs if either INFERIOR=yes or ;; if EMACS is set to a nonempty value. The EMACS setting is @@ -1369,6 +1367,7 @@ the variable `prolog-prompt-regexp'." (cons "INFERIOR=yes" process-environment)))) (apply 'make-comint-in-buffer "prolog" (current-buffer) pname nil pswitches)) + (prolog-inferior-mode) (unless prolog-system ;; Setup auto-detection. commit a98413726f5a10676f9faf4c4013ac6eaa53b42b Author: Stefan Monnier Date: Tue Jun 7 10:30:47 2022 -0400 find-func.el: Fix bug#41104 * lisp/emacs-lisp/find-func.el (find-function-advised-original): Look at the actual function definition rather than `advice--symbol-function` which sometimes returns only the advice. * test/lisp/emacs-lisp/find-func-tests.el (find-func-tests--find-library-verbose): Add test. diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index 96eaf1ab64..2dec51dd04 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -270,7 +270,7 @@ If FUNC is not a symbol, return it. Else, if it's not advised, return the symbol's function definition." (or (and (symbolp func) (featurep 'nadvice) - (let ((ofunc (advice--symbol-function func))) + (let ((ofunc (symbol-function func))) (if (advice--p ofunc) (advice--cd*r ofunc) ofunc))) @@ -516,8 +516,8 @@ Return t if any PRED returns t." (defun find-function-library (function &optional lisp-only verbose) "Return the pair (ORIG-FUNCTION . LIBRARY) for FUNCTION. -ORIG-FUNCTION is the original name, after removing all advice and -resolving aliases. LIBRARY is an absolute file name, a relative +ORIG-FUNCTION is the original name, after resolving aliases. +LIBRARY is an absolute file name, a relative file name inside the C sources directory, or a name of an autoloaded feature. diff --git a/test/lisp/emacs-lisp/find-func-tests.el b/test/lisp/emacs-lisp/find-func-tests.el index d29d9ff656..420c61acb5 100644 --- a/test/lisp/emacs-lisp/find-func-tests.el +++ b/test/lisp/emacs-lisp/find-func-tests.el @@ -95,6 +95,13 @@ expected function symbol and function library, respectively." (advice-remove #'mark-sexp 'my-message)) (ert-deftest find-func-tests--find-library-verbose () + (unwind-protect + (progn + (advice-add 'dired :before #'ignore) + ;; bug#41104 + (should (equal (find-function-library #'dired) '(dired . "dired")))) + (advice-remove 'dired #'ignore)) + (find-function-library #'join-line nil t) (with-current-buffer "*Messages*" (save-excursion commit 3864308c20deb69e7b75420377a3b86716215dd3 Author: Po Lu Date: Tue Jun 7 21:45:17 2022 +0800 Add selection stuff to DND tests * test/lisp/dnd-tests.el (dnd-tests-selection-table): New defvar. (gui-set-selection): Actually implement in a way that validates the local value and stores it for future use. (dnd-tests-verify-selection-data): New function. (dnd-tests-begin-text-drag): Add tests for the contents of various selections. diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index f194f3eac4..a714c4a4e5 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -29,6 +29,7 @@ (require 'dnd) (require 'cl-lib) (require 'tramp) +(require 'select) ;; This code was taken from tramp-tests.el: perhaps some of it isn't ;; strictly necessary. @@ -54,6 +55,9 @@ (format "/mock::%s" temporary-file-directory))) "Temporary directory for drag-and-drop tests involving remote files.") +(defvar dnd-tests-selection-table nil + "Alist of selection names to their values.") + ;; Substitute for x-begin-drag, which isn't present on all systems. (defalias 'x-begin-drag (lambda (_targets &optional action frame &rest _) @@ -73,7 +77,32 @@ ;; This doesn't work during tests. (defalias 'gui-set-selection - (lambda (&rest _))) + (lambda (type data) + (or (gui--valid-simple-selection-p data) + (and (vectorp data) + (let ((valid t)) + (dotimes (i (length data)) + (or (gui--valid-simple-selection-p (aref data i)) + (setq valid nil))) + valid)) + (signal 'error (list "invalid selection" data))) + (setf (alist-get type dnd-tests-selection-table) data))) + +(defun dnd-tests-verify-selection-data (type) + "Return the data of the drag-and-drop selection converted to TYPE." + (let* ((basic-value (cdr (assq 'XdndSelection + dnd-tests-selection-table))) + (local-value (if (stringp basic-value) + (or (get-text-property 0 type basic-value) + basic-value) + basic-value)) + (converter-list (assq type selection-converter-alist)) + (converter (if (consp converter-list) + (cdr converter-list) + converter-list))) + (if (and local-value converter) + (funcall converter 'XdndSelection type local-value) + (error "No selection converter or local value: %s" type)))) (defun dnd-tests-remote-accessible-p () "Return if a test involving remote files can proceed." @@ -90,11 +119,30 @@ The temporary file is not created." dnd-tests-temporary-file-directory)) (ert-deftest dnd-tests-begin-text-drag () - (should (eq (dnd-begin-text-drag "some test text that will be dragged") - 'copy)) - (should (eq (dnd-begin-text-drag "some test text that will be dragged" - nil 'move) - 'move))) + ;; ASCII Latin-1 UTF-8 + (let ((test-text "hello, everyone! sæl öllsömul! всем привет")) + ;; Verify that dragging works. + (should (eq (dnd-begin-text-drag test-text) 'copy)) + (should (eq (dnd-begin-text-drag test-text nil 'move) 'move)) + ;; Verify that the important data types are converted correctly. + (let ((string-data (dnd-tests-verify-selection-data 'STRING))) + ;; Check that the Latin-1 target is converted correctly. + (should (equal (cdr string-data) + (encode-coding-string test-text + 'iso-8859-1)))) + ;; And that UTF8_STRING and the Xdnd UTF8 string are as well. + (let ((string-data (dnd-tests-verify-selection-data + 'UTF8_STRING)) + (string-data-1 (cdr (dnd-tests-verify-selection-data + 'text/plain\;charset=utf-8)))) + (should (and (stringp (cdr string-data)) + (stringp string-data-1))) + (should (equal (cdr string-data) string-data-1))) + ;; Now check text/plain. + (let ((string-data (dnd-tests-verify-selection-data + 'text/plain))) + (should (equal (cdr string-data) + (encode-coding-string test-text 'ascii)))))) (ert-deftest dnd-tests-begin-file-drag () ;; These tests also involve handling remote file names. commit 7f778c6943f66bd1112bd41be19e223b64300509 Author: Eli Zaretskii Date: Tue Jun 7 16:01:04 2022 +0300 Fix debugging with GDB when a breakpoint has multiple locations * lisp/progmodes/gdb-mi.el (gdb-breakpoints--add-breakpoint-row): New function, extracted from 'gdb-breakpoints-list-handler-custom'. Don't print "in " for header-rows of breakpoints with multiple locations that don't have a function name attached. (gdb-breakpoints-list-handler-custom): Add to the breakpoint table also any locations in multiple-location breakpoints, which are supported since GDB 6.8. diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index 66fc4b1a4c..a1385b0dea 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -3076,6 +3076,45 @@ See `def-gdb-auto-update-handler'." 'gdb-breakpoints-mode 'gdb-invalidate-breakpoints) +(defun gdb-breakpoints--add-breakpoint-row (tbl bkpt) + (let ((at (gdb-mi--field bkpt 'at)) + (pending (gdb-mi--field bkpt 'pending)) + (addr (gdb-mi--field bkpt 'addr)) + (func (gdb-mi--field bkpt 'func)) + (type (gdb-mi--field bkpt 'type))) + (if (and (not func) (string-equal addr "")) + (setq func "")) + (gdb-table-add-row tbl + (list + (gdb-mi--field bkpt 'number) + (or type "") + (or (gdb-mi--field bkpt 'disp) "") + (let ((flag (gdb-mi--field bkpt 'enabled))) + (if (string-equal flag "y") + (eval-when-compile + (propertize "y" 'font-lock-face + font-lock-warning-face)) + (eval-when-compile + (propertize "n" 'font-lock-face + font-lock-comment-face)))) + addr + (or (gdb-mi--field bkpt 'times) "") + (if (and type (string-match ".*watchpoint" type)) + (gdb-mi--field bkpt 'what) + (or (and (equal func "") "") + pending at + (concat "in " + (propertize (or func "unknown") + 'font-lock-face + font-lock-function-name-face) + (gdb-frame-location bkpt))))) + ;; Add clickable properties only for + ;; breakpoints with file:line information + (append (list 'gdb-breakpoint bkpt) + (when func + '(help-echo "mouse-2, RET: visit breakpoint" + mouse-face highlight)))))) + (defun gdb-breakpoints-list-handler-custom () (let ((breakpoints-list (gdb-mi--field (gdb-mi--field (gdb-mi--partial-output 'bkpt) @@ -3088,37 +3127,14 @@ See `def-gdb-auto-update-handler'." (add-to-list 'gdb-breakpoints-list (cons (gdb-mi--field breakpoint 'number) breakpoint)) - (let ((at (gdb-mi--field breakpoint 'at)) - (pending (gdb-mi--field breakpoint 'pending)) - (func (gdb-mi--field breakpoint 'func)) - (type (gdb-mi--field breakpoint 'type))) - (gdb-table-add-row table - (list - (gdb-mi--field breakpoint 'number) - (or type "") - (or (gdb-mi--field breakpoint 'disp) "") - (let ((flag (gdb-mi--field breakpoint 'enabled))) - (if (string-equal flag "y") - (eval-when-compile - (propertize "y" 'font-lock-face - font-lock-warning-face)) - (eval-when-compile - (propertize "n" 'font-lock-face - font-lock-comment-face)))) - (gdb-mi--field breakpoint 'addr) - (or (gdb-mi--field breakpoint 'times) "") - (if (and type (string-match ".*watchpoint" type)) - (gdb-mi--field breakpoint 'what) - (or pending at - (concat "in " - (propertize (or func "unknown") - 'font-lock-face font-lock-function-name-face) - (gdb-frame-location breakpoint))))) - ;; Add clickable properties only for breakpoints with file:line - ;; information - (append (list 'gdb-breakpoint breakpoint) - (when func '(help-echo "mouse-2, RET: visit breakpoint" - mouse-face highlight)))))) + ;; Add the breakpoint/header row to the table. + (gdb-breakpoints--add-breakpoint-row table breakpoint) + ;; If this breakpoint has multiple locations, add them as well. + (when-let ((locations (gdb-mi--field breakpoint 'locations))) + (dolist (loc locations) + (add-to-list 'gdb-breakpoints-list + (cons (gdb-mi--field loc 'number) loc)) + (gdb-breakpoints--add-breakpoint-row table loc)))) (insert (gdb-table-string table " ")) (gdb-place-breakpoints))) commit 6a4444aa390f20c195f864a7c1b8114d82ffdeb5 Author: Po Lu Date: Tue Jun 7 12:13:10 2022 +0000 Fix coding style of some Haiku files * src/haiku_support.cc: (FrameResized): (class EmacsView, AfterResize): Fix coding and initializer style. * src/haiku_support.h (struct haiku_resize_event): Rename confusingly named fields. * src/haikuterm.c (haiku_read_socket): Update accordingly. diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 3b1a2cfcb3..3c8e5dc8c2 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -1103,8 +1103,8 @@ class EmacsWindow : public BWindow { struct haiku_resize_event rq; rq.window = this; - rq.px_heightf = newHeight + 1.0f; - rq.px_widthf = newWidth + 1.0f; + rq.width = newWidth + 1.0f; + rq.height = newHeight + 1.0f; haiku_write (FRAME_RESIZED, &rq); BWindow::FrameResized (newWidth, newHeight); @@ -1492,25 +1492,36 @@ class EmacsMenuBar : public BMenuBar class EmacsView : public BView { public: - uint32_t previous_buttons = 0; - int looper_locked_count = 0; + uint32_t previous_buttons; + int looper_locked_count; BRegion sb_region; BRegion invalid_region; - BView *offscreen_draw_view = NULL; - BBitmap *offscreen_draw_bitmap_1 = NULL; - BBitmap *copy_bitmap = NULL; + BView *offscreen_draw_view; + BBitmap *offscreen_draw_bitmap_1; + BBitmap *copy_bitmap; #ifdef USE_BE_CAIRO - cairo_surface_t *cr_surface = NULL; - cairo_t *cr_context = NULL; + cairo_surface_t *cr_surface; + cairo_t *cr_context; BLocker cr_surface_lock; #endif BPoint tt_absl_pos; - BMessage *wait_for_release_message = NULL; - - EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", B_FOLLOW_NONE, B_WILL_DRAW) + BMessage *wait_for_release_message; + + EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs", + B_FOLLOW_NONE, B_WILL_DRAW), + previous_buttons (0), + looper_locked_count (0), + offscreen_draw_view (NULL), + offscreen_draw_bitmap_1 (NULL), + copy_bitmap (NULL), +#ifdef USE_BE_CAIRO + cr_surface (NULL), + cr_context (NULL), +#endif + wait_for_release_message (NULL) { } @@ -1658,9 +1669,7 @@ class EmacsView : public BView #endif if (looper_locked_count) - { - offscreen_draw_bitmap_1->Lock (); - } + offscreen_draw_bitmap_1->Lock (); UnlockLooper (); } diff --git a/src/haiku_support.h b/src/haiku_support.h index 9597c24c5d..a2ad222f85 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -129,8 +129,8 @@ struct haiku_quit_requested_event struct haiku_resize_event { void *window; - float px_heightf; - float px_widthf; + float width; + float height; }; struct haiku_expose_event diff --git a/src/haikuterm.c b/src/haikuterm.c index 0a994b7e60..55e8640ec2 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3143,8 +3143,8 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) if (!f) continue; - int width = lrint (b->px_widthf); - int height = lrint (b->px_heightf); + int width = lrint (b->width); + int height = lrint (b->height); if (FRAME_OUTPUT_DATA (f)->wait_for_event_type == FRAME_RESIZED) commit 254d2a147760f83fa83d361eb6027ffa4000c2d9 Author: Lars Ingebrigtsen Date: Tue Jun 7 13:23:22 2022 +0200 Simplify mode line for vc-print-root-log * lisp/vc/vc.el (vc-print-root-log): Don't display "from " (bug#45007). diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 3508f684c4..d6f0f4a497 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -2654,7 +2654,10 @@ with its diffs (if the underlying VCS supports that)." (error "Directory is not version controlled"))) (setq default-directory rootdir) (vc-print-log-internal backend (list rootdir) revision revision limit - (when with-diff 'with-diff)))) + (when with-diff 'with-diff)) + ;; We're looking at the root, so displaying " from " in + ;; the mode line isn't helpful. + (setq vc-parent-buffer-name nil))) ;;;###autoload (defun vc-print-branch-log (branch) commit 4918ef09153ba2c320909ac83919bda4fa26d108 Author: Po Lu Date: Tue Jun 7 18:23:52 2022 +0800 Fix more bugs with DND selection handling * src/xterm.c (x_defer_selection_requests) (x_release_selection_requests): New functions. (x_dnd_begin_drag_and_drop): Use those functions to defer selections instead. Fix error signalled when ownership of XdndSelection is lost. (handle_one_xevent): Likewise. diff --git a/src/xterm.c b/src/xterm.c index ae46453eb6..0bf4b15daf 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -789,6 +789,22 @@ static int current_finish; static struct input_event *current_hold_quit; #endif +/* Queue selection requests in `pending_selection_requests' if more + than 0. */ +static int x_use_pending_selection_requests; + +static void +x_defer_selection_requests (void) +{ + x_use_pending_selection_requests++; +} + +static void +x_release_selection_requests (void) +{ + x_use_pending_selection_requests--; +} + struct x_selection_request_event { /* The selection request event. */ @@ -10748,6 +10764,14 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (x_dnd_in_progress || x_dnd_waiting_for_finish) error ("A drag-and-drop session is already in progress"); + x_defer_selection_requests (); + record_unwind_protect_void (x_release_selection_requests); + + /* If local_value is nil, then we lost ownership of XdndSelection. + Signal a more informative error than args-out-of-range. */ + if (NILP (local_value)) + error ("Lost ownership of XdndSelection"); + if (CONSP (local_value)) x_own_selection (QXdndSelection, Fnth (make_fixnum (1), local_value), frame); @@ -15877,10 +15901,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; SELECTION_EVENT_TIME (&inev.sie) = eventp->time; - if ((x_dnd_in_progress - && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) - || (x_dnd_waiting_for_finish - && dpyinfo->display == x_dnd_finish_display)) + if (x_use_pending_selection_requests) { x_push_selection_request (&inev.sie); EVENT_INIT (inev.ie); @@ -15908,10 +15929,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, events immediately, by setting hold_quit to the input event. */ - if ((x_dnd_in_progress - && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) - || (x_dnd_waiting_for_finish - && dpyinfo->display == x_dnd_finish_display)) + if (x_use_pending_selection_requests) { x_push_selection_request (&inev.sie); EVENT_INIT (inev.ie); commit dc546d1ca03022e6785eabe8ebf6dc2d9490f292 Author: Lars Ingebrigtsen Date: Tue Jun 7 12:21:53 2022 +0200 Clarify highlight-changes-rotate-faces doc string * lisp/hilit-chg.el (highlight-changes-rotate-faces): Doc string clarification (bug#44150). diff --git a/lisp/hilit-chg.el b/lisp/hilit-chg.el index 10e2512e9d..4832dd9023 100644 --- a/lisp/hilit-chg.el +++ b/lisp/hilit-chg.el @@ -669,7 +669,7 @@ This removes all saved change information." ;;;###autoload (defun highlight-changes-rotate-faces () - "Rotate the faces if in Highlight Changes mode and the changes are visible. + "\"Age\" changes if in Highlight Changes mode and the changes are visible. Current changes are displayed in the face described by the first element of `highlight-changes-face-list', one level older changes are shown in commit 6fe133c3ae0a3aaebb73b9318e81ca8a2bda6d8d Author: Po Lu Date: Tue Jun 7 15:44:05 2022 +0800 Remove mentions of GNOME MediaKeys from dbus documentation examples * doc/misc/dbus.texi (Properties and Annotations): * lisp/net/dbus.el (dbus-get-all-managed-objects): Remove mentions of obsolete GNOME APIs from example text. diff --git a/doc/misc/dbus.texi b/doc/misc/dbus.texi index 0b4f53ba13..bb97446d12 100644 --- a/doc/misc/dbus.texi +++ b/doc/misc/dbus.texi @@ -795,13 +795,7 @@ and interface. Example: (dbus-get-all-managed-objects :session "org.gnome.SettingsDaemon" "/") -@result{} (("/org/gnome/SettingsDaemon/MediaKeys" - ("org.gnome.SettingsDaemon.MediaKeys") - ("org.freedesktop.DBus.Peer") - ("org.freedesktop.DBus.Introspectable") - ("org.freedesktop.DBus.Properties") - ("org.freedesktop.DBus.ObjectManager")) - ("/org/gnome/SettingsDaemon/Power" +@result{} (("/org/gnome/SettingsDaemon/Power" ("org.gnome.SettingsDaemon.Power.Keyboard") ("org.gnome.SettingsDaemon.Power.Screen") ("org.gnome.SettingsDaemon.Power" diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index 6a8bf87967..d4d4ed54e9 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el @@ -1871,13 +1871,7 @@ name and cdr is the list of properties as returned by \(dbus-get-all-managed-objects :session \"org.gnome.SettingsDaemon\" \"/\") - => ((\"/org/gnome/SettingsDaemon/MediaKeys\" - (\"org.gnome.SettingsDaemon.MediaKeys\") - (\"org.freedesktop.DBus.Peer\") - (\"org.freedesktop.DBus.Introspectable\") - (\"org.freedesktop.DBus.Properties\") - (\"org.freedesktop.DBus.ObjectManager\")) - (\"/org/gnome/SettingsDaemon/Power\" + => ((\"/org/gnome/SettingsDaemon/Power\" (\"org.gnome.SettingsDaemon.Power.Keyboard\") (\"org.gnome.SettingsDaemon.Power.Screen\") (\"org.gnome.SettingsDaemon.Power\" commit 3bdeedd8aca18e449bd3700c4ab65055fa183201 Author: Po Lu Date: Tue Jun 7 13:49:41 2022 +0800 Improve compatibility with some clients of the Motif drop protocol * lisp/select.el (x-dnd-targets-list): New defvar. (xselect-convert-to-targets): Convert XdndSelection based on the DND targets list. * src/xfns.c (Fx_begin_drag): Pass new argument. * src/xselect.c (struct x_selection_request): New struct. (x_push_current_selection_request): (x_pop_current_selection_request): New functions. (x_selection_request_lisp_error, x_reply_selection_request) (x_handle_selection_request, x_convert_selection) (syms_of_xselect_for_pdumper): Correctly handle recursive requests for MULTIPLE by maintaining a stack of selection requests, converted selections, and other data. * src/xterm.c (x_dnd_begin_drag_and_drop): New argument `selection_target_list'. Bind it to the DND targets list. (syms_of_xterm): New defvar and associated defsym. * src/xterm.h: Update prototypes. diff --git a/lisp/select.el b/lisp/select.el index 83dc137e23..706197e027 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -601,19 +601,29 @@ two markers or an overlay. Otherwise, it is nil." (if len (xselect--int-to-cons len)))) +(defvar x-dnd-targets-list) + (defun xselect-convert-to-targets (selection _type value) ;; Return a vector of atoms, but remove duplicates first. - (apply #'vector - (delete-dups - `( TIMESTAMP MULTIPLE - . ,(delq '_EMACS_INTERNAL - (mapcar (lambda (conv) - (if (or (not (consp (cdr conv))) - (funcall (cadr conv) selection - (car conv) value)) - (car conv) - '_EMACS_INTERNAL)) - selection-converter-alist)))))) + (if (eq selection 'XdndSelection) + ;; This isn't required by the XDND protocol, and sure enough no + ;; clients seem to dependent on it, but Emacs implements the + ;; receiver side of the Motif drop protocol by looking at the + ;; initiator selection's TARGETS target (which Motif provides) + ;; instead of the target table on the drag window, so it seems + ;; plausible for other clients to rely on that as well. + (apply #'vector (mapcar #'intern x-dnd-targets-list)) + (apply #'vector + (delete-dups + `( TIMESTAMP MULTIPLE + . ,(delq '_EMACS_INTERNAL + (mapcar (lambda (conv) + (if (or (not (consp (cdr conv))) + (funcall (cadr conv) selection + (car conv) value)) + (car conv) + '_EMACS_INTERNAL)) + selection-converter-alist))))))) (defun xselect-convert-to-delete (selection _type _value) ;; This should be handled by the caller of `x-begin-drag'. diff --git a/src/xfns.c b/src/xfns.c index cfc6d4c212..cffb4a5d96 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6985,7 +6985,7 @@ that mouse buttons are being held down, such as immediately after a xaction, return_frame, action_list, (const char **) &name_list, nnames, !NILP (allow_current_frame), target_atoms, - ntargets); + ntargets, original); SAFE_FREE (); return lval; diff --git a/src/xselect.c b/src/xselect.c index b920540620..0271310d04 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -417,14 +417,6 @@ x_decline_selection_request (struct selection_input_event *event) unblock_input (); } -/* This is the selection request currently being processed. - It is set to zero when the request is fully processed. */ -static struct selection_input_event *x_selection_current_request; - -/* Display info in x_selection_request. */ - -static struct x_display_info *selection_request_dpyinfo; - /* Raw selection data, for sending to a requestor window. */ struct selection_data @@ -442,12 +434,59 @@ struct selection_data struct selection_data *next; }; -/* Linked list of the above (in support of MULTIPLE targets). */ +struct x_selection_request +{ + /* The last element in this stack. */ + struct x_selection_request *last; + + /* Its display info. */ + struct x_display_info *dpyinfo; + + /* Its selection input event. */ + struct selection_input_event *request; + + /* Linked list of the above (in support of MULTIPLE targets). */ + struct selection_data *converted_selections; -static struct selection_data *converted_selections; + /* "Data" to send a requestor for a failed MULTIPLE subtarget. */ + Atom conversion_fail_tag; + + /* Whether or not conversion was successful. */ + bool converted; +}; + +/* Stack of selections currently being processed. + NULL if all requests have been fully processed. */ + +struct x_selection_request *selection_request_stack; + +static void +x_push_current_selection_request (struct selection_input_event *se, + struct x_display_info *dpyinfo) +{ + struct x_selection_request *frame; -/* "Data" to send a requestor for a failed MULTIPLE subtarget. */ -static Atom conversion_fail_tag; + frame = xmalloc (sizeof *frame); + frame->converted = false; + frame->last = selection_request_stack; + frame->request = se; + frame->dpyinfo = dpyinfo; + frame->converted_selections = NULL; + frame->conversion_fail_tag = None; + + selection_request_stack = frame; +} + +static void +x_pop_current_selection_request (void) +{ + struct x_selection_request *tem; + + tem = selection_request_stack; + selection_request_stack = selection_request_stack->last; + + xfree (tem); +} /* Used as an unwind-protect clause so that, if a selection-converter signals an error, we tell the requestor that we were unable to do what they wanted @@ -457,19 +496,21 @@ static void x_selection_request_lisp_error (void) { struct selection_data *cs, *next; + struct x_selection_request *frame; + + frame = selection_request_stack; - for (cs = converted_selections; cs; cs = next) + for (cs = frame->converted_selections; cs; cs = next) { next = cs->next; if (! cs->nofree && cs->data) xfree (cs->data); xfree (cs); } - converted_selections = NULL; + frame->converted_selections = NULL; - if (x_selection_current_request != 0 - && selection_request_dpyinfo->display) - x_decline_selection_request (x_selection_current_request); + if (!frame->converted && frame->dpyinfo->display) + x_decline_selection_request (frame->request); } static void @@ -535,6 +576,9 @@ x_reply_selection_request (struct selection_input_event *event, int max_bytes = selection_quantum (display); specpdl_ref count = SPECPDL_INDEX (); struct selection_data *cs; + struct x_selection_request *frame; + + frame = selection_request_stack; reply->type = SelectionNotify; reply->display = display; @@ -558,7 +602,7 @@ x_reply_selection_request (struct selection_input_event *event, (section 2.7.2 of ICCCM). Note that we store the data for a MULTIPLE request in the opposite order; the ICCM says only that the conversion itself must be done in the same order. */ - for (cs = converted_selections; cs; cs = cs->next) + for (cs = frame->converted_selections; cs; cs = cs->next) { if (cs->property == None) continue; @@ -613,7 +657,7 @@ x_reply_selection_request (struct selection_input_event *event, be improved; there's a chance of deadlock if more than one subtarget in a MULTIPLE selection requires an INCR transfer, and the requestor and Emacs loop waiting on different transfers. */ - for (cs = converted_selections; cs; cs = cs->next) + for (cs = frame->converted_selections; cs; cs = cs->next) if (cs->wait_object) { int format_bytes = cs->format / 8; @@ -749,9 +793,11 @@ x_handle_selection_request (struct selection_input_event *event) && local_selection_time > SELECTION_EVENT_TIME (event)) goto DONE; - x_selection_current_request = event; - selection_request_dpyinfo = dpyinfo; + block_input (); + x_push_current_selection_request (event, dpyinfo); + record_unwind_protect_void (x_pop_current_selection_request); record_unwind_protect_void (x_selection_request_lisp_error); + unblock_input (); TRACE2 ("x_handle_selection_request: selection=%s, target=%s", SDATA (SYMBOL_NAME (selection_symbol)), @@ -808,11 +854,12 @@ x_handle_selection_request (struct selection_input_event *event) DONE: + selection_request_stack->converted = true; + if (success) x_reply_selection_request (event, dpyinfo); else x_decline_selection_request (event); - x_selection_current_request = 0; /* Run the `x-sent-selection-functions' abnormal hook. */ if (!NILP (Vx_sent_selection_functions) @@ -837,11 +884,14 @@ x_convert_selection (Lisp_Object selection_symbol, { Lisp_Object lisp_selection; struct selection_data *cs; + struct x_selection_request *frame; lisp_selection = x_get_local_selection (selection_symbol, target_symbol, false, dpyinfo); + frame = selection_request_stack; + /* A nil return value means we can't perform the conversion. */ if (NILP (lisp_selection) || (CONSP (lisp_selection) && NILP (XCDR (lisp_selection)))) @@ -849,15 +899,16 @@ x_convert_selection (Lisp_Object selection_symbol, if (for_multiple) { cs = xmalloc (sizeof *cs); - cs->data = (unsigned char *) &conversion_fail_tag; + cs->data = ((unsigned char *) + &selection_request_stack->conversion_fail_tag); cs->size = 1; cs->format = 32; cs->type = XA_ATOM; cs->nofree = true; cs->property = property; cs->wait_object = NULL; - cs->next = converted_selections; - converted_selections = cs; + cs->next = frame->converted_selections; + frame->converted_selections = cs; } return false; @@ -869,8 +920,8 @@ x_convert_selection (Lisp_Object selection_symbol, cs->nofree = true; cs->property = property; cs->wait_object = NULL; - cs->next = converted_selections; - converted_selections = cs; + cs->next = frame->converted_selections; + frame->converted_selections = cs; lisp_data_to_selection_data (dpyinfo, lisp_selection, cs); return true; } @@ -2777,6 +2828,4 @@ syms_of_xselect_for_pdumper (void) property_change_wait_list = 0; prop_location_identifier = 0; property_change_reply = Fcons (Qnil, Qnil); - converted_selections = NULL; - conversion_fail_tag = None; } diff --git a/src/xterm.c b/src/xterm.c index 4dce24104d..ae46453eb6 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10645,7 +10645,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, Lisp_Object return_frame, Atom *ask_action_list, const char **ask_action_names, size_t n_ask_actions, bool allow_current_frame, Atom *target_atoms, - int ntargets) + int ntargets, Lisp_Object selection_target_list) { #ifndef USE_GTK XEvent next_event; @@ -10674,6 +10674,10 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, base = SPECPDL_INDEX (); + /* Bind this here to avoid juggling bindings and SAFE_FREE in + Fx_begin_drag. */ + specbind (Qx_dnd_targets_list, selection_target_list); + /* Before starting drag-and-drop, walk through the keyboard buffer to see if there are any UNSUPPORTED_DROP_EVENTs, and run them now if they exist, to prevent race conditions from happening due to @@ -26516,6 +26520,7 @@ syms_of_xterm (void) DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms"); DEFSYM (Qlatin_1, "latin-1"); DEFSYM (Qnow, "now"); + DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list"); #ifdef USE_GTK xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg"); @@ -26752,4 +26757,11 @@ operation, and TIME is the X server time when the drop happened. */); doc: /* Max number of buckets allowed per display in the internal color cache. Values less than 1 mean 128. This option is for debugging only. */); x_color_cache_bucket_size = 128; + + DEFVAR_LISP ("x-dnd-targets-list", Vx_dnd_targets_list, + doc: /* List of drag-and-drop targets. +This variable contains the list of drag-and-drop selection targets +during a drag-and-drop operation, in the same format as the TARGET +argument to `x-begin-drag'. */); + Vx_dnd_targets_list = Qnil; } diff --git a/src/xterm.h b/src/xterm.h index c6be30d73e..1ab65f15d1 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1460,7 +1460,8 @@ extern void x_handle_pending_selection_requests (void); extern bool x_detect_pending_selection_requests (void); extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, Lisp_Object, Atom *, const char **, - size_t, bool, Atom *, int); + size_t, bool, Atom *, int, + Lisp_Object); extern void x_dnd_do_unsupported_drop (struct x_display_info *, Lisp_Object, Lisp_Object, Lisp_Object, Window, int, int, Time); commit 6871e649b52e3a6154cfe2495372c4652688588f Author: Po Lu Date: Tue Jun 7 13:07:26 2022 +0800 Add new drag-and-drop test * test/lisp/dnd-tests.el (dnd-tests-get-local-file-uri): New test. diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el index fbd6ce6a2c..f194f3eac4 100644 --- a/test/lisp/dnd-tests.el +++ b/test/lisp/dnd-tests.el @@ -21,8 +21,8 @@ ;; Tests for stuff in dnd.el that doesn't require a window system. -;; At present, these tests only checks the behavior of the simplified -;; drag APIs in dnd.el. Actual drags are not performed. +;; The drag API tests only check the behavior of the simplified drag +;; APIs in dnd.el. Actual drags are not performed. ;;; Code: @@ -194,5 +194,14 @@ The temporary file is not created." (delete-file normal-temp-file-1) (delete-file remote-temp-file)))) +(ert-deftest dnd-tests-get-local-file-uri () + (should (equal (dnd-get-local-file-uri "file://localhost/path/to/foo") + "file:///path/to/foo")) + (should (equal (dnd-get-local-file-uri + (format "file://%s/path/to/" (system-name))) + "file:///path/to/")) + (should-not (dnd-get-local-file-uri "file://some-remote-host/path/to/foo")) + (should-not (dnd-get-local-file-uri "file:///path/to/foo"))) + (provide 'dnd-tests) ;;; dnd-tests.el ends here commit 192de232bfe1270421a97c37987f0f19ad66175c Author: Po Lu Date: Tue Jun 7 12:59:37 2022 +0800 Fix leak of event data on GTK+ 2.x * src/xterm.c (handle_one_xevent): Fix goto XI_OTHER for valuator motion events generated on scroll bars. diff --git a/src/xterm.c b/src/xterm.c index a11a22ab10..4dce24104d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -18735,12 +18735,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, So instead of that, just ignore XI wheel events which land on a scroll bar. - Here we assume anything which isn't the edit - widget window is a scroll bar. */ + Here we assume anything which isn't the edit + widget window is a scroll bar. */ if (xev->child != None && xev->child != FRAME_X_WINDOW (f)) - goto OTHER; + goto XI_OTHER; #endif if (fabs (total_x) > 0 || fabs (total_y) > 0) commit f6f5634378228bf170576d5fad691a9708e3023c Author: Po Lu Date: Tue Jun 7 02:44:08 2022 +0000 Update Haiku drag-and-drop code * lisp/term/haiku-win.el (haiku-drag-and-drop): Don't allow dropping on places other than the text area (it doesn't work). Also respect mouse-yank-at-point. diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 0dcfc1e920..6ddf546ee5 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -311,6 +311,9 @@ or a pair of markers) and turns it into a file system reference." (if (eq string 'lambda) ; This means the mouse moved. (dnd-handle-movement (event-start event)) (cond + ;; Don't allow dropping on something other than the text area. + ;; It does nothing and doesn't work with text anyway. + ((posn-area (event-start event))) ((assoc "refs" string) (with-selected-window window (raise-frame) @@ -326,7 +329,8 @@ or a pair of markers) and turns it into a file system reference." (with-selected-window window (raise-frame) (dolist (text (cddr (assoc "text/plain" string))) - (goto-char (posn-point (event-start event))) + (unless mouse-yank-at-point + (goto-char (posn-point (event-start event)))) (dnd-insert-text window 'private (if (multibyte-string-p text) text commit c60cb3baa7e0dbb3ff17d431942ae2b60ffd9c3d Author: Po Lu Date: Tue Jun 7 10:39:55 2022 +0800 Don't allow dropping on invalid drop sites * lisp/x-dnd.el (x-dnd-drop-data): If dropping on something other than the text area, don't set point. (x-dnd-handle-xdnd, x-dnd-handle-motif): Don't pretend dropping on the mode line is ok. diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el index f3abb9d5e6..7befea7418 100644 --- a/lisp/x-dnd.el +++ b/lisp/x-dnd.el @@ -333,7 +333,10 @@ nil if not." ;; If dropping in an ordinary window which we could use, ;; let dnd-open-file-other-window specify what to do. (progn - (when (not mouse-yank-at-point) + (when (and (not mouse-yank-at-point) + ;; If dropping on top of the mode line, insert + ;; the text at point instead. + (posn-point (event-start event))) (goto-char (posn-point (event-start event)))) (funcall handler window action data)) ;; If we can't display the file here, @@ -487,7 +490,11 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (reply-action (car (rassoc (car action-type) x-dnd-xdnd-to-action))) (accept ;; 1 = accept, 0 = reject - (if (and reply-action action-type) 1 0)) + (if (and reply-action action-type + ;; Only allow drops on the text area of a + ;; window. + (not (posn-area (event-start event)))) + 1 0)) (list-to-send (list (string-to-number (frame-parameter frame 'outer-window-id)) @@ -495,8 +502,7 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (x-dnd-get-drop-x-y frame window) (x-dnd-get-drop-width-height frame window (eq accept 1)) - (or reply-action 0) - ))) + (or reply-action 0)))) (x-send-client-message frame dnd-source frame "XdndStatus" 32 list-to-send) (dnd-handle-movement (event-start event)))) @@ -653,13 +659,16 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (reply-action (car (rassoc (car action-type) x-dnd-motif-to-action))) (reply-flags - (x-dnd-motif-value-to-list - (if reply-action - (+ reply-action - ?\x30 ; 30: valid drop site - ?\x700) ; 700: can do copy, move or link - ?\x30) ; 30: drop site, but noop. - 2 my-byteorder)) + (if (posn-area (event-start event)) + (x-dnd-motif-value-to-list ?\x20 ; 20: invalid drop site + 2 my-byteorder) + (x-dnd-motif-value-to-list + (if reply-action + (+ reply-action + ?\x30 ; 30: valid drop site + ?\x700) ; 700: can do copy, move or link + ?\x30) ; 30: drop site, but noop. + 2 my-byteorder))) (reply (append (list (+ ?\x80 ; 0x80 indicates a reply. @@ -691,13 +700,16 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (reply-action (car (rassoc (car action-type) x-dnd-motif-to-action))) (reply-flags - (x-dnd-motif-value-to-list - (if reply-action - (+ reply-action - ?\x30 ; 30: valid drop site - ?\x700) ; 700: can do copy, move or link - ?\x30) ; 30: drop site, but noop - 2 my-byteorder)) + (if (posn-area (event-start event)) + (x-dnd-motif-value-to-list ?\x20 ; 20: invalid drop site + 2 my-byteorder) + (x-dnd-motif-value-to-list + (if reply-action + (+ reply-action + ?\x30 ; 30: valid drop site + ?\x700) ; 700: can do copy, move or link + ?\x30) ; 30: drop site, but noop. + 2 my-byteorder))) (reply (append (list (+ ?\x80 ; 0x80 indicates a reply. @@ -727,25 +739,28 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." (action-type (x-dnd-maybe-call-test-function window source-action)) - (reply-action (car (rassoc (car action-type) - x-dnd-motif-to-action))) + (reply-action (and (not (posn-area (event-start event))) + (car (rassoc (car action-type) + x-dnd-motif-to-action)))) (reply-flags (x-dnd-motif-value-to-list - (if reply-action - (+ reply-action - ?\x30 ; 30: valid drop site - ?\x700) ; 700: can do copy, move or link - (+ ?\x30 ; 30: drop site, but noop. - ?\x200)) ; 200: drop cancel. - 2 my-byteorder)) + (if (posn-area (event-start event)) + (+ ?\x20 ; 20: invalid drop site + ?\x200) ; 200: drop cancel + (if reply-action + (+ reply-action + ?\x30 ; 30: valid drop site + ?\x700) ; 700: can do copy, move or link + (+ ?\x30 ; 30: drop site, but noop. + ?\x200))) ; 200: drop cancel. + 2 my-byteorder)) (reply (append (list (+ ?\x80 ; 0x80 indicates a reply. 5) ; DROP_START. my-byteorder) reply-flags - x - y)) + x y)) (timestamp (x-dnd-get-motif-value data 4 4 source-byteorder)) action) @@ -774,7 +789,8 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent." timestamp) (x-dnd-forget-drop frame))) - (t (message "Unknown Motif drag-and-drop message: %s" (logand (aref data 0) #x3f))))))) + (t (message "Unknown Motif drag-and-drop message: %s" + (logand (aref data 0) #x3f))))))) ;;; commit cbc0d8f7c76c97efbc8595d8bd7c840975884786 Author: Po Lu Date: Tue Jun 7 10:27:03 2022 +0800 Don't display mouse face during mouse drag-and-drop * lisp/mouse.el (mouse-drag-and-drop-region): Don't display mouse face, since it leads to a lot of flicker. diff --git a/lisp/mouse.el b/lisp/mouse.el index 737c507870..024a018bb9 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -3085,6 +3085,7 @@ is copied instead of being cut." (display-multi-frame-p) (require 'tooltip)) mouse-drag-and-drop-region-show-tooltip)) + (mouse-highlight nil) (start (region-beginning)) (end (region-end)) (point (point)) commit e21c761d13faa158fb8445a0df4a7af666ea2782 Author: Po Lu Date: Tue Jun 7 09:45:41 2022 +0800 Prevent crashes with very large Motif targets tables * src/xterm.c (xm_setup_dnd_targets): Catch errors around xm_write_targets_table lest we get a BadAlloc error. diff --git a/src/xterm.c b/src/xterm.c index ee396f38cc..a11a22ab10 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2029,9 +2029,16 @@ xm_setup_dnd_targets (struct x_display_info *dpyinfo, it back to 0. There will probably be no more updates to the protocol either. */ header.protocol = XM_DRAG_PROTOCOL_VERSION; + + x_catch_errors (dpyinfo->display); xm_write_targets_table (dpyinfo->display, drag_window, dpyinfo->Xatom_MOTIF_DRAG_TARGETS, &header, recs); + /* Presumably we got a BadAlloc upon writing the targets + table. */ + if (x_had_errors_p (dpyinfo->display)) + idx = -1; + x_uncatch_errors_after_check (); } XUngrabServer (dpyinfo->display); commit 2267b48cac3c8e8a834b4faaa5390f2ad6a54281 Author: Po Lu Date: Tue Jun 7 09:26:15 2022 +0800 Fix two crashes when a display connection is lost This fixes errors caused by invalid error traps being left on the error handler stack if an IO error causes a non-local exit out of the protected code, and another crash caused by delete_frame trying to read async input. * src/eval.c (unwind_to_catch, push_handler_nosignal): Save and restore the X error handler stack. * src/lisp.h (struct handler): [HAVE_X_WINDOWS]: New field `x_error_handler_depth'. * src/xterm.c (struct x_error_message_stack): Make string a regular string. (x_unwind_errors_to): New function. (x_error_catcher, x_catch_errors_with_handler) (x_uncatch_errors_after_check, x_uncatch_errors): Update the stack depth. (x_check_errors): Stop manually unwinding since unwind_to_catch now does that for us. (x_had_errors_p, x_clear_errors): Update for new type of `string'. (x_connection_closed): Block input between just before delete_frame to when the terminal is unlinked. * src/xterm.h: Update prototypes. diff --git a/src/eval.c b/src/eval.c index c3be1dc12c..d4d4a6cfdd 100644 --- a/src/eval.c +++ b/src/eval.c @@ -1251,6 +1251,13 @@ unwind_to_catch (struct handler *catch, enum nonlocal_exit type, set_poll_suppress_count (catch->poll_suppress_count); unblock_input_to (catch->interrupt_input_blocked); +#ifdef HAVE_X_WINDOWS + /* Restore the X error handler stack. This is important because + otherwise a display disconnect won't unwind the stack of error + traps to the right depth. */ + x_unwind_errors_to (catch->x_error_handler_depth); +#endif + do { /* Unwind the specpdl stack, and then restore the proper set of @@ -1625,6 +1632,9 @@ push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype) c->act_rec = get_act_rec (current_thread); c->poll_suppress_count = poll_suppress_count; c->interrupt_input_blocked = interrupt_input_blocked; +#ifdef HAVE_X_WINDOWS + c->x_error_handler_depth = x_error_message_count; +#endif handlerlist = c; return c; } diff --git a/src/lisp.h b/src/lisp.h index ff6f0aaf54..499bacc330 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -3631,6 +3631,10 @@ struct handler struct bc_frame *act_rec; int poll_suppress_count; int interrupt_input_blocked; + +#ifdef HAVE_X_WINDOWS + int x_error_handler_depth; +#endif }; extern Lisp_Object memory_signal_data; diff --git a/src/xterm.c b/src/xterm.c index fa7e285425..ee396f38cc 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -21781,13 +21781,12 @@ x_text_icon (struct frame *f, const char *icon_name) return false; } -#define X_ERROR_MESSAGE_SIZE 200 struct x_error_message_stack { - /* Buffer containing the error message of any error that was - generated. */ - char string[X_ERROR_MESSAGE_SIZE]; + /* Pointer to the error message of any error that was generated, or + NULL. */ + char *string; /* The display this error handler applies to. */ Display *dpy; @@ -21817,6 +21816,9 @@ struct x_error_message_stack placed before 2006. */ static struct x_error_message_stack *x_error_message; +/* The amount of items (depth) in that stack. */ +int x_error_message_count; + static struct x_error_message_stack * x_find_error_handler (Display *dpy, XErrorEvent *event) { @@ -21837,6 +21839,17 @@ x_find_error_handler (Display *dpy, XErrorEvent *event) return NULL; } +void +x_unwind_errors_to (int depth) +{ + while (x_error_message_count > depth) + /* This is safe to call because we check whether or not + x_error_message->dpy is still alive before calling XSync. */ + x_uncatch_errors (); +} + +#define X_ERROR_MESSAGE_SIZE 200 + /* An X error handler which stores the error message in the first applicable handler in the x_error_message stack. This is called from *x_error_handler if an x_catch_errors for DISPLAY is in @@ -21846,8 +21859,15 @@ static void x_error_catcher (Display *display, XErrorEvent *event, struct x_error_message_stack *stack) { + char buf[X_ERROR_MESSAGE_SIZE]; + XGetErrorText (display, event->error_code, - stack->string, X_ERROR_MESSAGE_SIZE); + buf, X_ERROR_MESSAGE_SIZE); + + if (stack->string) + xfree (stack->string); + + stack->string = xstrdup (buf); if (stack->handler) stack->handler (display, event, stack->string, @@ -21875,15 +21895,17 @@ void x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler, void *handler_data) { - struct x_error_message_stack *data = xmalloc (sizeof *data); + struct x_error_message_stack *data; + data = xzalloc (sizeof *data); data->dpy = dpy; - data->string[0] = 0; data->handler = handler; data->handler_data = handler_data; data->prev = x_error_message; data->first_request = NextRequest (dpy); x_error_message = data; + + ++x_error_message_count; } void @@ -21907,6 +21929,9 @@ x_uncatch_errors_after_check (void) block_input (); tmp = x_error_message; x_error_message = x_error_message->prev; + --x_error_message_count; + if (tmp->string) + xfree (tmp->string); xfree (tmp); unblock_input (); } @@ -21942,6 +21967,9 @@ x_uncatch_errors (void) tmp = x_error_message; x_error_message = x_error_message->prev; + --x_error_message_count; + if (tmp->string) + xfree (tmp->string); xfree (tmp); unblock_input (); } @@ -21953,7 +21981,7 @@ x_uncatch_errors (void) void x_check_errors (Display *dpy, const char *format) { - char string[X_ERROR_MESSAGE_SIZE]; + char *string; /* This shouldn't happen, since x_check_errors should be called immediately inside an x_catch_errors block. */ @@ -21968,11 +21996,11 @@ x_check_errors (Display *dpy, const char *format) > x_error_message->first_request)) XSync (dpy, False); - if (x_error_message->string[0]) + if (x_error_message->string) { - memcpy (string, x_error_message->string, - X_ERROR_MESSAGE_SIZE); - x_uncatch_errors (); + string = alloca (strlen (x_error_message->string) + 1); + strcpy (string, x_error_message->string); + error (format, string); } } @@ -21995,7 +22023,7 @@ x_had_errors_p (Display *dpy) > x_error_message->first_request)) XSync (dpy, False); - return x_error_message->string[0] != 0; + return x_error_message->string; } /* Forget about any errors we have had, since we did x_catch_errors on @@ -22009,7 +22037,8 @@ x_clear_errors (Display *dpy) if (dpy != x_error_message->dpy) emacs_abort (); - x_error_message->string[0] = 0; + xfree (x_error_message->string); + x_error_message->string = NULL; } #if false @@ -22142,6 +22171,12 @@ x_connection_closed (Display *dpy, const char *error_message, bool ioerror) dpyinfo->display = 0; } + /* delete_frame can still try to read async input (even though we + tell pass `noelisp'), because looking up the `delete-before' + parameter calls Fassq which then calls maybe_quit. So block + input while deleting frames. */ + block_input (); + /* First delete frames whose mini-buffers are on frames that are on the dead display. */ FOR_EACH_FRAME (tail, frame) @@ -22206,6 +22241,8 @@ For details, see etc/PROBLEMS.\n", } } + unblock_input (); + if (terminal_list == 0) { fprintf (stderr, "%s\n", error_msg); diff --git a/src/xterm.h b/src/xterm.h index 22c6b55176..c6be30d73e 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1396,6 +1396,7 @@ extern void x_catch_errors_with_handler (Display *, x_special_error_handler, extern void x_check_errors (Display *, const char *) ATTRIBUTE_FORMAT_PRINTF (2, 0); extern bool x_had_errors_p (Display *); +extern void x_unwind_errors_to (int); extern void x_uncatch_errors (void); extern void x_uncatch_errors_after_check (void); extern void x_clear_errors (Display *); @@ -1615,6 +1616,7 @@ extern bool x_dnd_waiting_for_finish; extern struct frame *x_dnd_frame; extern struct frame *x_dnd_finish_frame; extern unsigned x_dnd_unsupported_event_level; +extern int x_error_message_count; #ifdef HAVE_XINPUT2 extern struct xi_device_t *xi_device_from_id (struct x_display_info *, int); commit 8c252e2326a3f633d281d70d2f9e7e75975ebdab Author: Lars Ingebrigtsen Date: Mon Jun 6 16:43:12 2022 +0200 Fix execute-extended-command help text for remapped commands * lisp/simple.el (execute-extended-command): Don't provide misleading help text for remapped commands (bug#23543). diff --git a/lisp/simple.el b/lisp/simple.el index ac41b394a7..f6932339c9 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2450,6 +2450,11 @@ invoking, give a prefix argument to `execute-extended-command'." (find-shorter nil)) (unless (commandp function) (error "`%s' is not a valid command name" command-name)) + ;; If we're executing a command that's remapped, we can't actually + ;; execute that command with the keymapping we've found with + ;; `where-is-internal'. + (when (and binding (command-remapping function)) + (setq binding nil)) ;; Some features, such as novice.el, rely on this-command-keys ;; including M-x COMMAND-NAME RET. (set--this-command-keys (concat "\M-x" (symbol-name function) "\r")) commit dc9337aacd682b6346b7918ec9b3067e3a06269b Author: Stephen Berman Date: Mon Jun 6 16:11:50 2022 +0200 Allow using xref buttons in non-*Help* buffers * lisp/help-mode.el (help-buffer): Allow using the xref buttons in non-*Help* buffers (bug#8147) (but display the result in a *Help* buffer). diff --git a/lisp/help-mode.el b/lisp/help-mode.el index 2fcb8b9f3e..a50524253b 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -515,17 +515,16 @@ restore it properly when going back." ;;;###autoload (defun help-buffer () "Return the name of a buffer for inserting help. -If `help-xref-following' is non-nil, this is the name of the -current buffer. Signal an error if this buffer is not derived -from `help-mode'. +If `help-xref-following' is non-nil and the current buffer is +derived from `help-mode', this is the name of the current buffer. + Otherwise, return \"*Help*\", creating a buffer with that name if it does not already exist." - (buffer-name ;for with-output-to-temp-buffer - (if (not help-xref-following) - (get-buffer-create "*Help*") - (unless (derived-mode-p 'help-mode) - (error "Current buffer is not in Help mode")) - (current-buffer)))) + (buffer-name ;for with-output-to-temp-buffer + (if (and help-xref-following + (derived-mode-p 'help-mode)) + (current-buffer) + (get-buffer-create "*Help*")))) (defvar describe-symbol-backends `((nil ,#'fboundp ,(lambda (s _b _f) (describe-function s))) diff --git a/test/lisp/help-mode-tests.el b/test/lisp/help-mode-tests.el index b5bdf6b8d4..04241f3138 100644 --- a/test/lisp/help-mode-tests.el +++ b/test/lisp/help-mode-tests.el @@ -41,11 +41,6 @@ (should (equal (buffer-name (current-buffer)) (help-buffer)))))) -(ert-deftest help-mode-tests-help-buffer-current-buffer-error () - (with-temp-buffer - (let ((help-xref-following t)) - (should-error (help-buffer))))) - (ert-deftest help-mode-tests-make-xrefs () (with-temp-buffer (insert "car is a built-in function in ‘C source code’. commit f3062c41048143e065a95d035e4a932f5457648a Author: Eli Zaretskii Date: Mon Jun 6 17:10:21 2022 +0300 ; * lisp/emacs-lisp/lisp.el (raise-sexp): Doc fix. (Bug#55788) diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index d6086abe59..641ce0d5c0 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -857,10 +857,14 @@ The option `delete-pair-blink-delay' can disable blinking." (delete-char -1))) (delete-char 1)))) -(defun raise-sexp (&optional arg) - "Raise ARG sexps higher up the tree. -This means that the ARGth enclosing form will be deleted and -replaced with the form that follows point. +(defun raise-sexp (&optional n) + "Raise N sexps one level higher up the tree. + +This function removes the sexp enclosing the form which follows +point, and then re-inserts N sexps that originally followe point, +thus raising those N sexps one level up. + +Interactively, N is the numeric prefix argument, and defaults to 1. For instance, if you have: @@ -879,7 +883,7 @@ and point is before (zot), \\[raise-sexp] will give you (buffer-substring (region-beginning) (region-end)) (buffer-substring (point) - (save-excursion (forward-sexp arg) (point)))))) + (save-excursion (forward-sexp n) (point)))))) (backward-up-list 1) (delete-region (point) (save-excursion (forward-sexp 1) (point))) (save-excursion (insert s)))) commit 7edf3d29029a884bbc30babe2bc105ac27aa61da Author: Lars Ingebrigtsen Date: Mon Jun 6 15:49:36 2022 +0200 Make find-file-noselect not pick buffers with broken symlinks * lisp/files.el (find-buffer-visiting): Improve doc string. (find-file-noselect): Don't pick buffers with broken symlinks, because that's too confusing (bug#41414). diff --git a/lisp/files.el b/lisp/files.el index 07ab2b45a5..d876a76119 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -2102,8 +2102,11 @@ started Emacs, set `abbreviated-home-dir' to nil so it will be recalculated)." "Return the buffer visiting file FILENAME (a string). This is like `get-file-buffer', except that it checks for any buffer visiting the same file, possibly under a different name. + If PREDICATE is non-nil, only buffers satisfying it are eligible, -and others are ignored. +and others are ignored. PREDICATE is called with the buffer as +the only argument, but not with the buffer as the current buffer. + If there is no such live buffer, return nil." (let ((predicate (or predicate #'identity)) (truename (abbreviate-file-name (file-truename filename)))) @@ -2324,7 +2327,16 @@ the various files." (attributes (file-attributes truename)) (number (nthcdr 10 attributes)) ;; Find any buffer for a file that has same truename. - (other (and (not buf) (find-buffer-visiting filename)))) + (other (and (not buf) + (find-buffer-visiting + filename + ;; We want to filter out buffers that we've + ;; visited via symlinks and the like, where + ;; the symlink no longer exists. + (lambda (buffer) + (let ((file (buffer-local-value + 'buffer-file-name buffer))) + (and file (file-exists-p file)))))))) ;; Let user know if there is a buffer with the same truename. (if other (progn commit 4c2ba16500dd86e70bc1bd4845292f0094f5ce2f Author: Lars Ingebrigtsen Date: Mon Jun 6 15:32:03 2022 +0200 Improve scheme-mode syntax-rules indentation * lisp/progmodes/scheme.el (syntax-rules): Indent syntax-rules with a parameter better (bug#40869). diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el index cf1d394983..9b24c2155d 100644 --- a/lisp/progmodes/scheme.el +++ b/lisp/progmodes/scheme.el @@ -587,7 +587,7 @@ indentation." (put 'sequence 'scheme-indent-function 0) ; SICP, not r4rs (put 'let-syntax 'scheme-indent-function 1) (put 'letrec-syntax 'scheme-indent-function 1) -(put 'syntax-rules 'scheme-indent-function 1) +(put 'syntax-rules 'scheme-indent-function 'defun) (put 'syntax-case 'scheme-indent-function 2) ; not r5rs (put 'with-syntax 'scheme-indent-function 1) (put 'library 'scheme-indent-function 1) ; R6RS commit 5f12e288a51eb70e7d38a111d610cb09dfe04332 Author: Lars Ingebrigtsen Date: Mon Jun 6 14:34:41 2022 +0200 Improve find-sibling-file error reporting * lisp/files.el (find-sibling-file): Improve error reporting. diff --git a/lisp/files.el b/lisp/files.el index 97e58946bd..07ab2b45a5 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7303,16 +7303,22 @@ The \"sibling\" file is defined by the `find-sibling-rules' variable." (unless buffer-file-name (user-error "Not visiting a file")) (list buffer-file-name))) + (unless find-sibling-rules + (user-error "The `find-sibling-rules' variable has not been configured")) (let ((siblings (find-sibling-file--search (expand-file-name file)))) - (if (length= siblings 1) - (find-file (car siblings)) + (cond + ((null siblings) + (user-error "Couldn't find any sibling files")) + ((length= siblings 1) + (find-file (car siblings))) + (t (let ((relatives (mapcar (lambda (sibling) (file-relative-name sibling (file-name-directory file))) siblings))) (find-file (completing-read (format-prompt "Find file" (car relatives)) - relatives nil t nil nil (car relatives))))))) + relatives nil t nil nil (car relatives)))))))) (defun find-sibling-file--search (file) (let ((results nil)) commit cf599c9fb8905db314abddb6d94714cfec299478 Author: Po Lu Date: Mon Jun 6 20:23:20 2022 +0800 Update comments in X error handling code * src/xterm.c (struct x_error_message_stack, x_error_message) (x_error_catcher, x_catch_errors, x_had_errors_p) (x_clear_errors): Long-overdue comment update. Describe the fields of the error message stack, and the fact that `x_error_message' is a stack, not a pointer to a string (which has been true since 2006). Also describe the updated conditions used to find an applicable error handler and to call x_uncatch_errors_after_check. diff --git a/src/xterm.c b/src/xterm.c index 27ee01dbce..fa7e285425 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -21783,18 +21783,22 @@ x_text_icon (struct frame *f, const char *icon_name) #define X_ERROR_MESSAGE_SIZE 200 -/* If non-nil, this should be a string. It means catch X errors and - store the error message in this string. - - The reason we use a stack is that x_catch_error/x_uncatch_error can - be called from a signal handler. */ - struct x_error_message_stack { + /* Buffer containing the error message of any error that was + generated. */ char string[X_ERROR_MESSAGE_SIZE]; + + /* The display this error handler applies to. */ Display *dpy; + + /* A function to call upon an error if non-NULL. */ x_special_error_handler handler; + + /* Some data to pass to that handler function. */ void *handler_data; + + /* The previous handler in this stack. */ struct x_error_message_stack *prev; /* The first request that this error handler applies to. Keeping @@ -21803,6 +21807,14 @@ struct x_error_message_stack unsigned long first_request; }; +/* Stack of X error message handlers. Whenever an error is generated + on a display, look in this stack for an appropriate error handler, + set its `string' to the error message and call its `handler' with + `handler_data'. If no handler applies to the error, don't catch + it, and let it crash Emacs instead. + + This used to be a pointer to a string in which any error would be + placed before 2006. */ static struct x_error_message_stack *x_error_message; static struct x_error_message_stack * @@ -21825,9 +21837,10 @@ x_find_error_handler (Display *dpy, XErrorEvent *event) return NULL; } -/* An X error handler which stores the error message in - *x_error_message. This is called from x_error_handler if - x_catch_errors is in effect. */ +/* An X error handler which stores the error message in the first + applicable handler in the x_error_message stack. This is called + from *x_error_handler if an x_catch_errors for DISPLAY is in + effect. */ static void x_error_catcher (Display *display, XErrorEvent *event, @@ -21844,8 +21857,8 @@ x_error_catcher (Display *display, XErrorEvent *event, /* Begin trapping X errors for display DPY. After calling this function, X protocol errors generated on DPY no - longer cause Emacs to exit; instead, they are recorded in the - string stored in *x_error_message. + longer cause Emacs to exit; instead, they are recorded in an error + handler pushed onto the stack `x_error_message'. Calling x_check_errors signals an Emacs error if an X error has occurred since the last call to x_catch_errors or x_check_errors. @@ -21853,8 +21866,10 @@ x_error_catcher (Display *display, XErrorEvent *event, Calling x_uncatch_errors resumes the normal error handling, skipping an XSync if the last request made is known to have been processed. Calling x_uncatch_errors_after_check is similar, but - skips an XSync to the server, and should be used only immediately - after x_had_errors_p or x_check_errors. */ + always skips an XSync to the server, and should be used only + immediately after x_had_errors_p or x_check_errors, or when it is + known that no requests have been made since the last x_catch_errors + call for DPY. */ void x_catch_errors_with_handler (Display *dpy, x_special_error_handler handler, @@ -21962,8 +21977,8 @@ x_check_errors (Display *dpy, const char *format) } } -/* Nonzero if we had any X protocol errors - since we did x_catch_errors on DPY. */ +/* Nonzero if any X protocol errors were generated since the last call + to x_catch_errors on DPY. */ bool x_had_errors_p (Display *dpy) @@ -21983,7 +21998,8 @@ x_had_errors_p (Display *dpy) return x_error_message->string[0] != 0; } -/* Forget about any errors we have had, since we did x_catch_errors on DPY. */ +/* Forget about any errors we have had, since we did x_catch_errors on + DPY. */ void x_clear_errors (Display *dpy) commit 10641eaf5bad1fc77b99d6e611b3b0e0bfaa6110 Author: Po Lu Date: Mon Jun 6 19:51:47 2022 +0800 Add drag-and-drop API tests * test/lisp/dnd-tests.el: New file. (dnd-tests-begin-text-drag): (dnd-tests-begin-file-drag): (dnd-tests-begin-drag-files): New tests. diff --git a/test/lisp/dnd-tests.el b/test/lisp/dnd-tests.el new file mode 100644 index 0000000000..fbd6ce6a2c --- /dev/null +++ b/test/lisp/dnd-tests.el @@ -0,0 +1,198 @@ +;;; dnd-tests.el --- Tests for window system independent DND support -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;; Tests for stuff in dnd.el that doesn't require a window system. + +;; At present, these tests only checks the behavior of the simplified +;; drag APIs in dnd.el. Actual drags are not performed. + +;;; Code: + +(require 'dnd) +(require 'cl-lib) +(require 'tramp) + +;; This code was taken from tramp-tests.el: perhaps some of it isn't +;; strictly necessary. +(defconst dnd-tests-temporary-file-directory + (cond + ((getenv "REMOTE_TEMPORARY_FILE_DIRECTORY")) + ((eq system-type 'windows-nt) null-device) + (t (add-to-list + 'tramp-methods + '("mock" + (tramp-login-program "sh") + (tramp-login-args (("-i"))) + (tramp-remote-shell "/bin/sh") + (tramp-remote-shell-args ("-c")) + (tramp-connection-timeout 10))) + (add-to-list + 'tramp-default-host-alist + `("\\`mock\\'" nil ,(system-name))) + ;; Emacs's Makefile sets $HOME to a nonexistent value. Needed + ;; in batch mode only, therefore. + (unless (and (null noninteractive) (file-directory-p "~/")) + (setenv "HOME" temporary-file-directory)) + (format "/mock::%s" temporary-file-directory))) + "Temporary directory for drag-and-drop tests involving remote files.") + +;; Substitute for x-begin-drag, which isn't present on all systems. +(defalias 'x-begin-drag + (lambda (_targets &optional action frame &rest _) + ;; Verify that frame is either nil or a valid frame. + (when (and frame (not (frame-live-p frame))) + (signal 'wrong-type-argument frame)) + ;; Verify that the action is valid and pretend the drag succeeded + ;; (by returning the action). + (cl-ecase action + ('XdndActionCopy action) + ('XdndActionMove action) + ('XdndActionLink action) + ;; These two are not technically valid, but x-begin-drag accepts + ;; them anyway. + ('XdndActionPrivate action) + ('XdndActionAsk 'XdndActionPrivate)))) + +;; This doesn't work during tests. +(defalias 'gui-set-selection + (lambda (&rest _))) + +(defun dnd-tests-remote-accessible-p () + "Return if a test involving remote files can proceed." + (ignore-errors + (and + (file-remote-p dnd-tests-temporary-file-directory) + (file-directory-p dnd-tests-temporary-file-directory) + (file-writable-p dnd-tests-temporary-file-directory)))) + +(defun dnd-tests-make-temp-name () + "Return a temporary remote file name for test. +The temporary file is not created." + (expand-file-name (make-temp-name "dnd-test-remote") + dnd-tests-temporary-file-directory)) + +(ert-deftest dnd-tests-begin-text-drag () + (should (eq (dnd-begin-text-drag "some test text that will be dragged") + 'copy)) + (should (eq (dnd-begin-text-drag "some test text that will be dragged" + nil 'move) + 'move))) + +(ert-deftest dnd-tests-begin-file-drag () + ;; These tests also involve handling remote file names. + (skip-unless (dnd-tests-remote-accessible-p)) + (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test") + temporary-file-directory)) + (remote-temp-file (dnd-tests-make-temp-name))) + ;; Touch those files if they don't exist. + (unless (file-exists-p normal-temp-file) + (write-region "" 0 normal-temp-file)) + (unless (file-exists-p remote-temp-file) + (write-region "" 0 remote-temp-file)) + (unwind-protect + (progn + ;; Now test dragging a normal file. + (should (eq (dnd-begin-file-drag normal-temp-file) 'copy)) + ;; And the remote file. + (should (eq (dnd-begin-file-drag remote-temp-file) 'copy)) + ;; Test that the remote file was added to the list of files + ;; to remove later. + (should dnd-last-dragged-remote-file) + ;; Test that the remote file was removed. + (should (progn + (dnd-begin-file-drag normal-temp-file) + (not dnd-last-dragged-remote-file))) + ;; Test that links to remote files can't be created. + (should-error (dnd-begin-file-drag remote-temp-file nil 'link))) + (delete-file normal-temp-file) + (delete-file remote-temp-file)))) + +(ert-deftest dnd-tests-begin-drag-files () + (skip-unless (dnd-tests-remote-accessible-p)) + (let ((normal-temp-file (expand-file-name (make-temp-name "dnd-test") + temporary-file-directory)) + (normal-temp-file-1 (expand-file-name (make-temp-name "dnd-test") + temporary-file-directory)) + (remote-temp-file (dnd-tests-make-temp-name)) + (nonexistent-local-file + (expand-file-name (make-temp-name "dnd-test") + temporary-file-directory)) + (nonexistent-remote-file (dnd-tests-make-temp-name)) + (nonexistent-remote-file-1 (dnd-tests-make-temp-name))) + ;; Touch those files if they don't exist. + (unless (file-exists-p normal-temp-file) + (write-region "" 0 normal-temp-file)) + (unless (file-exists-p normal-temp-file-1) + (write-region "" 0 normal-temp-file)) + (unless (file-exists-p remote-temp-file) + (write-region "" 0 remote-temp-file)) + (ignore-errors + (delete-file nonexistent-local-file) + (delete-file nonexistent-remote-file) + (delete-file nonexistent-remote-file-1)) + (unwind-protect + (progn + ;; Now test dragging a normal file and a remote file. + (should (eq (dnd-begin-drag-files (list normal-temp-file + remote-temp-file)) + 'copy)) + ;; Test that the remote file produced was added to the list + ;; of files to remove upon the next call. + (should dnd-last-dragged-remote-file) + ;; Two remote files at the same time. + (should (eq (dnd-begin-drag-files (list normal-temp-file + normal-temp-file-1)) + 'copy)) + ;; Test that the remote files were removed. + (should-not dnd-last-dragged-remote-file) + ;; Multiple local files with some remote files that will + ;; fail, and some that won't. + (should (and (eq (dnd-begin-drag-files (list normal-temp-file + remote-temp-file + remote-temp-file + nonexistent-remote-file + normal-temp-file-1 + nonexistent-remote-file-1)) + 'copy) + ;; Make sure exactly two valid remote files + ;; were downloaded. + (eq (length dnd-last-dragged-remote-file) 2))) + ;; Make sure links can't be created to remote files. + (should-error (dnd-begin-drag-files (list normal-temp-file + remote-temp-file + normal-temp-file-1) + nil 'link)) + ;; And that they can to normal files. + (should (eq (dnd-begin-drag-files (list normal-temp-file + normal-temp-file-1) + nil 'link) + 'link)) + ;; Make sure you can't drag an empty list of files. + (should-error (dnd-begin-drag-files nil)) + ;; And when all remote files are inaccessible. + (should-error (dnd-begin-drag-files (list nonexistent-remote-file + nonexistent-remote-file-1)))) + (delete-file normal-temp-file) + (delete-file normal-temp-file-1) + (delete-file remote-temp-file)))) + +(provide 'dnd-tests) +;;; dnd-tests.el ends here commit c3127f56387441fce09a1103324b923f55695109 Author: Po Lu Date: Mon Jun 6 19:05:36 2022 +0800 Improve handling of remote files during drag-and-drop * lisp/dnd.el (dnd-begin-drag-files): Don't fail if one remote file couldn't be downloaded. diff --git a/lisp/dnd.el b/lisp/dnd.el index 14d80ac6c5..0f65b5228d 100644 --- a/lisp/dnd.el +++ b/lisp/dnd.el @@ -469,9 +469,16 @@ FILES will be dragged." (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)) + (condition-case error + (progn (setcar tem (file-local-copy (car tem))) + (push (car tem) dnd-last-dragged-remote-file)) + (error (message "Failed to download file: %s" error) + (setcar tem nil)))) (setq tem (cdr tem))) + ;; Remove any files that failed to download from a remote host. + (setq new-files (delq nil new-files)) + (unless new-files + (error "No files were specified or no remote file could be downloaded")) (unless action (setq action 'copy)) (gui-set-selection 'XdndSelection commit 138d2f22f731bc3faf6de26b67e2b50ce9131541 Author: Mattias Engdegård Date: Mon Jun 6 10:47:42 2022 +0200 Test warning suppressions with lexical binding * test/lisp/emacs-lisp/bytecomp-tests.el (test-byte-comp-compile-and-load): Add lexical cookie to file being compiled as part of the test. (bytecomp-test--with-suppressed-warnings): Comment out the test for suppressing warnings when attempting to let-bind `nil`, as that (1) doesn't work and (2) is a silly thing to do anyway. diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 049eed10f9..39f053136a 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -747,6 +747,7 @@ byte-compiled. Run with dynamic binding." (ert-with-temp-file elcfile :suffix ".elc" (with-temp-buffer + (insert ";;; -*- lexical-binding: t -*-\n") (dolist (form forms) (print form (current-buffer))) (write-region (point-min) (point-max) elfile nil 'silent)) @@ -1227,12 +1228,19 @@ literals (Bug#20852)." '((lexical prefixless)) "global/dynamic var .prefixless. lacks") - (test-suppression - '(defun foo() - (let ((nil t)) - (message-mail))) - '((constants nil)) - "Warning: attempt to let-bind constant .nil.") + ;; FIXME: These messages cannot be suppressed reliably right now, + ;; but attempting mutate `nil' or `5' is a rather daft thing to do + ;; in the first place. Preventing mutation of constants such as + ;; `most-positive-fixnum' makes more sense but the compiler doesn't + ;; warn about that at all right now (it's caught at runtime, and we + ;; allow writing the same value). + ;; + ;; (test-suppression + ;; '(defun foo() + ;; (let ((nil t)) + ;; (message-mail))) + ;; '((constants nil)) + ;; "Warning: attempt to let-bind constant .nil.") (test-suppression '(progn commit 3cbdd5914658f39f53baaeaf6a0aadfa534c02e8 Author: Po Lu Date: Mon Jun 6 16:01:41 2022 +0800 Fix several more issues with running Lisp during drag-and-drop * src/xterm.c (handle_one_xevent): Fix _NET_WM_PING cycle again and set mouse_moved flags during drag-and-drop so reading mouse events from Lisp continues to work. diff --git a/src/xterm.c b/src/xterm.c index 450340c31e..27ee01dbce 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15676,8 +15676,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, mask specified by the EWMH. To avoid an infinite loop, make sure the client message's window is not the root window if DND is in progress. */ - && (!x_dnd_in_progress - || !x_dnd_waiting_for_finish + && (!(x_dnd_in_progress + || x_dnd_waiting_for_finish) || event->xclient.window != dpyinfo->root_window) && event->xclient.format == 32) { @@ -17160,6 +17160,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, xm_top_level_leave_message lmsg; xm_top_level_enter_message emsg; xm_drag_motion_message dmsg; + XRectangle *r; /* Always clear mouse face. */ clear_mouse_face (hlinfo); @@ -17171,7 +17172,28 @@ handle_one_xevent (struct x_display_info *dpyinfo, visible manually. */ if (f) - XTtoggle_invisible_pointer (f, false); + { + XTtoggle_invisible_pointer (f, false); + + r = &dpyinfo->last_mouse_glyph; + + /* Also remember the mouse glyph and set + mouse_moved. */ + if (f != dpyinfo->last_mouse_glyph_frame + || event->xmotion.x < r->x + || event->xmotion.x >= r->x + r->width + || event->xmotion.y < r->y + || event->xmotion.y >= r->y + r->height) + { + f->mouse_moved = true; + f->last_mouse_device = Qnil; + dpyinfo->last_mouse_scroll_bar = NULL; + + remember_mouse_glyph (f, event->xmotion.x, + event->xmotion.y, r); + dpyinfo->last_mouse_glyph_frame = f; + } + } target = x_dnd_get_target_window (dpyinfo, event->xmotion.x_root, @@ -18814,6 +18836,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, { Window target, toplevel; int target_proto, motif_style; + XRectangle *r; /* Always clear mouse face. */ clear_mouse_face (hlinfo); @@ -18825,7 +18848,29 @@ handle_one_xevent (struct x_display_info *dpyinfo, visible manually. */ if (f) - XTtoggle_invisible_pointer (f, false); + { + XTtoggle_invisible_pointer (f, false); + + r = &dpyinfo->last_mouse_glyph; + + /* Also remember the mouse glyph and set + mouse_moved. */ + if (f != dpyinfo->last_mouse_glyph_frame + || xev->event_x < r->x + || xev->event_x >= r->x + r->width + || xev->event_y < r->y + || xev->event_y >= r->y + r->height) + { + f->mouse_moved = true; + f->last_mouse_device = (source ? source->name + : Qnil); + dpyinfo->last_mouse_scroll_bar = NULL; + + remember_mouse_glyph (f, xev->event_x, + xev->event_y, r); + dpyinfo->last_mouse_glyph_frame = f; + } + } target = x_dnd_get_target_window (dpyinfo, xev->root_x, commit 31bc62b6adeee5aa1539b1b527f52b85ea153d26 Author: Po Lu Date: Mon Jun 6 12:48:40 2022 +0800 Signal an error XdndSelection was lost during drag-and-drop * src/xselect.c (x_handle_selection_clear): Signal an error if ownership of XdndSelection was lost during drag-and-drop. diff --git a/src/xselect.c b/src/xselect.c index 6e693c2588..b920540620 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -928,6 +928,12 @@ x_handle_selection_clear (struct selection_input_event *event) /* Run the `x-lost-selection-functions' abnormal hook. */ CALLN (Frun_hook_with_args, Qx_lost_selection_functions, selection_symbol); + /* If Emacs lost ownership of XdndSelection during drag-and-drop, + there is no point in continuing the drag-and-drop session. */ + if (x_dnd_in_progress + && EQ (selection_symbol, QXdndSelection)) + error ("Lost ownership of XdndSelection"); + redisplay_preserve_echo_area (20); } commit 9062856ed0be4a7966e82a8c44cc890b62cfc418 Author: Po Lu Date: Mon Jun 6 12:33:41 2022 +0800 Make mouse input work properly inside the debugger during DND * src/xterm.c (x_dnd_begin_drag_and_drop): Set `x_dnd_recursion_depth'. (handle_one_xevent): If the recursive edit level is higher than when DND started, handle mouse events normally. diff --git a/src/xterm.c b/src/xterm.c index ffbd09d27f..450340c31e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1188,6 +1188,10 @@ static sigjmp_buf x_dnd_disconnect_handler; happened inside the drag_and_drop event loop. */ static bool x_dnd_inside_handle_one_xevent; +/* The recursive edit depth when the drag-and-drop operation was + started. */ +static int x_dnd_recursion_depth; + /* Structure describing a single window that can be the target of drag-and-drop operations. */ struct x_client_list_window @@ -10838,6 +10842,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #endif x_dnd_in_progress = true; + x_dnd_recursion_depth = command_loop_level + minibuf_level; x_dnd_frame = f; x_dnd_last_seen_window = None; x_dnd_last_seen_toplevel = None; @@ -17141,6 +17146,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, f = mouse_or_wdesc_frame (dpyinfo, event->xmotion.window); if (x_dnd_in_progress + /* Handle these events normally if the recursion + level is higher than when the drag-and-drop + operation was initiated. This is so that mouse + input works while we're in the debugger for, say, + `x-dnd-movement-function`. */ + && (command_loop_level + minibuf_level + <= x_dnd_recursion_depth) && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { Window target, toplevel; @@ -17770,6 +17782,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, bool dnd_grab = false; if (x_dnd_in_progress + /* Handle these events normally if the recursion + level is higher than when the drag-and-drop + operation was initiated. This is so that mouse + input works while we're in the debugger for, say, + `x-dnd-movement-function`. */ + && (command_loop_level + minibuf_level + <= x_dnd_recursion_depth) && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { if (event->xbutton.type == ButtonPress @@ -17895,7 +17914,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto OTHER; } - if (x_dnd_in_progress) + if (x_dnd_in_progress + && (command_loop_level + minibuf_level + <= x_dnd_recursion_depth)) goto OTHER; memset (&compose_status, 0, sizeof (compose_status)); @@ -18782,6 +18803,13 @@ handle_one_xevent (struct x_display_info *dpyinfo, f = mouse_or_wdesc_frame (dpyinfo, xev->event); if (x_dnd_in_progress + /* Handle these events normally if the recursion + level is higher than when the drag-and-drop + operation was initiated. This is so that mouse + input works while we're in the debugger for, say, + `x-dnd-movement-function`. */ + && (command_loop_level + minibuf_level + <= x_dnd_recursion_depth) && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { Window target, toplevel; @@ -19079,6 +19107,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, int dnd_state; if (x_dnd_in_progress + && (command_loop_level + minibuf_level + <= x_dnd_recursion_depth) && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { if (xev->evtype == XI_ButtonPress @@ -19224,7 +19254,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, } } - if (x_dnd_in_progress) + if (x_dnd_in_progress + && (command_loop_level + minibuf_level + <= x_dnd_recursion_depth)) goto XI_OTHER; #ifdef USE_MOTIF commit 5ee4209f307fdf8cde9775539c9596d29edccd6d Author: Stefan Monnier Date: Mon Jun 6 00:04:00 2022 -0400 cl-typep: Emit warning when using a type not known to be a type `cl-typep` has used a heuristic that if there's a `-p` function, then can be used as a type. This made sense in the past where most types were not officially declared to be (cl-)types, but nowadays this just encourages abuses such as using `cl-typecase` with "types" like `fbound`. It's also a problem for EIEIO objects, where for historical reasons `-p` tests if the object is of type exactly `` whereas (cl-typep OBJ ) should instead test if OBJ is a *subtype* of ``. So we change `cl-typep` to emit a warning whenever this "-p" heuristic is used, to discourage abuses, encourage the use of explicit `cl-deftype` declarations, and try and detect some misuses of `-p` for EIEIO objects. * lisp/emacs-lisp/eieio.el (defclass): Define as type not only at run-time but also for the current compilation unit. * lisp/emacs-lisp/eieio-core.el (class, eieio-object): Define as types. * lisp/emacs-lisp/cl-preloaded.el (cl-struct-define): Don't abuse the "-p" heuristic. * lisp/emacs-lisp/cl-macs.el (cl-deftype-satisfies): Add entries for frames, windows, markers, and overlays. (cl-typep): Emit a warning when using a predicate that is not known to correspond to a type. * lisp/files.el (file-relative-name): Fix error that can trigger if there's an(other) error between loading `files.el` and loading `minibuffer.el`. diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index a9d422929f..ada4f0344d 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -3412,19 +3412,23 @@ Of course, we really can't know that for sure, so it's just a heuristic." (cons . consp) (fixnum . fixnump) (float . floatp) + (frame . framep) (function . functionp) (integer . integerp) (keyword . keywordp) (list . listp) + (marker . markerp) (natnum . natnump) (number . numberp) (null . null) + (overlay . overlayp) (real . numberp) (sequence . sequencep) (subr . subrp) (string . stringp) (symbol . symbolp) (vector . vectorp) + (window . windowp) ;; FIXME: Do we really want to consider this a type? (integer-or-marker . integer-or-marker-p) )) @@ -3475,16 +3479,19 @@ Of course, we really can't know that for sure, so it's just a heuristic." (inline-quote (funcall #',(get type 'cl-deftype-satisfies) ,val))) ((and (or 'nil 't) type) (inline-quote ',type)) ((and (pred symbolp) type) - (let* ((name (symbol-name type)) - (namep (intern (concat name "p")))) - (cond - ((cl--macroexp-fboundp namep) (inline-quote (funcall #',namep ,val))) - ((cl--macroexp-fboundp - (setq namep (intern (concat name "-p")))) - (inline-quote (funcall #',namep ,val))) - ((cl--macroexp-fboundp type) (inline-quote (funcall #',type ,val))) - (t (error "Unknown type %S" type))))) - (type (error "Bad type spec: %s" type))))) + (macroexp-warn-and-return + (format-message "Unknown type: %S" type) + (let* ((name (symbol-name type)) + (namep (intern (concat name "p")))) + (cond + ((cl--macroexp-fboundp namep) (inline-quote (funcall #',namep ,val))) + ((cl--macroexp-fboundp + (setq namep (intern (concat name "-p")))) + (inline-quote (funcall #',namep ,val))) + ((cl--macroexp-fboundp type) (inline-quote (funcall #',type ,val))) + (t (error "Unknown type %S" type)))) + nil nil type)) + (type (error "Bad type spec: %S" type))))) ;;;###autoload diff --git a/lisp/emacs-lisp/cl-preloaded.el b/lisp/emacs-lisp/cl-preloaded.el index 2b32bc4844..ec9fd86a55 100644 --- a/lisp/emacs-lisp/cl-preloaded.el +++ b/lisp/emacs-lisp/cl-preloaded.el @@ -152,7 +152,7 @@ supertypes from the most specific to least specific.") ;;;###autoload (defun cl-struct-define (name docstring parent type named slots children-sym tag print) - (cl-check-type name cl--struct-name) + (cl-check-type name (satisfies cl--struct-name-p)) (unless type ;; Legacy defstruct, using tagged vectors. Enable backward compatibility. (cl-old-struct-compat-mode 1)) diff --git a/lisp/emacs-lisp/eieio-core.el b/lisp/emacs-lisp/eieio-core.el index d687289b22..d9864e6965 100644 --- a/lisp/emacs-lisp/eieio-core.el +++ b/lisp/emacs-lisp/eieio-core.el @@ -137,6 +137,8 @@ Currently under control of this var: X can also be is a symbol." (eieio--class-p (if (symbolp x) (cl--find-class x) x))) +(cl-deftype class () `(satisfies class-p)) + (defun eieio--class-print-name (class) "Return a printed representation of CLASS." (format "#" (eieio-class-name class))) @@ -165,6 +167,8 @@ Return nil if that option doesn't exist." (and (recordp obj) (eieio--class-p (eieio--object-class obj)))) +(cl-deftype eieio-object () `(satisfies eieio-object-p)) + (define-obsolete-function-alias 'object-p #'eieio-object-p "25.1") (defun class-abstract-p (class) diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index 1315ca0c62..565eaf2d73 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el @@ -271,7 +271,8 @@ This method is obsolete." ;; test, so we can let typep have the CLOS documented behavior ;; while keeping our above predicate clean. - (define-symbol-prop ',name 'cl-deftype-satisfies #',testsym2) + (eval-and-compile + (define-symbol-prop ',name 'cl-deftype-satisfies #',testsym2)) (eieio-defclass-internal ',name ',superclasses ',slots ',options-and-doc) diff --git a/lisp/files.el b/lisp/files.el index 6c6fcbc55d..97e58946bd 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -5354,7 +5354,14 @@ on a DOS/Windows machine, it returns FILENAME in expanded form." (let ((fremote (file-remote-p filename)) (dremote (file-remote-p directory)) (fold-case (or (file-name-case-insensitive-p filename) - read-file-name-completion-ignore-case))) + ;; During bootstrap, it can happen that + ;; `read-file-name-completion-ignore-case' is + ;; not defined yet. + ;; FIXME: `read-file-name-completion-ignore-case' is + ;; a user-config which we shouldn't trust to reflect + ;; the actual file system's semantics. + (and (boundp 'read-file-name-completion-ignore-case) + read-file-name-completion-ignore-case)))) (if ;; Conditions for separate trees (or ;; Test for different filesystems on DOS/Windows commit b90d2a6a63f1b7f73d2cb7e976148e8195fc5502 Author: Po Lu Date: Mon Jun 6 11:08:19 2022 +0800 Rework X selections to make it safe to run the debugger inside converters * src/keyboard.c (prev_kbd_event): Delete function. (readable_events): Return 1 if x_detect_pending_selection_requests returns true. (kbd_buffer_unget_event): Also delete function, since nested selection requests are really handled correctly. (kbd_buffer_get_event): Handle events from the special X deferred selection queue as well. * src/keyboard.h: Update prototypes. * src/xselect.c (struct selection_event_queue) (selection_input_event_equal, x_queue_event) (x_start_queuing_selection_requests) (x_stop_queuing_selection_requests): Delete structs, since they are no longer required. (x_handle_selection_request, x_handle_selection_event): Allow nested selection events. * src/xterm.c (struct x_selection_request_event): New struct. (x_handle_pending_selection_requests_1) (x_handle_pending_selection_requests): Handle all events in the new selection event queue. (x_push_selection_request, x_detect_pending_selection_requests): New functions. (x_dnd_begin_drag_and_drop): Drain the selection queue here as well. (handle_one_xevent): When inside a nested event loop, just push selections to that queue. (XTread_socket): Allow reading X events if x_dnd_unwind_flag is true, even though DND is in progress. (x_delete_display): Delete pending selection events for the display that is going away. * src/xterm.h: Update prototypes. diff --git a/src/keyboard.c b/src/keyboard.c index 274c7b3fa8..55d710ed62 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -389,14 +389,6 @@ next_kbd_event (union buffered_input_event *ptr) return ptr == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : ptr + 1; } -#ifdef HAVE_X11 -static union buffered_input_event * -prev_kbd_event (union buffered_input_event *ptr) -{ - return ptr == kbd_buffer ? kbd_buffer + KBD_BUFFER_SIZE - 1 : ptr - 1; -} -#endif - /* Like EVENT_START, but assume EVENT is an event. This pacifies gcc -Wnull-dereference, which might otherwise complain about earlier checks that EVENT is indeed an event. */ @@ -3528,6 +3520,11 @@ readable_events (int flags) return 1; } +#ifdef HAVE_X_WINDOWS + if (x_detect_pending_selection_requests ()) + return 1; +#endif + if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && some_mouse_moved ()) return 1; if (single_kboard) @@ -3699,25 +3696,6 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event, Vquit_flag = Vthrow_on_input; } - -#ifdef HAVE_X11 - -/* Put a selection input event back in the head of the event queue. */ - -void -kbd_buffer_unget_event (struct selection_input_event *event) -{ - /* Don't let the very last slot in the buffer become full, */ - union buffered_input_event *kp = prev_kbd_event (kbd_fetch_ptr); - if (kp != kbd_store_ptr) - { - kp->sie = *event; - kbd_fetch_ptr = kp; - } -} - -#endif - /* Limit help event positions to this range, to avoid overflow problems. */ #define INPUT_EVENT_POS_MAX \ ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \ @@ -3874,6 +3852,11 @@ kbd_buffer_get_event (KBOARD **kbp, struct timespec *end_time) { Lisp_Object obj, str; +#ifdef HAVE_X_WINDOWS + bool had_pending_selection_requests; + + had_pending_selection_requests = false; +#endif #ifdef subprocesses if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4) @@ -3926,10 +3909,18 @@ kbd_buffer_get_event (KBOARD **kbp, #if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL) gobble_input (); #endif + if (kbd_fetch_ptr != kbd_store_ptr) break; if (some_mouse_moved ()) break; +#ifdef HAVE_X_WINDOWS + if (x_detect_pending_selection_requests ()) + { + had_pending_selection_requests = true; + break; + } +#endif if (end_time) { struct timespec now = current_timespec (); @@ -3966,6 +3957,16 @@ kbd_buffer_get_event (KBOARD **kbp, gobble_input (); } +#ifdef HAVE_X_WINDOWS + /* Handle pending selection requests. This can happen if Emacs + enters a recursive edit inside a nested event loop (probably + because the debugger opened) or someone called + `read-char'. */ + + if (had_pending_selection_requests) + x_handle_pending_selection_requests (); +#endif + if (CONSP (Vunread_command_events)) { Lisp_Object first; @@ -4345,6 +4346,10 @@ kbd_buffer_get_event (KBOARD **kbp, ? movement_frame->last_mouse_device : virtual_core_pointer_name); } +#ifdef HAVE_X_WINDOWS + else if (had_pending_selection_requests) + obj = Qnil; +#endif else /* We were promised by the above while loop that there was something for us to read! */ @@ -7241,7 +7246,10 @@ lucid_event_type_list_p (Lisp_Object object) If READABLE_EVENTS_FILTER_EVENTS is set in FLAGS, ignore internal events (FOCUS_IN_EVENT). If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse - movements and toolkit scroll bar thumb drags. */ + movements and toolkit scroll bar thumb drags. + + On X, this also returns if the selection event chain is full, since + that's also "keyboard input". */ static bool get_input_pending (int flags) diff --git a/src/keyboard.h b/src/keyboard.h index a0b7204fa2..6ae2dc9c4c 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -481,9 +481,6 @@ kbd_buffer_store_event_hold (struct input_event *event, kbd_buffer_store_buffered_event ((union buffered_input_event *) event, hold_quit); } -#ifdef HAVE_X11 -extern void kbd_buffer_unget_event (struct selection_input_event *); -#endif extern void poll_for_input_1 (void); extern void show_help_echo (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object); diff --git a/src/xselect.c b/src/xselect.c index 5f2a0cf56d..6e693c2588 100644 --- a/src/xselect.c +++ b/src/xselect.c @@ -116,92 +116,6 @@ selection_quantum (Display *display) assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) -/* Define a queue to save up SELECTION_REQUEST_EVENT events for later - handling. */ - -struct selection_event_queue - { - struct selection_input_event event; - struct selection_event_queue *next; - }; - -static struct selection_event_queue *selection_queue; - -/* Nonzero means queue up SELECTION_REQUEST_EVENT events. */ - -static int x_queue_selection_requests; - -/* True if the input events are duplicates. */ - -static bool -selection_input_event_equal (struct selection_input_event *a, - struct selection_input_event *b) -{ - return (a->kind == b->kind && a->dpyinfo == b->dpyinfo - && a->requestor == b->requestor && a->selection == b->selection - && a->target == b->target && a->property == b->property - && a->time == b->time); -} - -/* Queue up an SELECTION_REQUEST_EVENT *EVENT, to be processed later. */ - -static void -x_queue_event (struct selection_input_event *event) -{ - struct selection_event_queue *queue_tmp; - - /* Don't queue repeated requests. - This only happens for large requests which uses the incremental protocol. */ - for (queue_tmp = selection_queue; queue_tmp; queue_tmp = queue_tmp->next) - { - if (selection_input_event_equal (event, &queue_tmp->event)) - { - TRACE1 ("DECLINE DUP SELECTION EVENT %p", queue_tmp); - x_decline_selection_request (event); - return; - } - } - - queue_tmp = xmalloc (sizeof *queue_tmp); - TRACE1 ("QUEUE SELECTION EVENT %p", queue_tmp); - queue_tmp->event = *event; - queue_tmp->next = selection_queue; - selection_queue = queue_tmp; -} - -/* Start queuing SELECTION_REQUEST_EVENT events. */ - -static void -x_start_queuing_selection_requests (void) -{ - if (x_queue_selection_requests) - emacs_abort (); - - x_queue_selection_requests++; - TRACE1 ("x_start_queuing_selection_requests %d", x_queue_selection_requests); -} - -/* Stop queuing SELECTION_REQUEST_EVENT events. */ - -static void -x_stop_queuing_selection_requests (void) -{ - TRACE1 ("x_stop_queuing_selection_requests %d", x_queue_selection_requests); - --x_queue_selection_requests; - - /* Take all the queued events and put them back - so that they get processed afresh. */ - - while (selection_queue != NULL) - { - struct selection_event_queue *queue_tmp = selection_queue; - TRACE1 ("RESTORE SELECTION EVENT %p", queue_tmp); - kbd_buffer_unget_event (&queue_tmp->event); - selection_queue = queue_tmp->next; - xfree (queue_tmp); - } -} - /* This converts a Lisp symbol to a server Atom, avoiding a server roundtrip whenever possible. */ @@ -839,11 +753,6 @@ x_handle_selection_request (struct selection_input_event *event) selection_request_dpyinfo = dpyinfo; record_unwind_protect_void (x_selection_request_lisp_error); - /* We might be able to handle nested x_handle_selection_requests, - but this is difficult to test, and seems unimportant. */ - x_start_queuing_selection_requests (); - record_unwind_protect_void (x_stop_queuing_selection_requests); - TRACE2 ("x_handle_selection_request: selection=%s, target=%s", SDATA (SYMBOL_NAME (selection_symbol)), SDATA (SYMBOL_NAME (target_symbol))); @@ -1028,8 +937,6 @@ x_handle_selection_event (struct selection_input_event *event) TRACE0 ("x_handle_selection_event"); if (event->kind != SELECTION_REQUEST_EVENT) x_handle_selection_clear (event); - else if (x_queue_selection_requests) - x_queue_event (event); else x_handle_selection_request (event); } diff --git a/src/xterm.c b/src/xterm.c index 4d8d7e80eb..ffbd09d27f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -789,6 +789,21 @@ static int current_finish; static struct input_event *current_hold_quit; #endif +struct x_selection_request_event +{ + /* The selection request event. */ + struct selection_input_event se; + + /* The next unprocessed selection request event. */ + struct x_selection_request_event *next; +}; + +/* Chain of unprocessed selection request events. Used to handle + selection requests inside long-lasting modal event loops, such as + the drag-and-drop loop. */ + +struct x_selection_request_event *pending_selection_requests; + /* Compare two request serials A and B with OP, handling wraparound. */ #define X_COMPARE_SERIALS(a, op ,b) \ @@ -1169,6 +1184,10 @@ static unsigned int x_dnd_keyboard_state; terminating DND as part of the display disconnect handler. */ static sigjmp_buf x_dnd_disconnect_handler; +/* Whether or not the current invocation of handle_one_xevent + happened inside the drag_and_drop event loop. */ +static bool x_dnd_inside_handle_one_xevent; + /* Structure describing a single window that can be the target of drag-and-drop operations. */ struct x_client_list_window @@ -10546,6 +10565,53 @@ x_next_event_from_any_display (XEvent *event) #endif /* USE_X_TOOLKIT || USE_GTK */ +static void +x_handle_pending_selection_requests_1 (struct x_selection_request_event *tem) +{ + specpdl_ref count; + struct selection_input_event se; + + count = SPECPDL_INDEX (); + se = tem->se; + + record_unwind_protect_ptr (xfree, tem); + x_handle_selection_event (&se); + unbind_to (count, Qnil); +} + +/* Handle all pending selection request events from modal event + loops. */ +void +x_handle_pending_selection_requests (void) +{ + struct x_selection_request_event *tem; + + while (pending_selection_requests) + { + tem = pending_selection_requests; + pending_selection_requests = tem->next; + + x_handle_pending_selection_requests_1 (tem); + } +} + +static void +x_push_selection_request (struct selection_input_event *se) +{ + struct x_selection_request_event *tem; + + tem = xmalloc (sizeof *tem); + tem->next = pending_selection_requests; + tem->se = *se; + pending_selection_requests = tem; +} + +bool +x_detect_pending_selection_requests (void) +{ + return pending_selection_requests; +} + /* This function is defined far away from the rest of the XDND code so it can utilize `x_any_window_to_frame'. */ @@ -10841,6 +10907,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, while (x_dnd_in_progress || x_dnd_waiting_for_finish) { EVENT_INIT (hold_quit); + #ifdef USE_GTK current_finish = X_EVENT_NORMAL; current_hold_quit = &hold_quit; @@ -10849,6 +10916,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #endif block_input (); + x_dnd_inside_handle_one_xevent = true; #ifdef USE_GTK gtk_main_iteration (); #elif defined USE_X_TOOLKIT @@ -10890,6 +10958,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, current_count = -1; current_hold_quit = NULL; #endif + x_dnd_inside_handle_one_xevent = false; /* The unblock_input below might try to read input, but XTread_socket does nothing inside a drag-and-drop event @@ -10942,29 +11011,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (hold_quit.kind != NO_EVENT) { - if (hold_quit.kind == SELECTION_REQUEST_EVENT) - { - /* It's not safe to run Lisp inside this function if - x_dnd_in_progress and x_dnd_waiting_for_finish - are unset, so push it back into the event queue. */ - - if (!x_dnd_in_progress && !x_dnd_waiting_for_finish) - kbd_buffer_store_event (&hold_quit); - else - { - x_dnd_old_window_attrs = root_window_attrs; - x_dnd_unwind_flag = true; - - ref = SPECPDL_INDEX (); - record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f); - x_handle_selection_event ((struct selection_input_event *) &hold_quit); - x_dnd_unwind_flag = false; - unbind_to (ref, Qnil); - } - - continue; - } - if (x_dnd_in_progress) { if (x_dnd_last_seen_window != None @@ -11031,6 +11077,19 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, quit (); } + if (pending_selection_requests + && (x_dnd_in_progress || x_dnd_waiting_for_finish)) + { + x_dnd_old_window_attrs = root_window_attrs; + x_dnd_unwind_flag = true; + + ref = SPECPDL_INDEX (); + record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f); + x_handle_pending_selection_requests (); + x_dnd_unwind_flag = false; + unbind_to (ref, Qnil); + } + #ifdef USE_GTK if (xg_pending_quit_event.kind != NO_EVENT) { @@ -15801,6 +15860,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo; SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; SELECTION_EVENT_TIME (&inev.sie) = eventp->time; + + if ((x_dnd_in_progress + && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) + || (x_dnd_waiting_for_finish + && dpyinfo->display == x_dnd_finish_display)) + { + x_push_selection_request (&inev.sie); + EVENT_INIT (inev.ie); + } } break; @@ -15829,17 +15897,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, || (x_dnd_waiting_for_finish && dpyinfo->display == x_dnd_finish_display)) { -#ifndef USE_GTK - eassume (hold_quit); -#else - /* If the debugger runs inside a selection converter, then - xg_select can call handle_one_xevent with no - hold_quit. */ - if (!hold_quit) - goto done; -#endif - - *hold_quit = inev.ie; + x_push_selection_request (&inev.sie); EVENT_INIT (inev.ie); } @@ -21120,12 +21178,16 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit) read X events while the drag-and-drop event loop is in progress, things can go wrong very quick. + When x_dnd_unwind_flag is true, the above doesn't apply, since + the surrounding code takes special precautions to keep it safe. + That doesn't matter for events from displays other than the display of the drag-and-drop operation, though. */ - if ((x_dnd_in_progress - && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame)) - || (x_dnd_waiting_for_finish - && dpyinfo->display == x_dnd_finish_display)) + if (!x_dnd_unwind_flag + && ((x_dnd_in_progress + && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame)) + || (x_dnd_waiting_for_finish + && dpyinfo->display == x_dnd_finish_display))) return 0; block_input (); @@ -25840,6 +25902,7 @@ x_delete_display (struct x_display_info *dpyinfo) struct terminal *t; struct color_name_cache_entry *color_entry, *next_color_entry; int i; + struct x_selection_request_event *ie, *last, *temp; /* Close all frames and delete the generic struct terminal for this X display. */ @@ -25855,6 +25918,30 @@ x_delete_display (struct x_display_info *dpyinfo) break; } + /* Find any pending selection requests for this display and unchain + them. */ + + last = NULL; + + for (ie = pending_selection_requests; ie; ie = ie->next) + { + again: + + if (SELECTION_EVENT_DPYINFO (&ie->se) == dpyinfo) + { + if (last) + last->next = ie->next; + + temp = ie; + ie = ie->next; + xfree (temp); + + goto again; + } + + last = ie; + } + if (next_noop_dpyinfo == dpyinfo) next_noop_dpyinfo = dpyinfo->next; diff --git a/src/xterm.h b/src/xterm.h index 878cb5fd87..22c6b55176 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1455,6 +1455,8 @@ extern void x_xr_reset_ext_clip (struct frame *f); extern void x_scroll_bar_configure (GdkEvent *); #endif +extern void x_handle_pending_selection_requests (void); +extern bool x_detect_pending_selection_requests (void); extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, Lisp_Object, Atom *, const char **, size_t, bool, Atom *, int); commit 0a36671f415bd681ddca0bad8612aca031fd407d Author: Stefan Monnier Date: Sun Jun 5 19:51:29 2022 -0400 pcomplete.el: Fix part of bug#50470 Try and handle the case where `pcomplete-parse-arguments-function` directly returns a list of completions. * lisp/pcomplete.el (pcomplete-parse-arguments): Don't modify the buffer if we're not allowed to. Instead use the buffer's current content as the "pattern to be completed" and return the list of completions as is. Also, use `try-completions` to simplify the previous code. diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el index a1492af89d..3393c322e3 100644 --- a/lisp/pcomplete.el +++ b/lisp/pcomplete.el @@ -802,25 +802,30 @@ this is `comint-dynamic-complete-functions'." (let ((begin (pcomplete-begin 'last))) (if (and (listp pcomplete-stub) ;?? (not pcomplete-expand-only-p)) - (let* ((completions pcomplete-stub) ;?? - (common-stub (car completions)) - (c completions) - (len (length common-stub))) - (while (and c (> len 0)) - (while (and (> len 0) - (not (string= - (substring common-stub 0 len) - (substring (car c) 0 - (min (length (car c)) - len))))) - (setq len (1- len))) - (setq c (cdr c))) - (setq pcomplete-stub (substring common-stub 0 len) - pcomplete-autolist t) - (when (and begin (> len 0) (not pcomplete-show-list)) - (delete-region begin (point)) - (pcomplete-insert-entry "" pcomplete-stub)) - (throw 'pcomplete-completions completions)) + ;; If `pcomplete-stub' is a list, it means it's a list of + ;; completions computed during parsing, e.g. Eshell uses + ;; that to turn globs into lists of completions. + (if (not pcomplete-allow-modifications) + (progn + ;; FIXME: The mapping from what's in the buffer to the list + ;; of completions can be arbitrary and will often fail to be + ;; understood by the completion style. See bug#50470. + ;; E.g. `pcomplete-stub' may end up being "~/Down*" + ;; while the completions contain entries like + ;; "/home//Downloads" which will fail to match the + ;; "~/Down*" completion pattern since the completion + ;; is neither told that it's a file nor a global pattern. + (setq pcomplete-stub (buffer-substring begin (point))) + (throw 'pcomplete-completions pcomplete-stub)) + (let* ((completions pcomplete-stub) + (common-prefix (try-completion "" completions)) + (len (length common-prefix))) + (setq pcomplete-stub common-prefix + pcomplete-autolist t) + (when (and begin (> len 0) (not pcomplete-show-list)) + (delete-region begin (point)) + (pcomplete-insert-entry "" pcomplete-stub)) + (throw 'pcomplete-completions completions))) (when expand-p (if (stringp pcomplete-stub) (when begin commit f5e8e7a7b9db94092503e35be3a3501905798ed5 Author: Lars Ingebrigtsen Date: Mon Jun 6 00:42:56 2022 +0200 Add nohandle-guide images for tree-widget These are copies of the guide.* files diff --git a/etc/images/tree-widget/default/nohandle-guide.png b/etc/images/tree-widget/default/nohandle-guide.png new file mode 100644 index 0000000000..85fa0c87b7 Binary files /dev/null and b/etc/images/tree-widget/default/nohandle-guide.png differ diff --git a/etc/images/tree-widget/default/nohandle-guide.xpm b/etc/images/tree-widget/default/nohandle-guide.xpm new file mode 100644 index 0000000000..85b3cec00c --- /dev/null +++ b/etc/images/tree-widget/default/nohandle-guide.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char * guide_xpm[] = { +"6 21 2 1", +" c None", +". c #ADA5C6", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" .", +" ."}; diff --git a/etc/images/tree-widget/folder/nohandle-guide.png b/etc/images/tree-widget/folder/nohandle-guide.png new file mode 100644 index 0000000000..8535f86f3b Binary files /dev/null and b/etc/images/tree-widget/folder/nohandle-guide.png differ diff --git a/etc/images/tree-widget/folder/nohandle-guide.xpm b/etc/images/tree-widget/folder/nohandle-guide.xpm new file mode 100644 index 0000000000..647d059017 --- /dev/null +++ b/etc/images/tree-widget/folder/nohandle-guide.xpm @@ -0,0 +1,27 @@ +/* XPM */ +static char * guide_xpm[] = { +"6 22 2 1", +" c None", +". c #ADA5C6", +" ", +" .", +" ", +" .", +" ", +" .", +" ", +" .", +" ", +" .", +" ", +" .", +" ", +" .", +" ", +" .", +" ", +" .", +" ", +" .", +" ", +" ."}; commit fbc0cc0e9fdc0991b34468cec4ea7beed22b230d Author: Lars Ingebrigtsen Date: Sun Jun 5 22:52:59 2022 +0200 Re-re-fix previous describe-function change * lisp/help-fns.el (describe-function): Put back binding removed by mistake in previous change. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 0b496e635e..61fc8037df 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -258,7 +258,8 @@ handling of autoloaded functions." ;; calling that. (let ((describe-function-orig-buffer (or describe-function-orig-buffer - (current-buffer)))) + (current-buffer))) + (help-buffer-under-preparation t)) (help-setup-xref (list (lambda (function buffer) commit 46822e9c5e96147c068b324a545b530c4818097a Author: Lars Ingebrigtsen Date: Sun Jun 5 22:48:28 2022 +0200 Fix key binding buffer issue in describe-function better * lisp/help-fns.el (describe-function): Revert previous change here. (describe-function-1): Just use describe-function-orig-buffer instead of the key-buffer binding -- this will also make the rendering results correct when hitting `g' and `l'. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 8b4905aed1..0b496e635e 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -258,9 +258,7 @@ handling of autoloaded functions." ;; calling that. (let ((describe-function-orig-buffer (or describe-function-orig-buffer - (current-buffer))) - (key-buffer (current-buffer)) - (help-buffer-under-preparation t)) + (current-buffer)))) (help-setup-xref (list (lambda (function buffer) @@ -278,7 +276,7 @@ handling of autoloaded functions." ;; Use " is " instead of a colon so that ;; it is easier to get out the function name using forward-sexp. (princ " is ") - (describe-function-1 function key-buffer) + (describe-function-1 function) (with-current-buffer standard-output ;; Return the text we displayed. (buffer-string)))))) @@ -1026,7 +1024,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." (unless (eq ?\n (char-before (1- (point)))) (insert "\n"))) ;;;###autoload -(defun describe-function-1 (function &optional key-bindings-buffer) +(defun describe-function-1 (function) (let ((pt1 (with-current-buffer standard-output (point)))) (help-fns-function-description-header function) (with-current-buffer standard-output @@ -1047,8 +1045,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." ;; for invalid functions i.s.o. signaling an error. (documentation function t) ;; E.g. an alias for a not yet defined function. - ((invalid-function void-function) nil))) - (key-bindings-buffer (or key-bindings-buffer (current-buffer)))) + ((invalid-function void-function) nil)))) ;; If the function is autoloaded, and its docstring has ;; key substitution constructs, load the library. @@ -1065,7 +1062,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." (help-fns--signature function doc-raw (if (subrp def) (indirect-function real-def) real-def) - real-function key-bindings-buffer) + real-function describe-function-orig-buffer) ;; E.g. an alias for a not yet defined function. ((invalid-function void-function) doc-raw)))) (help-fns--ensure-empty-line) commit b1ed72fd707ddd81bf79b6937bf0a50ced4f025d Author: Lars Ingebrigtsen Date: Sun Jun 5 22:37:32 2022 +0200 Clarify syntax-ppss doc string * lisp/emacs-lisp/syntax.el (syntax-ppss): Clarify doc string. diff --git a/lisp/emacs-lisp/syntax.el b/lisp/emacs-lisp/syntax.el index 7cc076cd80..a4d7beade1 100644 --- a/lisp/emacs-lisp/syntax.el +++ b/lisp/emacs-lisp/syntax.el @@ -545,10 +545,11 @@ These are valid when the buffer has no restriction.") (defun syntax-ppss (&optional pos) "Parse-Partial-Sexp State at POS, defaulting to point. +If POS is given, this function moves point to POS. + The returned value is the same as that of `parse-partial-sexp' run from `point-min' to POS except that values at positions 2 and 6 in the returned list (counting from 0) cannot be relied upon. -Point is at POS when this function returns. It is necessary to call `syntax-ppss-flush-cache' explicitly if this function is called while `before-change-functions' is commit 50cbb727b53ca2e4025a6ac304423a94e26fe17f Author: Lars Ingebrigtsen Date: Sun Jun 5 22:29:08 2022 +0200 Simplify set-goal-column * lisp/simple.el (set-goal-column): Simplify the code. diff --git a/lisp/simple.el b/lisp/simple.el index c749e6e41d..ac41b394a7 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8096,18 +8096,10 @@ a buffer-local setting." (setq goal-column nil) (message "No goal column")) (setq goal-column (current-column)) - ;; The older method below can be erroneous if `set-goal-column' is bound - ;; to a sequence containing % - ;;(message (substitute-command-keys - ;;"Goal column %d (use \\[set-goal-column] with an arg to unset it)") - ;;goal-column) - (message "%s" - (concat - (format "Goal column %d " goal-column) - (substitute-command-keys - "(use \\[set-goal-column] with an arg to unset it)"))) - - ) + (message "Goal column %d %s" + goal-column + (substitute-command-keys + "(use \\[set-goal-column] with an arg to unset it)"))) nil) ;;; Editing based on visual lines, as opposed to logical lines. commit 3f388d7929346f39c99b7d801e8f62a9b71c4b73 Author: Lars Ingebrigtsen Date: Sun Jun 5 21:48:21 2022 +0200 Make `C-h f' look up key bindings in the current buffer again * lisp/help-fns.el (describe-function): Pass in the correct buffer to look up key bindings in. (describe-function-1): Use it. diff --git a/lisp/help-fns.el b/lisp/help-fns.el index f200077fae..8b4905aed1 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -259,6 +259,7 @@ handling of autoloaded functions." (let ((describe-function-orig-buffer (or describe-function-orig-buffer (current-buffer))) + (key-buffer (current-buffer)) (help-buffer-under-preparation t)) (help-setup-xref @@ -277,7 +278,7 @@ handling of autoloaded functions." ;; Use " is " instead of a colon so that ;; it is easier to get out the function name using forward-sexp. (princ " is ") - (describe-function-1 function) + (describe-function-1 function key-buffer) (with-current-buffer standard-output ;; Return the text we displayed. (buffer-string)))))) @@ -1025,7 +1026,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." (unless (eq ?\n (char-before (1- (point)))) (insert "\n"))) ;;;###autoload -(defun describe-function-1 (function) +(defun describe-function-1 (function &optional key-bindings-buffer) (let ((pt1 (with-current-buffer standard-output (point)))) (help-fns-function-description-header function) (with-current-buffer standard-output @@ -1047,7 +1048,7 @@ Returns a list of the form (REAL-FUNCTION DEF ALIASED REAL-DEF)." (documentation function t) ;; E.g. an alias for a not yet defined function. ((invalid-function void-function) nil))) - (key-bindings-buffer (current-buffer))) + (key-bindings-buffer (or key-bindings-buffer (current-buffer)))) ;; If the function is autoloaded, and its docstring has ;; key substitution constructs, load the library. commit bb9c899b07a6a7de3a04b65caa55f11fdc36908c Author: Lars Ingebrigtsen Date: Sun Jun 5 21:35:56 2022 +0200 Make the goal column work for the scrolling commands, too * doc/emacs/basic.texi (Moving Point): Document it. * lisp/simple.el (set-goal-column): Update doc string. * lisp/window.el (scroll-up-command, scroll-down-command): Make the goal column take effect for these commands, too (bug#17346). diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi index b93a6d5de6..1a4abdc9ec 100644 --- a/doc/emacs/basic.texi +++ b/doc/emacs/basic.texi @@ -347,11 +347,11 @@ move to the column number specified by the argument's numeric value. @kindex C-x C-n @findex set-goal-column Use the current column of point as the @dfn{semipermanent goal column} -for @kbd{C-n} and @kbd{C-p} (@code{set-goal-column}) in the current -buffer. When a semipermanent goal column is in effect, those commands -always try to move to this column, or as close as possible to it, -after moving vertically. The goal column remains in effect until -canceled. +(@code{set-goal-column}) in the current buffer. When a semipermanent +goal column is in effect, @kbd{C-n}, @kbd{C-p}, @kbd{} and +@kbd{} always try to move to this column, or as close as +possible to it, after moving vertically. The goal column remains in +effect until canceled. @item C-u C-x C-n Cancel the goal column. Henceforth, @kbd{C-n} and @kbd{C-p} try to diff --git a/etc/NEWS b/etc/NEWS index 8250cac1cc..b75c1c9f6c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -136,6 +136,11 @@ of 'user-emacs-directory'. * Incompatible changes in Emacs 29.1 ++++ +** Setting the goal columns now also affects '' and ''. +Previously, 'C-x C-n' only affected 'next-line' and 'previous-line', +but it now also affects 'scroll-up-command' and 'scroll-down-command'. + --- ** The 'd' command in Dired now more consistently skip dot files. In previous Emacs versions, commands like `C-u 10 d' would put the "D" diff --git a/lisp/simple.el b/lisp/simple.el index a22df8025b..c749e6e41d 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8078,13 +8078,18 @@ For motion by visual lines, see `beginning-of-visual-line'." (put 'set-goal-column 'disabled t) (defun set-goal-column (arg) - "Set the current horizontal position as a goal for \\[next-line] and \\[previous-line]. + "Set the current horizontal position as a goal column. +This goal column will affect the \\[next-line] and \\[previous-line] commands, +as well as the \\[scroll-up-command] and \\[scroll-down-command] commands. + Those commands will move to this position in the line moved to rather than trying to keep the same horizontal position. -With a non-nil argument ARG, clears out the goal column -so that \\[next-line] and \\[previous-line] resume vertical motion. -The goal column is stored in the variable `goal-column'. -This is a buffer-local setting." + +With a non-nil argument ARG, clears out the goal column so that +these commands resume normal motion. + +The goal column is stored in the variable `goal-column'. This is +a buffer-local setting." (interactive "P") (if arg (progn diff --git a/lisp/window.el b/lisp/window.el index 5da867715f..1b8fe2b262 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -10103,28 +10103,45 @@ scroll window further, move cursor to the bottom line. When point is already on that position, then signal an error. A near full screen is `next-screen-context-lines' less than a full screen. Negative ARG means scroll downward. -If ARG is the atom `-', scroll downward by nearly full screen." + +If ARG is the atom `-', scroll downward by nearly full screen. + +The command \\[set-goal-column] can be used to create a +semipermanent goal column for this command." (interactive "^P") - (cond - ((null scroll-error-top-bottom) - (scroll-up arg)) - ((eq arg '-) - (scroll-down-command nil)) - ((< (prefix-numeric-value arg) 0) - (scroll-down-command (- (prefix-numeric-value arg)))) - ((eobp) - (scroll-up arg)) ; signal error - (t - (condition-case nil - (scroll-up arg) - (end-of-buffer - (if arg - ;; When scrolling by ARG lines can't be done, - ;; move by ARG lines instead. - (forward-line arg) - ;; When ARG is nil for full-screen scrolling, - ;; move to the bottom of the buffer. - (goto-char (point-max)))))))) + (prog1 + (cond + ((null scroll-error-top-bottom) + (scroll-up arg)) + ((eq arg '-) + (scroll-down-command nil)) + ((< (prefix-numeric-value arg) 0) + (scroll-down-command (- (prefix-numeric-value arg)))) + ((eobp) + (scroll-up arg)) ; signal error + (t + (condition-case nil + (scroll-up arg) + (end-of-buffer + (if arg + ;; When scrolling by ARG lines can't be done, + ;; move by ARG lines instead. + (forward-line arg) + ;; When ARG is nil for full-screen scrolling, + ;; move to the bottom of the buffer. + (goto-char (point-max))))))) + (scroll-command--goto-goal-column))) + +(defun scroll-command--goto-goal-column () + (when goal-column + ;; Move to the desired column. + (if (and line-move-visual + (not (or truncate-lines truncate-partial-width-windows))) + ;; Under line-move-visual, goal-column should be + ;; interpreted in units of the frame's canonical character + ;; width, which is exactly what vertical-motion does. + (vertical-motion (cons goal-column 0)) + (line-move-to-column (truncate goal-column))))) (put 'scroll-up-command 'scroll-command t) @@ -10140,28 +10157,34 @@ scroll window further, move cursor to the top line. When point is already on that position, then signal an error. A near full screen is `next-screen-context-lines' less than a full screen. Negative ARG means scroll upward. -If ARG is the atom `-', scroll upward by nearly full screen." + +If ARG is the atom `-', scroll upward by nearly full screen. + +The command \\[set-goal-column] can be used to create a +semipermanent goal column for this command." (interactive "^P") - (cond - ((null scroll-error-top-bottom) - (scroll-down arg)) - ((eq arg '-) - (scroll-up-command nil)) - ((< (prefix-numeric-value arg) 0) - (scroll-up-command (- (prefix-numeric-value arg)))) - ((bobp) - (scroll-down arg)) ; signal error - (t - (condition-case nil - (scroll-down arg) - (beginning-of-buffer - (if arg - ;; When scrolling by ARG lines can't be done, - ;; move by ARG lines instead. - (forward-line (- arg)) - ;; When ARG is nil for full-screen scrolling, - ;; move to the top of the buffer. - (goto-char (point-min)))))))) + (prog1 + (cond + ((null scroll-error-top-bottom) + (scroll-down arg)) + ((eq arg '-) + (scroll-up-command nil)) + ((< (prefix-numeric-value arg) 0) + (scroll-up-command (- (prefix-numeric-value arg)))) + ((bobp) + (scroll-down arg)) ; signal error + (t + (condition-case nil + (scroll-down arg) + (beginning-of-buffer + (if arg + ;; When scrolling by ARG lines can't be done, + ;; move by ARG lines instead. + (forward-line (- arg)) + ;; When ARG is nil for full-screen scrolling, + ;; move to the top of the buffer. + (goto-char (point-min))))))) + (scroll-command--goto-goal-column))) (put 'scroll-down-command 'scroll-command t) commit 8c00e21df220b7391ae2f86867419a882e4f1ce1 Author: Lars Ingebrigtsen Date: Sun Jun 5 20:32:01 2022 +0200 Move two more variables from autoload.el to loaddefs-gen.el * lisp/emacs-lisp/loaddefs-gen.el (generated-autoload-file) (generated-autoload-load-name): Move the remaining two autoload.el variables used by loaddefs-gen.el from autoload.el. diff --git a/lisp/emacs-lisp/autoload.el b/lisp/emacs-lisp/autoload.el index d324a7fc70..eed88b6faf 100644 --- a/lisp/emacs-lisp/autoload.el +++ b/lisp/emacs-lisp/autoload.el @@ -38,31 +38,6 @@ (require 'cl-lib) (require 'loaddefs-gen) -(defvar generated-autoload-file nil - "File into which to write autoload definitions. -A Lisp file can set this in its local variables section to make -its autoloads go somewhere else. - -If this is a relative file name, the directory is determined as -follows: - - If a Lisp file defined `generated-autoload-file' as a - file-local variable, use its containing directory. - - Otherwise use the \"lisp\" subdirectory of `source-directory'. - -The autoload file is assumed to contain a trailer starting with a -FormFeed character.") -;;;###autoload -(put 'generated-autoload-file 'safe-local-variable 'stringp) - -(defvar generated-autoload-load-name nil - "Load name for `autoload' statements generated from autoload cookies. -If nil, this defaults to the file name, sans extension. -Typically, you need to set this when the directory containing the file -is not in `load-path'. -This also affects the generated cus-load.el file.") -;;;###autoload -(put 'generated-autoload-load-name 'safe-local-variable 'stringp) - ;; This feels like it should be a defconst, but MH-E sets it to ;; ";;;###mh-autoload" for the autoloads that are to go into mh-loaddefs.el. (defvar generate-autoload-cookie ";;;###autoload" diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index 7661f60e0b..a6a4baffba 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -65,6 +65,31 @@ be included.") More specifically those definitions will not be considered for the `register-definition-prefixes' call.") +(defvar generated-autoload-file nil + "File into which to write autoload definitions. +A Lisp file can set this in its local variables section to make +its autoloads go somewhere else. + +If this is a relative file name, the directory is determined as +follows: + - If a Lisp file defined `generated-autoload-file' as a + file-local variable, use its containing directory. + - Otherwise use the \"lisp\" subdirectory of `source-directory'. + +The autoload file is assumed to contain a trailer starting with a +FormFeed character.") +;;;###autoload +(put 'generated-autoload-file 'safe-local-variable 'stringp) + +(defvar generated-autoload-load-name nil + "Load name for `autoload' statements generated from autoload cookies. +If nil, this defaults to the file name, sans extension. +Typically, you need to set this when the directory containing the file +is not in `load-path'. +This also affects the generated cus-load.el file.") +;;;###autoload +(put 'generated-autoload-load-name 'safe-local-variable 'stringp) + (defun loaddefs-generate--file-load-name (file outfile) "Compute the name that will be used to load FILE. OUTFILE should be the name of the global loaddefs.el file, which commit 3406e4064f09fb60c34317143209485bed18e366 Author: Lars Ingebrigtsen Date: Sun Jun 5 20:17:30 2022 +0200 Make finder/cus-dep scraping use generate-lisp-file functions * lisp/finder.el (finder-compile-keywords): * lisp/cus-dep.el (custom-make-dependencies): Use generate-lisp-file functions directly instead of piggy-backing on the autoload.el functions. (This is part of making autoload.el obsolete.) diff --git a/lisp/cus-dep.el b/lisp/cus-dep.el index 87dcbbb004..47d2cac3be 100644 --- a/lisp/cus-dep.el +++ b/lisp/cus-dep.el @@ -156,9 +156,9 @@ Usage: emacs -batch -l ./cus-dep.el -f custom-make-dependencies DIRS" (set-buffer (find-file-noselect generated-custom-dependencies-file)) (setq buffer-undo-list t) (erase-buffer) - (insert (autoload-rubric generated-custom-dependencies-file - "custom dependencies" t)) - (search-backward " ") + (generate-lisp-file-heading + generated-custom-dependencies-file 'custom-make-dependencies + :title "custom dependencies") (let (alist) (mapatoms (lambda (symbol) (let ((members (get symbol 'custom-group)) @@ -241,6 +241,7 @@ This is an alist whose members have as car a version string, and as elements the files that have variables or faces that contain that version. These files should be loaded before showing the customization buffer that `customize-changed' generates.\")\n\n")) + (generate-lisp-file-trailer generated-custom-dependencies-file) (save-buffer) (byte-compile-info (format "Generating %s...done" generated-custom-dependencies-file) t)) diff --git a/lisp/finder.el b/lisp/finder.el index a2a27ea061..73072c0cd4 100644 --- a/lisp/finder.el +++ b/lisp/finder.el @@ -127,8 +127,6 @@ Keywords and package names both should be symbols.") cus-load\\|finder-inf\\|esh-groups\\|subdirs\\|leim-list\\)\\.el$\\)" "Regexp matching file names not to scan for keywords.") -(autoload 'autoload-rubric "autoload") - (defconst finder--builtins-descriptions ;; I have no idea whether these are supposed to be capitalized ;; and/or end in a full-stop. Existing file headers are inconsistent, @@ -264,9 +262,9 @@ from; the default is `load-path'." (find-file-noselect generated-finder-keywords-file) (setq buffer-undo-list t) (erase-buffer) - (insert (autoload-rubric generated-finder-keywords-file - "keyword-to-package mapping" t)) - (search-backward " ") + (generate-lisp-file-heading + generated-finder-keywords-file 'finder-compile-keywords + :title "keyword-to-package mapping") ;; FIXME: Now that we have package--builtin-versions, package--builtins is ;; only needed to get the list of unversioned packages and to get the ;; summary description of each package. @@ -280,6 +278,7 @@ from; the default is `load-path'." (insert "(setq finder-keywords-hash\n ") (prin1 finder-keywords-hash (current-buffer)) (insert ")\n") + (generate-lisp-file-trailer generated-finder-keywords-file) (basic-save-buffer))) (defun finder-compile-keywords-make-dist () commit 251e7c30180223f636f2c67fede92e78e737466b Author: Stefan Kangas Date: Sun Jun 5 18:23:17 2022 +0200 Don't generate separate autoload file for htmlfontify * lisp/hfy-cmap.el: Update file local to no longer put htmlfontify autoloads in htmlfontify-loaddefs.el. * lisp/htmlfontify.el (htmlfontify-loaddefs): Don't require. * test/lisp/htmlfontify-tests.el (htmlfontify-autoload): Delete test (bug#52400). diff --git a/lisp/hfy-cmap.el b/lisp/hfy-cmap.el index 258502bfe7..c08359696d 100644 --- a/lisp/hfy-cmap.el +++ b/lisp/hfy-cmap.el @@ -859,8 +859,4 @@ Loads the variable `hfy-rgb-txt-color-map', which is used by (provide 'hfy-cmap) -;; Local Variables: -;; generated-autoload-file: "htmlfontify-loaddefs.el" -;; End: - ;;; hfy-cmap.el ends here diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el index 89cacdff21..dbcc152c15 100644 --- a/lisp/htmlfontify.el +++ b/lisp/htmlfontify.el @@ -81,8 +81,6 @@ (eval-when-compile (require 'cl-lib)) (require 'cus-edit) -(require 'htmlfontify-loaddefs) - (defconst htmlfontify-version 0.21) (defconst hfy-meta-tags diff --git a/test/lisp/htmlfontify-tests.el b/test/lisp/htmlfontify-tests.el index fdfe996b03..5c1f053066 100644 --- a/test/lisp/htmlfontify-tests.el +++ b/test/lisp/htmlfontify-tests.el @@ -21,15 +21,6 @@ (require 'ert) (require 'htmlfontify) -(ert-deftest htmlfontify-autoload () - "Tests to see whether reftex-auc has been autoloaded" - (should - (fboundp 'htmlfontify-load-rgb-file)) - (should - (autoloadp - (symbol-function - 'htmlfontify-load-rgb-file)))) - (ert-deftest htmlfontify-bug25468 () "Tests that htmlfontify can be loaded even if no shell is available (Bug#25468)." commit 98d454627ca2e9a6cdb906895b044e7221db3f2f Author: Lars Ingebrigtsen Date: Sun Jun 5 17:48:29 2022 +0200 Rename generate-file to generate-lisp-file * lisp/url/url-cookie.el (url-cookie-write-file): * lisp/international/titdic-cnv.el (tit-process-header) (miscdic-convert): * lisp/international/ja-dic-cnv.el (skkdic-convert): * lisp/international/emoji.el (emoji--generate-file): * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--rubric): * admin/unidata/unidata-gen.el (unidata-gen-file) (unidata-gen-charprop): Adjust callers. * lisp/emacs-lisp/generate-lisp-file.el: Renamed from generate-file.el. Also rename some keyword parameters and require a generator function. diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el index dc8c071999..0a9fd5108c 100644 --- a/admin/unidata/unidata-gen.el +++ b/admin/unidata/unidata-gen.el @@ -89,7 +89,7 @@ ;; PROPn: string representing the nth property value (eval-when-compile (require 'cl-lib)) -(require 'generate-file) +(require 'generate-lisp-file) (defvar unidata-list nil) @@ -1423,10 +1423,9 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (or elt (user-error "Unknown output file: %s" basename)) (or noninteractive (message "Generating %s..." file)) (with-temp-file file - (generate-file-heading - basename - :text (concat copyright " \ -Generated from Unicode data files by unidata-gen.el. \ + (generate-lisp-file-heading + basename 'unidata-gen-file + :commentary (concat copyright " \ The sources for this file are found in the admin/unidata/ directory in \ the Emacs sources. The Unicode data files are used under the \ Unicode Terms of Use, as contained in the file copyright.html in that \ @@ -1448,15 +1447,15 @@ same directory.")) (set-char-table-extra-slot table 3 describer)) (insert (format "(define-char-code-property '%S\n %S\n %S)\n" prop table docstring)))) - (generate-file-trailer basename :inhibit-provide t)))) + (generate-lisp-file-trailer basename :inhibit-provide t)))) (or noninteractive (message "Generating %s...done" file))) (defun unidata-gen-charprop (&optional charprop-file text) (or charprop-file (setq charprop-file (pop command-line-args-left))) (with-temp-file charprop-file - (generate-file-heading - charprop-file - :text "Automatically generated by unidata-gen.el. See the admin/unidata/ directory in the Emacs sources.") + (generate-lisp-file-heading + charprop-file 'unidata-gen-charprop + :commentary "See the admin/unidata/ directory in the Emacs sources.") (if text (insert text) (dolist (elt unidata-file-alist) @@ -1465,7 +1464,7 @@ same directory.")) (unidata-prop-prop proplist) (car elt) (unidata-prop-docstring proplist)))))) (or noninteractive (message "Writing %s..." charprop-file)) - (generate-file-trailer charprop-file))) + (generate-lisp-file-trailer charprop-file))) (defun unidata-gen-scripts (&optional file) ;; Running from Makefile. diff --git a/lisp/emacs-lisp/generate-file.el b/lisp/emacs-lisp/generate-lisp-file.el similarity index 82% rename from lisp/emacs-lisp/generate-file.el rename to lisp/emacs-lisp/generate-lisp-file.el index 456503df6a..8896a3f701 100644 --- a/lisp/emacs-lisp/generate-file.el +++ b/lisp/emacs-lisp/generate-lisp-file.el @@ -1,4 +1,4 @@ -;;; generate-file.el --- utility functions for generated files -*- lexical-binding: t -*- +;;; generate-lisp-file.el --- utility functions for generated files -*- lexical-binding: t -*- ;; Copyright (C) 2022 Free Software Foundation, Inc. @@ -26,17 +26,18 @@ (eval-when-compile (require 'cl-lib)) -(cl-defun generate-file-heading (file &key description text (code t)) - "Insert a standard header for FILE. +(cl-defun generate-lisp-file-heading (file generator + &key title commentary (code t)) + "Insert a standard header for FILE created by GENERATOR. This header will specify that this is a generated file that should not be edited. If `standard-output' is bound to a buffer, insert in that buffer. If no, insert at point in the current buffer. -DESCRIPTION (if any) will be used in the first line. +TITLE (if any) will be used in the first line. -TEXT (if given) will be inserted as a comment. +COMMENTARY (if given) will be inserted as a comment. If CODE is non-nil (which is the default), a Code: line is inserted." @@ -45,21 +46,22 @@ inserted." (current-buffer)) (insert ";;; " (file-name-nondirectory file) " --- " - (or description "automatically generated") + (or title "automatically generated") " (do not edit) " - " -*- lexical-binding: t -*-\n\n" + " -*- lexical-binding: t -*-\n" + (format ";; Generated by the `%s' function.\n\n" generator) ";; This file is part of GNU Emacs.\n\n") - (when text + (when commentary (insert ";;; Commentary:\n\n") (let ((start (point)) (fill-prefix ";; ")) - (insert ";; " text) + (insert ";; " commentary) (fill-region start (point)))) (ensure-empty-lines 1) (when code (insert ";;; Code:\n\n")))) -(cl-defun generate-file-trailer (file &key version inhibit-provide +(cl-defun generate-lisp-file-trailer (file &key version inhibit-provide (coding 'utf-8-emacs-unix) autoloads compile provide) "Insert a standard trailer for FILE. @@ -106,6 +108,6 @@ If no, insert at point in the current buffer." ";; End:\n\n" ";;; " (file-name-nondirectory file) " ends here\n"))) -(provide 'generate-file) +(provide 'generate-lisp-file) -;;; generate-file.el ends here +;;; generate-lisp-file.el ends here diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index 9aa2967d7b..7661f60e0b 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -40,7 +40,7 @@ (require 'radix-tree) (require 'lisp-mnt) -(require 'generate-file) +(require 'generate-lisp-file) (defvar autoload-compute-prefixes t "If non-nil, autoload will add code to register the prefixes used in a file. @@ -440,17 +440,18 @@ be a string naming the feature, otherwise it will be based on FILE's name." (let ((lp (and (equal type "package") (setq type "autoloads")))) (with-temp-buffer - (generate-file-heading - file - :description (concat "automatically extracted " (or type "autoloads")) - :text (and (string-match "/lisp/loaddefs\\.el\\'" file) - "This file will be copied to ldefs-boot.el and checked in periodically.")) + (generate-lisp-file-heading + file 'loaddefs-generate--rubric + :title (concat "automatically extracted " (or type "autoloads")) + :commentary (and (string-match "/lisp/loaddefs\\.el\\'" file) + "This file will be copied to ldefs-boot.el and checked in periodically.")) (when lp (insert "(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))\n\n")) (insert " \n;;; End of scraped data\n\n") - (generate-file-trailer file :provide (and (stringp feature) feature) - :inhibit-provide (not feature)) + (generate-lisp-file-trailer + file :provide (and (stringp feature) feature) + :inhibit-provide (not feature)) (buffer-string)))) (defun loaddefs-generate--insert-section-header (outbuf autoloads diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index d53b01173d..8970a466b7 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -31,7 +31,7 @@ (require 'cl-extra) (require 'transient) (require 'multisession) -(require 'generate-file) +(require 'generate-lisp-file) (defgroup emoji nil "Inserting Emojis." @@ -416,7 +416,7 @@ the name is not known." (dolist (glyph glyphs) (remhash glyph emoji--derived))) (with-temp-buffer - (generate-file-heading file) + (generate-lisp-file-heading file 'emoji--generate-file) (insert ";; Copyright © 1991-2021 Unicode, Inc. ;; Generated from Unicode data files by emoji.el. ;; The source for this file is found in the admin/unidata/emoji-test.txt @@ -427,7 +427,7 @@ the name is not known." (insert (format "(defconst %s '" var)) (pp (symbol-value var) (current-buffer)) (insert (format "\n) ;; End %s\n\n" var))) - (generate-file-trailer file) + (generate-lisp-file-trailer file) (write-region (point-min) (point-max) file))) (defun emoji--base-name (name derivations) diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el index 563eba6682..1bbc664e75 100644 --- a/lisp/international/ja-dic-cnv.el +++ b/lisp/international/ja-dic-cnv.el @@ -44,7 +44,7 @@ ;;; Code: -(require 'generate-file) +(require 'generate-lisp-file) ;; Name of a file to generate from SKK dictionary. (defvar ja-dic-filename "ja-dic.el") @@ -342,9 +342,8 @@ Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)." (with-current-buffer buf (erase-buffer) (buffer-disable-undo) - (generate-file-heading ja-dic-filename :code nil) - (insert ";;\tGenerated by the `skkdic-convert' function.\n" - ";;\tOriginal SKK dictionary file: " + (generate-lisp-file-heading ja-dic-filename 'skkdic-convert :code nil) + (insert ";; Original SKK dictionary file: " (file-relative-name (expand-file-name filename) dirname) "\n\n" ";;; Start of the header of the original SKK dictionary.\n\n") @@ -394,7 +393,7 @@ Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)." ;; Postfix (with-current-buffer buf (goto-char (point-max)) - (generate-file-trailer ja-dic-filename :compile t))) + (generate-lisp-file-trailer ja-dic-filename :compile t))) ;; Save the working buffer. (set-buffer buf) diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el index bdb77ca702..2a91e7cb5e 100644 --- a/lisp/international/titdic-cnv.el +++ b/lisp/international/titdic-cnv.el @@ -62,7 +62,7 @@ ;;; Code: (require 'quail) -(require 'generate-file) +(require 'generate-lisp-file) ;; List of values of key "ENCODE:" and the corresponding Emacs ;; coding-system and language environment name. @@ -270,12 +270,10 @@ SPC, 6, 3, 4, or 7 specifying a tone (SPC:陰平, 6:陽平, 3:上聲, 4:去聲, (tit-moveleft ",<") (tit-keyprompt nil)) - (generate-file-heading filename :code nil) + (generate-lisp-file-heading filename 'titdic-convert :code nil) (princ ";; Quail package `") (princ package) (princ "\n") - (princ (substitute-command-keys - ";; Generated by the `titdic-convert' function.\n")) (princ ";;\tOriginal TIT dictionary file: ") (princ (file-name-nondirectory filename)) (princ "\n\n") @@ -521,7 +519,7 @@ the generated Quail package is saved." ;; Process the body part (tit-process-body) - (generate-file-trailer + (generate-lisp-file-trailer filename :inhibit-provide t :compile t :coding nil)))))) ;;;###autoload @@ -1132,10 +1130,8 @@ the generated Quail package is saved." ;; Explicitly set eol format to `unix'. (setq coding-system-for-write 'utf-8-unix) (with-temp-file (expand-file-name quailfile dirname) - (generate-file-heading quailfile) + (generate-lisp-file-heading quailfile 'miscdic-convert) (insert (format-message ";; Quail package `%s'\n" name)) - (insert (format-message - ";; Generated by the `miscdic-convert' function.\n")) (insert ";; Source dictionary file: " dicfile "\n") (insert ";; Copyright notice of the source file\n") (insert ";;------------------------------------------------------\n") @@ -1157,7 +1153,7 @@ the generated Quail package is saved." (let ((dicbuf (current-buffer))) (with-current-buffer dstbuf (funcall converter dicbuf))))) - (generate-file-trailer + (generate-lisp-file-trailer quailfile :inhibit-provide t :compile t :coding nil))) (setq tail (cdr tail))))) diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el index dab367485e..15c78512c6 100644 --- a/lisp/url/url-cookie.el +++ b/lisp/url/url-cookie.el @@ -26,7 +26,7 @@ (require 'url-util) (require 'url-parse) (require 'url-domsuf) -(require 'generate-file) +(require 'generate-lisp-file) (eval-when-compile (require 'cl-lib)) @@ -159,7 +159,7 @@ i.e. 1970-1-1) are loaded as expiring one year from now instead." (insert ")\n(setq url-cookie-secure-storage\n '") (pp url-cookie-secure-storage (current-buffer))) (insert ")\n") - (generate-file-trailer fname :inhibit-provide t :autoloads t) + (generate-lisp-file-trailer fname :inhibit-provide t :autoloads t) (setq-local version-control 'never) (write-file fname)) (setq url-cookies-changed-since-last-save nil)))) commit e8a941cf705f26cf9571e1eba4d23bbc63a056e4 Author: Eli Zaretskii Date: Sun Jun 5 17:53:43 2022 +0300 ; * etc/NEWS: Fix wording of entry about 'file-expand-wildcards'. diff --git a/etc/NEWS b/etc/NEWS index 8514ed3c3c..8250cac1cc 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1942,7 +1942,7 @@ Previously it produced a nonsense value, -1, that was never intended. * Lisp Changes in Emacs 29.1 +++ -** 'file-expand-wildcards' can now also take a regexp match. +** 'file-expand-wildcards' can now also take a regexp as PATTERN argument. --- ** vc-mtn (the backend for Monotone) has been made obsolete. commit 9d2f4a8d5a92fdfab80ce9faf0dcfa159189916b Author: Lars Ingebrigtsen Date: Sun Jun 5 16:36:25 2022 +0200 Add convenience functions for generating Emacs Lisp files * lisp/url/url-cookie.el (url-cookie-write-file): * lisp/international/titdic-cnv.el (tit-process-header): * lisp/international/ja-dic-cnv.el (skkdic-convert): * lisp/international/emoji.el (emoji--generate-file): * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--rubric) * admin/unidata/unidata-gen.el (unidata-gen-file) (unidata-gen-charprop): Use the new functions. * lisp/emacs-lisp/generate-file.el: New file to provide convenience functions for generated files. It's not always trivial to know which parts of the trailer that has to be obfuscated to avoid not getting byte-compiled etc, and some parts of the headers/trailers are usually forgotten when hand-coding these. diff --git a/admin/unidata/unidata-gen.el b/admin/unidata/unidata-gen.el index 149f753558..dc8c071999 100644 --- a/admin/unidata/unidata-gen.el +++ b/admin/unidata/unidata-gen.el @@ -89,6 +89,7 @@ ;; PROPn: string representing the nth property value (eval-when-compile (require 'cl-lib)) +(require 'generate-file) (defvar unidata-list nil) @@ -1422,13 +1423,14 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (or elt (user-error "Unknown output file: %s" basename)) (or noninteractive (message "Generating %s..." file)) (with-temp-file file - (insert ";;; " basename " -*- lexical-binding:t -*- -;; " copyright " -;; Generated from Unicode data files by unidata-gen.el. -;; The sources for this file are found in the admin/unidata/ directory in -;; the Emacs sources. The Unicode data files are used under the -;; Unicode Terms of Use, as contained in the file copyright.html in that -;; same directory.\n") + (generate-file-heading + basename + :text (concat copyright " \ +Generated from Unicode data files by unidata-gen.el. \ +The sources for this file are found in the admin/unidata/ directory in \ +the Emacs sources. The Unicode data files are used under the \ +Unicode Terms of Use, as contained in the file copyright.html in that \ +same directory.")) (dolist (proplist (cdr elt)) (let ((prop (unidata-prop-prop proplist)) (index (unidata-prop-index proplist)) @@ -1446,21 +1448,15 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (set-char-table-extra-slot table 3 describer)) (insert (format "(define-char-code-property '%S\n %S\n %S)\n" prop table docstring)))) - (insert ";; Local Variables:\n" - ";; coding: utf-8\n" - ";; version-control: never\n" - ";; no-byte-compile: t\n" - ";; no-update-autoloads: t\n" - ";; End:\n\n" - (format ";;; %s ends here\n" basename))))) + (generate-file-trailer basename :inhibit-provide t)))) (or noninteractive (message "Generating %s...done" file))) (defun unidata-gen-charprop (&optional charprop-file text) (or charprop-file (setq charprop-file (pop command-line-args-left))) (with-temp-file charprop-file - (insert ";; Automatically generated by unidata-gen.el." - " -*- lexical-binding: t -*-\n" - ";; See the admin/unidata/ directory in the Emacs sources.\n") + (generate-file-heading + charprop-file + :text "Automatically generated by unidata-gen.el. See the admin/unidata/ directory in the Emacs sources.") (if text (insert text) (dolist (elt unidata-file-alist) @@ -1469,19 +1465,7 @@ Property value is a symbol `o' (Open), `c' (Close), or `n' (None)." (unidata-prop-prop proplist) (car elt) (unidata-prop-docstring proplist)))))) (or noninteractive (message "Writing %s..." charprop-file)) - (insert "\n" - (format "(provide '%s)\n" - (file-name-sans-extension - (file-name-nondirectory charprop-file))) - " \n" - ";; Local Variables:\n" - ";; coding: utf-8\n" - ";; version-control: never\n" - ";; no-byte-compile: t\n" - ";; no-update-autoloads: t\n" - ";; End:\n\n" - (format ";;; %s ends here\n" - (file-name-nondirectory charprop-file))))) + (generate-file-trailer charprop-file))) (defun unidata-gen-scripts (&optional file) ;; Running from Makefile. diff --git a/lisp/emacs-lisp/generate-file.el b/lisp/emacs-lisp/generate-file.el new file mode 100644 index 0000000000..456503df6a --- /dev/null +++ b/lisp/emacs-lisp/generate-file.el @@ -0,0 +1,111 @@ +;;; generate-file.el --- utility functions for generated files -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; Keywords: maint +;; Package: emacs + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; Code: + +(eval-when-compile (require 'cl-lib)) + +(cl-defun generate-file-heading (file &key description text (code t)) + "Insert a standard header for FILE. +This header will specify that this is a generated file that +should not be edited. + +If `standard-output' is bound to a buffer, insert in that buffer. +If no, insert at point in the current buffer. + +DESCRIPTION (if any) will be used in the first line. + +TEXT (if given) will be inserted as a comment. + +If CODE is non-nil (which is the default), a Code: line is +inserted." + (with-current-buffer (if (bufferp standard-output) + standard-output + (current-buffer)) + (insert ";;; " (file-name-nondirectory file) + " --- " + (or description "automatically generated") + " (do not edit) " + " -*- lexical-binding: t -*-\n\n" + ";; This file is part of GNU Emacs.\n\n") + (when text + (insert ";;; Commentary:\n\n") + (let ((start (point)) + (fill-prefix ";; ")) + (insert ";; " text) + (fill-region start (point)))) + (ensure-empty-lines 1) + (when code + (insert ";;; Code:\n\n")))) + +(cl-defun generate-file-trailer (file &key version inhibit-provide + (coding 'utf-8-emacs-unix) autoloads + compile provide) + "Insert a standard trailer for FILE. +By default, this trailer inhibits version control, byte +compilation, updating autoloads, and uses a `utf-8-emacs-unix' +coding system. These can be inhibited by providing non-nil +values to the VERSION, NO-PROVIDE, AUTOLOADS and COMPILE +keyword arguments. + +CODING defaults to `utf-8-emacs-unix'. Use a nil value to +inhibit generating this setting, or a coding system value to use +that. + +If PROVIDE is non-nil, use that in the `provide' statement +instead of using FILE as the basis. + +If `standard-output' is bound to a buffer, insert in that buffer. +If no, insert at point in the current buffer." + (with-current-buffer (if (bufferp standard-output) + standard-output + (current-buffer)) + (ensure-empty-lines 1) + (unless inhibit-provide + (insert (format "(provide '%s)\n\n" + (or provide + (file-name-sans-extension + (file-name-nondirectory file)))))) + ;; Some of the strings below are chopped into bits to inhibit + ;; automatic scanning tools from thinking that they are actual + ;; directives. + (insert ";; Local " "Variables:\n") + (unless version + (insert ";; version-control: never\n")) + (unless compile + (insert ";; no-byte-" "compile: t\n")) ;; #$ is byte-compiled into nil. + (unless autoloads + (insert ";; no-update-autoloads: t\n")) + (when coding + (insert (format ";; coding: %s\n" + (if (eq coding t) + 'utf-8-emacs-unix + coding)))) + (insert + ";; End:\n\n" + ";;; " (file-name-nondirectory file) " ends here\n"))) + +(provide 'generate-file) + +;;; generate-file.el ends here diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index dce5466be2..9aa2967d7b 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -40,6 +40,7 @@ (require 'radix-tree) (require 'lisp-mnt) +(require 'generate-file) (defvar autoload-compute-prefixes t "If non-nil, autoload will add code to register the prefixes used in a file. @@ -437,32 +438,20 @@ but adds an extra line to the output to modify `load-path'. If FEATURE is non-nil, FILE will provide a feature. FEATURE may be a string naming the feature, otherwise it will be based on FILE's name." - (let ((basename (file-name-nondirectory file)) - (lp (if (equal type "package") (setq type "autoloads")))) - (concat ";;; " basename - " --- automatically extracted " (or type "autoloads") - " -*- lexical-binding: t -*-\n" - (when (string-match "/lisp/loaddefs\\.el\\'" file) - ";; This file will be copied to ldefs-boot.el and checked in periodically.\n") - ";;\n" - ";;; Code:\n\n" - (if lp - "(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path))))\n\n") - " \n;;; End of scraped data\n\n" - ;; This is used outside of autoload.el, eg cus-dep, finder. - (if feature - (format "(provide '%s)\n" - (if (stringp feature) feature - (file-name-sans-extension basename)))) - ";; Local Variables:\n" - ";; version-control: never\n" - ";; no-byte-compile: t\n" ;; #$ is byte-compiled into nil. - ";; no-update-autoloads: t\n" - ";; coding: utf-8-emacs-unix\n" - ";; End:\n" - ";;; " basename - " ends here\n"))) + (let ((lp (and (equal type "package") (setq type "autoloads")))) + (with-temp-buffer + (generate-file-heading + file + :description (concat "automatically extracted " (or type "autoloads")) + :text (and (string-match "/lisp/loaddefs\\.el\\'" file) + "This file will be copied to ldefs-boot.el and checked in periodically.")) + (when lp + (insert "(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path))))\n\n")) + (insert " \n;;; End of scraped data\n\n") + (generate-file-trailer file :provide (and (stringp feature) feature) + :inhibit-provide (not feature)) + (buffer-string)))) (defun loaddefs-generate--insert-section-header (outbuf autoloads load-name file time) diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index df488708af..d53b01173d 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -31,6 +31,7 @@ (require 'cl-extra) (require 'transient) (require 'multisession) +(require 'generate-file) (defgroup emoji nil "Inserting Emojis." @@ -415,8 +416,8 @@ the name is not known." (dolist (glyph glyphs) (remhash glyph emoji--derived))) (with-temp-buffer - (insert ";; Generated file -- do not edit. -*- lexical-binding:t -*- -;; Copyright © 1991-2021 Unicode, Inc. + (generate-file-heading file) + (insert ";; Copyright © 1991-2021 Unicode, Inc. ;; Generated from Unicode data files by emoji.el. ;; The source for this file is found in the admin/unidata/emoji-test.txt ;; file in the Emacs sources. The Unicode data files are used under the @@ -426,18 +427,7 @@ the name is not known." (insert (format "(defconst %s '" var)) (pp (symbol-value var) (current-buffer)) (insert (format "\n) ;; End %s\n\n" var))) - (insert ";; Local" " Variables: -;; coding: utf-8 -;; version-control: never -;; no-byte-" - ;; Obfuscate to not inhibit compilation of this file, too. - "compile: t -;; no-update-autoloads: t -;; End: - -\(provide 'emoji-labels) - -\;;; emoji-labels.el ends here\n") + (generate-file-trailer file) (write-region (point-min) (point-max) file))) (defun emoji--base-name (name derivations) diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el index 7f7c0261dc..563eba6682 100644 --- a/lisp/international/ja-dic-cnv.el +++ b/lisp/international/ja-dic-cnv.el @@ -44,6 +44,8 @@ ;;; Code: +(require 'generate-file) + ;; Name of a file to generate from SKK dictionary. (defvar ja-dic-filename "ja-dic.el") @@ -340,13 +342,11 @@ Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)." (with-current-buffer buf (erase-buffer) (buffer-disable-undo) - (insert ";;; ja-dic.el --- dictionary for Japanese input method" - " -*- lexical-binding:t -*-\n" - ";;\tGenerated by the command `skkdic-convert'\n" + (generate-file-heading ja-dic-filename :code nil) + (insert ";;\tGenerated by the `skkdic-convert' function.\n" ";;\tOriginal SKK dictionary file: " (file-relative-name (expand-file-name filename) dirname) "\n\n" - ";; This file is part of GNU Emacs.\n\n" ";;; Start of the header of the original SKK dictionary.\n\n") (set-buffer skkbuf) (goto-char 1) @@ -394,13 +394,7 @@ Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)." ;; Postfix (with-current-buffer buf (goto-char (point-max)) - (insert ";;\n(provide 'ja-dic)\n\n" - ";; Local Variables:\n" - ";; version-control: never\n" - ";; no-update-autoloads: t\n" - ";; coding: utf-8\n" - ";; End:\n\n" - ";;; ja-dic.el ends here\n"))) + (generate-file-trailer ja-dic-filename :compile t))) ;; Save the working buffer. (set-buffer buf) diff --git a/lisp/international/titdic-cnv.el b/lisp/international/titdic-cnv.el index a3b6266791..bdb77ca702 100644 --- a/lisp/international/titdic-cnv.el +++ b/lisp/international/titdic-cnv.el @@ -62,6 +62,7 @@ ;;; Code: (require 'quail) +(require 'generate-file) ;; List of values of key "ENCODE:" and the corresponding Emacs ;; coding-system and language environment name. @@ -269,13 +270,12 @@ SPC, 6, 3, 4, or 7 specifying a tone (SPC:陰平, 6:陽平, 3:上聲, 4:去聲, (tit-moveleft ",<") (tit-keyprompt nil)) - (princ (format ";;; %s -*- lexical-binding:t -*-\n" - (file-name-nondirectory filename))) + (generate-file-heading filename :code nil) (princ ";; Quail package `") (princ package) (princ "\n") (princ (substitute-command-keys - ";; Generated by the command `titdic-convert'\n")) + ";; Generated by the `titdic-convert' function.\n")) (princ ";;\tOriginal TIT dictionary file: ") (princ (file-name-nondirectory filename)) (princ "\n\n") @@ -521,11 +521,8 @@ the generated Quail package is saved." ;; Process the body part (tit-process-body) - - (princ ";; Local Variables:\n") - (princ ";; version-control: never\n") - (princ ";; no-update-autoloads: t\n") - (princ ";; End:\n")))))) + (generate-file-trailer + filename :inhibit-provide t :compile t :coding nil)))))) ;;;###autoload (defun batch-titdic-convert (&optional force) @@ -1135,11 +1132,10 @@ the generated Quail package is saved." ;; Explicitly set eol format to `unix'. (setq coding-system-for-write 'utf-8-unix) (with-temp-file (expand-file-name quailfile dirname) - (insert (format ";;; %s -*- lexical-binding:t -*-\n" - (file-name-nondirectory quailfile))) + (generate-file-heading quailfile) (insert (format-message ";; Quail package `%s'\n" name)) (insert (format-message - ";; Generated by the command `miscdic-convert'\n")) + ";; Generated by the `miscdic-convert' function.\n")) (insert ";; Source dictionary file: " dicfile "\n") (insert ";; Copyright notice of the source file\n") (insert ";;------------------------------------------------------\n") @@ -1161,11 +1157,8 @@ the generated Quail package is saved." (let ((dicbuf (current-buffer))) (with-current-buffer dstbuf (funcall converter dicbuf))))) - (insert ";; Local Variables:\n" - ";; version-control: never\n" - ";; no-update-autoloads: t\n" - ";; End:\n\n" - ";;; " quailfile " ends here\n"))) + (generate-file-trailer + quailfile :inhibit-provide t :compile t :coding nil))) (setq tail (cdr tail))))) (defun batch-miscdic-convert () @@ -1228,7 +1221,4 @@ The library is named pinyin.el, and contains the constant (insert "(provide 'pinyin)\n")) (kill-emacs 0))) -;; Prevent "Local Variables" above confusing Emacs. - - ;;; titdic-cnv.el ends here diff --git a/lisp/url/url-cookie.el b/lisp/url/url-cookie.el index 42e1fa22fa..dab367485e 100644 --- a/lisp/url/url-cookie.el +++ b/lisp/url/url-cookie.el @@ -26,6 +26,7 @@ (require 'url-util) (require 'url-parse) (require 'url-domsuf) +(require 'generate-file) (eval-when-compile (require 'cl-lib)) @@ -158,10 +159,7 @@ i.e. 1970-1-1) are loaded as expiring one year from now instead." (insert ")\n(setq url-cookie-secure-storage\n '") (pp url-cookie-secure-storage (current-buffer))) (insert ")\n") - (insert " \n;; Local Variables:\n" - ";; version-control: never\n" - ";; no-byte-compile: t\n" - ";; End:\n") + (generate-file-trailer fname :inhibit-provide t :autoloads t) (setq-local version-control 'never) (write-file fname)) (setq url-cookies-changed-since-last-save nil)))) commit ac6660a2d026e89214814768990d0d232f0a9d06 Author: Eli Zaretskii Date: Sun Jun 5 17:08:49 2022 +0300 ; * lisp/international/fontset.el (setup-default-fontset): Fix comment. diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index d07619cd80..44421a96da 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -974,9 +974,10 @@ (set-fontset-font "fontset-default" 'emoji '("Noto Color Emoji" . "iso10646-1") nil 'prepend) - ;; This allows the display of tamil supplement characters. As these characters - ;; are pretty simple and do not need reordering, ligatures, vowel signs, virama - ;; etc. tml2 or other OTF tags are not needed here. + ;; This supports the display of Tamil Supplement characters. As + ;; these characters are pretty simple and do not need reordering, + ;; ligatures, vowel signs, virama etc., neither tml2 nor other OTF + ;; features are needed here. (set-fontset-font "fontset-default" '(#x11FC0 . #x11FFF) '("Noto Sans Tamil Supplement" . "iso10646-1") nil 'append) commit 0e2b70b6594f58243fdcc8b2739d21f3f36e4545 Author: समीर सिंह Sameer Singh Date: Sun Jun 5 17:09:40 2022 +0530 Add a fallback font for Tamil Supplement characters * lisp/international/fontset.el (setup-default-fontset): Add and entry for "Noto Sans Tamil Supplement". (Bug#55807) diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index 74be7edc64..d07619cd80 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -974,6 +974,12 @@ (set-fontset-font "fontset-default" 'emoji '("Noto Color Emoji" . "iso10646-1") nil 'prepend) + ;; This allows the display of tamil supplement characters. As these characters + ;; are pretty simple and do not need reordering, ligatures, vowel signs, virama + ;; etc. tml2 or other OTF tags are not needed here. + (set-fontset-font "fontset-default" '(#x11FC0 . #x11FFF) + '("Noto Sans Tamil Supplement" . "iso10646-1") nil 'append) + ;; Append CJK fonts for characters other than han, kana, cjk-misc. ;; Append fonts for scripts whose name is also a charset name. (let* ((data (build-default-fontset-data)) commit 11dadfbf3b497a86d2b0fb4c51eb95c5b4c13423 Author: JD Smith Date: Sun Jun 5 15:59:37 2022 +0200 Make the Unicode tree widget prettier * lisp/tree-widget.el (tree-widget-nohandle-guide): New widget: "One small change is needed to accommodate this style. `tree-widget-guide’ specifies a single vertical bar “guide” widget. In the unicode tree, two separate vertical bars are needed — one “plain” (│), and one which connects to the horizontal “handle” preceding the node (├)." (tree-widget--cursors): (tree-widget): (tree-widget-value-create): Use it. Copyright-paperwork-exempt: yes diff --git a/lisp/tree-widget.el b/lisp/tree-widget.el index 4ba96a36a4..f91b36bfc2 100644 --- a/lisp/tree-widget.el +++ b/lisp/tree-widget.el @@ -319,6 +319,7 @@ has been found accessible." '( ("guide" . arrow) ("no-guide" . arrow) + ("nohandle-guide" . arrow) ("end-guide" . arrow) ("handle" . arrow) ("no-handle" . arrow) @@ -440,6 +441,12 @@ Handle mouse button 1 click on buttons.") :format "%t" ) +(define-widget 'tree-widget-nohandle-guide 'item + "Vertical guide line, when there is no handle." + :tag " |" + ;;:tag-glyph (tree-widget-find-image "nohandle-guide") + :format "%t") + (define-widget 'tree-widget-end-guide 'item "End of a vertical guide line." :tag " \\=`" @@ -483,6 +490,7 @@ Handle mouse button 1 click on buttons.") :empty-icon 'tree-widget-empty-icon :leaf-icon 'tree-widget-leaf-icon :guide 'tree-widget-guide + :nohandle-guide 'tree-widget-nohandle-guide :end-guide 'tree-widget-end-guide :no-guide 'tree-widget-no-guide :handle 'tree-widget-handle @@ -612,11 +620,13 @@ This hook should be local in the buffer setup to display widgets.") ;;;; Expanded node. (let ((args (widget-get tree :args)) (guide (widget-get tree :guide)) + (nohandle-guide (widget-get tree :nohandle-guide)) (noguide (widget-get tree :no-guide)) (endguide (widget-get tree :end-guide)) (handle (widget-get tree :handle)) (nohandle (widget-get tree :no-handle)) (guidi (tree-widget-find-image "guide")) + (nohandle-guidi (tree-widget-find-image "nohandle-guide")) (noguidi (tree-widget-find-image "no-guide")) (endguidi (tree-widget-find-image "end-guide")) (handli (tree-widget-find-image "handle")) @@ -648,8 +658,8 @@ This hook should be local in the buffer setup to display widgets.") ;; Insert guide lines elements from previous levels. (dolist (f (reverse flags)) (widget-create-child-and-convert - tree (if f guide noguide) - :tag-glyph (if f guidi noguidi)) + tree (if f nohandle-guide noguide) + :tag-glyph (if f nohandle-guidi noguidi)) (widget-create-child-and-convert tree nohandle :tag-glyph nohandli)) ;; Insert guide line element for this level. commit 408fa62148e54e90ab67ad02b338fafadc0bbd76 Author: Lars Ingebrigtsen Date: Sun Jun 5 15:43:38 2022 +0200 Add new command find-sibling-file * doc/emacs/files.texi (Visiting): Document it. * lisp/files.el (file-expand-wildcards): Fix up the regexp expansion. (find-sibling-rules, find-sibling-file): New user option and command. (find-sibling-file--search): New helper function. diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index ffd8079fc1..2c4f1f4619 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -326,6 +326,45 @@ of @code{require-final-newline} (@pxref{Customize Save}). If you have already visited the same file in the usual (non-literal) manner, this command asks you whether to visit it literally instead. +@findex find-sibling-file +@vindex find-sibling-rules +Files are sometimes (loosely) tied to other files, and you could call +these files @dfn{sibling files}. For instance, when editing C files, +if you have a file called @samp{"foo.c"}, you often also have a file +called @samp{"foo.h"}, and that could be its sibling file. Or you may +have different versions of a file, for instance +@samp{"src/emacs/emacs-27/lisp/allout.el"} and +@samp{"src/emacs/emacs-28/lisp/allout.el"} might be considered +siblings. Emacs provides the @code{find-sibling-file} command to jump +between sibling files, but it's impossible to guess at which files a +user might want to be considered siblings, so Emacs lets you configure +this freely by altering the @code{find-sibling-rules} user option. +This is a list of match/expansion elements. + +For instance, to do the @samp{".c"} to @samp{".h"} mapping, you could +say: + +@lisp +(setq find-sibling-rules + '(("\\([^/]+\\)\\.c\\'" "\\1.h"))) +@end lisp + +Or, if you want to consider all files under +@samp{"src/emacs/DIR/file-name"} to be siblings of other @var{dir}s, +you could say: + +@lisp +(setq find-sibling-rules + '(("src/emacs/[^/]+/\\(.*\\)\\'" "src/emacs/.*/\\1"))) +@end lisp + +As you can see, this is a list of @var{(MATCH EXPANSION...)} elements. +The @var{match} is a regular expression that matches the visited file +name, and each @var{expansion} may refer to match groups by using +@samp{\\1} and so on. The resulting expansion string is then applied +to the file system to see if any files match this expansion +(interpreted as a regexp). + @vindex find-file-hook @vindex find-file-not-found-functions Two special hook variables allow extensions to modify the operation diff --git a/etc/NEWS b/etc/NEWS index a46bf850b1..8514ed3c3c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -271,6 +271,11 @@ startup. Previously, these functions ignored * Changes in Emacs 29.1 ++++ +** New command 'find-sibling-file'. +This command jumps to a file considered a "sibling file", which is +determined according to the new user option 'find-sibling-rules'. + +++ ** New user option 'delete-selection-temporary-region'. When non-nil, 'delete-selection-mode' will only delete the temporary diff --git a/lisp/files.el b/lisp/files.el index 95f5b2c535..6c6fcbc55d 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7241,10 +7241,13 @@ default directory. However, if FULL is non-nil, they are absolute." (unless (string-match "\\`\\.\\.?\\'" (file-name-nondirectory name)) name)) - (directory-files (or dir ".") full - (if regexp - nondir - (wildcard-to-regexp nondir))))))) + (directory-files + (or dir ".") full + (if regexp + ;; We're matching each file name + ;; element separately. + (concat "\\`" nondir "\\'") + (wildcard-to-regexp nondir))))))) (setq contents (nconc (if (and dir (not full)) @@ -7254,6 +7257,89 @@ default directory. However, if FULL is non-nil, they are absolute." contents))))) contents))) +(defcustom find-sibling-rules nil + "Rules for finding \"sibling\" files. +This is used by the `find-sibling-file' command. + +This variable is a list of (MATCH EXPANSION...) elements. + +MATCH is a regular expression that should match a file name that +has a sibling. It can contain sub-expressions that will be used +in EXPANSIONS. + +EXPANSION is a string that matches file names. For instance, to +define \".h\" files as siblings of any \".c\", you could say: + + (\"\\\\([^/]+\\\\)\\\\.c\\\\\\='\" \"\\\\1.h\") + +MATCH and EXPANSION can also be fuller paths. For instance, if +you want to define other versions of a project as being sibling +files, you could say something like: + + (\"src/emacs/[^/]+/\\\\(.*\\\\)\\\\\\='\" \"src/emacs/.*/\\\\1\\\\\\='\") + +In this example, if you're in src/emacs/emacs-27/lisp/abbrev.el, +and you an src/emacs/emacs-28/lisp/abbrev.el file exists, it's +now defined as a sibling." + :type 'sexp + :version "29.1") + +(defun find-sibling-file (file) + "Visit a \"sibling\" file of FILE. +By default, return only files that exist, but if ALL is non-nil, +return all matches. + +When called interactively, FILE is the currently visited file. + +The \"sibling\" file is defined by the `find-sibling-rules' variable." + (interactive (progn + (unless buffer-file-name + (user-error "Not visiting a file")) + (list buffer-file-name))) + (let ((siblings (find-sibling-file--search (expand-file-name file)))) + (if (length= siblings 1) + (find-file (car siblings)) + (let ((relatives (mapcar (lambda (sibling) + (file-relative-name + sibling (file-name-directory file))) + siblings))) + (find-file + (completing-read (format-prompt "Find file" (car relatives)) + relatives nil t nil nil (car relatives))))))) + +(defun find-sibling-file--search (file) + (let ((results nil)) + (pcase-dolist (`(,match . ,expansions) find-sibling-rules) + ;; Go through the list and find matches. + (when (string-match match file) + (let ((match-data (match-data))) + (dolist (expansion expansions) + (let ((start 0)) + ;; Expand \\1 forms in the expansions. + (while (string-match "\\\\\\([0-9]+\\)" expansion start) + (let ((index (string-to-number (match-string 1 expansion)))) + (setq start (match-end 0) + expansion + (replace-match + (substring file + (elt match-data (* index 2)) + (elt match-data (1+ (* index 2)))) + t t expansion))))) + ;; Then see which files we have that are matching. (And + ;; expand from the end of the file's match, since we might + ;; be doing a relative match.) + (let ((default-directory (substring file 0 (car match-data)))) + ;; Keep the first matches first. + (setq results + (nconc + results + (mapcar #'expand-file-name + (file-expand-wildcards expansion nil t))))))))) + ;; Delete the file itself (in case it matched), and remove + ;; duplicates, in case we have several expansions and some match + ;; the same subsets of files. + (delete file (delete-dups results)))) + ;; Let Tramp know that `file-expand-wildcards' does not need an advice. (provide 'files '(remote-wildcards)) commit 25e53e93910f19ff66aa8f13271f119218acdc6f Author: Eli Zaretskii Date: Sun Jun 5 16:40:22 2022 +0300 ; * lisp/files.el (file-expand-wildcards): Doc fix. diff --git a/lisp/files.el b/lisp/files.el index 292c05b58e..ea57f02ac0 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7109,15 +7109,15 @@ by `sh' are supported." :group 'dired) (defun file-expand-wildcards (pattern &optional full) - "Expand wildcard pattern PATTERN. -This returns a list of file names that match the pattern. -Files are sorted in `string<' order. + "Expand (a.k.a. \"glob\") file-name wildcard pattern PATTERN. +This returns a list of file names that match PATTERN. +The returned list of file names is sorted in the `string<' order. If PATTERN is written as an absolute file name, -the values are absolute also. +the expansions in the returned list are also absolute. If PATTERN is written as a relative file name, it is interpreted -relative to the current default directory, `default-directory'. +relative to the current `default-directory'. The file names returned are normally also relative to the current default directory. However, if FULL is non-nil, they are absolute." (save-match-data commit fcb4d836f01cbec30cb5f906941179c566414b81 Author: Po Lu Date: Sun Jun 5 21:16:09 2022 +0800 Fix file name encoding of Motif drop protocol file selections * lisp/select.el (xselect-convert-to-filename): (xselect-convert-to-dt-netfile): Encode in the file name coding system instead of `raw-text-unix'. diff --git a/lisp/select.el b/lisp/select.el index c5412f2a73..83dc137e23 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -633,7 +633,8 @@ two markers or an overlay. Otherwise, it is nil." ;; Motif expects this to be STRING, but it treats the data as ;; a sequence of bytes instead of a Latin-1 string. (cons 'STRING (encode-coding-string (expand-file-name value) - 'raw-text-unix)) + (or file-name-coding-system + default-file-name-coding-system))) (when (vectorp value) (with-temp-buffer (cl-loop for file across value @@ -643,7 +644,8 @@ two markers or an overlay. Otherwise, it is nil." (delete-char -1)) ;; Motif wants STRING. (cons 'STRING (encode-coding-string (buffer-string) - 'raw-text-unix))))))) + (or file-name-coding-system + default-file-name-coding-system)))))))) (defun xselect-convert-to-charpos (_selection _type value) (when (setq value (xselect--selection-bounds value)) @@ -771,8 +773,11 @@ VALUE should be SELECTION's local value." (stringp value) (file-exists-p value) (not (file-remote-p value))) - (encode-coding-string (xselect-tt-net-file value) - 'raw-text-unix t))) + (cons 'STRING + (encode-coding-string (xselect-tt-net-file value) + (or file-name-coding-system + default-file-name-coding-system) + t)))) (setq selection-converter-alist '((TEXT . xselect-convert-to-string) commit d8924e179e2e53bf9abffa987f428890b4edcf57 Author: Lars Ingebrigtsen Date: Sun Jun 5 14:08:31 2022 +0200 Extend file-expand-wildcards to allow regexps * doc/lispref/files.texi (Contents of Directories): Document it. * lisp/files.el (file-expand-wildcards): Extend to allow regexps. * lisp/emacs-lisp/shortdoc.el (file): Expand the file-expand-wildcards example. diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi index 75905658e6..d473261026 100644 --- a/doc/lispref/files.texi +++ b/doc/lispref/files.texi @@ -3112,10 +3112,16 @@ except those two. It is useful as the @var{match-regexp} argument to returns @code{nil}, if directory @samp{/foo} is empty. @end defvr -@defun file-expand-wildcards pattern &optional full +@defun file-expand-wildcards pattern &optional full regexp This function expands the wildcard pattern @var{pattern}, returning a list of file names that match it. +@var{pattern} is, by default, a ``glob''/wildcard string, e.g., +@samp{"/tmp/*.png"} or @samp{"/*/*/foo.png"}, but can also be a +regular expression if the optional @var{regexp} parameter is non-nil. +In any case, the matches are applied per sub-directory, so a match +can't span a parent/sub directory. + If @var{pattern} is written as an absolute file name, the values are absolute also. diff --git a/etc/NEWS b/etc/NEWS index 551aea411e..a46bf850b1 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1936,6 +1936,9 @@ Previously it produced a nonsense value, -1, that was never intended. * Lisp Changes in Emacs 29.1 ++++ +** 'file-expand-wildcards' can now also take a regexp match. + --- ** vc-mtn (the backend for Monotone) has been made obsolete. diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 92b9c1dd32..a1256ce1b8 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -468,7 +468,9 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), :no-eval* (directory-files-and-attributes "/tmp/foo")) (file-expand-wildcards :no-eval (file-expand-wildcards "/tmp/*.png") - :eg-result ("/tmp/foo.png" "/tmp/zot.png")) + :eg-result ("/tmp/foo.png" "/tmp/zot.png") + :no-eval (file-expand-wildcards "/*/foo.png") + :eg-result ("/tmp/foo.png" "/var/foo.png")) (locate-dominating-file :no-eval (locate-dominating-file "foo.png" "/tmp/foo/bar/zot") :eg-result "/tmp/foo.png") diff --git a/lisp/files.el b/lisp/files.el index b5da0ea5c5..95f5b2c535 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7198,13 +7198,21 @@ by `sh' are supported." :type 'string :group 'dired) -(defun file-expand-wildcards (pattern &optional full) +(defun file-expand-wildcards (pattern &optional full regexp) "Expand wildcard pattern PATTERN. This returns a list of file names that match the pattern. -Files are sorted in `string<' order. -If PATTERN is written as an absolute file name, -the values are absolute also. +PATTERN is, by default, a \"glob\"/wildcard string, e.g., +\"/tmp/*.png\" or \"/*/*/foo.png\", but can also be a regular +expression if the optional REGEXP parameter is non-nil. In any +case, the matches are applied per sub-directory, so a match can't +span a parent/sub directory, which means that a regexp bit can't +contain the \"/\" character. + +The list of files returned are sorted in `string<' order. + +If PATTERN is written as an absolute file name, the values are +absolute also. If PATTERN is written as a relative file name, it is interpreted relative to the current default directory, `default-directory'. @@ -7219,7 +7227,8 @@ default directory. However, if FULL is non-nil, they are absolute." (dirs (if (and dirpart (string-match "[[*?]" (file-local-name dirpart))) (mapcar 'file-name-as-directory - (file-expand-wildcards (directory-file-name dirpart))) + (file-expand-wildcards + (directory-file-name dirpart) nil regexp)) (list dirpart))) contents) (dolist (dir dirs) @@ -7233,7 +7242,9 @@ default directory. However, if FULL is non-nil, they are absolute." (file-name-nondirectory name)) name)) (directory-files (or dir ".") full - (wildcard-to-regexp nondir)))))) + (if regexp + nondir + (wildcard-to-regexp nondir))))))) (setq contents (nconc (if (and dir (not full)) commit 3ea9357d109e303fece9d49e1fdad8a2e42cc858 Author: Eli Zaretskii Date: Sun Jun 5 11:28:10 2022 +0300 Update documentation of 'aset' and 'store-substring' * doc/lispref/strings.texi (Modifying Strings): Adjust to implementation changes: it is possible for the modified string to have fewer or more bytes than the original. Add recommendations regarding unibyte vs multibyte strings and characters. (Bug#55801) diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 742ab76244..c9612e598a 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -461,23 +461,29 @@ Remove the final newline, if any, from @var{string}. described in this section. @xref{Mutability}. The most basic way to alter the contents of an existing string is with -@code{aset} (@pxref{Array Functions}). @code{(aset @var{string} -@var{idx} @var{char})} stores @var{char} into @var{string} at index -@var{idx}. Each character occupies one or more bytes, and if @var{char} -needs a different number of bytes from the character already present at -that index, @code{aset} signals an error. +@code{aset} (@pxref{Array Functions}). @w{@code{(aset @var{string} +@var{idx} @var{char})}} stores @var{char} into @var{string} at character +index @var{idx}. It will automatically convert a pure-@acronym{ASCII} +@var{string} to a multibyte string (@pxref{Text Representations}) if +needed, but we recommend to always make sure @var{string} is multibyte +(e.g., by using @code{string-to-multibyte}, @pxref{Converting +Representations}), if @var{char} is a non-@acronym{ASCII} character, not +a raw byte. A more powerful function is @code{store-substring}: @defun store-substring string idx obj -This function alters part of the contents of the string @var{string}, by -storing @var{obj} starting at index @var{idx}. The argument @var{obj} -may be either a character or a (smaller) string. - -Since it is impossible to change the length of an existing string, it is -an error if @var{obj} doesn't fit within @var{string}'s actual length, -or if any new character requires a different number of bytes from the -character currently present at that point in @var{string}. +This function alters part of the contents of the specified @var{string}, +by storing @var{obj} starting at character index @var{idx}. The +argument @var{obj} may be either a character (in which case the function +behaves exactly as @code{aset}) or a (smaller) string. If @var{obj} +is a multibyte string, we recommend to make sure @var{string} is also +multibyte, even if it's pure-@acronym{ASCII}. + +Since it is impossible to change the number of characters in an +existing string, it is en error if @var{obj} consists of more +characters than would fit in @var{string} starting at character index +@var{idx}. @end defun To clear out a string that contained a password, use commit 6011d39b6a4bc659da364255bcae22c4e6ef3a3f Author: Po Lu Date: Sun Jun 5 15:34:49 2022 +0800 Fix drag-and-drop of files with multibyte filenames * lisp/dired.el (dired-mouse-drag): Fix re-signalling of errors. * lisp/select.el (xselect-convert-to-filename): (xselect-convert-to-text-uri-list): (xselect-convert-to-dt-netfile): Encode in raw-text-unix. * src/xgselect.c (suppress_xg_select, release_xg_select): New functions. (xg_select): Respect xg_select suppression by delegating to pselect. * src/xgselect.h: Update prototypes. * src/xterm.c (x_dnd_begin_drag_and_drop): Suppress xg_select during the nested event loop. (handle_one_xevent): Handle cases where hold_quit is nil inside a selection event handler during DND. diff --git a/lisp/dired.el b/lisp/dired.el index 7df50a7b2a..55e150e9e0 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -1787,12 +1787,12 @@ other marked file as well. Otherwise, unmark all files." nil action t)))) (error (when (eq (event-basic-type new-event) 'mouse-1) (push new-event unread-command-events)) - ;; Errors from `dnd-begin-drag-file' should be + ;; Errors from `dnd-begin-drag-files' should be ;; treated as user errors, since they should ;; only occur when the user performs an invalid ;; action, such as trying to create a link to - ;; an invalid file. - (user-error error)))))))))) + ;; a remote file. + (user-error (cadr error))))))))))) (defvar dired-mouse-drag-files-map (let ((keymap (make-sparse-keymap))) (define-key keymap [down-mouse-1] #'dired-mouse-drag) diff --git a/lisp/select.el b/lisp/select.el index df1d402655..c5412f2a73 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -630,20 +630,20 @@ two markers or an overlay. Otherwise, it is nil." (xselect--encode-string 'TEXT (buffer-file-name (nth 2 value)))) (if (and (stringp value) (file-exists-p value)) - (xselect--encode-string 'TEXT (expand-file-name value) - nil t) + ;; Motif expects this to be STRING, but it treats the data as + ;; a sequence of bytes instead of a Latin-1 string. + (cons 'STRING (encode-coding-string (expand-file-name value) + 'raw-text-unix)) (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"))) + do (insert (expand-file-name file) "\0")) ;; Get rid of the last NULL byte. (when (> (point) 1) (delete-char -1)) ;; Motif wants STRING. - (cons 'STRING (buffer-string))))))) + (cons 'STRING (encode-coding-string (buffer-string) + 'raw-text-unix))))))) (defun xselect-convert-to-charpos (_selection _type value) (when (setq value (xselect--selection-bounds value)) @@ -710,14 +710,15 @@ This function returns the string \"emacs\"." (defun xselect-convert-to-text-uri-list (_selection _type value) (if (stringp value) - (concat (url-encode-url value) "\n") + (xselect--encode-string 'TEXT + (concat (url-encode-url value) "\n")) (when (vectorp value) (with-temp-buffer (cl-loop for tem across value do (progn (insert (url-encode-url tem)) (insert "\n"))) - (buffer-string))))) + (xselect--encode-string 'TEXT (buffer-string)))))) (defun xselect-convert-to-xm-file (selection _type value) (when (and (stringp value) @@ -770,7 +771,8 @@ VALUE should be SELECTION's local value." (stringp value) (file-exists-p value) (not (file-remote-p value))) - (xselect-tt-net-file value))) + (encode-coding-string (xselect-tt-net-file value) + 'raw-text-unix t))) (setq selection-converter-alist '((TEXT . xselect-convert-to-string) diff --git a/src/xgselect.c b/src/xgselect.c index 7252210c68..6e09a15fa8 100644 --- a/src/xgselect.c +++ b/src/xgselect.c @@ -33,6 +33,9 @@ along with GNU Emacs. If not, see . */ static ptrdiff_t threads_holding_glib_lock; static GMainContext *glib_main_context; +/* The depth of xg_select suppression. */ +static int xg_select_suppress_count; + void release_select_lock (void) { @@ -69,6 +72,23 @@ acquire_select_lock (GMainContext *context) #endif } +/* Call this to not use xg_select when using it would be a bad idea, + i.e. during drag-and-drop. */ +void +suppress_xg_select (void) +{ + ++xg_select_suppress_count; +} + +void +release_xg_select (void) +{ + if (!xg_select_suppress_count) + emacs_abort (); + + --xg_select_suppress_count; +} + /* `xg_select' is a `pselect' replacement. Why do we need a separate function? 1. Timeouts. Glib and Gtk rely on timer events. If we did pselect with a greater timeout then the one scheduled by Glib, we would @@ -100,6 +120,9 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set *efds, bool already_has_events; #endif + if (xg_select_suppress_count) + return pselect (fds_lim, rfds, wfds, efds, timeout, sigmask); + context = g_main_context_default (); acquire_select_lock (context); diff --git a/src/xgselect.h b/src/xgselect.h index 15482cbf92..156d4bde59 100644 --- a/src/xgselect.h +++ b/src/xgselect.h @@ -25,9 +25,10 @@ along with GNU Emacs. If not, see . */ struct timespec; -extern int xg_select (int max_fds, - fd_set *rfds, fd_set *wfds, fd_set *efds, - struct timespec *timeout, sigset_t *sigmask); +extern int xg_select (int, fd_set *, fd_set *, fd_set *, + struct timespec *, sigset_t *); +extern void suppress_xg_select (void); +extern void release_xg_select (void); extern void release_select_lock (void); diff --git a/src/xterm.c b/src/xterm.c index a6ef2bfd15..4d8d7e80eb 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -700,6 +700,10 @@ along with GNU Emacs. If not, see . */ #endif #endif +#ifdef USE_GTK +#include +#endif + #include "bitmaps/gray.xbm" #ifdef HAVE_XKB @@ -10760,6 +10764,13 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (x_dnd_toplevels) x_dnd_free_toplevels (true); +#ifdef USE_GTK + /* Prevent GTK+ timeouts from being run, since they can call + handle_one_xevent behind our back. */ + suppress_xg_select (); + record_unwind_protect_void (release_xg_select); +#endif + x_dnd_in_progress = true; x_dnd_frame = f; x_dnd_last_seen_window = None; @@ -15818,7 +15829,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, || (x_dnd_waiting_for_finish && dpyinfo->display == x_dnd_finish_display)) { +#ifndef USE_GTK eassume (hold_quit); +#else + /* If the debugger runs inside a selection converter, then + xg_select can call handle_one_xevent with no + hold_quit. */ + if (!hold_quit) + goto done; +#endif *hold_quit = inev.ie; EVENT_INIT (inev.ie); commit 993853531aebb303870d6ff1ba7db2007d464b63 Author: Eli Zaretskii Date: Sun Jun 5 09:52:09 2022 +0300 Fix sorting in ls-lisp.el under -v * lisp/ls-lisp.el (ls-lisp-version-lessp): Handle correctly the case where strings begin with numerical parts. More faithful implementation of the 'strverscmp' spec for fractional parts. (Bug#55787) * test/lisp/ls-lisp-tests.el (ls-lisp-test-bug55787): New test. diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el index 33dd98ef8d..6d1f449568 100644 --- a/lisp/ls-lisp.el +++ b/lisp/ls-lisp.el @@ -621,14 +621,22 @@ in some standard C libraries does." (sub2 (substring s2 ni2 e2)) ;; "Fraction" is a numerical sequence with leading zeros. (fr1 (string-match "\\`0+" sub1)) - (fr2 (string-match "\\`0+" sub2))) + (efr1 (match-end 0)) + (fr2 (string-match "\\`0+" sub2)) + (efr2 (match-end 0))) (cond - ((and fr1 fr2) ; two fractions, the shortest wins - (setq val (- val (- (length sub1) (length sub2))))) + ;; Two fractions: the longer one is less than the other, + ;; but only if the "common prefix" is all-zeroes, + ;; otherwise fall back on numerical comparison. + ((and fr1 fr2) + (if (or (and (< efr1 (- e1 ni1)) (< efr2 (- e2 ni2)) + (not (eq (aref sub1 efr1) (aref sub2 efr2)))) + (= efr1 (- e1 ni1)) (= efr2 (- e2 ni2))) + (setq val (- val (- (length sub1) (length sub2)))))) (fr1 ; a fraction is always less than an integral - (setq val (- ni1))) + (setq val (- 0 ni1 1))) ; make sure val is non-zero (fr2 - (setq val ni2))) + (setq val (1+ ni2)))) ; make sure val is non-zero (if (zerop val) ; fall back on numerical comparison (setq val (- (string-to-number sub1) (string-to-number sub2)))) diff --git a/test/lisp/ls-lisp-tests.el b/test/lisp/ls-lisp-tests.el index 3e23fc7454..39843defc2 100644 --- a/test/lisp/ls-lisp-tests.el +++ b/test/lisp/ls-lisp-tests.el @@ -93,5 +93,44 @@ (should (looking-back "[[:space:]]" (1- (point))))) (when (buffer-live-p buf) (kill-buffer buf))))) +(ert-deftest ls-lisp-test-bug55787 () + "Test proper sorting by version." + (let ((files1 (vector "34 klmn-300dpi.jpg" + "34 klmn-300dpi.png" + "054_xyz.jpg" + "054_xyz.png" + "91 opqrs.jpg" + "91 opqrs.png" + "0717-abcd.jpg" + "0717-abcd.png" + "1935 uv.jpg" + "1935 uv.png" + "FFFF_fghk.jpg" + "FFFF_fghk.png" + "hhhh.jpg" + "hhhh.png")) + (files2 (vector "01.0" "10" "010" "01.2"))) + (should (equal (sort files1 + (lambda (x y) + (ls-lisp-version-lessp x y))) + '["0717-abcd.jpg" + "0717-abcd.png" + "054_xyz.jpg" + "054_xyz.png" + "34 klmn-300dpi.jpg" + "34 klmn-300dpi.png" + "91 opqrs.jpg" + "91 opqrs.png" + "1935 uv.jpg" + "1935 uv.png" + "FFFF_fghk.jpg" + "FFFF_fghk.png" + "hhhh.jpg" + "hhhh.png"])) + (should (equal (sort files2 + (lambda (x y) + (ls-lisp-version-lessp x y))) + '["01.0" "01.2" "010" "10"])))) + (provide 'ls-lisp-tests) ;;; ls-lisp-tests.el ends here commit e4725ab688f0c64f79312b32ce6fb3bc7f0b4b51 Author: Po Lu Date: Sun Jun 5 13:03:55 2022 +0800 Fix bug#55779 * src/xterm.c (x_update_opaque_region): Don't make GTK reset the opaque region if F is a child frame. diff --git a/src/xterm.c b/src/xterm.c index 3b60dba69b..a6ef2bfd15 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -4349,11 +4349,16 @@ x_update_opaque_region (struct frame *f, XEvent *configure) (unsigned char *) &opaque_region, 4); else { - object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f)); - class = GTK_WIDGET_CLASS (object_class); + /* This causes child frames to not update correctly for an + unknown reason. (bug#55779) */ + if (!FRAME_PARENT_FRAME (f)) + { + object_class = G_OBJECT_GET_CLASS (FRAME_GTK_OUTER_WIDGET (f)); + class = GTK_WIDGET_CLASS (object_class); - if (class->style_updated) - class->style_updated (FRAME_GTK_OUTER_WIDGET (f)); + if (class->style_updated) + class->style_updated (FRAME_GTK_OUTER_WIDGET (f)); + } } #endif unblock_input (); commit 7d7a6f6719ddf99a4afefe6ae44f7cba48707d45 Author: Po Lu Date: Sun Jun 5 13:02:58 2022 +0800 Better respect window manager stacking order * src/xfns.c (x_frame_list_z_order, Fx_frame_list_z_order): Use _NET_CLIENT_LIST_STACKING if supported. * src/xterm.c (x_wm_supports_1): New function. Accept dpyinfo instead of frame. (x_wm_supports): Use that function instead. * src/xterm.h: Update prototypes. diff --git a/src/xfns.c b/src/xfns.c index e3763a5589..cfc6d4c212 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6600,17 +6600,61 @@ menu bar or tool bar of FRAME. */) * WINDOW to FRAMES and return FRAMES. */ static Lisp_Object -x_frame_list_z_order (Display* dpy, Window window) +x_frame_list_z_order (struct x_display_info *dpyinfo, Window window) { + Display *dpy; Window root, parent, *children; unsigned int nchildren; - int i; - Lisp_Object frames = Qnil; + unsigned long i; + Lisp_Object frames, val; + Atom type; + Window *toplevels; + int format, rc; + unsigned long nitems, bytes_after; + unsigned char *data; + struct frame *f; + + dpy = dpyinfo->display; + data = NULL; + frames = Qnil; + + if (window == dpyinfo->root_window + && x_wm_supports_1 (dpyinfo, + dpyinfo->Xatom_net_client_list_stacking)) + { + rc = XGetWindowProperty (dpyinfo->display, dpyinfo->root_window, + dpyinfo->Xatom_net_client_list_stacking, + 0, LONG_MAX, False, XA_WINDOW, &type, + &format, &nitems, &bytes_after, &data); + + if (rc != Success) + return Qnil; + + if (format != 32 || type != XA_WINDOW) + { + XFree (data); + return Qnil; + } + + toplevels = (Window *) data; + + for (i = 0; i < nitems; ++i) + { + f = x_top_window_to_frame (dpyinfo, toplevels[i]); + + if (f) + { + XSETFRAME (val, f); + frames = Fcons (val, frames); + } + } + + XFree (data); + return frames; + } - block_input (); if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren)) { - unblock_input (); for (i = 0; i < nchildren; i++) { Lisp_Object frame, tail; @@ -6628,10 +6672,9 @@ x_frame_list_z_order (Display* dpy, Window window) } } - if (children) XFree ((char *)children); + if (children) + XFree (children); } - else - unblock_input (); return frames; } @@ -6652,7 +6695,6 @@ Frames are listed from topmost (first) to bottommost (last). */) (Lisp_Object terminal) { struct x_display_info *dpyinfo = check_x_display_info (terminal); - Display *dpy = dpyinfo->display; Window window; if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal))) @@ -6660,7 +6702,7 @@ Frames are listed from topmost (first) to bottommost (last). */) else window = dpyinfo->root_window; - return x_frame_list_z_order (dpy, window); + return x_frame_list_z_order (dpyinfo, window); } /** diff --git a/src/xterm.c b/src/xterm.c index 2bf37e94d6..3b60dba69b 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -22591,17 +22591,16 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity) https://freedesktop.org/wiki/Specifications/wm-spec/. */ bool -x_wm_supports (struct frame *f, Atom want_atom) +x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom) { Atom actual_type; unsigned long actual_size, bytes_remaining; int i, rc, actual_format; bool ret; Window wmcheck_window; - struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); Window target_window = dpyinfo->root_window; int max_len = 65536; - Display *dpy = FRAME_X_DISPLAY (f); + Display *dpy = dpyinfo->display; unsigned char *tmp_data = NULL; Atom target_type = XA_WINDOW; @@ -22675,6 +22674,13 @@ x_wm_supports (struct frame *f, Atom want_atom) return ret; } +bool +x_wm_supports (struct frame *f, Atom want_atom) +{ + return x_wm_supports_1 (FRAME_DISPLAY_INFO (f), + want_atom); +} + static void set_wm_state (Lisp_Object frame, bool add, Atom atom, Atom value) { diff --git a/src/xterm.h b/src/xterm.h index d7e184ed9f..878cb5fd87 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -1497,6 +1497,7 @@ extern void x_set_shaded (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object); extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object); extern bool x_wm_supports (struct frame *, Atom); +extern bool x_wm_supports_1 (struct x_display_info *, Atom); extern void x_wait_for_event (struct frame *, int); extern void x_clear_under_internal_border (struct frame *f); commit d46e94f23fbbd522f2a017444b29f9f18203b4bc Merge: ddfb91c0a7 1b8719835a Author: Stefan Kangas Date: Sun Jun 5 06:30:25 2022 +0200 Merge from origin/emacs-28 1b8719835a Update to Org 9.5.4 92c5faafd7 Clarify documentation of 'string-to-unibyte' 2848512654 ; * lisp/files.el (find-file): Avoid too short lines in do... 672f9f787f Improve keystrokes in doc strings in some find-file functions ef5651cc77 Fix segfaults when starting on 80x26 TTY frames bfa647972f ; Fix doc string of 'delete-selection-repeat-replace-region' a95d46e00f Make it explicit that a couple of _s in lispref are unders... 5c74c25123 Remove from FAQ the MS-Windows info about BDF fonts edb48646f2 Fix Display Property manual example commit ddfb91c0a7e46f0332caf82237cabc736ddfd276 Author: Po Lu Date: Sun Jun 5 10:02:55 2022 +0800 Fix positioning of non-system tooltips on GTK builds * src/xfns.c (compute_tip_xy): Fix coding style. * src/xterm.c (handle_one_xevent): Set tooltip size immediately on GTK builds. diff --git a/src/xfns.c b/src/xfns.c index d696078440..e3763a5589 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -8156,9 +8156,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms) the display in *ROOT_X, and *ROOT_Y. */ static void -compute_tip_xy (struct frame *f, - Lisp_Object parms, Lisp_Object dx, Lisp_Object dy, - int width, int height, int *root_x, int *root_y) +compute_tip_xy (struct frame *f, Lisp_Object parms, Lisp_Object dx, + Lisp_Object dy, int width, int height, int *root_x, + int *root_y) { Lisp_Object left, top, right, bottom; int win_x, win_y; @@ -8184,7 +8184,7 @@ compute_tip_xy (struct frame *f, &root, &child, root_x, root_y, &win_x, &win_y, &pmask); unblock_input (); - XSETFRAME(frame, f); + XSETFRAME (frame, f); attributes = Fx_display_monitor_attributes_list (frame); /* Try to determine the monitor where the mouse pointer is and @@ -8199,11 +8199,13 @@ compute_tip_xy (struct frame *f, min_y = XFIXNUM (Fnth (make_fixnum (2), geometry)); max_x = min_x + XFIXNUM (Fnth (make_fixnum (3), geometry)); max_y = min_y + XFIXNUM (Fnth (make_fixnum (4), geometry)); + if (min_x <= *root_x && *root_x < max_x && min_y <= *root_y && *root_y < max_y) { break; } + max_y = -1; } @@ -8213,7 +8215,7 @@ compute_tip_xy (struct frame *f, /* It was not possible to determine the monitor's geometry, so we assign some sane defaults here: */ - if ( max_y < 0 ) + if (max_y < 0) { min_x = 0; min_y = 0; diff --git a/src/xterm.c b/src/xterm.c index 57a3f73cac..2bf37e94d6 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -17554,15 +17554,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, #endif x_net_wm_state (f, configureEvent.xconfigure.window); -#ifdef USE_X_TOOLKIT +#if defined USE_X_TOOLKIT || defined USE_GTK /* Tip frames are pure X window, set size for them. */ if (FRAME_TOOLTIP_P (f)) { if (FRAME_PIXEL_HEIGHT (f) != configureEvent.xconfigure.height || FRAME_PIXEL_WIDTH (f) != configureEvent.xconfigure.width) - { - SET_FRAME_GARBAGED (f); - } + SET_FRAME_GARBAGED (f); + FRAME_PIXEL_HEIGHT (f) = configureEvent.xconfigure.height; FRAME_PIXEL_WIDTH (f) = configureEvent.xconfigure.width; } commit f15f9ddea1ee512d017b1abf132d648f999a07f6 Author: Po Lu Date: Sun Jun 5 09:30:45 2022 +0800 Adjust last change for GTK+ 2.x * src/xterm.c (x_tooltip_window_to_frame): Fix build on GTK 2.x. diff --git a/src/xterm.c b/src/xterm.c index 3eb9ee21da..57a3f73cac 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10318,12 +10318,21 @@ x_tooltip_window_to_frame (struct x_display_info *dpyinfo, else tooltip_window = NULL; +#ifdef HAVE_GTK3 if (tooltip_window && (gdk_x11_window_get_xid (tooltip_window) == wdesc)) { *unrelated_tooltip_p = true; break; } +#else + if (tooltip_window + && (GDK_WINDOW_XID (tooltip_window) == wdesc)) + { + *unrelated_tooltip_p = true; + break; + } +#endif #endif } commit 3f349a08ae0f23ccbef96f21e7c1a9a1c5869a9b Author: Po Lu Date: Sun Jun 5 09:24:20 2022 +0800 Make `mouse-position' work correctly with GTK tooltips * src/xterm.c (x_tooltip_window_to_frame): New parameter `unrelated_tooltip_p'. (XTmouse_position): Pass that, and if it turns out to be true, look beneath the tooltip window. diff --git a/src/xterm.c b/src/xterm.c index 34a40da548..3eb9ee21da 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10281,13 +10281,22 @@ 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. */ +/* Like x_any_window_to_frame but only try to find tooltip frames. + + If wdesc is a toolkit tooltip without an associated frame, set + UNRELATED_TOOLTIP_P to true. Otherwise, set it to false. */ static struct frame * x_tooltip_window_to_frame (struct x_display_info *dpyinfo, - Window wdesc) + Window wdesc, bool *unrelated_tooltip_p) { Lisp_Object tail, frame; struct frame *f; +#ifdef USE_GTK + GtkWidget *widget; + GdkWindow *tooltip_window; +#endif + + *unrelated_tooltip_p = false; FOR_EACH_FRAME (tail, frame) { @@ -10297,6 +10306,25 @@ x_tooltip_window_to_frame (struct x_display_info *dpyinfo, && FRAME_DISPLAY_INFO (f) == dpyinfo && FRAME_X_WINDOW (f) == wdesc) return f; + +#ifdef USE_GTK + if (FRAME_X_OUTPUT (f)->ttip_window) + widget = GTK_WIDGET (FRAME_X_OUTPUT (f)->ttip_window); + else + widget = NULL; + + if (widget) + tooltip_window = gtk_widget_get_window (widget); + else + tooltip_window = NULL; + + if (tooltip_window + && (gdk_x11_window_get_xid (tooltip_window) == wdesc)) + { + *unrelated_tooltip_p = true; + break; + } +#endif } return NULL; @@ -11782,6 +11810,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, { struct frame *f1, *maybe_tooltip; struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); + bool unrelated_tooltip; block_input (); @@ -11882,9 +11911,10 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, && (EQ (track_mouse, Qdrag_source) || EQ (track_mouse, Qdropping))) { - maybe_tooltip = x_tooltip_window_to_frame (dpyinfo, child); + maybe_tooltip = x_tooltip_window_to_frame (dpyinfo, child, + &unrelated_tooltip); - if (maybe_tooltip) + if (maybe_tooltip || unrelated_tooltip) child = x_get_window_below (dpyinfo->display, child, parent_x, parent_y, &win_x, &win_y); commit 1b8719835a200a2be17da226e82030f691caba80 Author: Kyle Meyer Date: Sat Jun 4 16:21:06 2022 -0400 Update to Org 9.5.4 diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex index 2b4718805a..bb4bc5b25d 100644 --- a/etc/refcards/orgcard.tex +++ b/etc/refcards/orgcard.tex @@ -1,5 +1,5 @@ % Reference Card for Org Mode -\def\orgversionnumber{9.5.3} +\def\orgversionnumber{9.5.4} \def\versionyear{2021} % latest update \input emacsver.tex diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el index 895d124e14..081a617834 100644 --- a/lisp/org/org-clock.el +++ b/lisp/org/org-clock.el @@ -1106,7 +1106,7 @@ to be CLOCKED OUT.")))) 60)) (keep (or (and (memq ch '(?k ?K)) - (read-number "Keep how many minutes? " default)) + (read-number "Keep how many minutes: " default)) (and (memq ch '(?t ?T)) (floor (/ (float-time @@ -1114,7 +1114,7 @@ to be CLOCKED OUT.")))) 60))))) (gotback (and (memq ch '(?g ?G)) - (read-number "Got back how many minutes ago? " default))) + (read-number "Got back how many minutes ago: " default))) (subtractp (memq ch '(?s ?S))) (barely-started-p (org-time-less-p (org-time-subtract last-valid (cdr clock)) diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 6bafb6fc37..6bdcb0afff 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -5,13 +5,13 @@ (defun org-release () "The release version of Org. Inserted by installing Org mode or when a release is made." - (let ((org-release "9.5.3")) + (let ((org-release "9.5.4")) org-release)) ;;;###autoload (defun org-git-version () "The Git version of Org mode. Inserted by installing Org or when a release is made." - (let ((org-git-version "release_9.5.3-6-gef41f3")) + (let ((org-git-version "release_9.5.4")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/org.el b/lisp/org/org.el index 6842bfe9b1..06af12339e 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -9,7 +9,7 @@ ;; Homepage: https://orgmode.org ;; Package-Requires: ((emacs "25.1")) -;; Version: 9.5.3 +;; Version: 9.5.4 ;; This file is part of GNU Emacs. ;; commit e74652386d62a5a6142bf6332e0e4b4aa48c7088 Author: Lars Ingebrigtsen Date: Sat Jun 4 18:41:10 2022 +0200 Make loaddefs-generate--parse-file more robust * lisp/emacs-lisp/loaddefs-gen.el (loaddefs-generate--parse-file): Ensure that we don't have an autoload cookie on the first column inside a string. diff --git a/lisp/emacs-lisp/loaddefs-gen.el b/lisp/emacs-lisp/loaddefs-gen.el index 2e345d6669..dce5466be2 100644 --- a/lisp/emacs-lisp/loaddefs-gen.el +++ b/lisp/emacs-lisp/loaddefs-gen.el @@ -359,42 +359,49 @@ don't include." (goto-char (point-min)) ;; The cookie might be like ;;;###tramp-autoload... (while (re-search-forward lisp-mode-autoload-regexp nil t) - ;; ... and if we have one of these names, then alter outfile. - (let* ((aname (match-string 2)) - (to-file (if aname - (expand-file-name - (concat aname "-loaddefs.el") - (file-name-directory file)) - (or local-outfile main-outfile)))) - (if (eolp) - ;; We have a form following. - (let* ((form (prog1 - (read (current-buffer)) - (unless (bolp) - (forward-line 1)))) - (autoload (or (loaddefs-generate--make-autoload - form load-name) - form))) - ;; We get back either an autoload form, or a tree - ;; structure of `(progn ...)' things, so unravel that. - (let ((forms (if (eq (car autoload) 'progn) - (cdr autoload) - (list autoload)))) - (while forms - (let ((elem (pop forms))) - (if (eq (car elem) 'progn) - ;; More recursion; add it to the start. - (setq forms (nconc (cdr elem) forms)) - ;; We have something to add to the defs; do it. - (push (list to-file file elem) defs)))))) - ;; Just put the rest of the line into the loaddefs. - ;; FIXME: We skip the first space if there's more - ;; whitespace after. - (when (looking-at-p " [\t ]") - (forward-char 1)) - (push (list to-file file - (buffer-substring (point) (line-end-position))) - defs)))) + (when (or package-data + ;; Outside of the main Emacs build (`package-data' + ;; is set in the Emacs build), check that we don't + ;; have an autoload cookie on the first column of a + ;; doc string or the like. (The Emacs tree + ;; shouldn't contain any such instances.) + (not (ppss-string-terminator (syntax-ppss)))) + ;; ... and if we have one of these names, then alter outfile. + (let* ((aname (match-string 2)) + (to-file (if aname + (expand-file-name + (concat aname "-loaddefs.el") + (file-name-directory file)) + (or local-outfile main-outfile)))) + (if (eolp) + ;; We have a form following. + (let* ((form (prog1 + (read (current-buffer)) + (unless (bolp) + (forward-line 1)))) + (autoload (or (loaddefs-generate--make-autoload + form load-name) + form))) + ;; We get back either an autoload form, or a tree + ;; structure of `(progn ...)' things, so unravel that. + (let ((forms (if (eq (car autoload) 'progn) + (cdr autoload) + (list autoload)))) + (while forms + (let ((elem (pop forms))) + (if (eq (car elem) 'progn) + ;; More recursion; add it to the start. + (setq forms (nconc (cdr elem) forms)) + ;; We have something to add to the defs; do it. + (push (list to-file file elem) defs)))))) + ;; Just put the rest of the line into the loaddefs. + ;; FIXME: We skip the first space if there's more + ;; whitespace after. + (when (looking-at-p " [\t ]") + (forward-char 1)) + (push (list to-file file + (buffer-substring (point) (line-end-position))) + defs))))) (when (and autoload-compute-prefixes compute-prefixes) commit 0a5477b448e6b62bcedc1803e531ec7686eea48d Author: Lars Ingebrigtsen Date: Sat Jun 4 15:07:01 2022 +0200 Make skkdic-convert replacements literal * lisp/international/ja-dic-cnv.el (skkdic-convert): The replacement is literal and fixed-case. (The build on EMBA is failing mysteriously with "Match data clobbered by buffer modification hooks", so this is mainly a stab in the dark at fixing that, but it's also generally correct.) diff --git a/lisp/international/ja-dic-cnv.el b/lisp/international/ja-dic-cnv.el index 704f1a1ae6..7f7c0261dc 100644 --- a/lisp/international/ja-dic-cnv.el +++ b/lisp/international/ja-dic-cnv.el @@ -335,7 +335,7 @@ Saves the output as `ja-dic-filename', in directory DIRNAME (if specified)." (insert-file-contents (expand-file-name filename))) (re-search-forward "^[^;]") (while (re-search-forward ";[^\n/]*/" nil t) - (replace-match "/"))) + (replace-match "/" t t))) ;; Setup and generate the header part of working buffer. (with-current-buffer buf (erase-buffer) commit 54ed817eeeeb735cdfb384ae310caf62be5b7e20 Author: Lars Ingebrigtsen Date: Sat Jun 4 14:16:26 2022 +0200 Make vc-mtn obsolete * lisp/obsolete/vc-mtn.el: Make obsolete (bug#6513). diff --git a/etc/NEWS b/etc/NEWS index 850854edfa..551aea411e 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1936,6 +1936,9 @@ Previously it produced a nonsense value, -1, that was never intended. * Lisp Changes in Emacs 29.1 +--- +** vc-mtn (the backend for Monotone) has been made obsolete. + +++ ** 'gui-set-selection' can now specify different values for different data types. If DATA is a string, then its text properties are searched for values diff --git a/lisp/vc/vc-mtn.el b/lisp/obsolete/vc-mtn.el similarity index 99% rename from lisp/vc/vc-mtn.el rename to lisp/obsolete/vc-mtn.el index 20fbf92bb1..cd56b29007 100644 --- a/lisp/vc/vc-mtn.el +++ b/lisp/obsolete/vc-mtn.el @@ -5,6 +5,7 @@ ;; Author: Stefan Monnier ;; Keywords: vc ;; Package: vc +;; Obsolete-since: 29.1 ;; This file is part of GNU Emacs. commit d37d099ad7968ed9217599faa168571699fa03e4 Author: Lars Ingebrigtsen Date: Sat Jun 4 14:04:41 2022 +0200 Fix failing shortdoc test * lisp/emacs-lisp/shortdoc.el (string): Each example section is supposed to contain only examples of using the function in question (as policed by the FAILED shortdoc-examples test). diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 5c94b06e76..92b9c1dd32 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -260,16 +260,16 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), :no-manual t :eval (string-blank-p " \n")) (string-lessp - :eval (string-lessp "foo" "bar")) + :eval (string-lessp "foo" "bar") + :eval (string-lessp "pic4.png" "pic32.png") + :eval (string-lessp "1.1" "1 2")) (string-greaterp :eval (string-greaterp "foo" "bar")) (string-version-lessp :eval (string-version-lessp "pic4.png" "pic32.png") - :eval (string-lessp "pic4.png" "pic32.png")) + :eval (string-version-lessp "1.1" "1 2")) (string-collate-lessp - :eval (string-collate-lessp "1.1" "1 2") - :eval (string-version-lessp "1.1" "1 2") - :eval (string-lessp "1.1" "1 2")) + :eval (string-collate-lessp "1.1" "1 2")) (string-prefix-p :eval (string-prefix-p "foo" "foobar")) (string-suffix-p commit fe6f1dfeb4ad4aaf517d1ac34435f3750f7f4569 Author: Po Lu Date: Sat Jun 4 20:00:40 2022 +0800 Fix error during DND from both Emacs and GTK at the same time * src/xterm.c (x_dnd_get_target_window): Make mapping and releasing the COW atomic. This is to fix a rare bug when MPX (multi-pointer X) is in use and the user tries to drag from both GTK and Emacs at the same time using multiple seats. diff --git a/src/xterm.c b/src/xterm.c index edfb89070f..34a40da548 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3524,10 +3524,13 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, dpyinfo->Xatom_NET_WM_CM_Sn) != None) { x_catch_errors (dpyinfo->display); + XGrabServer (dpyinfo->display); overlay_window = XCompositeGetOverlayWindow (dpyinfo->display, dpyinfo->root_window); XCompositeReleaseOverlayWindow (dpyinfo->display, dpyinfo->root_window); + XUngrabServer (dpyinfo->display); + if (!x_had_errors_p (dpyinfo->display)) { XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs); @@ -3682,10 +3685,13 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, dpyinfo->Xatom_NET_WM_CM_Sn) != None) { x_catch_errors (dpyinfo->display); + XGrabServer (dpyinfo->display); overlay_window = XCompositeGetOverlayWindow (dpyinfo->display, dpyinfo->root_window); XCompositeReleaseOverlayWindow (dpyinfo->display, dpyinfo->root_window); + XUngrabServer (dpyinfo->display); + if (!x_had_errors_p (dpyinfo->display)) { XGetWindowAttributes (dpyinfo->display, overlay_window, &attrs); commit f76f529524113513397ab50fb7b8f7aaba197152 Author: Lars Ingebrigtsen Date: Sat Jun 4 14:00:10 2022 +0200 Further raise-sexp doc string improvement * lisp/emacs-lisp/lisp.el (raise-sexp): Fix the key binding syntax in the doc string. diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index 9d9ae41f30..d6086abe59 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -870,7 +870,7 @@ For instance, if you have: (zot) (+ foo 2))) -and point is before (zot), `M-x raise-sexp' will give you +and point is before (zot), \\[raise-sexp] will give you (let ((foo 2)) (zot))" commit b3dc23dd60896423f1a7ccbe5ab747f54599ea24 Author: Lars Ingebrigtsen Date: Sat Jun 4 13:57:08 2022 +0200 Improve the raise-sexp doc string * lisp/emacs-lisp/lisp.el (raise-sexp): Try to explain what the command does (bug#55788). diff --git a/lisp/emacs-lisp/lisp.el b/lisp/emacs-lisp/lisp.el index ffca0dcf4f..9d9ae41f30 100644 --- a/lisp/emacs-lisp/lisp.el +++ b/lisp/emacs-lisp/lisp.el @@ -858,7 +858,22 @@ The option `delete-pair-blink-delay' can disable blinking." (delete-char 1)))) (defun raise-sexp (&optional arg) - "Raise ARG sexps higher up the tree." + "Raise ARG sexps higher up the tree. +This means that the ARGth enclosing form will be deleted and +replaced with the form that follows point. + +For instance, if you have: + + (let ((foo 2)) + (progn + (setq foo 3) + (zot) + (+ foo 2))) + +and point is before (zot), `M-x raise-sexp' will give you + + (let ((foo 2)) + (zot))" (interactive "p") (let ((s (if (and transient-mark-mode mark-active) (buffer-substring (region-beginning) (region-end)) commit a418730a1b071953ac8ed61662664b369b3deac4 Author: Lars Ingebrigtsen Date: Sat Jun 4 13:50:07 2022 +0200 Fix warnings introduced by the lisp-mode-autoload-regexp change * lisp/emacs-lisp/lisp-mode.el (lisp-fdefs): The package name bit in ###;;;foo-autoload may be missing, so do a lax match (bug#55784). diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index c2d0efbf50..aaec13d1af 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -437,7 +437,7 @@ This will generate compile-time constants from BINDINGS." ;; Emacs Lisp autoload cookies. Supports the slightly different ;; forms used by mh-e, calendar, etc. (,lisp-mode-autoload-regexp (3 font-lock-warning-face prepend) - (2 font-lock-function-name-face prepend))) + (2 font-lock-function-name-face prepend t))) "Subdued level highlighting for Emacs Lisp mode.") (defconst lisp-cl-font-lock-keywords-1 commit f0189819d848e3a0302b7a6ac6979874121f8ee8 Author: Lars Ingebrigtsen Date: Sat Jun 4 13:43:58 2022 +0200 Add a face to \\= doc string escapes * lisp/emacs-lisp/lisp-mode.el (lisp-fdefs): Add a face to \\= doc string escapes (bug#55783). diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 0492f25dc9..c2d0efbf50 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -485,6 +485,9 @@ This will generate compile-time constants from BINDINGS." ;; Words inside ‘’, '' and `' tend to be symbol names. (,(concat "[`‘']\\(" lisp-mode-symbol-regexp "\\)['’]") (1 font-lock-constant-face prepend)) + ;; \\= tends to be an escape in doc strings. + ("\\\\\\\\=" + (0 font-lock-builtin-face prepend)) ;; Constant values. (,(concat "\\_<:" lisp-mode-symbol-regexp "\\_>") (0 font-lock-builtin-face)) commit 01b192534af6a319b8c9b3e8730fd61bd8e74710 Author: Lars Ingebrigtsen Date: Sat Jun 4 13:29:53 2022 +0200 Further notes about quotation marks in the manual * doc/lispref/tips.texi (Documentation Tips): Note that we previously recommended using single quotation marks (bug#55780). diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi index 8232550220..30146a89eb 100644 --- a/doc/lispref/tips.texi +++ b/doc/lispref/tips.texi @@ -707,7 +707,11 @@ 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}. +@xref{Keys in Documentation}. (Some previous versions of this section +recommended using the non-@acronym{ASCII} single quotation marks +directly in doc strings, but this is now discouraged, since that leads +to broken help string displays on terminals that don't support +displaying those characters.) @cindex hyperlinks in documentation strings Help mode automatically creates a hyperlink when a documentation string commit f1b4c0aff507e32d0311e04c927b866dcb457ac3 Author: Po Lu Date: Sat Jun 4 18:07:20 2022 +0800 Allow keyboard modifiers to control the action taken during dired DND * doc/emacs/dired.texi (Misc Dired Features): Update documentation. * lisp/dired.el (dired-mouse-drag-files): Update defcustom for new values. (dired-mouse-drag): Recognize more values of `dired-mouse-drag-files' and keyboard modifiers. (dired-mouse-drag-files-map): Add C-down-mouse-1, M-down-mouse-1 and S-down-mouse-1. diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index ed4ff5213f..9e14e0f9a9 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -1711,6 +1711,9 @@ the originating program. Dragging files out of a Dired buffer is also supported, by enabling the user option @code{dired-mouse-drag-files}, the mouse can be used to drag files onto other programs. When set to @code{link}, it will make the other program (typically a file manager) -create a symbolic link to the file, and setting it to any other -non-@code{nil} value will make the other program open or create a copy -of the file. +create a symbolic link to the file; when set to @code{move}, it will +make the other program move the file to a new location, and setting it +to any other non-@code{nil} value will make the other program open or +create a copy of the file. The keyboard modifiers pressed during the +drag-and-drop operation can also control what action the other program +takes towards the file. diff --git a/lisp/dired.el b/lisp/dired.el index 4d3d93441b..7df50a7b2a 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -259,7 +259,21 @@ 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 -the file instead by the other program (usually a file manager)." +the file instead by the other program (usually a file manager). + +If the value is `move', then the default action will be for the +other program to move the file to a different location. For this +to work optimally, `auto-revert-mode' should be enabled in the +Dired buffer. + +If the Meta key is held down when the mouse button is pressed, +then this will always be equivalent to `link'. + +If the Control key is held down when the mouse button is pressed, +then dragging the file will always copy it to the new location. + +If the Shift key is held down when the mouse button is pressed, +then this will always be equivalent to `move'." :set (lambda (option value) (set-default option value) (dolist (buffer (buffer-list)) @@ -267,7 +281,8 @@ the file instead by the other program (usually a file manager)." (when (derived-mode-p 'dired-mode) (revert-buffer nil t))))) :type '(choice (const :tag "Don't allow dragging" nil) - (const :tag "Copy file to other window" t) + (const :tag "Copy file to new location" t) + (const :tag "Move file to new location" t) (const :tag "Create symbolic link to file" link)) :group 'dired :version "29.1") @@ -1717,61 +1732,73 @@ other marked file as well. Otherwise, unmark all files." (interactive "e") (when mark-active (deactivate-mark)) - (save-excursion - (with-selected-window (posn-window (event-end event)) - (goto-char (posn-point (event-end event)))) - (track-mouse - (let ((beginning-position (mouse-pixel-position)) - new-event) - (catch 'track-again - (setq new-event (read-event)) - (if (not (eq (event-basic-type new-event) 'mouse-movement)) - (when (eq (event-basic-type new-event) 'mouse-1) - (push new-event unread-command-events)) - (let ((current-position (mouse-pixel-position))) - ;; If the mouse didn't move far enough, don't - ;; inadvertently trigger a drag. - (when (and (eq (car current-position) (car beginning-position)) - (ignore-errors - (and (> 3 (abs (- (cadr beginning-position) - (cadr current-position)))) - (> 3 (abs (- (caddr beginning-position) - (caddr current-position))))))) - (throw 'track-again nil))) - ;; We can get an error if there's by some chance no file - ;; name at point. - (condition-case nil - (let ((filename (with-selected-window (posn-window - (event-end event)) - (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 - (if (and (consp filename) - (cdr filename)) - (dnd-begin-drag-files filename nil - (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) - 'link 'copy) - t)))) - (error (when (eq (event-basic-type new-event) 'mouse-1) - (push new-event unread-command-events)))))))))) + (let* ((modifiers (event-modifiers event)) + (action (cond ((memq 'control modifiers) 'copy) + ((memq 'shift modifiers) 'move) + ((memq 'meta modifiers) 'link) + (t (if (memq dired-mouse-drag-files + '(copy move link)) + dired-mouse-drag-files + 'copy))))) + (save-excursion + (with-selected-window (posn-window (event-end event)) + (goto-char (posn-point (event-end event)))) + (track-mouse + (let ((beginning-position (mouse-pixel-position)) + new-event) + (catch 'track-again + (setq new-event (read-event)) + (if (not (eq (event-basic-type new-event) 'mouse-movement)) + (when (eq (event-basic-type new-event) 'mouse-1) + (push new-event unread-command-events)) + (let ((current-position (mouse-pixel-position))) + ;; If the mouse didn't move far enough, don't + ;; inadvertently trigger a drag. + (when (and (eq (car current-position) (car beginning-position)) + (ignore-errors + (and (> 3 (abs (- (cadr beginning-position) + (cadr current-position)))) + (> 3 (abs (- (caddr beginning-position) + (caddr current-position))))))) + (throw 'track-again nil))) + ;; We can get an error if there's by some chance no file + ;; name at point. + (condition-case error + (let ((filename (with-selected-window (posn-window + (event-end event)) + (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 + (if (and (consp filename) + (cdr filename)) + (dnd-begin-drag-files filename nil action t) + (dnd-begin-file-drag (if (stringp filename) + filename + (car filename)) + nil action t)))) + (error (when (eq (event-basic-type new-event) 'mouse-1) + (push new-event unread-command-events)) + ;; Errors from `dnd-begin-drag-file' should be + ;; treated as user errors, since they should + ;; only occur when the user performs an invalid + ;; action, such as trying to create a link to + ;; an invalid file. + (user-error error)))))))))) (defvar dired-mouse-drag-files-map (let ((keymap (make-sparse-keymap))) (define-key keymap [down-mouse-1] #'dired-mouse-drag) + (define-key keymap [C-down-mouse-1] #'dired-mouse-drag) + (define-key keymap [S-down-mouse-1] #'dired-mouse-drag) + (define-key keymap [M-down-mouse-1] #'dired-mouse-drag) keymap) "Keymap applied to file names when `dired-mouse-drag-files' is enabled.") commit acf27496cbf10e3ac2d36f6be1f1413691925eef Author: Michael Albinus Date: Sat Jun 4 11:23:53 2022 +0200 * lisp/emacs-lisp/shortdoc.el (string): Add `string-collate-lessp'. diff --git a/lisp/emacs-lisp/shortdoc.el b/lisp/emacs-lisp/shortdoc.el index 4c8ca967f1..5c94b06e76 100644 --- a/lisp/emacs-lisp/shortdoc.el +++ b/lisp/emacs-lisp/shortdoc.el @@ -264,7 +264,12 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'), (string-greaterp :eval (string-greaterp "foo" "bar")) (string-version-lessp - :eval (string-version-lessp "pic4.png" "pic32.png")) + :eval (string-version-lessp "pic4.png" "pic32.png") + :eval (string-lessp "pic4.png" "pic32.png")) + (string-collate-lessp + :eval (string-collate-lessp "1.1" "1 2") + :eval (string-version-lessp "1.1" "1 2") + :eval (string-lessp "1.1" "1 2")) (string-prefix-p :eval (string-prefix-p "foo" "foobar")) (string-suffix-p commit 65dc15b722441fb43a9a1aadfe4a442e8f1fceda Author: समीर सिंह Sameer Singh Date: Wed Jun 1 22:29:24 2022 +0530 Add support for the Grantha script (bug#55782) * lisp/language/indian.el ("Grantha"): New language environment. Add composition rules for Grantha. Add sample text and input method. * lisp/international/fontset.el (script-representative-chars) (setup-default-fontset): Support Grantha. * lisp/leim/quail/indian.el ("grantha"): New input method. * etc/HELLO: Add two Grantha greetings. * etc/NEWS: Announce the new language environment. diff --git a/etc/HELLO b/etc/HELLO index 4148183949..6694501a7d 100644 --- a/etc/HELLO +++ b/etc/HELLO @@ -56,6 +56,7 @@ Finnish (suomi) Hei / Hyvää päivää French (français) Bonjour / Salut Georgian (ქართული) გამარჯობა German (Deutsch) Guten Tag / Grüß Gott +Grantha (𑌗𑍍𑌰𑌨𑍍𑌥) 𑌨𑌮𑌸𑍍𑌤𑍇 / 𑌨𑌮𑌸𑍍𑌕𑌾𑌰𑌃 Greek (ελληνικά) Γειά σας Greek, ancient (ἑλληνική) Οὖλέ τε καὶ μέγα χαῖρε Gujarati (ગુજરાતી) નમસ્તે diff --git a/etc/NEWS b/etc/NEWS index 777c8eb341..850854edfa 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -852,6 +852,7 @@ corresponding language environments are: **** Makasar script and language environment **** Lontara script and language environment **** Hanifi Rohingya script and language environment +**** Grantha script and language environment --- *** The "Oriya" language environment was renamed to "Odia". diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index 2c54c86ab7..74be7edc64 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -250,7 +250,7 @@ (sharada #x11191 #x111B3 #x111CD) (khojki #x11200) (khudawadi #x112B0) - (grantha #x11305) + (grantha #x11315 #x1133E #x11374) (newa #x11400) (tirhuta #x11481 #x1148F #x114D0) (siddham #x1158E #x115AF #x115D4) @@ -801,6 +801,7 @@ brahmi kaithi sharada + grantha tirhuta siddham modi diff --git a/lisp/language/indian.el b/lisp/language/indian.el index 4dfad75275..9329b43fea 100644 --- a/lisp/language/indian.el +++ b/lisp/language/indian.el @@ -233,6 +233,17 @@ Limbu language and its script are supported in this language environment.")) '("Indian")) +(set-language-info-alist + "Grantha" '((charset unicode) + (coding-system utf-8) + (coding-priority utf-8) + (input-method . "grantha") + (sample-text . "Grantha (𑌗𑍍𑌰𑌨𑍍𑌥) 𑌨𑌮𑌸𑍍𑌤𑍇 / 𑌨𑌮𑌸𑍍𑌕𑌾𑌰𑌃") + (documentation . "\ +Languages such as Sanskrit and Manipravalam, when they use the +Grantha script, are supported in this language environment.")) + '("Indian")) + ;; Replace mnemonic characters in REGEXP according to TABLE. TABLE is ;; an alist of (MNEMONIC-STRING . REPLACEMENT-STRING). @@ -696,5 +707,32 @@ language environment.")) "?" vowel "?" other-signs "?") 1 'font-shape-gstring)))) +;; Grantha composition rules +(let ((consonant "[\x11315-\x11339]") + (nukta "\x1133C") + (independent-vowel "[\x11305-\x11314\x11360\x11361]") + (vowel "[\x1133E-\x1134C\x11357\x11362\x11363]") + (nasal "[\x11300-\x11302]") + (bindu "\x1133B") + (visarga "\x11303") + (virama "\x1134D") + (avagraha "\x1133D") + (modifier-above "[\x11366-\x11374]")) + (set-char-table-range composition-function-table + '(#x1133B . #x1134D) + (list (vector + ;; Consonant based syllables + (concat consonant nukta "?" "\\(?:" virama consonant nukta + "?\\)*\\(?:" virama "\\|" vowel "*" nukta "?" nasal + "?" bindu "?" visarga "?" modifier-above "?" + avagraha "?\\)") + 1 'font-shape-gstring) + (vector + ;; Vowels based syllables + (concat independent-vowel nukta "?" virama "?" vowel "?" + nasal "?" bindu "?" visarga "?" modifier-above + "?" avagraha "?") + 1 'font-shape-gstring)))) + (provide 'indian) ;;; indian.el ends here diff --git a/lisp/leim/quail/indian.el b/lisp/leim/quail/indian.el index 031c30aabb..6a3582e83d 100644 --- a/lisp/leim/quail/indian.el +++ b/lisp/leim/quail/indian.el @@ -1656,4 +1656,119 @@ Full key sequences are listed below:") ("`?" ?᥅) ) +(quail-define-package + "grantha" "Grantha" "𑌗𑍍𑌰" t "Grantha phonetic input method. + + `\\=`' is used to switch levels instead of Alt-Gr." + nil t t t t nil nil nil nil nil t) + +(quail-define-rules + ("``" ?₹) + ("1" ?௧) + ("`1" ?1) + ("`!" ?𑍧) + ("2" ?௨) + ("`2" ?2) + ("`@" ?𑍨) + ("3" ?௩) + ("`3" ?3) + ("`#" ?𑍩) + ("4" ?௪) + ("`4" ?4) + ("`$" ?𑍪) + ("5" ?௫) + ("`5" ?5) + ("`%" ?𑍫) + ("6" ?௬) + ("`6" ?6) + ("`^" ?𑍬) + ("7" ?௭) + ("`7" ?7) + ("8" ?௮) + ("`8" ?8) + ("9" ?௯) + ("`9" ?9) + ("0" ?௦) + ("`0" ?0) + ("q" ?𑌟) + ("Q" ?𑌠) + ("`q" ?𑍐) + ("`Q" ?𑍝) + ("w" ?𑌡) + ("W" ?𑌢) + ("`w" ?𑍞) + ("`W" ?𑍟) + ("e" ?𑍇) + ("E" ?𑍈) + ("`e" ?𑌏) + ("`E" ?𑌐) + ("r" ?𑌰) + ("R" ?𑍃) + ("`r" ?𑌋) + ("t" ?𑌤) + ("T" ?𑌥) + ("`t" ?𑍗) + ("y" ?𑌯) + ("u" ?𑍁) + ("U" ?𑍂) + ("`u" ?𑌉) + ("`U" ?𑌊) + ("i" ?𑌿) + ("I" ?𑍀) + ("`i" ?𑌇) + ("`I" ?𑌈) + ("o" ?𑍋) + ("O" ?𑍌) + ("`o" ?𑌓) + ("`O" ?𑌔) + ("p" ?𑌪) + ("P" ?𑌫) + ("`p" ?𑍴) + ("a" ?𑌾) + ("A" ?𑌆) + ("`a" ?𑌅) + ("`A" ?𑍰) + ("s" ?𑌸) + ("S" ?𑌶) + ("d" ?𑌦) + ("D" ?𑌧) + ("f" ?𑍍) + ("F" ?𑍄) + ("`f" ?𑍠) + ("g" ?𑌗) + ("G" ?𑌘) + ("h" ?𑌹) + ("H" ?𑌃) + ("j" ?𑌜) + ("J" ?𑌝) + ("k" ?𑌕) + ("K" ?𑌖) + ("`k" ?𑍱) + ("l" ?𑌲) + ("L" ?𑌳) + ("`l" ?𑍢) + ("`L" ?𑌌) + ("z" ?𑌞) + ("Z" ?𑌙) + ("`z" ?𑍣) + ("`Z" ?𑍡) + ("x" ?𑌷) + ("X" ?𑌼) + ("`x" ?𑌻) + ("c" ?𑌚) + ("C" ?𑌛) + ("`c" #x200C) ; ZWNJ + ("v" ?𑌵) + ("V" ?𑌽) + ("`v" ?𑍳) + ("b" ?𑌬) + ("B" ?𑌭) + ("n" ?𑌨) + ("N" ?𑌣) + ("`n" ?𑍲) + ("m" ?𑌮) + ("M" ?𑌂) + ("`m" ?𑌁) + ("`M" ?𑌀)) + ;;; indian.el ends here commit effbd2aeef3d6ec3d09d40ff095e072b2d9834d4 Author: Po Lu Date: Sat Jun 4 16:19:01 2022 +0800 Fix file drag-and-drop on GNUstep * src/nsselect.m (ns_decode_data_to_pasteboard): Convert URL to path names when we're using NSFilenamesPboardType. * src/nsterm.m: ([EmacsView performDragOperation:]): Handle cases where plist is a string. diff --git a/src/nsselect.m b/src/nsselect.m index a719eef4e8..6831090aa2 100644 --- a/src/nsselect.m +++ b/src/nsselect.m @@ -565,6 +565,9 @@ Updated by Christian Limpach (chris@nice.ch) NSMutableArray *temp; Lisp_Object tem; specpdl_ref count; +#if !NS_USE_NSPasteboardTypeFileURL + NSURL *url; +#endif types = [pasteboard types]; count = SPECPDL_INDEX (); @@ -602,7 +605,12 @@ Updated by Christian Limpach (chris@nice.ch) [pasteboard setString: [NSString stringWithLispString: data] forType: NSPasteboardTypeFileURL]; #else - [pasteboard setString: [NSString stringWithLispString: data] + url = [NSURL URLWithString: [NSString stringWithLispString: data]]; + + if (!url) + signal_error ("Invalid file URL", data); + + [pasteboard setString: [url path] forType: NSFilenamesPboardType]; #endif } diff --git a/src/nsterm.m b/src/nsterm.m index 04475bbba0..4663ac85d8 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -8724,7 +8724,7 @@ - (BOOL) performDragOperation: (id ) sender Lisp_Object type_sym; struct input_event ie; - NSTRACE ("[EmacsView performDragOperation:]"); + NSTRACE (@"[EmacsView performDragOperation:]"); source = [sender draggingSource]; @@ -8752,7 +8752,7 @@ - (BOOL) performDragOperation: (id ) sender if (!type) return NO; -#if NS_USE_NSPasteboardTypeFileURL != 0 +#if NS_USE_NSPasteboardTypeFileURL else if ([type isEqualToString: NSPasteboardTypeFileURL]) { type_sym = Qfile; @@ -8767,18 +8767,29 @@ - (BOOL) performDragOperation: (id ) sender #else // !NS_USE_NSPasteboardTypeFileURL else if ([type isEqualToString: NSFilenamesPboardType]) { - NSArray *files; + id files; NSEnumerator *fenum; NSString *file; - if (!(files = [pb propertyListForType: type])) + files = [pb propertyListForType: type]; + + if (!files) return NO; type_sym = Qfile; - fenum = [files objectEnumerator]; - while ( (file = [fenum nextObject]) ) - strings = Fcons ([file lispString], strings); + /* On GNUstep, files might be a string. */ + + if ([files respondsToSelector: @selector (objectEnumerator:)]) + { + fenum = [files objectEnumerator]; + + while ((file = [fenum nextObject])) + strings = Fcons ([file lispString], strings); + } + else + /* Then `files' is an NSString. */ + strings = list1 ([files lispString]); } #endif // !NS_USE_NSPasteboardTypeFileURL else if ([type isEqualToString: NSPasteboardTypeURL]) @@ -8795,11 +8806,12 @@ - (BOOL) performDragOperation: (id ) sender { NSString *data; - if (! (data = [pb stringForType: type])) + data = [pb stringForType: type]; + + if (!data) return NO; type_sym = Qnil; - strings = list1 ([data lispString]); } else @@ -8807,7 +8819,8 @@ - (BOOL) performDragOperation: (id ) sender EVENT_INIT (ie); ie.kind = DRAG_N_DROP_EVENT; - ie.arg = Fcons (type_sym, Fcons (operations, strings)); + ie.arg = Fcons (type_sym, Fcons (operations, + strings)); XSETINT (ie.x, x); XSETINT (ie.y, y); XSETFRAME (ie.frame_or_window, emacsframe); commit 2ce686c049a7a35cdc3eb87626d8a94539388a35 Author: Po Lu Date: Sat Jun 4 15:45:41 2022 +0800 Support dragging multiple files on NS This has to use a deprecated pasteboard type, since Emacs uses the "old" (but not deprecated) dragImage: method for drag-and-drop, which can't drop file URLs. * lisp/term/ns-win.el (x-begin-drag): Update accordingly. * src/nsselect.m (ns_decode_data_to_pasteboard): (Fns_begin_drag): Allow files to be a list of filenames as well. diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index a36d5d11e7..2e021b9b29 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -905,11 +905,21 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (push (cons 'string ns-dnd-selection-value) pasteboard)) (when (and (member "FILE_NAME" targets) (file-exists-p ns-dnd-selection-value)) - (push (cons 'file - (url-encode-url (concat "file://" - (expand-file-name - ns-dnd-selection-value)))) - pasteboard)) + (let ((value (if (stringp ns-dnd-selection-value) + (or (get-text-property 0 'FILE_NAME + ns-dnd-selection-value) + ns-dnd-selection-value) + ns-dnd-selection-value))) + (if (vectorp value) + (push (cons 'file + (cl-loop for file across value + collect (expand-file-name file))) + pasteboard) + (push (cons 'file + (url-encode-url (concat "file://" + (expand-file-name + ns-dnd-selection-value)))) + pasteboard)))) (ns-begin-drag frame pasteboard action return-frame allow-current-frame))) (defun ns-handle-drag-motion (frame x y) diff --git a/src/nsselect.m b/src/nsselect.m index a4129b12f0..a719eef4e8 100644 --- a/src/nsselect.m +++ b/src/nsselect.m @@ -562,8 +562,12 @@ Updated by Christian Limpach (chris@nice.ch) NSPasteboard *pasteboard) { NSArray *types, *new; + NSMutableArray *temp; + Lisp_Object tem; + specpdl_ref count; types = [pasteboard types]; + count = SPECPDL_INDEX (); CHECK_SYMBOL (type); @@ -580,10 +584,11 @@ Updated by Christian Limpach (chris@nice.ch) } else if (EQ (type, Qfile)) { - CHECK_STRING (data); - #if NS_USE_NSPasteboardTypeFileURL - new = [types arrayByAddingObject: NSPasteboardTypeFileURL]; + if (CONSP (data)) + new = [types arrayByAddingObject: NSPasteboardTypeURL]; + else + new = [types arrayByAddingObject: NSPasteboardTypeFileURL]; #else new = [types arrayByAddingObject: NSFilenamesPboardType]; #endif @@ -591,13 +596,41 @@ Updated by Christian Limpach (chris@nice.ch) [pasteboard declareTypes: new owner: nil]; + if (STRINGP (data)) + { #if NS_USE_NSPasteboardTypeFileURL - [pasteboard setString: [NSString stringWithLispString: data] - forType: NSPasteboardTypeFileURL]; + [pasteboard setString: [NSString stringWithLispString: data] + forType: NSPasteboardTypeFileURL]; #else - [pasteboard setString: [NSString stringWithLispString: data] - forType: NSFilenamesPboardType]; + [pasteboard setString: [NSString stringWithLispString: data] + forType: NSFilenamesPboardType]; +#endif + } + else + { + CHECK_LIST (data); + temp = [[NSMutableArray alloc] init]; + record_unwind_protect_ptr (ns_release_object, temp); + + for (tem = data; CONSP (tem); tem = XCDR (tem)) + { + CHECK_STRING (XCAR (tem)); + + [temp addObject: [NSString stringWithLispString: XCAR (tem)]]; + } + CHECK_LIST_END (tem, data); +#if NS_USE_NSPasteboardTypeFileURL + [pasteboard setPropertyList: temp + /* We have to use this deprecated pasteboard + type, since Apple doesn't let us use + dragImage:at: to drag multiple file URLs. */ + forType: @"NSFilenamesPboardType"]; +#else + [pasteboard setPropertyList: temp + forType: NSFilenamesPboardType]; #endif + unbind_to (count, Qnil); + } } else signal_error ("Unknown pasteboard type", type); @@ -673,7 +706,8 @@ Updated by Christian Limpach (chris@nice.ch) be dragged to another program. - `file' means DATA should be a file URL that will be dragged to - another program. + another program. DATA may also be a list of file names; that + means each file in the list will be dragged to another program. ACTION is the action that will be taken by the drop target towards the data inside PBOARD. commit 1289d0c3dd964a501ea0b039c0ce9bc39ec47caa Author: Po Lu Date: Sat Jun 4 15:41:39 2022 +0800 Fix splurious drag-mouse-1 events after NS drag-and-drop * src/nsterm.m ([EmacsWindow beginDrag:...]): Clear dpyinfo->grabbed. diff --git a/src/nsterm.m b/src/nsterm.m index ecaca5b87f..04475bbba0 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -9662,7 +9662,6 @@ - (NSDragOperation) beginDrag: (NSDragOperation) op NSInteger window_number; NSWindow *w; #endif - drag_op = op; selected_op = NSDragOperationNone; image = [[NSImage alloc] initWithSize: NSMakeSize (1.0, 1.0)]; @@ -9716,6 +9715,11 @@ - (NSDragOperation) beginDrag: (NSDragOperation) op #endif unblock_input (); + /* Assume all buttons have been released since the drag-and-drop + operation is now over. */ + if (!dnd_return_frame) + x_display_list->grabbed = 0; + [image release]; *frame_return = dnd_return_frame; commit 937a011352e4bc24c40a1eab1c4b4d7f8aba7c7b Author: Po Lu Date: Sat Jun 4 15:17:50 2022 +0800 Clear mouse face during drag-and-drop * src/xterm.c (handle_one_xevent): Clear mouse face during drag and drop, since note_mouse_highlight isn't called. diff --git a/src/xterm.c b/src/xterm.c index fe7cab7258..edfb89070f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -17022,6 +17022,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, xm_top_level_enter_message emsg; xm_drag_motion_message dmsg; + /* Always clear mouse face. */ + clear_mouse_face (hlinfo); + hlinfo->mouse_face_hidden = true; + /* Sometimes the drag-and-drop operation starts with the pointer of a frame invisible due to input. Since motion events are ignored during that, make the pointer @@ -18657,6 +18661,10 @@ handle_one_xevent (struct x_display_info *dpyinfo, Window target, toplevel; int target_proto, motif_style; + /* Always clear mouse face. */ + clear_mouse_face (hlinfo); + hlinfo->mouse_face_hidden = true; + /* Sometimes the drag-and-drop operation starts with the pointer of a frame invisible due to input. Since motion events are ignored during that, make the pointer commit 92c5faafd7aac9b2382939fefd2cdf54f386a8e3 Author: Eli Zaretskii Date: Sat Jun 4 10:06:43 2022 +0300 Clarify documentation of 'string-to-unibyte' * doc/lispref/nonascii.texi (Converting Representations): Clarify what 'string-to-unibyte' does. Reported by Richard Hansen . (Bug#55777) diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi index d7d25dc36a..6dc23637a7 100644 --- a/doc/lispref/nonascii.texi +++ b/doc/lispref/nonascii.texi @@ -280,11 +280,12 @@ to the codepoints @code{#x3FFF80} through @code{#x3FFFFF}, inclusive @defun string-to-unibyte string This function returns a unibyte string containing the same sequence of -characters as @var{string}. It signals an error if @var{string} -contains a non-@acronym{ASCII} character. If @var{string} is a -unibyte string, it is returned unchanged. Use this function for -@var{string} arguments that contain only @acronym{ASCII} and eight-bit -characters. +characters as @var{string}. If @var{string} is a unibyte string, it +is returned unchanged. Otherwise, @acronym{ASCII} characters and +characters in the @code{eight-bit} charset are converted to their +corresponding byte values. Use this function for @var{string} +arguments that contain only @acronym{ASCII} and eight-bit characters; +the function signals an error if any other characters are encountered. @end defun @defun byte-to-string byte commit 284851265423e875d6de963922f3deb536aa2882 Author: Eli Zaretskii Date: Thu Jun 2 16:04:38 2022 +0300 ; * lisp/files.el (find-file): Avoid too short lines in doc string. diff --git a/lisp/files.el b/lisp/files.el index 5e9dce555f..292c05b58e 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -1706,19 +1706,18 @@ rather than FUN itself, to `minibuffer-setup-hook'." (defun find-file (filename &optional wildcards) "Edit file FILENAME. -\\Switch to a buffer visiting file FILENAME, -creating one if none already exists. +\\Switch to a buffer visiting file FILENAME, creating one if none +already exists. Interactively, the default if you just type RET is the current directory, but the visited file name is available through the minibuffer history: type \\[next-history-element] to pull it into the minibuffer. -The first time \\[next-history-element] is used after Emacs prompts for -the file name, the result is affected by `file-name-at-point-functions', -which by default try to guess the file name by looking at point in the -current buffer. Customize the value of `file-name-at-point-functions' -or set it to nil, if you want only the visited file name and the -current directory to be available on first \\[next-history-element] -request. +The first time \\[next-history-element] is used after Emacs prompts for the file name, +the result is affected by `file-name-at-point-functions', which by +default try to guess the file name by looking at point in the current +buffer. Customize the value of `file-name-at-point-functions' or set +it to nil, if you want only the visited file name and the current +directory to be available on first \\[next-history-element] request. You can visit files on remote machines by specifying something like /ssh:SOME_REMOTE_MACHINE:FILE for the file name. You can commit 672f9f787fb34919b35d6fdb30f56083b8b7fb79 Author: Ikumi Keita Date: Thu Jun 2 14:29:38 2022 +0200 Improve keystrokes in doc strings in some find-file functions * lisp/files.el (find-file): (find-file-other-window): (find-file-other-frame): Include the correct keymap so that keystrokes are displayed better (bug#55761). Copyright-paperwork-exempt: yes diff --git a/lisp/files.el b/lisp/files.el index b187c0b3a0..5e9dce555f 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -1706,7 +1706,7 @@ rather than FUN itself, to `minibuffer-setup-hook'." (defun find-file (filename &optional wildcards) "Edit file FILENAME. -Switch to a buffer visiting file FILENAME, +\\Switch to a buffer visiting file FILENAME, creating one if none already exists. Interactively, the default if you just type RET is the current directory, but the visited file name is available through the minibuffer history: @@ -1731,7 +1731,7 @@ Interactively, or if WILDCARDS is non-nil in a call from Lisp, expand wildcards (if any) and visit multiple files. You can suppress wildcard expansion by setting `find-file-wildcards' to nil. -To visit a file without any kind of conversion and without +\\To visit a file without any kind of conversion and without automatically choosing a major mode, use \\[find-file-literally]." (interactive (find-file-read-args "Find file: " @@ -1747,6 +1747,7 @@ automatically choosing a major mode, use \\[find-file-literally]." Like \\[find-file] (which see), but creates a new window or reuses an existing one. See the function `display-buffer'. +\\\ Interactively, the default if you just type RET is the current directory, but the visited file name is available through the minibuffer history: type \\[next-history-element] to pull it into the minibuffer. @@ -1779,6 +1780,7 @@ expand wildcards (if any) and visit multiple files." Like \\[find-file] (which see), but creates a new frame or reuses an existing one. See the function `display-buffer'. +\\\ Interactively, the default if you just type RET is the current directory, but the visited file name is available through the minibuffer history: type \\[next-history-element] to pull it into the minibuffer. commit ef5651cc77b9a57bd6af5f9914c26528355c80be Author: Eli Zaretskii Date: Thu Jun 2 13:41:59 2022 +0300 Fix segfaults when starting on 80x26 TTY frames * src/dispnew.c (adjust_frame_glyphs_for_frame_redisplay): Make sure we have valid frame glyph matrices for the interactive session. (Bug#55760) (adjust_frame_glyphs): Add assertions for when we fail to allocate valid frame glyph matrices for a TTY frame. diff --git a/src/dispnew.c b/src/dispnew.c index 332ba54ee7..39e5469db0 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -1837,7 +1837,18 @@ adjust_frame_glyphs (struct frame *f) if (FRAME_WINDOW_P (f)) adjust_frame_glyphs_for_window_redisplay (f); else - adjust_frame_glyphs_for_frame_redisplay (f); + { + adjust_frame_glyphs_for_frame_redisplay (f); + eassert (FRAME_INITIAL_P (f) + || noninteractive + || !initialized + || (f->current_matrix + && f->current_matrix->nrows > 0 + && f->current_matrix->rows + && f->desired_matrix + && f->desired_matrix->nrows > 0 + && f->desired_matrix->rows)); + } /* Don't forget the buffer for decode_mode_spec. */ adjust_decode_mode_spec_buffer (f); @@ -2119,6 +2130,19 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f) SET_FRAME_GARBAGED (f); } } + else if (!FRAME_INITIAL_P (f) && !noninteractive && initialized) + { + if (!f->desired_matrix->nrows || !f->desired_matrix->rows) + { + adjust_glyph_matrix (NULL, f->desired_matrix, 0, 0, matrix_dim); + SET_FRAME_GARBAGED (f); + } + if (!f->current_matrix->nrows || !f->current_matrix->rows) + { + adjust_glyph_matrix (NULL, f->current_matrix, 0, 0, matrix_dim); + SET_FRAME_GARBAGED (f); + } + } } commit bfa647972f39e709c7a51981be3761224f0c1d48 Author: Eli Zaretskii Date: Wed Jun 1 22:30:59 2022 +0300 ; Fix doc string of 'delete-selection-repeat-replace-region' * lisp/delsel.el (delete-selection-repeat-replace-region): Doc fix. (Bug#55755) diff --git a/lisp/delsel.el b/lisp/delsel.el index f5fe7cf793..554b1e7249 100644 --- a/lisp/delsel.el +++ b/lisp/delsel.el @@ -108,7 +108,8 @@ the active region is killed instead of deleted." "Repeat replacing text of highlighted region with typed text. Search for the next stretch of text identical to the region last replaced by typing text over it and replaces it with the same stretch of text. -With ARG, repeat that many times. `\\[universal-argument]' means until end of buffer." +With ARG (interactively, prefix numeric argument), repeat that many times. +Just `\\[universal-argument]' means repeat until the end of the buffer's accessible portion." (interactive "P") (let ((old-text (and delete-selection-save-to-register (get-register delete-selection-save-to-register))) commit a95d46e00febf3ef4a7fd016e06d5c426e81f1e2 Author: Lars Ingebrigtsen Date: Wed Jun 1 17:56:45 2022 +0200 Make it explicit that a couple of _s in lispref are underscores * doc/lispref/strings.texi (Custom Format Strings): * doc/lispref/control.texi (pcase Macro): Make it explicit that it's an underscore (bug#55742). diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index ecf616fc2b..34653d7056 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -525,7 +525,7 @@ core pattern can have the following forms: @table @code -@item _ +@item _@r{ (underscore)} Matches any @var{expval}. This is also known as @dfn{don't care} or @dfn{wildcard}. diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 3d8db985e9..742ab76244 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -1345,7 +1345,7 @@ given width, if specified. This flag converts the substituted text to upper case (@pxref{Case Conversion}). -@item _ +@item _@r{ (underscore)} This flag converts the substituted text to lower case (@pxref{Case Conversion}). @end table commit 5c74c2512378e1903ddc569987e2462108cc0acf Author: Eli Zaretskii Date: Tue May 31 20:20:07 2022 +0300 Remove from FAQ the MS-Windows info about BDF fonts * doc/misc/efaq.texi (How to add fonts): Remove the MS-Windows specific steps, as BDF fonts are no longer supported on MS-Windows. (Bug#55740) diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi index c1fd002bcb..373efe9ad5 100644 --- a/doc/misc/efaq.texi +++ b/doc/misc/efaq.texi @@ -4337,75 +4337,6 @@ add the following line to your @file{~/.emacs}: (setq ps-multibyte-buffer 'bdf-font-except-latin) @end lisp -A few additional steps are necessary for MS-Windows; they are listed -below. - -First, make sure @emph{all} the directories with BDF font files are -mentioned in @code{bdf-directory-list}. On Unix and GNU/Linux -systems, one normally runs @kbd{make install} to install the BDF fonts -in the same directory. By contrast, Windows users typically don't run -the Intlfonts installation command, but unpack the distribution in -some directory, which leaves the BDF fonts in its subdirectories. For -example, assume that you unpacked Intlfonts in @file{C:/Intlfonts}; -then you should set @code{bdf-directory-list} as follows: - -@lisp - (setq bdf-directory-list - '("C:/Intlfonts/Asian" - "C:/Intlfonts/Chinese" "C:/Intlfonts/Chinese.X" - "C:/Intlfonts/Chinese.BIG" "C:/Intlfonts/Ethiopic" - "C:/Intlfonts/European" "C:/Intlfonts/European.BIG" - "C:/Intlfonts/Japanese" "C:/Intlfonts/Japanese.X" - "C:/Intlfonts/Japanese.BIG" "C:/Intlfonts/Korean.X" - "C:/Intlfonts/Misc")) -@end lisp - -@cindex @code{w32-bdf-filename-alist} -@cindex @code{w32-find-bdf-fonts} -Next, you need to set up the variable @code{w32-bdf-filename-alist} to -an alist of the BDF fonts and their corresponding file names. -Assuming you have set @code{bdf-directory-list} to name all the -directories with the BDF font files, the following Lisp snippet will -set up @code{w32-bdf-filename-alist}: - -@lisp - (setq w32-bdf-filename-alist - (w32-find-bdf-fonts bdf-directory-list)) -@end lisp - -Now, create fontsets for the BDF fonts: - -@smallexample - (create-fontset-from-fontset-spec - "-*-fixed-medium-r-normal-*-16-*-*-*-c-*-fontset-bdf, - japanese-jisx0208:-*-*-medium-r-normal-*-16-*-*-*-c-*-jisx0208.1983-*, - katakana-jisx0201:-*-*-medium-r-normal-*-16-*-*-*-c-*-jisx0201*-*, - latin-jisx0201:-*-*-medium-r-normal-*-16-*-*-*-c-*-jisx0201*-*, - japanese-jisx0208-1978:-*-*-medium-r-normal-*-16-*-*-*-c-*-jisx0208.1978-*, - thai-tis620:-misc-fixed-medium-r-normal--16-160-72-72-m-80-tis620.2529-1, - lao:-misc-fixed-medium-r-normal--16-160-72-72-m-80-MuleLao-1, - tibetan-1-column:-TibMdXA-fixed-medium-r-normal--16-160-72-72-m-80-MuleTibetan-1, - ethiopic:-Admas-Ethiomx16f-Medium-R-Normal--16-150-100-100-M-160-Ethiopic-Unicode, - tibetan:-TibMdXA-fixed-medium-r-normal--16-160-72-72-m-160-MuleTibetan-0") -@end smallexample - -Many of the international bdf fonts from Intlfonts are type 0, and -therefore need to be added to font-encoding-alist: - -@lisp - (setq font-encoding-alist - (append '(("MuleTibetan-0" (tibetan . 0)) - ("GB2312" (chinese-gb2312 . 0)) - ("JISX0208" (japanese-jisx0208 . 0)) - ("JISX0212" (japanese-jisx0212 . 0)) - ("VISCII" (vietnamese-viscii-lower . 0)) - ("KSC5601" (korean-ksc5601 . 0)) - ("MuleArabic-0" (arabic-digit . 0)) - ("MuleArabic-1" (arabic-1-column . 0)) - ("MuleArabic-2" (arabic-2-column . 0))) - font-encoding-alist)) -@end lisp - You can now use the Emacs font menu to select the @samp{bdf: 16-dot medium} fontset, or you can select it by setting the default font in your @file{~/.emacs}: @@ -4414,7 +4345,6 @@ fontset, or you can select it by setting the default font in your (set-frame-font "fontset-bdf") @end lisp - @c ------------------------------------------------------------ @node Mail and news @chapter Mail and news commit edb48646f273735534796c09d1943a2fc61750e5 Author: Ikumi Keita Date: Tue May 31 13:19:48 2022 +0200 Fix Display Property manual example * doc/lispref/display.texi (Display Property): Fix syntax of example (bug#55736). Copyright-paperwork-exempt: yes diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 61aca5b88a..1147ba112a 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -4869,7 +4869,7 @@ which are evaluated at display time. This could be unsafe in certain situations, e.g., when the display specification was generated by some external program/agent. Wrapping a display specification in a list that begins with the special symbol @code{disable-eval}, as in -@w{@code{('disable-eval @var{spec})}}, will disable evaluation of any +@w{@code{(disable-eval @var{spec})}}, will disable evaluation of any Lisp in @var{spec}, while still supporting all the other display property features.