commit 37ad776b9e6c90b2c289dd2413868066608594a7 (HEAD, refs/remotes/origin/master) Author: Po Lu Date: Thu Dec 30 15:04:18 2021 +0800 Make xwidget motion commands hscroll the window of wide widgets * lisp/xwidget.el (xwidget-info): New function declaration. (xwidget-webkit-scroll-forward): (xwidget-webkit-scroll-backward): Hscroll the window if the widget is wider than the text area. (bug#52885) * src/xwidget.c (xwidget_scroll, xwidget_motion_notify): Apply clip offsets to coordinates. diff --git a/lisp/xwidget.el b/lisp/xwidget.el index ce9839ebd3..12ee597504 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -60,6 +60,7 @@ (declare-function xwidget-webkit-set-cookie-storage-file "xwidget.c" (xwidget file)) (declare-function xwidget-live-p "xwidget.c" (xwidget)) (declare-function xwidget-webkit-stop-loading "xwidget.c" (xwidget)) +(declare-function xwidget-info "xwidget.c" (xwidget)) (defgroup xwidget nil "Displaying native widgets in Emacs buffers." @@ -347,23 +348,36 @@ If N is omitted or nil, scroll down by one line." (defun xwidget-webkit-scroll-forward (&optional n) "Scroll webkit horizontally by N chars. -The width of char is calculated with `window-font-width'. -If N is omitted or nil, scroll forwards by one char." +If the widget is larger than the window, hscroll by N columns +instead. The width of char is calculated with +`window-font-width'. If N is omitted or nil, scroll forwards by +one char." (interactive "p" xwidget-webkit-mode) - (xwidget-webkit-execute-script - (xwidget-webkit-current-session) - (format "window.scrollBy(%d, 0);" - (* n (window-font-width))))) + (let ((session (xwidget-webkit-current-session))) + (if (> (- (aref (xwidget-info session) 2) + (window-text-width nil t)) + (window-font-width)) + (set-window-hscroll nil (+ (window-hscroll) n)) + (xwidget-webkit-execute-script session + (format "window.scrollBy(%d, 0);" + (* n (window-font-width))))))) (defun xwidget-webkit-scroll-backward (&optional n) "Scroll webkit back by N chars. -The width of char is calculated with `window-font-width'. -If N is omitted or nil, scroll backwards by one char." +If the widget is larger than the window, hscroll backwards by N +columns instead. The width of char is calculated with +`window-font-width'. If N is omitted or nil, scroll backwards by +one char." (interactive "p" xwidget-webkit-mode) - (xwidget-webkit-execute-script - (xwidget-webkit-current-session) - (format "window.scrollBy(-%d, 0);" - (* n (window-font-width))))) + (let ((session (xwidget-webkit-current-session))) + (if (and (> (- (aref (xwidget-info session) 2) + (window-text-width nil t)) + (window-font-width)) + (> (window-hscroll) 0)) + (set-window-hscroll nil (- (window-hscroll) n)) + (xwidget-webkit-execute-script session + (format "window.scrollBy(%-d, 0);" + (* n (window-font-width))))))) (defun xwidget-webkit-scroll-top () "Scroll webkit to the very top." diff --git a/src/xwidget.c b/src/xwidget.c index 5aeb2beae2..49e15a0955 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1156,7 +1156,8 @@ xwidget_motion_notify (struct xwidget_view *view, record_osr_embedder (view); target = find_widget_at_pos (model->widgetwindow_osr, - lrint (x), lrint (y), + lrint (x + view->clip_left), + lrint (y + view->clip_top), &target_x, &target_y); if (!target) @@ -1198,7 +1199,8 @@ xwidget_scroll (struct xwidget_view *view, double x, double y, record_osr_embedder (view); target = find_widget_at_pos (model->widgetwindow_osr, - lrint (x), lrint (y), + lrint (x + view->clip_left), + lrint (y + view->clip_top), &target_x, &target_y); if (!target) commit a3129af331b8893cec3036f8baec26d49e339b5f Merge: a4893515c2 06545bc0cc Author: Stefan Kangas Date: Thu Dec 30 06:30:43 2021 +0100 Merge from origin/emacs-28 06545bc0cc CC Mode: c-update-brace-stack: After struct foo *, do not ... f11779f01b Improve documentation of 'M-X' and related features # Conflicts: # etc/NEWS commit a4893515c249386bca39f1b9a90adc6fc68b48d5 Author: Po Lu Date: Thu Dec 30 11:18:42 2021 +0800 Work around xwidgets releasing the passive grab on an entry event * src/xterm.c (handle_one_xevent): Don't send XI_Enter events to xwidgets if button 1 is pressed. diff --git a/src/xterm.c b/src/xterm.c index 61dff7aaab..afac07e7ff 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10011,8 +10011,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, #ifdef HAVE_XWIDGETS if (xwidget_view) { - *finish = X_EVENT_DROP; - xwidget_motion_or_crossing (xwidget_view, event); + /* Don't send an enter event to the xwidget if the + first button is pressed, to avoid it releasing + the passive grab. I don't know why that happens, + but this workaround makes dragging to select text + work again. */ + if (!(enter->buttons.mask_len + && XIMaskIsSet (enter->buttons.mask, 1))) + xwidget_motion_or_crossing (xwidget_view, event); goto XI_OTHER; } commit b88024ad1aa0c2e75b407634038050a653fdb64b Author: Po Lu Date: Thu Dec 30 10:04:29 2021 +0800 Use XRandR 1.5 to generate monitor attributes if available * src/xfns.c (x_get_monitor_attributes_xrandr): Use XRR 1.5 if present. (xlw_monitor_dimensions_at_pos_1): Remove redundant XRR 1.5 code. (xlw_monitor_dimensions_at_pos): Rely on `x_get_monitor_attributes_xrandr' to retrieve the workarea instead. diff --git a/src/xfns.c b/src/xfns.c index 7c4e694320..bfa88b1c8c 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4933,6 +4933,70 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo) int i, n_monitors, primary = -1; RROutput pxid = None; struct MonitorInfo *monitors; + bool randr15_p = false; + +#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5) + XRRMonitorInfo *rr_monitors; + + /* If RandR 1.5 or later is available, use that instead, as some + video drivers don't report correct dimensions via other versions + of RandR. */ + if (dpyinfo->xrandr_major_version > 1 + || (dpyinfo->xrandr_major_version == 1 + && dpyinfo->xrandr_minor_version >= 5)) + { + XRectangle workarea; + char *name; + + rr_monitors = XRRGetMonitors (dpyinfo->display, + dpyinfo->root_window, + True, &n_monitors); + if (!rr_monitors) + goto fallback; + + monitors = xzalloc (n_monitors * sizeof *monitors); + + for (int i = 0; i < n_monitors; ++i) + { + monitors[i].geom.x = rr_monitors[i].x; + monitors[i].geom.y = rr_monitors[i].y; + monitors[i].geom.width = rr_monitors[i].width; + monitors[i].geom.height = rr_monitors[i].height; + monitors[i].mm_width = rr_monitors[i].mwidth; + monitors[i].mm_height = rr_monitors[i].mheight; + + name = XGetAtomName (dpyinfo->display, rr_monitors[i].name); + if (name) + { + monitors[i].name = xstrdup (name); + XFree (name); + } + else + monitors[i].name = xstrdup ("Unknown Monitor"); + + if (rr_monitors[i].primary) + primary = i; + + if (rr_monitors[i].primary + && x_get_net_workarea (dpyinfo, &workarea)) + { + monitors[i].work = workarea; + if (!gui_intersect_rectangles (&monitors[i].geom, + &monitors[i].work, + &monitors[i].work)) + monitors[i].work = monitors[i].geom; + } + else + monitors[i].work = monitors[i].geom; + } + + XRRFreeMonitors (rr_monitors); + randr15_p = true; + goto out; + } + + fallback:; +#endif #define RANDR13_LIBRARY \ (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3)) @@ -5021,12 +5085,16 @@ x_get_monitor_attributes_xrandr (struct x_display_info *dpyinfo) XRRFreeOutputInfo (info); } XRRFreeScreenResources (resources); - +#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5) + out: +#endif attributes_list = x_make_monitor_attribute_list (monitors, n_monitors, primary, dpyinfo, - "XRandr"); + (randr15_p + ? "XRandR 1.5" + : "XRandr")); free_monitors (monitors, n_monitors); return attributes_list; } @@ -5077,55 +5145,13 @@ xlw_monitor_dimensions_at_pos_1 (struct x_display_info *dpyinfo, int *x, int *y, int *width, int *height) { Lisp_Object attrs, tem, val; -#ifdef HAVE_XRANDR -#if RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 5) - int num_rr_monitors; - XRRMonitorInfo *rr_monitors; - - /* If RandR 1.5 or later is available, use that instead, as some - video drivers don't report correct dimensions via other versions - of RandR. */ - if (dpyinfo->xrandr_major_version > 1 - || (dpyinfo->xrandr_major_version == 1 - && dpyinfo->xrandr_minor_version >= 5)) - { - rr_monitors = XRRGetMonitors (dpyinfo->display, - RootWindowOfScreen (screen), - True, &num_rr_monitors); - if (!rr_monitors) - goto fallback; - - for (int i = 0; i < num_rr_monitors; ++i) - { - if (rr_monitors[i].x <= src_x - && src_x < (rr_monitors[i].x - + rr_monitors[i].width) - && rr_monitors[i].y <= src_y - && src_y < (rr_monitors[i].y - + rr_monitors[i].height)) - { - *x = rr_monitors[i].x; - *y = rr_monitors[i].y; - *width = rr_monitors[i].width; - *height = rr_monitors[i].height; - - XRRFreeMonitors (rr_monitors); - return; - } - } - XRRFreeMonitors (rr_monitors); - } - - fallback: -#endif -#endif attrs = x_get_monitor_attributes (dpyinfo); for (tem = attrs; CONSP (tem); tem = XCDR (tem)) { int sx, sy, swidth, sheight; - val = assq_no_quit (Qgeometry, XCAR (tem)); + val = assq_no_quit (Qworkarea, XCAR (tem)); if (!NILP (val)) { sx = XFIXNUM (XCAR (XCDR (val))); @@ -5156,37 +5182,15 @@ xlw_monitor_dimensions_at_pos (Display *dpy, Screen *screen, int src_x, int src_y, int *x, int *y, int *width, int *height) { struct x_display_info *dpyinfo = x_display_info_for_display (dpy); - XRectangle rect, workarea, intersection; - int dim_x, dim_y, dim_w, dim_h; if (!dpyinfo) emacs_abort (); block_input (); xlw_monitor_dimensions_at_pos_1 (dpyinfo, screen, src_x, src_y, - &dim_x, &dim_y, &dim_w, &dim_h); - rect.x = dim_x; - rect.y = dim_y; - rect.width = dim_w; - rect.height = dim_h; - - if (!x_get_net_workarea (dpyinfo, &workarea)) - memset (&workarea, 0, sizeof workarea); - unblock_input (); + x, y, width, height); - if (!gui_intersect_rectangles (&rect, &workarea, &intersection)) - { - *x = 0; - *y = 0; - *width = 0; - *height = 0; - return; - } - - *x = intersection.x; - *y = intersection.y; - *width = intersection.width; - *height = intersection.height; + unblock_input (); } #endif commit 14f074f95e2b57ddcd4b449fbdc04169290d0647 Author: Po Lu Date: Thu Dec 30 09:24:30 2021 +0800 Translate crossing event mode when sending them to xwidgets * src/xwidget.c (xi_translate_notify_detail): Use XI constants instead. (xwidget_motion_or_crossing): Translate XI entry event mode. diff --git a/src/xwidget.c b/src/xwidget.c index 30e9c2895d..5aeb2beae2 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1235,15 +1235,15 @@ xi_translate_notify_detail (int detail) { switch (detail) { - case NotifyInferior: + case XINotifyInferior: return GDK_NOTIFY_INFERIOR; - case NotifyAncestor: + case XINotifyAncestor: return GDK_NOTIFY_ANCESTOR; - case NotifyVirtual: + case XINotifyVirtual: return GDK_NOTIFY_VIRTUAL; - case NotifyNonlinear: + case XINotifyNonlinear: return GDK_NOTIFY_NONLINEAR; - case NotifyNonlinearVirtual: + case XINotifyNonlinearVirtual: return GDK_NOTIFY_NONLINEAR_VIRTUAL; default: emacs_abort (); @@ -1328,6 +1328,7 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event) xg_event->crossing.y_root = (gdouble) xev->root_y; xg_event->crossing.time = xev->time; xg_event->crossing.focus = xev->focus; + xg_event->crossing.mode = xev->mode; xg_event->crossing.detail = xi_translate_notify_detail (xev->detail); xg_event->crossing.state = xev->mods.effective; commit fb4f2aa0389d7d10dfcc1b6d8601c2d5e80730f0 Author: Juri Linkov Date: Wed Dec 29 21:10:04 2021 +0200 * lisp/textmodes/paragraphs.el (repunctuate-sentences-filter): New function. (repunctuate-sentences): Use it on isearch-filter-predicate to skip unnecessary matches. (bug#52769) diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el index acb26fd1c1..788230141e 100644 --- a/lisp/textmodes/paragraphs.el +++ b/lisp/textmodes/paragraphs.el @@ -479,6 +479,14 @@ sentences. Also, every paragraph boundary terminates sentences as well." (setq arg (1- arg))) (constrain-to-field nil opoint t))) +(defun repunctuate-sentences-filter (_start _end) + "Search filter used by `repunctuate-sentences' to skip unneeded spaces. +By default, it skips occurrences that already have two spaces. +It is advised to put `advice-add' on this function to add more filters, +for example, `(looking-back (rx (or \"e.g.\" \"i.e.\") \" \") 5)' +with a set of predefined abbreviations to skip from adding two spaces." + (not (length= (match-string 4) 2))) + (defun repunctuate-sentences (&optional no-query start end) "Put two spaces at the end of sentences from point to the end of buffer. It works using `query-replace-regexp'. In Transient Mark mode, @@ -489,14 +497,20 @@ asking for confirmation." (interactive (list nil (if (use-region-p) (region-beginning)) (if (use-region-p) (region-end)))) - (let ((regexp "\\([]\"')]?\\)\\([.?!]\\)\\([]\"')]?\\) +") + (let ((regexp "\\([]\"')]?\\)\\([.?!]\\)\\([]\"')]?\\)\\( +\\)") (to-string "\\1\\2\\3 ")) (if no-query (progn (when start (goto-char start)) (while (re-search-forward regexp end t) (replace-match to-string))) - (query-replace-regexp regexp to-string nil start end)))) + (unwind-protect + (progn + (add-function :after-while isearch-filter-predicate + #'repunctuate-sentences-filter) + (query-replace-regexp regexp to-string nil start end)) + (remove-function isearch-filter-predicate + #'repunctuate-sentences-filter))))) (defun backward-sentence (&optional arg) commit 06545bc0cc533b1abd831dd521df5f3369675d61 Author: Alan Mackenzie Date: Wed Dec 29 19:05:11 2021 +0000 CC Mode: c-update-brace-stack: After struct foo *, do not expect a brace. This fixes bug #52796. * lisp/progmodes/cc-engine.el (c-update-brace-stack): Handle a "*" like a semicolon, cancelling the expectation of a brace. * lisp/progmodes/cc-langs.el (c-brace-stack-thing-key): Add a "*" into the sets of significant characters. diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index db1f46621d..862652e2e5 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -6135,7 +6135,7 @@ comment at the start of cc-engine.el for more info." (setq s (cons -1 (cdr s)))) ((and (equal match ",") (eq (car s) -1))) ; at "," in "class foo : bar, ..." - ((member match '(";" "," ")")) + ((member match '(";" "*" "," "(")) (when (and s (cdr s) (<= (car s) 0)) (setq s (cdr s)))) ((c-keyword-member kwd-sym 'c-flat-decl-block-kwds) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 53f6206a82..85cc887110 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -3180,8 +3180,8 @@ Note that Java specific rules are currently applied to tell this from (append (c-lang-const c-flat-decl-block-kwds) (if (c-lang-const c-recognize-<>-arglists) - '("{" "}" ";" "," ")" ":" "<") - '("{" "}" ";" "," ")" ":"))))) + '("{" "}" ";" "*" "," ")" ":" "<") + '("{" "}" ";" "*" "," ")" ":"))))) (c-lang-defvar c-brace-stack-thing-key (c-lang-const c-brace-stack-thing-key)) (c-lang-defconst c-brace-stack-no-semi-key commit 3fc8032a1aac535e8f6ba03547bd9fa2b0880193 Author: Juri Linkov Date: Wed Dec 29 20:52:11 2021 +0200 * lisp/textmodes/sgml-mode.el (sgml-mode): Set skeleton-end-newline to nil. Prevent skeleton.el from adding a newline to each inserted skeleton. Those which do want a newline do that explicitly in their define-skeleton form. This is what texinfo-mode does (bug#52864). diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index cae1fecebc..3acf0e8965 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el @@ -624,6 +624,7 @@ Do \\[describe-key] on the following bindings to discover what they do. (setq-local comment-indent-function 'sgml-comment-indent) (setq-local comment-line-break-function 'sgml-comment-indent-new-line) (setq-local skeleton-further-elements '((completion-ignore-case t))) + (setq-local skeleton-end-newline nil) (setq-local skeleton-end-hook (lambda () (or (eolp) commit 58d06af57d5942e87ca5c49ee941b426c76779e7 Author: Eli Zaretskii Date: Wed Dec 29 20:25:02 2021 +0200 ; * lisp/replace.el (replace-regexp-function): Doc fix. (Bug#52558) diff --git a/lisp/replace.el b/lisp/replace.el index 2e877305c0..70d3ec73f8 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -2622,9 +2622,13 @@ It is called with three arguments, as if it were `re-search-forward'.") (defvar replace-regexp-function nil - "Function to convert a search string to a regexp to replace. -It's bound to `isearch-regexp-function' when searching -for a string to replace.") + "Function to convert the FROM string of query-replace commands to a regexp. +This is used by `query-replace', `query-replace-regexp', etc. as +the value of `isearch-regexp-function' when they search for the +occurences of the string/regexp to be replaced. This is intended +to be used when the string to be replaced, as typed by the user, +is not to be interpreted literally, but instead should be converted +to a regexp that is actually used for the search.") (defun replace-search (search-string limit regexp-flag delimited-flag case-fold &optional backward) commit f6e383c8bb2023793731fcebde88c15be721d8ee Author: Eli Zaretskii Date: Wed Dec 29 19:45:06 2021 +0200 Fix documentation of 'define-keymap' * doc/lispref/keymaps.texi (Creating Keymaps) (Changing Key Bindings): Fix typos, improve wording. diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 59cadb021a..f19d55cd05 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -373,14 +373,14 @@ number of keys. Here's a very basic example: "C-c C-c" #'quit-window) @end lisp -This function creates a new sparse keymap, defines the two keystrokes -in @var{pairs}, and returns the new keymap. +This function creates a new sparse keymap, defines the keystrokes in +@var{pairs}, and returns the new keymap. @var{pairs} is a list of alternating key bindings and key definitions, -as accepted by @code{keymap-set}. In addition the key can be the +as accepted by @code{keymap-set}. In addition, the key can be the special symbol @code{:menu}, in which case the definition should be a menu definition as accepted by @code{easy-menu-define} (@pxref{Easy -Menu}). Here's a brief example: +Menu}). Here's a brief example of this usage: @lisp (define-keymap :full t @@ -391,37 +391,40 @@ Menu}). Here's a brief example: @end lisp A number of keywords can be used before the key/definition pairs to -changes features of the new keymap. If the keyword is missing, the -default value for the feature is @code{nil}. Here's a list of the -available keywords: +change features of the new keymap. If any of the feature keywords is +missing from the @code{define-keymap} call, the default value for that +feature is @code{nil}. Here's a list of the available feature +keywords: @table @code @item :full -If non-@code{nil}, create a chartable keymap (as from +If non-@code{nil}, create a char-table keymap (as from @code{make-keymap}) instead of a sparse keymap (as from @code{make-sparse-keymap} (@pxref{Creating Keymaps}). A sparse keymap is the default. @item :parent -If non-@code{nil}, this should be a keymap to use as the parent +If non-@code{nil}, the value should be a keymap to use as the parent (@pxref{Inheritance and Keymaps}). @item :keymap -If non-@code{nil}, this should be a keymap. Instead of creating a new -keymap, this keymap is modified instead. +If non-@code{nil}, the value should be a keymap. Instead of creating +a new keymap, the specified keymap is modified instead. @item :suppress If non-@code{nil}, the keymap will be suppressed with -@code{suppress-keymap} (@pxref{Changing Key Bindings}). If -@code{nodigits}, treat digits like other chars. +@code{suppress-keymap} (@pxref{Changing Key Bindings}). By default, +digits and the minus sign are exempt from suppressing, but if the +value is @code{nodigits}, this suppresses digits and minus-sign like +it does with other characters. @item :name -If non-@code{nil}, this should be a string to use as the menu for the -keymap if you use it as a menu with @code{x-popup-menu} (@pxref{Pop-Up -Menus}). +If non-@code{nil}, the value should be a string to use as the menu for +the keymap if you use it as a menu with @code{x-popup-menu} +(@pxref{Pop-Up Menus}). @item :prefix -If non-@code{nil}, this should be a symbol to be used as a prefix +If non-@code{nil}, the value should be a symbol to be used as a prefix command (@pxref{Prefix Keys}). If this is the case, this symbol is returned by @code{define-keymap} instead of the map itself. @end table @@ -433,13 +436,13 @@ By far, the most common thing to do with a keymap is to bind it to a variable. This is what virtually all modes do---a mode called @code{foo} almost always has a variable called @code{foo-mode-map}. -This macro defines @var{name} as a variable, and passes @var{options} -and @var{pars} to @code{define-keymap}, and uses the result as the +This macro defines @var{name} as a variable, passes @var{options} +and @var{pairs} to @code{define-keymap}, and uses the result as the default value for the variable. -@var{options} is like the keywords in @code{define-keymap}, but adds a -@code{:doc} keyword that says what the doc string for the @var{name} -variable should be. +@var{options} is like the keywords in @code{define-keymap}, but +there's an additional @code{:doc} keyword that provides the doc +string for the defined variable. Here's an example: @@ -1483,7 +1486,7 @@ keymap. When writing modes, however, you frequently have to bind a large number of keys at once, and using @code{keymap-set} on them all can be tedious and error-prone. Instead you can use @code{define-keymap}, which creates a keymap and binds a number of -keys. @xref{Creating Keymaps} for details. +keys. @xref{Creating Keymaps}, for details. The function @code{substitute-key-definition} scans a keymap for keys that have a certain binding and rebinds them with a different commit 1915c19131b5279f65080ec7795761a2e2aa21ea Author: Eli Zaretskii Date: Wed Dec 29 19:30:23 2021 +0200 Fix recent changes in 'keymap-lookup' documentation * doc/lispref/keymaps.texi (Functions for Key Lookup): Improve wording, correct typos. diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 856a1a5671..59cadb021a 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1240,14 +1240,15 @@ Like the normal command loop, @code{keymap-lookup} will remap the command resulting from looking up @var{key} by looking up the command in the current keymaps. However, if the optional third argument @var{no-remap} is non-@code{nil}, @code{keymap-lookup} returns the -unmapped command. +command without remapping. If the optional argument @var{position} is non-@code{nil}, it specifies a mouse position as returned by @code{event-start} and @code{event-end}, and the lookup occurs in the keymaps associated with -it instead of @var{key}. It can also be a number or marker, in which -case the keymap properties at the specified buffer position instead of -point are used. +that position, instead of in @var{keymap}. @var{position} can also be +a number or a marker, in which case it is interpreted as a buffer +position, and the function uses the keymap properties at that position +instead of at point. @end defun @deffn Command undefined commit 7715fb3eff59102487e37fba5fc0d421dc8b9a51 Author: Tassilo Horn Date: Wed Dec 29 18:00:52 2021 +0100 Revert "Revert "Fix fontification in diff--font-lock-prettify"" This reverts commit 3cadd72673d8095df7eeb8e847db87ae42b5e2f6. diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 8f83aa580e..60d210ca22 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -2612,19 +2612,17 @@ fixed, visit it in a buffer." "\\(?:index.*\n\\)?" "--- \\(?:" null-device "\\|a/\\(.*\\)\\)\n" "\\+\\+\\+ \\(?:" null-device "\\|b/\\(.*\\)\\)\n")))) - (put-text-property (match-beginning 0) - (or (match-beginning 2) (match-beginning 1)) - 'display (propertize - (cond - ((null (match-beginning 1)) - (concat "new file " (match-string 2))) - ((null (match-beginning 2)) - (concat "deleted " (match-string 1))) - (t - (concat "modified " (match-string 1)))) - 'face '(diff-file-header diff-header))) - (put-text-property (match-end 1) (1- (match-end 0)) - 'display "")))) + (put-text-property (match-beginning 0) (1- (match-end 0)) + 'display + (propertize + (cond + ((null (match-string 1)) + (concat "new file " (match-string 2))) + ((null (match-string 2)) + (concat "deleted " (match-string 1))) + (t + (concat "modified " (match-string 1)))) + 'face '(diff-file-header diff-header)))))) nil) ;;; Syntax highlighting from font-lock commit 3cadd72673d8095df7eeb8e847db87ae42b5e2f6 Author: Tassilo Horn Date: Wed Dec 29 18:00:30 2021 +0100 Revert "Fix fontification in diff--font-lock-prettify" This reverts commit 1da392d62d1ae743151f7fda83d0725ec6053686. diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 60d210ca22..8f83aa580e 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -2612,17 +2612,19 @@ fixed, visit it in a buffer." "\\(?:index.*\n\\)?" "--- \\(?:" null-device "\\|a/\\(.*\\)\\)\n" "\\+\\+\\+ \\(?:" null-device "\\|b/\\(.*\\)\\)\n")))) - (put-text-property (match-beginning 0) (1- (match-end 0)) - 'display - (propertize - (cond - ((null (match-string 1)) - (concat "new file " (match-string 2))) - ((null (match-string 2)) - (concat "deleted " (match-string 1))) - (t - (concat "modified " (match-string 1)))) - 'face '(diff-file-header diff-header)))))) + (put-text-property (match-beginning 0) + (or (match-beginning 2) (match-beginning 1)) + 'display (propertize + (cond + ((null (match-beginning 1)) + (concat "new file " (match-string 2))) + ((null (match-beginning 2)) + (concat "deleted " (match-string 1))) + (t + (concat "modified " (match-string 1)))) + 'face '(diff-file-header diff-header))) + (put-text-property (match-end 1) (1- (match-end 0)) + 'display "")))) nil) ;;; Syntax highlighting from font-lock commit 1da392d62d1ae743151f7fda83d0725ec6053686 Author: Matthias Meulien Date: Wed Dec 29 17:25:35 2021 +0100 Fix fontification in diff--font-lock-prettify * lisp/vc/diff-mode.el (diff--font-lock-prettify): Fix diff--font-lock-prettify on created or deleted files (bug#52810). diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 8f83aa580e..60d210ca22 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -2612,19 +2612,17 @@ fixed, visit it in a buffer." "\\(?:index.*\n\\)?" "--- \\(?:" null-device "\\|a/\\(.*\\)\\)\n" "\\+\\+\\+ \\(?:" null-device "\\|b/\\(.*\\)\\)\n")))) - (put-text-property (match-beginning 0) - (or (match-beginning 2) (match-beginning 1)) - 'display (propertize - (cond - ((null (match-beginning 1)) - (concat "new file " (match-string 2))) - ((null (match-beginning 2)) - (concat "deleted " (match-string 1))) - (t - (concat "modified " (match-string 1)))) - 'face '(diff-file-header diff-header))) - (put-text-property (match-end 1) (1- (match-end 0)) - 'display "")))) + (put-text-property (match-beginning 0) (1- (match-end 0)) + 'display + (propertize + (cond + ((null (match-string 1)) + (concat "new file " (match-string 2))) + ((null (match-string 2)) + (concat "deleted " (match-string 1))) + (t + (concat "modified " (match-string 1)))) + 'face '(diff-file-header diff-header)))))) nil) ;;; Syntax highlighting from font-lock commit 0d5bda36fbab68112f1391d7894d804d45b786af Author: Lars Ingebrigtsen Date: Wed Dec 29 17:20:08 2021 +0100 Document keymap-set-after in Modifying Menus in lispref * doc/lispref/keymaps.texi (Modifying Menus): Document keymap-set-after (bug#52819). diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 11cad3957e..856a1a5671 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -2291,7 +2291,7 @@ the keymap. Since @code{define-key} puts new bindings at the front, you should define the menu items starting at the bottom of the menu and moving to the top, if you care about the order. When you add an item to an existing menu, you can specify its position in the menu using -@code{define-key-after} (@pxref{Modifying Menus}). +@code{keymap-set-after} (@pxref{Modifying Menus}). @menu * Simple Menu Items:: A simple kind of menu key binding. @@ -3045,9 +3045,9 @@ To force recalculation of the tool bar, call When you insert a new item in an existing menu, you probably want to put it in a particular place among the menu's existing items. If you use @code{define-key} to add the item, it normally goes at the front of -the menu. To put it elsewhere in the menu, use @code{define-key-after}: +the menu. To put it elsewhere in the menu, use @code{keymap-set-after}: -@defun define-key-after map key binding &optional after +@defun keymap-set-after map key binding &optional after Define a binding in @var{map} for @var{key}, with value @var{binding}, just like @code{define-key}, but position the binding in @var{map} after the binding for the event @var{after}. The argument @var{key} should be @@ -3061,7 +3061,7 @@ inherited keymap. Here is an example: @example -(define-key-after my-menu [drink] +(keymap-set-after my-menu "" '("Drink" . drink-command) 'eat) @end example @@ -3073,7 +3073,7 @@ Here is how to insert an item called @samp{Work} in the @samp{Signals} menu of Shell mode, after the item @code{break}: @example -(define-key-after shell-mode-map [menu-bar signals work] +(keymap-set-after shell-mode-map " " '("Work" . work-command) 'break) @end example @end defun commit 2970dbaa32e6b33189973ce814b1b327bbbb15fa Author: Lars Ingebrigtsen Date: Wed Dec 29 17:11:31 2021 +0100 Document `keymap-lookup' in the lipsref manual * doc/lispref/keymaps.texi (Functions for Key Lookup): Document `keymap-lookup' instead of `lookup-key' (bug#52820). diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index 0aa7eaa149..11cad3957e 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -1183,22 +1183,18 @@ macro, a symbol that leads to one of them, or @code{nil}. Here are the functions and variables pertaining to key lookup. -@defun lookup-key keymap key &optional accept-defaults +@defun keymap-lookup keymap key &optional accept-defaults no-remap position This function returns the definition of @var{key} in @var{keymap}. All the other functions described in this chapter that look up keys use -@code{lookup-key}. Here are examples: +@code{keymap-lookup}. Here are examples: @example @group -(lookup-key (current-global-map) "\C-x\C-f") +(keymap-lookup (current-global-map) "C-x C-f") @result{} find-file @end group @group -(lookup-key (current-global-map) (kbd "C-x C-f")) - @result{} find-file -@end group -@group -(lookup-key (current-global-map) "\C-x\C-f12345") +(keymap-lookup (current-global-map) "C-x C-f 1 2 3 4 5") @result{} 2 @end group @end example @@ -1209,9 +1205,9 @@ and have extra events at the end that do not fit into a single key sequence. Then the value is a number, the number of events at the front of @var{key} that compose a complete key. -If @var{accept-defaults} is non-@code{nil}, then @code{lookup-key} +If @var{accept-defaults} is non-@code{nil}, then @code{keymap-lookup} considers default bindings as well as bindings for the specific events -in @var{key}. Otherwise, @code{lookup-key} reports only bindings for +in @var{key}. Otherwise, @code{keymap-lookup} reports only bindings for the specific sequence @var{key}, ignoring default bindings except when you explicitly ask about them. (To do this, supply @code{t} as an element of @var{key}; see @ref{Format of Keymaps}.) @@ -1224,11 +1220,11 @@ the second example. @example @group -(lookup-key (current-global-map) "\M-f") +(keymap-lookup (current-global-map) "M-f") @result{} forward-word @end group @group -(lookup-key (current-global-map) "\ef") +(keymap-lookup (current-global-map) "ESC f") @result{} forward-word @end group @end example @@ -1239,6 +1235,19 @@ Unlike @code{read-key-sequence}, this function does not modify the specified events in ways that discard information (@pxref{Key Sequence Input}). In particular, it does not convert letters to lower case and it does not change drag events to clicks. + +Like the normal command loop, @code{keymap-lookup} will remap the +command resulting from looking up @var{key} by looking up the command +in the current keymaps. However, if the optional third argument +@var{no-remap} is non-@code{nil}, @code{keymap-lookup} returns the +unmapped command. + +If the optional argument @var{position} is non-@code{nil}, it +specifies a mouse position as returned by @code{event-start} and +@code{event-end}, and the lookup occurs in the keymaps associated with +it instead of @var{key}. It can also be a number or marker, in which +case the keymap properties at the specified buffer position instead of +point are used. @end defun @deffn Command undefined @@ -1251,7 +1260,7 @@ This function returns the binding for @var{key} in the current local keymap, or @code{nil} if it is undefined there. The argument @var{accept-defaults} controls checking for default bindings, -as in @code{lookup-key} (above). +as in @code{keymap-lookup} (above). @end defun @defun keymap-global-binding key &optional accept-defaults @@ -1259,7 +1268,7 @@ This function returns the binding for command @var{key} in the current global keymap, or @code{nil} if it is undefined there. The argument @var{accept-defaults} controls checking for default bindings, -as in @code{lookup-key} (above). +as in @code{keymap-lookup} (above). @end defun @defun minor-mode-key-binding key &optional accept-defaults @@ -1276,7 +1285,7 @@ modes are omitted, since they would be completely shadowed. Similarly, the list omits non-prefix bindings that follow prefix bindings. The argument @var{accept-defaults} controls checking for default -bindings, as in @code{lookup-key} (above). +bindings, as in @code{keymap-lookup} (above). @end defun @defopt meta-prefix-char commit ef344cc55c88579a3f73b7404fc37163b2f59efc Author: Lars Ingebrigtsen Date: Wed Dec 29 16:56:16 2021 +0100 Move define-keymap manual entry to Creating Keymaps * doc/lispref/keymaps.texi (Creating Keymaps) (Changing Key Bindings): Move `define-keymap'/`defvar-keymap' to the Creating Keymaps node. diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi index adde65e970..0aa7eaa149 100644 --- a/doc/lispref/keymaps.texi +++ b/doc/lispref/keymaps.texi @@ -357,6 +357,100 @@ A full keymap is more efficient than a sparse keymap when it holds lots of bindings; for just a few, the sparse keymap is better. @end defun +@defun define-keymap &key options... &rest pairs... +You can create a keymap with the functions described above, and then +use @code{keymap-set} (@pxref{Changing Key Bindings}) to specify key +bindings in that map. When writing modes, however, you frequently +have to bind a large number of keys at once, and using +@code{keymap-set} on them all can be tedious and error-prone. Instead +you can use @code{define-keymap}, which creates a keymap and binds a +number of keys. Here's a very basic example: + +@lisp +(define-keymap + "n" #'forward-line + "f" #'previous-line + "C-c C-c" #'quit-window) +@end lisp + +This function creates a new sparse keymap, defines the two keystrokes +in @var{pairs}, and returns the new keymap. + +@var{pairs} is a list of alternating key bindings and key definitions, +as accepted by @code{keymap-set}. In addition the key can be the +special symbol @code{:menu}, in which case the definition should be a +menu definition as accepted by @code{easy-menu-define} (@pxref{Easy +Menu}). Here's a brief example: + +@lisp +(define-keymap :full t + "g" #'eww-reload + :menu '("Eww" + ["Exit" quit-window t] + ["Reload" eww-reload t])) +@end lisp + +A number of keywords can be used before the key/definition pairs to +changes features of the new keymap. If the keyword is missing, the +default value for the feature is @code{nil}. Here's a list of the +available keywords: + +@table @code +@item :full +If non-@code{nil}, create a chartable keymap (as from +@code{make-keymap}) instead of a sparse keymap (as from +@code{make-sparse-keymap} (@pxref{Creating Keymaps}). A sparse keymap +is the default. + +@item :parent +If non-@code{nil}, this should be a keymap to use as the parent +(@pxref{Inheritance and Keymaps}). + +@item :keymap +If non-@code{nil}, this should be a keymap. Instead of creating a new +keymap, this keymap is modified instead. + +@item :suppress +If non-@code{nil}, the keymap will be suppressed with +@code{suppress-keymap} (@pxref{Changing Key Bindings}). If +@code{nodigits}, treat digits like other chars. + +@item :name +If non-@code{nil}, this should be a string to use as the menu for the +keymap if you use it as a menu with @code{x-popup-menu} (@pxref{Pop-Up +Menus}). + +@item :prefix +If non-@code{nil}, this should be a symbol to be used as a prefix +command (@pxref{Prefix Keys}). If this is the case, this symbol is +returned by @code{define-keymap} instead of the map itself. +@end table + +@end defun + +@defmac defvar-keymap name &key options... &rest pairs... +By far, the most common thing to do with a keymap is to bind it to a +variable. This is what virtually all modes do---a mode called +@code{foo} almost always has a variable called @code{foo-mode-map}. + +This macro defines @var{name} as a variable, and passes @var{options} +and @var{pars} to @code{define-keymap}, and uses the result as the +default value for the variable. + +@var{options} is like the keywords in @code{define-keymap}, but adds a +@code{:doc} keyword that says what the doc string for the @var{name} +variable should be. + +Here's an example: + +@lisp +(defvar-keymap eww-textarea-map + :parent text-mode-map + "RET" #'forward-line + "TAB" #'shr-next-link) +@end lisp +@end defmac + @defun copy-keymap keymap This function returns a copy of @var{keymap}. This is almost never needed. If you want a keymap that's like another yet with a few @@ -1374,100 +1468,14 @@ changing an entry in @code{ctl-x-map}, and this has the effect of changing the bindings of both @kbd{C-p C-f} and @kbd{C-x C-f} in the default global map. -@defun define-keymap &key options... &rest pairs... @code{keymap-set} is the general work horse for defining a key in a keymap. When writing modes, however, you frequently have to bind a large number of keys at once, and using @code{keymap-set} on them all can be tedious and error-prone. Instead you can use -@code{define-keymap}, which creates a keymaps and binds a number of -keys. Here's a very basic example: - -@lisp -(define-keymap - "n" #'forward-line - "f" #'previous-line - "C-c C-c" #'quit-window) -@end lisp - -This function creates a new sparse keymap, defines the two keystrokes -in @var{pairs}, and returns the new keymap. - -@var{pairs} is a list of alternating key bindings and key definitions, -as accepted by @code{keymap-set}. In addition the key can be the -special symbol @code{:menu}, in which case the definition should be a -menu definition as accepted by @code{easy-menu-define} (@pxref{Easy -Menu}). Here's a brief example: - -@lisp -(define-keymap :full t - "g" #'eww-reload - :menu '("Eww" - ["Exit" quit-window t] - ["Reload" eww-reload t])) -@end lisp - -A number of keywords can be used before the key/definition pairs to -changes features of the new keymap. If the keyword is missing, the -default value for the feature is @code{nil}. Here's a list of the -available keywords: - -@table @code -@item :full -If non-@code{nil}, create a chartable keymap (as from -@code{make-keymap}) instead of a sparse keymap (as from -@code{make-sparse-keymap} (@pxref{Creating Keymaps}). A sparse keymap -is the default. - -@item :parent -If non-@code{nil}, this should be a keymap to use as the parent -(@pxref{Inheritance and Keymaps}). - -@item :keymap -If non-@code{nil}, this should be a keymap. Instead of creating a new -keymap, this keymap is modified instead. - -@item :suppress -If non-@code{nil}, the keymap will be suppressed with -@code{suppress-keymap} (@pxref{Changing Key Bindings}). If -@code{nodigits}, treat digits like other chars. - -@item :name -If non-@code{nil}, this should be a string to use as the menu for the -keymap if you use it as a menu with @code{x-popup-menu} (@pxref{Pop-Up -Menus}). - -@item :prefix -If non-@code{nil}, this should be a symbol to be used as a prefix -command (@pxref{Prefix Keys}). If this is the case, this symbol is -returned by @code{define-keymap} instead of the map itself. -@end table - -@end defun - -@defmac defvar-keymap name &key options... &rest pairs... -By far, the most common thing to do with a keymap is to bind it to a -variable. This is what virtually all modes do---a mode called -@code{foo} almost always has a variable called @code{foo-mode-map}. - -This macro defines @var{name} as a variable, and passes @var{options} -and @var{pars} to @code{define-keymap}, and uses the result as the -default value for the variable. - -@var{options} is like the keywords in @code{define-keymap}, but adds a -@code{:doc} keyword that says what the doc string for the @var{name} -variable should be. - -Here's an example: - -@lisp -(defvar-keymap eww-textarea-map - :parent text-mode-map - "RET" #'forward-line - "TAB" #'shr-next-link) -@end lisp -@end defmac +@code{define-keymap}, which creates a keymap and binds a number of +keys. @xref{Creating Keymaps} for details. - The function @code{substitute-key-definition} scans a keymap for +The function @code{substitute-key-definition} scans a keymap for keys that have a certain binding and rebinds them with a different binding. Another feature which is cleaner and can often produce the same results is to remap one command into another (@pxref{Remapping commit d9b28ba7c3fa3dc9647aa67ae398ce8b36fb1f4e Author: Lars Ingebrigtsen Date: Wed Dec 29 16:48:34 2021 +0100 Allow the user to specify shr-width in mm-shr * lisp/gnus/mm-decode.el (mm-shr): Allow the user to specify the width by setting `shr-width' (bug#52825). diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el index d2889a50c0..e2fb4b66b1 100644 --- a/lisp/gnus/mm-decode.el +++ b/lisp/gnus/mm-decode.el @@ -1869,7 +1869,7 @@ If RECURSIVE, search recursively." ;; Require since we bind its variables. (require 'shr) (let ((shr-width (if shr-use-fonts - nil + shr-width fill-column)) (shr-content-function (lambda (id) (let ((handle (mm-get-content-id id))) commit 0e1a06ac85f6b926327963c8cd1b8b95e0f7d5ba Author: Lars Ingebrigtsen Date: Wed Dec 29 16:09:22 2021 +0100 Make multi-test-files-busy shorter diff --git a/test/lisp/emacs-lisp/multisession-tests.el b/test/lisp/emacs-lisp/multisession-tests.el index 6618699c4d..57ca420488 100644 --- a/test/lisp/emacs-lisp/multisession-tests.el +++ b/test/lisp/emacs-lisp/multisession-tests.el @@ -62,7 +62,7 @@ (setq multisession--db nil))))) (ert-deftest multi-test-sqlite-busy () - (skip-unless (and t (sqlite-available-p))) + (skip-unless (sqlite-available-p)) (ert-with-temp-file dir :directory t (let ((user-init-file "/tmp/foo.el") @@ -136,7 +136,7 @@ (should (= (multisession-value multisession--sfoo) 2))))) (ert-deftest multi-test-files-busy () - (skip-unless (and t (sqlite-available-p))) + (skip-unless (sqlite-available-p)) (ert-with-temp-file dir :directory t (let ((user-init-file "/tmp/foo.el") @@ -163,14 +163,14 @@ (user-init-file "/tmp/sbar.el")) (define-multisession-variable multisession--sbar 0 "" :synchronized t) - (dotimes (i 1000) + (dotimes (i 100) (cl-incf (multisession-value multisession--sbar)))))))) (while (process-live-p proc) (message "multisession--sbar %s" (multisession-value multisession--sbar)) ;;(cl-incf (multisession-value multisession--sbar)) (sleep-for 0.1)) (message "multisession--sbar ends up as %s" (multisession-value multisession--sbar)) - (should (< (multisession-value multisession--sbar) 2000))))) + (should (< (multisession-value multisession--sbar) 200))))) (ert-deftest multi-test-files-some-values () (ert-with-temp-file dir commit bdd0b071bed56c681a3fa5affa0ab12dc520f563 Author: Lars Ingebrigtsen Date: Wed Dec 29 16:06:50 2021 +0100 Ignore manual/ directory made by admin/make-manuals diff --git a/.gitignore b/.gitignore index 78557a5e87..3e84de3ecf 100644 --- a/.gitignore +++ b/.gitignore @@ -320,3 +320,6 @@ lib-src/seccomp-filter-exec.pfc # gsettings schema /etc/*.gschema.valid + +# Ignore directory made by admin/make-manuals. +manual/ commit 918ed4904bdbb976a40b006c8874795756dce6a7 Author: Lars Ingebrigtsen Date: Wed Dec 29 16:06:32 2021 +0100 Adjust multi-test-files-simple test for Windows * test/lisp/emacs-lisp/multisession-tests.el (multi-test-files-simple): Adjust test to Emacs timestamp resolution on Windows. diff --git a/test/lisp/emacs-lisp/multisession-tests.el b/test/lisp/emacs-lisp/multisession-tests.el index f1dbbb29fd..6618699c4d 100644 --- a/test/lisp/emacs-lisp/multisession-tests.el +++ b/test/lisp/emacs-lisp/multisession-tests.el @@ -130,6 +130,9 @@ "" :synchronized t) (cl-incf (multisession-value multisession--sfoo)))))) + ;; On Windows, we don't have sub-second resolution. + (when (memq system-type '(windows-nt haiku)) + (sleep-for 2)) (should (= (multisession-value multisession--sfoo) 2))))) (ert-deftest multi-test-files-busy () commit f11779f01b229235feb4ce0c1b20a8c2fabfbb88 Author: Eli Zaretskii Date: Wed Dec 29 16:39:20 2021 +0200 Improve documentation of 'M-X' and related features * doc/emacs/m-x.texi (M-x): Index 'M-X'. * doc/lispref/commands.texi (Interactive Call, Command Modes): Mention 'M-X' and 'execute-extended-command-for-buffer'. * etc/NEWS: Clarify that the '(declare (completion ...' and '(declare (modes ...' forms have no effect by default. Likewise for '(interactive "..." MODE)' specs. (Bug#52839) diff --git a/doc/emacs/m-x.texi b/doc/emacs/m-x.texi index d35a835154..4e95e03aae 100644 --- a/doc/emacs/m-x.texi +++ b/doc/emacs/m-x.texi @@ -59,6 +59,7 @@ the option @code{read-extended-command-predicate} to exclude those irrelevant commands from completion results. @kindex M-S-x +@kindex M-X Conversely, Emacs can exclude all commands except those that are particularly relevant to the current buffer. The @kbd{M-S-x} (that's ``meta shift x'') command works just like @kbd{M-x}, but instead of diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 4e36d5807c..2f3d6148f6 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -630,17 +630,26 @@ any modes that are derived from @code{dired-mode}). Any number of modes can be added to the @code{interactive} form. @vindex read-extended-command-predicate -Specifying modes may affect completion in @kbd{M-x}, depending on the +Specifying modes affects command completion in @kbd{M-S-x} +(@code{execute-extended-command-for-buffer}, @pxref{Interactive +Call}). It may also affect completion in @kbd{M-x}, depending on the value of @code{read-extended-command-predicate}. For instance, when using the -@code{command-completion-default-include-p} predicate, @kbd{M-x} won't -list commands that have been marked as being applicable to a specific -mode (unless you are in a buffer that uses that mode, of course). -This goes for both major and minor modes. +@code{command-completion-default-include-p} predicate as the value of +@code{read-extended-command-predicate}, @kbd{M-x} won't list commands +that have been marked as being applicable to a specific mode (unless +you are in a buffer that uses that mode, of course). This goes for +both major and minor modes. (By contrast, @kbd{M-S-x} always omits +inapplicable commands from the completion candidates.) -Marking commands this way will also make @kbd{C-h m} list these -commands (if they aren't bound to any keys). +By default, @code{read-extended-command-predicate} is @code{nil}, and +completion in @kbd{M-x} lists all the commands that match what the +user has typed, whether those commands are or aren't marked as +applicable to the current buffer's mode. + +Marking commands to be applicable to a mode will also make @kbd{C-h m} +list these commands (if they aren't bound to any keys). If using this extended @code{interactive} form isn't convenient (because the code is supposed to work in older versions of Emacs that @@ -857,13 +866,16 @@ non-@code{nil} if the command is to be included when completing in that buffer. @end deffn +@kindex @kbd{M-X} +@kindex @kbd{M-S-x} @deffn Command execute-extended-command-for-buffer prefix-argument This is like @code{execute-extended-command}, but limits the commands offered for completion to those commands that are of particular relevance to the current major mode (and enabled minor modes). This includes commands that are tagged with the modes (@pxref{Using Interactive}), and also commands that are bound to locally active -keymaps. +keymaps. This command is the normal definition of @kbd{M-S-x} +(that's ``meta shift x''). @end deffn @node Distinguish Interactive diff --git a/etc/NEWS b/etc/NEWS index 1664ccfd04..f1bf2fe67d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -3730,15 +3730,28 @@ commands as being applicable for modes derived from 'dired-mode', or if the mode is a minor mode, when the current buffer has that minor mode activated. Note that using this form will create byte code that is not compatible with byte code in previous Emacs versions. +Also note that by default these annotations have no effect, unless the +new option 'read-extended-command-predicate' option is customized to call +'command-completion-default-include-p' or a similar function. +++ -** New forms to declare how completion should happen has been added. +** New 'declare' forms to control completion of commands in 'M-x'. '(declare (completion PREDICATE))' can be used as a general predicate -to say whether the command should be present when completing with -'M-x TAB'. '(declare (modes MODE...))' can be used as a short-hand -way of saying that the command should be present when completing from -buffers in major modes derived from MODE..., or, if it's a minor mode, -when that minor mode is enabled in the current buffer. +to say whether the command should be considered a completion candidate +when completing with 'M-x TAB'. + +'(declare (modes MODE...))' can be used as a short-hand way of saying +that the command should be considered a completion candidate when +completing on commands from buffers in major modes derived from +MODE..., or, if it's a minor mode, when that minor mode is enabled in +the current buffer. + +Note that these forms will only have their effect if the +'read-extended-command-predicate' option is customized to call +'command-completion-default-include-p' or a similar function. The +default value of 'read-extended-command-predicate' is nil, which means +no commands that match what you have typed are excluded from being +completion candidates. +++ ** 'define-minor-mode' now takes an ':interactive' argument. commit fb386e22e129f77bbb2d9faa757cf5bc4f5d90e1 Author: Po Lu Date: Wed Dec 29 18:59:47 2021 +0800 Fix a hang on servers that don't support the X Keyboard Extension * src/xfns.c (Fx_backspace_delete_keys_p): Don't block input before checking for Xkb. diff --git a/src/xfns.c b/src/xfns.c index ae01bb0405..7c4e694320 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -7749,11 +7749,11 @@ present and mapped to the usual X keysyms. */) Display *dpy = FRAME_X_DISPLAY (f); Lisp_Object have_keys; - block_input (); - if (!FRAME_DISPLAY_INFO (f)->supports_xkb) return Qlambda; + block_input (); + /* In this code we check that the keyboard has physical keys with names that start with BKSP (Backspace) and DELE (Delete), and that they generate keysym XK_BackSpace and XK_Delete respectively. commit 7d672ed069f7936b9410f61cff2df97f804fabff Author: Po Lu Date: Wed Dec 29 18:37:04 2021 +0800 Translate state of XI2 entry events when sending them to xwidgets * src/xwidget.c (xi_translate_notify_detail): New function. (xwidget_motion_or_crossing): Translate detail and state of GenericEvents before sending them to the widget. diff --git a/src/xwidget.c b/src/xwidget.c index 671d0390a0..30e9c2895d 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -1229,6 +1229,28 @@ xwidget_scroll (struct xwidget_view *view, double x, double y, } #endif +#ifdef HAVE_XINPUT2 +static GdkNotifyType +xi_translate_notify_detail (int detail) +{ + switch (detail) + { + case NotifyInferior: + return GDK_NOTIFY_INFERIOR; + case NotifyAncestor: + return GDK_NOTIFY_ANCESTOR; + case NotifyVirtual: + return GDK_NOTIFY_VIRTUAL; + case NotifyNonlinear: + return GDK_NOTIFY_NONLINEAR; + case NotifyNonlinearVirtual: + return GDK_NOTIFY_NONLINEAR_VIRTUAL; + default: + emacs_abort (); + } +} +#endif + void xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event) { @@ -1306,6 +1328,19 @@ xwidget_motion_or_crossing (struct xwidget_view *view, const XEvent *event) xg_event->crossing.y_root = (gdouble) xev->root_y; xg_event->crossing.time = xev->time; xg_event->crossing.focus = xev->focus; + xg_event->crossing.detail = xi_translate_notify_detail (xev->detail); + xg_event->crossing.state = xev->mods.effective; + + if (xev->buttons.mask_len) + { + if (XIMaskIsSet (xev->buttons.mask, 1)) + xg_event->crossing.state |= GDK_BUTTON1_MASK; + if (XIMaskIsSet (xev->buttons.mask, 2)) + xg_event->crossing.state |= GDK_BUTTON2_MASK; + if (XIMaskIsSet (xev->buttons.mask, 3)) + xg_event->crossing.state |= GDK_BUTTON3_MASK; + } + gdk_event_set_device (xg_event, find_suitable_pointer (view->frame)); } #endif commit 9d1312d8e9bf78c12a94fa075cda3c8ad7d1dad7 Author: Po Lu Date: Wed Dec 29 18:06:34 2021 +0800 Get rid of obsolete xwidget-related code on PGTK * src/emacsgtkfixed.c (emacs_fixed_class_init): Stop setting obsolete methods. (EMACS_FIXED_GET_CLASS, struct GtkFixedPrivateL): (emacs_fixed_gtk_widget_size_allocate): Delete obsolete things. * src/xwidget.c (x_draw_xwidget_glyph_string): Work around mysterious bug. diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index 7130e3535a..bd365004ad 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -27,7 +27,6 @@ along with GNU Emacs. If not, see . */ #else #include "xterm.h" #endif -#include "xwidget.h" #include "emacsgtkfixed.h" /* Silence a bogus diagnostic; see GNOME bug 683906. */ @@ -63,92 +62,6 @@ EMACS_FIXED (GtkWidget *widget) EmacsFixed); } -#if defined HAVE_XWIDGETS && defined HAVE_PGTK - -static EmacsFixedClass * -EMACS_FIXED_GET_CLASS (GtkWidget *widget) -{ - return G_TYPE_INSTANCE_GET_CLASS (widget, emacs_fixed_get_type (), - EmacsFixedClass); -} - -struct GtkFixedPrivateL -{ - GList *children; -}; - -static void -emacs_fixed_gtk_widget_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - /* For xwidgets. - - This basically re-implements the base class method and adds an - additional case for an xwidget view. - - It would be nicer if the bse class method could be called first, - and the xview modification only would remain here. It wasn't - possible to solve it that way yet. */ - EmacsFixedClass *klass; - GtkWidgetClass *parent_class; - struct GtkFixedPrivateL *priv; - - klass = EMACS_FIXED_GET_CLASS (widget); - parent_class = g_type_class_peek_parent (klass); - parent_class->size_allocate (widget, allocation); - - priv = G_TYPE_INSTANCE_GET_PRIVATE (widget, GTK_TYPE_FIXED, - struct GtkFixedPrivateL); - - gtk_widget_set_allocation (widget, allocation); - - if (gtk_widget_get_has_window (widget)) - { - if (gtk_widget_get_realized (widget)) - gdk_window_move_resize (gtk_widget_get_window (widget), - allocation->x, - allocation->y, - allocation->width, - allocation->height); - } - - for (GList *children = priv->children; children; children = children->next) - { - GtkFixedChild *child = children->data; - - if (!gtk_widget_get_visible (child->widget)) - continue; - - GtkRequisition child_requisition; - gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL); - - GtkAllocation child_allocation; - child_allocation.x = child->x; - child_allocation.y = child->y; - - if (!gtk_widget_get_has_window (widget)) - { - child_allocation.x += allocation->x; - child_allocation.y += allocation->y; - } - - child_allocation.width = child_requisition.width; - child_allocation.height = child_requisition.height; - - struct xwidget_view *xv - = g_object_get_data (G_OBJECT (child->widget), XG_XWIDGET_VIEW); - if (xv) - { - child_allocation.width = xv->clip_right; - child_allocation.height = xv->clip_bottom - xv->clip_top; - } - - gtk_widget_size_allocate (child->widget, &child_allocation); - } -} - -#endif /* HAVE_XWIDGETS && HAVE_PGTK */ - static void emacs_fixed_class_init (EmacsFixedClass *klass) { @@ -158,9 +71,6 @@ emacs_fixed_class_init (EmacsFixedClass *klass) widget_class->get_preferred_width = emacs_fixed_get_preferred_width; widget_class->get_preferred_height = emacs_fixed_get_preferred_height; -#if defined HAVE_XWIDGETS && defined HAVE_PGTK - widget_class->size_allocate = emacs_fixed_gtk_widget_size_allocate; -#endif g_type_class_add_private (klass, sizeof (EmacsFixedPrivate)); } diff --git a/src/xwidget.c b/src/xwidget.c index 71a1a46d10..671d0390a0 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -2168,9 +2168,11 @@ x_draw_xwidget_glyph_string (struct glyph_string *s) covers the entire frame. Clipping might have changed even if we haven't actually moved; try to figure out when we need to reclip for real. */ +#ifndef HAVE_PGTK if (xv->clip_right != clip_right || xv->clip_bottom != clip_bottom || xv->clip_top != clip_top || xv->clip_left != clip_left) +#endif { #ifdef USE_GTK #ifdef HAVE_X_WINDOWS commit 8719abe4ca5d4b6ccc0e405dc0313730c6ec7d72 Author: Po Lu Date: Wed Dec 29 17:49:42 2021 +0800 Test for Xkb support when opening a display * src/xfns.c (Fx_backspace_delete_keys_p): Use dpyinfo->supports_xkb instead of testing for its presence manually. * src/xterm.c (x_term_init): Test for Xkb presence and set supports_xkb appropriately. * src/xterm.h (struct x_display_info): New field `supports_xkb'. diff --git a/src/xfns.c b/src/xfns.c index 8dc383ddfa..ae01bb0405 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -7748,27 +7748,11 @@ present and mapped to the usual X keysyms. */) struct frame *f = decode_window_system_frame (frame); Display *dpy = FRAME_X_DISPLAY (f); Lisp_Object have_keys; - int major, minor, op, event, error_code; block_input (); - /* Check library version in case we're dynamically linked. */ - major = XkbMajorVersion; - minor = XkbMinorVersion; - if (!XkbLibraryVersion (&major, &minor)) - { - unblock_input (); - return Qlambda; - } - - /* Check that the server supports XKB. */ - major = XkbMajorVersion; - minor = XkbMinorVersion; - if (!XkbQueryExtension (dpy, &op, &event, &error_code, &major, &minor)) - { - unblock_input (); - return Qlambda; - } + if (!FRAME_DISPLAY_INFO (f)->supports_xkb) + return Qlambda; /* In this code we check that the keyboard has physical keys with names that start with BKSP (Backspace) and DELE (Delete), and that they diff --git a/src/xterm.c b/src/xterm.c index e3079727d5..61dff7aaab 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -14887,9 +14887,19 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) #endif #ifdef HAVE_XKB - dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display, - XkbAllComponentsMask, - XkbUseCoreKbd); + int xkb_major, xkb_minor, xkb_op, xkb_event, xkb_error_code; + xkb_major = XkbMajorVersion; + xkb_minor = XkbMinorVersion; + + if (XkbLibraryVersion (&xkb_major, &xkb_minor) + && XkbQueryExtension (dpyinfo->display, &xkb_op, &xkb_event, + &xkb_error_code, &xkb_major, &xkb_minor)) + { + dpyinfo->supports_xkb = true; + dpyinfo->xkb_desc = XkbGetMap (dpyinfo->display, + XkbAllComponentsMask, + XkbUseCoreKbd); + } #endif #if defined USE_CAIRO || defined HAVE_XFT diff --git a/src/xterm.h b/src/xterm.h index 5615a55d6b..a233e28dbe 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -522,6 +522,7 @@ struct x_display_info #endif #ifdef HAVE_XKB + bool supports_xkb; XkbDescPtr xkb_desc; #endif };