commit 76ee4dc82375893a5c59c63acda43af27879e54a (HEAD, refs/remotes/origin/master) Merge: 5b90b05e42 57c112cfe5 Author: Stefan Kangas Date: Sat Feb 19 06:30:51 2022 +0100 Merge from origin/emacs-28 57c112cfe5 ; * doc/emacs/files.texi (Comparing Files): Fix a reference. bdeac2d5af ; Fix a typo in filesets.el's doc string commit 5b90b05e428c26e91b1409356a41d2c1dd654b44 Author: Po Lu Date: Sat Feb 19 13:27:03 2022 +0800 Always decode GTK input method text as utf-8-unix * src/gtkutil.c (xg_im_context_commit): Use `utf-8-unix' as coding system for text. diff --git a/src/gtkutil.c b/src/gtkutil.c index bed983c77e..27aa28b890 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -6099,6 +6099,10 @@ xg_im_context_commit (GtkIMContext *imc, gchar *str, EVENT_INIT (ie); ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; ie.arg = build_unibyte_string (str); + + Fput_text_property (make_fixnum (0), make_fixnum (strlen (str)), + Qcoding, Qutf_8_unix, ie.arg); + XSETFRAME (ie.frame_or_window, f); ie.modifiers = 0; ie.timestamp = 0; commit 7829f1b5e698267c2baf37327fd393124f23c0ea Author: Po Lu Date: Sat Feb 19 11:51:05 2022 +0800 Be less strict about which emulated motion events to ignore * src/xterm.c (handle_one_xevent): Don't test XI2 version before dropping PointerEmulated motion events. diff --git a/src/xterm.c b/src/xterm.c index 53cb7a2ac4..af456389ab 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11017,8 +11017,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto XI_OTHER; #ifdef XI_TouchBegin - if (xev->flags & XIPointerEmulated - && dpyinfo->xi2_version >= 2) + if (xev->flags & XIPointerEmulated) goto XI_OTHER; #endif commit 8f9edb2e7cb48ec0ab4153a4cca31922c1cc7486 Author: Po Lu Date: Sat Feb 19 02:19:29 2022 +0000 * src/haikufns.c (haiku_create_frame): Error if font wasn't found. diff --git a/src/haikufns.c b/src/haikufns.c index 3f60aa807f..ea42dd0daa 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -673,6 +673,12 @@ haiku_create_frame (Lisp_Object parms) FRAME_RIF (f)->default_font_parameter (f, parms); + if (!FRAME_FONT (f)) + { + delete_frame (frame, Qnoelisp); + error ("Invalid frame font"); + } + gui_default_parameter (f, parms, Qborder_width, make_fixnum (0), "borderwidth", "BorderWidth", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qinternal_border_width, make_fixnum (2), @@ -682,9 +688,9 @@ haiku_create_frame (Lisp_Object parms) "childFrameBorderWidth", "childFrameBorderWidth", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qright_divider_width, make_fixnum (0), - NULL, NULL, RES_TYPE_NUMBER); + NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qbottom_divider_width, make_fixnum (0), - NULL, NULL, RES_TYPE_NUMBER); + NULL, NULL, RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qvertical_scroll_bars, Qt, "verticalScrollBars", "VerticalScrollBars", RES_TYPE_SYMBOL); commit 02bca34852b1f9dd2b3e5364274452d377686f6a Author: Po Lu Date: Sat Feb 19 09:18:27 2022 +0800 Utilize new string decoding feature in GTK native input * src/gtkutil.c (xg_im_context_commit): Don't decode strings manually using g_utf8_to_ucs4 but pass unibyte string as the keystroke event arg instead. diff --git a/src/gtkutil.c b/src/gtkutil.c index 5e41863c0a..bed983c77e 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -6095,29 +6095,15 @@ xg_im_context_commit (GtkIMContext *imc, gchar *str, { struct frame *f = user_data; struct input_event ie; - gunichar *ucs4_str; - ucs4_str = g_utf8_to_ucs4_fast (str, -1, NULL); + EVENT_INIT (ie); + ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + ie.arg = build_unibyte_string (str); + XSETFRAME (ie.frame_or_window, f); + ie.modifiers = 0; + ie.timestamp = 0; - if (!ucs4_str) - return; - - for (gunichar *c = ucs4_str; *c; c++) - { - EVENT_INIT (ie); - ie.kind = (SINGLE_BYTE_CHAR_P (*c) - ? ASCII_KEYSTROKE_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - ie.arg = Qnil; - ie.code = *c; - XSETFRAME (ie.frame_or_window, f); - ie.modifiers = 0; - ie.timestamp = 0; - - kbd_buffer_store_event (&ie); - } - - g_free (ucs4_str); + kbd_buffer_store_event (&ie); } static void commit 57c112cfe59e68eb31185ac15cde699dcc72db45 (refs/remotes/origin/emacs-28) Author: Philipp Stephani Date: Fri Feb 18 18:53:49 2022 +0100 ; * doc/emacs/files.texi (Comparing Files): Fix a reference. diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 3c62be677e..13c0e6d314 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -1467,8 +1467,8 @@ specified buffers. The command @kbd{M-x compare-windows} compares the text in the current window with that in the window that was the selected window before you selected the current one. (For more information about -windows in Emacs, @ref{Windows}.) Comparison starts at point in each -window, after pushing each initial point value on the mark ring +windows in Emacs, @pxref{Windows}.) Comparison starts at point in +each window, after pushing each initial point value on the mark ring (@pxref{Mark Ring}) in its respective buffer. Then it moves point forward in each window, one character at a time, until it reaches characters that don't match. Then the command exits. commit 51e51ce2df46fc0c6e17a97e74b00366bb9c09d8 Author: Eric Abrahamsen Date: Fri Feb 18 08:37:33 2022 -0800 Handle multiple directory separators in gnus-search results Try to treat the file names more like file names, less like strings to massage. * lisp/gnus/gnus-search.el (gnus-search-indexed-parse-output): Use `expand-file-name' to collapse separators and generally canonicalize the name. Use `file-name-split' and joining instead of regexp munging. diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index 27b07e3655..4ca873eeec 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -1393,18 +1393,27 @@ Returns a list of [group article score] vectors." (when (and f-name (file-readable-p f-name) (null (file-directory-p f-name))) - (setq group - (replace-regexp-in-string - "[/\\]" "." - (replace-regexp-in-string - "/?\\(cur\\|new\\|tmp\\)?/\\'" "" + ;; `expand-file-name' canoncalizes the file name, + ;; specifically collapsing multiple consecutive directory + ;; separators. + (setq f-name (expand-file-name f-name) + group + (delete + "" ; forward slash at root leaves an empty string + (file-name-split (replace-regexp-in-string - "\\`\\." "" - (string-remove-prefix + "\\`\\." "" ; why do we do this? + (string-remove-prefix prefix (file-name-directory f-name)) - nil t) - nil t) - nil t)) + nil t))) + ;; Turn file name segments into a Gnus group name. + group (mapconcat + #'identity + (if (member (car (last group)) + '("new" "tmp" "cur")) + (nbutlast group) + group) + ".")) (setq article (file-name-nondirectory f-name) article ;; TODO: Provide a cleaner way of producing final commit bdeac2d5afbc6cea9290e9f026cf9ac90c229190 Author: Eli Zaretskii Date: Fri Feb 18 15:46:57 2022 +0200 ; Fix a typo in filesets.el's doc string * lisp/filesets.el (filesets-remove-buffer, filesets-add-buffer): Doc fixes. Reported by Иванов Дмитрий . diff --git a/lisp/filesets.el b/lisp/filesets.el index 0bc44ecd91..83a914d58c 100644 --- a/lisp/filesets.el +++ b/lisp/filesets.el @@ -1761,7 +1761,7 @@ Use LOOKUP-NAME for deducing the save-function, if provided." (defun filesets-add-buffer (&optional name buffer) "Add BUFFER (or current buffer) to the fileset called NAME. -User will be queried, if no fileset name is provided." +If no fileset name is provided, prompt for NAME." (interactive) (let* ((buffer (or buffer (current-buffer))) @@ -1796,8 +1796,8 @@ User will be queried, if no fileset name is provided." (message "Filesets: Can't add `%s' to fileset `%s'" this name))))))) (defun filesets-remove-buffer (&optional name buffer) - "Remove BUFFER (or current buffer) to fileset NAME. -User will be queried, if no fileset name is provided." + "Remove BUFFER (or current buffer) from the fileset called NAME. +If no fileset name is provided, prompt for NAME." (interactive) (let* ((buffer (or buffer (current-buffer))) commit b76cd8af054a0e24ed8cd1bea515f1ca4619b115 Author: Po Lu Date: Fri Feb 18 21:24:42 2022 +0800 Fix background stipple with `alpha_background' * src/xterm.c (x_fill_rectangle): Fix treatment of foreground and background colors when there is a stipple. diff --git a/src/xterm.c b/src/xterm.c index 930d9cf370..53cb7a2ac4 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1417,7 +1417,6 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height, #endif x_xr_apply_ext_clip (f, gc); - x_xrender_color_from_gc_foreground (f, gc, &xc, true); #if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10) XGetGCValues (FRAME_X_DISPLAY (f), @@ -1426,15 +1425,9 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height, if (xgcv.fill_style == FillOpaqueStippled && FRAME_CHECK_XR_VERSION (f, 0, 10)) { - alpha.red = 65535 * f->alpha_background; - alpha.green = 65535 * f->alpha_background; - alpha.blue = 65535 * f->alpha_background; - alpha.alpha = 65535 * f->alpha_background; - - fill = XRenderCreateSolidFill (FRAME_X_DISPLAY (f), - &alpha); + x_xrender_color_from_gc_background (f, gc, &alpha, true); + x_xrender_color_from_gc_foreground (f, gc, &xc, true); attrs.repeat = RepeatNormal; - attrs.alpha_map = fill; stipple = XRenderCreatePicture (FRAME_X_DISPLAY (f), xgcv.stipple, @@ -1442,19 +1435,26 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height, PictStandardA1), CPRepeat, &attrs); - XRenderComposite (FRAME_X_DISPLAY (f), - PictOpSrc, stipple, - None, FRAME_X_PICTURE (f), - x, y, 0, 0, x, y, width, height); + XRenderFillRectangle (FRAME_X_DISPLAY (f), PictOpSrc, + FRAME_X_PICTURE (f), + &alpha, x, y, width, height); + + fill = XRenderCreateSolidFill (FRAME_X_DISPLAY (f), &xc); + + XRenderComposite (FRAME_X_DISPLAY (f), PictOpOver, fill, stipple, + FRAME_X_PICTURE (f), 0, 0, x, y, x, y, width, height); XRenderFreePicture (FRAME_X_DISPLAY (f), stipple); XRenderFreePicture (FRAME_X_DISPLAY (f), fill); } else #endif - XRenderFillRectangle (FRAME_X_DISPLAY (f), - PictOpSrc, FRAME_X_PICTURE (f), - &xc, x, y, width, height); + { + x_xrender_color_from_gc_foreground (f, gc, &xc, true); + XRenderFillRectangle (FRAME_X_DISPLAY (f), + PictOpSrc, FRAME_X_PICTURE (f), + &xc, x, y, width, height); + } x_xr_reset_ext_clip (f); x_mark_frame_dirty (f); commit 1f755a74b7a0268aad6a55764f4ceba3ba4063ff Author: Po Lu Date: Fri Feb 18 18:01:58 2022 +0800 Fix a crash on some versions of GTK * src/emacsgtkfixed.c (XSetWMNormalHints): Fix potential arithmetic fault. diff --git a/src/emacsgtkfixed.c b/src/emacsgtkfixed.c index cd5d1d1435..f2c9fa7b7d 100644 --- a/src/emacsgtkfixed.c +++ b/src/emacsgtkfixed.c @@ -183,9 +183,12 @@ XSetWMSizeHints (Display *d, if (hints->flags & PResizeInc) { - if (data[5] % hints->width_inc) + /* Some versions of GTK set PResizeInc even if the + increments are at their initial values. */ + + if (hints->width_inc && data[5] % hints->width_inc) data[5] += (hints->width_inc - (data[5] % hints->width_inc)); - if (data[6] % hints->height_inc) + if (hints->height_inc && data[6] % hints->height_inc) data[6] += (hints->height_inc - (data[6] % hints->height_inc)); } } commit 3306e11107595524bdde90482023077b69e6c733 Merge: ead9c9602c 1e4b04c540 Author: Eli Zaretskii Date: Fri Feb 18 10:38:52 2022 +0200 Merge from origin/emacs-28 1e4b04c Improve documentation of filling and justification commands 9fd396e * lisp/progmodes/subword.el (superword-mode): Doc fix. (Bug#... e303cb1 Fix indexing of module functions that return complex types. commit ead9c9602cda4c53ff73c3c4fee388a930d42c92 Merge: 2ed240296c b30ef09919 Author: Eli Zaretskii Date: Fri Feb 18 10:38:50 2022 +0200 ; Merge from origin/emacs-28 The following commit was skipped: b30ef09 Prevent crashes caused by invalid locale coding systems commit 2ed240296c181cc677caeef1ec33befd8428aa98 Merge: b16aed76cb c8442df581 Author: Eli Zaretskii Date: Fri Feb 18 10:38:47 2022 +0200 Merge from origin/emacs-28 c8442df ; Separate command and concept index in Transient manual 8aa052c ; Fix Transient manual 5b7752a Fix problem with popd for in remote shell buffers 38f6ea1 Import texi source file for transient manual df34929 Update to Org 9.5.2-15-gc5ceb6 commit b16aed76cb2e94dc5a8cb27ba574346a3931ca92 Merge: c2913c30b1 fe27479cad Author: Eli Zaretskii Date: Fri Feb 18 10:38:45 2022 +0200 ; Merge from origin/emacs-28 The following commits were skipped: fe27479 Fix 'exchange-point-and-mark' in 'transient-mark-mode' 2289a7a2 Fix "C-SPC C-SPC" after "C-x C-x" commit c2913c30b16652c72561ce4dfdf841b5b70e9991 Merge: ef1dfd2261 29085a668e Author: Eli Zaretskii Date: Fri Feb 18 10:38:42 2022 +0200 Merge from origin/emacs-28 # Conflicts: # lisp/startup.el commit ef1dfd2261f717136896b73dc96e7c3fbd72c14d Author: Po Lu Date: Fri Feb 18 15:48:50 2022 +0800 Fix blurry text on multiple scale monitor setups * src/pgtkterm.c (pgtk_copy_bits): Preserve window scale factor on temporary surface. (bug#54040) diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 65408801cf..54b65ac54e 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -2927,6 +2927,7 @@ pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect, cairo_t *cr; GdkWindow *window; cairo_surface_t *surface; /* temporary surface */ + int scale; window = gtk_widget_get_window (FRAME_GTK_WIDGET (f)); @@ -2936,6 +2937,9 @@ pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect, FRAME_CR_SURFACE_DESIRED_HEIGHT (f)); + scale = gtk_widget_get_scale_factor (FRAME_GTK_WIDGET (f)); + cairo_surface_set_device_scale (surface, scale, scale); + cr = cairo_create (surface); cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), -src_rect->x, -src_rect->y); commit 1e4b04c54030eeed22b12e4f0928e9cdfda74251 Author: Eli Zaretskii Date: Fri Feb 18 09:47:44 2022 +0200 Improve documentation of filling and justification commands * doc/lispref/text.texi (Filling): * lisp/textmodes/fill.el (fill-region-as-paragraph) (default-justification, set-justification, justify-current-line): Clarify "canonicalization" of spaces and the meaning of justification styles. (Bug#54047) (set-justification-left, set-justification-right) (set-justification-full): Improve wording of doc strings. diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi index 013050c2ad..958da2f360 100644 --- a/doc/lispref/text.texi +++ b/doc/lispref/text.texi @@ -1670,8 +1670,9 @@ filling when @var{justify} is non-@code{nil}. If @var{nosqueeze} is non-@code{nil}, that means to leave whitespace other than line breaks untouched. If @var{squeeze-after} is -non-@code{nil}, it specifies a position in the region, and means don't -canonicalize spaces before that position. +non-@code{nil}, it specifies a position in the region, and means +that whitespace other than line breaks should be left untouched before +that position. In Adaptive Fill mode, this command calls @code{fill-context-prefix} to choose a fill prefix by default. @xref{Adaptive Fill}. diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el index beb30c6e95..ff84c353aa 100644 --- a/lisp/textmodes/fill.el +++ b/lisp/textmodes/fill.el @@ -648,20 +648,27 @@ The break position will be always after LINEBEG and generally before point." (defun fill-region-as-paragraph (from to &optional justify nosqueeze squeeze-after) - "Fill the region as one paragraph. -It removes any paragraph breaks in the region and extra newlines at the end, -indents and fills lines between the margins given by the -`current-left-margin' and `current-fill-column' functions. -\(In most cases, the variable `fill-column' controls the width.) -It leaves point at the beginning of the line following the paragraph. - -Normally performs justification according to the `current-justification' -function, but with a prefix arg, does full justification instead. - -From a program, optional third arg JUSTIFY can specify any type of -justification. Fourth arg NOSQUEEZE non-nil means not to make spaces -between words canonical before filling. Fifth arg SQUEEZE-AFTER, if non-nil, -means don't canonicalize spaces before that position. + "Fill the region as if it were a single paragraph. +This command removes any paragraph breaks in the region and +extra newlines at the end, and indents and fills lines between the +margins given by the `current-left-margin' and `current-fill-column' +functions. (In most cases, the variable `fill-column' controls the +width.) It leaves point at the beginning of the line following the +region. + +Normally, the command performs justification according to +the `current-justification' function, but with a prefix arg, it +does full justification instead. + +When called from Lisp, optional third arg JUSTIFY can specify any +type of justification; see `default-justification' for the possible +values. +Optional fourth arg NOSQUEEZE non-nil means not to make spaces +between words canonical before filling. +Fifth arg SQUEEZE-AFTER, if non-nil, should be a buffer position; it +means canonicalize spaces only starting from that position. +See `canonically-space-region' for the meaning of canonicalization +of spaces. Return the `fill-prefix' used for filling. @@ -1104,6 +1111,10 @@ space does not end a sentence, so don't break a line there." (defcustom default-justification 'left "Method of justifying text not otherwise specified. Possible values are `left', `right', `full', `center', or `none'. +The values `left' and `right' mean lines are lined up at, +respectively, left or right margin, and ragged at the other margin. +`full' means lines are lined up at both margins. `center' means each +line is centered. `none' means no justification or centering. The requested kind of justification is done whenever lines are filled. The `justification' text-property can locally override this variable." :type '(choice (const left) @@ -1133,6 +1144,7 @@ However, it returns nil rather than `none' to mean \"don't justify\"." (defun set-justification (begin end style &optional whole-par) "Set the region's justification style to STYLE. This commands prompts for the kind of justification to use. +See `default-justification' for the possible values and their meaning. If the mark is not active, this command operates on the current paragraph. If the mark is active, it operates on the region. However, if the beginning and end of the region are not at paragraph breaks, they are @@ -1184,7 +1196,8 @@ If the mark is not active, this applies to the current paragraph." (defun set-justification-left (b e) "Make paragraphs in the region left-justified. -This means they are flush at the left margin and ragged on the right. +This means lines are flush (lined up) at the left margin and ragged +on the right. This is usually the default, but see the variable `default-justification'. If the mark is not active, this applies to the current paragraph." (interactive (list (if mark-active (region-beginning) (point)) @@ -1193,7 +1206,8 @@ If the mark is not active, this applies to the current paragraph." (defun set-justification-right (b e) "Make paragraphs in the region right-justified. -This means they are flush at the right margin and ragged on the left. +This means lines are flush (lined up) at the right margin and ragged +on the left. If the mark is not active, this applies to the current paragraph." (interactive (list (if mark-active (region-beginning) (point)) (if mark-active (region-end) (point)))) @@ -1201,7 +1215,7 @@ If the mark is not active, this applies to the current paragraph." (defun set-justification-full (b e) "Make paragraphs in the region fully justified. -This makes lines flush on both margins by inserting spaces between words. +This makes lines be lined up on both margins by inserting spaces between words. If the mark is not active, this applies to the current paragraph." (interactive (list (if mark-active (region-beginning) (point)) (if mark-active (region-end) (point)))) @@ -1236,7 +1250,8 @@ If the mark is not active, this applies to the current paragraph." Normally does full justification: adds spaces to the line to make it end at the column given by `current-fill-column'. Optional first argument HOW specifies alternate type of justification: -it can be `left', `right', `full', `center', or `none'. +it can be `left', `right', `full', `center', or `none'; for their +meaning, see `default-justification'. If HOW is t, will justify however the `current-justification' function says to. If HOW is nil or missing, full justification is done by default. Second arg EOP non-nil means that this is the last line of the paragraph, so commit 9fd396e4d07fb36d111c32c6ad8e67cf6dbaa97e Author: Eli Zaretskii Date: Fri Feb 18 09:01:06 2022 +0200 * lisp/progmodes/subword.el (superword-mode): Doc fix. (Bug#54045) diff --git a/lisp/progmodes/subword.el b/lisp/progmodes/subword.el index b1b78b4d12..e06eb9a6f7 100644 --- a/lisp/progmodes/subword.el +++ b/lisp/progmodes/subword.el @@ -264,8 +264,8 @@ Optional argument ARG is the same as for `capitalize-word'." "Toggle superword movement and editing (Superword mode). Superword mode is a buffer-local minor mode. Enabling it changes -the definition of words such that symbols characters are treated -as parts of words: e.g., in `superword-mode', +the definition of words such that characters which have symbol +syntax are treated as parts of words: e.g., in `superword-mode', \"this_is_a_symbol\" counts as one word. \\{superword-mode-map}" commit 9a9a3390adc7ed286442300d46c87ecfdc764614 Author: Andrew G Cohen Date: Fri Feb 18 14:01:55 2022 +0800 Make sure nnselect search query is properly parsed * lisp/gnus/gnus-search.el (gnus-search-make-spec): The search query should not be interpreted as raw, but whatever the underlying search engine expects. diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index ec4dc4cf50..27b07e3655 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -2188,8 +2188,7 @@ article came from is also searched." (read-from-minibuffer "Query: " nil gnus-search-minibuffer-map nil 'gnus-search-history))) - (cons 'raw - (or (gnus-nnselect-group-p (gnus-group-group-name)) arg)))) + (cons 'raw arg))) (provide 'gnus-search) ;;; gnus-search.el ends here commit 8a924c8b49e6d7db74ec28120c05d3295eaed541 Author: Andrew G Cohen Date: Fri Feb 18 13:56:19 2022 +0800 Fix gnus searching of native servers * lisp/gnus/gnus-group.el (gnus-group-make-search-group): (gnus-group-read-ephemeral-search-group): Find the real server even when the group is native. diff --git a/lisp/gnus/gnus-group.el b/lisp/gnus/gnus-group.el index e59a972350..550f4e940a 100644 --- a/lisp/gnus/gnus-group.el +++ b/lisp/gnus/gnus-group.el @@ -3226,8 +3226,11 @@ non-nil SPECS arg must be an alist with `search-query-spec' and (if (gnus-server-server-name) (list (list (gnus-server-server-name))) (seq-group-by - (lambda (elt) (gnus-method-to-server - (gnus-find-method-for-group elt))) + (lambda (elt) + (if (gnus-group-native-p elt) + (gnus-group-server elt) + (gnus-method-to-server + (gnus-find-method-for-group elt)))) (or gnus-group-marked (if (gnus-group-group-name) (list (gnus-group-group-name)) @@ -3278,8 +3281,11 @@ non-nil SPECS arg must be an alist with `search-query-spec' and (if (gnus-server-server-name) (list (list (gnus-server-server-name))) (seq-group-by - (lambda (elt) (gnus-method-to-server - (gnus-find-method-for-group elt))) + (lambda (elt) + (if (gnus-group-native-p elt) + (gnus-group-server elt) + (gnus-method-to-server + (gnus-find-method-for-group elt)))) (or gnus-group-marked (if (gnus-group-group-name) (list (gnus-group-group-name)) commit e87b07e277a6fe7fc0cca7fa49e68e0d2dcce024 Author: Po Lu Date: Fri Feb 18 13:47:56 2022 +0800 Make treatment of `alpha-background' more consistent * src/xterm.c (x_clear_glyph_string_rect): (x_draw_glyph_string_background): Ignore alpha_background on all cursors. diff --git a/src/xterm.c b/src/xterm.c index 70fa054bcf..930d9cf370 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -2549,9 +2549,7 @@ x_compute_glyph_string_overhangs (struct glyph_string *s) static void x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) { - x_clear_rectangle (s->f, s->gc, x, y, w, h, - (s->first_glyph->type != STRETCH_GLYPH - || s->hl != DRAW_CURSOR)); + x_clear_rectangle (s->f, s->gc, x, y, w, h, s->hl != DRAW_CURSOR); } @@ -2580,7 +2578,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) s->y + box_line_width, s->background_width, s->height - 2 * box_line_width, - true); + s->hl != DRAW_CURSOR); XSetFillStyle (display, s->gc, FillSolid); s->background_filled_p = true; } @@ -4246,7 +4244,7 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h) /* Fill background with a stipple pattern. */ XSetFillStyle (display, s->gc, FillOpaqueStippled); - x_fill_rectangle (s->f, s->gc, x, y, w, h, false); + x_fill_rectangle (s->f, s->gc, x, y, w, h, true); XSetFillStyle (display, s->gc, FillSolid); } else commit 86ebc88cd8e54c6013c458c513cd21510942d133 Author: Eric Abrahamsen Date: Thu Feb 17 21:28:40 2022 -0800 Fix gnus-search-run-search methods * lisp/gnus/gnus-search.el (gnus-search-run-search): Both these implementations were setting the current buffer and then not setting it back. diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index 1e927ca922..ec4dc4cf50 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -1346,16 +1346,14 @@ This method is common to all indexed search engines. Returns a list of [group article score] vectors." - (save-excursion - (let* ((qstring (gnus-search-make-query-string engine query)) - (program (slot-value engine 'program)) - (buffer (slot-value engine 'proc-buffer)) - (cp-list (gnus-search-indexed-search-command - engine qstring query groups)) - proc exitstatus) - (set-buffer buffer) + (let* ((qstring (gnus-search-make-query-string engine query)) + (program (slot-value engine 'program)) + (buffer (slot-value engine 'proc-buffer)) + (cp-list (gnus-search-indexed-search-command + engine qstring query groups)) + proc exitstatus) + (with-current-buffer buffer (erase-buffer) - (if groups (gnus-message 7 "Doing %s query on %s..." program groups) (gnus-message 7 "Doing %s query..." program)) @@ -1374,7 +1372,7 @@ Returns a list of [group article score] vectors." ;; wants it. (when (> gnus-verbose 6) (display-buffer buffer)) - nil)))) + nil)))) (cl-defmethod gnus-search-indexed-parse-output ((engine gnus-search-indexed) server query &optional groups) @@ -1628,17 +1626,17 @@ Namazu provides a little more information, for instance a score." (cp-list (gnus-search-indexed-search-command engine qstring query groups)) thread-ids proc) - (set-buffer proc-buffer) - (erase-buffer) - (setq proc (apply #'start-process (format "search-%s" server) - proc-buffer program cp-list)) - (while (process-live-p proc) - (accept-process-output proc)) - (goto-char (point-min)) - (while (re-search-forward - "^thread:\\([^[:space:]\n]+\\)" - (point-max) t) - (cl-pushnew (match-string 1) thread-ids :test #'equal)) + (with-current-buffer proc-buffer + (erase-buffer) + (setq proc (apply #'start-process (format "search-%s" server) + proc-buffer program cp-list)) + (while (process-live-p proc) + (accept-process-output proc)) + (goto-char (point-min)) + (while (re-search-forward + "^thread:\\([^[:space:]\n]+\\)" + (point-max) t) + (cl-pushnew (match-string 1) thread-ids :test #'equal))) (cl-call-next-method engine server ;; If we found threads, completely replace the query with commit 7938410ac0fc17858a7195ecf4b9c19d3b0497e7 Author: Po Lu Date: Fri Feb 18 10:34:20 2022 +0800 Make stipple backgrounds respect `alpha-background' * src/xterm.c (x_fill_rectangle): Respect `alpha-background' when drawing stipple. diff --git a/src/xterm.c b/src/xterm.c index e3e67f23c6..70fa054bcf 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -1409,11 +1409,52 @@ x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height, { XRenderColor xc; +#if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10) + XGCValues xgcv; + XRenderPictureAttributes attrs; + XRenderColor alpha; + Picture stipple, fill; +#endif + x_xr_apply_ext_clip (f, gc); x_xrender_color_from_gc_foreground (f, gc, &xc, true); - XRenderFillRectangle (FRAME_X_DISPLAY (f), - PictOpSrc, FRAME_X_PICTURE (f), - &xc, x, y, width, height); + +#if RENDER_MAJOR > 0 || (RENDER_MINOR >= 10) + XGetGCValues (FRAME_X_DISPLAY (f), + gc, GCFillStyle | GCStipple, &xgcv); + + if (xgcv.fill_style == FillOpaqueStippled + && FRAME_CHECK_XR_VERSION (f, 0, 10)) + { + alpha.red = 65535 * f->alpha_background; + alpha.green = 65535 * f->alpha_background; + alpha.blue = 65535 * f->alpha_background; + alpha.alpha = 65535 * f->alpha_background; + + fill = XRenderCreateSolidFill (FRAME_X_DISPLAY (f), + &alpha); + attrs.repeat = RepeatNormal; + attrs.alpha_map = fill; + + stipple = XRenderCreatePicture (FRAME_X_DISPLAY (f), + xgcv.stipple, + XRenderFindStandardFormat (FRAME_X_DISPLAY (f), + PictStandardA1), + CPRepeat, &attrs); + + XRenderComposite (FRAME_X_DISPLAY (f), + PictOpSrc, stipple, + None, FRAME_X_PICTURE (f), + x, y, 0, 0, x, y, width, height); + + XRenderFreePicture (FRAME_X_DISPLAY (f), stipple); + XRenderFreePicture (FRAME_X_DISPLAY (f), fill); + } + else +#endif + XRenderFillRectangle (FRAME_X_DISPLAY (f), + PictOpSrc, FRAME_X_PICTURE (f), + &xc, x, y, width, height); x_xr_reset_ext_clip (f); x_mark_frame_dirty (f); @@ -2539,7 +2580,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) s->y + box_line_width, s->background_width, s->height - 2 * box_line_width, - false); + true); XSetFillStyle (display, s->gc, FillSolid); s->background_filled_p = true; } commit 1a8b3b639063d0662298c55bd20dc3d129e19476 Author: Po Lu Date: Fri Feb 18 09:37:36 2022 +0800 Fix mis-parsing of certain malformed XBM files * src/image.c (xbm_scan): Return error on a character literal that doesn't start with "\x". diff --git a/src/image.c b/src/image.c index d012fcea6a..e2ba744e0a 100644 --- a/src/image.c +++ b/src/image.c @@ -3719,9 +3719,9 @@ xbm_scan (char **s, char *end, char *sval, int *ival) overflow |= INT_MULTIPLY_WRAPV (value, 16, &value); value += digit; } - - return 0; } + + return 0; } else if (c_isalpha (c) || c == '_') { commit 2236ee40ea78973d9377e845bfd0ee3a58cd4386 Author: Po Lu Date: Fri Feb 18 09:12:48 2022 +0800 Parse XBM images which use character escapes for hex literals * src/image.c (xbm_scan): Implement parsing of hex escapes in character literals. diff --git a/src/image.c b/src/image.c index 5c1bf8d7be..d012fcea6a 100644 --- a/src/image.c +++ b/src/image.c @@ -3681,6 +3681,48 @@ xbm_scan (char **s, char *end, char *sval, int *ival) *ival = value; return overflow ? XBM_TK_OVERFLOW : XBM_TK_NUMBER; } + /* Character literal. XBM images typically contain hex escape + sequences and not actual characters, so we only try to handle + that here. */ + else if (c == '\'') + { + int value = 0, digit; + bool overflow = false; + + if (*s == end) + return 0; + + c = *(*s)++; + + if (c != '\\' || *s == end) + return 0; + + c = *(*s)++; + + if (c == 'x') + { + while (*s < end) + { + c = *(*s)++; + + if (c == '\'') + { + *ival = value; + return overflow ? XBM_TK_OVERFLOW : XBM_TK_NUMBER; + } + + digit = char_hexdigit (c); + + if (digit < 0) + return 0; + + overflow |= INT_MULTIPLY_WRAPV (value, 16, &value); + value += digit; + } + + return 0; + } + } else if (c_isalpha (c) || c == '_') { *sval++ = c; commit 246f627a4125d8b3ae5e88748a439f3f594340b5 Author: Eric Abrahamsen Date: Thu Feb 17 13:09:49 2022 -0800 Fix gnus-search notmuch thread searches * lisp/gnus/gnus-search.el (gnus-search-run-search): Multiple things wrong with collecting thread ids from the search results, and constructing a new search query. (gnus-search-indexed-search-command): Use list appending rather than backtick construction, that was more confusing than it was helpful. diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index 605d8a34e9..1e927ca922 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -1634,13 +1634,20 @@ Namazu provides a little more information, for instance a score." proc-buffer program cp-list)) (while (process-live-p proc) (accept-process-output proc)) - (while (re-search-forward "^thread:\\([^ ]+\\)" (point-max) t) - (push (match-string 1) thread-ids)) + (goto-char (point-min)) + (while (re-search-forward + "^thread:\\([^[:space:]\n]+\\)" + (point-max) t) + (cl-pushnew (match-string 1) thread-ids :test #'equal)) (cl-call-next-method engine server - ;; Completely replace the query with our new thread-based one. - (mapconcat (lambda (thrd) (concat "thread:" thrd)) - thread-ids " or ") + ;; If we found threads, completely replace the query with + ;; our new thread-based one. + (if thread-ids + `((query . ,(mapconcat (lambda (thrd) + (concat "thread:" thrd)) + thread-ids " or "))) + query) nil))) (cl-call-next-method engine server query groups))) @@ -1653,16 +1660,16 @@ Namazu provides a little more information, for instance a score." (let ((limit (alist-get 'limit query)) (thread (alist-get 'thread query))) (with-slots (switches config-file) engine - `(,(format "--config=%s" config-file) - "search" - ,(if thread - "--output=threads" - "--output=files") - "--duplicate=1" ; I have found this necessary, I don't know why. - ,@switches - ,(if limit (format "--limit=%d" limit) "") - ,qstring - )))) + (append + (list (format "--config=%s" config-file) + "search" + (if thread + "--output=threads" + "--output=files")) + (unless thread '("--duplicate=1")) + (when limit (list (format "--limit=%d" limit))) + switches + (list qstring))))) ;;; Mairix interface commit 3d0f5bc219de43ebd1789882bad483720d581a4e Author: Juri Linkov Date: Thu Feb 17 20:28:43 2022 +0200 * lisp/mouse.el (context-menu-entry): Don't create menu for Help commands. Help commands that describe keybindings call context-menu-entry bound to a key. This causes too much trouble when trying to build the context menu in a temporary Help buffer that is not displayed in a window. OTOH, there is no information in context menus useful for Help commands. So `help-buffer-under-preparation' is added to filter out such calls. (bug#53910) diff --git a/lisp/mouse.el b/lisp/mouse.el index 1e205283de..da2ca1c036 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -541,7 +541,9 @@ Some context functions add menu items below the separator." (defvar context-menu-entry `(menu-item ,(purecopy "Context Menu") ,(make-sparse-keymap) - :filter ,(lambda (_) (context-menu-map))) + :filter ,(lambda (_) (unless help-buffer-under-preparation + ;; No need to build menu to describe keys + (context-menu-map)))) "Menu item that creates the context menu and can be bound to a mouse key.") (defvar context-menu-mode-map commit 09ba81f1d26b605c4334c82044b40608a5486c33 Author: Eli Zaretskii Date: Thu Feb 17 19:23:46 2022 +0200 ; * lisp/international/fontset.el (otf-script-alist): Update. diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index 973c637eff..2c81bca705 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -283,7 +283,7 @@ (defvar otf-script-alist) -;; The below was synchronized with the latest Oct 8, 2020 version of +;; The below was synchronized with the latest Sep 12, 2021 version of ;; https://docs.microsoft.com/en-us/typography/opentype/spec/scripttags (setq otf-script-alist '((adlm . adlam) @@ -316,6 +316,7 @@ (copt . coptic) (xsux . cuneiform) (cprt . cypriot) + (cpmn . cypro-minoan) (cyrl . cyrillic) (dsrt . deseret) (deva . devanagari) @@ -339,7 +340,7 @@ (gur2 . gurmukhi) (hani . han) (hang . hangul) - (jamo . hangul) + (jamo . hangul) ; Not recommended; use 'hang' instead. (rohg . hanifi-rohingya) (hano . hanunoo) (hatr . hatran) @@ -389,6 +390,7 @@ (musc . musical-symbol) (mym2 . burmese) (mymr . burmese) + (nand . nandinagari) (nbat . nabataean) (newa . newa) (nko\ . nko) @@ -403,6 +405,7 @@ (sogo . old-sogdian) (sarb . old-south-arabian) (orkh . old-turkic) + (ougr . old-uyghur) (orya . oriya) (ory2 . oriya) (osge . osage) @@ -439,6 +442,7 @@ (takr . takri) (taml . tamil) (tml2 . tamil) + (tnsa . tangsa) (tang . tangut) (telu . telugu) (tel2 . telugu) @@ -447,7 +451,9 @@ (tibt . tibetan) (tfng . tifinagh) (tirh . tirhuta) + (toto . toto) (ugar . ugaritic) + (vith . vithkuqi) (vai\ . vai) (wcho . wancho) (wara . warang-citi) commit 927bebcd4b57303db3c32042e14e2175ab22ab8b Author: Eli Zaretskii Date: Thu Feb 17 16:35:03 2022 +0200 Resurrect innocent joke in byte-opt.el * lisp/emacs-lisp/byte-opt.el: Resurrect innocent joke in a comment. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 3ca0472efb..0a79bf9b79 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -29,7 +29,11 @@ ;; "No matter how hard you try, you can't make a racehorse out of a pig. ;; You can, however, make a faster pig." ;; - +;; Or, to put it another way, the Emacs byte compiler is a VW Bug. This code +;; makes it be a VW Bug with fuel injection and a turbocharger... You're +;; still not going to make it go faster than 70 mph, but it might be easier +;; to get it there. +;; ;; TO DO: ;; ;; ;; An awful lot of functions always return a non-nil value. If they're commit a3c5638db653fe3458256d9e58ba41ff50962b83 Author: Eli Zaretskii Date: Thu Feb 17 16:30:42 2022 +0200 Fix files-tests on MS-Windows * test/lisp/files-tests.el (files-tests-zzdont-rewrite-precious-files): Renamed from 'files-tests-dont-rewrite-precious-files', to fix a subtle problem that breaks 2 tests on MS-Windows. (files-tests-revert-buffer) (files-tests-revert-buffer-with-fine-grain): No need to disable file locking anymore. diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index 5d0a1bc2f3..42b09201de 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1411,7 +1411,10 @@ See ." (equal tmpfile (executable-find (file-name-nondirectory tmpfile))))))) -(ert-deftest files-tests-dont-rewrite-precious-files () +;; Note: we call this test "...-zzdont..." so that it runs near the +;; end, because otherwise the advice it adds to write-region doesn't +;; get removed(??) and breaks the revert-file tests on MS-Windows. +(ert-deftest files-tests-zzdont-rewrite-precious-files () "Test that `file-precious-flag' forces files to be saved by renaming only, rather than modified in-place." (ert-with-temp-file temp-file-name @@ -1540,13 +1543,10 @@ The door of all subtleties! (ert-with-temp-file temp-file-name (with-temp-buffer (insert files-tests-lao) - ;; Disable lock files, since that barfs in - ;; userlock--check-content-unchanged on MS-Windows. - (let (create-lockfiles) - (write-file temp-file-name) - (erase-buffer) - (insert files-tests-tzu) - (revert-buffer t t t)) + (write-file temp-file-name) + (erase-buffer) + (insert files-tests-tzu) + (revert-buffer t t t) (should (compare-strings files-tests-lao nil nil (buffer-substring (point-min) (point-max)) nil nil))))) @@ -1556,13 +1556,10 @@ The door of all subtleties! (ert-with-temp-file temp-file-name (with-temp-buffer (insert files-tests-lao) - ;; Disable lock files, since that barfs in - ;; userlock--check-content-unchanged on MS-Windows. - (let (create-lockfiles) - (write-file temp-file-name) - (erase-buffer) - (insert files-tests-tzu) - (should (revert-buffer-with-fine-grain t t))) + (write-file temp-file-name) + (erase-buffer) + (insert files-tests-tzu) + (should (revert-buffer-with-fine-grain t t)) (should (compare-strings files-tests-lao nil nil (buffer-substring (point-min) (point-max)) nil nil))))) commit c1111e944784f68593964e528a9bd0dd6a6314fb Author: Mattias Engdegård Date: Thu Feb 17 14:39:42 2022 +0100 Fix or remove outdated comments * src/eval.c (funcall_lambda): Rewrite obsolete comment. * src/bytecode.c (exec_byte_code): Remove lying comment and unneeded #define. * lisp/emacs-lisp/byte-opt.el: Remove car. Keep pig. (byte-compile-log-lap-1): Remove obsolete and irrelevant comment. diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index 25898285fa..3ca0472efb 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -29,11 +29,6 @@ ;; "No matter how hard you try, you can't make a racehorse out of a pig. ;; You can, however, make a faster pig." ;; -;; Or, to put it another way, the Emacs byte compiler is a VW Bug. This code -;; makes it be a VW Bug with fuel injection and a turbocharger... You're -;; still not going to make it go faster than 70 mph, but it might be easier -;; to get it there. -;; ;; TO DO: ;; @@ -74,10 +69,6 @@ (eval-when-compile (require 'subr-x)) (defun byte-compile-log-lap-1 (format &rest args) - ;; Newer byte codes for stack-ref make the slot 0 non-nil again. - ;; But the "old disassembler" is *really* ancient by now. - ;; (if (aref byte-code-vector 0) - ;; (error "The old version of the disassembler is loaded. Reload new-bytecomp as well")) (byte-compile-log-1 (apply #'format-message format (let (c a) diff --git a/src/bytecode.c b/src/bytecode.c index bda9a39b7f..96f1f90581 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -458,17 +458,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, #ifdef BYTE_CODE_THREADED - /* A convenience define that saves us a lot of typing and makes - the table clearer. */ -#define LABEL(OP) [OP] = &&insn_ ## OP - /* This is the dispatch table for the threaded interpreter. */ static const void *const targets[256] = { [0 ... (Bconstant - 1)] = &&insn_default, [Bconstant ... 255] = &&insn_Bconstant, -#define DEFINE(name, value) LABEL (name) , +#define DEFINE(name, value) [name] = &&insn_ ## name, BYTE_CODES #undef DEFINE }; diff --git a/src/eval.c b/src/eval.c index 7472e649af..d3342289fb 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3243,19 +3243,15 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, else if (COMPILEDP (fun)) { syms_left = AREF (fun, COMPILED_ARGLIST); + /* Bytecode objects using lexical binding have an integral + ARGLIST slot value: pass the arguments to the byte-code + engine directly. */ if (FIXNUMP (syms_left)) - /* A byte-code object with an integer args template means we - shouldn't bind any arguments, instead just call the byte-code - interpreter directly; it will push arguments as necessary. - - Byte-code objects with a nil args template (the default) - have dynamically-bound arguments, and use the - argument-binding code below instead (as do all interpreted - functions, even lexically bound ones). */ - { - return fetch_and_exec_byte_code (fun, XFIXNUM (syms_left), - nargs, arg_vector); - } + return fetch_and_exec_byte_code (fun, XFIXNUM (syms_left), + nargs, arg_vector); + /* Otherwise the bytecode object uses dynamic binding and the + ARGLIST slot contains a standard formal argument list whose + variables are bound dynamically below. */ lexenv = Qnil; } #ifdef HAVE_MODULES commit df6e989f7ab1044e6f98be4b503761af07cd370b Author: Stefan Monnier Date: Thu Feb 17 08:37:24 2022 -0500 * lisp/face-remap.el: Fix bug#53294 * lisp/face-remap.el (face-remap--copy-face): New function. (face-attrs--make-indirect-safe): Use it. diff --git a/lisp/face-remap.el b/lisp/face-remap.el index 34cd030652..eb4f6b9534 100644 --- a/lisp/face-remap.el +++ b/lisp/face-remap.el @@ -70,16 +70,28 @@ :foreground :background :stipple :overline :strike-through :box :font :inherit :fontset :distant-foreground :extend :vector]) +(defun face-remap--copy-face (val) + "Return a copy of the `face' property value VAL." + ;; A `face' property can be either a face name (a symbol), or a face + ;; property list like (:foreground "red" :inherit default), + ;; or a list of such things. + ;; FIXME: This should probably be shared to some extent with + ;; `add-face-text-property'. + (if (or (not (listp val)) (keywordp (car val))) + val + (copy-sequence val))) + (defun face-attrs--make-indirect-safe () "Deep-copy the buffer's `face-remapping-alist' upon cloning the buffer." (setq-local face-remapping-alist - (mapcar #'copy-sequence face-remapping-alist))) + (mapcar #'face-remap--copy-face face-remapping-alist))) (add-hook 'clone-indirect-buffer-hook #'face-attrs--make-indirect-safe) (defun face-attrs-more-relative-p (attrs1 attrs2) - "Return true if ATTRS1 contains a greater number of relative -face-attributes than ATTRS2. A face attribute is considered + "Return non-nil if ATTRS1 is \"more relative\" than ATTRS2. +We define this as meaning that ATTRS1 contains a greater number of +relative face-attributes than ATTRS2. A face attribute is considered relative if `face-attribute-relative-p' returns non-nil. ATTRS1 and ATTRS2 may be any value suitable for a `face' text @@ -106,7 +118,7 @@ face lists so that more specific faces are located near the end." "Order ENTRY so that more relative face specs are near the beginning. The list structure of ENTRY may be destructively modified." (setq entry (nreverse entry)) - (setcdr entry (sort (cdr entry) 'face-attrs-more-relative-p)) + (setcdr entry (sort (cdr entry) #'face-attrs-more-relative-p)) (nreverse entry)) ;;;###autoload commit a6b7bb2dfd8dd436a1d845e35bedf910405c918b Author: Eli Zaretskii Date: Thu Feb 17 15:26:37 2022 +0200 Speed up exiting "emacs -Q" * lisp/files.el (files--buffers-needing-to-be-saved): Don't call functions from seq.el. Using seq.el has an annoying side-effect of slowing down "C-x C-c" from "emacs -Q" due to the need to load seq.el. diff --git a/lisp/files.el b/lisp/files.el index b2792818e6..a0501cffa1 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -5826,23 +5826,26 @@ of the directory that was default during command invocation." (defun files--buffers-needing-to-be-saved (pred) "Return a list of buffers to save according to PRED. See `save-some-buffers' for PRED values." - (seq-filter - (lambda (buffer) - ;; Note that killing some buffers may kill others via - ;; hooks (e.g. Rmail and its viewing buffer). - (and (buffer-live-p buffer) - (buffer-modified-p buffer) - (not (buffer-base-buffer buffer)) - (or - (buffer-file-name buffer) - (with-current-buffer buffer - (or (eq buffer-offer-save 'always) - (and pred buffer-offer-save - (> (buffer-size) 0))))) - (or (not (functionp pred)) - (with-current-buffer buffer - (funcall pred))))) - (buffer-list))) + (let ((buffers + (mapcar (lambda (buffer) + (if + ;; Note that killing some buffers may kill others via + ;; hooks (e.g. Rmail and its viewing buffer). + (and (buffer-live-p buffer) + (buffer-modified-p buffer) + (not (buffer-base-buffer buffer)) + (or + (buffer-file-name buffer) + (with-current-buffer buffer + (or (eq buffer-offer-save 'always) + (and pred buffer-offer-save + (> (buffer-size) 0))))) + (or (not (functionp pred)) + (with-current-buffer buffer + (funcall pred)))) + buffer)) + (buffer-list)))) + (delq nil buffers))) (defun save-some-buffers (&optional arg pred) "Save some modified file-visiting buffers. Asks user about each one. commit e303cb18077538b5ec32e73ce8def958d40c361f Author: Philipp Stephani Date: Thu Feb 17 14:02:28 2022 +0100 Fix indexing of module functions that return complex types. Return types that consist of more than one word need to be enclosed in braces, see Info node `(texinfo) Typed Functions'. Otherwise they are indexed incorrectly. * doc/lispref/internals.texi (Module Values): Enclose multi-word return types in braces. diff --git a/doc/lispref/internals.texi b/doc/lispref/internals.texi index 33664d949a..39e26aaf8f 100644 --- a/doc/lispref/internals.texi +++ b/doc/lispref/internals.texi @@ -1629,7 +1629,7 @@ This function returns the value of a Lisp float specified by @var{arg}, as a C @code{double} value. @end deftypefn -@deftypefn Function struct timespec extract_time (emacs_env *@var{env}, emacs_value @var{arg}) +@deftypefn Function {struct timespec} extract_time (emacs_env *@var{env}, emacs_value @var{arg}) This function, which is available since Emacs 27, interprets @var{arg} as an Emacs Lisp time value and returns the corresponding @code{struct timespec}. @xref{Time of Day}. @code{struct timespec} represents a @@ -1934,7 +1934,7 @@ garbage-collected. Don't run any expensive code in a finalizer, because GC must finish quickly to keep Emacs responsive. @end deftypefn -@deftypefn Function void *get_user_ptr (emacs_env *@var{env}, emacs_value @var{arg}) +@deftypefn Function {void *}get_user_ptr (emacs_env *@var{env}, emacs_value @var{arg}) This function extracts the C pointer from the Lisp object represented by @var{arg}. @end deftypefn commit 64eb2a5f8d3176c4e790c9bea9e753ba9bf9593b Author: Po Lu Date: Thu Feb 17 20:44:53 2022 +0800 Fix crash when displaying XBM images on a 32-bit visual * src/image.c (Create_Pixmap_From_Bitmap_Data): Fix use of wrong (default) depth. diff --git a/src/image.c b/src/image.c index e511326935..5c1bf8d7be 100644 --- a/src/image.c +++ b/src/image.c @@ -3804,7 +3804,7 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data, data, img->width, img->height, fg, bg, - DefaultDepthOfScreen (FRAME_X_SCREEN (f))); + FRAME_DISPLAY_INFO (f)->n_planes); # if !defined USE_CAIRO && defined HAVE_XRENDER if (img->pixmap) img->picture = x_create_xrender_picture (f, img->pixmap, 0); commit 7e6fa8ed385a9fc096f037bcea17c18220fa69f1 Author: Po Lu Date: Thu Feb 17 12:35:39 2022 +0000 Implement XBM images on Haiku * src/image.c (image_create_bitmap_from_data): Handle allocation failures on Haiku. (Create_Pixmap_From_Bitmap_Data): Implement for Haiku. diff --git a/src/image.c b/src/image.c index 3c521e413a..e511326935 100644 --- a/src/image.c +++ b/src/image.c @@ -543,6 +543,10 @@ image_create_bitmap_from_data (struct frame *f, char *bits, #ifdef HAVE_HAIKU void *bitmap = BBitmap_new (width, height, 1); + + if (!bitmap) + return -1; + BBitmap_import_mono_bits (bitmap, bits, width, height); #endif @@ -3815,6 +3819,21 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data, convert_mono_to_color_image (f, img, fg, bg); #elif defined HAVE_NS img->pixmap = ns_image_from_XBM (data, img->width, img->height, fg, bg); +#elif defined HAVE_HAIKU + img->pixmap = BBitmap_new (img->width, img->height, 0); + + if (img->pixmap) + { + int bytes_per_line = (img->width + 7) / 8; + + for (int y = 0; y < img->height; y++) + { + for (int x = 0; x < img->width; x++) + PUT_PIXEL (img->pixmap, x, y, + (data[x / 8] >> (x % 8)) & 1 ? fg : bg); + data += bytes_per_line; + } + } #endif } @@ -3999,6 +4018,7 @@ xbm_load_image (struct frame *f, struct image *img, char *contents, char *end) rc = xbm_read_bitmap_data (f, contents, end, &img->width, &img->height, &data, 0); + if (rc) { unsigned long foreground = img->face_foreground; commit c218660d66394ba8306d21dcc182b82b15ba42de Author: Lars Ingebrigtsen Date: Thu Feb 17 12:57:15 2022 +0100 Add a NEWS entry for the bookmark changes (bug#54030) * lisp/bookmark.el (bookmark-bmenu-mode): Make the type shorter. diff --git a/etc/NEWS b/etc/NEWS index 0bc0b120a9..706c88d67b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -991,6 +991,11 @@ support for pipelines which will move a lot of data. See section ** Miscellaneous +--- +*** 'list-bookmarks' now includes a type column. +Types are registered via a 'bookmark-handler-type' symbol property on +the jumping function. + --- *** 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 61c532c1f3..2751731817 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -1903,7 +1903,7 @@ Bookmark names preceded by a \"*\" have annotations. (setq tabulated-list-format `[("" 1) ;; Space to add "*" for bookmark with annotation ("Bookmark" ,bookmark-bmenu-file-column bookmark-bmenu--name-predicate) - ("Type" 15 bookmark-bmenu--type-predicate) + ("Type" 8 bookmark-bmenu--type-predicate) ,@(if bookmark-bmenu-toggle-filenames '(("File" 0 bookmark-bmenu--file-predicate)))]) (setq tabulated-list-padding bookmark-bmenu-marks-width) commit a1617f070baf64de4c0b10e56a3c3659f224690e Author: Matthias Meulien Date: Wed Feb 16 08:49:07 2022 +0100 Don't prefix bookmark name with VC backend name * lisp/vc/vc-dir.el (vc-dir-bookmark-make-record): Remove prefix from bookmark name. diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el index 944b409ea2..0d750515c3 100644 --- a/lisp/vc/vc-dir.el +++ b/lisp/vc/vc-dir.el @@ -1538,9 +1538,8 @@ These are the commands available for use in the file status buffer: This implements the `bookmark-make-record-function' type for `vc-dir' buffers." (let* ((bookmark-name - (concat "(" (symbol-name vc-dir-backend) ") " - (file-name-nondirectory - (directory-file-name default-directory)))) + (file-name-nondirectory + (directory-file-name default-directory))) (defaults (list bookmark-name default-directory))) `(,bookmark-name ,@(bookmark-make-record-default 'no-file) commit 7c995264359824cc1aca40ca37201db5ed44e659 Author: Matthias Meulien Date: Tue Feb 15 23:39:02 2022 +0100 Extend bookmark menu with with handler type column * lisp/bookmark.el (bookmark-bmenu--revert): Extend table entries with handler type. (bookmark-bmenu-mode): Add handler type column. * lisp/doc-view.el (doc-view-bookmark-jump): Set bookmark handler type. * lisp/help-mode.el (help-bookmark-jump): Set bookmark handler type. * lisp/image-dired.el (image-dired-bookmark-jump): Set bookmark handler type. * lisp/info.el (Info-bookmark-jump): Set bookmark handler type. * lisp/net/eww.el (eww-bookmark-jump): Set bookmark handler type. * lisp/vc/vc-dir.el (vc-dir-bookmark-jump): Set bookmark handler type. * lisp/woman.el (woman-bookmark-jump): Set bookmark handler type. diff --git a/lisp/bookmark.el b/lisp/bookmark.el index 8753326881..61c532c1f3 100644 --- a/lisp/bookmark.el +++ b/lisp/bookmark.el @@ -344,6 +344,17 @@ This point is in `bookmark-current-buffer'.") BOOKMARK-RECORD is, e.g., one element from `bookmark-alist'." (car bookmark-record)) +(defun bookmark-type-from-full-record (bookmark-record) + "Return then type of BOOKMARK-RECORD. +BOOKMARK-RECORD is, e.g., one element from `bookmark-alist'. It's +type is read from the symbol property named +`bookmark-handler-type' read on the record handler function." + (let ((handler (bookmark-get-handler bookmark-record))) + (when (autoloadp (symbol-function handler)) + (autoload-do-load (symbol-function handler))) + (if (symbolp handler) + (get handler 'bookmark-handler-type) + ""))) (defun bookmark-all-names () "Return a list of all current bookmark names." @@ -1351,7 +1362,6 @@ minibuffer history list `bookmark-history'." (bookmark-get-filename bookmark-name-or-record) "-- Unknown location --")) - ;;;###autoload (defun bookmark-rename (old-name &optional new-name) "Change the name of OLD-NAME bookmark to NEW-NAME name. @@ -1790,6 +1800,7 @@ Don't affect the buffer ring order." (let (entries) (dolist (full-record (bookmark-maybe-sort-alist)) (let* ((name (bookmark-name-from-full-record full-record)) + (type (bookmark-type-from-full-record full-record)) (annotation (bookmark-get-annotation full-record)) (location (bookmark-location full-record))) (push (list @@ -1803,6 +1814,7 @@ Don't affect the buffer ring order." 'follow-link t 'help-echo "mouse-2: go to this bookmark in other window") name) + ,(or type "") ,@(if bookmark-bmenu-toggle-filenames (list location))]) entries))) @@ -1891,6 +1903,7 @@ Bookmark names preceded by a \"*\" have annotations. (setq tabulated-list-format `[("" 1) ;; Space to add "*" for bookmark with annotation ("Bookmark" ,bookmark-bmenu-file-column bookmark-bmenu--name-predicate) + ("Type" 15 bookmark-bmenu--type-predicate) ,@(if bookmark-bmenu-toggle-filenames '(("File" 0 bookmark-bmenu--file-predicate)))]) (setq tabulated-list-padding bookmark-bmenu-marks-width) @@ -1905,6 +1918,10 @@ Bookmark names preceded by a \"*\" have annotations. This is used for `tabulated-list-format' in `bookmark-bmenu-mode'." (string< (caar a) (caar b))) +(defun bookmark-bmenu--type-predicate (a b) + "Predicate to sort \"*Bookmark List*\" buffer by the type column. +This is used for `tabulated-list-format' in `bookmark-bmenu-mode'." + (string< (elt (cadr a) 2) (elt (cadr b) 2))) (defun bookmark-bmenu--file-predicate (a b) "Predicate to sort \"*Bookmark List*\" buffer by the file column. diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 4979a2c0e2..193cf42ea4 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -2247,6 +2247,8 @@ 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") + ;; Obsolete. (defun doc-view-intersection (l1 l2) diff --git a/lisp/help-mode.el b/lisp/help-mode.el index 5fb5dcfb19..d1b9357f3c 100644 --- a/lisp/help-mode.el +++ b/lisp/help-mode.el @@ -936,6 +936,7 @@ BOOKMARK is a bookmark name or a bookmark record." (pop-to-buffer "*Help*") (goto-char position))) +(put 'help-bookmark-jump 'bookmark-handler-type "Help") (provide 'help-mode) diff --git a/lisp/image-dired.el b/lisp/image-dired.el index 9b0bbb70df..d8bd2937db 100644 --- a/lisp/image-dired.el +++ b/lisp/image-dired.el @@ -2792,6 +2792,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") ;;; Obsolete diff --git a/lisp/info.el b/lisp/info.el index bb8cd0d312..0565663c38 100644 --- a/lisp/info.el +++ b/lisp/info.el @@ -5449,6 +5449,7 @@ type returned by `Info-bookmark-make-record', which see." (bookmark-default-handler `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bmk))))) +(put 'Info-bookmark-jump 'bookmark-handler-type "Info") ;;;###autoload (defun info-display-manual (manual) diff --git a/lisp/net/eww.el b/lisp/net/eww.el index eaa5c11938..9db07b51db 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -2499,6 +2499,8 @@ Otherwise, the restored buffer will contain a prompt to do so by using "Default bookmark handler for EWW buffers." (eww (bookmark-prop-get bookmark 'location))) +(put 'eww-bookmark-jump 'bookmark-handler-type "EWW") + (provide 'eww) ;;; eww.el ends here diff --git a/lisp/vc/vc-dir.el b/lisp/vc/vc-dir.el index ba6e098d98..944b409ea2 100644 --- a/lisp/vc/vc-dir.el +++ b/lisp/vc/vc-dir.el @@ -1560,6 +1560,8 @@ type returned by `vc-dir-bookmark-make-record'." (bookmark-default-handler `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bmk))))) +(put 'vc-dir-bookmark-jump 'bookmark-handler-type "VC") + (provide 'vc-dir) diff --git a/lisp/woman.el b/lisp/woman.el index e16785329a..c0c8f34348 100644 --- a/lisp/woman.el +++ b/lisp/woman.el @@ -4579,6 +4579,8 @@ logging the message." (bookmark-default-handler `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark))))) +(put 'woman-bookmark-jump 'bookmark-handler-type "WoMan") + ;; Obsolete. (defvar woman-version "0.551 (beta)" "WoMan version information.") commit c78b3c02a3d5bf250bfc9db34745888da44c1543 Author: Protesilaos Stavrou Date: Thu Feb 17 13:15:39 2022 +0200 Update modus-themes to version 2.1.0 * doc/misc/modus-themes.org (Customization Options): Document new user options and relevant changes. (Option for links, Option for box buttons) (Option for completion framework aesthetics, Option for mail citations) (Option for intense markup in Org and others) (Option for diff buffer looks, Option for org-mode block styles) (Option for Org agenda constructs) (Option for the headings' overall style): Update user options. (More accurate colors in terminal emulators): Add section on how to improve the accuracy of color reproduction in terminal emulators. (Case-by-case face specs using the themes' palette) (Face specs at scale using the themes' palette, Override colors) (Override colors through blending, Custom Org user faces): Improve wording. (Custom Org emphasis faces): Add section about bespoke faces for Org emphasis markers. (Backdrop for pdf-tools): Improve sample code. (Ediff without diff color-coding): Add section about user-level changes to the style of Ediff buffers. (Full support for packages or face groups): Update lists of supported packages. (Indirectly covered packages): Update list of indirectly supported packages. (Note on underlines in compilation buffers): Clarify wording. (Note on EWW and Elfeed fonts): Be more specific about 'shr' faces. (Are these color schemes?): Answer frequently asked question. (Acknowledgements): Update acknowledgements' section. * etc/themes/modus-themes.el (modus-themes-operandi-colors) (modus-themes-vivendi-colors): Update color palettes. (modus-themes-subtle-red, modus-themes-subtle-green) (modus-themes-subtle-yellow, modus-themes-subtle-blue) (modus-themes-subtle-magenta, modus-themes-subtle-cyan) (modus-themes-subtle-neutral, modus-themes-intense-red) (modus-themes-intense-green, modus-themes-intense-yellow) (modus-themes-intense-blue, modus-themes-intense-magenta) (modus-themes-intense-cyan, modus-themes-intense-neutral) (modus-themes-refine-red, modus-themes-refine-green) (modus-themes-refine-yellow, modus-themes-refine-blue) (modus-themes-refine-magenta, modus-themes-refine-cyan) (modus-themes-nuanced-red, modus-themes-nuanced-green) (modus-themes-nuanced-yellow, modus-themes-nuanced-blue) (modus-themes-nuanced-magenta, modus-themes-nuanced-cyan) (modus-themes-special-cold, modus-themes-special-mild) (modus-themes-special-warm, modus-themes-special-calm) (modus-themes-diff-added, modus-themes-diff-changed) (modus-themes-diff-removed, modus-themes-diff-refine-added) (modus-themes-diff-refine-changed, modus-themes-diff-refine-removed) (modus-themes-diff-focus-added, modus-themes-diff-focus-changed) (modus-themes-diff-focus-removed, modus-themes-diff-heading) (modus-themes-heading-1, modus-themes-heading-2, modus-themes-heading-3) (modus-themes-heading-4, modus-themes-heading-5, modus-themes-heading-6) (modus-themes-heading-7, modus-themes-heading-8, modus-themes-hl-line) (modus-themes-variable-pitch, modus-themes-lang-note) (modus-themes-lang-warning, modus-themes-lang-error) (modus-themes-reset-soft, modus-themes-reset-hard): Fix typo in ':group'. (modus-themes-markup-code): Add face. (modus-themes--headings-choice, modus-themes-headings) (modus-themes-org-agenda): Update documentation about typographic weights. (modus-themes-org-blocks, modus-themes-completions): Update doc string and add new stylistic variant. (modus-themes-intense-markup): Deprecate old user option. Replace it with 'modus-themes-markup'. (modus-themes-mail-citations): Update doc string and add another stylistic variant. (modus-themes-box-buttons): Add new user option. (modus-themes--slant): Tweak how slant is applied. (modus-themes--markup, modus-themes--prompt, modus-themes--paren) (modus-themes--syntax-foreground, modus-themes--syntax-extra) (modus-themes--syntax-string, modus-themes--syntax-comment) (modus-themes--heading, modus-themes--agenda-structure) (modus-themes--agenda-habit, modus-themes--org-block-delim) (modus-themes--mode-line-attrs, modus-themes--standard-completions) (modus-themes--link, modus-themes--link-color, modus-themes--region) (modus-themes--hl-line, modus-themes--mail-cite): Tweak private functions. (modus-themes--button): Adjust private function. (modus-themes--heading-weights): Deprecate it. Replace by 'modus-themes-weights'. (modus-themes-faces): Update faces. * etc/themes/modus-vivendi-theme.el * etc/themes/modus-operandi-theme.el: Bump version number. For a detailed change log, read: . diff --git a/doc/misc/modus-themes.org b/doc/misc/modus-themes.org index 35bc8853fd..a3bc468413 100644 --- a/doc/misc/modus-themes.org +++ b/doc/misc/modus-themes.org @@ -5,9 +5,9 @@ #+options: ':t toc:nil author:t email:t num:t #+startup: content -#+macro: stable-version 2.0.0 -#+macro: release-date 2021-12-24 -#+macro: development-version 2.1.0-dev +#+macro: stable-version 2.1.0 +#+macro: release-date 2022-02-17 +#+macro: development-version 2.2.0-dev #+macro: file @@texinfo:@file{@@$1@@texinfo:}@@ #+macro: space @@texinfo:@: @@ #+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@ @@ -42,7 +42,7 @@ Current development target is {{{development-version}}}. :custom_id: h:b14c3fcb-13dd-4144-9d92-2c58b3ed16d3 :end: -Copyright (C) 2020-2022 Free Software Foundation, Inc. +Copyright (C) 2020-2022 Free Software Foundation, Inc. #+begin_quote Permission is granted to copy, distribute and/or modify this document @@ -416,7 +416,6 @@ this manual. modus-themes-bold-constructs nil modus-themes-mixed-fonts nil modus-themes-subtle-line-numbers nil - modus-themes-intense-markup t modus-themes-deuteranopia t modus-themes-tabs-accented t modus-themes-variable-pitch-ui nil @@ -435,6 +434,11 @@ this manual. ;; `accented', and a natural number for extra padding modus-themes-mode-line '(4 accented borderless) + ;; Options for `modus-themes-markup' are either nil, or a list + ;; that can combine any of `bold', `italic', `background', + ;; `intense'. + modus-themes-markup '(background italic) + ;; Options for `modus-themes-syntax' are either nil (the default), ;; or a list of properties that may include any of those symbols: ;; `faint', `yellow-comments', `green-strings', `alt-syntax' @@ -456,14 +460,21 @@ this manual. ;; `bold', `italic', `background' modus-themes-links '(neutral-underline background) + ;; Options for `modus-themes-box-buttons' are either nil (the + ;; default), or a list that can combine any of `flat', `accented', + ;; `faint', `variable-pitch', `underline', the symbol of any font + ;; weight as listed in `modus-themes-weights', and a floating + ;; point number (e.g. 0.9) for the height of the button's text. + modus-themes-box-buttons '(variable-pitch flat faint 0.9) + ;; Options for `modus-themes-prompts' are either nil (the ;; default), or a list of properties that may include any of those ;; symbols: `background', `bold', `gray', `intense', `italic' modus-themes-prompts '(intense bold) - modus-themes-completions 'moderate ; {nil,'moderate,'opinionated} + modus-themes-completions 'moderate ; {nil,'moderate,'opinionated,'super-opinionated} - modus-themes-mail-citations nil ; {nil,'faint,'monochrome} + modus-themes-mail-citations nil ; {nil,'intense,'faint,'monochrome} ;; Options for `modus-themes-region' are either nil (the default), ;; or a list of properties that may include any of those symbols: @@ -711,7 +722,7 @@ possible options are ~org-variable-pitch~ and ~mixed-pitch~. :properties: :alt_title: Link styles :description: Choose among several styles, with or without underline -:custom_id: h:c119d7b2-fcd4-4e44-890e-5e25733d5e52 +:custom_id: h:5808be52-361a-4d18-88fd-90129d206f9b :end: #+vindex: modus-themes-links @@ -780,6 +791,89 @@ controlled by ~x-use-underline-position-properties~, ~x-underline-at-descent-line~, ~underline-minimum-offset~. Please refer to their documentation strings. +** Option for box buttons +:properties: +:alt_title: Box buttons +:description: Choose among several styles for buttons +:custom_id: h:8b85f711-ff40-45b0-b7fc-4727503cd2ec +:end: +#+vindex: modus-themes-box-buttons + +Brief: Control the style of buttons in the Custom UI and related. + +Symbol: ~modus-themes-box-buttons~ (=choice= type, list of properties) + +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: + ++ ~flat~ ++ ~accented~ ++ ~faint~ ++ ~variable-pitch~ ++ ~underline~ ++ A font weight, which must be supported by the underlying typeface: + - ~thin~ + - ~ultralight~ + - ~extralight~ + - ~light~ + - ~semilight~ + - ~regular~ + - ~medium~ + - ~semibold~ + - ~bold~ + - ~heavy~ + - ~extrabold~ + - ~ultrabold~ ++ A floating point as a height multiple of the default (e.g. =0.9=) + +The default (a nil value or an empty list) is a gray background combined +with a pseudo three-dimensional effect. + +The ~flat~ property makes the button two dimensional. + +The ~accented~ property changes the background from gray to an accent +color. + +The ~faint~ property reduces the overall coloration. + +The ~variable-pitch~ property applies a proportionately spaced typeface +to the button~s text. + +[[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]]. + +The ~underline~ property draws a line below the affected text and +removes whatever box effect. This is optimal when Emacs runs inside a +terminal emulator ([[#h:fbb5e254-afd6-4313-bb05-93b3b4f67358][More accurate colors in terminal emulators]]). If +~flat~ and ~underline~ are defined together, the latter takes +precedence. + +The symbol of a weight attribute adjusts the font of the button +accordingly, such as ~light~, ~semibold~, etc. Valid symbols are +defined in the variable ~modus-themes-weights~. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +A number, expressed as a floating point (e.g. =0.9=), adjusts the height +of the button's text to that many times the base font size. The default +height is the same as =1.0=, though it need not be explicitly stated. + +Combinations of any of those properties are expressed as a list, +like in these examples: + +#+begin_src emacs-lisp +(flat) +(variable-pitch flat) +(variable-pitch flat 0.9 semibold) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-box-buttons '(variable-pitch flat 0.9)) +#+end_src + ** Option for command prompt styles :properties: :alt_title: Command prompts @@ -978,35 +1072,39 @@ Possible values: 1. ~nil~ (default) 2. ~moderate~ 3. ~opinionated~ +4. ~super-opinionated~ This is a special option that has different effects depending on the completion UI. The interfaces can be grouped in two categories, based on their default aesthetics: (i) those that only or mostly use foreground colors for their interaction model, and (ii) those that combine background and foreground values for some of their metaphors. -The former category encompasses Icomplete, Ido, Selectrum, Vertico, as -well as pattern matching styles like Orderless and Flx. The latter +The former category encompasses Icomplete, Ido, Selectrum, Vertico, Mct, +as well as pattern matching styles like Orderless and Flx. The latter covers Helm and Ivy. -A value of ~nil~ (the default) will simply respect the metaphors of each +A value of nil (the default) will simply respect the metaphors of each completion framework. Option ~moderate~ applies a combination of background and foreground that is fairly subtle. For Icomplete and friends this constitutes a departure from their default aesthetics, however the difference is -small. While Helm, Ivy et al appear slightly different than their -original looks, as they are toned down a bit. +small. While Helm and Ivy appear slightly different than their original +looks, as they are toned down a bit. Option ~opinionated~ uses color combinations that refashion the completion UI. For the Icomplete camp this means that intense background and -foreground combinations are used: in effect their looks emulate those of -Helm, Ivy and co. in their original style. Whereas the other group of -packages will revert to an even more nuanced aesthetic with some +foreground combinations are used: in effect their looks approximate +those of Helm and Ivy in their original style. Whereas the other group +of packages will revert to an even more nuanced aesthetic with some additional changes to the choice of hues. +Option ~super-opinionated~ is like the ~opinionated~ though it has a more +pronounced effect, especially on the color of the current +line/candidate. + To appreciate the scope of this customization option, you should spend -some time with every one of the ~nil~ (default), ~moderate~, and ~opinionated~ -possibilities. +some time with every one of those presets. ** Option for mail citations :properties: @@ -1024,17 +1122,21 @@ Symbol: ~modus-themes-mail-citations~ (=choice= type) Possible values: 1. ~nil~ (default) -2. ~faint~ -3. ~monochrome~ +2. ~intense~ +3. ~faint~ +4. ~monochrome~ + +By default (a nil value) citations are styled with contrasting hues to +denote their depth. Colors are easy to tell apart because they +complement each other, but they otherwise are not very prominent. -By default, citations in email-related buffers apply contrasting hues to -different levels of depth in cited text. The colors are fairly easy to -tell apart. +Option ~intense~ is similar to the default in terms of using contrasting +and complementary hues, but applies more saturated colors. -A value of ~faint~ makes all citation levels less intense, while retaining -the default style of contrasting hues (albeit very subtle ones). +Option ~faint~ maintains the same color-based distinction between citation +levels though the colors it uses have subtle differences between them. -Option ~monochrome~ turns all citations in to a uniform shade of gray. +Option ~monochrome~ turns all quotes into a shade of gray. Whatever the value assigned to this variable, citations in emails are controlled by typographic elements or indentation, which the themes do @@ -1220,29 +1322,60 @@ Instead they retain the primary background of the theme, blending with the rest of the buffer. Foreground values for all relevant faces are updated to accommodate this aesthetic. -** Option for intense markup in Org and others +** Option for markup style in Org and others :properties: -:alt_title: Intense markup -:description: Toggle intense style for markup in Org and others +:alt_title: Markup +:description: Choose style for markup in Org and others :custom_id: h:9d9a4e64-99ac-4018-8f66-3051b9c43fd7 :end: -#+vindex: modus-themes-intense-markup +#+vindex: modus-themes-markup -Brief: Toggle intense style for inline code and related markup. +Brief: Choose style of markup in Org, Markdown, and others (affects +constructs such as Org's ==verbatim== and =~code~=). -Symbol: ~modus-themes-intense-markup~ (=boolean= type) +Symbol: ~modus-themes-markup~ (=boolean= type) -Possible value: +Possible values are expressed as a list of properties (default is ~nil~ or +an empty list). The list can include any of the following symbols: -1. ~nil~ (default) -2. ~t~ +1. ~bold~ +2. ~italic~ +3. ~background~ +4. ~intense~ + +The ~italic~ property applies a typographic slant (italics). + +The ~bold~ property applies a heavier typographic weight. + +[[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. + +The ~background~ property adds a background color. The background is a +shade of gray, unless the ~intense~ property is also set. -The default style for certain markup types like inline code and verbatim -constructs in Org and related major modes is a subtle foreground color -combined with a subtle background. +The ~intense~ property amplifies the existing coloration. When +~background~ is used, the background color is enhanced as well and +becomes tinted instead of being gray. -With a non-nil value (~t~), these constructs will use a more prominent -background and foreground color combination instead. +Combinations of any of those properties are expressed as a list, +like in these examples: + +#+begin_src emacs-lisp +(bold) +(bold italic) +(bold italic intense) +(bold italic intense background) +#+end_src + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + +#+begin_src emacs-lisp +(setq modus-themes-markup '(bold italic)) +#+end_src + +Also check the variables ~org-hide-emphasis-markers~, +~org-hide-macro-markers~. ** Option for parenthesis matching :properties: @@ -1387,6 +1520,8 @@ contrast threshold. [[#h:e2aed9eb-5e1e-45ec-bbd7-bc4faeab3236][Diffs with only the foreground]]. +[[#h:b0b31802-0216-427e-b071-1a47adcfe608][Ediff without diff color-coding]]. + ** Option for org-mode block styles :properties: :alt_title: Org mode blocks @@ -1405,20 +1540,28 @@ Possible values: 2. ~gray-background~ (value ~grayscale~ exists for backward compatibility) 3. ~tinted-background~ (value ~rainbow~ exists for backward compatibility) -The default means that the block has no distinct background of its own -and uses the one that applies to the rest of the buffer. +Nil (the default) means that the block has no background of its own: it +uses the one that applies to the rest of the buffer. In this case, the +delimiter lines have a gray color for their text, making them look +exactly like all other Org properties. Option ~gray-background~ applies a subtle gray background to the block's -contents. It also affects the begin and end lines of the block: their -background extends to the edge of the window for Emacs version >= 27 -where the ~:extend~ keyword is recognized by ~set-face-attribute~ (this is -contingent on the variable ~org-fontify-whole-block-delimiter-line~). +contents. It also affects the begin and end lines of the block as they +get another shade of gray as their background, which differentiates them +from the contents of the block. All background colors extend to the +edge of the window, giving the area a rectangular, "blocky" +presentation. Option ~tinted-background~ uses a slightly colored background for the contents of the block. The exact color will depend on the programming language and is controlled by the variable ~org-src-block-faces~ (refer to the theme's source code for the current association list). For this to -take effect, Org must be restarted with {{{kbd(M-x org-mode-restart)}}}. +take effect, the Org buffer needs to be restarted with ~org-mode-restart~. +In this scenario, it may be better to inhibit the extension of the +delimiter lines' background to the edge of the window because Org does +not provide a mechanism to update their colors depending on the contents +of the block. Disable the extension of such backgrounds by setting +~org-fontify-whole-block-delimiter-line~ to nil. Code blocks use their major mode's colors only when the variable ~org-src-fontify-natively~ is non-nil. While quote/verse blocks require @@ -1471,10 +1614,10 @@ properties: are present, the default is a small increase in height (a value of 1.15). - The symbol of a weight attribute adjusts the font of the heading - accordingly, such as ~light~, ~semibold~, etc. Valid symbols are defined - in the internal variable ~modus-themes--heading-weights~. The absence - of a weight means that bold will be used by virtue of inheriting the - ~bold~ face. + accordingly, such as ~light~, ~semibold~, etc. Valid symbols are + defined in the variable ~modus-themes-weights~. The absence of a + weight means that bold will be used by virtue of inheriting the ~bold~ + face. [[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. @@ -1594,10 +1737,10 @@ passed as a symbol. Those are: being too late. The difference between ready and clear states is attenuated by painting both of them using shades of green. This option thus highlights the alert and overdue states. -- When ~modus-themes-deuteranopia~ is non-nil the habit graph uses a - three-color style like the aforementioned ~traffic-light~ variant, - except that shades of blue are applied instead of green. This is - suitable for users with red-green color deficiency (deuteranopia). +- When ~modus-themes-deuteranopia~ is non-nil the exact style of the habit + graph adapts to the needs of users with red-green colour deficiency by + substituting every instance of green with blue or cyan (depending on + the specifics). [[#h:3ed03a48-20d8-4ce7-b214-0eb7e4c79abe][Option for red-green color deficiency or deuteranopia]]. @@ -1674,7 +1817,7 @@ Properties: - ~extrabold~ - ~ultrabold~ + ~no-bold~ (deprecated alias of a ~regular~ weight) -+ A floating point as a height multiple of the default ++ A floating point as a height multiple of the default (e.g. =1.1=) By default (a ~nil~ value for this variable), all headings have a bold typographic weight and use a desaturated text color. @@ -1695,10 +1838,10 @@ A ~variable-pitch~ property changes the font family of the heading to that of the ~variable-pitch~ face (normally a proportionately spaced typeface). The symbol of a weight attribute adjusts the font of the heading -accordingly, such as ~light~, ~semibold~, etc. Valid symbols are defined in -the internal variable ~modus-themes--heading-weights~. The absence of a -weight means that bold will be used by virtue of inheriting the ~bold~ -face. For backward compatibility, the ~no-bold~ value is accepted, though +accordingly, such as ~light~, ~semibold~, etc. Valid symbols are +defined in the variable ~modus-themes-weights~. The absence of a weight +means that bold will be used by virtue of inheriting the ~bold~ face. +For backward compatibility, the ~no-bold~ value is accepted, though users are encouraged to specify a ~regular~ weight instead. [[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]. @@ -1793,6 +1936,57 @@ their own local tweaks and who are willing to deal with any possible incompatibilities between versioned releases of the themes. As such, they are labelled as "do-it-yourself" or "DIY". +** More accurate colors in terminal emulators +:PROPERTIES: +:CUSTOM_ID: h:fbb5e254-afd6-4313-bb05-93b3b4f67358 +:END: +#+cindex: Color accuracy of terminal emulators + +[ This is based on partial information. Please help verify and/or + expand these findings. ] + +The graphical version of Emacs can reproduce color values accurately. +Whereas things get more tricky when Emacs is used in a terminal +emulator, because the terminals' own capabilities determine the number +of colors that may be displayed: the Modus themes don't look as good in +that case. + +There is, however, a way to instruct supported terminal emulators to use +more accurate colors. In a shell prompt type =toe -a | grep direct= to +get a list of relevant terminfo entries. There should be items such as +=xterm-direct=, =alacritty-direct=, =kitty-direct=. Once you find the one +that corresponds to your terminal, call Emacs with an environment +variable like =TERM=xterm-direct=. Example that can be adapted to shell +aliases: + +: TERM=xterm-direct emacsclient -nw + +Another example that can be bound to a key: + +: TERM=xterm-direct uxterm -e emacsclient -nw + +** Visualize the active Modus theme's palette +:properties: +:custom_id: h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d +:end: +#+findex: modus-themes-list-colors +#+findex: modus-themes-list-colors-current +#+cindex: Preview color values + +The command ~modus-themes-list-colors~ prompts for a choice between +=modus-operandi= and =modus-vivendi= to produce a help buffer that shows a +preview of each variable in the given theme's color palette. The +command ~modus-themes-list-colors-current~ skips the prompt, using the +current Modus theme. + +Each row shows a foreground and background coloration using the +underlying value it references. For example a line with =#a60000= (a +shade of red) will show red text followed by a stripe with that same +color as a backdrop. + +The name of the buffer describes the given Modus theme. It is thus +called =*modus-operandi-list-colors*= or =*modus-vivendi-list-colors*=. + ** Per-theme customization settings :properties: :custom_id: h:a897b302-8e10-4a26-beab-3caaee1e1193 @@ -1868,7 +2062,11 @@ The function always extracts the color value of the active Modus theme. #+end_src Do {{{kbd(C-h v)}}} on the aforementioned variables to check all the available -symbols that can be passed to this function. +symbols that can be passed to this function. Or simply invoke the +command ~modus-themes-list-colors~ to produce a buffer with a preview of +each entry in the palette. + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. With that granted, let us expand the example to actually change the ~cursor~ face's background property. We employ the built-in function of @@ -1947,7 +2145,10 @@ The ~modus-themes-with-colors~ macro lets you retrieve multiple color values by employing the backquote/backtick and comma notation. The values are stored in the alists ~modus-themes-operandi-colors~ and ~modus-themes-vivendi-colors~, while the macro always queries that of the -active Modus theme. +active Modus theme (preview the current palette with the command +~modus-themes-list-colors~). + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. Here is an abstract example that just returns a list of color values while ~modus-operandi~ is enabled: @@ -2288,6 +2489,8 @@ mirror a subset of the associations in ~modus-themes-operandi-colors~ and ~modus-themes-vivendi-colors~ respectively. As with all customisations, overriding must be done before loading the affected theme. +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. + Let us approach the present topic one step at a time. Here is a simplified excerpt of the default palette for Modus Operandi with some basic background values that apply to buffers and the mode line @@ -2509,6 +2712,71 @@ inspiration from the ~modus-themes-toggle~ we already provide: ('modus-vivendi (modus-themes-load-vivendi)))) #+end_src +** Override colors through blending +:properties: +:custom_id: h:80c326bf-fe32-47b2-8c59-58022256fd6e +:end: +#+cindex: Change theme colors through blending + +This is yet another method of overriding color values. + +[[#h:307d95dd-8dbd-4ece-a543-10ae86f155a6][Override colors]]. + +[[#h:4589acdc-2505-41fc-9f5e-699cfc45ab00][Override color saturation]]. + +Building on ideas and concepts from the previous sections, this method +blends the entire palette at once with the chosen colors. The function +~my-modus-themes-interpolate~ blends two colors, taking a value from the +themes and mixing it with a user-defined color to arrive at a midpoint. +This scales to all background and foreground colors with the help of the +~my-modus-themes-tint-palette~ function. + +#+begin_src emacs-lisp +(setq my-modus-operandi-bg-blend "#fbf1c7" + my-modus-operandi-fg-blend "#3a6084" + my-modus-vivendi-bg-blend "#3a4042" + my-modus-vivendi-fg-blend "#d7b765") + +;; Adapted from the `kurecolor-interpolate' function of kurecolor.el +(defun my-modus-themes-interpolate (color1 color2) + (cl-destructuring-bind (r g b) + (mapcar #'(lambda (n) (* (/ n 2) 255.0)) + (cl-mapcar '+ (color-name-to-rgb color1) (color-name-to-rgb color2))) + (format "#%02X%02X%02X" r g b))) + +(defun my-modus-themes-tint-palette (palette bg-blend fg-blend) + "Modify Modus PALETTE programmatically and return a new palette. +Blend background colors with BG-BLEND and foreground colors with FG-BLEND." + (let (name cons colors) + (dolist (cons palette) + (let ((blend (if (string-match "bg" (symbol-name (car cons))) + bg-blend + fg-blend))) + (setq name (my-modus-themes-interpolate (cdr cons) blend))) + (setq name (format "%s" name)) + (setq cons `(,(car cons) . ,name)) + (push cons colors)) + colors)) + +(define-minor-mode modus-themes-tinted-mode + "Tweak some Modus themes colors." + :init-value nil + :global t + (if modus-themes-tinted-mode + (setq modus-themes-operandi-color-overrides + (my-modus-themes-tint-palette modus-themes-operandi-colors + my-modus-operandi-bg-blend + my-modus-operandi-fg-blend) + modus-themes-vivendi-color-overrides + (my-modus-themes-tint-palette modus-themes-vivendi-colors + my-modus-vivendi-bg-blend + my-modus-vivendi-fg-blend)) + (setq modus-themes-operandi-color-overrides nil + modus-themes-vivendi-color-overrides nil))) + +(modus-themes-tinted-mode 1) +#+end_src + ** Font configurations for Org and others :properties: :custom_id: h:defcf4fc-8fa8-4c29-b12e-7119582cc929 @@ -2670,11 +2938,11 @@ of the themes, which can make it easier to redefine faces in bulk). [[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]. -** Custom Org user faces +** Custom Org todo keyword and priority faces :properties: :custom_id: h:89f0678d-c5c3-4a57-a526-668b2bb2d7ad :end: -#+cindex: Org extra faces +#+cindex: Org custom todo faces Users of ~org-mode~ have the option to configure various keywords and priority cookies to better match their workflow. User options are @@ -2758,6 +3026,139 @@ it if you plan to control face attributes. [[#h:02e25930-e71a-493d-828a-8907fc80f874][Check color combinations]]. +** Custom Org emphasis faces +:properties: +:custom_id: h:26026302-47f4-4471-9004-9665470e7029 +:end: +#+cindex: Org custom emphasis faces + +Org provides the user option ~org-emphasis-alist~ which assosiates a +character with a face, list of faces, or face attributes. The default +specification of that variable looks like this: + +#+begin_src emacs-lisp +(setq org-emphasis-alist + '(("*" bold) + ("/" italic) + ("_" underline) + ("=" org-verbatim verbatim) + ("~" org-code verbatim) + ("+" (:strike-through t)))) +#+end_src + +With the exception of ~org-verbatim~ and ~org-code~ faces, everything else +uses the corresponding type of emphasis: a bold typographic weight, or +italicised, underlined, and struck through text. + +The best way for users to add some extra attributes, such as a +foreground color, is to define their own faces and assign them to the +given emphasis marker/character. + +This is a custom face that extends the standard ~bold~ face with a red +foreground value (so it colorises the text in addition to the bold +weight): + +#+begin_src emacs-lisp +(defface my-org-emphasis-bold + '((default :inherit bold) + (((class color) (min-colors 88) (background light)) + :foreground "#a60000") + (((class color) (min-colors 88) (background dark)) + :foreground "#ff8059")) + "My bold emphasis for Org.") +#+end_src + +This face definition reads as follows: + ++ Always inherit the ~bold~ face ([[#h:2793a224-2109-4f61-a106-721c57c01375][Configure bold and italic faces]]). ++ For versions of Emacs that support at least 88 colors (graphical + Emacs, for example) and use a light background, apply the =#a60000= + value. ++ For the same kind of Emacs that has a dark background use the =#ff8059= + color instead. + +Same principle for how to extend ~italic~ and ~underline~ with, for example, +green and yellow hues, respectively: + +#+begin_src emacs-lisp +(defface my-org-emphasis-italic + '((default :inherit italic) + (((class color) (min-colors 88) (background light)) + :foreground "#005e00") + (((class color) (min-colors 88) (background dark)) + :foreground "#44bc44")) + "My italic emphasis for Org.") + +(defface my-org-emphasis-underline + '((default :inherit underline) + (((class color) (min-colors 88) (background light)) + :foreground "#813e00") + (((class color) (min-colors 88) (background dark)) + :foreground "#d0bc00")) + "My underline emphasis for Org.") +#+end_src + +In the case of a strike-through effect, we have no generic face to +inherit from, so we can write it as follows to also change the +foreground to a more subtle gray: + +#+begin_src emacs-lisp +(defface my-org-emphasis-strike-through + '((default :strike-through t) + (((class color) (min-colors 88) (background light)) + :foreground "#505050") + (((class color) (min-colors 88) (background dark)) + :foreground "#a8a8a8")) + "My strike-through emphasis for Org.") +#+end_src + +Or we can just change the color of the line that strikes through the +text to, for example, a shade of red: + +#+begin_src emacs-lisp +(defface my-org-emphasis-strike-through + '((((class color) (min-colors 88) (background light)) + :strike-through "#972500") + (((class color) (min-colors 88) (background dark)) + :strike-through "#ef8b50")) + "My strike-through emphasis for Org.") +#+end_src + +It is possible to combine those effects: + +#+begin_src emacs-lisp +(defface my-org-emphasis-strike-through + '((((class color) (min-colors 88) (background light)) + :strike-through "#972500" :foreground "#505050") + (((class color) (min-colors 88) (background dark)) + :strike-through "#ef8b50" :foreground "#a8a8a8")) + "My strike-through emphasis for Org.") +#+end_src + +One may inspect the variables ~modus-themes-operandi-colors~ and +~modus-themes-vivendi-colors~ for possible color values. Or call the +command ~modus-themes-list-colors~ to show a buffer that previews each +entry in the palette. + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. + +Once we have defined the faces we need, we must update the +~org-emphasis-alist~. Given that ~org-verbatim~ and ~org-code~ are already +styled by the themes, it probably is best not to edit them: + +#+begin_src emacs-lisp +(setq org-emphasis-alist + '(("*" my-org-emphasis-bold) + ("/" my-org-emphasis-italic) + ("_" my-org-emphasis-underline) + ("=" org-verbatim verbatim) + ("~" org-code verbatim) + ("+" my-org-emphasis-strike-through))) +#+end_src + +That's it! For changes to take effect in already visited Org files, +invoke {{{kbd(M-x org-mode-restart)}}}. + ** Update Org block delimiter fontification :properties: :custom_id: h:f44cc6e3-b0f1-4a5e-8a90-9e48fa557b50 @@ -2954,13 +3355,20 @@ at something like the following, which builds on the above example: (pdf-view-midnight-minor-mode -1)) (my-pdf-tools-backdrop))) +(defun my-pdf-tools-themes-toggle () + (mapc + (lambda (buf) + (with-current-buffer buf + (my-pdf-tools-midnight-mode-toggle))) + (buffer-list))) + (add-hook 'pdf-tools-enabled-hook #'my-pdf-tools-midnight-mode-toggle) -(add-hook 'modus-themes-after-load-theme-hook #'my-pdf-tools-midnight-mode-toggle) +(add-hook 'modus-themes-after-load-theme-hook #'my-pdf-tools-themes-toggle) #+end_src With those in place, PDFs have a distinct backdrop for their page, while -they automatically switch to their dark mode when ~modus-themes-toggle~ is -called from inside a buffer whose major-mode is ~pdf-view-mode~. +buffers with major-mode as ~pdf-view-mode~ automatically switches to dark +mode when ~modus-themes-toggle~ is called. ** Decrease mode line height :properties: @@ -3161,6 +3569,45 @@ This used to be an optional style of ~modus-themes-diffs~, but has been removed since version =2.0.0= to ensure that the accessibility standard and aesthetic quality of the themes is not compromised. +** Ediff without diff color-coding +:properties: +:custom_id: h:b0b31802-0216-427e-b071-1a47adcfe608 +:end: + +Ediff uses the same color-coding as ordinary diffs in ~diff-mode~, Magit, +etc. ([[#h:ea7ac54f-5827-49bd-b09f-62424b3b6427][Option for diff buffer looks]]). This is consistent with the +principle of least surprise. + +Users may, however, prefer to treat Ediff differently on the premise +that it does not need any particular color-coding to show added or +removed lines/words: it does not use the =+= or =-= markers, after all. + +This can be achieved by customizing the Ediff faces with color +combinations that do not carry the same connotations as those of diffs. +Consider this example, which leverages the ~modus-themes-with-colors~ +macro ([[#h:51ba3547-b8c8-40d6-ba5a-4586477fd4ae][Face specs at scale using the themes' palette]]): + +#+begin_src emacs-lisp +(defun my-modus-themes-custom-faces () + (modus-themes-with-colors + (custom-set-faces + `(ediff-current-diff-A ((,class :inherit unspecified :background ,bg-special-faint-cold :foreground ,fg-special-cold))) + `(ediff-current-diff-B ((,class :inherit unspecified :background ,bg-special-faint-warm :foreground ,fg-special-warm))) + `(ediff-current-diff-C ((,class :inherit unspecified :background ,bg-special-faint-calm :foreground ,fg-special-calm))) + `(ediff-fine-diff-A ((,class :inherit unspecified :background ,bg-special-cold :foreground ,fg-special-cold))) + `(ediff-fine-diff-B ((,class :inherit unspecified :background ,bg-special-warm :foreground ,fg-special-warm))) + `(ediff-fine-diff-C ((,class :inherit unspecified :background ,bg-special-calm :foreground ,fg-special-calm)))))) + +;; This is so that the changes persist when switching between +;; `modus-operandi' and `modus-vivendi'. +(add-hook 'modus-themes-after-load-theme-hook #'my-modus-themes-custom-faces) +#+end_src + +Remove the =:foreground= and its value to preserve the underlying +coloration. + +[[#h:f4d4b71b-2ca5-4c3d-b0b4-9bfd7aa7fb4d][Visualize the active Modus theme's palette]]. + * Face coverage :properties: :custom_id: h:a9c8f29d-7f72-4b54-b74b-ddefe15d6a19 @@ -3186,6 +3633,8 @@ have lots of extensions, so the "full support" may not be 100% true… + ace-window + alert + all-the-icons ++ all-the-icons-dired ++ all-the-icons-ibuffer + annotate + ansi-color + anzu @@ -3209,6 +3658,7 @@ have lots of extensions, so the "full support" may not be 100% true… + change-log and log-view (such as ~vc-print-log~, ~vc-print-root-log~) + cider + circe ++ citar + color-rg + column-enforce-mode + company-mode* @@ -3257,6 +3707,7 @@ have lots of extensions, so the "full support" may not be 100% true… + elfeed-score + elpher + embark ++ ement + emms + enh-ruby-mode (enhanced-ruby-mode) + epa @@ -3348,6 +3799,7 @@ have lots of extensions, so the "full support" may not be 100% true… + marginalia + markdown-mode + markup-faces (~adoc-mode~) ++ mct + mentor + messages + minimap @@ -3395,6 +3847,7 @@ have lots of extensions, so the "full support" may not be 100% true… + proced + prodigy + pulse ++ pyim + quick-peek + racket-mode + rainbow-blocks @@ -3417,6 +3870,8 @@ have lots of extensions, so the "full support" may not be 100% true… + side-notes + sieve-mode + skewer-mode ++ slime (slbd) ++ sly + smart-mode-line + smartparens + smerge @@ -3438,6 +3893,7 @@ have lots of extensions, so the "full support" may not be 100% true… + telephone-line + terraform-mode + term ++ textsec + tomatinho + transient (pop-up windows such as Magit's) + trashed @@ -3492,6 +3948,7 @@ supported by the themes. + counsel-org-capture-string + define-word + disk-usage ++ dtache + easy-kill + edit-indirect + evil-owl @@ -3504,6 +3961,7 @@ supported by the themes. + i3wm-config-mode + minibuffer-line + no-emoji ++ org-remark + parrot + perl-mode + php-mode @@ -3597,14 +4055,15 @@ Various buffers that produce compilation results or run tests on code apply an underline to the file names they reference or to relevant messages. Users may consider this unnecessary or excessive. -To outright disable the effect, use this: +To outright disable the effect, use this (buffers need to be generated +anew): #+begin_src emacs-lisp (setq compilation-message-face nil) #+end_src If some element of differentiation is still desired, a good option is to -render the affected text using the ~italic~ face: +render the affected text with the ~italic~ face: #+begin_src emacs-lisp (setq compilation-message-face 'italic) @@ -4075,20 +4534,66 @@ specifications the webpage provides. Consult {{{kbd(C-h v shr-use-colors)}}}. -** Note on EWW and Elfeed fonts +** Note on SHR fonts :properties: :custom_id: h:e6c5451f-6763-4be7-8fdb-b4706a422a4c :end: +#+cindex: Fonts in EWW, Elfeed, Ement, and SHR -EWW and Elfeed rely on the Simple HTML Renderer to display their -content. The {{{file(shr.el)}}} library contains the variable ~shr-use-fonts~ -that controls whether the text in the buffer is set to a ~variable-pitch~ -typeface (proportionately spaced) or if just retains whatever the -default font family is. Its default value is non-nil, which means that -~variable-pitch~ is applied. +By default, packages that build on top of the Simple HTML Remember (=shr=) +use proportionately spaced fonts. This is controlled by the user option +~shr-use-fonts~, which is set to non-nil by default. To use the standard +font instead, set that variable to nil. [[#h:defcf4fc-8fa8-4c29-b12e-7119582cc929][Font configurations for Org and others]]. +Packages affected by this are: + ++ elfeed ++ ement ++ eww + +This is a non-exhaustive list. + +** Note on Ement colors and fonts +:properties: +:custom_id: h:8e636056-356c-4ca7-bc78-ebe61031f585 +:end: + +The =ement.el= library by Adam Porter (also known as "alphapapa") defaults +to a method of colorizing usernames in a rainbow style. This is +controlled by the user option ~ement-room-prism~ and can be disabled with: + +#+begin_src emacs-lisp +(setq ement-room-prism nil) +#+end_src + +The contrast ratio of these colors is governed by another user option: +~ement-room-prism-minimum-contrast~. By default, it is set to 6 which is +slightly below our nominal target. Try this instead: + +#+begin_src emacs-lisp +(setq ement-room-prism-minimum-contrast 7) +#+end_src + +With regard to fonts, Ement depends on =shr= ([[#h:e6c5451f-6763-4be7-8fdb-b4706a422a4c][Note on SHR fonts]]). + +Since we are here, here is an excerpt from Ement's source code: + +#+begin_src emacs-lisp +(defcustom ement-room-prism-minimum-contrast 6 + "Attempt to enforce this minimum contrast ratio for user faces. +This should be a reasonable number from, e.g. 0-7 or so." + ;; Prot would almost approve of this default. :) I would go all the way + ;; to 7, but 6 already significantly dilutes the colors in some cases. + :type 'number) +#+end_src + +Yes, I do approve of that default. Even a 4.5 (the WCAG AA rating) +would be a good baseline for many themes and/or user configurations. +Our target is the highest of the sort, though we do not demand that +everyone conforms with it. + ** Note on Helm grep :properties: :custom_id: h:d28879a2-8e4b-4525-986e-14c0f873d229 @@ -4400,6 +4905,139 @@ The color combinations may have been optimized for accessibility, though the remaining contributing factors in each case need to be considered in full. +** Are these color schemes? +:properties: +:custom_id: h:a956dbd3-8fd2-4f5d-8b01-5f881268cf2b +:end: +#+cindex: Themes, not color schemes + +No, the Modus themes are not color schemes. + +A color scheme is a collection of colors. A good color scheme is a +combination of colors with an inner logic or abstract structure. + +A theme is a set of patterns that are applied across different contexts. +A good theme is one that does so with consistency, though not +uniformity. + +In practical terms, a color scheme is what one uses when, for example, +they edit the first sixteen escape sequences of a terminal emulator to +the hues of their preference. The terminal offers the option to choose, +say, the exact value of what counts as "red", but does not provide the +means to control where that is mapped to and whether it should also have +other qualities such as a bold weight for the underlying text or an +added background color. In contradistinction, Emacs uses constructs +known as "faces" which allow the user/developer to specify where a given +color will be used and whether it should be accompanied by other +typographic or stylistic attributes. + +By configuring the multitude of faces on offer we thus control both +which colors are applied and how they appear in their context. When a +package wants to render each instance of "foo" with the "bar" face, it +is not requesting a specific color, which makes things considerably more +flexible as we can treat "bar" in its own right without necessarily +having to use some color value that we hardcoded somewhere. + +Which brings us to the distinction between consistency and uniformity +where our goal is always the former: we want things to look similar +across all interfaces, but we must never force a visual identity where +that runs contrary to the functionality of the given interface. For +instance, all links are underlined by default yet there are cases such +as when viewing listings of emails in Gnus (and Mu4e, Notmuch) where (i) +it is already understood that one must follow the indicator or headline +to view its contents and (ii) underlining everything would make the +interface virtually unusable. + +[[#h:5808be52-361a-4d18-88fd-90129d206f9b][Option for links]]. + +Again, one must exercise judgement in order to avoid discrimination, +where "discrimination" refers to: + ++ The treatment of substantially different magnitudes as if they were of + the same class. ++ Or the treatment of the same class of magnitudes as if they were of a + different class. + +(To treat similar things differently; to treat dissimilar things alike.) + +If, in other words, one was to enforce uniformity without accounting for +the particular requirements of each case---the contextual demands for +usability beyond matters of color---they would be making a +not-so-obvious error of treating different cases as if they were the +same. + +The Modus themes prioritise "thematic consistency" over abstract harmony +or regularity among their applicable colors. In concrete terms, we do +not claim that, say, our yellows are the best complements for our blues +because we generally avoid using complementary colors side-by-side, so +it is wrong to optimise for a decontextualised blue+yellow combination. +Not to imply that our colors do not work well together because they do, +just to clarify that consistency of context is what themes must strive +for, and that requires widening the scope of the design beyond the +particularities of a color scheme. + +Long story short: color schemes and themes have different requirements. +Please do not conflate the two. + +** Port the Modus themes to other platforms? +:properties: +:custom_id: h:7156b949-917d-488e-9a72-59f70d80729c +:end: +#+cindex: Porting the themes to other editors + +There is no plan to port the themes to other platforms or text editors. +I (Protesilaos) only use GNU Emacs and thus cannot maintain code that +targets software I am either not familiar with or am not using on a +daily basis. + +While it is possible to produce a simulacrum based on a given template, +doing so would run contrary to how this project is maintained where +details matter greatly. + +Each program has its own requirements so it won't always be +possible---or indeed desirable---to have 1:1 correspondence between what +applies to Emacs and what should be done elsewhere. No port should ever +strive to be a faithful copy of the Emacs implementation, as no other +program is an Emacs equivalent, but instead try to follow the spirit of +the design. For example, some of the customization options accept a +list as their value, or an alist, which may not be possible to reproduce +on other platforms. + +[[#h:bf1c82f2-46c7-4eb2-ad00-dd11fdd8b53f][Customization options]]. + +In other words, if something must be done differently on a certain +editor then that is acceptable so long as (i) the accessibility +standards are not compromised and (ii) the overall character of the +themes remains consistent. + +The former criterion should be crystal clear as it pertains to the +scientific foundations of the themes: high legibility and taking care of +the needs of users with red-green colour deficiency (deuteranopia) by +avoiding red+green colour coding paradigms and/or by providing red+blue +variants. + +The latter criterion is the "je ne sais quoi" of the artistic aspect of +the themes, which is partially fleshed out in this manual. + +[[#h:b3384767-30d3-4484-ba7f-081729f03a47][Frequently Asked Questions]]. + +With regard to the artistic aspect (where "art" qua skill may amount to +an imprecise science), there is no hard-and-fast rule in effect as it +requires one to exercise discretion and make decisions based on +context-dependent information or constraints. As is true with most +things in life, when in doubt, do not cling on to the letter of the law +but try to understand its spirit. + +For a trivial example: the curly underline that Emacs draws for spelling +errors is thinner than, e.g., what a graphical web browser has, so if I +was to design for an editor than has a thicker curly underline I would +make the applicable colours less intense to counterbalance the +typographic intensity of the added thickness. + +With those granted, if anyone is willing to develop a port of the +themes, they are welcome to contact me and I will do my best to help +them in their efforts. + * Contributing :properties: :custom_id: h:9c3cd842-14b7-44d7-84b2-a5c8bc3fc3b1 @@ -4523,17 +5161,18 @@ The Modus themes are a collective effort. Every bit of work matters. + Author/maintainer :: Protesilaos Stavrou. -+ Contributions to code or documentation :: Anders Johansson, Basil - L.{{{space()}}} Contovounesios, Björn Lindström, Carlo Zancanaro, Christian - Tietze, Daniel Mendler, Eli Zaretskii, Fritz Grabo, Illia Ostapyshyn, - Kévin Le Gouguec, Kostadin Ninev, Madhavan Krishnan, Markus Beppler, - Matthew Stevenson, Mauro Aranda, Nicolas De Jaeghere, Philip - Kaludercic, Rudolf Adamkovič, Stephen Gildea, Shreyas Ragavan, Stefan - Kangas, Vincent Murphy, Xinglu Chen. ++ Contributions to code or documentation :: Alex Griffin, Anders + Johansson, Basil L.{{{space()}}} Contovounesios, Björn Lindström, Carlo + Zancanaro, Christian Tietze, Daniel Mendler, Eli Zaretskii, Fritz + Grabo, Illia Ostapyshyn, Kévin Le Gouguec, Kostadin Ninev, Madhavan + Krishnan, Markus Beppler, Matthew Stevenson, Mauro Aranda, Nicolas De + Jaeghere, Philip Kaludercic, Rudolf Adamkovič, Stephen Gildea, Shreyas + Ragavan, Stefan Kangas, Utkarsh Singh, Vincent Murphy, Xinglu Chen, + Yuanchen Xie. + Ideas and user feedback :: Aaron Jensen, Adam Porter, Adam Spiers, - Adrian Manea, Alex Griffin, Alex Peitsinis, Alexey Shmalko, Alok - Singh, Anders Johansson, André Alexandre Gomes, Arif Rezai, Basil + Adrian Manea, Alex Griffin, Alex Koen, Alex Peitsinis, Alexey Shmalko, + Alok Singh, Anders Johansson, André Alexandre Gomes, Arif Rezai, Basil L.{{{space()}}} Contovounesios, Burgess Chang, Christian Tietze, Christopher Dimech, Damien Cassou, Daniel Mendler, Dario Gjorgjevski, David Edmondson, Davor Rotim, Divan Santana, Eliraz Kedmi, Emanuele Michele @@ -4541,17 +5180,18 @@ The Modus themes are a collective effort. Every bit of work matters. Agbobada, Gianluca Recchia, Guilherme Semente, Gustavo Barros, Hörmetjan Yiltiz, Ilja Kocken, Iris Garcia, Jeremy Friesen, Jerry Zhang, Johannes Grødem, John Haman, Joshua O'Connor, Kevin Fleming, - Kévin Le Gouguec, Kostadin Ninev, Len Trigg, Manuel Uberti, Mark - Burton, Markus Beppler, Mauro Aranda, Michael Goldenberg, Morgan - Smith, Murilo Pereira, Nicky van Foreest, Nicolas De Jaeghere, Paul - Poloskov, Pengji Zhang, Pete Kazmier, Peter Wu, Philip Kaludercic, - Pierre Téchoueyres, Roman Rudakov, Ryan Phillips, Rudolf Adamkovič, - Sam Kleinman, Shreyas Ragavan, Simon Pugnet, Tassilo Horn, Thibaut - Verron, Thomas Heartman, Trey Merkley, Togan Muftuoglu, Toon Claes, - Uri Sharf, Utkarsh Singh, Vincent Foley. As well as users: Ben, - CsBigDataHub1, Emacs Contrib, Eugene, Fourchaux, Fredrik, Moesasji, - Nick, TheBlob42, Trey, bepolymathe, doolio, fleimgruber, iSeeU, - jixiuf, okamsn, pRot0ta1p. + Kévin Le Gouguec, Kostadin Ninev, Len Trigg, Magne Hov, Manuel Uberti, + Mark Bestley, Mark Burton, Markus Beppler, Mauro Aranda, Michael + Goldenberg, Morgan Smith, Murilo Pereira, Nicky van Foreest, Nicolas + De Jaeghere, Paul Poloskov, Pengji Zhang, Pete Kazmier, Peter Wu, + Philip Kaludercic, Pierre Téchoueyres, Roman Rudakov, Ryan Phillips, + Rudolf Adamkovič, Sam Kleinman, Samuel Culpepper, Saša Janiška, + Shreyas Ragavan, Simon Pugnet, Tassilo Horn, Thibaut Verron, Thomas + Heartman, Togan Muftuoglu, Trey Merkley, Tomasz Hołubowicz, Toon + Claes, Uri Sharf, Utkarsh Singh, Vincent Foley. As well as users: + Ben, CsBigDataHub1, Emacs Contrib, Eugene, Fourchaux, Fredrik, + Moesasji, Nick, TheBlob42, Trey, bepolymathe, bit9tream, derek-upham, + doolio, fleimgruber, gitrj95, iSeeU, jixiuf, okamsn, pRot0ta1p. + Packaging :: Basil L.{{{space()}}} Contovounesios, Eli Zaretskii, Glenn Morris, Mauro Aranda, Richard Stallman, Stefan Kangas (core Emacs), @@ -4589,6 +5229,8 @@ of this sort): + [[https://protesilaos.com/codelog/2021-01-11-modus-themes-review-select-faint-colours/][Modus themes: review of select "faint" colours]] (2021-01-11) + [[https://protesilaos.com/codelog/2021-02-25-modus-themes-diffs-deuteranopia/][The Modus themes now cover deuteranopia in diffs]] (2021-02-25) + [[https://protesilaos.com/codelog/2021-06-02-modus-themes-org-agenda/][Introducing the variable modus-themes-org-agenda]] (2021-06-02) ++ [[https://protesilaos.com/codelog/2022-01-02-review-modus-themes-org-habit-colours/][Modus themes: review of the org-habit graph colours]] (2022-01-02) ++ [[https://protesilaos.com/codelog/2022-01-03-modus-themes-port-faq/][Re: VSCode or Vim ports of the Emacs modus-themes?]] (2022-01-03) And here are the canonical sources of this project's documentation: diff --git a/etc/themes/modus-operandi-theme.el b/etc/themes/modus-operandi-theme.el index a5e8fc701c..aac5b04c6a 100644 --- a/etc/themes/modus-operandi-theme.el +++ b/etc/themes/modus-operandi-theme.el @@ -1,10 +1,10 @@ -;;; modus-operandi-theme.el --- Accessible light theme (WCAG AAA) -*- lexical-binding:t -*- +;;; modus-operandi-theme.el --- Accessible and customizable light theme (WCAG AAA) -*- lexical-binding:t -*- -;; Copyright (C) 2019-2022 Free Software Foundation, Inc. +;; Copyright (C) 2019-2022 Free Software Foundation, Inc. ;; Author: Protesilaos Stavrou ;; URL: https://gitlab.com/protesilaos/modus-themes -;; Version: 2.0.0 +;; Version: 2.1.0 ;; Package-Requires: ((emacs "27.1")) ;; Keywords: faces, theme, accessibility diff --git a/etc/themes/modus-themes.el b/etc/themes/modus-themes.el index 8afa961ba3..a902cc8ca2 100644 --- a/etc/themes/modus-themes.el +++ b/etc/themes/modus-themes.el @@ -1,11 +1,11 @@ -;;; modus-themes.el --- Highly accessible themes (WCAG AAA) -*- lexical-binding:t -*- +;;; modus-themes.el --- Highly accessible and customizable themes (WCAG AAA) -*- lexical-binding:t -*- -;; Copyright (C) 2019-2022 Free Software Foundation, Inc. +;; Copyright (C) 2019-2022 Free Software Foundation, Inc. ;; Author: Protesilaos Stavrou ;; URL: https://gitlab.com/protesilaos/modus-themes -;; Version: 2.0.0 -;; Last-Modified: <2021-12-24 12:35:25 +0200> +;; Version: 2.1.0 +;; Last-Modified: <2022-02-17 10:36:27 +0200> ;; Package-Requires: ((emacs "27.1")) ;; Keywords: faces, theme, accessibility @@ -40,11 +40,11 @@ ;; modus-themes-bold-constructs (boolean) ;; modus-themes-deuteranopia (boolean) ;; modus-themes-inhibit-reload (boolean) -;; modus-themes-intense-markup (boolean) ;; modus-themes-italic-constructs (boolean) ;; modus-themes-mixed-fonts (boolean) ;; modus-themes-subtle-line-numbers (boolean) ;; modus-themes-variable-pitch-ui (boolean) +;; modus-themes-box-buttons (choice) ;; modus-themes-completions (choice) ;; modus-themes-diffs (choice) ;; modus-themes-fringes (choice) @@ -52,6 +52,7 @@ ;; modus-themes-lang-checkers (choice) ;; modus-themes-links (choice) ;; modus-themes-mail-citations (choice) +;; modus-themes-markup (choice) ;; modus-themes-mode-line (choice) ;; modus-themes-org-blocks (choice) ;; modus-themes-paren-match (choice) @@ -74,6 +75,8 @@ ;; ace-window ;; alert ;; all-the-icons +;; all-the-icons-dired +;; all-the-icons-ibuffer ;; annotate ;; ansi-color ;; anzu @@ -97,6 +100,7 @@ ;; change-log and log-view (`vc-print-log' and `vc-print-root-log') ;; cider ;; circe +;; citar ;; color-rg ;; column-enforce-mode ;; company-mode @@ -146,6 +150,7 @@ ;; elfeed-score ;; elpher ;; embark +;; ement (ement.el) ;; emms ;; enh-ruby-mode (enhanced-ruby-mode) ;; epa @@ -235,6 +240,7 @@ ;; marginalia ;; markdown-mode ;; markup-faces (`adoc-mode') +;; mct ;; mentor ;; messages ;; minimap @@ -281,6 +287,7 @@ ;; proced ;; prodigy ;; pulse +;; pyim ;; quick-peek ;; racket-mode ;; rainbow-blocks @@ -303,6 +310,8 @@ ;; side-notes ;; sieve-mode ;; skewer-mode +;; slime (sldb) +;; sly ;; smart-mode-line ;; smartparens ;; smerge @@ -323,6 +332,7 @@ ;; telephone-line ;; terraform-mode ;; term +;; textsec ;; tomatinho ;; transient (pop-up windows like Magit's) ;; trashed @@ -412,10 +422,10 @@ cover the blue-cyan-magenta side of the spectrum." ;; highlighted constructs; they must either be used as pairs based ;; on their name or each can be combined with {fg,bg}-{main,alt,dim} ;; always in accordance with their role as background or foreground - (bg-special-cold . "#dde3f4") (fg-special-cold . "#093060") - (bg-special-mild . "#c4ede0") (fg-special-mild . "#184034") - (bg-special-warm . "#f0e0d4") (fg-special-warm . "#5d3026") - (bg-special-calm . "#f8ddea") (fg-special-calm . "#61284f") + (bg-special-cold . "#dde3f4") (bg-special-faint-cold . "#f0f1ff") (fg-special-cold . "#093060") + (bg-special-mild . "#c4ede0") (bg-special-faint-mild . "#ebf5eb") (fg-special-mild . "#184034") + (bg-special-warm . "#f0e0d4") (bg-special-faint-warm . "#fef2ea") (fg-special-warm . "#5d3026") + (bg-special-calm . "#f8ddea") (bg-special-faint-calm . "#faeff9") (fg-special-calm . "#61284f") ;; foregrounds that can be combined with bg-main, bg-dim, bg-alt (red . "#a60000") (red-alt . "#972500") @@ -495,18 +505,18 @@ cover the blue-cyan-magenta side of the spectrum." ;; those background values should only be used for graphs or similar ;; applications where colored blocks are expected to be positioned ;; next to each other - (red-graph-0-bg . "#ef6f79") - (red-graph-1-bg . "#ff9f9f") - (green-graph-0-bg . "#49d239") - (green-graph-1-bg . "#6dec6d") - (yellow-graph-0-bg . "#efec08") - (yellow-graph-1-bg . "#dbff4e") - (blue-graph-0-bg . "#55a2f0") - (blue-graph-1-bg . "#7fcfff") - (magenta-graph-0-bg . "#ba86ef") - (magenta-graph-1-bg . "#e7afff") - (cyan-graph-0-bg . "#30d3f0") - (cyan-graph-1-bg . "#6fefff") + (red-graph-0-bg . "#ef7969") + (red-graph-1-bg . "#ffaab4") + (green-graph-0-bg . "#4faa09") + (green-graph-1-bg . "#8fef00") + (yellow-graph-0-bg . "#ffcf00") + (yellow-graph-1-bg . "#f9ff00") + (blue-graph-0-bg . "#7090ff") + (blue-graph-1-bg . "#9fc6ff") + (magenta-graph-0-bg . "#e07fff") + (magenta-graph-1-bg . "#fad0ff") + (cyan-graph-0-bg . "#70d3f0") + (cyan-graph-1-bg . "#afefff") ;; the following are for cases where both the foreground and the ;; background need to have a similar hue and so must be combined ;; with themselves, even though the foregrounds can be paired with @@ -545,6 +555,8 @@ cover the blue-cyan-magenta side of the spectrum." ;; while bg-tab-inactive should be combined with fg-dim, whereas ;; bg-tab-inactive-alt goes together with fg-main ;; + ;; bg-completion-* variants are meant to be combined with fg-main + ;; ;; fg-escape-char-construct and fg-escape-char-backslash can ;; be combined bg-main, bg-dim, bg-alt ;; @@ -564,7 +576,7 @@ cover the blue-cyan-magenta side of the spectrum." ;; all pairs are combinable with themselves (bg-hl-line . "#f2eff3") (bg-hl-line-intense . "#e0e0e0") - (bg-hl-line-intense-accent . "#b9e1ef") + (bg-hl-line-intense-accent . "#cfe2ff") (bg-hl-alt . "#fbeee0") (bg-hl-alt-intense . "#e8dfd1") (bg-paren-match . "#e0af82") @@ -574,6 +586,10 @@ cover the blue-cyan-magenta side of the spectrum." (bg-region-accent . "#afafef") (bg-region-accent-subtle . "#efdfff") + (bg-completion-nuanced . "#dfe5ff") + (bg-completion-subtle . "#c3d4ff") + (bg-completion-intense . "#9fc8ff") + (bg-tab-active . "#f6f6f6") (bg-tab-inactive . "#b7b7b7") (bg-tab-inactive-accent . "#a9b4f6") @@ -653,10 +669,10 @@ symbol and the latter as a string.") ;; highlighted constructs; they must either be used as pairs based ;; on their name or each can be combined with {fg,bg}-{main,alt,dim} ;; always in accordance with their role as background or foreground - (bg-special-cold . "#203448") (fg-special-cold . "#c6eaff") - (bg-special-mild . "#00322e") (fg-special-mild . "#bfebe0") - (bg-special-warm . "#382f27") (fg-special-warm . "#f8dec0") - (bg-special-calm . "#392a48") (fg-special-calm . "#fbd6f4") + (bg-special-cold . "#203448") (bg-special-faint-cold . "#0e183a") (fg-special-cold . "#c6eaff") + (bg-special-mild . "#00322e") (bg-special-faint-mild . "#001f1a") (fg-special-mild . "#bfebe0") + (bg-special-warm . "#382f27") (bg-special-faint-warm . "#241613") (fg-special-warm . "#f8dec0") + (bg-special-calm . "#392a48") (bg-special-faint-calm . "#251232") (fg-special-calm . "#fbd6f4") ;; foregrounds that can be combined with bg-main, bg-dim, bg-alt (red . "#ff8059") (red-alt . "#ef8b50") @@ -736,18 +752,18 @@ symbol and the latter as a string.") ;; those background values should only be used for graphs or similar ;; applications where colored blocks are expected to be positioned ;; next to each other - (red-graph-0-bg . "#af0404") - (red-graph-1-bg . "#801f2f") - (green-graph-0-bg . "#24ba2f") - (green-graph-1-bg . "#0f8f07") - (yellow-graph-0-bg . "#ffd03e") - (yellow-graph-1-bg . "#d7d800") - (blue-graph-0-bg . "#406fff") - (blue-graph-1-bg . "#2f50c8") - (magenta-graph-0-bg . "#af7bee") - (magenta-graph-1-bg . "#7f59cf") - (cyan-graph-0-bg . "#47dcfa") - (cyan-graph-1-bg . "#0bc0df") + (red-graph-0-bg . "#b52c2c") + (red-graph-1-bg . "#702020") + (green-graph-0-bg . "#4fd100") + (green-graph-1-bg . "#007800") + (yellow-graph-0-bg . "#f1e00a") + (yellow-graph-1-bg . "#b08600") + (blue-graph-0-bg . "#2fafef") + (blue-graph-1-bg . "#1f2f8f") + (magenta-graph-0-bg . "#bf94fe") + (magenta-graph-1-bg . "#5f509f") + (cyan-graph-0-bg . "#47dfea") + (cyan-graph-1-bg . "#00808f") ;; the following are for cases where both the foreground and the ;; background need to have a similar hue and so must be combined ;; with themselves, even though the foregrounds can be paired with @@ -786,6 +802,8 @@ symbol and the latter as a string.") ;; while bg-tab-inactive should be combined with fg-dim, whereas ;; bg-tab-inactive-alt goes together with fg-main ;; + ;; bg-completion-* variants are meant to be combined with fg-main + ;; ;; fg-escape-char-construct and fg-escape-char-backslash can ;; be combined bg-main, bg-dim, bg-alt ;; @@ -805,16 +823,20 @@ symbol and the latter as a string.") ;; all pairs are combinable with themselves (bg-hl-line . "#151823") (bg-hl-line-intense . "#292929") - (bg-hl-line-intense-accent . "#00353f") + (bg-hl-line-intense-accent . "#002a4f") (bg-hl-alt . "#181732") (bg-hl-alt-intense . "#282e46") - (bg-paren-match . "#5f362f") + (bg-paren-match . "#6f3355") (bg-paren-match-intense . "#7416b5") (bg-paren-expression . "#221044") (bg-region . "#3c3c3c") (bg-region-accent . "#4f3d88") (bg-region-accent-subtle . "#240f55") + (bg-completion-nuanced . "#1a2854") + (bg-completion-subtle . "#282878") + (bg-completion-intense . "#323da2") + (bg-tab-active . "#0e0e0e") (bg-tab-inactive . "#424242") (bg-tab-inactive-accent . "#35398f") @@ -888,7 +910,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-subtle-green nil "Subtle green background combined with a dimmed foreground. @@ -896,7 +918,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-subtle-yellow nil "Subtle yellow background combined with a dimmed foreground. @@ -904,7 +926,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-subtle-blue nil "Subtle blue background combined with a dimmed foreground. @@ -912,7 +934,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-subtle-magenta nil "Subtle magenta background combined with a dimmed foreground. @@ -920,7 +942,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-subtle-cyan nil "Subtle cyan background combined with a dimmed foreground. @@ -928,7 +950,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-subtle-neutral nil "Subtle gray background combined with a dimmed foreground. @@ -936,7 +958,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-intense-red nil "Intense red background combined with the main foreground. @@ -944,7 +966,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-intense-green nil "Intense green background combined with the main foreground. @@ -952,7 +974,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-intense-yellow nil "Intense yellow background combined with the main foreground. @@ -960,7 +982,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-intense-blue nil "Intense blue background combined with the main foreground. @@ -968,7 +990,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-intense-magenta nil "Intense magenta background combined with the main foreground. @@ -976,7 +998,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-intense-cyan nil "Intense cyan background combined with the main foreground. @@ -984,7 +1006,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-intense-neutral nil "Intense gray background combined with the main foreground. @@ -992,7 +1014,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-refine-red nil "Combination of accented red background and foreground. @@ -1000,7 +1022,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-refine-green nil "Combination of accented green background and foreground. @@ -1008,7 +1030,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-refine-yellow nil "Combination of accented yellow background and foreground. @@ -1016,7 +1038,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-refine-blue nil "Combination of accented blue background and foreground. @@ -1024,7 +1046,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-refine-magenta nil "Combination of accented magenta background and foreground. @@ -1032,7 +1054,7 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-refine-cyan nil "Combination of accented cyan background and foreground. @@ -1040,91 +1062,91 @@ This is used for general purpose highlighting, mostly in buffers or for completion interfaces. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-active-red nil "A red background meant for use on the mode line or similar. This is combined with the mode lines primary foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-active-green nil "A green background meant for use on the mode line or similar. This is combined with the mode lines primary foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-active-yellow nil "A yellow background meant for use on the mode line or similar. This is combined with the mode lines primary foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-active-blue nil "A blue background meant for use on the mode line or similar. This is combined with the mode lines primary foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-active-magenta nil "A magenta background meant for use on the mode line or similar. This is combined with the mode lines primary foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-active-cyan nil "A cyan background meant for use on the mode line or similar. This is combined with the mode lines primary foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-fringe-red nil "A red background meant for use on the fringe or similar. This is combined with the main foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-fringe-green nil "A green background meant for use on the fringe or similar. This is combined with the main foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-fringe-yellow nil "A yellow background meant for use on the fringe or similar. This is combined with the main foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-fringe-blue nil "A blue background meant for use on the fringe or similar. This is combined with the main foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-fringe-magenta nil "A magenta background meant for use on the fringe or similar. This is combined with the main foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-fringe-cyan nil "A cyan background meant for use on the fringe or similar. This is combined with the main foreground value. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-nuanced-red nil "A nuanced red background. @@ -1134,7 +1156,7 @@ headings, and any other surface that needs to retain the colors on display. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-nuanced-green nil "A nuanced green background. @@ -1144,7 +1166,7 @@ headings, and any other surface that needs to retain the colors on display. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-nuanced-yellow nil "A nuanced yellow background. @@ -1154,7 +1176,7 @@ headings, and any other surface that needs to retain the colors on display. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-nuanced-blue nil "A nuanced blue background. @@ -1164,7 +1186,7 @@ headings, and any other surface that needs to retain the colors on display. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-nuanced-magenta nil "A nuanced magenta background. @@ -1174,7 +1196,7 @@ headings, and any other surface that needs to retain the colors on display. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-nuanced-cyan nil "A nuanced cyan background. @@ -1184,7 +1206,7 @@ headings, and any other surface that needs to retain the colors on display. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-special-cold nil "Combines the 'special cold' background and foreground values. @@ -1193,7 +1215,7 @@ suitable and where a combination of more saturated colors would not be appropriate. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-special-mild nil "Combines the 'special mild' background and foreground values. @@ -1202,7 +1224,7 @@ suitable and where a combination of more saturated colors would not be appropriate. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-special-warm nil "Combines the 'special warm' background and foreground values. @@ -1211,7 +1233,7 @@ suitable and where a combination of more saturated colors would not be appropriate. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-special-calm nil "Combines the 'special calm' background and foreground values. @@ -1220,7 +1242,7 @@ suitable and where a combination of more saturated colors would not be appropriate. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-added nil "Combines green colors for the 'added' state in diffs. @@ -1228,7 +1250,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-changed nil "Combines yellow colors for the 'changed' state in diffs. @@ -1236,7 +1258,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-removed nil "Combines red colors for the 'removed' state in diffs. @@ -1244,7 +1266,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-refine-added nil "Combines green colors for word-wise 'added' state in diffs. @@ -1252,7 +1274,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-refine-changed nil "Combines yellow colors for word-wise 'changed' state in diffs. @@ -1260,7 +1282,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-refine-removed nil "Combines red colors for word-wise 'removed' state in diffs. @@ -1268,7 +1290,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-focus-added nil "Combines green colors for the focused 'added' state in diffs. @@ -1276,7 +1298,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-focus-changed nil "Combines yellow colors for the focused 'changed' state in. @@ -1284,7 +1306,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-focus-removed nil "Combines red colors for the focused 'removed' state in diffs. @@ -1292,7 +1314,7 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-diff-heading nil "Combines blue colors for the diff hunk heading. @@ -1300,40 +1322,40 @@ The applied colors are contingent on the value assigned to `modus-themes-diffs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-pseudo-header nil "Generic style for some elements that function like headings. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-mark-alt nil "Combines yellow colors for marking special lines. This is intended for use in modes such as Dired, Ibuffer, Proced. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-mark-del nil "Combines red colors for marking deletable lines. This is intended for use in modes such as Dired, Ibuffer, Proced. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-mark-sel nil "Combines green colors for marking lines. This is intended for use in modes such as Dired, Ibuffer, Proced. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-mark-symbol nil "Applies a blue color and other styles for mark indicators. This is intended for use in modes such as Dired, Ibuffer, Proced. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-heading-1 nil "General purpose face for use in headings level 1. @@ -1341,7 +1363,7 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-headings' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-heading-2 nil "General purpose face for use in headings level 2. @@ -1349,7 +1371,7 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-headings' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-heading-3 nil "General purpose face for use in headings level 3. @@ -1357,7 +1379,7 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-headings' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-heading-4 nil "General purpose face for use in headings level 4. @@ -1365,7 +1387,7 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-headings' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-heading-5 nil "General purpose face for use in headings level 5. @@ -1373,7 +1395,7 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-headings' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-heading-6 nil "General purpose face for use in headings level 6. @@ -1381,7 +1403,7 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-headings' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-heading-7 nil "General purpose face for use in headings level 7. @@ -1389,7 +1411,7 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-headings' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-heading-8 nil "General purpose face for use in headings level 8. @@ -1397,7 +1419,7 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-headings' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-hl-line nil "General purpose face for the current line. @@ -1405,21 +1427,21 @@ The exact attributes assigned to this face are contingent on the values assigned to the `modus-themes-hl-line' variable. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-bold nil "Generic face for applying a conditional bold weight. This behaves in accordance with `modus-themes-bold-constructs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-slant nil "Generic face for applying a conditional slant (italics). This behaves in accordance with `modus-themes-italic-constructs'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-variable-pitch nil "Generic face for applying a conditional `variable-pitch'. @@ -1428,127 +1450,19 @@ This behaves in accordance with `modus-themes-mixed-fonts', and `modus-themes-variable-pitch-ui'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-fixed-pitch nil "Generic face for applying a conditional `fixed-pitch'. This behaves in accordance with `modus-themes-mixed-fonts'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-ui-variable-pitch nil "Face for `modus-themes-variable-pitch-ui'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-red-0 nil - "Special subdued red face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-red-1 nil - "Special prominent red face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-green-0 nil - "Special subdued green face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-green-1 nil - "Special prominent green face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-yellow-0 nil - "Special subdued yellow face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-yellow-1 nil - "Special prominent yellow face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-blue-0 nil - "Special subdued blue face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-blue-1 nil - "Special prominent blue face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-magenta-0 nil - "Special subdued magenta face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-magenta-1 nil - "Special prominent magenta face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-cyan-0 nil - "Special subdued cyan face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) - -(defface modus-themes-graph-cyan-1 nil - "Special prominent cyan face for use in graphs. -This is intended to be applied in contexts such as the Org agenda -habit graph where faithfulness to the semantics of a color value -is of paramount importance. - -The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-lang-note nil "Generic face for linter or spell checker notes. @@ -1556,7 +1470,7 @@ The exact attributes and color combinations are controlled by `modus-themes-lang-checkers'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-lang-warning nil "Generic face for linter or spell checker warnings. @@ -1564,7 +1478,7 @@ The exact attributes and color combinations are controlled by `modus-themes-lang-checkers'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-lang-error nil "Generic face for linter or spell checker errors. @@ -1572,7 +1486,7 @@ The exact attributes and color combinations are controlled by `modus-themes-lang-checkers'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-reset-soft nil "Generic face to set most face properties to nil. @@ -1583,7 +1497,7 @@ text should not be underlined as well) yet still blend in. Also see `modus-themes-reset-hard'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-reset-hard nil "Generic face to set all face properties to nil. @@ -1594,32 +1508,32 @@ text should not be underlined as well) and not blend in. Also see `modus-themes-reset-soft'. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-key-binding nil "Generic face for key bindings. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-search-success nil "Generic face for successful search. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-search-success-modeline nil "Generic mode line indicator for successful search. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-search-success-lazy nil "Generic face for successful, lazily highlighted search. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) (defface modus-themes-prompt nil "Generic face for command prompts. The actual styling of the face is done by `modus-themes-faces'." - :group 'modus-theme-faces) + :group 'modus-themes-faces) ;; "Grue" is "green" and "blue". (defface modus-themes-grue nil @@ -1682,11 +1596,51 @@ The actual styling of the face is done by `modus-themes-faces'." The actual styling of the face is done by `modus-themes-faces'." :group 'modus-themes-faces) +(defface modus-themes-markup-code nil + "Face of inline code markup. +The actual styling of the face is done by `modus-themes-faces'." + :group 'modus-themes-faces) + +(defface modus-themes-markup-macro nil + "Face of macro markup. +The actual styling of the face is done by `modus-themes-faces'." + :group 'modus-themes-faces) + (defface modus-themes-markup-verbatim nil "Face of verbatim markup. The actual styling of the face is done by `modus-themes-faces'." :group 'modus-themes-faces) +(defface modus-themes-completion-standard-first-match nil + "Face for the Icomplete/Ido style first match. +The actual styling of the face is done by `modus-themes-faces'." + :group 'modus-themes-faces) + +(defface modus-themes-completion-standard-selected nil + "Face for the standard completion UI current selection. +The actual styling of the face is done by `modus-themes-faces'." + :group 'modus-themes-faces) + +(defface modus-themes-completion-extra-selected nil + "Face for the extra completion UI current selection. +The actual styling of the face is done by `modus-themes-faces'." + :group 'modus-themes-faces) + +(defface modus-themes-completion-key-binding nil + "Face for key bindings in a completion UI context. +The actual styling of the face is done by `modus-themes-faces'." + :group 'modus-themes-faces) + +(defface modus-themes-box-button nil + "Face for widget buttons (e.g. in the Custom UI). +The actual styling of the face is done by `modus-themes-faces'." + :group 'modus-themes-faces) + +(defface modus-themes-box-button-pressed nil + "Face for pressed widget buttons (e.g. in the Custom UI). +The actual styling of the face is done by `modus-themes-faces'." + :group 'modus-themes-faces) + ;;; Customization variables @@ -1827,6 +1781,7 @@ Users may need to explicitly configure the font family of (defconst modus-themes--headings-choice '(set :tag "Properties" :greedy t (const :tag "Background color" background) + (const :tag "Proportionately spaced font (variable-pitch)" variable-pitch) (const :tag "Overline" overline) (choice :tag "Font weight (must be supported by the typeface)" (const :tag "Bold (default)" nil) @@ -1890,12 +1845,12 @@ proportionately spaced typeface). The symbol of a weight attribute adjusts the font of the heading accordingly, such as `light', `semibold', etc. Valid symbols are -defined in the internal variable `modus-themes--heading-weights'. -The absence of a weight means that bold will be used by virtue of -inheriting the `bold' face (check the manual for tweaking bold -and italic faces). For backward compatibility, the `no-bold' -value is accepted, though users are encouraged to specify a -`regular' weight instead. +defined in the variable `modus-themes-weights'. The absence of a +weight means that bold will be used by virtue of inheriting the +`bold' face (check the manual for tweaking bold and italic +faces). For backward compatibility, the `no-bold' value is +accepted, though users are encouraged to specify a `regular' +weight instead. A number, expressed as a floating point (e.g. 1.5), adjusts the height of the heading to that many times the base font size. The @@ -1979,10 +1934,10 @@ include either or both of those properties: small increase in height (a value of 1.15). - The symbol of a weight attribute adjusts the font of the heading accordingly, such as `light', `semibold', etc. Valid - symbols are defined in the internal variable - `modus-themes--heading-weights'. The absence of a weight means - that bold will be used by virtue of inheriting the `bold' - face (check the manual for tweaking bold and italic faces). + symbols are defined in the variable `modus-themes-weights'. + The absence of a weight means that bold will be used by virtue + of inheriting the `bold' face (check the manual for tweaking + bold and italic faces). In case both a number and `no-scale' are in the list, the latter takes precedence. If two numbers are specified, the first one is @@ -2100,11 +2055,10 @@ value are passed as a symbol. Those are: The difference between ready and clear states is attenuated by painting both of them using shades of green. This option thus highlights the alert and overdue states. -- When `modus-themes-deuteranopia' is non-nil the habit graph - uses a three-color style like the aforementioned - `traffic-light' variant, except that shades of blue are applied - instead of green. This is suitable for users with red-green - color deficiency (deuteranopia). +- When `modus-themes-deuteranopia' is non-nil the exact style of + the habit graph adapts to the needs of users with red-green + colour deficiency by substituting every instance of green with + blue or cyan (depending on the specifics). For example: @@ -2112,7 +2066,7 @@ For example: (habit . simplified) (habit . traffic-light)" :group 'modus-themes - :package-version '(modus-themes . "2.0.0") + :package-version '(modus-themes . "2.1.0") :version "29.1" :type '(set (cons :tag "Block header" @@ -2323,25 +2277,32 @@ variables `flymake-fringe-indicator-position' and :link '(info-link "(modus-themes) Language checkers")) (defcustom modus-themes-org-blocks nil - "Use a subtle gray or color-coded background for Org blocks. + "Set the overall style of Org code blocks, quotes, and the like. -Nil (the default) means that the block has no distinct background -of its own and uses the one that applies to the rest of the -buffer. +Nil (the default) means that the block has no background of its +own: it uses the one that applies to the rest of the buffer. In +this case, the delimiter lines have a gray color for their text, +making them look exactly like all other Org properties. Option `gray-background' applies a subtle gray background to the block's contents. It also affects the begin and end lines of the -block: their background extends to the edge of the window for -Emacs version >= 27 where the ':extend' keyword is recognized by -`set-face-attribute' (this is contingent on the variable -`org-fontify-whole-block-delimiter-line'). +block as they get another shade of gray as their background, +which differentiates them from the contents of the block. All +background colors extend to the edge of the window, giving the +area a rectangular, \"blocky\" presentation. Option `tinted-background' uses a slightly colored background for the contents of the block. The exact color will depend on the programming language and is controlled by the variable `org-src-block-faces' (refer to the theme's source code for the current association list). For this to take effect, the Org -buffer needs to be restarted with `org-mode-restart'. +buffer needs to be restarted with `org-mode-restart'. In this +scenario, it may be better to inhibit the extension of the +delimiter lines' background to the edge of the window because Org +does not provide a mechanism to update their colors depending on +the contents of the block. Disable the extension of such +backgrounds by setting `org-fontify-whole-block-delimiter-line' +to nil. Code blocks use their major mode's colors only when the variable `org-src-fontify-natively' is non-nil. While quote/verse blocks @@ -2353,7 +2314,7 @@ Older versions of the themes provided options `grayscale' (or are aliases for `gray-background' and `tinted-background', respectively." :group 'modus-themes - :package-version '(modus-themes . "1.4.0") + :package-version '(modus-themes . "2.1.0") :version "28.1" :type '(choice (const :format "[%v] %t\n" :tag "No Org block background (default)" nil) @@ -2509,8 +2470,9 @@ categories, based on their default aesthetics: (i) those that only or mostly use foreground colors for their interaction model, and (ii) those that combine background and foreground values for some of their metaphors. The former category encompasses -Icomplete, Ido, Selectrum, Vertico, as well as pattern matching -styles like Orderless and Flx. The latter covers Helm and Ivy. +Icomplete, Ido, Selectrum, Vertico, Mct, as well as pattern +matching styles like Orderless and Flx. The latter covers Helm +and Ivy. A value of nil (the default) will simply respect the metaphors of each completion framework. @@ -2518,28 +2480,32 @@ each completion framework. Option `moderate' applies a combination of background and foreground that is fairly subtle. For Icomplete and friends this constitutes a departure from their default aesthetics, however -the difference is small. While Helm, Ivy et al appear slightly +the difference is small. While Helm and Ivy appear slightly different than their original looks, as they are toned down a bit. Option `opinionated' uses color combinations that refashion the completion UI. For the Icomplete camp this means that intense background and foreground combinations are used: in effect their -looks emulate those of Helm, Ivy and company in their original -style. Whereas the other group of packages will revert to an -even more nuanced aesthetic with some additional changes to the -choice of hues. +looks approximate those of Helm and Ivy in their original style. +Whereas the other group of packages will revert to an even more +nuanced aesthetic with some additional changes to the choice of +hues. + +Option `super-opinionated' is like the `opinionated' though it +has a more pronounced effect, especially on the color of the +current line/candidate. To appreciate the scope of this customization option, you should -spend some time with every one of the nil (default), `moderate', -and `opinionated' possibilities." +spend some time with each of those presets." :group 'modus-themes - :package-version '(modus-themes . "1.0.0") - :version "28.1" + :package-version '(modus-themes . "2.1.0") + :version "29.1" :type '(choice (const :format "[%v] %t\n" :tag "Respect the framework's established aesthetic (default)" nil) (const :format "[%v] %t\n" :tag "Subtle backgrounds for various elements" moderate) - (const :format "[%v] %t\n" :tag "Radical alternative to the framework's looks" opinionated)) + (const :format "[%v] %t\n" :tag "Alternative to the framework's looks" opinionated) + (const :format "[%v] %t\n" :tag "Radical alternative to the framework's looks" super-opinionated)) :set #'modus-themes--set-option :initialize #'custom-initialize-default :link '(info-link "(modus-themes) Completion UIs")) @@ -2646,21 +2612,56 @@ results with underlines." :initialize #'custom-initialize-default :link '(info-link "(modus-themes) Line numbers")) -(defcustom modus-themes-intense-markup nil - "Use more intense markup in Org, Markdown, and related. -The default style for certain markup types like inline code and -verbatim constructs in Org and related major modes is a subtle -foreground color combined with a subtle background. +(defcustom modus-themes-markup nil + "Style markup in Org, Markdown, and others. + +This affects constructs such as Org's =verbatim= and ~code~. + +The value is a list of properties, each designated by a symbol. +The default (a nil value or an empty list) is a foreground +color. + +The `italic' property applies a typographic slant (italics). + +The `bold' property applies a heavier typographic weight. + +The `background' property adds a background color. The +background is a shade of gray, unless the `intense' property is +also set. -With a non-nil value (t), these constructs will use a more -prominent background and foreground color combination instead." +The `intense' property amplifies the existing coloration. When +`background' is used, the background color is enhanced as well +and becomes tinted instead of being gray. + +Combinations of any of those properties are expressed as a list, +like in these examples: + + (bold) + (bold italic) + (bold italic intense) + (bold italic intense background) + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + + (setq modus-themes-markup (quote (bold italic))) + +Also check the variables `org-hide-emphasis-markers', +`org-hide-macro-markers'." :group 'modus-themes - :package-version '(modus-themes . "1.7.0") + :package-version '(modus-themes . "2.1.0") :version "29.1" - :type 'boolean + :type '(set :tag "Properties" :greedy t + (const :tag "Added background" background) + (const :tag "Intense colors" intense) + (const :tag "Bold weight" bold) + (const :tag "Italics (slanted text)" italic)) :set #'modus-themes--set-option :initialize #'custom-initialize-default - :link '(info-link "(modus-themes) Intense markup")) + :link '(info-link "(modus-themes) Markup")) + +(make-obsolete 'modus-themes-intense-markup 'modus-themes-markup "2.1.0") (defcustom modus-themes-paren-match nil "Control the style of matching parentheses or delimiters. @@ -2895,23 +2896,32 @@ the spectrum." :link '(info-link "(modus-themes) Deuteranopia style")) (defcustom modus-themes-mail-citations nil - "Control the color of citations in messages or email clients. + "Control the color of citations/quotes in messages or emails. + +By default (a nil value) citations are styled with contrasting +hues to denote their depth. Colors are easy to tell apart +because they complement each other, but they otherwise are not +very prominent. + +Option `intense' is similar to the default in terms of using +contrasting and complementary hues, but applies more saturated +colors. -Nil (the default) means to use a variety of contrasting hues to -denote depth in nested citations. Colors are fairly easy to tell -apart. +Option `faint' maintains the same color-based distinction between +citation levels though the colors it uses have subtle differences +between them. -Option `faint' maintains a color-based distinction between -citation levels but the colors it applies have very subtle -differences between them. +Option `monochrome' turns all quotes into a shade of gray. -Option `monochrome' turns all citations that would otherwise be -colored into a uniform shade of shade of gray." +Whatever the value assigned to this variable, citations in emails +are controlled by typographic elements and/or indentation, which +the themes do not touch." :group 'modus-themes - :package-version '(modus-themes . "1.4.0") - :version "28.1" + :package-version '(modus-themes . "2.1.0") + :version "29.1" :type '(choice - (const :format "[%v] %t\n" :tag "Colorful mail citations with contrasting hues (default)" nil) + (const :format "[%v] %t\n" :tag "Colorful email citations with contrasting hues (default)" nil) + (const :format "[%v] %t\n" :tag "Like the default, but with more saturated colors" intense) (const :format "[%v] %t\n" :tag "Like the default, but with less saturated colors" faint) (const :format "[%v] %t\n" :tag "Deprecated alias of `faint'" desaturated) (const :format "[%v] %t\n" :tag "Uniformly gray mail citations" monochrome)) @@ -2931,6 +2941,75 @@ as the Centaur tabs package." :initialize #'custom-initialize-default :link '(info-link "(modus-themes) Tab style")) +(defcustom modus-themes-box-buttons nil + "Control the style of buttons in the Custom UI and related. + +The value is a list of properties, each designated by a symbol. +The default (a nil value or an empty list) is a gray background +combined with a pseudo three-dimensional effect. + +The `flat' property makes the button two dimensional. + +The `accented' property changes the background from gray to an +accent color. + +The `faint' property reduces the overall coloration. + +The `variable-pitch' property applies a proportionately spaced +typeface to the button's text. + +The `underline' property draws a line below the affected text and +removes whatever box effect. This is optimal when Emacs runs +inside a terminal emulator. If `flat' and `underline' are +defined together, the latter takes precedence. + +The symbol of a weight attribute adjusts the font of the button +accordingly, such as `light', `semibold', etc. Valid symbols are +defined in the variable `modus-themes-weights'. + +A number, expressed as a floating point (e.g. 0.9), adjusts the +height of the button's text to that many times the base font +size. The default height is the same as 1.0, though it need not +be explicitly stated. + +Combinations of any of those properties are expressed as a list, +like in these examples: + + (flat) + (variable-pitch flat) + (variable-pitch flat 0.9 semibold) + +The order in which the properties are set is not significant. + +In user configuration files the form may look like this: + + (setq modus-themes-box-buttons (quote (variable-pitch flat 0.9)))" + :group 'modus-themes + :package-version '(modus-themes . "2.1.0") + :version "29.1" + :type '(set :tag "Properties" :greedy t + (const :tag "Two-dimensional button" flat) + (const :tag "Accented background instead of gray" accented) + (const :tag "Reduce overall coloration" faint) + (const :tag "Proportionately spaced font (variable-pitch)" variable-pitch) + (const :tag "Underline instead of a box effect" underline) + (choice :tag "Font weight (must be supported by the typeface)" + (const :tag "Thin" thin) + (const :tag "Ultra-light" ultralight) + (const :tag "Extra-light" extralight) + (const :tag "Light" light) + (const :tag "Semi-light" semilight) + (const :tag "Regulat (default)" nil) + (const :tag "Medium" medium) + (const :tag "Bold" bold) + (const :tag "Semi-bold" semibold) + (const :tag "Extra-bold" extrabold) + (const :tag "Ultra-bold" ultrabold)) + (float :tag "Number (float) to adjust height by" :value 0.9)) + :set #'modus-themes--set-option + :initialize #'custom-initialize-default + :link '(info-link "(modus-themes) Box buttons")) + ;;; Internal functions @@ -2985,9 +3064,8 @@ Those are stored in `modus-themes-faces' and (defun modus-themes--slant () "Conditional use of italics for slant attribute." - (if modus-themes-italic-constructs - (list 'italic) - (list 'normal))) + (when modus-themes-italic-constructs + (list :inherit 'italic))) (defun modus-themes--fixed-pitch () "Conditional application of `fixed-pitch' inheritance." @@ -3016,14 +3094,41 @@ combines with the theme's primary background (white/black)." (list :background (or altbg 'unspecified) :foreground altfg) (list :background mainbg :foreground mainfg))) -(defun modus-themes--markup (mainfg intensefg &optional mainbg intensebg) +(defun modus-themes--markup (mainfg intensefg subtlebg intensebg) "Conditional use of colors for markup in Org and others. -MAINBG is the default background. MAINFG is the default -foreground. INTENSEBG and INTENSEFG must be more colorful -variants." - (if modus-themes-intense-markup - (list :background (or intensebg 'unspecified) :foreground intensefg) - (list :background (or mainbg 'unspecified) :foreground mainfg))) +MAINFG is the default foreground. SUBTLEBG is a gray background. +INTENSEBG is a colorful background for use with the main +foreground. INTENSEFG is an alternative to the default." + (let ((properties modus-themes-markup)) + (list + :inherit + (cond + ((and (memq 'bold properties) + (memq 'italic properties)) + (list 'modus-themes-fixed-pitch 'bold-italic)) + ((memq 'italic properties) + (list 'modus-themes-fixed-pitch 'italic)) + ((memq 'bold properties) + (list 'modus-themes-fixed-pitch 'bold)) + (t 'modus-themes-fixed-pitch)) + :background + (cond + ((and (memq 'background properties) + (memq 'intense properties)) + intensebg) + ((memq 'background properties) + subtlebg) + (t + 'unspecified)) + :foreground + (cond + ((and (memq 'background properties) + (memq 'intense properties)) + mainfg) + ((memq 'intense properties) + intensefg) + (t + mainfg))))) (defun modus-themes--lang-check (underline subtlefg intensefg intensefg-alt subtlebg intensebg faintfg) "Conditional use of foreground colors for language checkers. @@ -3090,19 +3195,7 @@ should be combinable with INTENSEBG-FG. SUBTLEBGGRAY and INTENSEBGGRAY are background values. The former can be combined with GRAYFG, while the latter only works with the theme's fallback text color." - (let ((properties - (if (listp modus-themes-prompts) - modus-themes-prompts - ;; translation layer for legacy values - (pcase modus-themes-prompts - ;; `subtle' is the same as `subtle-accented', while `intense' is - ;; equal to `intense-accented' for backward compatibility - ('subtle '(background)) - ('subtle-accented '(background)) - ('subtle-gray '(background gray)) - ('intense '(background intense)) - ('intense-accented '(background intense)) - ('intense-gray '(background intense gray)))))) + (let ((properties modus-themes-prompts)) (list :foreground (cond ((and (memq 'gray properties) @@ -3148,16 +3241,7 @@ NORMALBG should be the special palette color 'bg-paren-match' or something similar. INTENSEBG must be easier to discern next to other backgrounds, such as the special palette color 'bg-paren-match-intense'." - (let ((properties - (if (listp modus-themes-paren-match) - modus-themes-paren-match - ;; translation layer for legacy values - (pcase modus-themes-paren-match - ;; `subtle' is the same as `subtle-accented', while `intense' is - ;; equal to `intense-accented' for backward compatibility - ('intense-bold '(intense bold)) - ('subtle-bold '(bold)) - ('intense '(intense)))))) + (let ((properties modus-themes-paren-match)) (list :inherit (if (memq 'bold properties) 'bold @@ -3175,18 +3259,7 @@ other backgrounds, such as the special palette color "Apply foreground value to code syntax. FG is the default. FAINT is typically the same color in its desaturated version." - (let ((properties - (if (listp modus-themes-syntax) - modus-themes-syntax - ;; translation layer for legacy values - (pcase modus-themes-syntax - ('faint '(faint)) - ('faint-yellow-comments '(faint yellow-comments)) - ('green-strings '(green-strings)) - ('yellow-comments '(yellow-comments)) - ('yellow-comments-green-strings '(green-strings yellow-comments)) - ('alt-syntax '(alt-syntax)) - ('alt-syntax-yellow-comments '(alt-syntax yellow-comments)))))) + (let ((properties modus-themes-syntax)) (list :foreground (cond ((memq 'faint properties) @@ -3198,18 +3271,7 @@ desaturated version." FG is the default. FAINT is typically the same color in its desaturated version. ALT is another hue while optional FAINT-ALT is its subtle alternative." - (let ((properties - (if (listp modus-themes-syntax) - modus-themes-syntax - ;; translation layer for legacy values - (pcase modus-themes-syntax - ('faint '(faint)) - ('faint-yellow-comments '(faint yellow-comments)) - ('green-strings '(green-strings)) - ('yellow-comments '(yellow-comments)) - ('yellow-comments-green-strings '(green-strings yellow-comments)) - ('alt-syntax '(alt-syntax)) - ('alt-syntax-yellow-comments '(alt-syntax yellow-comments)))))) + (let ((properties modus-themes-syntax)) (list :foreground (cond ((and (memq 'alt-syntax properties) @@ -3228,18 +3290,7 @@ desaturated version. GREEN is a color variant in that side of the spectrum. ALT is another hue. Optional FAINT-GREEN is a subtle alternative to GREEN. Optional FAINT-ALT is a subtle alternative to ALT." - (let ((properties - (if (listp modus-themes-syntax) - modus-themes-syntax - ;; translation layer for legacy values - (pcase modus-themes-syntax - ('faint '(faint)) - ('faint-yellow-comments '(faint yellow-comments)) - ('green-strings '(green-strings)) - ('yellow-comments '(yellow-comments)) - ('yellow-comments-green-strings '(green-strings yellow-comments)) - ('alt-syntax '(alt-syntax)) - ('alt-syntax-yellow-comments '(alt-syntax yellow-comments)))))) + (let ((properties modus-themes-syntax)) (list :foreground (cond ((and (memq 'faint properties) @@ -3261,18 +3312,7 @@ alternative to ALT." FG is the default. YELLOW is a color variant of that name while optional FAINT-YELLOW is its subtle variant. Optional FAINT is an alternative to the default value." - (let ((properties - (if (listp modus-themes-syntax) - modus-themes-syntax - ;; translation layer for legacy values - (pcase modus-themes-syntax - ('faint '(faint)) - ('faint-yellow-comments '(faint yellow-comments)) - ('green-strings '(green-strings)) - ('yellow-comments '(yellow-comments)) - ('yellow-comments-green-strings '(green-strings yellow-comments)) - ('alt-syntax '(alt-syntax)) - ('alt-syntax-yellow-comments '(alt-syntax yellow-comments)))))) + (let ((properties modus-themes-syntax)) (list :foreground (cond ((and (memq 'faint properties) @@ -3292,12 +3332,17 @@ an alternative to the default value." "Get cdr of KEY in ALIST." (cdr (assoc key alist))) -(defvar modus-themes--heading-weights +(define-obsolete-variable-alias + 'modus-themes--heading-weights + 'modus-themes-weights + "2.1.0") + +(defconst modus-themes-weights '( thin ultralight extralight light semilight regular medium semibold bold heavy extrabold ultrabold) - "List of font weights used by `modus-themes--heading'.") + "List of font weights.") -(defun modus-themes--heading-weight (list) +(defun modus-themes--weight (list) "Search for `modus-themes--heading' weight in LIST." (catch 'found (dolist (elt list) @@ -3316,33 +3361,12 @@ that combines well with the background and foreground." (let* ((key (modus-themes--key-cdr level modus-themes-headings)) (style (or key (modus-themes--key-cdr t modus-themes-headings))) (style-listp (listp style)) - (properties - (if style-listp - style - ;; translation layer for legacy values - (pcase style - ('highlight '(background)) - ('highlight-no-bold '(background no-bold)) - ('line '(overline)) - ('line-no-bold '(no-bold overline)) - ('no-bold '(no-bold)) - ('no-color '(monochrome)) - ('no-color-no-bold '(no-bold monochrome)) - ('rainbow '(rainbow)) - ('rainbow-highlight '(rainbow background)) - ('rainbow-highlight-no-bold '(no-bold rainbow background)) - ('rainbow-line '(rainbow overline)) - ('rainbow-no-bold '(no-bold rainbow)) - ('rainbow-line-no-bold '(rainbow overline no-bold)) - ('rainbow-section '(rainbow overline background)) - ('rainbow-section-no-bold '(no-bold rainbow background overline)) - ('section '(background overline)) - ('section-no-bold '(background overline no-bold))))) + (properties style) (var (when (memq 'variable-pitch properties) 'variable-pitch)) (varbold (if var (append (list 'bold) (list var)) 'bold)) - (weight (when style-listp (modus-themes--heading-weight style)))) + (weight (when style-listp (modus-themes--weight style)))) (list :inherit (cond ;; `no-bold' is for backward compatibility because we cannot @@ -3378,7 +3402,7 @@ that combines well with the background and foreground." "Control the style of the Org agenda structure. FG is the foreground color to use." (let* ((properties (modus-themes--key-cdr 'header-block modus-themes-org-agenda)) - (weight (modus-themes--heading-weight properties))) + (weight (modus-themes--weight properties))) (list :inherit (cond ((and weight (memq 'variable-pitch properties)) @@ -3479,18 +3503,28 @@ clearly distinguishes past, present, future tasks." ('rainbow (list :foreground rainbowfg)) (_ (list :foreground defaultfg)))) -(defun modus-themes--agenda-habit (default traffic simple &optional traffic-deuteran) +(defun modus-themes--agenda-habit (default traffic simple &optional default-d traffic-d simple-d) "Specify background values for `modus-themes-org-agenda' habits. DEFAULT is the original foregrounc color. TRAFFIC is to be used when the 'traffic-light' style is applied, while SIMPLE -corresponds to the 'simplified style'. Optional TRAFFIC-DEUTERAN -is an alternative to TRAFFIC, meant for deuteranopia." - (if modus-themes-deuteranopia - (list :background (or traffic-deuteran traffic)) - (pcase (modus-themes--key-cdr 'habit modus-themes-org-agenda) - ('traffic-light (list :background traffic)) - ('simplified (list :background simple)) - (_ (list :background default))))) +corresponds to the 'simplified style'. + +Optional DEFAULT-D, TRAFFIC-D, SIMPLE-D are alternatives to the +main colors, meant for dopia when `modus-themes-deuteranopia' is +non-nil." + (let ((habit (modus-themes--key-cdr 'habit modus-themes-org-agenda))) + (cond + ((and modus-themes-deuteranopia (null habit)) + (list :background (or default-d default))) + ((and modus-themes-deuteranopia (eq habit 'traffic-light)) + (list :background (or traffic-d traffic))) + ((and modus-themes-deuteranopia (eq habit 'simplified)) + (list :background (or simple-d simple))) + (t + (pcase habit + ('traffic-light (list :background traffic)) + ('simplified (list :background simple)) + (_ (list :background default))))))) (defun modus-themes--org-block (bgblk fgdefault &optional fgblk) "Conditionally set the background of Org blocks. @@ -3526,8 +3560,9 @@ set to `rainbow'." ('gray-background (list :background bg :foreground fg :extend t)) ('grayscale (list :background bg :foreground fg :extend t)) ('greyscale (list :background bg :foreground fg :extend t)) + ('tinted-background (list :background bgaccent :foreground fgaccent :extend nil)) ('rainbow (list :background bgaccent :foreground fgaccent :extend nil)) - (_ (list :background bg :foreground fg :extend nil)))) + (_ (list :foreground fg :extend nil)))) (defun modus-themes--mode-line-attrs (fg bg fg-alt bg-alt fg-accent bg-accent border border-3d &optional alt-style fg-distant) @@ -3545,22 +3580,7 @@ line's box property. Optional FG-DISTANT should be close to the main background values. It is intended to be used as a distant-foreground property." - (let* ((properties - (if (listp modus-themes-mode-line) - modus-themes-mode-line - ;; translation layer for legacy values - (alist-get modus-themes-mode-line - '((3d . (3d)) - (moody . (moody)) - (borderless . (borderless)) - (borderless-3d . (borderless 3d)) - (borderless-moody . (borderless moody)) - (accented . (accented)) - (accented-3d . (accented 3d)) - (accented-moody . (accented moody)) - (borderless-accented . (borderless accented)) - (borderless-accented-3d . (borderless accented 3d)) - (borderless-accented-moody . (borderless accented moody)))))) + (let* ((properties modus-themes-mode-line) (padding (seq-find #'natnump properties 1)) (padded (> padding 1)) (base (cond ((memq 'accented properties) @@ -3622,6 +3642,12 @@ property." fg-distant 'unspecified)))) +;; Basically this is just for the keycast key indicator. +(defun modus-themes--mode-line-padded-box (color) + "Set padding of mode line box attribute with given COLOR." + (let ((padding (seq-find #'natnump modus-themes-mode-line 1))) + (list :box (list :line-width padding :color color)))) + (defun modus-themes--diff (mainbg mainfg altbg altfg &optional deuteranbg deuteranfg bg-only-fg) "Color combinations for `modus-themes-diffs'. @@ -3650,39 +3676,47 @@ unspecified." (list deuteran) (list main))) -(defun modus-themes--standard-completions (mainfg subtlebg intensebg intensefg) +(defun modus-themes--standard-completions (mainfg subtlebg subtlefg intensebg intensefg &optional superbg superfg) "Combinations for `modus-themes-completions'. MAINFG is an accented foreground value. SUBTLEBG is an accented -background value that can be combined with MAINFG. INTENSEBG and -INTENSEFG are accented colors that are designed to be used in -tandem. +background value that can be combined with SUBTLEFG. INTENSEBG +and INTENSEFG are accented colors that are designed to be used in +tandem. Same principle for the optional SUPERBG and SUPERFG. These are intended for Icomplete, Ido, and related." (pcase modus-themes-completions + ('super-opinionated (list :background (or superbg intensebg) :foreground (or superfg intensefg))) ('opinionated (list :background intensebg :foreground intensefg)) - ('moderate (list :background subtlebg :foreground mainfg)) + ('moderate (list :background subtlebg :foreground subtlefg)) (_ (list :foreground mainfg)))) -(defun modus-themes--extra-completions (subtleface intenseface altface &optional altfg bold) +(defun modus-themes--extra-completions (default moderate opinionated) "Combinations for `modus-themes-completions'. -SUBTLEFACE and INTENSEFACE are custom theme faces that combine a -background and foreground value. The difference between the two -is a matter of degree. +DEFAULT, MODERATE, and OPINIONATED are faces that correspond to +the stylistic variants of the aforementioned user option. + +These are intended for Ivy and Helm." + (pcase modus-themes-completions + ('super-opinionated (list :inherit (list 'bold opinionated))) + ('opinionated (list :inherit (list 'bold opinionated))) + ('moderate (list :inherit (list 'bold moderate))) + (_ (list :inherit (list 'bold default))))) -ALTFACE is a combination of colors that represents a departure -from the UI's default aesthetics. Optional ALTFG is meant to be -used in tandem with it. +(defun modus-themes--extra-completions-line (mainfg mainbg modbg opbg sopbg) + "Combinations for `modus-themes-completions'. -Optional BOLD will apply a heavier weight to the text. +MAINFG and MAINBG form the basic intense style. MODBG, OPBG, and +SOPBG are the moderate, opinionated, and super-opinionated +backgrounds, respectively. -These are intended for Helm, Ivy, etc." +These are intended for Ivy and Helm." (pcase modus-themes-completions - ('opinionated (list :inherit (list altface bold) - :foreground (or altfg 'unspecified))) - ('moderate (list :inherit (list subtleface bold))) - (_ (list :inherit (list intenseface bold))))) + ('super-opinionated (list :inherit 'bold :background sopbg :foreground mainfg)) + ('opinionated (list :inherit 'bold :background opbg :foreground mainfg)) + ('moderate (list :inherit 'bold :background modbg :foreground mainfg)) + (_ (list :inherit 'bold :background mainbg :foreground mainfg)))) (defun modus-themes--link (fg fgfaint underline bg bgneutral) "Conditional application of link styles. @@ -3690,17 +3724,7 @@ FG is the link's default color for its text and underline property. FGFAINT is a desaturated color for the text and underline. UNDERLINE is a gray color only for the undeline. BG is a background color and BGNEUTRAL is its fallback value." - (let ((properties - (if (listp modus-themes-links) - modus-themes-links - ;; translation layer for legacy values - (pcase modus-themes-links - ('faint '(faint)) - ('neutral-underline '(neutral-underline)) - ('faint-neutral-underline '(neutral-underline faint)) - ('no-underline '(no-underline)) - ('underline-only '(no-color)) - ('neutral-underline-only '(no-color neutral-underline)))))) + (let ((properties modus-themes-links)) (list :inherit (cond ((and (memq 'bold properties) @@ -3738,17 +3762,7 @@ is a background color and BGNEUTRAL is its fallback value." "Extend `modus-themes--link'. FG is the main accented foreground. FGFAINT is also accented, yet desaturated. Optional NEUTRALFG is a gray value." - (let ((properties - (if (listp modus-themes-links) - modus-themes-links - ;; translation layer for legacy values - (pcase modus-themes-links - ('faint '(faint)) - ('neutral-underline '(neutral-underline)) - ('faint-neutral-underline '(neutral-underline faint)) - ('no-underline '(no-underline)) - ('underline-only '(no-color)) - ('neutral-underline-only '(no-color neutral-underline)))))) + (let ((properties modus-themes-links)) (list :foreground (cond ((memq 'no-color properties) @@ -3772,16 +3786,7 @@ is a subtle background value that can be combined with all colors used to fontify text and code syntax. BGACCENT is a colored background that combines well with FG. BGACCENTSUBTLE can be combined with all colors used to fontify text." - (let ((properties - (if (listp modus-themes-region) - modus-themes-region - ;; translation layer for legacy values - (pcase modus-themes-region - ('bg-only '(bg-only)) - ('bg-only-no-extend '(bg-only no-extend)) - ('accent '(accented)) - ('accent-no-extend '(accented no-extend)) - ('no-extend '(no-extend)))))) + (let ((properties modus-themes-region)) (list :background (cond ((and (memq 'accented properties) @@ -3817,17 +3822,7 @@ LINEACCENT are color values that can remain distinct against the buffer's possible backgrounds: the former is neutral, the latter is accented. LINENEUTRALINTENSE and LINEACCENTINTENSE are their more prominent alternatives." - (let ((properties - (if (listp modus-themes-hl-line) - modus-themes-hl-line - ;; translation layer for legacy values - (pcase modus-themes-hl-line - ('intense-background '(intense)) - ('accented-background '(accented)) - ('underline-neutral '(underline)) - ('underline-accented '(underline accented)) - ('underline-only-neutral '(underline)) ; only underline styles have been removed - ('underline-only-accented '(underline accented)))))) + (let ((properties modus-themes-hl-line)) (list :background (cond ((and (memq 'intense properties) @@ -3855,13 +3850,14 @@ more prominent alternatives." lineneutral) ('unspecified))))) -(defun modus-themes--mail-cite (mainfg subtlefg) +(defun modus-themes--mail-cite (mainfg intensefg subtlefg) "Combinations for `modus-themes-mail-citations'. MAINFG is an accented foreground value. SUBTLEFG is its -desaturated counterpart." +desaturated counterpart. INTENSEFG is a more saturated variant." (pcase modus-themes-mail-citations ('monochrome (list :inherit 'shadow)) + ('intense (list :foreground intensefg)) ('faint (list :foreground subtlefg)) ('desaturated (list :foreground subtlefg)) (_ (list :foreground mainfg)))) @@ -3890,10 +3886,118 @@ application of a variable-pitch font." :foreground (or foreground 'unspecified) :box (if box-p (list :line-width 2 :color background) 'unspecified)))) +(defun modus-themes--button (bg bgfaint bgaccent bgaccentfaint border &optional pressed-button-p) + "Apply `modus-themes-box-buttons' styles. + +Work in progress. BG BGFAINT BGACCENT BGACCENTFAINT BORDER PRESSED-BUTTON-P." + (let* ((properties modus-themes-box-buttons) + (weight (modus-themes--weight properties))) + (list :inherit + (cond + ((and (memq 'variable-pitch properties) + (eq weight 'bold)) + (list 'bold 'variable-pitch)) + ((memq 'variable-pitch properties) + 'variable-pitch) + ((eq weight 'bold) + 'bold) + ('unspecified)) + :background + (cond + ((and (memq 'accented properties) + (memq 'faint properties) + bgaccentfaint)) + ((memq 'faint properties) + bgfaint) + ((memq 'accented properties) + bgaccent) + (bg)) + :box + (cond + ((memq 'underline properties) + 'unspecified) + ((memq 'flat properties) + (list :line-width -1 :color border)) + ((list :line-width -1 + :style (if pressed-button-p + 'pressed-button + 'released-button) + :color border))) + :weight + (cond + ((eq weight 'bold) + 'unspecified) ; we :inherit the `bold' face above + (weight weight) + ('unspecified)) + :height + (seq-find #'floatp properties 'unspecified) + :underline + (if (memq 'underline properties) + t + 'unspecified)))) + ;;;; Utilities for DIY users +;;;;; List colors (a respin of M-x list-colors-display) + +(defun modus-themes--list-colors-render (buffer palette) + "Render colors in BUFFER from PALETTE. +Routine for `modus-themes-list-colors'." + (with-help-window buffer + (with-current-buffer standard-output + (erase-buffer) + ;; We need this to properly render the first line. + (insert " ") + (dolist (cell palette) + (let* ((name (car cell)) + (color (cdr cell)) + (fg (readable-foreground-color color)) + (pad (make-string 5 ?\s))) + (let ((old-point (point))) + (insert (format "%s %s" color pad)) + (put-text-property old-point (point) 'face `( :foreground ,color))) + (let ((old-point (point))) + (insert (format " %s %s %s\n" color pad name)) + (put-text-property old-point (point) + 'face `( :background ,color + :foreground ,fg + :extend t))) + ;; We need this to properly render the last line. + (insert " ")))))) + +(defvar modus-themes--list-colors-prompt-history '() + "Minibuffer history for `modus-themes--list-colors-prompt'.") + +(defun modus-themes--list-colors-prompt () + "Prompt for Modus theme. +Helper function for `modus-themes-list-colors'." + (let ((def (format "%s" (modus-themes--current-theme)))) + (completing-read + (format "Use palette from theme [%s]: " def) + '(modus-operandi modus-vivendi) nil t nil + 'modus-themes--list-colors-prompt-history def))) + +(defun modus-themes-list-colors (theme) + "Preview palette of the Modus THEME of choice." + (interactive + (list (intern (modus-themes--list-colors-prompt)))) + (let ((palette (pcase theme + ('modus-operandi modus-themes-operandi-colors) + ('modus-vivendi modus-themes-vivendi-colors) + (_ (user-error "`%s' is not a Modus theme" theme))))) + (modus-themes--list-colors-render + (format "*%s-list-colors*" theme) + palette))) + +(defun modus-themes-list-colors-current () + "Call `modus-themes-list-colors' for the current Modus theme." + (interactive) + (modus-themes-list-colors (modus-themes--current-theme))) + +;;;;; Formula to measure relative luminance + ;; This is the WCAG formula: https://www.w3.org/TR/WCAG20-TECHS/G18.html (defun modus-themes-wcag-formula (hex) "Get WCAG value of color value HEX. @@ -3913,6 +4017,8 @@ C1 and C2 are color values written in hexadecimal RGB." (+ (modus-themes-wcag-formula c2) 0.05)))) (max ct (/ ct)))) +;;;;; Retrieve colors from the themes + (defun modus-themes-current-palette () "Return current color palette." (modus-themes--palette (modus-themes--current-theme))) @@ -4215,19 +4321,6 @@ by virtue of calling either of `modus-themes-load-operandi' and ((,class ,@(modus-themes--heading 8 magenta-nuanced-fg magenta bg-alt bg-alt bg-region)))) -;;;;; graph-specific faces - `(modus-themes-graph-red-0 ((,class :background ,red-graph-0-bg))) - `(modus-themes-graph-red-1 ((,class :background ,red-graph-1-bg))) - `(modus-themes-graph-green-0 ((,class :background ,green-graph-0-bg))) - `(modus-themes-graph-green-1 ((,class :background ,green-graph-1-bg))) - `(modus-themes-graph-yellow-0 ((,class :background ,yellow-graph-0-bg))) - `(modus-themes-graph-yellow-1 ((,class :background ,yellow-graph-1-bg))) - `(modus-themes-graph-blue-0 ((,class :background ,blue-graph-0-bg))) - `(modus-themes-graph-blue-1 ((,class :background ,blue-graph-1-bg))) - `(modus-themes-graph-magenta-0 ((,class :background ,magenta-graph-0-bg))) - `(modus-themes-graph-magenta-1 ((,class :background ,magenta-graph-1-bg))) - `(modus-themes-graph-cyan-0 ((,class :background ,cyan-graph-0-bg))) - `(modus-themes-graph-cyan-1 ((,class :background ,cyan-graph-1-bg))) ;;;;; language checkers `(modus-themes-lang-error ((,class ,@(modus-themes--lang-check fg-lang-underline-error fg-lang-error @@ -4241,21 +4334,72 @@ by virtue of calling either of `modus-themes-load-operandi' and ;;;;; links `(modus-themes-link-broken ((,class :inherit button ,@(modus-themes--link-color red red-faint)))) `(modus-themes-link-symlink ((,class :inherit button ,@(modus-themes--link-color cyan cyan-faint)))) +;;;;; markup + `(modus-themes-markup-code + ((,class ,@(modus-themes--markup cyan-alt-other cyan-intense bg-alt + bg-special-faint-mild)))) + `(modus-themes-markup-macro + ((,class ,@(modus-themes--markup magenta-alt-other purple-intense bg-alt + bg-special-faint-cold)))) + `(modus-themes-markup-verbatim + ((,class ,@(modus-themes--markup magenta-alt magenta-intense bg-alt + bg-special-faint-calm)))) +;;;;; search + `(modus-themes-search-success ((,class :inherit ,@(modus-themes--deuteran + 'modus-themes-intense-blue + 'modus-themes-intense-green)))) + `(modus-themes-search-success-lazy ((,class :inherit ,@(modus-themes--deuteran + 'modus-themes-special-mild + 'modus-themes-refine-cyan)))) + `(modus-themes-search-success-modeline ((,class :foreground ,@(modus-themes--deuteran + blue-active + green-active)))) ;;;;; tabs `(modus-themes-tab-active ((,class ,@(modus-themes--tab bg-tab-active nil nil nil t t)))) `(modus-themes-tab-backdrop ((,class ,@(modus-themes--tab bg-active bg-active-accent nil nil nil nil t)))) `(modus-themes-tab-inactive ((,class ,@(modus-themes--tab bg-tab-inactive bg-tab-inactive-accent fg-dim nil t)))) -;;;;; other custom faces +;;;;; completion frameworks + `(modus-themes-completion-standard-first-match + ((,class :inherit bold + ,@(modus-themes--standard-completions + magenta bg-alt magenta-alt + bg-active fg-main + blue-intense-bg)))) + `(modus-themes-completion-standard-selected + ((,class :inherit bold :foreground ,fg-main + :background ,@(pcase modus-themes-completions + ('super-opinionated (list bg-completion-intense)) + ('opinionated (list bg-active)) + ('moderate (list bg-completion-nuanced)) + (_ (list bg-inactive)))))) + `(modus-themes-completion-extra-selected + ((,class ,@(modus-themes--extra-completions-line + fg-main bg-completion-intense bg-completion-subtle + bg-completion-nuanced bg-active)))) + `(modus-themes-completion-key-binding + ((,class ,@(if (null modus-themes-completions) + (list :foreground magenta-alt-other) + (list :inherit 'modus-themes-key-binding))))) +;;;;; buttons + `(modus-themes-box-button + ((,class ,@(modus-themes--button bg-active bg-main bg-active-accent + bg-special-cold bg-region)))) + `(modus-themes-box-button-pressed + ((,class ,@(modus-themes--button bg-active bg-main bg-active-accent + bg-special-cold bg-region t)))) +;;;;; typography `(modus-themes-bold ((,class ,@(modus-themes--bold-weight)))) + `(modus-themes-fixed-pitch ((,class ,@(modus-themes--fixed-pitch)))) + `(modus-themes-slant ((,class ,@(modus-themes--slant)))) + `(modus-themes-ui-variable-pitch ((,class ,@(modus-themes--variable-pitch-ui)))) +;;;;; other custom faces `(modus-themes-hl-line ((,class ,@(modus-themes--hl-line bg-hl-line bg-hl-line-intense bg-hl-line-intense-accent blue-nuanced-bg bg-region blue-intense-bg - fg-alt cyan-intense) + fg-alt blue-intense) :extend t))) - `(modus-themes-key-binding ((,class ,@(if (facep 'help-key-binding) ; check emacs28 face - (list :inherit 'help-key-binding) - (list :inherit 'bold :foreground blue-alt-other))))) + `(modus-themes-key-binding ((,class :inherit bold :foreground ,blue-alt-other))) `(modus-themes-prompt ((,class ,@(modus-themes--prompt cyan-alt-other blue-alt-other fg-alt cyan-nuanced-bg blue-refine-bg fg-main @@ -4264,21 +4408,6 @@ by virtue of calling either of `modus-themes-load-operandi' and `(modus-themes-reset-soft ((,class :background ,bg-main :foreground ,fg-main :weight normal :slant normal :strike-through nil :box nil :underline nil :overline nil :extend nil))) - `(modus-themes-search-success ((,class :inherit ,@(modus-themes--deuteran - 'modus-themes-intense-blue - 'modus-themes-intense-green)))) - `(modus-themes-search-success-lazy ((,class :inherit ,@(modus-themes--deuteran - 'modus-themes-special-mild - 'modus-themes-refine-cyan)))) - `(modus-themes-search-success-modeline ((,class :foreground ,@(modus-themes--deuteran - blue-active - green-active)))) - `(modus-themes-slant ((,class :inherit italic :slant ,@(modus-themes--slant)))) - `(modus-themes-ui-variable-pitch ((,class ,@(modus-themes--variable-pitch-ui)))) - `(modus-themes-fixed-pitch ((,class ,@(modus-themes--fixed-pitch)))) - `(modus-themes-markup-verbatim ((,class :inherit modus-themes-fixed-pitch - ,@(modus-themes--markup fg-special-calm magenta-alt - bg-alt magenta-nuanced-bg)))) ;;;; standard faces ;;;;; absolute essentials `(default ((,class :background ,bg-main :foreground ,fg-main))) @@ -4290,28 +4419,31 @@ by virtue of calling either of `modus-themes-load-operandi' and `(bold ((,class :weight bold))) `(bold-italic ((,class :inherit (bold italic)))) `(buffer-menu-buffer ((,class :inherit bold))) + `(child-frame-border ((,class :background ,fg-window-divider-inner))) `(comint-highlight-input ((,class :inherit bold))) `(comint-highlight-prompt ((,class :inherit modus-themes-prompt))) `(confusingly-reordered ((,class :inherit modus-themes-lang-error))) + `(elisp-shorthand-font-lock-face ((,class :inherit font-lock-variable-name-face))) `(error ((,class :inherit bold :foreground ,red))) `(escape-glyph ((,class :foreground ,fg-escape-char-construct))) `(file-name-shadow ((,class :inherit (shadow italic)))) `(header-line ((,class :inherit modus-themes-ui-variable-pitch :background ,bg-header :foreground ,fg-header))) - `(header-line-highlight ((,class :inherit modus-themes-active-blue))) + `(header-line-highlight ((,class :inherit highlight))) `(help-argument-name ((,class :inherit modus-themes-slant :foreground ,cyan))) - `(help-key-binding ((,class :box (:line-width (-1 . -1) :color ,bg-active) ; NOTE: box syntax is for Emacs28 - :background ,bg-alt))) + `(help-key-binding ((,class :inherit modus-themes-key-binding))) `(homoglyph ((,class :foreground ,red-alt-faint))) `(ibuffer-locked-buffer ((,class :foreground ,yellow-alt-other-faint))) `(italic ((,class :slant italic))) `(nobreak-hyphen ((,class :foreground ,fg-escape-char-construct))) `(nobreak-space ((,class :foreground ,fg-escape-char-construct :underline t))) + `(menu ((,class :inverse-video unspecified :inherit modus-themes-intense-neutral))) `(minibuffer-prompt ((,class :inherit modus-themes-prompt))) `(mm-command-output ((,class :foreground ,red-alt-other))) `(mm-uu-extract ((,class :background ,bg-dim :foreground ,fg-special-mild))) `(next-error ((,class :inherit modus-themes-subtle-red :extend t))) - `(rectangle-preview ((,class :inherit modus-themes-special-mild))) + `(pgtk-im-0 ((,class :inherit modus-themes-fringe-blue :underline t))) + `(rectangle-preview ((,class :background ,bg-special-faint-warm :foreground ,fg-special-warm))) `(region ((,class ,@(modus-themes--region bg-region fg-main bg-hl-alt-intense bg-region-accent bg-region-accent-subtle)))) @@ -4332,7 +4464,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(widget-button ((,class :inherit bold :foreground ,blue-alt))) `(widget-button-pressed ((,class :inherit widget-button :foreground ,magenta))) `(widget-documentation ((,class :foreground ,green))) - `(widget-field ((,class :background ,bg-alt :foreground ,fg-dim))) + `(widget-field ((,class :background ,bg-alt :foreground ,fg-main :extend nil))) `(widget-inactive ((,class :inherit shadow :background ,bg-dim))) `(widget-single-line-field ((,class :inherit widget-field))) ;;;;; alert @@ -4342,41 +4474,47 @@ by virtue of calling either of `modus-themes-load-operandi' and `(alert-trivial-face ((,class :foreground ,fg-special-calm))) `(alert-urgent-face ((,class :inherit bold :foreground ,red-intense))) ;;;;; all-the-icons - `(all-the-icons-blue ((,class :foreground ,blue))) + `(all-the-icons-blue ((,class :foreground ,blue-alt-other))) `(all-the-icons-blue-alt ((,class :foreground ,blue-alt))) - `(all-the-icons-cyan ((,class :foreground ,cyan))) + `(all-the-icons-cyan ((,class :foreground ,cyan-intense))) `(all-the-icons-cyan-alt ((,class :foreground ,cyan-alt))) - `(all-the-icons-dblue ((,class :foreground ,blue-alt-other))) - `(all-the-icons-dcyan ((,class :foreground ,cyan-alt-other))) - `(all-the-icons-dgreen ((,class :foreground ,green-alt-other))) - `(all-the-icons-dired-dir-face ((,class :foreground ,blue))) - `(all-the-icons-dmaroon ((,class :foreground ,magenta-alt-other))) - `(all-the-icons-dorange ((,class :foreground ,red-alt-other))) - `(all-the-icons-dpink ((,class :foreground ,magenta))) - `(all-the-icons-dpurple ((,class :foreground ,magenta-alt))) - `(all-the-icons-dred ((,class :foreground ,red))) - `(all-the-icons-dsilver ((,class :foreground ,fg-special-cold))) - `(all-the-icons-dyellow ((,class :foreground ,yellow))) - `(all-the-icons-green ((,class :foreground ,green))) - `(all-the-icons-lblue ((,class :foreground ,blue-refine-fg))) - `(all-the-icons-lcyan ((,class :foreground ,cyan-refine-fg))) - `(all-the-icons-lgreen ((,class :foreground ,green-refine-fg))) - `(all-the-icons-lmaroon ((,class :foreground ,magenta-refine-fg))) - `(all-the-icons-lorange ((,class :foreground ,red-refine-fg))) - `(all-the-icons-lpink ((,class :foreground ,magenta-refine-fg))) - `(all-the-icons-lpurple ((,class :foreground ,magenta-refine-fg))) - `(all-the-icons-lred ((,class :foreground ,red-refine-fg))) - `(all-the-icons-lsilver ((,class :foreground ,fg-special-cold))) - `(all-the-icons-lyellow ((,class :foreground ,yellow-refine-fg))) - `(all-the-icons-maroon ((,class :foreground ,magenta))) - `(all-the-icons-orange ((,class :foreground ,red-alt))) - `(all-the-icons-pink ((,class :foreground ,magenta))) - `(all-the-icons-purple ((,class :foreground ,magenta-alt))) - `(all-the-icons-purple-alt ((,class :foreground ,magenta-alt-other))) - `(all-the-icons-red ((,class :foreground ,red))) - `(all-the-icons-red-alt ((,class :foreground ,red-alt))) + `(all-the-icons-dblue ((,class :foreground ,blue-faint))) + `(all-the-icons-dcyan ((,class :foreground ,cyan-faint))) + `(all-the-icons-dgreen ((,class :foreground ,green))) + `(all-the-icons-dmaroon ((,class :foreground ,magenta-alt-faint))) + `(all-the-icons-dorange ((,class :foreground ,red-alt-faint))) + `(all-the-icons-dpink ((,class :foreground ,magenta-faint))) + `(all-the-icons-dpurple ((,class :foreground ,magenta-alt-other-faint))) + `(all-the-icons-dred ((,class :foreground ,red-faint))) + `(all-the-icons-dsilver ((,class :foreground ,cyan-alt-faint))) + `(all-the-icons-dyellow ((,class :foreground ,yellow-alt-faint))) + `(all-the-icons-green ((,class :foreground ,green-intense))) + `(all-the-icons-lblue ((,class :foreground ,blue-alt-other))) + `(all-the-icons-lcyan ((,class :foreground ,cyan))) + `(all-the-icons-lgreen ((,class :foreground ,green-alt-other))) + `(all-the-icons-lmaroon ((,class :foreground ,magenta-alt))) + `(all-the-icons-lorange ((,class :foreground ,red-alt))) + `(all-the-icons-lpink ((,class :foreground ,magenta))) + `(all-the-icons-lpurple ((,class :foreground ,magenta-faint))) + `(all-the-icons-lred ((,class :foreground ,red))) + `(all-the-icons-lsilver ((,class :foreground ,fg-docstring))) + `(all-the-icons-lyellow ((,class :foreground ,yellow-alt))) + `(all-the-icons-maroon ((,class :foreground ,magenta-intense))) + `(all-the-icons-orange ((,class :foreground ,orange-intense))) + `(all-the-icons-pink ((,class :foreground ,fg-special-calm))) + `(all-the-icons-purple ((,class :foreground ,magenta-alt-other))) + `(all-the-icons-purple-alt ((,class :foreground ,purple-intense))) + `(all-the-icons-red ((,class :foreground ,red-intense))) + `(all-the-icons-red-alt ((,class :foreground ,red-alt-other))) `(all-the-icons-silver ((,class :foreground ,fg-special-cold))) `(all-the-icons-yellow ((,class :foreground ,yellow))) +;;;;; all-the-icons-dired + `(all-the-icons-dired-dir-face ((,class :foreground ,cyan-faint))) +;;;;; all-the-icons-ibuffer + `(all-the-icons-ibuffer-dir-face ((,class :foreground ,cyan-faint))) + `(all-the-icons-ibuffer-file-face ((,class :foreground ,blue-faint))) + `(all-the-icons-ibuffer-mode-face ((,class :foreground ,cyan))) + `(all-the-icons-ibuffer-size-face ((,class :foreground ,cyan-alt-other))) ;;;;; annotate `(annotate-annotation ((,class :inherit modus-themes-subtle-blue))) `(annotate-annotation-secondary ((,class :inherit modus-themes-subtle-green))) @@ -4430,12 +4568,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(font-latex-italic-face ((,class :inherit italic))) `(font-latex-math-face ((,class :inherit font-lock-constant-face))) `(font-latex-script-char-face ((,class :inherit font-lock-builtin-face))) - `(font-latex-sectioning-0-face ((,class :inherit modus-themes-heading-1))) - `(font-latex-sectioning-1-face ((,class :inherit modus-themes-heading-2))) - `(font-latex-sectioning-2-face ((,class :inherit modus-themes-heading-3))) - `(font-latex-sectioning-3-face ((,class :inherit modus-themes-heading-4))) - `(font-latex-sectioning-4-face ((,class :inherit modus-themes-heading-5))) - `(font-latex-sectioning-5-face ((,class :inherit modus-themes-heading-6))) + `(font-latex-sectioning-5-face ((,class :inherit (bold modus-themes-variable-pitch) :foreground ,blue-nuanced-fg))) `(font-latex-sedate-face ((,class :inherit font-lock-keyword-face))) `(font-latex-slide-title-face ((,class :inherit modus-themes-heading-1))) `(font-latex-string-face ((,class :inherit font-lock-string-face))) @@ -4617,6 +4750,9 @@ by virtue of calling either of `modus-themes-load-operandi' and `(lui-button-face ((,class :inherit button))) `(lui-highlight-face ((,class :foreground ,magenta-alt))) `(lui-time-stamp-face ((,class :foreground ,blue-nuanced-fg))) +;;;;; citar + `(citar ((,class :inherit shadow))) + `(citar-highlight (( ))) ;;;;; color-rg `(color-rg-font-lock-column-number ((,class :foreground ,magenta-alt-other))) `(color-rg-font-lock-command ((,class :inherit bold :foreground ,fg-main))) @@ -4656,23 +4792,23 @@ by virtue of calling either of `modus-themes-load-operandi' and `(company-posframe-active-backend-name ((,class :inherit bold :background ,bg-active :foreground ,blue-active))) `(company-posframe-inactive-backend-name ((,class :background ,bg-active :foreground ,fg-active))) `(company-posframe-metadata ((,class :background ,bg-inactive :foreground ,fg-inactive))) -;;;;; compilation feedback - `(compilation-column-number ((,class :foreground ,magenta-alt-other))) +;;;;; compilation + `(compilation-column-number ((,class :inherit compilation-line-number))) `(compilation-error ((,class :inherit modus-themes-bold :foreground ,red))) `(compilation-info ((,class :inherit modus-themes-bold :foreground ,fg-special-cold))) `(compilation-line-number ((,class :foreground ,fg-special-warm))) - `(compilation-mode-line-exit ((,class :inherit modus-themes-bold :foreground ,blue-active))) + `(compilation-mode-line-exit ((,class :inherit bold))) `(compilation-mode-line-fail ((,class :inherit modus-themes-bold :foreground ,red-active))) - `(compilation-mode-line-run ((,class :inherit modus-themes-bold :foreground ,magenta-active))) - `(compilation-warning ((,class :inherit modus-themes-bold :foreground ,yellow))) + `(compilation-mode-line-run ((,class :inherit modus-themes-bold :foreground ,cyan-active))) + `(compilation-warning ((,class :inherit modus-themes-bold :foreground ,yellow-alt))) ;;;;; completions `(completions-annotations ((,class :inherit modus-themes-slant :foreground ,cyan-faint))) `(completions-common-part ((,class ,@(modus-themes--standard-completions - blue-alt blue-nuanced-bg + blue-alt bg-special-mild fg-special-mild cyan-refine-bg cyan-refine-fg)))) `(completions-first-difference ((,class :inherit bold ,@(modus-themes--standard-completions - magenta-alt blue-nuanced-bg + magenta-alt bg-special-calm fg-special-calm magenta-intense-bg fg-main)))) ;;;;; consult `(consult-async-running ((,class :inherit bold :foreground ,blue))) @@ -4736,12 +4872,9 @@ by virtue of calling either of `modus-themes-load-operandi' and ;;;;; cursor-flash `(cursor-flash-face ((,class :inherit modus-themes-intense-blue))) ;;;;; custom (M-x customize) - `(custom-button ((,class :box (:line-width 2 :color nil :style released-button) - :background ,bg-active :foreground ,fg-main))) - `(custom-button-mouse ((,class :box (:line-width 2 :color nil :style released-button) - :background ,bg-active :foreground ,fg-active))) - `(custom-button-pressed ((,class :box (:line-width 2 :color nil :style pressed-button) - :background ,bg-active :foreground ,fg-main))) + `(custom-button ((,class :inherit modus-themes-box-button))) + `(custom-button-mouse ((,class :inherit (highlight custom-button)))) + `(custom-button-pressed ((,class :inherit modus-themes-box-button-pressed))) `(custom-changed ((,class :inherit modus-themes-subtle-cyan))) `(custom-comment ((,class :inherit shadow))) `(custom-comment-tag ((,class :background ,bg-alt :foreground ,yellow-alt-other))) @@ -4752,9 +4885,9 @@ by virtue of calling either of `modus-themes-load-operandi' and `(custom-modified ((,class :inherit modus-themes-subtle-cyan))) `(custom-rogue ((,class :inherit modus-themes-refine-magenta))) `(custom-set ((,class :foreground ,blue-alt))) - `(custom-state ((,class :foreground ,cyan-alt-other))) + `(custom-state ((,class :foreground ,red-alt-faint))) `(custom-themed ((,class :inherit modus-themes-subtle-blue))) - `(custom-variable-tag ((,class :inherit bold :foreground ,cyan))) + `(custom-variable-tag ((,class :foreground ,cyan))) ;;;;; dap-mode `(dap-mouse-eval-thing-face ((,class :box (:line-width -1 :color ,blue-active :style nil) :background ,bg-active :foreground ,fg-main))) @@ -5032,7 +5165,9 @@ by virtue of calling either of `modus-themes-load-operandi' and `(el-search-occur-match ((,class :inherit modus-themes-special-calm))) ;;;;; eldoc ;; NOTE: see https://github.com/purcell/package-lint/issues/187 - (list 'eldoc-highlight-function-argument `((,class :inherit bold :foreground ,blue-alt-other))) + (list 'eldoc-highlight-function-argument `((,class :inherit bold + :background ,yellow-nuanced-bg + :foreground ,yellow-alt-other))) ;;;;; eldoc-box `(eldoc-box-body ((,class :background ,bg-alt :foreground ,fg-main))) `(eldoc-box-border ((,class :background ,fg-alt))) @@ -5045,10 +5180,10 @@ by virtue of calling either of `modus-themes-load-operandi' and `(elfeed-search-date-face ((,class :foreground ,cyan))) `(elfeed-search-feed-face ((,class :foreground ,blue-faint))) `(elfeed-search-filter-face ((,class :inherit bold :foreground ,magenta-active))) - `(elfeed-search-last-update-face ((,class :foreground ,cyan-active))) - `(elfeed-search-tag-face ((,class :foreground ,cyan-alt-other))) + `(elfeed-search-last-update-face ((,class :inherit bold :foreground ,cyan-active))) + `(elfeed-search-tag-face ((,class :foreground ,magenta-alt-faint))) `(elfeed-search-title-face ((,class :foreground ,fg-dim))) - `(elfeed-search-unread-count-face ((,class :foreground ,green-active))) + `(elfeed-search-unread-count-face ((,class :inherit bold :foreground ,fg-active))) `(elfeed-search-unread-title-face ((,class :inherit bold :foreground ,fg-main))) ;;;;; elfeed-score `(elfeed-score-date-face ((,class :foreground ,blue))) @@ -5061,7 +5196,19 @@ by virtue of calling either of `modus-themes-load-operandi' and `(elpher-gemini-heading2 ((,class :inherit modus-themes-heading-2))) `(elpher-gemini-heading3 ((,class :inherit modus-themes-heading-3))) ;;;;; embark - `(embark-keybinding ((,class :inherit modus-themes-key-binding))) + `(embark-keybinding ((,class :inherit modus-themes-completion-key-binding))) +;;;;; ement (ement.el) + `(ement-room-fully-read-marker ((,class :background ,cyan-subtle-bg))) + `(ement-room-membership ((,class :inherit shadow))) + `(ement-room-mention (( ))) + `(ement-room-name ((,class :inherit bold))) + `(ement-room-reactions ((,class :inherit shadow))) + `(ement-room-read-receipt-marker ((,class :background ,yellow-subtle-bg))) + `(ement-room-self ((,class :inherit bold :foreground ,magenta))) + `(ement-room-self-message ((,class :foreground ,magenta-faint))) + `(ement-room-timestamp ((,class :inherit shadow))) + `(ement-room-timestamp-header ((,class :inherit bold :foreground ,cyan))) + `(ement-room-user ((,class :inherit bold :foreground ,blue))) ;;;;; emms `(emms-browser-album-face ((,class :foreground ,magenta-alt-other))) `(emms-browser-artist-face ((,class :foreground ,cyan))) @@ -5239,10 +5386,9 @@ by virtue of calling either of `modus-themes-load-operandi' and `(eww-form-checkbox ((,class :inherit eww-form-text))) `(eww-form-file ((,class :inherit eww-form-submit))) `(eww-form-select ((,class :inherit eww-form-submit))) - `(eww-form-submit ((,class :box (:line-width 2 :style released-button) - :background ,bg-active))) - `(eww-form-text ((,class :box ,bg-active :background ,bg-alt))) - `(eww-form-textarea ((,class :background ,bg-alt))) + `(eww-form-submit ((,class :inherit modus-themes-box-button))) + `(eww-form-text ((,class :inherit widget-field))) + `(eww-form-textarea ((,class :inherit eww-form-text))) ;;;;; eyebrowse `(eyebrowse-mode-line-active ((,class :inherit bold :foreground ,blue-active))) ;;;;; fancy-dabbrev @@ -5295,11 +5441,9 @@ by virtue of calling either of `modus-themes-load-operandi' and `(flyspell-incorrect ((,class :inherit modus-themes-lang-error))) ;;;;; flx `(flx-highlight-face ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-magenta 'modus-themes-intense-magenta - 'modus-themes-nuanced-magenta - magenta-alt - 'bold)))) + 'modus-themes-subtle-magenta + 'modus-themes-special-calm)))) ;;;;; freeze-it `(freeze-it-show ((,class :background ,bg-dim :foreground ,fg-special-warm))) ;;;;; frog-menu @@ -5346,17 +5490,17 @@ by virtue of calling either of `modus-themes-load-operandi' and `(font-lock-regexp-grouping-backslash ((,class :inherit bold ,@(modus-themes--syntax-string fg-escape-char-backslash yellow-alt-faint - yellow magenta-alt - yellow-faint red-faint)))) + yellow-alt magenta-alt + red-faint green-alt-other-faint)))) `(font-lock-regexp-grouping-construct ((,class :inherit bold ,@(modus-themes--syntax-string fg-escape-char-construct red-alt-other-faint - blue blue-alt-other + red-alt-other blue-alt-other blue-faint blue-alt-other-faint)))) `(font-lock-string-face ((,class ,@(modus-themes--syntax-string blue-alt blue-alt-faint - green red - green-faint red-faint)))) + green-alt-other red-alt + green-alt-faint red-alt-faint)))) `(font-lock-type-face ((,class :inherit modus-themes-bold ,@(modus-themes--syntax-foreground cyan-alt-other cyan-alt-faint)))) @@ -5395,8 +5539,10 @@ by virtue of calling either of `modus-themes-load-operandi' and `(fountain-synopsis ((,class :foreground ,cyan-alt))) `(fountain-trans ((,class :foreground ,yellow-alt-other))) ;;;;; geiser - `(geiser-font-lock-autodoc-current-arg ((,class :inherit font-lock-function-name-face))) - `(geiser-font-lock-autodoc-identifier ((,class :inherit font-lock-constant-face))) + `(geiser-font-lock-autodoc-current-arg ((,class :inherit bold + :background ,yellow-nuanced-bg + :foreground ,yellow-alt-other))) + `(geiser-font-lock-autodoc-identifier ((,class :foreground ,cyan))) `(geiser-font-lock-doc-button ((,class :inherit button :foreground ,fg-docstring))) `(geiser-font-lock-doc-link ((,class :inherit button))) `(geiser-font-lock-error-link ((,class :inherit button :foreground ,red))) @@ -5550,10 +5696,9 @@ by virtue of calling either of `modus-themes-load-operandi' and `(helm-etags-file ((,class :foreground ,fg-dim :underline t))) `(helm-ff-backup-file ((,class :inherit shadow))) `(helm-ff-denied ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-red 'modus-themes-intense-red - 'modus-themes-nuanced-red - red)))) + 'modus-themes-subtle-red + 'modus-themes-special-warm)))) `(helm-ff-directory ((,class :inherit helm-buffer-directory))) `(helm-ff-dirs ((,class :inherit bold :foreground ,blue-alt-other))) `(helm-ff-dotted-directory ((,class :inherit bold :background ,bg-alt :foreground ,fg-alt))) @@ -5565,19 +5710,16 @@ by virtue of calling either of `modus-themes-load-operandi' and `(helm-ff-pipe ((,class ,@(modus-themes--extra-completions 'modus-themes-refine-magenta 'modus-themes-subtle-magenta - 'modus-themes-nuanced-magenta - magenta)))) + 'modus-themes-special-calm)))) `(helm-ff-prefix ((,class ,@(modus-themes--extra-completions 'modus-themes-refine-yellow 'modus-themes-subtle-yellow - 'modus-themes-nuanced-yellow - yellow-alt-other)))) + 'modus-themes-special-warm)))) `(helm-ff-socket ((,class :foreground ,red-alt-other))) `(helm-ff-suid ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-red 'modus-themes-refine-red - 'modus-themes-nuanced-yellow - red-alt)))) + 'modus-themes-subtle-red + 'modus-themes-special-warm)))) `(helm-ff-symlink ((,class :inherit modus-themes-link-symlink))) `(helm-ff-truename ((,class :foreground ,blue-alt-other))) `(helm-fd-finish ((,class :foreground ,green-active))) @@ -5589,57 +5731,39 @@ by virtue of calling either of `modus-themes-load-operandi' and `(helm-header ((,class :inherit bold :foreground ,fg-special-cold))) `(helm-header-line-left-margin ((,class :inherit bold :foreground ,yellow-intense))) `(helm-history-deleted ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-red 'modus-themes-intense-red - 'modus-themes-nuanced-red - red - 'bold)))) + 'modus-themes-subtle-red + 'modus-themes-special-warm)))) `(helm-history-remote ((,class :foreground ,red-alt-other))) - `(helm-lisp-completion-info ((,class :foreground ,fg-special-warm))) + `(helm-lisp-completion-info ((,class :inherit compilation-info))) `(helm-lisp-show-completion ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-yellow 'modus-themes-refine-yellow - 'modus-themes-nuanced-yellow - yellow - 'bold)))) - `(helm-locate-finish ((,class :foreground ,green-active))) + 'modus-themes-subtle-yellow + 'modus-themes-special-warm)))) + `(helm-locate-finish ((,class :inherit success))) `(helm-match ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-cyan 'modus-themes-refine-cyan - 'modus-themes-nuanced-cyan - cyan - 'bold)))) - `(helm-match-item ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-neutral - 'modus-themes-subtle-cyan - 'modus-themes-nuanced-cyan - cyan-alt-other)))) + 'modus-themes-subtle-cyan + 'modus-themes-special-mild)))) + `(helm-match-item ((,class :inherit helm-match))) `(helm-minibuffer-prompt ((,class :inherit modus-themes-prompt))) `(helm-moccur-buffer ((,class :inherit button :foreground ,cyan-alt-other))) `(helm-mode-prefix ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-magenta 'modus-themes-intense-magenta - 'modus-themes-nuanced-magenta - magenta-alt - 'bold)))) + 'modus-themes-subtle-magenta + 'modus-themes-special-calm)))) `(helm-non-file-buffer ((,class :inherit shadow))) `(helm-prefarg ((,class :foreground ,red-active))) `(helm-resume-need-update ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-magenta 'modus-themes-refine-magenta - 'modus-themes-nuanced-magenta - magenta-alt-other)))) - `(helm-selection ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-blue - 'modus-themes-refine-blue - 'modus-themes-special-cold - nil - 'bold)))) + 'modus-themes-subtle-magenta + 'modus-themes-special-calm)))) + `(helm-selection ((,class :inherit modus-themes-completion-extra-selected))) `(helm-selection-line ((,class :inherit modus-themes-special-cold))) `(helm-separator ((,class :foreground ,fg-special-mild))) `(helm-time-zone-current ((,class :foreground ,green))) `(helm-time-zone-home ((,class :foreground ,magenta))) - `(helm-source-header ((,class :inherit modus-themes-pseudo-header :foreground ,fg-special-cold))) + `(helm-source-header ((,class :inherit modus-themes-pseudo-header :foreground ,fg-special-warm))) `(helm-top-columns ((,class :inherit helm-header))) `(helm-ucs-char ((,class :foreground ,yellow-alt-other))) `(helm-visible-mark ((,class :inherit modus-themes-subtle-cyan))) @@ -5655,14 +5779,11 @@ by virtue of calling either of `modus-themes-load-operandi' and `(helm-ls-git-untracked-face ((,class :foreground ,fg-special-cold))) ;;;;; helm-switch-shell `(helm-switch-shell-new-shell-face ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-magenta 'modus-themes-refine-magenta - 'modus-themes-nuanced-magenta - magenta-alt-other - 'bold)))) + 'modus-themes-subtle-magenta + 'modus-themes-nuanced-magenta)))) ;;;;; helm-xref - `(helm-xref-file-name ((,class :inherit bold :foreground ,fg-special-cold))) - `(helm-xref-file-name ((,class :foreground ,fg-special-warm))) + `(helm-xref-file-name ((,class :inherit compilation-info))) ;;;;; helpful `(helpful-heading ((,class :inherit modus-themes-heading-1))) ;;;;; highlight region or ad-hoc regexp @@ -5678,7 +5799,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(hi-red-b ((,class :inherit bold :background ,red-intense-bg :foreground ,fg-main))) `(hi-salmon ((,class :background ,red-subtle-bg :foreground ,fg-main))) `(hi-yellow ((,class :background ,yellow-subtle-bg :foreground ,fg-main))) - `(highlight ((,class :background ,blue-subtle-bg :foreground ,fg-main))) + `(highlight ((,class :background ,cyan-subtle-bg :foreground ,fg-main))) `(highlight-changes ((,class :foreground ,red-alt :underline nil))) `(highlight-changes-delete ((,class :background ,red-nuanced-bg :foreground ,red :underline t))) @@ -5705,27 +5826,15 @@ by virtue of calling either of `modus-themes-load-operandi' and `(hydra-face-red ((,class :inherit bold :foreground ,red-faint))) `(hydra-face-teal ((,class :inherit bold :foreground ,cyan-alt-other))) ;;;;; icomplete - `(icomplete-first-match ((,class :inherit bold - ,@(modus-themes--standard-completions - magenta bg-alt - bg-active fg-main)))) - `(icomplete-selected-match ((,class :inherit bold :foreground ,fg-main - :background ,@(pcase modus-themes-completions - ('opinionated (list bg-active)) - (_ (list bg-inactive)))))) + `(icomplete-first-match ((,class :inherit modus-themes-completion-standard-first-match))) + `(icomplete-selected-match ((,class :inherit modus-themes-completion-standard-selected))) ;;;;; icomplete-vertical `(icomplete-vertical-separator ((,class :inherit shadow))) ;;;;; ido-mode - `(ido-first-match ((,class :inherit bold - ,@(modus-themes--standard-completions - magenta bg-alt - bg-active fg-main)))) + `(ido-first-match ((,class :inherit modus-themes-completion-standard-first-match))) `(ido-incomplete-regexp ((,class :inherit error))) `(ido-indicator ((,class :inherit modus-themes-subtle-yellow))) - `(ido-only-match ((,class :inherit bold - ,@(modus-themes--standard-completions - green green-nuanced-bg - green-intense-bg fg-main)))) + `(ido-only-match ((,class :inherit ido-first-match))) `(ido-subdir ((,class :foreground ,blue))) `(ido-virtual ((,class :foreground ,fg-special-warm))) ;;;;; iedit @@ -5759,7 +5868,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(info-header-node ((,class :inherit (shadow bold)))) `(info-header-xref ((,class :foreground ,blue-active))) `(info-index-match ((,class :inherit match))) - `(info-menu-header ((,class :inherit modus-themes-heading-3))) + `(info-menu-header ((,class :inherit modus-themes-pseudo-header))) `(info-menu-star ((,class :foreground ,red))) `(info-node ((,class :inherit bold))) `(info-title-1 ((,class :inherit modus-themes-heading-1))) @@ -5803,62 +5912,32 @@ by virtue of calling either of `modus-themes-load-operandi' and `(match ((,class :inherit modus-themes-special-calm))) `(query-replace ((,class :inherit (modus-themes-intense-yellow bold)))) ;;;;; ivy - `(ivy-action ((,class :inherit bold :foreground ,red-alt))) - `(ivy-completions-annotations ((,class :inherit completions-annotations))) - `(ivy-confirm-face ((,class :foreground ,cyan))) - `(ivy-current-match ((,class ,@(modus-themes--extra-completions - 'modus-themes-refine-cyan - 'modus-themes-intense-cyan - 'modus-themes-special-cold - nil - 'bold)))) + `(ivy-action ((,class :inherit modus-themes-key-binding))) + `(ivy-confirm-face ((,class :inherit success))) + `(ivy-current-match ((,class :inherit modus-themes-completion-extra-selected))) `(ivy-cursor ((,class :background ,fg-main :foreground ,bg-main))) - `(ivy-grep-info ((,class :foreground ,cyan-alt))) - `(ivy-grep-line-number ((,class :foreground ,fg-special-warm))) `(ivy-highlight-face ((,class :foreground ,magenta))) `(ivy-match-required-face ((,class :inherit error))) - `(ivy-minibuffer-match-face-1 ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-neutral - 'modus-themes-intense-neutral - 'modus-themes-nuanced-cyan - fg-alt)))) + `(ivy-minibuffer-match-face-1 ((,class :inherit modus-themes-subtle-neutral))) `(ivy-minibuffer-match-face-2 ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-green 'modus-themes-refine-green - 'modus-themes-nuanced-green - green-alt-other - 'bold)))) + 'modus-themes-subtle-green + 'modus-themes-special-mild)))) `(ivy-minibuffer-match-face-3 ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-blue 'modus-themes-refine-blue - 'modus-themes-nuanced-blue - blue-alt-other - 'bold)))) + 'modus-themes-subtle-blue + 'modus-themes-special-cold)))) `(ivy-minibuffer-match-face-4 ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-magenta 'modus-themes-refine-magenta - 'modus-themes-nuanced-magenta - magenta-alt-other - 'bold)))) - `(ivy-minibuffer-match-highlight ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-cyan - 'modus-themes-intense-cyan - 'modus-themes-nuanced-cyan - cyan-alt-other - 'bold)))) + 'modus-themes-subtle-magenta + 'modus-themes-special-calm)))) `(ivy-modified-buffer ((,class :inherit modus-themes-slant :foreground ,yellow))) - `(ivy-modified-outside-buffer ((,class :inherit modus-themes-slant :foreground ,yellow-alt))) + `(ivy-modified-outside-buffer ((,class :inherit modus-themes-slant :foreground ,red-alt))) `(ivy-org ((,class :foreground ,cyan-alt-other))) - `(ivy-prompt-match ((,class :inherit ivy-current-match))) `(ivy-remote ((,class :foreground ,magenta))) `(ivy-separator ((,class :inherit shadow))) - `(ivy-subdir ((,class :foreground ,blue-alt-other))) + `(ivy-subdir ((,class :foreground ,blue))) `(ivy-virtual ((,class :foreground ,magenta-alt-other))) - `(ivy-yanked-word ((,class ,@(modus-themes--extra-completions - 'modus-themes-subtle-blue - 'modus-themes-refine-blue - 'modus-themes-nuanced-blue - blue-alt)))) ;;;;; ivy-posframe `(ivy-posframe ((,class :background ,bg-dim :foreground ,fg-main))) `(ivy-posframe-border ((,class :background ,fg-window-divider-inner))) @@ -5910,7 +5989,8 @@ by virtue of calling either of `modus-themes-load-operandi' and `(kaocha-runner-warning-face ((,class :inherit warning))) ;;;;; keycast `(keycast-command ((,class :inherit bold :foreground ,blue-active))) - `(keycast-key ((,class :background ,blue-active :foreground ,bg-main))) + `(keycast-key ((,class ,@(modus-themes--mode-line-padded-box blue-active) + :background ,blue-active :foreground ,bg-main))) ;;;;; ledger-mode `(ledger-font-auto-xact-face ((,class :foreground ,magenta))) `(ledger-font-account-name-face ((,class :foreground ,fg-special-cold))) @@ -5992,9 +6072,9 @@ by virtue of calling either of `modus-themes-load-operandi' and `(macrostep-gensym-5 ((,class :inherit bold :foreground ,magenta :box t))) `(macrostep-macro-face ((,class :inherit button :foreground ,green-alt))) ;;;;; magit - `(magit-bisect-bad ((,class :foreground ,red-alt-other))) - `(magit-bisect-good ((,class :foreground ,green-alt-other))) - `(magit-bisect-skip ((,class :foreground ,yellow-alt-other))) + `(magit-bisect-bad ((,class :inherit error))) + `(magit-bisect-good ((,class :inherit success))) + `(magit-bisect-skip ((,class :inherit warning))) `(magit-blame-date ((,class :foreground ,blue))) `(magit-blame-dimmed ((,class :inherit (shadow modus-themes-reset-hard)))) `(magit-blame-hash ((,class :foreground ,fg-special-warm))) @@ -6073,19 +6153,19 @@ by virtue of calling either of `modus-themes-load-operandi' and `(magit-log-author ((,class :foreground ,cyan))) `(magit-log-date ((,class :inherit shadow))) `(magit-log-graph ((,class :foreground ,fg-dim))) - `(magit-mode-line-process ((,class :inherit bold :foreground ,blue-active))) + `(magit-mode-line-process ((,class :inherit bold :foreground ,cyan-active))) `(magit-mode-line-process-error ((,class :inherit bold :foreground ,red-active))) `(magit-process-ng ((,class :inherit error))) `(magit-process-ok ((,class :inherit success))) - `(magit-reflog-amend ((,class :background ,bg-main :foreground ,magenta-intense))) - `(magit-reflog-checkout ((,class :background ,bg-main :foreground ,blue-intense))) - `(magit-reflog-cherry-pick ((,class :background ,bg-main :foreground ,green-intense))) - `(magit-reflog-commit ((,class :background ,bg-main :foreground ,green-intense))) - `(magit-reflog-merge ((,class :background ,bg-main :foreground ,green-intense))) - `(magit-reflog-other ((,class :background ,bg-main :foreground ,cyan-intense))) - `(magit-reflog-rebase ((,class :background ,bg-main :foreground ,magenta-intense))) - `(magit-reflog-remote ((,class :background ,bg-main :foreground ,cyan-intense))) - `(magit-reflog-reset ((,class :background ,bg-main :foreground ,red-intense))) + `(magit-reflog-amend ((,class :inherit warning))) + `(magit-reflog-checkout ((,class :inherit bold :foreground ,blue-alt))) + `(magit-reflog-cherry-pick ((,class :inherit success))) + `(magit-reflog-commit ((,class :inherit bold))) + `(magit-reflog-merge ((,class :inherit success))) + `(magit-reflog-other ((,class :inherit bold :foreground ,cyan))) + `(magit-reflog-rebase ((,class :inherit bold :foreground ,magenta))) + `(magit-reflog-remote ((,class :inherit bold :foreground ,magenta-alt-other))) + `(magit-reflog-reset ((,class :inherit error))) `(magit-refname ((,class :inherit shadow))) `(magit-refname-pullreq ((,class :inherit shadow))) `(magit-refname-stash ((,class :inherit shadow))) @@ -6094,21 +6174,21 @@ by virtue of calling either of `modus-themes-load-operandi' and `(magit-section-heading ((,class :inherit bold :foreground ,cyan))) `(magit-section-heading-selection ((,class :inherit (modus-themes-refine-cyan bold)))) `(magit-section-highlight ((,class :background ,bg-alt))) - `(magit-sequence-done ((,class :inherit modus-themes-grue))) - `(magit-sequence-drop ((,class :foreground ,red-alt))) - `(magit-sequence-exec ((,class :foreground ,magenta-alt))) - `(magit-sequence-head ((,class :foreground ,cyan-alt))) - `(magit-sequence-onto ((,class :inherit shadow))) - `(magit-sequence-part ((,class :foreground ,yellow-alt))) - `(magit-sequence-pick ((,class :foreground ,blue-alt))) - `(magit-sequence-stop ((,class :foreground ,red))) - `(magit-signature-bad ((,class :inherit bold :foreground ,red))) - `(magit-signature-error ((,class :foreground ,red-alt))) - `(magit-signature-expired ((,class :foreground ,yellow))) + `(magit-sequence-done ((,class :inherit success))) + `(magit-sequence-drop ((,class :inherit error))) + `(magit-sequence-exec ((,class :inherit bold :foreground ,magenta-alt))) + `(magit-sequence-head ((,class :inherit bold :foreground ,cyan-alt))) + `(magit-sequence-onto ((,class :inherit (bold shadow)))) + `(magit-sequence-part ((,class :inherit warning))) + `(magit-sequence-pick ((,class :inherit bold))) + `(magit-sequence-stop ((,class :inherit error))) + `(magit-signature-bad ((,class :inherit error))) + `(magit-signature-error ((,class :inherit error))) + `(magit-signature-expired ((,class :inherit warning))) `(magit-signature-expired-key ((,class :foreground ,yellow))) - `(magit-signature-good ((,class :inherit modus-themes-grue))) - `(magit-signature-revoked ((,class :foreground ,magenta))) - `(magit-signature-untrusted ((,class :foreground ,cyan))) + `(magit-signature-good ((,class :inherit success))) + `(magit-signature-revoked ((,class :inherit bold :foreground ,magenta))) + `(magit-signature-untrusted ((,class :inherit (bold shadow)))) `(magit-tag ((,class :foreground ,yellow-alt-other))) ;;;;; magit-imerge `(magit-imerge-overriding-value ((,class :inherit bold :foreground ,red-alt))) @@ -6116,9 +6196,8 @@ by virtue of calling either of `modus-themes-load-operandi' and `(makefile-makepp-perl ((,class :background ,cyan-nuanced-bg))) `(makefile-space ((,class :background ,magenta-nuanced-bg))) ;;;;; man - `(Man-overstrike ((,class :inherit bold :foreground ,magenta))) + `(Man-overstrike ((,class :inherit bold :foreground ,fg-special-calm))) `(Man-reverse ((,class :inherit modus-themes-subtle-magenta))) - `(Man-underline ((,class :foreground ,cyan :underline t))) ;;;;; marginalia `(marginalia-archive ((,class :foreground ,cyan-alt-other))) `(marginalia-char ((,class :foreground ,magenta))) @@ -6134,14 +6213,8 @@ by virtue of calling either of `modus-themes-load-operandi' and `(marginalia-file-priv-rare ((,class :foreground ,red))) `(marginalia-file-priv-read ((,class :foreground ,fg-main))) `(marginalia-file-priv-write ((,class :foreground ,cyan))) - ;; Here we make an exception of not applying the bespoke - ;; `modus-themes-key-binding' for two reasons: (1) completion - ;; highlights can be fairly intense, so we do not want more - ;; components to compete with them for attention, (2) the - ;; `marginalia-key' may not be used for key bindings specifically, - ;; so we might end up applying styles in places we should not. `(marginalia-function ((,class :foreground ,magenta-alt-faint))) - `(marginalia-key ((,class :foreground ,magenta-alt-other))) + `(marginalia-key ((,class :inherit modus-themes-completion-key-binding))) `(marginalia-lighter ((,class :foreground ,blue-alt))) `(marginalia-list ((,class :foreground ,magenta-alt-other-faint))) `(marginalia-mode ((,class :foreground ,cyan))) @@ -6172,6 +6245,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(markdown-header-face-5 ((,class :inherit modus-themes-heading-5))) `(markdown-header-face-6 ((,class :inherit modus-themes-heading-6))) `(markdown-header-rule-face ((,class :inherit bold :foreground ,fg-special-warm))) + `(markdown-highlighting-face ((,class :inherit modus-themes-refine-yellow))) `(markdown-hr-face ((,class :inherit bold :foreground ,fg-special-warm))) `(markdown-html-attr-name-face ((,class :inherit modus-themes-fixed-pitch :foreground ,cyan))) @@ -6237,6 +6311,8 @@ by virtue of calling either of `modus-themes-load-operandi' and `(markup-title-4-face ((,class :inherit modus-themes-heading-5))) `(markup-title-5-face ((,class :inherit modus-themes-heading-6))) `(markup-verbatim-face ((,class :inherit modus-themes-fixed-pitch :background ,bg-alt))) +;;;;; mct + `(mct-highlight-candidate ((,class :inherit modus-themes-completion-standard-selected))) ;;;;; mentor `(mentor-download-message ((,class :foreground ,fg-special-warm))) `(mentor-download-name ((,class :foreground ,fg-special-cold))) @@ -6248,10 +6324,10 @@ by virtue of calling either of `modus-themes-load-operandi' and `(mentor-highlight-face ((,class :inherit modus-themes-subtle-blue))) `(mentor-tracker-name ((,class :foreground ,magenta-alt))) ;;;;; messages - `(message-cited-text-1 ((,class ,@(modus-themes--mail-cite blue-faint fg-alt)))) - `(message-cited-text-2 ((,class ,@(modus-themes--mail-cite green-faint fg-comment-yellow)))) - `(message-cited-text-3 ((,class ,@(modus-themes--mail-cite red-faint fg-special-cold)))) - `(message-cited-text-4 ((,class ,@(modus-themes--mail-cite yellow-faint fg-special-calm)))) + `(message-cited-text-1 ((,class ,@(modus-themes--mail-cite blue-faint blue fg-special-cold)))) + `(message-cited-text-2 ((,class ,@(modus-themes--mail-cite yellow-faint yellow yellow-alt-faint)))) + `(message-cited-text-3 ((,class ,@(modus-themes--mail-cite magenta-alt-faint magenta-alt fg-special-calm)))) + `(message-cited-text-4 ((,class ,@(modus-themes--mail-cite cyan-alt-other-faint cyan-alt-other fg-special-mild)))) `(message-header-cc ((,class :foreground ,blue-alt-other))) `(message-header-name ((,class :inherit bold :foreground ,cyan))) `(message-header-newsgroups ((,class :inherit message-header-other))) @@ -6283,8 +6359,8 @@ by virtue of calling either of `modus-themes-load-operandi' and 'alt-style bg-main)))) `(mode-line-active ((,class :inherit mode-line))) `(mode-line-buffer-id ((,class :inherit bold))) - `(mode-line-emphasis ((,class :inherit bold :foreground ,blue-active))) - `(mode-line-highlight ((,class :inherit modus-themes-active-blue :box (:line-width -1 :style pressed-button)))) + `(mode-line-emphasis ((,class :inherit bold :foreground ,magenta-active))) + `(mode-line-highlight ((,class :inherit highlight))) `(mode-line-inactive ((,class :inherit modus-themes-ui-variable-pitch ,@(modus-themes--mode-line-attrs fg-inactive bg-inactive @@ -6436,19 +6512,19 @@ by virtue of calling either of `modus-themes-load-operandi' and ;;;;; orderless `(orderless-match-face-0 ((,class :inherit bold ,@(modus-themes--standard-completions - blue-alt-other blue-nuanced-bg + blue-alt-other bg-special-cold fg-special-cold blue-refine-bg blue-refine-fg)))) `(orderless-match-face-1 ((,class :inherit bold ,@(modus-themes--standard-completions - magenta-alt magenta-nuanced-bg + magenta-alt bg-special-calm fg-special-calm magenta-refine-bg magenta-refine-fg)))) `(orderless-match-face-2 ((,class :inherit bold ,@(modus-themes--standard-completions - green green-nuanced-bg + green bg-special-mild fg-special-mild green-refine-bg green-refine-fg)))) `(orderless-match-face-3 ((,class :inherit bold ,@(modus-themes--standard-completions - yellow yellow-nuanced-bg + yellow bg-special-warm fg-special-warm yellow-refine-bg yellow-refine-fg)))) ;;;;; org `(org-agenda-calendar-event ((,class ,@(modus-themes--agenda-event blue-alt)))) @@ -6489,10 +6565,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(org-checkbox-statistics-done ((,class :inherit org-done))) `(org-checkbox-statistics-todo ((,class :inherit org-todo))) `(org-clock-overlay ((,class :inherit modus-themes-special-cold))) - `(org-code ((,class :inherit modus-themes-fixed-pitch - ,@(modus-themes--markup fg-special-mild green-alt-other - bg-alt green-nuanced-bg) - :extend t))) + `(org-code ((,class :inherit modus-themes-markup-code :extend t))) `(org-column ((,class :inherit (modus-themes-fixed-pitch default) :background ,bg-alt))) `(org-column-title ((,class :inherit (bold modus-themes-fixed-pitch default) @@ -6515,7 +6588,8 @@ by virtue of calling either of `modus-themes-load-operandi' and `(org-habit-alert-face ((,class ,@(modus-themes--agenda-habit yellow-graph-0-bg yellow-graph-0-bg - yellow-graph-1-bg)))) + yellow-graph-1-bg) + :foreground "black"))) ; special case `(org-habit-alert-future-face ((,class ,@(modus-themes--agenda-habit yellow-graph-1-bg yellow-graph-0-bg @@ -6524,11 +6598,14 @@ by virtue of calling either of `modus-themes-load-operandi' and blue-graph-0-bg green-graph-1-bg blue-graph-1-bg - blue-graph-1-bg)))) + blue-graph-1-bg + blue-graph-1-bg) + :foreground "black"))) ; special case `(org-habit-clear-future-face ((,class ,@(modus-themes--agenda-habit blue-graph-1-bg green-graph-1-bg blue-graph-1-bg + blue-graph-1-bg blue-graph-1-bg)))) `(org-habit-overdue-face ((,class ,@(modus-themes--agenda-habit red-graph-0-bg @@ -6542,12 +6619,17 @@ by virtue of calling either of `modus-themes-load-operandi' and green-graph-0-bg green-graph-0-bg green-graph-1-bg - blue-graph-0-bg)))) + cyan-graph-0-bg + blue-graph-0-bg + cyan-graph-1-bg) + :foreground "black"))) ; special case `(org-habit-ready-future-face ((,class ,@(modus-themes--agenda-habit green-graph-1-bg green-graph-0-bg green-graph-1-bg - blue-graph-0-bg)))) + cyan-graph-1-bg + blue-graph-0-bg + cyan-graph-1-bg)))) `(org-headline-done ((,class :inherit (modus-themes-variable-pitch modus-themes-grue-nuanced)))) `(org-headline-todo ((,class :inherit modus-themes-variable-pitch :foreground ,red-nuanced-fg))) `(org-hide ((,class :foreground ,bg-main))) @@ -6564,9 +6646,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(org-level-8 ((,class :inherit modus-themes-heading-8))) `(org-link ((,class :inherit button))) `(org-list-dt ((,class :inherit bold))) - `(org-macro ((,class :inherit modus-themes-fixed-pitch - ,@(modus-themes--markup cyan-nuanced-fg cyan - cyan-nuanced-bg cyan-nuanced-bg)))) + `(org-macro ((,class :inherit modus-themes-markup-macro))) `(org-meta-line ((,class :inherit (shadow modus-themes-fixed-pitch)))) `(org-mode-line-clock ((,class :foreground ,fg-main))) `(org-mode-line-clock-overrun ((,class :inherit bold :foreground ,red-active))) @@ -6734,6 +6814,10 @@ by virtue of calling either of `modus-themes-load-operandi' and `(prodigy-yellow-face ((,class :inherit warning))) ;;;;; pulse `(pulse-highlight-start-face ((,class :background ,bg-active-accent :extend t))) +;;;;; pyim + `(pyim-page ((,class :background ,bg-active :foreground ,fg-active))) + `(pyim-page-selection ((,class :inherit bold :background ,bg-active :foreground ,blue-active))) + `(pyim-page-subword ((,class :background ,bg-inactive))) ;;;;; quick-peek `(quick-peek-background-face ((,class :background ,bg-alt))) `(quick-peek-border-face ((,class :background ,fg-window-divider-inner :height 1))) @@ -6834,11 +6918,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(ruler-mode-pad ((,class :inherit ruler-mode-default :background ,bg-active :foreground ,fg-inactive))) `(ruler-mode-tab-stop ((,class :inherit ruler-mode-default :foreground ,fg-special-warm))) ;;;;; selectrum - `(selectrum-current-candidate - ((,class :inherit bold :foreground ,fg-main - :background ,@(pcase modus-themes-completions - ('opinionated (list bg-active)) - (_ (list bg-inactive)))))) + `(selectrum-current-candidate ((,class :inherit modus-themes-completion-standard-selected))) `(selectrum-mouse-highlight ((,class :inherit highlight))) `(selectrum-quick-keys-highlight ((,class :inherit modus-themes-refine-red))) @@ -6848,12 +6928,12 @@ by virtue of calling either of `modus-themes-load-operandi' and `(selectrum-prescient-primary-highlight ((,class :inherit bold ,@(modus-themes--standard-completions - magenta-alt magenta-nuanced-bg + magenta-alt bg-special-calm fg-special-calm magenta-refine-bg magenta-refine-fg)))) `(selectrum-prescient-secondary-highlight ((,class :inherit bold ,@(modus-themes--standard-completions - cyan-alt-other cyan-nuanced-bg + cyan-alt-other bg-special-cold fg-special-cold cyan-refine-bg cyan-refine-fg)))) ;;;;; semantic `(semantic-complete-inline-face ((,class :foreground ,fg-special-warm :underline t))) @@ -6903,6 +6983,33 @@ by virtue of calling either of `modus-themes-load-operandi' and `(sieve-test-commands ((,class :inherit font-lock-function-name-face))) ;;;;; skewer-mode `(skewer-error-face ((,class :foreground ,red :underline t))) +;;;;; slime (sldb) + `(sldb-condition-face ((,class :inherit font-lock-preprocessor-face))) + `(sldb-restart-number-face ((,class :inherit bold))) + `(sldb-restart-type-face ((,class :inherit font-lock-type-face))) + `(sldb-restartable-frame-line-face ((,class :inherit success))) + `(sldb-section-face ((,class :inherit modus-themes-pseudo-header))) + `(slime-error-face ((,class :inherit modus-themes-lang-error))) + `(slime-note-face ((,class :underline t))) + `(slime-repl-input-face ((,class :inherit bold))) + `(slime-repl-inputed-output-face ((,class :inherit font-lock-string-face))) + `(slime-repl-output-mouseover-face ((,class :inherit highlight))) + `(slime-repl-prompt-face ((,class :inherit modus-themes-prompt))) + `(slime-style-warning-face ((,class :inherit modus-themes-lang-note))) + `(slime-warning-face ((,class :inherit modus-themes-lang-warning))) +;;;;; sly + `(sly-action-face ((,class :inherit font-lock-type-face))) + `(sly-db-condition-face ((,class :inherit font-lock-preprocessor-face))) + `(sly-db-restartable-frame-line-face ((,class :inherit success))) + `(sly-error-face ((,class :inherit modus-themes-lang-error))) + `(sly-mode-line ((,class :inherit mode-line-emphasis))) + `(sly-mrepl-output-face ((,class :inherit font-lock-string-face))) + `(sly-mrepl-output-face ((,class :inherit font-lock-string-face))) + `(sly-mrepl-prompt-face ((,class :inherit modus-themes-prompt))) + `(sly-note-face ((,class :inherit modus-themes-lang-note))) + `(sly-stickers-placed-face ((,class :inherit modus-themes-subtle-neutral))) + `(sly-style-warning-face ((,class :inherit modus-themes-lang-note))) + `(sly-warning-face ((,class :inherit modus-themes-lang-warning))) ;;;;; smart-mode-line `(sml/charging ((,class :foreground ,green-active))) `(sml/discharging ((,class :foreground ,red-active))) @@ -7082,6 +7189,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(telega-entity-type-code ((,class :inherit modus-themes-fixed-pitch))) `(telega-entity-type-mention ((,class :foreground ,cyan))) `(telega-entity-type-pre ((,class :inherit modus-themes-fixed-pitch))) + `(telega-entity-type-spoiler ((,class :background ,fg-main :foreground ,fg-main))) `(telega-msg-heading ((,class :background ,bg-alt))) `(telega-msg-self-title ((,class :inherit bold))) `(telega-root-heading ((,class :inherit modus-themes-subtle-neutral))) @@ -7128,6 +7236,8 @@ by virtue of calling either of `modus-themes-load-operandi' and `(term-color-white ((,class :background "gray65" :foreground "gray65"))) `(term-color-yellow ((,class :background ,yellow :foreground ,yellow))) `(term-underline ((,class :underline t))) +;;;;; textsec + `(textsec-suspicious ((,class :inherit modus-themes-refine-red))) ;;;;; tomatinho `(tomatinho-ok-face ((,class :foreground ,blue-intense))) `(tomatinho-pause-face ((,class :foreground ,yellow-intense))) @@ -7135,7 +7245,7 @@ by virtue of calling either of `modus-themes-load-operandi' and ;;;;; transient `(transient-active-infix ((,class :inherit modus-themes-special-mild))) `(transient-amaranth ((,class :inherit bold :foreground ,yellow-alt))) - `(transient-argument ((,class :inherit bold :foreground ,green))) + `(transient-argument ((,class :inherit bold :background ,cyan-nuanced-bg :foreground ,cyan))) `(transient-blue ((,class :inherit bold :foreground ,blue))) `(transient-disabled-suffix ((,class :inherit modus-themes-intense-red))) `(transient-enabled-suffix ((,class :inherit modus-themes-grue-background-subtle))) @@ -7146,11 +7256,12 @@ by virtue of calling either of `modus-themes-load-operandi' and `(transient-mismatched-key ((,class :underline t))) `(transient-nonstandard-key ((,class :underline t))) `(transient-pink ((,class :inherit bold :foreground ,magenta-alt-faint))) + `(transient-purple ((,class :inherit bold :foreground ,magenta-alt-other))) `(transient-red ((,class :inherit bold :foreground ,red-faint))) `(transient-teal ((,class :inherit bold :foreground ,cyan-alt-other))) - `(transient-unreachable ((,class :foreground ,fg-unfocused))) - `(transient-unreachable-key ((,class :foreground ,fg-unfocused))) - `(transient-value ((,class :inherit bold :foreground ,magenta-alt-other))) + `(transient-unreachable ((,class :inherit shadow))) + `(transient-unreachable-key ((,class :inherit shadow))) + `(transient-value ((,class :inherit bold :background ,yellow-nuanced-bg :foreground ,yellow-alt-other))) ;;;;; trashed `(trashed-deleted ((,class :inherit modus-themes-mark-del))) `(trashed-directory ((,class :foreground ,blue))) @@ -7237,10 +7348,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(vc-state-base ((,class :foreground ,fg-active))) `(vc-up-to-date-state ((,class :foreground ,fg-special-cold))) ;;;;; vertico - `(vertico-current ((,class :inherit bold :foreground ,fg-main - :background ,@(pcase modus-themes-completions - ('opinionated (list bg-active)) - (_ (list bg-inactive)))))) + `(vertico-current ((,class :inherit modus-themes-completion-standard-selected))) ;;;;; vertico-quick `(vertico-quick1 ((,class :inherit (modus-themes-intense-magenta bold)))) `(vertico-quick2 ((,class :inherit (modus-themes-refine-cyan bold)))) @@ -7365,7 +7473,7 @@ by virtue of calling either of `modus-themes-load-operandi' and `(which-key-local-map-description-face ((,class :foreground ,fg-main))) `(which-key-note-face ((,class :foreground ,fg-special-warm))) `(which-key-separator-face ((,class :inherit shadow))) - `(which-key-special-key-face ((,class :inherit bold :foreground ,orange-intense))) + `(which-key-special-key-face ((,class :inherit bold :foreground ,red-alt))) ;;;;; whitespace-mode `(whitespace-big-indent ((,class :inherit modus-themes-subtle-red))) `(whitespace-empty ((,class :inherit modus-themes-intense-magenta))) @@ -7390,9 +7498,8 @@ by virtue of calling either of `modus-themes-load-operandi' and `(writegood-weasels-face ((,class :inherit modus-themes-lang-error))) ;;;;; woman `(woman-addition ((,class :foreground ,magenta-alt-other))) - `(woman-bold ((,class :inherit bold :foreground ,magenta))) - `(woman-italic ((,class :inherit italic :foreground ,cyan))) - `(woman-unknown ((,class :inherit italic :foreground ,yellow))) + `(woman-bold ((,class :inherit bold :foreground ,fg-special-calm))) + `(woman-unknown ((,class :foreground ,cyan))) ;;;;; xah-elisp-mode `(xah-elisp-at-symbol ((,class :inherit font-lock-warning-face))) `(xah-elisp-cap-variable ((,class :inherit font-lock-preprocessor-face))) diff --git a/etc/themes/modus-vivendi-theme.el b/etc/themes/modus-vivendi-theme.el index 738753741c..3e78a6c959 100644 --- a/etc/themes/modus-vivendi-theme.el +++ b/etc/themes/modus-vivendi-theme.el @@ -1,10 +1,10 @@ -;;; modus-vivendi-theme.el --- Accessible dark theme (WCAG AAA) -*- lexical-binding:t -*- +;;; modus-vivendi-theme.el --- Accessible and customizable dark theme (WCAG AAA) -*- lexical-binding:t -*- -;; Copyright (C) 2019-2022 Free Software Foundation, Inc. +;; Copyright (C) 2019-2022 Free Software Foundation, Inc. ;; Author: Protesilaos Stavrou ;; URL: https://gitlab.com/protesilaos/modus-themes -;; Version: 2.0.0 +;; Version: 2.1.0 ;; Package-Requires: ((emacs "27.1")) ;; Keywords: faces, theme, accessibility commit 136f1cb54962f5dcae9e8b63e41e4df70995599c Author: Lars Ingebrigtsen Date: Thu Feb 17 12:31:12 2022 +0100 Have setopt check types * doc/lispref/variables.texi (Setting Variables): Note type checking. * lisp/cus-edit.el (setopt--set): New function to avoid having Customize saving values, too. (setopt): Use it. diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index a520b3856c..d991ae9e27 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -886,6 +886,10 @@ will also issue a message: (setopt my-var 2) @end example +@code{setopt} also checks whether the value is valid for the user +option. For instance, using @code{setopt} to set a user option +defined with a @code{number} type to a string will signal an error. + The @code{setopt} macro can be used on regular, non-user option variables, but is much less efficient than @code{setq}. The main use case for this macro is setting user options in the user's init file. diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index bb7ffc1eae..bec7348099 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1049,10 +1049,7 @@ If given a prefix (or a COMMENT argument), also prompt for a comment." "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 -Customize form associated with VARIABLE. - -If VARIABLE has a `custom-set' property, that is used for setting -VARIABLE, otherwise `set-default' is used. +`custom-set' form associated with VARIABLE. \(fn [VARIABLE VALUE]...)" (declare (debug setq)) @@ -1062,11 +1059,20 @@ VARIABLE, otherwise `set-default' is used. (while pairs (unless (symbolp (car pairs)) (error "Attempting to set a non-symbol: %s" (car pairs))) - (push `(customize-set-variable ',(car pairs) ,(cadr pairs)) + (push `(setopt--set ',(car pairs) ,(cadr pairs)) expr) (setq pairs (cddr pairs))) (macroexp-progn (nreverse expr)))) +;;;###autoload +(defun setopt--set (variable value) + (custom-load-symbol variable) + ;; Check that the type is correct. + (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))) + (funcall (or (get variable 'custom-set) #'set-default) variable value)) + ;;;###autoload (defun customize-save-variable (variable value &optional comment) "Set the default for VARIABLE to VALUE, and save it for future sessions. diff --git a/test/lisp/cus-edit-tests.el b/test/lisp/cus-edit-tests.el index 01a1407dca..7a597ccf34 100644 --- a/test/lisp/cus-edit-tests.el +++ b/test/lisp/cus-edit-tests.el @@ -76,5 +76,13 @@ (customize-saved) (should (search-forward cus-edit-tests--obsolete-option-tag nil t))))) +(ert-deftest test-setopt () + (defcustom cus-edit-test-foo1 0 + "" + :type 'number) + (should (= (setopt cus-edit-test-foo1 1) 1)) + (should (= cus-edit-test-foo1 1)) + (should-error (setopt cus-edit-test-foo1 :foo))) + (provide 'cus-edit-tests) ;;; cus-edit-tests.el ends here commit 33a9ee2084f860610dbdc67bd3db237dcb64202e Author: Po Lu Date: Thu Feb 17 19:10:24 2022 +0800 Fix warning during dumping on MS-DOS * lisp/cus-start.el (standard): Filter out `process-error-pause-time' on MS-DOS. diff --git a/lisp/cus-start.el b/lisp/cus-start.el index f8bab89e90..83ab61b28b 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -858,6 +858,8 @@ since it could result in memory overflow and make Emacs crash." (featurep 'ns)) ((string-match "\\`haiku-" (symbol-name symbol)) (featurep 'haiku)) + ((eq symbol 'process-error-pause-time) + (not (eq system-type 'ms-dos))) ((eq symbol 'x-gtk-use-native-input) (and (featurep 'x) (featurep 'gtk))) commit c0fa3f2a6b8ce06af59f5e70cf1757189bd401f0 Author: Po Lu Date: Thu Feb 17 18:01:30 2022 +0800 Prevent menu items leak if x-pre-popup-menu-hook signals * src/menu.c (x_popup_menu_1): Make sure menu items are discarded if the pre popup menu hook signals. diff --git a/src/menu.c b/src/menu.c index ad4e3abe9f..398bf9329f 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1391,9 +1391,7 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu) } #endif -#ifdef HAVE_NS /* FIXME: ns-specific, why? --Stef */ record_unwind_protect_void (discard_menu_items); -#endif run_hook (Qx_pre_popup_menu_hook); @@ -1404,11 +1402,7 @@ x_popup_menu_1 (Lisp_Object position, Lisp_Object menu) selection = FRAME_TERMINAL (f)->menu_show_hook (f, xpos, ypos, menuflags, title, &error_name); -#ifdef HAVE_NS unbind_to (specpdl_count, Qnil); -#else - discard_menu_items (); -#endif #ifdef HAVE_NTGUI /* W32 specific because other terminals clear the grab inside their `menu_show_hook's if commit 3750612093e5383afa55ea261f47737868660942 Author: Michael Albinus Date: Thu Feb 17 10:40:52 2022 +0100 Fix problem with "~" in Tramp * lisp/net/tramp.el (tramp-handle-substitute-in-file-name): Remove special handling of "~" in localname. (Bug#53053) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 91c0efb482..0ffaeb0ce9 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -4571,10 +4571,7 @@ BUFFER might be a list, in this case STDERR is separated." ;; We must disable cygwin-mount file name ;; handlers and alike. (tramp-run-real-handler - #'substitute-in-file-name (list localname)))))))) - ;; "/m:h:~" does not work for completion. We use "/m:h:~/". - (if (and (stringp localname) (string-equal "~" localname)) - (concat filename "/") + #'substitute-in-file-name (list localname))))))) filename)))) (defconst tramp-time-dont-know '(0 0 0 1000) commit b30ef0991915fbcab016a9485b1dece6f15f801c Author: Po Lu Date: Thu Feb 17 15:35:41 2022 +0800 Prevent crashes caused by invalid locale coding systems * src/xterm.c (handle_one_xevent): Prevent a signal inside `setup_coding_system' which crashes recent versions of GLib if the locale coding system is invalid. Do not merge to master. diff --git a/src/xterm.c b/src/xterm.c index b80d45f855..59413eafd4 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -8739,6 +8739,15 @@ handle_one_xevent (struct x_display_info *dpyinfo, { /* Decode the input data. */ +#ifdef HAVE_GLIB + /* If this isn't done in a build with GLib (usually + with GTK), then the resulting signal in + `setup_coding_system' will cause Emacs to + crash. */ + if (NILP (Fcoding_system_p (coding_system))) + coding_system = Qraw_text; +#endif + /* The input should be decoded with `coding_system' which depends on which X*LookupString function we used just above and the locale. */ commit c8442df581feb45d50530b372152beff9d23211d Author: Jonas Bernoulli Date: Wed Feb 16 13:06:17 2022 +0100 ; Separate command and concept index in Transient manual * doc/misc/transient.texi (cp): Use cp index for Concept index. * doc/misc/transient.texi (fn): Use fn index for Commands as well. diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index eea9489721..bf048841a6 100644 --- a/doc/misc/transient.texi +++ b/doc/misc/transient.texi @@ -79,9 +79,9 @@ This manual is for Transient version 0.3.7. * Related Abstractions and Packages:: * FAQ:: * Keystroke Index:: -* Command Index:: -* Function Index:: +* Command and Function Index:: * Variable Index:: +* Concept Index:: * GNU General Public License:: @detailmenu @@ -326,10 +326,10 @@ the latter, then you can later resume the stack of transients using @table @asis @kindex C-g -@cindex transient-quit-seq +@findex transient-quit-seq @item @kbd{C-g} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-seq}) @kindex C-g -@cindex transient-quit-one +@findex transient-quit-one @item @kbd{C-g} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-one}) This key quits the currently active incomplete key sequence, if any, @@ -343,7 +343,7 @@ doc string. @table @asis @kindex C-q -@cindex transient-quit-all +@findex transient-quit-all @item @kbd{C-q} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-all}) This command quits the currently active incomplete key sequence, if @@ -351,7 +351,7 @@ any, and all transients, including the active transient and all suspended transients, if any. @kindex C-z -@cindex transient-suspend +@findex transient-suspend @item @kbd{C-z} @tie{}@tie{}@tie{}@tie{}(@code{transient-suspend}) Like @code{transient-quit-all}, this command quits an incomplete key @@ -366,7 +366,7 @@ If another stack is already saved, then saving a new stack discards the previous stack. @kindex M-x transient-resume -@cindex transient-resume +@findex transient-resume @item @kbd{M-x transient-resume} @tie{}@tie{}@tie{}@tie{}(@code{transient-resume}) This command resumes the previously suspended stack of transients, @@ -390,7 +390,7 @@ common commands to always be shown for all transients. @table @asis @kindex C-x t -@cindex transient-toggle-common +@findex transient-toggle-common @item @kbd{C-x t} @tie{}@tie{}@tie{}@tie{}(@code{transient-toggle-common}) This command toggles whether the generic commands that are common to @@ -441,14 +441,14 @@ but it is easily accessible (@pxref{Using History}). @table @asis @kindex C-x s -@cindex transient-set +@findex transient-set @item @kbd{C-x s} @tie{}@tie{}@tie{}@tie{}(@code{transient-set}) This command saves the value of the active transient for this Emacs session. @kindex C-x C-s -@cindex transient-save +@findex transient-save @item @kbd{C-x C-s} @tie{}@tie{}@tie{}@tie{}(@code{transient-save}) Save the value of the active transient persistently across Emacs @@ -473,20 +473,20 @@ user-input in the minibuffer. @table @asis @kindex C-M-p -@cindex transient-history-prev +@findex transient-history-prev @item @kbd{C-M-p} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-prev}) @kindex C-x p -@cindex transient-history-prev +@findex transient-history-prev @item @kbd{C-x p} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-prev}) This command switches to the previous value used for the active transient. @kindex C-M-n -@cindex transient-history-next +@findex transient-history-next @item @kbd{C-M-n} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-next}) @kindex C-x n -@cindex transient-history-next +@findex transient-history-next @item @kbd{C-x n} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-next}) This command switches to the next value used for the active @@ -528,7 +528,7 @@ transient. @table @asis @kindex C-h -@cindex transient-help +@findex transient-help @item @kbd{C-h} @tie{}@tie{}@tie{}@tie{}(@code{transient-help}) This command enters help mode. When help mode is active, @@ -596,7 +596,7 @@ transients and their suffixes between Emacs sessions. @table @asis @kindex C-x l -@cindex transient-set-level +@findex transient-set-level @item @kbd{C-x l} @tie{}@tie{}@tie{}@tie{}(@code{transient-set-level}) This command enters edit mode. When edit mode is active, then all @@ -633,7 +633,7 @@ following commands. These commands are never shown in the transient window, and the key bindings are the same as for @code{scroll-up-command} and @code{scroll-down-command} in other buffers. -@cindex transient-scroll-up arg +@findex transient-scroll-up arg @deffn Command transient-scroll-up arg This command scrolls text of transient popup window upward @var{arg} @@ -641,7 +641,7 @@ lines. If @var{arg} is @code{nil}, then it scrolls near full screen. This is a wrapper around @code{scroll-up-command} (which see). @end deffn -@cindex transient-scroll-down arg +@findex transient-scroll-down arg @deffn Command transient-scroll-down arg This command scrolls text of transient popup window down @var{arg} @@ -2537,13 +2537,8 @@ necessary changes. See its doc string for more information. @printindex ky -@node Command Index -@appendix Command Index - -@printindex cp - -@node Function Index -@appendix Function Index +@node Command and Function Index +@appendix Command and Function Index @printindex fn @@ -2552,6 +2547,11 @@ necessary changes. See its doc string for more information. @printindex vr +@node Concept Index +@appendix Concept and Feature Index + +@printindex cp + @node GNU General Public License @appendix GNU General Public License commit 8aa052c207d8b4f9572437f120c868b9f4a7cdaa Author: Eli Zaretskii Date: Tue Feb 15 21:06:21 2022 +0200 ; Fix Transient manual * doc/misc/transient.texi (all nodes): Replace ".." with Texinfo style ``..'' quoting or by @dfn{..} or by other appropriate markup, like @samp{..}. Add indexing. Fix punctuation. Fix markup of keyboard commands. diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index 17b7bef6b7..eea9489721 100644 --- a/doc/misc/transient.texi +++ b/doc/misc/transient.texi @@ -47,11 +47,11 @@ General Public License for more details. Taking inspiration from prefix keys and prefix arguments, Transient implements a similar abstraction involving a prefix command, infix arguments and suffix commands. We could call this abstraction a -"transient command", but because it always involves at least two +``transient command'', but because it always involves at least two commands (a prefix and a suffix) we prefer to call it just a -"transient". +``transient''. -When the user calls a transient prefix command, then a transient +When the user calls a transient prefix command, a transient (temporary) keymap is activated, which binds the transient's infix and suffix commands, and functions that control the transient state are added to @code{pre-command-hook} and @code{post-command-hook}. The available @@ -144,23 +144,24 @@ Related Abstractions and Packages Taking inspiration from prefix keys and prefix arguments, Transient implements a similar abstraction involving a prefix command, infix arguments and suffix commands. We could call this abstraction a -"transient command", but because it always involves at least two +``transient command'', but because it always involves at least two commands (a prefix and a suffix) we prefer to call it just a -"transient". +``transient''. @quotation Transient keymaps are a feature provided by Emacs. Transients as implemented by this package involve the use of transient keymaps. -Emacs provides a feature that it calls "prefix commands". When we -talk about "prefix commands" in this manual, then we mean our own kind -of "prefix commands", unless specified otherwise. To avoid ambiguity -we sometimes use the terms "transient prefix command" for our kind and -"regular prefix command" for Emacs' kind. +@cindex transient prefix command +Emacs provides a feature that it calls @dfn{prefix commands}. When we +talk about ``prefix commands'' in this manual, then we mean our own kind +of ``prefix commands'', unless specified otherwise. To avoid ambiguity +we sometimes use the terms @dfn{transient prefix command} for our kind and +``regular prefix command'' for the Emacs' kind. @end quotation -When the user calls a transient prefix command, then a transient +When the user calls a transient prefix command, a transient (temporary) keymap is activated, which binds the transient's infix and suffix commands, and functions that control the transient state are added to @code{pre-command-hook} and @code{post-command-hook}. The available suffix @@ -184,7 +185,7 @@ the transient. A suffix command can, but does not have to, use the infix arguments in much the same way any command can choose to use or ignore the prefix -arguments. For a suffix command that was invoked from a transient the +arguments. For a suffix command that was invoked from a transient, the variable @code{transient-current-suffixes} and the function @code{transient-args} serve about the same purpose as the variables @code{prefix-arg} and @code{current-prefix-arg} do for any command that was called after the prefix @@ -207,14 +208,15 @@ looks a bit like this: @quotation This is a simplified version of @code{magit-tag}. Info manuals do not -support images or colored text, so the above "screenshot" lacks some +support images or colored text, so the above ``screenshot'' lacks some information; in practice you would be able to tell whether the arguments @code{--force} and @code{--annotate} are enabled or not based on their color. @end quotation -Transient can be used to implement simple "command dispatchers". The +@cindex command dispatchers +Transient can be used to implement simple ``command dispatchers''. The main benefit then is that the user can see all the available commands in a popup buffer. That is useful by itself because it frees the user from having to remember all the keys that are valid after a certain @@ -226,36 +228,36 @@ In addition to that, Transient also allows users to interactively pass arguments to commands. These arguments can be much more complex than what is reasonable when using prefix arguments. There is a limit to how many aspects of a command can be controlled using prefix -arguments. Furthermore what a certain prefix argument means for +arguments. Furthermore, what a certain prefix argument means for different commands can be completely different, and users have to read documentation to learn and then commit to memory what a certain prefix argument means to a certain command. -Transient suffix commands on the other hand can accept dozens of +Transient suffix commands, on the other hand, can accept dozens of different arguments without the user having to remember anything. -When using Transient, then one can call a command with arguments that +When using Transient, one can call a command with arguments that are just as complex as when calling the same function non-interactively -using code. +from Lisp. Invoking a transient command with arguments is similar to invoking a command in a shell with command-line completion and history enabled. One benefit of the Transient interface is that it remembers history -not only on a global level ("this command was invoked using these -arguments and previously it was invoked using those other arguments"), +not only on a global level (``this command was invoked using these +arguments, and previously it was invoked using those other arguments''), but also remembers the values of individual arguments independently. -See @ref{Using History}. +@xref{Using History}. -After a transient prefix command is invoked @code{C-h } can be used to -show the documentation for the infix or suffix command that @code{} is -bound to (see @ref{Getting Help for Suffix Commands}) and infixes and -suffixes can be removed from the transient using @code{C-x l }. Infixes +After a transient prefix command is invoked, @kbd{C-h @var{key}} can be used to +show the documentation for the infix or suffix command that @kbd{@var{key}} is +bound to (@pxref{Getting Help for Suffix Commands}), and infixes and +suffixes can be removed from the transient using @kbd{C-x l @var{key}}. Infixes and suffixes that are disabled by default can be enabled the same way. -See @ref{Enabling and Disabling Suffixes}. +@xref{Enabling and Disabling Suffixes}. Transient ships with support for a few different types of specialized -infix commands. A command that sets a command line option for example +infix commands. A command that sets a command line option, for example, has different needs than a command that merely toggles a boolean flag. -Additionally Transient provides abstractions for defining new types, +Additionally, Transient provides abstractions for defining new types, which the author of Transient did not anticipate (or didn't get around to implementing yet). @@ -276,6 +278,7 @@ to implementing yet). @node Invoking Transients @section Invoking Transients +@cindex invoking transients A transient prefix command is invoked like any other command by pressing the key that is bound to that command. The main difference @@ -287,36 +290,39 @@ disabled while the transient state is in effect. There are two kinds of commands that are available after invoking a transient prefix command; infix and suffix commands. Infix commands set some value (which is then shown in a popup buffer), without -leaving the transient. Suffix commands on the other hand usually quit +leaving the transient. Suffix commands, on the other hand, usually quit the transient and they may use the values set by the infix commands, -i.e. the infix @strong{arguments}. +i.e.@: the infix @strong{arguments}. Instead of setting arguments to be used by a suffix command, infix -commands may also set some value by side-effect, e.g. by setting the +commands may also set some value by side-effect, e.g., by setting the value of some variable. @node Aborting and Resuming Transients @section Aborting and Resuming Transients +@cindex aborting transients +@cindex resuming transients +@cindex quit transient To quit the transient without invoking a suffix command press @code{C-g}. Key bindings in transient keymaps may be longer than a single event. After pressing a valid prefix key, all commands whose bindings do not begin with that prefix key are temporarily unavailable and grayed out. -To abort the prefix key press @code{C-g} (which in this case only quits the +To abort the prefix key press @kbd{C-g} (which in this case only quits the prefix key, but not the complete transient). A transient prefix command can be bound as a suffix of another transient. Invoking such a suffix replaces the current transient -state with a new transient state, i.e. the available bindings change +state with a new transient state, i.e.@: the available bindings change and the information displayed in the popup buffer is updated -accordingly. Pressing @code{C-g} while a nested transient is active only +accordingly. Pressing @kbd{C-g} while a nested transient is active only quits the innermost transient, causing a return to the previous transient. -@code{C-q} or @code{C-z} on the other hand always exits all transients. If you use +@kbd{C-q} or @kbd{C-z} on the other hand always exits all transients. If you use the latter, then you can later resume the stack of transients using -@code{M-x transient-resume}. +@kbd{M-x transient-resume}. @table @asis @kindex C-g @@ -328,10 +334,10 @@ the latter, then you can later resume the stack of transients using This key quits the currently active incomplete key sequence, if any, or else the current transient. When quitting the current transient, -then it returns to the previous transient, if any. +it returns to the previous transient, if any. @end table -Transient's predecessor bound @code{q} instead of @code{C-g} to the quit command. +Transient's predecessor bound @kbd{q} instead of @kbd{C-g} to the quit command. To learn how to get that binding back see @code{transient-bind-q-to-quit}'s doc string. @@ -349,10 +355,10 @@ suspended transients, if any. @item @kbd{C-z} @tie{}@tie{}@tie{}@tie{}(@code{transient-suspend}) Like @code{transient-quit-all}, this command quits an incomplete key -sequence, if any, and all transients. Additionally it saves the +sequence, if any, and all transients. Additionally, it saves the stack of transients so that it can easily be resumed (which is -particularly useful if you quickly need to do "something else" and -the stack is deeper than a single transient and/or you have already +particularly useful if you quickly need to do ``something else'', and +the stack is deeper than a single transient, and/or you have already changed the values of some infix arguments). Note that only a single stack of transients can be saved at a time. @@ -369,16 +375,17 @@ if any. @node Common Suffix Commands @section Common Suffix Commands +@cindex common suffix commands A few shared suffix commands are available in all transients. These suffix commands are not shown in the popup buffer by default. -This includes the aborting commands mentioned in the previous node as -well as some other commands that are all bound to @code{C-x }. After -@code{C-x} is pressed, a section featuring all these common commands is +This includes the aborting commands mentioned in the previous section, as +well as some other commands that are all bound to @kbd{C-x @var{key}}. After +@kbd{C-x} is pressed, a section featuring all these common commands is temporarily shown in the popup buffer. After invoking one of them, -the section disappears again. Note however that one of these commands -is described as "Show common permanently"; invoke that if you want the +the section disappears again. Note, however, that one of these commands +is described as ``Show common permanently''; invoke that if you want the common commands to always be shown for all transients. @table @asis @@ -388,7 +395,7 @@ common commands to always be shown for all transients. This command toggles whether the generic commands that are common to all transients are always displayed or only after typing the -incomplete prefix key sequence @code{C-x}. This only affects the current +incomplete prefix key sequence @kbd{C-x}. This only affects the current Emacs session. @end table @@ -397,38 +404,40 @@ Emacs session. This option controls whether shared suffix commands are shown alongside the transient-specific infix and suffix commands. By -default the shared commands are not shown to avoid overwhelming -the user with to many options. +default, the shared commands are not shown to avoid overwhelming +the user with too many options. -While a transient is active, pressing @code{C-x} always shows the common -command. The value of this option can be changed for the current -Emacs session by typing @code{C-x t} while a transient is active. +While a transient is active, pressing @kbd{C-x} always shows the common +commands. The value of this option can be changed for the current +Emacs session by typing @kbd{C-x t} while a transient is active. @end defopt -The other common commands are described in either the previous node or -in one of the following nodes. +The other common commands are described in either the previous or +in one of the following sections. Some of Transient's key bindings differ from the respective bindings of Magit-Popup; see @ref{FAQ} for more information. @node Saving Values @section Saving Values +@cindex saving values of arguments After setting the infix arguments in a transient, the user can save those arguments for future invocations. Most transients will start out with the saved arguments when they are -invoked. There are a few exceptions though. Some transients are +invoked. There are a few exceptions, though. Some transients are designed so that the value that they use is stored externally as the buffer-local value of some variable. Invoking such a transient again -uses the buffer-local value. @footnote{@code{magit-diff} and @code{magit-log} are two prominent examples, and their +uses the buffer-local value.@footnote{ +@code{magit-diff} and @code{magit-log} are two prominent examples, and their handling of buffer-local values is actually a bit more complicated than outlined above and even customizable.} If the user does not save the value and just exits using a regular suffix command, then the value is merely saved to the transient's -history. That value won't be used when the transient is next invoked -but it is easily accessible (see @ref{Using History}). +history. That value won't be used when the transient is next invoked, +but it is easily accessible (@pxref{Using History}). @table @asis @kindex C-x s @@ -449,12 +458,13 @@ sessions. @defopt transient-values-file -This file is used to persist the values of transients between Emacs -sessions. +This option names the file that is used to persist the values of +transients between Emacs sessions. @end defopt @node Using History @section Using History +@cindex value history Every time the user invokes a suffix command the transient's current value is saved to its history. These values can be cycled through the @@ -485,20 +495,20 @@ transient. In addition to the transient-wide history, Transient of course supports per-infix history. When an infix reads user-input using the -minibuffer, then the user can use the regular minibuffer history +minibuffer, the user can use the regular minibuffer history commands to cycle through previously used values. Usually the same keys as those mentioned above are bound to those commands. Authors of transients should arrange for different infix commands that -read the same kind of value to also use the same history key (see -@ref{Suffix Slots}). +read the same kind of value to also use the same history key +(@pxref{Suffix Slots}). Both kinds of history are saved to a file when Emacs is exited. @defopt transient-history-file -This file is used to persist the history of transients and their -infixes between Emacs sessions. +This option names the file that is used to persist the history of +transients and their infixes between Emacs sessions. @end defopt @defopt transient-history-limit @@ -509,6 +519,7 @@ the history is saved in @code{transient-history-file}. @node Getting Help for Suffix Commands @section Getting Help for Suffix Commands +@cindex getting help Transients can have many suffixes and infixes that the user might not be familiar with. To make it trivial to get help for these, Transient @@ -520,13 +531,13 @@ transient. @cindex transient-help @item @kbd{C-h} @tie{}@tie{}@tie{}@tie{}(@code{transient-help}) -This command enters help mode. When help mode is active, then -typing @code{} shows information about the suffix command that @code{} -normally is bound to (instead of invoking it). Pressing @code{C-h} a +This command enters help mode. When help mode is active, +typing a key shows information about the suffix command that the key +is normally bound to (instead of invoking it). Pressing @kbd{C-h} a second time shows information about the @emph{prefix} command. -After typing @code{} the stack of transient states is suspended and -information about the suffix command is shown instead. Typing @code{q} in +After typing a key, the stack of transient states is suspended and +information about the suffix command is shown instead. Typing @kbd{q} in the help buffer buries that buffer and resumes the transient state. @end table @@ -539,24 +550,28 @@ non-infix suffixes this is usually appropriate. @node Enabling and Disabling Suffixes @section Enabling and Disabling Suffixes +@cindex enabling suffixes +@cindex disabling suffixes The user base of a package that uses transients can be very diverse. This is certainly the case for Magit; some users have been using it and Git for a decade, while others are just getting started now. +@cindex levels For that reason a mechanism is needed that authors can use to classify a transient's infixes and suffixes along the essentials@dots{}everything -spectrum. We use the term "levels" to describe that mechanism. +spectrum. We use the term @dfn{levels} to describe that mechanism. +@cindex transient-level Each suffix command is placed on a level and each transient has a -level (called transient-level), which controls which suffix commands +level (called @dfn{transient-level}), which controls which suffix commands are available. Integers between 1 and 7 (inclusive) are valid levels. For suffixes, 0 is also valid; it means that the suffix is not displayed at any level. The levels of individual transients and/or their individual suffixes can be changed interactively, by invoking the transient and then -pressing @code{C-x l} to enter the "edit" mode, see below. +pressing @kbd{C-x l} to enter the ``edit'' mode, see below. The default level for both transients and their suffixes is 4. The @code{transient-default-level} option only controls the default for @@ -575,8 +590,8 @@ user has not set that individually. @defopt transient-levels-file -This file is used to persist the levels of transients and their -suffixes between Emacs sessions. +This option names the file that is used to persist the levels of +transients and their suffixes between Emacs sessions. @end defopt @table @asis @@ -596,12 +611,12 @@ placed on. Help mode is available in edit mode. -To change the transient level press @code{C-x l} again. +To change the transient level press @kbd{C-x l} again. -To exit edit mode press @code{C-g}. +To exit edit mode press @kbd{C-g}. Note that edit mode does not display any suffixes that are not -currently usable. @code{magit-rebase} for example shows different suffixes +currently usable. @code{magit-rebase}, for example, shows different suffixes depending on whether a rebase is already in progress or not. The predicates also apply in edit mode. @@ -621,16 +636,16 @@ window, and the key bindings are the same as for @code{scroll-up-command} and @cindex transient-scroll-up arg @deffn Command transient-scroll-up arg -This command scrolls text of transient popup window upward ARG -lines. If ARG is @code{nil}, then it scrolls near full screen. This +This command scrolls text of transient popup window upward @var{arg} +lines. If @var{arg} is @code{nil}, then it scrolls near full screen. This is a wrapper around @code{scroll-up-command} (which see). @end deffn @cindex transient-scroll-down arg @deffn Command transient-scroll-down arg -This command scrolls text of transient popup window down ARG -lines. If ARG is @code{nil}, then it scrolls near full screen. This +This command scrolls text of transient popup window down @var{arg} +lines. If @var{arg} is @code{nil}, then it scrolls near full screen. This is a wrapper around @code{scroll-down-command} (which see). @end deffn @@ -661,7 +676,7 @@ is shown; only the pressed key itself is shown. The popup is shown when the user explicitly requests it by pressing an incomplete prefix key sequence. Unless this is zero, -then the popup is shown after that many seconds of inactivity +the popup is shown after that many seconds of inactivity (using the absolute value). @end itemize @end defopt @@ -678,15 +693,15 @@ is non-nil, then the following features are available: @itemize @item -@code{} moves the cursor to the previous suffix. -@code{} moves the cursor to the next suffix. -@code{RET} invokes the suffix the cursor is on. +@key{UP} moves the cursor to the previous suffix. +@key{DOWN} moves the cursor to the next suffix. +@key{RET} invokes the suffix the cursor is on. @item -@code{} invokes the clicked on suffix. +@key{mouse-1} invokes the clicked on suffix. @item -@code{C-s} and @code{C-r} start isearch in the popup buffer. +@kbd{C-s} and @kbd{C-r} start isearch in the popup buffer. @end itemize @end defopt @@ -694,25 +709,28 @@ is non-nil, then the following features are available: This option specifies the action used to display the transient popup buffer. The transient popup buffer is displayed in a window using -@code{(display-buffer BUFFER transient-display-buffer-action)}. +@code{(display-buffer @var{buffer} transient-display-buffer-action)}. -The value of this option has the form @code{(FUNCTION . ALIST)}, -where FUNCTION is a function or a list of functions. Each such +The value of this option has the form @code{(@var{function} . @var{alist})}, +where @var{function} is a function or a list of functions. Each such function should accept two arguments: a buffer to display and an -alist of the same form as ALIST@. See @ref{Choosing Window,,,elisp,} +alist of the same form as @var{alist}. @xref{Choosing Window,,,elisp,}, for details. The default is: +@lisp (display-buffer-in-side-window (side . bottom) (inhibit-same-window . t) (window-parameters (no-other-window . t))) +@end lisp This displays the window at the bottom of the selected frame. -Another useful FUNCTION is @code{display-buffer-below-selected}, which +Another useful @var{function} is @code{display-buffer-below-selected}, which is what @code{magit-popup} used by default. For more alternatives see -@ref{Display Action Functions,,,elisp,} and @ref{Buffer Display Action Alists,,,elisp,}. +@ref{Display Action Functions,,,elisp,}, and see @ref{Buffer Display +Action Alists,,,elisp,}. Note that the buffer that was current before the transient buffer is shown should remain the current buffer. Many suffix commands @@ -741,17 +759,18 @@ good value. If @code{line} (the default), then the buffer also has no mode-line, but a thin line is drawn instead, using the background color of the face -@code{transient-separator}. Termcap frames cannot display thin lines and -therefore fallback to treating @code{line} like @code{nil}. +@code{transient-separator}. Text-mode frames cannot display thin lines, and +therefore fall back to treating @code{line} like @code{nil}. -Otherwise this can be any mode-line format. See @ref{Mode Line Format,,,elisp,} for details. +Otherwise this can be any mode-line format. @xref{Mode Line +Format,,,elisp,}, for details. @end defopt @defopt transient-read-with-initial-input This option controls whether the last history element is used as the initial minibuffer input when reading the value of an infix argument -from the user. If @code{nil}, then there is no initial input and the first +from the user. If @code{nil}, there is no initial input and the first element has to be accessed the same way as the older elements. @end defopt @@ -761,9 +780,9 @@ This option controls whether key bindings of infix commands that do not match the respective command-line argument should be highlighted. For other infix commands this option has no effect. -When this option is non-nil, then the key binding for an infix argument -is highlighted when only a long argument (e.g. @code{--verbose}) is -specified but no shorthand (e.g @code{-v}). In the rare case that a +When this option is non-@code{nil}, the key binding for an infix argument +is highlighted when only a long argument (e.g., @code{--verbose}) is +specified but no shorthand (e.g., @code{-v}). In the rare case that a shorthand is specified but the key binding does not match, then it is highlighted differently. @@ -778,7 +797,7 @@ The highlighting is done using one of the faces @defopt transient-substitute-key-function This function is used to modify key bindings. If the value of this -option is nil (the default), then no substitution is performed. +option is @code{nil} (the default), then no substitution is performed. This function is called with one argument, the prefix object, and must return a key binding description, either the existing key @@ -786,8 +805,8 @@ description it finds in the @code{key} slot, or the key description that replaces the prefix key. It could be used to make other substitutions, but that is discouraged. -For example, @code{=} is hard to reach using my custom keyboard layout, -so I substitute @code{(} for that, which is easy to reach using a layout +For example, @kbd{=} is hard to reach using my custom keyboard layout, +so I substitute @kbd{(} for that, which is easy to reach using a layout optimized for lisp. @lisp @@ -803,11 +822,11 @@ optimized for lisp. @defopt transient-detect-key-conflicts This option controls whether key binding conflicts should be -detected at the time the transient is invoked. If so, then this +detected at the time the transient is invoked. If so, this results in an error, which prevents the transient from being used. Because of that, conflicts are ignored by default. -Conflicts cannot be determined earlier, i.e. when the transient is +Conflicts cannot be determined earlier, i.e.@: when the transient is being defined and when new suffixes are being added, because at that time there can be false-positives. It is actually valid for multiple suffixes to share a common key binding, provided the @@ -820,42 +839,43 @@ enabled at a time. This option controls whether to force the use of a monospaced font in popup buffer. Even if you use a proportional font for the @code{default} face, you might still want to use a monospaced font in -transient's popup buffer. Setting this option to t causes @code{default} +transient's popup buffer. Setting this option to @code{t} causes @code{default} to be remapped to @code{fixed-pitch} in that buffer. @end defopt @node Modifying Existing Transients @chapter Modifying Existing Transients +@cindex modifying existing transients -To an extent transients can be customized interactively, see @ref{Enabling and Disabling Suffixes}. This section explains how existing transients +To an extent, transients can be customized interactively, see @ref{Enabling and Disabling Suffixes}. This section explains how existing transients can be further modified non-interactively. The following functions share a few arguments: @itemize @item -PREFIX is a transient prefix command, a symbol. +@var{prefix} is a transient prefix command, a symbol. @item -SUFFIX is a transient infix or suffix specification in the same form +@var{suffix} is a transient infix or suffix specification in the same form as expected by @code{transient-define-prefix}. Note that an infix is a -special kind of suffix. Depending on context "suffixes" means -"suffixes (including infixes)" or "non-infix suffixes". Here it -means the former. See @ref{Suffix Specifications}. +special kind of suffix. Depending on context ``suffixes'' means +``suffixes (including infixes)'' or ``non-infix suffixes''. Here it +means the former. @xref{Suffix Specifications}. -SUFFIX may also be a group in the same form as expected by -@code{transient-define-prefix}. See @ref{Group Specifications}. +@var{suffix} may also be a group in the same form as expected by +@code{transient-define-prefix}. @xref{Group Specifications}. @item -LOC is a command, a key vector, a key description (a string as +@var{loc} is a command, a key vector, a key description (a string as returned by @code{key-description}), or a list specifying coordinates (the -last element may also be a command or key). For example @code{(1 0 -1)} +last element may also be a command or key). For example @code{(1 0 -1)} identifies the last suffix (@code{-1}) of the first subgroup (@code{0}) of the second group (@code{1}). -If LOC is a list of coordinates, then it can be used to identify a +If @var{loc} is a list of coordinates, then it can be used to identify a group, not just an individual suffix command. The function @code{transient-get-suffix} can be useful to determine whether @@ -865,51 +885,55 @@ at the definition of the transient prefix command. @end itemize These functions operate on the information stored in the -@code{transient--layout} property of the PREFIX symbol. Suffix entries in -that tree are not objects but have the form @code{(LEVEL CLASS PLIST)}, where -plist should set at least @code{:key}, @code{:description} and @code{:command}. +@code{transient--layout} property of the @var{prefix} symbol. Suffix entries in +that tree are not objects but have the form @code{(@var{level} +@var{class} @var{plist})}, where +@var{plist} should set at least @code{:key}, @code{:description} and +@code{:command}. @defun transient-insert-suffix prefix loc suffix -This function inserts suffix or group SUFFIX into PREFIX before LOC@. +This function inserts suffix or group @var{suffix} into @var{prefix} +before @var{loc}. @end defun @defun transient-append-suffix prefix loc suffix -This function inserts suffix or group SUFFIX into PREFIX after LOC@. +This function inserts suffix or group @var{suffix} into @var{prefix} +after @var{loc}. @end defun @defun transient-replace-suffix prefix loc suffix -This function replaces the suffix or group at LOC in PREFIX with -suffix or group SUFFIX@. +This function replaces the suffix or group at @var{loc} in @var{prefix} with +suffix or group @var{suffix}. @end defun @defun transient-remove-suffix prefix loc -This function removes the suffix or group at LOC in PREFIX@. +This function removes the suffix or group at @var{loc} in @var{prefix}. @end defun @defun transient-get-suffix prefix loc -This function returns the suffix or group at LOC in PREFIX@. The +This function returns the suffix or group at @var{loc} in @var{prefix}. The returned value has the form mentioned above. @end defun @defun transient-suffix-put prefix loc prop value -This function edits the suffix or group at LOC in PREFIX, by setting -the PROP of its plist to VALUE@. +This function edits the suffix or group at @var{loc} in @var{prefix}, +by setting the @var{prop} of its plist to @var{value}. @end defun Most of these functions do not signal an error if they cannot perform the requested modification. The functions that insert new suffixes -show a warning if LOC cannot be found in PREFIX, without signaling an -error. The reason for doing it like this is that establishing a key -binding (and that is what we essentially are trying to do here) should -not prevent the rest of the configuration from loading. Among these -functions only @code{transient-get-suffix} and @code{transient-suffix-put} may -signal an error. +show a warning if @var{loc} cannot be found in @var{prefix}, without +signaling an error. The reason for doing it like this is that +establishing a key binding (and that is what we essentially are trying +to do here) should not prevent the rest of the configuration from +loading. Among these functions only @code{transient-get-suffix} and +@code{transient-suffix-put} may signal an error. @node Defining New Commands @chapter Defining New Commands @@ -934,11 +958,11 @@ that is used to invoke that transient. @defmac transient-define-prefix name arglist [docstring] [keyword value]@dots{} group@dots{} [body@dots{}] -This macro defines NAME as a transient prefix command and binds the +This macro defines @var{name} as a transient prefix command and binds the transient's infix and suffix commands. -ARGLIST are the arguments that the prefix command takes. -DOCSTRING is the documentation string and is optional. +@var{arglist} are the arguments that the prefix command takes. +@var{docstring} is the documentation string and is optional. These arguments can optionally be followed by keyword-value pairs. Each key has to be a keyword symbol, either @code{:class} or a keyword @@ -946,11 +970,11 @@ argument supported by the constructor of that class. The @code{transient-prefix} class is used if the class is not specified explicitly. -GROUPs add key bindings for infix and suffix commands and specify +@var{group}s add key bindings for infix and suffix commands and specify how these bindings are presented in the popup buffer. At least one -GROUP has to be specified. See @ref{Binding Suffix and Infix Commands}. +@var{group} has to be specified. @xref{Binding Suffix and Infix Commands}. -The BODY is optional. If it is omitted, then ARGLIST is ignored and +The @var{body} is optional. If it is omitted, then @var{arglist} is ignored and the function definition becomes: @lisp @@ -959,14 +983,15 @@ the function definition becomes: (transient-setup 'NAME)) @end lisp -If BODY is specified, then it must begin with an @code{interactive} form -that matches ARGLIST, and it must call @code{transient-setup}. It may -however call that function only when some condition is satisfied. +If @var{body} is specified, then it must begin with an @code{interactive} form +that matches @var{arglist}, and it must call @code{transient-setup}. It may, +however, call that function only when some condition is satisfied. +@cindex scope of a transient All transients have a (possibly @code{nil}) value, which is exported when suffix commands are called, so that they can consume that value. For some transients it might be necessary to have a sort of -secondary value, called a "scope". Such a scope would usually be +secondary value, called a ``scope''. Such a scope would usually be set in the command's @code{interactive} form and has to be passed to the setup function: @@ -982,13 +1007,15 @@ the branch whose variables are being configured. @section Binding Suffix and Infix Commands The macro @code{transient-define-prefix} is used to define a transient. -This defines the actual transient prefix command (see @ref{Defining Transients}) and adds the transient's infix and suffix bindings, as +This defines the actual transient prefix command (@pxref{Defining +Transients}) and adds the transient's infix and suffix bindings, as described below. Users and third-party packages can add additional bindings using -functions such as @code{transient-insert-suffix} (See @ref{Modifying Existing Transients}). These functions take a "suffix specification" as one of -their arguments, which has the same form as the specifications used in -@code{transient-define-prefix}. +functions such as @code{transient-insert-suffix} (@pxref{Modifying +Existing Transients}). These functions take a ``suffix +specification'' as one of their arguments, which has the same form as +the specifications used in @code{transient-define-prefix}. @menu * Group Specifications:: @@ -997,6 +1024,7 @@ their arguments, which has the same form as the specifications used in @node Group Specifications @subsection Group Specifications +@cindex group specifications The suffix and infix commands of a transient are organized in groups. The grouping controls how the descriptions of the suffixes are @@ -1015,47 +1043,47 @@ brackets to do the latter. Group specifications then have this form: @lisp -[@{LEVEL@} @{DESCRIPTION@} @{KEYWORD VALUE@}... ELEMENT...] +[@{@var{level}@} @{@var{description}@} + @{@var{keyword} @var{value}@}... + @var{element}...] @end lisp -The LEVEL is optional and defaults to 4. See @ref{Enabling and Disabling Suffixes}. +The @var{level} is optional and defaults to 4. @xref{Enabling and +Disabling Suffixes}. -The DESCRIPTION is optional. If present it is used as the heading of +The @var{description} is optional. If present, it is used as the heading of the group. -The KEYWORD-VALUE pairs are optional. Each keyword has to be a +The @var{keyword}-@var{value} pairs are optional. Each keyword has to be a keyword symbol, either @code{:class} or a keyword argument supported by the constructor of that class. @itemize @item One of these keywords, @code{:description}, is equivalent to specifying -DESCRIPTION at the very beginning of the vector. The recommendation +@var{description} at the very beginning of the vector. The recommendation is to use @code{:description} if some other keyword is also used, for -consistency, or DESCRIPTION otherwise, because it looks better. - +consistency, or @var{description} otherwise, because it looks better. @item -Likewise @code{:level} is equivalent to LEVEL@. - +Likewise @code{:level} is equivalent to @var{level}. @item Other important keywords include the @code{:if...} keywords. These keywords control whether the group is available in a certain situation. -For example, one group of the @code{magit-rebase} transient uses @code{:if - magit-rebase-in-progress-p}, which contains the suffixes that are -useful while rebase is already in progress; and another that uses +For example, one group of the @code{magit-rebase} transient uses +@code{:if magit-rebase-in-progress-p}, which contains the suffixes +that are useful while rebase is already in progress; and another that uses @code{:if-not magit-rebase-in-progress-p}, which contains the suffixes that initiate a rebase. These predicates can also be used on individual suffixes and are only documented once, see @ref{Predicate Slots}. - @item -The value of @code{:hide}, if non-nil, is a predicate that controls +The value of @code{:hide}, if non-@code{nil}, is a predicate that controls whether the group is hidden by default. The key bindings for suffixes of a hidden group should all use the same prefix key. Pressing that prefix key should temporarily show the group and its @@ -1067,35 +1095,33 @@ suffixes, which assumes that a predicate like this is used: ?\C-c)) ; the prefix key shared by all bindings @end lisp - @item -The value of @code{:setup-children}, if non-nil, is a function that takes -two arguments the group object itself and a list of children. +The value of @code{:setup-children}, if non-@code{nil}, is a function +that takes two arguments the group object itself and a list of children. The children are given as a, potentially empty, list consisting of either group or suffix specifications. It can make arbitrary changes to the children including constructing new children from scratch. Also see @code{transient-setup-children}. - @item The boolean @code{:pad-keys} argument controls whether keys of all suffixes contained in a group are right padded, effectively aligning the descriptions. @end itemize -The ELEMENTs are either all subgroups (vectors), or all suffixes +The @var{element}s are either all subgroups (vectors), or all suffixes (lists) and strings. (At least currently no group type exists that would allow mixing subgroups with commands at the same level, though in principle there is nothing that prevents that.) -If the ELEMENTs are not subgroups, then they can be a mixture of lists +If the @var{element}s are not subgroups, then they can be a mixture of lists that specify commands and strings. Strings are inserted verbatim. The empty string can be used to insert gaps between suffixes, which is particularly useful if the suffixes are outlined as a table. Variables are supported inside group specifications. For example in place of a direct subgroup specification, a variable can be used whose -value is a vector that qualifies as a group specification. Likewise a +value is a vector that qualifies as a group specification. Likewise, a variable can be used where a suffix specification is expected. Lists of group or suffix specifications are also supported. Indirect specifications are resolved when the transient prefix is being @@ -1105,6 +1131,7 @@ The form of suffix specifications is documented in the next node. @node Suffix Specifications @subsection Suffix Specifications +@cindex suffix specifications A transient's suffix and infix commands are bound when the transient prefix command is defined using @code{transient-define-prefix}, see @@ -1113,36 +1140,37 @@ prefix command is defined using @code{transient-define-prefix}, see individual suffix command. The same form is also used when later binding additional commands -using functions such as @code{transient-insert-suffix}, see @ref{Modifying Existing Transients}. +using functions such as @code{transient-insert-suffix}, +see @ref{Modifying Existing Transients}. -Note that an infix is a special kind of suffix. Depending on context -"suffixes" means "suffixes (including infixes)" or "non-infix -suffixes". Here it means the former. +Note that an infix is a special kind of suffix. Depending on context +``suffixes'' means ``suffixes (including infixes)'' or ``non-infix +suffixes''. Here it means the former. Suffix specifications have this form: @lisp -([LEVEL] [KEY] [DESCRIPTION] COMMAND|ARGUMENT [KEYWORD VALUE]...) +([@var{level}] + [@var{key}] [@var{description}] + @var{command}|@var{argument} [@var{keyword} @var{value}]...) @end lisp -LEVEL, KEY and DESCRIPTION can also be specified using the KEYWORDs +@var{level}, @var{key} and @var{description} can also be specified using the @var{keyword}s @code{:level}, @code{:key} and @code{:description}. If the object that is associated with -COMMAND sets these properties, then they do not have to be specified +@var{command} sets these properties, then they do not have to be specified here. You can however specify them here anyway, possibly overriding the object's values just for the binding inside this transient. @itemize @item -LEVEL is the suffix level, an integer between 1 and 7. See -@ref{Enabling and Disabling Suffixes}. - +@var{level} is the suffix level, an integer between 1 and 7. +@xref{Enabling and Disabling Suffixes}. @item -KEY is the key binding, either a vector or key description string. - +@var{key} is the key binding, either a vector or key description string. @item -DESCRIPTION is the description, either a string or a function that +@var{description} is the description, either a string or a function that returns a string. The function should be a lambda expression to avoid ambiguity. In some cases a symbol that is bound as a function would also work but to be safe you should use @code{:description} in that @@ -1154,7 +1182,7 @@ argument that is mandatory in all cases. @itemize @item -Usually COMMAND is a symbol that is bound as a function, which has +Usually @var{command} is a symbol that is bound as a function, which has to be defined or at least autoloaded as a command by the time the containing prefix command is invoked. @@ -1170,7 +1198,7 @@ the @code{:setup-children} function in @ref{Group Specifications}. As mentioned above, the object that is associated with a command can be used to set the default for certain values that otherwise have to be set in the suffix specification. Therefore if there is no object, -then you have to make sure to specify the KEY and the DESCRIPTION@. +then you have to make sure to specify the @var{key} and the @var{description}. As a special case, if you want to add a command that might be neither defined nor autoloaded, you can use a workaround like: @@ -1181,9 +1209,8 @@ defined nor autoloaded, you can use a workaround like: :if (lambda () (featurep 'no-library)))) @end lisp -Instead of @code{featurep} you could also use @code{require} with a non-nil value -for NOERROR@. - +Instead of @code{featurep} you could also use @code{require} with a +non-nil value for @var{noerror}. @item The mandatory argument can also be a command-line argument, a @@ -1199,28 +1226,31 @@ Only the long argument is displayed in the popup buffer. See used. Unless the class is specified explicitly, the appropriate class is -guessed based on the long argument. If the argument ends with "=​" -(e.g. "--format=") then @code{transient-option} is used, otherwise +guessed based on the long argument. If the argument ends with @samp{=} +(e.g. @samp{--format=}) then @code{transient-option} is used, otherwise @code{transient-switch}. @end itemize -Finally, details can be specified using optional KEYWORD-VALUE pairs. +Finally, details can be specified using optional +@var{keyword}-@var{value} pairs. Each keyword has to be a keyword symbol, either @code{:class} or a keyword argument supported by the constructor of that class. See @ref{Suffix Slots}. @node Defining Suffix and Infix Commands @section Defining Suffix and Infix Commands +@cindex defining suffix commands +@cindex defining infix commands -Note that an infix is a special kind of suffix. Depending on context -"suffixes" means "suffixes (including infixes)" or "non-infix -suffixes". +Note that an infix is a special kind of suffix. Depending on context +``suffixes'' means ``suffixes (including infixes)'' or ``non-infix +suffixes''. @defmac transient-define-suffix name arglist [docstring] [keyword value]@dots{} body@dots{} -This macro defines NAME as a transient suffix command. +This macro defines @var{name} as a transient suffix command. -ARGLIST are the arguments that the command takes. -DOCSTRING is the documentation string and is optional. +@var{arglist} are the arguments that the command takes. +@var{docstring} is the documentation string and is optional. These arguments can optionally be followed by keyword-value pairs. Each keyword has to be a keyword symbol, either @code{:class} or a keyword @@ -1228,17 +1258,17 @@ argument supported by the constructor of that class. The @code{transient-suffix} class is used if the class is not specified explicitly. -The BODY must begin with an @code{interactive} form that matches ARGLIST@. +The @var{body} must begin with an @code{interactive} form that matches @var{arglist}. The infix arguments are usually accessed by using @code{transient-args} inside @code{interactive}. @end defmac @defmac transient-define-infix name arglist [docstring] [keyword value]@dots{} -This macro defines NAME as a transient infix command. +This macro defines @var{name} as a transient infix command. -ARGLIST is always ignored (but mandatory never-the-less) and -reserved for future use. DOCSTRING is the documentation string and +@var{arglist} is always ignored (but mandatory never-the-less) and +reserved for future use. @var{docstring} is the documentation string and is optional. The keyword-value pairs are mandatory. All transient infix commands @@ -1273,7 +1303,7 @@ the value of the @code{:transient} keyword. @defmac transient-define-argument name arglist [docstring] [keyword value]@dots{} -This macro defines NAME as a transient infix command. +This macro defines @var{name} as a transient infix command. This is an alias for @code{transient-define-infix}. Only use this alias to define an infix command that actually sets an infix argument. @@ -1283,8 +1313,9 @@ To define an infix command that, for example, sets a variable, use @node Using Infix Arguments @section Using Infix Arguments +@cindex using infix arguments -The function and the variables described below allow suffix commands +The functions and the variables described below allow suffix commands to access the value of the transient from which they were invoked; which is the value of its infix arguments. These variables are set when the user invokes a suffix command that exits the transient, but @@ -1294,7 +1325,7 @@ When returning to the command-loop after calling the suffix command, the arguments are reset to @code{nil} (which causes the function to return @code{nil} too). -Like for Emacs' prefix arguments it is advisable, but not mandatory, +Like for Emacs' prefix arguments, it is advisable, but not mandatory, to access the infix arguments inside the command's @code{interactive} form. The preferred way of doing that is to call the @code{transient-args} function, which for infix arguments serves about the same purpose as @@ -1303,29 +1334,29 @@ function, which for infix arguments serves about the same purpose as @defun transient-args prefix This function returns the value of the transient prefix command -PREFIX@. +@var{prefix}. If the current command was invoked from the transient prefix command -PREFIX, then it returns the active infix arguments. If the current -command was not invoked from PREFIX, then it returns the set, saved -or default value for PREFIX@. +@var{prefix}, then it returns the active infix arguments. If the current +command was not invoked from @var{prefix}, then it returns the set, saved +or default value for @var{prefix}. @end defun @defun transient-arg-value arg args -This function return the value of ARG as it appears in ARGS@. +This function return the value of @var{arg} as it appears in @var{args}. For a switch a boolean is returned. For an option the value is returned as a string, using the empty string for the empty value, -or nil if the option does not appear in ARGS@. +or @code{nil} if the option does not appear in @var{args}. @end defun @defun transient-suffixes prefix This function returns the suffixes of the transient prefix command -PREFIX@. This is a list of objects. This function should only be +@var{prefix}. This is a list of objects. This function should only be used if you need the objects (as opposed to just their values) and -if the current command is not being invoked from PREFIX@. +if the current command is not being invoked from @var{prefix}. @end defun @defvar transient-current-suffixes @@ -1334,7 +1365,7 @@ The suffixes of the transient from which this suffix command was invoked. This is a list of objects. Usually it is sufficient to instead use the function @code{transient-args}, which returns a list of values. In complex cases it might be necessary to use this variable -instead, i.e. if you need access to information beside the value. +instead, i.e.@: if you need access to information beside the value. @end defvar @defvar transient-current-prefix @@ -1352,9 +1383,10 @@ returned value is a symbol, the transient prefix command. @node Transient State @section Transient State +@cindex transient state -Invoking a transient prefix command "activates" the respective -transient, i.e. it puts a transient keymap into effect, which binds +Invoking a transient prefix command ``activates'' the respective +transient, i.e.@: it puts a transient keymap into effect, which binds the transient's infix and suffix commands. The default behavior while a transient is active is as follows: @@ -1364,23 +1396,21 @@ The default behavior while a transient is active is as follows: Invoking an infix command does not affect the transient state; the transient remains active. - @item -Invoking a (non-infix) suffix command "deactivates" the transient +Invoking a (non-infix) suffix command ``deactivates'' the transient state by removing the transient keymap and performing some additional cleanup. - @item Invoking a command that is bound in a keymap other than the transient keymap is disallowed and trying to do so results in a -warning. This does not "deactivate" the transient. +warning. This does not ``deactivate'' the transient. @end itemize But these are just the defaults. Whether a certain command -deactivates or "exits" the transient is configurable. There is more -than one way in which a command can be "transient" or "non-transient"; -the exact behavior is implemented by calling a so-called "pre-command" +deactivates or ``exits'' the transient is configurable. There is more +than one way in which a command can be ``transient'' or ``non-transient''; +the exact behavior is implemented by calling a so-called ``pre-command'' function. Whether non-suffix commands are allowed to be called is configurable per transient. @@ -1408,23 +1438,21 @@ slot is @code{nil}, so the suffix's @code{transient} slot being unbound is essentially equivalent to it being @code{nil}. @end itemize - @item A suffix command can be a prefix command itself, i.e. a -"sub-prefix". While a sub-prefix is active we nearly always want -@code{C-g} to take the user back to the "super-prefix". However in rare +``sub-prefix''. While a sub-prefix is active we nearly always want +@kbd{C-g} to take the user back to the ``super-prefix''. However in rare cases this may not be desirable, and that makes the following complication necessary: For @code{transient-suffix} objects the @code{transient} slot is unbound. We can ignore that for the most part because, as stated above, @code{nil} and the -slot being unbound are equivalent, and mean "do exit". That isn't +slot being unbound are equivalent, and mean ``do exit''. That isn't actually true for suffixes that are sub-prefixes though. For such -suffixes unbound means "do exit but allow going back", which is the -default, while @code{nil} means "do exit permanently", which requires that +suffixes unbound means ``do exit but allow going back'', which is the +default, while @code{nil} means ``do exit permanently'', which requires that slot to be explicitly set to that value. - @item The transient-ness of certain built-in suffix commands is specified using @code{transient-predicate-map}. This is a special keymap, which @@ -1437,9 +1465,9 @@ called by @code{transient--pre-command}, a function on @code{pre-command-hook} a the value that they return determines whether the transient is exited. To do so the value of one of the constants @code{transient--exit} or @code{transient--stay} is used (that way we don't have to remember if @code{t} means -"exit" or "stay"). +``exit'' or ``stay''). -Additionally these functions may change the value of @code{this-command} +Additionally, these functions may change the value of @code{this-command} (which explains why they have to be called using @code{pre-command-hook}), call @code{transient-export}, @code{transient--stack-zap} or @code{transient--stack-push}; and set the values of @code{transient--exitp}, @code{transient--helpp} or @@ -1475,14 +1503,14 @@ Call the command after exporting variables and stay transient. Call the transient prefix command, replacing the active transient. -This is used for suffixes that are prefixes themselves, i.e. for +This is used for suffixes that are prefixes themselves, i.e.@: for sub-prefixes. @end defun @anchor{Pre-commands for Non-Suffixes} @subheading Pre-commands for Non-Suffixes -The default for non-suffixes, i.e commands that are bound in other +The default for non-suffixes, i.e@: commands that are bound in other keymaps beside the transient keymap, is @code{transient--do-warn}. Silently ignoring the user-error is also an option, though probably not a good one. @@ -1508,25 +1536,26 @@ Call @code{transient-noop} and stay transient. If active, quit help or edit mode, else exit the active transient. -This is used when the user pressed @code{C-g}. +This is used when the user pressed @kbd{C-g}. @end defun @defun transient--do-quit-all Exit all transients without saving the transient stack. -This is used when the user pressed @code{C-q}. +This is used when the user pressed @kbd{C-q}. @end defun @defun transient--do-suspend Suspend the active transient, saving the transient stack. -This is used when the user pressed @code{C-z}. +This is used when the user pressed @kbd{C-z}. @end defun @node Classes and Methods @chapter Classes and Methods +@cindex classes and methods Transient uses classes and generic functions to make it possible to define new types of suffix commands that are similar to existing @@ -1550,7 +1579,6 @@ without having to convince the maintainer of Transient that that new type is important enough to justify adding a special case to a dozen or so functions. - @item Associating a command with an object makes it possible to easily store information that is specific to that particular command. @@ -1594,29 +1622,25 @@ The abstract @code{transient-child} class is the base class of both @code{transient-group} (and therefore all groups) as well as of @code{transient-suffix} (and therefore all suffix and infix commands). -This class exists because the elements (aka "children") of certain +This class exists because the elements (a.k.a.@: ``children'') of certain groups can be other groups instead of suffix and infix commands. - @item The abstract @code{transient-group} class is the superclass of all other group classes. - @item The @code{transient-column} class is the simplest group. -This is the default "flat" group. If the class is not specified +This is the default ``flat'' group. If the class is not specified explicitly and the first element is not a vector (i.e. not a group), then this class is used. This class displays each element on a separate line. - @item The @code{transient-row} class displays all elements on a single line. - @item The @code{transient-columns} class displays commands organized in columns. @@ -1624,11 +1648,10 @@ Direct elements have to be groups whose elements have to be commands or strings. Each subgroup represents a column. This class takes care of inserting the subgroups' elements. -This is the default "nested" group. If the class is not specified -explicitly and the first element is a vector (i.e. a group), then +This is the default ``nested'' group. If the class is not specified +explicitly and the first element is a vector (i.e.@: a group), then this class is used. - @item The @code{transient-subgroups} class wraps other groups. @@ -1646,11 +1669,11 @@ elements. This generic function can be used to setup the children or a group. The default implementation usually just returns the children -unchanged, but if the @code{setup-children} slot of GROUP is non-nil, then -it calls that function with CHILDREN as the only argument and +unchanged, but if the @code{setup-children} slot of @var{group} is non-nil, then +it calls that function with @var{children} as the only argument and returns the value. -The children are given as a, potentially empty, list consisting of +The children are given as a (potentially empty) list consisting of either group or suffix specifications. These functions can make arbitrary changes to the children including constructing new children from scratch. @@ -1698,8 +1721,7 @@ object should not affect later invocations. @item All suffix and infix classes derive from @code{transient-suffix}, which in turn derives from @code{transient-child}, from which @code{transient-group} also -derives (see @ref{Group Classes}). - +derives (@pxref{Group Classes}). @item All infix classes derive from the abstract @code{transient-infix} class, @@ -1713,36 +1735,30 @@ that does not do so. If you do that then you get to implement many methods. Also, infixes and non-infix suffixes are usually defined using -different macros (see @ref{Defining Suffix and Infix Commands}). - +different macros (@pxref{Defining Suffix and Infix Commands}). @item Classes used for infix commands that represent arguments should be derived from the abstract @code{transient-argument} class. - @item The @code{transient-switch} class (or a derived class) is used for infix arguments that represent command-line switches (arguments that do not take a value). - @item The @code{transient-option} class (or a derived class) is used for infix arguments that represent command-line options (arguments that do take a value). - @item The @code{transient-switches} class can be used for a set of mutually exclusive command-line switches. - @item -The @code{transient-files} class can be used for a "--" argument that +The @code{transient-files} class can be used for a @samp{--} argument that indicates that all remaining arguments are files. - @item Classes used for infix commands that represent variables should derived from the abstract @code{transient-variables} class. @@ -1769,7 +1785,7 @@ functions use @code{describe-function}. @defun transient-init-value obj -This generic function sets the initial value of the object OBJ@. +This generic function sets the initial value of the object @var{obj}. This function is called for all suffix commands, but unless a concrete method is implemented this falls through to the default @@ -1783,7 +1799,7 @@ a method. @defun transient-infix-read obj This generic function determines the new value of the infix object -OBJ@. +@var{obj}. This function merely determines the value; @code{transient-infix-set} is used to actually store the new value in the object. @@ -1793,7 +1809,7 @@ user using the reader specified by the @code{reader} slot (using the @code{transient-infix-value} method described below). For some infix classes the value is changed without reading -anything in the minibuffer, i.e. the mere act of invoking the +anything in the minibuffer, i.e.@: the mere act of invoking the infix command determines what the new value should be, based on the previous value. @end defun @@ -1801,24 +1817,24 @@ on the previous value. @defun transient-prompt obj This generic function returns the prompt to be used to read infix -object OBJ's value. +object @var{obj}'s value. @end defun @defun transient-infix-set obj value -This generic function sets the value of infix object OBJ to VALUE@. +This generic function sets the value of infix object @var{obj} to @var{value}. @end defun @defun transient-infix-value obj -This generic function returns the value of the suffix object OBJ@. +This generic function returns the value of the suffix object @var{obj}. This function is called by @code{transient-args} (which see), meaning this function is how the value of a transient is determined so that the invoked suffix command can use it. Currently most values are strings, but that is not set in stone. -@code{nil} is not a value, it means "no value". +@code{nil} is not a value, it means ``no value''. Usually only infixes have a value, but see the method for @code{transient-suffix}. @@ -1826,7 +1842,7 @@ Usually only infixes have a value, but see the method for @defun transient-init-scope obj -This generic function sets the scope of the suffix object OBJ@. +This generic function sets the scope of the suffix object @var{obj}. The scope is actually a property of the transient prefix, not of individual suffixes. However it is possible to invoke a suffix @@ -1844,7 +1860,7 @@ implementation, which is a noop. @defun transient-format obj -This generic function formats and returns OBJ for display. +This generic function formats and returns @var{obj} for display. When this function is called, then the current buffer is some temporary buffer. If you need the buffer from which the prefix @@ -1854,30 +1870,30 @@ making @code{transient--source-buffer} current. @defun transient-format-key obj -This generic function formats OBJ's @code{key} for display and returns the +This generic function formats @var{obj}'s @code{key} for display and returns the result. @end defun @defun transient-format-description obj -This generic function formats OBJ's @code{description} for display and +This generic function formats @var{obj}'s @code{description} for display and returns the result. @end defun @defun transient-format-value obj -This generic function formats OBJ's value for display and returns +This generic function formats @var{obj}'s value for display and returns the result. @end defun @defun transient-show-help obj Show help for the prefix, infix or suffix command represented by -OBJ@. +@var{obj}. For prefixes, show the info manual, if that is specified using the -@code{info-manual} slot. Otherwise show the manpage if that is specified -using the @code{man-page} slot. Otherwise show the command's doc string. +@code{info-manual} slot. Otherwise, show the manpage if that is specified +using the @code{man-page} slot. Otherwise, show the command's doc string. For suffixes, show the command's doc string. @@ -1895,19 +1911,16 @@ the prefix and its suffixes. The command @code{transient-help} uses the method @code{transient-show-help} (which see) to lookup and use these values. - @item @code{history-key} If multiple prefix commands should share a single value, then this slot has to be set to the same value for all of them. You probably don't want that. - @item @code{transient-suffix} and @code{transient-non-suffix} play a part when determining whether the currently active transient prefix command remains active/transient when a suffix or abitrary non-suffix -command is invoked. See @ref{Transient State}. - +command is invoked. @xref{Transient State}. @item @code{incompatible} A list of lists. Each sub-list specifies a set of @@ -1915,10 +1928,9 @@ mutually exclusive arguments. Enabling one of these arguments causes the others to be disabled. An argument may appear in multiple sub-lists. - @item @code{scope} For some transients it might be necessary to have a sort of -secondary value, called a "scope". See @code{transient-define-prefix}. +secondary value, called a ``scope''. See @code{transient-define-prefix}. @end itemize @anchor{Internal Prefix Slots} @@ -1933,25 +1945,21 @@ set in calls to @code{transient-define-prefix}. of that object is stored in the global variable @code{transient--prefix} and the prototype is stored in the clone's @code{prototype} slot. - @item @code{command} The command, a symbol. Each transient prefix command consists of a command, which is stored in a symbol's function slot and an object, which is stored in the @code{transient--prefix} property of the same symbol. - @item @code{level} The level of the prefix commands. The suffix commands whose -layer is equal or lower are displayed. See @ref{Enabling and Disabling Suffixes}. - +layer is equal or lower are displayed. @pxref{Enabling and Disabling Suffixes}. @item @code{value} The likely outdated value of the prefix. Instead of accessing this slot directly you should use the function @code{transient-get-value}, which is guaranteed to return the up-to-date value. - @item @code{history} and @code{history-pos} are used to keep track of historic values. Unless you implement your own @code{transient-infix-read} method you should @@ -1974,14 +1982,11 @@ Also see @ref{Suffix Classes}. @item @code{key} The key, a key vector or a key description string. - @item @code{command} The command, a symbol. - @item -@code{transient} Whether to stay transient. See @ref{Transient State}. - +@code{transient} Whether to stay transient. @xref{Transient State}. @item @code{format} The format used to display the suffix in the popup buffer. @@ -1998,7 +2003,6 @@ It must contain the following %-placeholders: @code{%v} For the infix value. Non-infix suffixes don't have a value. @end itemize - @item @code{description} The description, either a string or a function that is called with no argument and returns a string. @@ -2014,60 +2018,49 @@ They are defined here anyway to allow sharing certain methods. @item @code{argument} The long argument, e.g. @code{--verbose}. - @item @code{shortarg} The short argument, e.g. @code{-v}. - @item @code{value} The value. Should not be accessed directly. - @item @code{init-value} Function that is responsable for setting the object's value. If bound, then this is called with the object as the only argument. Usually this is not bound, in which case the object's primary @code{transient-init-value} method is called instead. - @item @code{unsavable} Whether the value of the suffix is not saved as part of the prefixes. - @item @code{multi-value} For options, whether the option can have multiple values. If non-nil, then default to use @code{completing-read-multiple}. - @item @code{always-read} For options, whether to read a value on every invocation. If this is nil, then options that have a value are simply unset and have to be invoked a second time to set a new value. - @item @code{allow-empty} For options, whether the empty string is a valid value. - @item @code{history-key} The key used to store the history. This defaults to the command name. This is useful when multiple infixes should share the same history because their values are of the same kind. - @item @code{reader} The function used to read the value of an infix. Not used -for switches. The function takes three arguments, PROMPT, -INITIAL-INPUT and HISTORY, and must return a string. - +for switches. The function takes three arguments, @var{prompt}, +@var{initial-input} and @var{history}, and must return a string. @item @code{prompt} The prompt used when reading the value, either a string or a function that takes the object as the only argument and which returns a prompt string. - @item @code{choices} A list of valid values. How exactly that is used depends on the class of the object. @@ -2087,12 +2080,11 @@ the class of the object. @itemize @item @code{argument-format} The display format. Must contain @code{%s}, one of the -@code{choices} is substituted for that. E.g. @code{--%s-order}. - +@code{choices} is substituted for that. E.g., @code{--%s-order}. @item @code{argument-regexp} The regexp used to match any one of the switches. -E.g. @code{\\(--\\(topo\\|author-date\\|date\\)-order\\)}. +E.g., @code{\\(--\\(topo\\|author-date\\|date\\)-order\\)}. @end itemize @node Predicate Slots @@ -2105,16 +2097,16 @@ what happens if you use more than one. @itemize @item -@code{if} Enable if predicate returns non-nil. +@code{if} Enable if predicate returns non-@code{nil}. @item -@code{if-not} Enable if predicate returns nil. +@code{if-not} Enable if predicate returns @code{nil}. @item -@code{if-non-nil} Enable if variable's value is non-nil. +@code{if-non-nil} Enable if variable's value is non-@code{nil}. @item -@code{if-nil} Enable if variable's value is nil. +@code{if-nil} Enable if variable's value is @code{nil}. @item @code{if-mode} Enable if major-mode matches value. @@ -2134,7 +2126,7 @@ the slots documented above, it is a predicate, but it is used for a different purpose. The value has to be an integer between 1 and 7. @code{level} controls whether a suffix or a group should be available depending on user preference. -See @ref{Enabling and Disabling Suffixes}. +@xref{Enabling and Disabling Suffixes}. @node Related Abstractions and Packages @chapter Related Abstractions and Packages @@ -2160,16 +2152,16 @@ The following diagrams illustrate some of the differences. @code{(+)} represents the user's choice to press one key or another. @item -@code{@{WORD@}} are possible behaviors. +@code{@{@var{word}@}} are possible behaviors. @item -@code{@{NUMBER@}} is a footnote. +@code{@{@var{number}@}} is a footnote. @end itemize @anchor{Regular Prefix Commands} @subheading Regular Prefix Commands -See @ref{Prefix Keys,,,elisp,}. +@xref{Prefix Keys,,,elisp,}. @example ,--> command1 --> (c) @@ -2182,7 +2174,7 @@ See @ref{Prefix Keys,,,elisp,}. @anchor{Regular Prefix Arguments} @subheading Regular Prefix Arguments -See @ref{Prefix Command Arguments,,,elisp,}. +@xref{Prefix Command Arguments,,,elisp,}. @example ,----------------------------------, @@ -2347,7 +2339,6 @@ infix arguments for future invocations. The behavior can also be specified for individual suffix commands and may even depend on state. - @item @code{@{2@}} Transients can be configured to allow the user to invoke non-suffix commands. The default is to not allow that and instead @@ -2367,7 +2358,7 @@ covered elsewhere. @anchor{Magit-Popup} @subheading Magit-Popup -Transient is the successor to Magit-Popup (see @ref{Top,,,magit-popup,}). +Transient is the successor to Magit-Popup (@pxref{Top,,,magit-popup,}). One major difference between these two implementations of the same ideas is that while Transient uses transient keymaps and embraces the @@ -2382,8 +2373,8 @@ type was added, which was not already part of Magit-Popup's initial release. A lot of things are hard-coded in Magit-Popup. One random example is -that the key bindings for switches must begin with "-" and those for -options must begin with "=". +that the key bindings for switches must begin with @code{-} and those for +options must begin with @code{=}. @anchor{Hydra} @subheading Hydra @@ -2395,9 +2386,9 @@ Both packages use transient keymaps to make a set of commands temporarily available and show the available commands in a popup buffer. -A Hydra "body" is equivalent to a Transient "prefix" and a Hydra -"head" is equivalent to a Transient "suffix". Hydra has no equivalent -of a Transient "infix". +A Hydra ``body'' is equivalent to a Transient ``prefix'' and a Hydra +``head'' is equivalent to a Transient ``suffix''. Hydra has no equivalent +of a Transient ``infix''. Both hydras and transients can be used as simple command dispatchers. Used like this they are similar to regular prefix commands and prefix @@ -2450,7 +2441,6 @@ things. The downside of this is that it becomes harder for a user to add additional commands to an existing hydra and to change key bindings. - @item Transient allows the author of a transient to organize the commands into groups and the use of generic functions allows authors of @@ -2496,20 +2486,21 @@ bindings. The bindings that do use a prefix do so to avoid wasting too many non-prefix bindings, keeping them available for use in individual transients. The bindings that do not use a prefix and that are @strong{not} grayed out are very important bindings that are @strong{always} -available, even when invoking the "common command key prefix" or @strong{any +available, even when invoking the ``common command key prefix'' or @strong{any other} transient-specific prefix. The non-prefix keys that @strong{are} grayed out however, are not available when any incomplete prefix key sequence -is active. They do not use the "common command key prefix" because it +is active. They do not use the ``common command key prefix'' because it is likely that users want to invoke them several times in a row and -e.g. @code{M-p M-p M-p} is much more convenient than @code{C-x M-p C-x M-p C-x M-p}. +e.g. @kbd{M-p M-p M-p} is much more convenient than +@kbd{C-x M-p C-x M-p C-x M-p}. -You may also have noticed that the "Set" command is bound to @code{C-x s}, -while Magit-Popup used to bind @code{C-c C-c} instead. I have seen several +You may also have noticed that the "Set" command is bound to @kbd{C-x s}, +while Magit-Popup used to bind @kbd{C-c C-c} instead. I have seen several users praise the latter binding (sic), so I did not change it willy-nilly. The reason that I changed it is that using different prefix keys for different common commands, would have made the temporary display of the common commands even more confusing, -i.e. after pressing @code{C-c} all the @code{C-x ...} bindings would be grayed out. +i.e. after pressing @kbd{C-c} all the @kbd{C-x ...} bindings would be grayed out. Using a single prefix for common commands key means that all other potential prefix keys can be used for transient-specific commands @@ -2522,20 +2513,21 @@ also using that for a common command would prevent me from doing so. @anchor{Why does @code{q} not quit popups anymore?} @appendixsec Why does @code{q} not quit popups anymore? -I agree that @code{q} is a good binding for commands that quit something. +I agree that @kbd{q} is a good binding for commands that quit something. This includes quitting whatever transient is currently active, but it also includes quitting whatever it is that some specific transient is controlling. The transient @code{magit-blame} for example binds @code{q} to the command that turns @code{magit-blame-mode} off. -So I had to decide if @code{q} should quit the active transient (like -Magit-Popup used to) or whether @code{C-g} should do that instead, so that @code{q} +So I had to decide if @kbd{q} should quit the active transient (like +Magit-Popup used to) or whether @kbd{C-g} should do that instead, so +that @kbd{q} could be bound in individual transient to whatever commands make sense for them. Because all other letters are already reserved for use by individual transients, I have decided to no longer make an exception -for @code{q}. +for @kbd{q}. -If you want to get @code{q}'s old binding back then you can do so. Doing +If you want to get @kbd{q}'s old binding back then you can do so. Doing that is a bit more complicated than changing a single key binding, so I have implemented a function, @code{transient-bind-q-to-quit} that makes the necessary changes. See its doc string for more information. commit 5b7752a865f22171a6389b6c26dd13ad7009a2de Author: Michael Albinus Date: Tue Feb 15 18:13:04 2022 +0100 Fix problem with popd for in remote shell buffers * lisp/shell.el (shell-prefixed-directory-name): Use `file-local-name' for DIR. (Bug#53927) diff --git a/lisp/shell.el b/lisp/shell.el index ffaeb61c0e..c9def1bb3f 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -941,7 +941,7 @@ Environment variables are expanded, see function `substitute-in-file-name'." dir (if (file-name-absolute-p dir) ;; The name is absolute, so prepend the prefix. - (concat comint-file-name-prefix dir) + (concat comint-file-name-prefix (file-local-name dir)) ;; For relative name we assume default-directory already has the prefix. (expand-file-name dir)))) commit 38f6ea1df00075dcafbd6946ed6045f026853755 Author: Jonas Bernoulli Date: Tue Feb 15 17:49:04 2022 +0100 Import texi source file for transient manual * doc/misc/Makefile.in: Add transient to INFO_COMMON. * doc/misc/transient.texi: New file. diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in index fab4edcc32..1e3398701f 100644 --- a/doc/misc/Makefile.in +++ b/doc/misc/Makefile.in @@ -73,8 +73,8 @@ INFO_COMMON = auth autotype bovine calc ccmode cl \ flymake forms gnus emacs-gnutls htmlfontify idlwave ido info.info \ mairix-el message mh-e modus-themes newsticker nxml-mode octave-mode \ org pcl-cvs pgg rcirc remember reftex sasl \ - sc semantic ses sieve smtpmail speedbar srecode todo-mode tramp \ - url vhdl-mode vip viper widget wisent woman + sc semantic ses sieve smtpmail speedbar srecode todo-mode transient \ + tramp url vhdl-mode vip viper widget wisent woman ## Info files to install on current platform. INFO_INSTALL = $(INFO_COMMON) $(DOCMISC_W32) diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi new file mode 100644 index 0000000000..17b7bef6b7 --- /dev/null +++ b/doc/misc/transient.texi @@ -0,0 +1,2568 @@ +\input texinfo @c -*- texinfo -*- +@c %**start of header +@setfilename transient.info +@settitle Transient User and Developer Manual +@documentencoding UTF-8 +@documentlanguage en +@c %**end of header + +@copying +@quotation +Copyright (C) 2018-2022 Free Software Foundation, Inc. + +You can redistribute this document 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 document 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. + +@end quotation +@end copying + +@dircategory Emacs +@direntry +* Transient: (transient). Transient Commands. +@end direntry + +@finalout +@titlepage +@title Transient User and Developer Manual +@subtitle for version 0.3.7 +@author Jonas Bernoulli +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@contents + +@ifnottex +@node Top +@top Transient User and Developer Manual + +Taking inspiration from prefix keys and prefix arguments, Transient +implements a similar abstraction involving a prefix command, infix +arguments and suffix commands. We could call this abstraction a +"transient command", but because it always involves at least two +commands (a prefix and a suffix) we prefer to call it just a +"transient". + +When the user calls a transient prefix command, then a transient +(temporary) keymap is activated, which binds the transient's infix +and suffix commands, and functions that control the transient state +are added to @code{pre-command-hook} and @code{post-command-hook}. The available +suffix and infix commands and their state are shown in a popup buffer +until the transient is exited by invoking a suffix command. + +Calling an infix command causes its value to be changed, possibly by +reading a new value in the minibuffer. + +Calling a suffix command usually causes the transient to be exited +but suffix commands can also be configured to not exit the transient. + +@noindent +This manual is for Transient version 0.3.7. + +@insertcopying +@end ifnottex + +@menu +* Introduction:: +* Usage:: +* Modifying Existing Transients:: +* Defining New Commands:: +* Classes and Methods:: +* Related Abstractions and Packages:: +* FAQ:: +* Keystroke Index:: +* Command Index:: +* Function Index:: +* Variable Index:: +* GNU General Public License:: + +@detailmenu +--- The Detailed Node Listing --- + +Usage + +* Invoking Transients:: +* Aborting and Resuming Transients:: +* Common Suffix Commands:: +* Saving Values:: +* Using History:: +* Getting Help for Suffix Commands:: +* Enabling and Disabling Suffixes:: +* Other Commands:: +* Other Options:: + +Defining New Commands + +* Defining Transients:: +* Binding Suffix and Infix Commands:: +* Defining Suffix and Infix Commands:: +* Using Infix Arguments:: +* Transient State:: + +Binding Suffix and Infix Commands + +* Group Specifications:: +* Suffix Specifications:: + + +Classes and Methods + +* Group Classes:: +* Group Methods:: +* Prefix Classes:: +* Suffix Classes:: +* Suffix Methods:: +* Prefix Slots:: +* Suffix Slots:: +* Predicate Slots:: + +Suffix Methods + +* Suffix Value Methods:: +* Suffix Format Methods:: + + +Related Abstractions and Packages + +* Comparison With Prefix Keys and Prefix Arguments:: +* Comparison With Other Packages:: + +@end detailmenu +@end menu + +@node Introduction +@chapter Introduction + +Taking inspiration from prefix keys and prefix arguments, Transient +implements a similar abstraction involving a prefix command, infix +arguments and suffix commands. We could call this abstraction a +"transient command", but because it always involves at least two +commands (a prefix and a suffix) we prefer to call it just a +"transient". + +@quotation +Transient keymaps are a feature provided by Emacs. Transients as +implemented by this package involve the use of transient keymaps. + +Emacs provides a feature that it calls "prefix commands". When we +talk about "prefix commands" in this manual, then we mean our own kind +of "prefix commands", unless specified otherwise. To avoid ambiguity +we sometimes use the terms "transient prefix command" for our kind and +"regular prefix command" for Emacs' kind. + +@end quotation + +When the user calls a transient prefix command, then a transient +(temporary) keymap is activated, which binds the transient's infix and +suffix commands, and functions that control the transient state are +added to @code{pre-command-hook} and @code{post-command-hook}. The available suffix +and infix commands and their state are shown in a popup buffer until +the transient state is exited by invoking a suffix command. + +Calling an infix command causes its value to be changed. How that is +done depends on the type of the infix command. The simplest case is +an infix command that represents a command-line argument that does not +take a value. Invoking such an infix command causes the switch to be +toggled on or off. More complex infix commands may read a value from +the user, using the minibuffer. + +Calling a suffix command usually causes the transient to be exited; +the transient keymaps and hook functions are removed, the popup buffer +no longer shows information about the (no longer bound) suffix +commands, the values of some public global variables are set, while +some internal global variables are unset, and finally the command is +actually called. Suffix commands can also be configured to not exit +the transient. + +A suffix command can, but does not have to, use the infix arguments in +much the same way any command can choose to use or ignore the prefix +arguments. For a suffix command that was invoked from a transient the +variable @code{transient-current-suffixes} and the function @code{transient-args} +serve about the same purpose as the variables @code{prefix-arg} and +@code{current-prefix-arg} do for any command that was called after the prefix +arguments have been set using a command such as @code{universal-argument}. + +The information shown in the popup buffer while a transient is active +looks a bit like this: + +@example +,----------------------------------------- +|Arguments +| -f Force (--force) +| -a Annotate (--annotate) +| +|Create +| t tag +| r release +`----------------------------------------- +@end example + +@quotation +This is a simplified version of @code{magit-tag}. Info manuals do not +support images or colored text, so the above "screenshot" lacks some +information; in practice you would be able to tell whether the +arguments @code{--force} and @code{--annotate} are enabled or not based on their +color. + +@end quotation + +Transient can be used to implement simple "command dispatchers". The +main benefit then is that the user can see all the available commands +in a popup buffer. That is useful by itself because it frees the user +from having to remember all the keys that are valid after a certain +prefix key or command. Magit's @code{magit-dispatch} (on @code{C-x M-g}) command is +an example of using Transient to merely implement a command +dispatcher. + +In addition to that, Transient also allows users to interactively pass +arguments to commands. These arguments can be much more complex than +what is reasonable when using prefix arguments. There is a limit to +how many aspects of a command can be controlled using prefix +arguments. Furthermore what a certain prefix argument means for +different commands can be completely different, and users have to read +documentation to learn and then commit to memory what a certain prefix +argument means to a certain command. + +Transient suffix commands on the other hand can accept dozens of +different arguments without the user having to remember anything. +When using Transient, then one can call a command with arguments that +are just as complex as when calling the same function non-interactively +using code. + +Invoking a transient command with arguments is similar to invoking a +command in a shell with command-line completion and history enabled. +One benefit of the Transient interface is that it remembers history +not only on a global level ("this command was invoked using these +arguments and previously it was invoked using those other arguments"), +but also remembers the values of individual arguments independently. +See @ref{Using History}. + +After a transient prefix command is invoked @code{C-h } can be used to +show the documentation for the infix or suffix command that @code{} is +bound to (see @ref{Getting Help for Suffix Commands}) and infixes and +suffixes can be removed from the transient using @code{C-x l }. Infixes +and suffixes that are disabled by default can be enabled the same way. +See @ref{Enabling and Disabling Suffixes}. + +Transient ships with support for a few different types of specialized +infix commands. A command that sets a command line option for example +has different needs than a command that merely toggles a boolean flag. +Additionally Transient provides abstractions for defining new types, +which the author of Transient did not anticipate (or didn't get around +to implementing yet). + +@node Usage +@chapter Usage + +@menu +* Invoking Transients:: +* Aborting and Resuming Transients:: +* Common Suffix Commands:: +* Saving Values:: +* Using History:: +* Getting Help for Suffix Commands:: +* Enabling and Disabling Suffixes:: +* Other Commands:: +* Other Options:: +@end menu + +@node Invoking Transients +@section Invoking Transients + +A transient prefix command is invoked like any other command by +pressing the key that is bound to that command. The main difference +to other commands is that a transient prefix command activates a +transient keymap, which temporarily binds the transient's infix and +suffix commands. Bindings from other keymaps may, or may not, be +disabled while the transient state is in effect. + +There are two kinds of commands that are available after invoking a +transient prefix command; infix and suffix commands. Infix commands +set some value (which is then shown in a popup buffer), without +leaving the transient. Suffix commands on the other hand usually quit +the transient and they may use the values set by the infix commands, +i.e. the infix @strong{arguments}. + +Instead of setting arguments to be used by a suffix command, infix +commands may also set some value by side-effect, e.g. by setting the +value of some variable. + +@node Aborting and Resuming Transients +@section Aborting and Resuming Transients + +To quit the transient without invoking a suffix command press @code{C-g}. + +Key bindings in transient keymaps may be longer than a single event. +After pressing a valid prefix key, all commands whose bindings do not +begin with that prefix key are temporarily unavailable and grayed out. +To abort the prefix key press @code{C-g} (which in this case only quits the +prefix key, but not the complete transient). + +A transient prefix command can be bound as a suffix of another +transient. Invoking such a suffix replaces the current transient +state with a new transient state, i.e. the available bindings change +and the information displayed in the popup buffer is updated +accordingly. Pressing @code{C-g} while a nested transient is active only +quits the innermost transient, causing a return to the previous +transient. + +@code{C-q} or @code{C-z} on the other hand always exits all transients. If you use +the latter, then you can later resume the stack of transients using +@code{M-x transient-resume}. + +@table @asis +@kindex C-g +@cindex transient-quit-seq +@item @kbd{C-g} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-seq}) +@kindex C-g +@cindex transient-quit-one +@item @kbd{C-g} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-one}) + +This key quits the currently active incomplete key sequence, if any, +or else the current transient. When quitting the current transient, +then it returns to the previous transient, if any. +@end table + +Transient's predecessor bound @code{q} instead of @code{C-g} to the quit command. +To learn how to get that binding back see @code{transient-bind-q-to-quit}'s +doc string. + +@table @asis +@kindex C-q +@cindex transient-quit-all +@item @kbd{C-q} @tie{}@tie{}@tie{}@tie{}(@code{transient-quit-all}) + +This command quits the currently active incomplete key sequence, if +any, and all transients, including the active transient and all +suspended transients, if any. + +@kindex C-z +@cindex transient-suspend +@item @kbd{C-z} @tie{}@tie{}@tie{}@tie{}(@code{transient-suspend}) + +Like @code{transient-quit-all}, this command quits an incomplete key +sequence, if any, and all transients. Additionally it saves the +stack of transients so that it can easily be resumed (which is +particularly useful if you quickly need to do "something else" and +the stack is deeper than a single transient and/or you have already +changed the values of some infix arguments). + +Note that only a single stack of transients can be saved at a time. +If another stack is already saved, then saving a new stack discards +the previous stack. + +@kindex M-x transient-resume +@cindex transient-resume +@item @kbd{M-x transient-resume} @tie{}@tie{}@tie{}@tie{}(@code{transient-resume}) + +This command resumes the previously suspended stack of transients, +if any. +@end table + +@node Common Suffix Commands +@section Common Suffix Commands + +A few shared suffix commands are available in all transients. These +suffix commands are not shown in the popup buffer by default. + +This includes the aborting commands mentioned in the previous node as +well as some other commands that are all bound to @code{C-x }. After +@code{C-x} is pressed, a section featuring all these common commands is +temporarily shown in the popup buffer. After invoking one of them, +the section disappears again. Note however that one of these commands +is described as "Show common permanently"; invoke that if you want the +common commands to always be shown for all transients. + +@table @asis +@kindex C-x t +@cindex transient-toggle-common +@item @kbd{C-x t} @tie{}@tie{}@tie{}@tie{}(@code{transient-toggle-common}) + +This command toggles whether the generic commands that are common to +all transients are always displayed or only after typing the +incomplete prefix key sequence @code{C-x}. This only affects the current +Emacs session. + +@end table + +@defopt transient-show-common-commands + +This option controls whether shared suffix commands are shown +alongside the transient-specific infix and suffix commands. By +default the shared commands are not shown to avoid overwhelming +the user with to many options. + +While a transient is active, pressing @code{C-x} always shows the common +command. The value of this option can be changed for the current +Emacs session by typing @code{C-x t} while a transient is active. +@end defopt + +The other common commands are described in either the previous node or +in one of the following nodes. + +Some of Transient's key bindings differ from the respective bindings +of Magit-Popup; see @ref{FAQ} for more information. + +@node Saving Values +@section Saving Values + +After setting the infix arguments in a transient, the user can save +those arguments for future invocations. + +Most transients will start out with the saved arguments when they are +invoked. There are a few exceptions though. Some transients are +designed so that the value that they use is stored externally as the +buffer-local value of some variable. Invoking such a transient again +uses the buffer-local value. @footnote{@code{magit-diff} and @code{magit-log} are two prominent examples, and their +handling of buffer-local values is actually a bit more complicated +than outlined above and even customizable.} + +If the user does not save the value and just exits using a regular +suffix command, then the value is merely saved to the transient's +history. That value won't be used when the transient is next invoked +but it is easily accessible (see @ref{Using History}). + +@table @asis +@kindex C-x s +@cindex transient-set +@item @kbd{C-x s} @tie{}@tie{}@tie{}@tie{}(@code{transient-set}) + +This command saves the value of the active transient for this Emacs +session. + +@kindex C-x C-s +@cindex transient-save +@item @kbd{C-x C-s} @tie{}@tie{}@tie{}@tie{}(@code{transient-save}) + +Save the value of the active transient persistently across Emacs +sessions. + +@end table + +@defopt transient-values-file + +This file is used to persist the values of transients between Emacs +sessions. +@end defopt + +@node Using History +@section Using History + +Every time the user invokes a suffix command the transient's current +value is saved to its history. These values can be cycled through the +same way one can cycle through the history of commands that read +user-input in the minibuffer. + +@table @asis +@kindex C-M-p +@cindex transient-history-prev +@item @kbd{C-M-p} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-prev}) +@kindex C-x p +@cindex transient-history-prev +@item @kbd{C-x p} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-prev}) + +This command switches to the previous value used for the active +transient. + +@kindex C-M-n +@cindex transient-history-next +@item @kbd{C-M-n} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-next}) +@kindex C-x n +@cindex transient-history-next +@item @kbd{C-x n} @tie{}@tie{}@tie{}@tie{}(@code{transient-history-next}) + +This command switches to the next value used for the active +transient. +@end table + +In addition to the transient-wide history, Transient of course +supports per-infix history. When an infix reads user-input using the +minibuffer, then the user can use the regular minibuffer history +commands to cycle through previously used values. Usually the same +keys as those mentioned above are bound to those commands. + +Authors of transients should arrange for different infix commands that +read the same kind of value to also use the same history key (see +@ref{Suffix Slots}). + +Both kinds of history are saved to a file when Emacs is exited. + +@defopt transient-history-file + +This file is used to persist the history of transients and their +infixes between Emacs sessions. +@end defopt + +@defopt transient-history-limit + +This option controls how many history elements are kept at the time +the history is saved in @code{transient-history-file}. +@end defopt + +@node Getting Help for Suffix Commands +@section Getting Help for Suffix Commands + +Transients can have many suffixes and infixes that the user might not +be familiar with. To make it trivial to get help for these, Transient +provides access to the documentation directly from the active +transient. + +@table @asis +@kindex C-h +@cindex transient-help +@item @kbd{C-h} @tie{}@tie{}@tie{}@tie{}(@code{transient-help}) + +This command enters help mode. When help mode is active, then +typing @code{} shows information about the suffix command that @code{} +normally is bound to (instead of invoking it). Pressing @code{C-h} a +second time shows information about the @emph{prefix} command. + +After typing @code{} the stack of transient states is suspended and +information about the suffix command is shown instead. Typing @code{q} in +the help buffer buries that buffer and resumes the transient state. +@end table + +What sort of documentation is shown depends on how the transient was +defined. For infix commands that represent command-line arguments +this ideally shows the appropriate manpage. @code{transient-help} then tries +to jump to the correct location within that. Info manuals are also +supported. The fallback is to show the command's doc string, for +non-infix suffixes this is usually appropriate. + +@node Enabling and Disabling Suffixes +@section Enabling and Disabling Suffixes + +The user base of a package that uses transients can be very diverse. +This is certainly the case for Magit; some users have been using it and +Git for a decade, while others are just getting started now. + +For that reason a mechanism is needed that authors can use to classify a +transient's infixes and suffixes along the essentials@dots{}everything +spectrum. We use the term "levels" to describe that mechanism. + +Each suffix command is placed on a level and each transient has a +level (called transient-level), which controls which suffix commands +are available. Integers between 1 and 7 (inclusive) are valid levels. +For suffixes, 0 is also valid; it means that the suffix is not +displayed at any level. + +The levels of individual transients and/or their individual suffixes +can be changed interactively, by invoking the transient and then +pressing @code{C-x l} to enter the "edit" mode, see below. + +The default level for both transients and their suffixes is 4. The +@code{transient-default-level} option only controls the default for +transients. The default suffix level is always 4. The authors of +transients should place certain suffixes on a higher level, if they +expect that it won't be of use to most users, and they should place +very important suffixes on a lower level, so that they remain +available even if the user lowers the transient level. + +@defopt transient-default-level + +This option controls which suffix levels are made available by +default. It sets the transient-level for transients for which the +user has not set that individually. +@end defopt + +@defopt transient-levels-file + +This file is used to persist the levels of transients and their +suffixes between Emacs sessions. +@end defopt + +@table @asis +@kindex C-x l +@cindex transient-set-level +@item @kbd{C-x l} @tie{}@tie{}@tie{}@tie{}(@code{transient-set-level}) + +This command enters edit mode. When edit mode is active, then all +infixes and suffixes that are currently usable are displayed along +with their levels. The colors of the levels indicate whether they +are enabled or not. The level of the transient is also displayed +along with some usage information. + +In edit mode, pressing the key that would usually invoke a certain +suffix instead prompts the user for the level that suffix should be +placed on. + +Help mode is available in edit mode. + +To change the transient level press @code{C-x l} again. + +To exit edit mode press @code{C-g}. + +Note that edit mode does not display any suffixes that are not +currently usable. @code{magit-rebase} for example shows different suffixes +depending on whether a rebase is already in progress or not. The +predicates also apply in edit mode. + +Therefore, to control which suffixes are available given a certain +state, you have to make sure that that state is currently active. +@end table + +@node Other Commands +@section Other Commands + +When invoking a transient in a small frame, the transient window may +not show the complete buffer, making it necessary to scroll, using the +following commands. These commands are never shown in the transient +window, and the key bindings are the same as for @code{scroll-up-command} and +@code{scroll-down-command} in other buffers. + +@cindex transient-scroll-up arg +@deffn Command transient-scroll-up arg + +This command scrolls text of transient popup window upward ARG +lines. If ARG is @code{nil}, then it scrolls near full screen. This +is a wrapper around @code{scroll-up-command} (which see). +@end deffn + +@cindex transient-scroll-down arg +@deffn Command transient-scroll-down arg + +This command scrolls text of transient popup window down ARG +lines. If ARG is @code{nil}, then it scrolls near full screen. This +is a wrapper around @code{scroll-down-command} (which see). +@end deffn + +@node Other Options +@section Other Options + +@defopt transient-show-popup + +This option controls whether the current transient's infix and +suffix commands are shown in the popup buffer. + +@itemize +@item +If @code{t} (the default) then the popup buffer is shown as soon as a +transient prefix command is invoked. + + +@item +If @code{nil}, then the popup buffer is not shown unless the user +explicitly requests it, by pressing an incomplete prefix key +sequence. + + +@item +If a number, then the a brief one-line summary is shown instead of +the popup buffer. If zero or negative, then not even that summary +is shown; only the pressed key itself is shown. + +The popup is shown when the user explicitly requests it by +pressing an incomplete prefix key sequence. Unless this is zero, +then the popup is shown after that many seconds of inactivity +(using the absolute value). +@end itemize +@end defopt + +@defopt transient-enable-popup-navigation + +This option controls whether navigation commands are enabled in the +transient popup buffer. + +While a transient is active the transient popup buffer is not the +current buffer, making it necessary to use dedicated commands to act +on that buffer itself. This is disabled by default. If this option +is non-nil, then the following features are available: + +@itemize +@item +@code{} moves the cursor to the previous suffix. +@code{} moves the cursor to the next suffix. +@code{RET} invokes the suffix the cursor is on. + +@item +@code{} invokes the clicked on suffix. + +@item +@code{C-s} and @code{C-r} start isearch in the popup buffer. +@end itemize +@end defopt + +@defopt transient-display-buffer-action + +This option specifies the action used to display the transient popup +buffer. The transient popup buffer is displayed in a window using +@code{(display-buffer BUFFER transient-display-buffer-action)}. + +The value of this option has the form @code{(FUNCTION . ALIST)}, +where FUNCTION is a function or a list of functions. Each such +function should accept two arguments: a buffer to display and an +alist of the same form as ALIST@. See @ref{Choosing Window,,,elisp,} +for details. + +The default is: + +(display-buffer-in-side-window + (side . bottom) + (inhibit-same-window . t) + (window-parameters (no-other-window . t))) + +This displays the window at the bottom of the selected frame. +Another useful FUNCTION is @code{display-buffer-below-selected}, which +is what @code{magit-popup} used by default. For more alternatives see +@ref{Display Action Functions,,,elisp,} and @ref{Buffer Display Action Alists,,,elisp,}. + +Note that the buffer that was current before the transient buffer +is shown should remain the current buffer. Many suffix commands +act on the thing at point, if appropriate, and if the transient +buffer became the current buffer, then that would change what is +at point. To that effect @code{inhibit-same-window} ensures that the +selected window is not used to show the transient buffer. + +It may be possible to display the window in another frame, but +whether that works in practice depends on the window-manager. +If the window manager selects the new window (Emacs frame), +then that unfortunately changes which buffer is current. + +If you change the value of this option, then you might also +want to change the value of @code{transient-mode-line-format}. +@end defopt + +@defopt transient-mode-line-format + +This option controls whether the transient popup buffer has a +mode-line, separator line, or neither. + +If @code{nil}, then the buffer has no mode-line. If the buffer is not +displayed right above the echo area, then this probably is not a +good value. + +If @code{line} (the default), then the buffer also has no mode-line, but a +thin line is drawn instead, using the background color of the face +@code{transient-separator}. Termcap frames cannot display thin lines and +therefore fallback to treating @code{line} like @code{nil}. + +Otherwise this can be any mode-line format. See @ref{Mode Line Format,,,elisp,} for details. +@end defopt + +@defopt transient-read-with-initial-input + +This option controls whether the last history element is used as the +initial minibuffer input when reading the value of an infix argument +from the user. If @code{nil}, then there is no initial input and the first +element has to be accessed the same way as the older elements. +@end defopt + +@defopt transient-highlight-mismatched-keys + +This option controls whether key bindings of infix commands that do +not match the respective command-line argument should be highlighted. +For other infix commands this option has no effect. + +When this option is non-nil, then the key binding for an infix argument +is highlighted when only a long argument (e.g. @code{--verbose}) is +specified but no shorthand (e.g @code{-v}). In the rare case that a +shorthand is specified but the key binding does not match, then it +is highlighted differently. + +Highlighting mismatched key bindings is useful when learning the +arguments of the underlying command-line tool; you wouldn't want to +learn any short-hands that do not actually exist. + +The highlighting is done using one of the faces +@code{transient-mismatched-key} and @code{transient-nonstandard-key}. +@end defopt + +@defopt transient-substitute-key-function + +This function is used to modify key bindings. If the value of this +option is nil (the default), then no substitution is performed. + +This function is called with one argument, the prefix object, and +must return a key binding description, either the existing key +description it finds in the @code{key} slot, or the key description that +replaces the prefix key. It could be used to make other +substitutions, but that is discouraged. + +For example, @code{=} is hard to reach using my custom keyboard layout, +so I substitute @code{(} for that, which is easy to reach using a layout +optimized for lisp. + +@lisp +(setq transient-substitute-key-function + (lambda (obj) + (let ((key (oref obj key))) + (if (string-match "\\`\\(=\\)[a-zA-Z]" key) + (replace-match "(" t t key 1) + key)))) +@end lisp +@end defopt + +@defopt transient-detect-key-conflicts + +This option controls whether key binding conflicts should be +detected at the time the transient is invoked. If so, then this +results in an error, which prevents the transient from being used. +Because of that, conflicts are ignored by default. + +Conflicts cannot be determined earlier, i.e. when the transient is +being defined and when new suffixes are being added, because at that +time there can be false-positives. It is actually valid for +multiple suffixes to share a common key binding, provided the +predicates of those suffixes prevent that more than one of them is +enabled at a time. +@end defopt + +@defopt transient-force-fixed-pitch + +This option controls whether to force the use of a monospaced font +in popup buffer. Even if you use a proportional font for the +@code{default} face, you might still want to use a monospaced font in +transient's popup buffer. Setting this option to t causes @code{default} +to be remapped to @code{fixed-pitch} in that buffer. +@end defopt + +@node Modifying Existing Transients +@chapter Modifying Existing Transients + +To an extent transients can be customized interactively, see @ref{Enabling and Disabling Suffixes}. This section explains how existing transients +can be further modified non-interactively. + +The following functions share a few arguments: + +@itemize +@item +PREFIX is a transient prefix command, a symbol. + + +@item +SUFFIX is a transient infix or suffix specification in the same form +as expected by @code{transient-define-prefix}. Note that an infix is a +special kind of suffix. Depending on context "suffixes" means +"suffixes (including infixes)" or "non-infix suffixes". Here it +means the former. See @ref{Suffix Specifications}. + +SUFFIX may also be a group in the same form as expected by +@code{transient-define-prefix}. See @ref{Group Specifications}. + + +@item +LOC is a command, a key vector, a key description (a string as +returned by @code{key-description}), or a list specifying coordinates (the +last element may also be a command or key). For example @code{(1 0 -1)} +identifies the last suffix (@code{-1}) of the first subgroup (@code{0}) of the +second group (@code{1}). + +If LOC is a list of coordinates, then it can be used to identify a +group, not just an individual suffix command. + +The function @code{transient-get-suffix} can be useful to determine whether +a certain coordination list identifies the suffix or group that you +expect it to identify. In hairy cases it may be necessary to look +at the definition of the transient prefix command. +@end itemize + +These functions operate on the information stored in the +@code{transient--layout} property of the PREFIX symbol. Suffix entries in +that tree are not objects but have the form @code{(LEVEL CLASS PLIST)}, where +plist should set at least @code{:key}, @code{:description} and @code{:command}. + +@defun transient-insert-suffix prefix loc suffix + +This function inserts suffix or group SUFFIX into PREFIX before LOC@. +@end defun + +@defun transient-append-suffix prefix loc suffix + +This function inserts suffix or group SUFFIX into PREFIX after LOC@. +@end defun + +@defun transient-replace-suffix prefix loc suffix + +This function replaces the suffix or group at LOC in PREFIX with +suffix or group SUFFIX@. +@end defun + +@defun transient-remove-suffix prefix loc + +This function removes the suffix or group at LOC in PREFIX@. +@end defun + +@defun transient-get-suffix prefix loc + +This function returns the suffix or group at LOC in PREFIX@. The +returned value has the form mentioned above. +@end defun + +@defun transient-suffix-put prefix loc prop value + +This function edits the suffix or group at LOC in PREFIX, by setting +the PROP of its plist to VALUE@. +@end defun + +Most of these functions do not signal an error if they cannot perform +the requested modification. The functions that insert new suffixes +show a warning if LOC cannot be found in PREFIX, without signaling an +error. The reason for doing it like this is that establishing a key +binding (and that is what we essentially are trying to do here) should +not prevent the rest of the configuration from loading. Among these +functions only @code{transient-get-suffix} and @code{transient-suffix-put} may +signal an error. + +@node Defining New Commands +@chapter Defining New Commands + +@menu +* Defining Transients:: +* Binding Suffix and Infix Commands:: +* Defining Suffix and Infix Commands:: +* Using Infix Arguments:: +* Transient State:: +@end menu + +@node Defining Transients +@section Defining Transients + +A transient consists of a prefix command and at least one suffix +command, though usually a transient has several infix and suffix +commands. The below macro defines the transient prefix command @strong{and} +binds the transient's infix and suffix commands. In other words, it +defines the complete transient, not just the transient prefix command +that is used to invoke that transient. + +@defmac transient-define-prefix name arglist [docstring] [keyword value]@dots{} group@dots{} [body@dots{}] + +This macro defines NAME as a transient prefix command and binds the +transient's infix and suffix commands. + +ARGLIST are the arguments that the prefix command takes. +DOCSTRING is the documentation string and is optional. + +These arguments can optionally be followed by keyword-value pairs. +Each key has to be a keyword symbol, either @code{:class} or a keyword +argument supported by the constructor of that class. The +@code{transient-prefix} class is used if the class is not specified +explicitly. + +GROUPs add key bindings for infix and suffix commands and specify +how these bindings are presented in the popup buffer. At least one +GROUP has to be specified. See @ref{Binding Suffix and Infix Commands}. + +The BODY is optional. If it is omitted, then ARGLIST is ignored and +the function definition becomes: + +@lisp +(lambda () + (interactive) + (transient-setup 'NAME)) +@end lisp + +If BODY is specified, then it must begin with an @code{interactive} form +that matches ARGLIST, and it must call @code{transient-setup}. It may +however call that function only when some condition is satisfied. + +All transients have a (possibly @code{nil}) value, which is exported when +suffix commands are called, so that they can consume that value. +For some transients it might be necessary to have a sort of +secondary value, called a "scope". Such a scope would usually be +set in the command's @code{interactive} form and has to be passed to the +setup function: + +@lisp +(transient-setup 'NAME nil nil :scope SCOPE) +@end lisp + +For example, the scope of the @code{magit-branch-configure} transient is +the branch whose variables are being configured. +@end defmac + +@node Binding Suffix and Infix Commands +@section Binding Suffix and Infix Commands + +The macro @code{transient-define-prefix} is used to define a transient. +This defines the actual transient prefix command (see @ref{Defining Transients}) and adds the transient's infix and suffix bindings, as +described below. + +Users and third-party packages can add additional bindings using +functions such as @code{transient-insert-suffix} (See @ref{Modifying Existing Transients}). These functions take a "suffix specification" as one of +their arguments, which has the same form as the specifications used in +@code{transient-define-prefix}. + +@menu +* Group Specifications:: +* Suffix Specifications:: +@end menu + +@node Group Specifications +@subsection Group Specifications + +The suffix and infix commands of a transient are organized in groups. +The grouping controls how the descriptions of the suffixes are +outlined visually but also makes it possible to set certain properties +for a set of suffixes. + +Several group classes exist, some of which organize suffixes in +subgroups. In most cases the class does not have to be specified +explicitly, but see @ref{Group Classes}. + +Groups are specified in the call to @code{transient-define-prefix}, using +vectors. Because groups are represented using vectors, we cannot use +square brackets to indicate an optional element and instead use curly +brackets to do the latter. + +Group specifications then have this form: + +@lisp +[@{LEVEL@} @{DESCRIPTION@} @{KEYWORD VALUE@}... ELEMENT...] +@end lisp + +The LEVEL is optional and defaults to 4. See @ref{Enabling and Disabling Suffixes}. + +The DESCRIPTION is optional. If present it is used as the heading of +the group. + +The KEYWORD-VALUE pairs are optional. Each keyword has to be a +keyword symbol, either @code{:class} or a keyword argument supported by the +constructor of that class. + +@itemize +@item +One of these keywords, @code{:description}, is equivalent to specifying +DESCRIPTION at the very beginning of the vector. The recommendation +is to use @code{:description} if some other keyword is also used, for +consistency, or DESCRIPTION otherwise, because it looks better. + + +@item +Likewise @code{:level} is equivalent to LEVEL@. + + +@item +Other important keywords include the @code{:if...} keywords. These +keywords control whether the group is available in a certain +situation. + +For example, one group of the @code{magit-rebase} transient uses @code{:if + magit-rebase-in-progress-p}, which contains the suffixes that are +useful while rebase is already in progress; and another that uses +@code{:if-not magit-rebase-in-progress-p}, which contains the suffixes that +initiate a rebase. + +These predicates can also be used on individual suffixes and are +only documented once, see @ref{Predicate Slots}. + + +@item +The value of @code{:hide}, if non-nil, is a predicate that controls +whether the group is hidden by default. The key bindings for +suffixes of a hidden group should all use the same prefix key. +Pressing that prefix key should temporarily show the group and its +suffixes, which assumes that a predicate like this is used: + +@lisp +(lambda () + (eq (car transient--redisplay-key) + ?\C-c)) ; the prefix key shared by all bindings +@end lisp + + +@item +The value of @code{:setup-children}, if non-nil, is a function that takes +two arguments the group object itself and a list of children. +The children are given as a, potentially empty, list consisting +of either group or suffix specifications. It can make arbitrary +changes to the children including constructing new children from +scratch. Also see @code{transient-setup-children}. + + +@item +The boolean @code{:pad-keys} argument controls whether keys of all suffixes +contained in a group are right padded, effectively aligning the +descriptions. +@end itemize + +The ELEMENTs are either all subgroups (vectors), or all suffixes +(lists) and strings. (At least currently no group type exists that +would allow mixing subgroups with commands at the same level, though +in principle there is nothing that prevents that.) + +If the ELEMENTs are not subgroups, then they can be a mixture of lists +that specify commands and strings. Strings are inserted verbatim. +The empty string can be used to insert gaps between suffixes, which is +particularly useful if the suffixes are outlined as a table. + +Variables are supported inside group specifications. For example in +place of a direct subgroup specification, a variable can be used whose +value is a vector that qualifies as a group specification. Likewise a +variable can be used where a suffix specification is expected. Lists +of group or suffix specifications are also supported. Indirect +specifications are resolved when the transient prefix is being +defined. + +The form of suffix specifications is documented in the next node. + +@node Suffix Specifications +@subsection Suffix Specifications + +A transient's suffix and infix commands are bound when the transient +prefix command is defined using @code{transient-define-prefix}, see +@ref{Defining Transients}. The commands are organized into groups, see +@ref{Group Specifications}. Here we describe the form used to bind an +individual suffix command. + +The same form is also used when later binding additional commands +using functions such as @code{transient-insert-suffix}, see @ref{Modifying Existing Transients}. + +Note that an infix is a special kind of suffix. Depending on context +"suffixes" means "suffixes (including infixes)" or "non-infix +suffixes". Here it means the former. + +Suffix specifications have this form: + +@lisp +([LEVEL] [KEY] [DESCRIPTION] COMMAND|ARGUMENT [KEYWORD VALUE]...) +@end lisp + +LEVEL, KEY and DESCRIPTION can also be specified using the KEYWORDs +@code{:level}, @code{:key} and @code{:description}. If the object that is associated with +COMMAND sets these properties, then they do not have to be specified +here. You can however specify them here anyway, possibly overriding +the object's values just for the binding inside this transient. + +@itemize +@item +LEVEL is the suffix level, an integer between 1 and 7. See +@ref{Enabling and Disabling Suffixes}. + + +@item +KEY is the key binding, either a vector or key description string. + + +@item +DESCRIPTION is the description, either a string or a function that +returns a string. The function should be a lambda expression to +avoid ambiguity. In some cases a symbol that is bound as a function +would also work but to be safe you should use @code{:description} in that +case. +@end itemize + +The next element is either a command or an argument. This is the only +argument that is mandatory in all cases. + +@itemize +@item +Usually COMMAND is a symbol that is bound as a function, which has +to be defined or at least autoloaded as a command by the time the +containing prefix command is invoked. + +Any command will do; it does not need to have an object associated +with it (as would be the case if @code{transient-define-suffix} or +@code{transient-define-infix} were used to define it). + +The command can also be a closure or lambda expression, but that +should only be used for dynamic transients whose suffixes are +defined when the prefix command is invoked. See information about +the @code{:setup-children} function in @ref{Group Specifications}. + +As mentioned above, the object that is associated with a command can +be used to set the default for certain values that otherwise have to +be set in the suffix specification. Therefore if there is no object, +then you have to make sure to specify the KEY and the DESCRIPTION@. + +As a special case, if you want to add a command that might be neither +defined nor autoloaded, you can use a workaround like: + +@lisp +(transient-insert-suffix 'some-prefix "k" + '("!" "Ceci n'est pas une commande" no-command + :if (lambda () (featurep 'no-library)))) +@end lisp + +Instead of @code{featurep} you could also use @code{require} with a non-nil value +for NOERROR@. + + +@item +The mandatory argument can also be a command-line argument, a +string. In that case an anonymous command is defined and bound. + +Instead of a string, this can also be a list of two strings, in +which case the first string is used as the short argument (which can +also be specified using @code{:shortarg}) and the second as the long argument +(which can also be specified using @code{:argument}). + +Only the long argument is displayed in the popup buffer. See +@code{transient-detect-key-conflicts} for how the short argument may be +used. + +Unless the class is specified explicitly, the appropriate class is +guessed based on the long argument. If the argument ends with "=​" +(e.g. "--format=") then @code{transient-option} is used, otherwise +@code{transient-switch}. +@end itemize + +Finally, details can be specified using optional KEYWORD-VALUE pairs. +Each keyword has to be a keyword symbol, either @code{:class} or a keyword +argument supported by the constructor of that class. See @ref{Suffix Slots}. + +@node Defining Suffix and Infix Commands +@section Defining Suffix and Infix Commands + +Note that an infix is a special kind of suffix. Depending on context +"suffixes" means "suffixes (including infixes)" or "non-infix +suffixes". + +@defmac transient-define-suffix name arglist [docstring] [keyword value]@dots{} body@dots{} + +This macro defines NAME as a transient suffix command. + +ARGLIST are the arguments that the command takes. +DOCSTRING is the documentation string and is optional. + +These arguments can optionally be followed by keyword-value pairs. +Each keyword has to be a keyword symbol, either @code{:class} or a keyword +argument supported by the constructor of that class. The +@code{transient-suffix} class is used if the class is not specified +explicitly. + +The BODY must begin with an @code{interactive} form that matches ARGLIST@. +The infix arguments are usually accessed by using @code{transient-args} +inside @code{interactive}. +@end defmac + +@defmac transient-define-infix name arglist [docstring] [keyword value]@dots{} + +This macro defines NAME as a transient infix command. + +ARGLIST is always ignored (but mandatory never-the-less) and +reserved for future use. DOCSTRING is the documentation string and +is optional. + +The keyword-value pairs are mandatory. All transient infix commands +are @code{equal} to each other (but not @code{eq}), so it is meaningless to define +an infix command without also setting at least @code{:class} and one other +keyword (which it is depends on the used class, usually @code{:argument} or +@code{:variable}). + +Each keyword has to be a keyword symbol, either @code{:class} or a keyword +argument supported by the constructor of that class. The +@code{transient-switch} class is used if the class is not specified +explicitly. + +The function definition is always: + +@lisp +(lambda () + (interactive) + (let ((obj (transient-suffix-object))) + (transient-infix-set obj (transient-infix-read obj))) + (transient--show)) +@end lisp + +@code{transient-infix-read} and @code{transient-infix-set} are generic functions. +Different infix commands behave differently because the concrete +methods are different for different infix command classes. In rare +cases the above command function might not be suitable, even if you +define your own infix command class. In that case you have to use +@code{transient-suffix-command} to define the infix command and use @code{t} as +the value of the @code{:transient} keyword. +@end defmac + +@defmac transient-define-argument name arglist [docstring] [keyword value]@dots{} + +This macro defines NAME as a transient infix command. + +This is an alias for @code{transient-define-infix}. Only use this alias +to define an infix command that actually sets an infix argument. +To define an infix command that, for example, sets a variable, use +@code{transient-define-infix} instead. +@end defmac + +@node Using Infix Arguments +@section Using Infix Arguments + +The function and the variables described below allow suffix commands +to access the value of the transient from which they were invoked; +which is the value of its infix arguments. These variables are set +when the user invokes a suffix command that exits the transient, but +before actually calling the command. + +When returning to the command-loop after calling the suffix command, +the arguments are reset to @code{nil} (which causes the function to return +@code{nil} too). + +Like for Emacs' prefix arguments it is advisable, but not mandatory, +to access the infix arguments inside the command's @code{interactive} form. +The preferred way of doing that is to call the @code{transient-args} +function, which for infix arguments serves about the same purpose as +@code{prefix-arg} serves for prefix arguments. + +@defun transient-args prefix + +This function returns the value of the transient prefix command +PREFIX@. + +If the current command was invoked from the transient prefix command +PREFIX, then it returns the active infix arguments. If the current +command was not invoked from PREFIX, then it returns the set, saved +or default value for PREFIX@. +@end defun + +@defun transient-arg-value arg args + +This function return the value of ARG as it appears in ARGS@. + +For a switch a boolean is returned. For an option the value is +returned as a string, using the empty string for the empty value, +or nil if the option does not appear in ARGS@. +@end defun + +@defun transient-suffixes prefix + +This function returns the suffixes of the transient prefix command +PREFIX@. This is a list of objects. This function should only be +used if you need the objects (as opposed to just their values) and +if the current command is not being invoked from PREFIX@. +@end defun + +@defvar transient-current-suffixes + +The suffixes of the transient from which this suffix command was +invoked. This is a list of objects. Usually it is sufficient to +instead use the function @code{transient-args}, which returns a list of +values. In complex cases it might be necessary to use this variable +instead, i.e. if you need access to information beside the value. +@end defvar + +@defvar transient-current-prefix + +The transient from which this suffix command was invoked. The +returned value is a @code{transient-prefix} object, which holds information +associated with the transient prefix command. +@end defvar + +@defvar transient-current-command + +The transient from which this suffix command was invoked. The +returned value is a symbol, the transient prefix command. +@end defvar + +@node Transient State +@section Transient State + +Invoking a transient prefix command "activates" the respective +transient, i.e. it puts a transient keymap into effect, which binds +the transient's infix and suffix commands. + +The default behavior while a transient is active is as follows: + +@itemize +@item +Invoking an infix command does not affect the transient state; the +transient remains active. + + +@item +Invoking a (non-infix) suffix command "deactivates" the transient +state by removing the transient keymap and performing some +additional cleanup. + + +@item +Invoking a command that is bound in a keymap other than the +transient keymap is disallowed and trying to do so results in a +warning. This does not "deactivate" the transient. +@end itemize + +But these are just the defaults. Whether a certain command +deactivates or "exits" the transient is configurable. There is more +than one way in which a command can be "transient" or "non-transient"; +the exact behavior is implemented by calling a so-called "pre-command" +function. Whether non-suffix commands are allowed to be called is +configurable per transient. + +@itemize +@item +The transient-ness of suffix commands (including infix commands) is +controlled by the value of their @code{transient} slot, which can be set +either when defining the command or when adding a binding to a +transient while defining the respective transient prefix command. + +Valid values are booleans and the pre-commands described below. + +@itemize +@item +@code{t} is equivalent to @code{transient--do-stay}. + +@item +@code{nil} is equivalent to @code{transient--do-exit}. + +@item +If @code{transient} is unbound (and that is actually the default for +non-infix suffixes) then the value of the prefix's +@code{transient-suffix} slot is used instead. The default value of that +slot is @code{nil}, so the suffix's @code{transient} slot being unbound is +essentially equivalent to it being @code{nil}. +@end itemize + + +@item +A suffix command can be a prefix command itself, i.e. a +"sub-prefix". While a sub-prefix is active we nearly always want +@code{C-g} to take the user back to the "super-prefix". However in rare +cases this may not be desirable, and that makes the following +complication necessary: + +For @code{transient-suffix} objects the @code{transient} slot is unbound. We can +ignore that for the most part because, as stated above, @code{nil} and the +slot being unbound are equivalent, and mean "do exit". That isn't +actually true for suffixes that are sub-prefixes though. For such +suffixes unbound means "do exit but allow going back", which is the +default, while @code{nil} means "do exit permanently", which requires that +slot to be explicitly set to that value. + + +@item +The transient-ness of certain built-in suffix commands is specified +using @code{transient-predicate-map}. This is a special keymap, which +binds commands to pre-commands (as opposed to keys to commands) and +takes precedence over the @code{transient} slot. +@end itemize + +The available pre-command functions are documented below. They are +called by @code{transient--pre-command}, a function on @code{pre-command-hook} and +the value that they return determines whether the transient is exited. +To do so the value of one of the constants @code{transient--exit} or +@code{transient--stay} is used (that way we don't have to remember if @code{t} means +"exit" or "stay"). + +Additionally these functions may change the value of @code{this-command} +(which explains why they have to be called using @code{pre-command-hook}), +call @code{transient-export}, @code{transient--stack-zap} or @code{transient--stack-push}; +and set the values of @code{transient--exitp}, @code{transient--helpp} or +@code{transient--editp}. + +@anchor{Pre-commands for Infixes} +@subheading Pre-commands for Infixes + +The default for infixes is @code{transient--do-stay}. This is also the only +function that makes sense for infixes. + +@defun transient--do-stay + +Call the command without exporting variables and stay transient. +@end defun + +@anchor{Pre-commands for Suffixes} +@subheading Pre-commands for Suffixes + +The default for suffixes is @code{transient--do-exit}. + +@defun transient--do-exit + +Call the command after exporting variables and exit the transient. +@end defun + +@defun transient--do-call + +Call the command after exporting variables and stay transient. +@end defun + +@defun transient--do-replace + +Call the transient prefix command, replacing the active transient. + +This is used for suffixes that are prefixes themselves, i.e. for +sub-prefixes. +@end defun + +@anchor{Pre-commands for Non-Suffixes} +@subheading Pre-commands for Non-Suffixes + +The default for non-suffixes, i.e commands that are bound in other +keymaps beside the transient keymap, is @code{transient--do-warn}. Silently +ignoring the user-error is also an option, though probably not a good +one. + +If you want to let the user invoke non-suffix commands, then use +@code{transient--do-stay} as the value of the prefix's @code{transient-non-suffix} +slot. + +@defun transient--do-warn + +Call @code{transient-undefined} and stay transient. +@end defun + +@defun transient--do-noop + +Call @code{transient-noop} and stay transient. +@end defun + +@anchor{Special Pre-Commands} +@subheading Special Pre-Commands + +@defun transient--do-quit-one + +If active, quit help or edit mode, else exit the active transient. + +This is used when the user pressed @code{C-g}. +@end defun + +@defun transient--do-quit-all + +Exit all transients without saving the transient stack. + +This is used when the user pressed @code{C-q}. +@end defun + +@defun transient--do-suspend + +Suspend the active transient, saving the transient stack. + +This is used when the user pressed @code{C-z}. +@end defun + +@node Classes and Methods +@chapter Classes and Methods + +Transient uses classes and generic functions to make it possible to +define new types of suffix commands that are similar to existing +types, but behave differently in some aspects. It does the same for +groups and prefix commands, though at least for prefix commands that +@strong{currently} appears to be less important. + +Every prefix, infix and suffix command is associated with an object, +which holds information that controls certain aspects of its behavior. +This happens in two ways. + +@itemize +@item +Associating a command with a certain class gives the command a type. +This makes it possible to use generic functions to do certain things +that have to be done differently depending on what type of command +it acts on. + +That in turn makes it possible for third-parties to add new types +without having to convince the maintainer of Transient that that new +type is important enough to justify adding a special case to a dozen +or so functions. + + +@item +Associating a command with an object makes it possible to easily +store information that is specific to that particular command. + +Two commands may have the same type, but obviously their key +bindings and descriptions still have to be different, for example. + +The values of some slots are functions. The @code{reader} slot for example +holds a function that is used to read a new value for an infix +command. The values of such slots are regular functions. + +Generic functions are used when a function should do something +different based on the type of the command, i.e. when all commands +of a certain type should behave the same way but different from the +behavior for other types. Object slots that hold a regular function +as value are used when the task that they perform is likely to +differ even between different commands of the same type. +@end itemize + +@menu +* Group Classes:: +* Group Methods:: +* Prefix Classes:: +* Suffix Classes:: +* Suffix Methods:: +* Prefix Slots:: +* Suffix Slots:: +* Predicate Slots:: +@end menu + +@node Group Classes +@section Group Classes + +The type of a group can be specified using the @code{:class} property at the +beginning of the class specification, e.g. @code{[:class transient-columns +...]} in a call to @code{transient-define-prefix}. + +@itemize +@item +The abstract @code{transient-child} class is the base class of both +@code{transient-group} (and therefore all groups) as well as of +@code{transient-suffix} (and therefore all suffix and infix commands). + +This class exists because the elements (aka "children") of certain +groups can be other groups instead of suffix and infix commands. + + +@item +The abstract @code{transient-group} class is the superclass of all other +group classes. + + +@item +The @code{transient-column} class is the simplest group. + +This is the default "flat" group. If the class is not specified +explicitly and the first element is not a vector (i.e. not a group), +then this class is used. + +This class displays each element on a separate line. + + +@item +The @code{transient-row} class displays all elements on a single line. + + +@item +The @code{transient-columns} class displays commands organized in columns. + +Direct elements have to be groups whose elements have to be commands +or strings. Each subgroup represents a column. This class takes +care of inserting the subgroups' elements. + +This is the default "nested" group. If the class is not specified +explicitly and the first element is a vector (i.e. a group), then +this class is used. + + +@item +The @code{transient-subgroups} class wraps other groups. + +Direct elements have to be groups whose elements have to be commands +or strings. This group inserts an empty line between subgroups. +The subgroups themselves are responsible for displaying their +elements. +@end itemize + +@node Group Methods +@section Group Methods + +@defun transient-setup-children group children + +This generic function can be used to setup the children or a group. + +The default implementation usually just returns the children +unchanged, but if the @code{setup-children} slot of GROUP is non-nil, then +it calls that function with CHILDREN as the only argument and +returns the value. + +The children are given as a, potentially empty, list consisting of +either group or suffix specifications. These functions can make +arbitrary changes to the children including constructing new +children from scratch. +@end defun + +@defun transient--insert-group group + +This generic function formats the group and its elements and inserts +the result into the current buffer, which is a temporary buffer. +The contents of that buffer are later inserted into the popup buffer. + +Functions that are called by this function may need to operate in +the buffer from which the transient was called. To do so they can +temporarily make the @code{transient--source-buffer} the current buffer. +@end defun + +@node Prefix Classes +@section Prefix Classes + +Currently the @code{transient-prefix} class is being used for all prefix +commands and there is only a single generic function that can be +specialized based on the class of a prefix command. + +@defun transient--history-init obj + +This generic function is called while setting up the transient and +is responsible for initializing the @code{history} slot. This is the +transient-wide history; many individual infixes also have a history +of their own. + +The default (and currently only) method extracts the value from the +global variable @code{transient-history}. +@end defun + +A transient prefix command's object is stored in the @code{transient--prefix} +property of the command symbol. While a transient is active, a clone +of that object is stored in the variable @code{transient--prefix}. A clone +is used because some changes that are made to the active transient's +object should not affect later invocations. + +@node Suffix Classes +@section Suffix Classes + +@itemize +@item +All suffix and infix classes derive from @code{transient-suffix}, which in +turn derives from @code{transient-child}, from which @code{transient-group} also +derives (see @ref{Group Classes}). + + +@item +All infix classes derive from the abstract @code{transient-infix} class, +which in turn derives from the @code{transient-suffix} class. + +Infixes are a special type of suffixes. The primary difference is +that infixes always use the @code{transient--do-stay} pre-command, while +non-infix suffixes use a variety of pre-commands (see @ref{Transient State}). Doing that is most easily achieved by using this class, +though theoretically it would be possible to define an infix class +that does not do so. If you do that then you get to implement many +methods. + +Also, infixes and non-infix suffixes are usually defined using +different macros (see @ref{Defining Suffix and Infix Commands}). + + +@item +Classes used for infix commands that represent arguments should +be derived from the abstract @code{transient-argument} class. + + +@item +The @code{transient-switch} class (or a derived class) is used for infix +arguments that represent command-line switches (arguments that do +not take a value). + + +@item +The @code{transient-option} class (or a derived class) is used for infix +arguments that represent command-line options (arguments that do +take a value). + + +@item +The @code{transient-switches} class can be used for a set of mutually +exclusive command-line switches. + + +@item +The @code{transient-files} class can be used for a "--" argument that +indicates that all remaining arguments are files. + + +@item +Classes used for infix commands that represent variables should +derived from the abstract @code{transient-variables} class. +@end itemize + +Magit defines additional classes, which can serve as examples for the +fancy things you can do without modifying Transient. Some of these +classes will likely get generalized and added to Transient. For now +they are very much subject to change and not documented. + +@node Suffix Methods +@section Suffix Methods + +To get information about the methods implementing these generic +functions use @code{describe-function}. + +@menu +* Suffix Value Methods:: +* Suffix Format Methods:: +@end menu + +@node Suffix Value Methods +@subsection Suffix Value Methods + +@defun transient-init-value obj + +This generic function sets the initial value of the object OBJ@. + +This function is called for all suffix commands, but unless a +concrete method is implemented this falls through to the default +implementation, which is a noop. In other words this usually +only does something for infix commands, but note that this is +not implemented for the abstract class @code{transient-infix}, so if +your class derives from that directly, then you must implement +a method. +@end defun + +@defun transient-infix-read obj + +This generic function determines the new value of the infix object +OBJ@. + +This function merely determines the value; @code{transient-infix-set} is +used to actually store the new value in the object. + +For most infix classes this is done by reading a value from the +user using the reader specified by the @code{reader} slot (using the +@code{transient-infix-value} method described below). + +For some infix classes the value is changed without reading +anything in the minibuffer, i.e. the mere act of invoking the +infix command determines what the new value should be, based +on the previous value. +@end defun + +@defun transient-prompt obj + +This generic function returns the prompt to be used to read infix +object OBJ's value. +@end defun + +@defun transient-infix-set obj value + +This generic function sets the value of infix object OBJ to VALUE@. +@end defun + +@defun transient-infix-value obj + +This generic function returns the value of the suffix object OBJ@. + +This function is called by @code{transient-args} (which see), meaning this +function is how the value of a transient is determined so that the +invoked suffix command can use it. + +Currently most values are strings, but that is not set in stone. +@code{nil} is not a value, it means "no value". + +Usually only infixes have a value, but see the method for +@code{transient-suffix}. +@end defun + +@defun transient-init-scope obj + +This generic function sets the scope of the suffix object OBJ@. + +The scope is actually a property of the transient prefix, not of +individual suffixes. However it is possible to invoke a suffix +command directly instead of from a transient. In that case, if +the suffix expects a scope, then it has to determine that itself +and store it in its @code{scope} slot. + +This function is called for all suffix commands, but unless a +concrete method is implemented this falls through to the default +implementation, which is a noop. +@end defun + +@node Suffix Format Methods +@subsection Suffix Format Methods + +@defun transient-format obj + +This generic function formats and returns OBJ for display. + +When this function is called, then the current buffer is some +temporary buffer. If you need the buffer from which the prefix +command was invoked to be current, then do so by temporarily +making @code{transient--source-buffer} current. +@end defun + +@defun transient-format-key obj + +This generic function formats OBJ's @code{key} for display and returns the +result. +@end defun + +@defun transient-format-description obj + +This generic function formats OBJ's @code{description} for display and +returns the result. +@end defun + +@defun transient-format-value obj + +This generic function formats OBJ's value for display and returns +the result. +@end defun + +@defun transient-show-help obj + +Show help for the prefix, infix or suffix command represented by +OBJ@. + +For prefixes, show the info manual, if that is specified using the +@code{info-manual} slot. Otherwise show the manpage if that is specified +using the @code{man-page} slot. Otherwise show the command's doc string. + +For suffixes, show the command's doc string. + +For infixes, show the manpage if that is specified. Otherwise show +the command's doc string. +@end defun + +@node Prefix Slots +@section Prefix Slots + +@itemize +@item +@code{man-page} or @code{info-manual} can be used to specify the documentation for +the prefix and its suffixes. The command @code{transient-help} uses the +method @code{transient-show-help} (which see) to lookup and use these +values. + + +@item +@code{history-key} If multiple prefix commands should share a single value, +then this slot has to be set to the same value for all of them. You +probably don't want that. + + +@item +@code{transient-suffix} and @code{transient-non-suffix} play a part when +determining whether the currently active transient prefix command +remains active/transient when a suffix or abitrary non-suffix +command is invoked. See @ref{Transient State}. + + +@item +@code{incompatible} A list of lists. Each sub-list specifies a set of +mutually exclusive arguments. Enabling one of these arguments +causes the others to be disabled. An argument may appear in +multiple sub-lists. + + +@item +@code{scope} For some transients it might be necessary to have a sort of +secondary value, called a "scope". See @code{transient-define-prefix}. +@end itemize + +@anchor{Internal Prefix Slots} +@subheading Internal Prefix Slots + +These slots are mostly intended for internal use. They should not be +set in calls to @code{transient-define-prefix}. + +@itemize +@item +@code{prototype} When a transient prefix command is invoked, then a clone +of that object is stored in the global variable @code{transient--prefix} +and the prototype is stored in the clone's @code{prototype} slot. + + +@item +@code{command} The command, a symbol. Each transient prefix command +consists of a command, which is stored in a symbol's function slot +and an object, which is stored in the @code{transient--prefix} property +of the same symbol. + + +@item +@code{level} The level of the prefix commands. The suffix commands whose +layer is equal or lower are displayed. See @ref{Enabling and Disabling Suffixes}. + + +@item +@code{value} The likely outdated value of the prefix. Instead of accessing +this slot directly you should use the function @code{transient-get-value}, +which is guaranteed to return the up-to-date value. + + +@item +@code{history} and @code{history-pos} are used to keep track of historic values. +Unless you implement your own @code{transient-infix-read} method you should +not have to deal with these slots. +@end itemize + +@node Suffix Slots +@section Suffix Slots + +Here we document most of the slots that are only available for suffix +objects. Some slots are shared by suffix and group objects, they are +documented in @ref{Predicate Slots}. + +Also see @ref{Suffix Classes}. + +@anchor{Slots of @code{transient-suffix}} +@subheading Slots of @code{transient-suffix} + +@itemize +@item +@code{key} The key, a key vector or a key description string. + + +@item +@code{command} The command, a symbol. + + +@item +@code{transient} Whether to stay transient. See @ref{Transient State}. + + +@item +@code{format} The format used to display the suffix in the popup buffer. +It must contain the following %-placeholders: + +@itemize +@item +@code{%k} For the key. + +@item +@code{%d} For the description. + +@item +@code{%v} For the infix value. Non-infix suffixes don't have a value. +@end itemize + + +@item +@code{description} The description, either a string or a function that is +called with no argument and returns a string. +@end itemize + +@anchor{Slots of @code{transient-infix}} +@subheading Slots of @code{transient-infix} + +Some of these slots are only meaningful for some of the subclasses. +They are defined here anyway to allow sharing certain methods. + +@itemize +@item +@code{argument} The long argument, e.g. @code{--verbose}. + + +@item +@code{shortarg} The short argument, e.g. @code{-v}. + + +@item +@code{value} The value. Should not be accessed directly. + + +@item +@code{init-value} Function that is responsable for setting the object's +value. If bound, then this is called with the object as the only +argument. Usually this is not bound, in which case the object's +primary @code{transient-init-value} method is called instead. + + +@item +@code{unsavable} Whether the value of the suffix is not saved as part of +the prefixes. + + +@item +@code{multi-value} For options, whether the option can have multiple +values. If non-nil, then default to use @code{completing-read-multiple}. + + +@item +@code{always-read} For options, whether to read a value on every invocation. +If this is nil, then options that have a value are simply unset and +have to be invoked a second time to set a new value. + + +@item +@code{allow-empty} For options, whether the empty string is a valid value. + + +@item +@code{history-key} The key used to store the history. This defaults to the +command name. This is useful when multiple infixes should share the +same history because their values are of the same kind. + + +@item +@code{reader} The function used to read the value of an infix. Not used +for switches. The function takes three arguments, PROMPT, +INITIAL-INPUT and HISTORY, and must return a string. + + +@item +@code{prompt} The prompt used when reading the value, either a string or a +function that takes the object as the only argument and which +returns a prompt string. + + +@item +@code{choices} A list of valid values. How exactly that is used depends on +the class of the object. +@end itemize + +@anchor{Slots of @code{transient-variable}} +@subheading Slots of @code{transient-variable} + +@itemize +@item +@code{variable} The variable. +@end itemize + +@anchor{Slots of @code{transient-switches}} +@subheading Slots of @code{transient-switches} + +@itemize +@item +@code{argument-format} The display format. Must contain @code{%s}, one of the +@code{choices} is substituted for that. E.g. @code{--%s-order}. + + +@item +@code{argument-regexp} The regexp used to match any one of the switches. +E.g. @code{\\(--\\(topo\\|author-date\\|date\\)-order\\)}. +@end itemize + +@node Predicate Slots +@section Predicate Slots + +Suffix and group objects share some predicate slots that control +whether a group or suffix should be available depending on some state. +Only one of these slots can be used at the same time. It is undefined +what happens if you use more than one. + +@itemize +@item +@code{if} Enable if predicate returns non-nil. + +@item +@code{if-not} Enable if predicate returns nil. + +@item +@code{if-non-nil} Enable if variable's value is non-nil. + +@item +@code{if-nil} Enable if variable's value is nil. + +@item +@code{if-mode} Enable if major-mode matches value. + +@item +@code{if-not-mode} Enable if major-mode does not match value. + +@item +@code{if-derived} Enable if major-mode derives from value. + +@item +@code{if-not-derived} Enable if major-mode does not derive from value. +@end itemize + +One more slot is shared between group and suffix classes, @code{level}. Like +the slots documented above, it is a predicate, but it is used for a +different purpose. The value has to be an integer between 1 +and 7. @code{level} controls whether a suffix or a group should be +available depending on user preference. +See @ref{Enabling and Disabling Suffixes}. + +@node Related Abstractions and Packages +@chapter Related Abstractions and Packages + +@menu +* Comparison With Prefix Keys and Prefix Arguments:: +* Comparison With Other Packages:: +@end menu + +@node Comparison With Prefix Keys and Prefix Arguments +@section Comparison With Prefix Keys and Prefix Arguments + +While transient commands were inspired by regular prefix keys and +prefix arguments, they are also quite different and much more complex. + +The following diagrams illustrate some of the differences. + +@itemize +@item +@code{(c)} represents a return to the command loop. + +@item +@code{(+)} represents the user's choice to press one key or another. + +@item +@code{@{WORD@}} are possible behaviors. + +@item +@code{@{NUMBER@}} is a footnote. +@end itemize + +@anchor{Regular Prefix Commands} +@subheading Regular Prefix Commands + +See @ref{Prefix Keys,,,elisp,}. + +@example + ,--> command1 --> (c) + | +(c)-(+)-> prefix command or key --+--> command2 --> (c) + | + `--> command3 --> (c) +@end example + +@anchor{Regular Prefix Arguments} +@subheading Regular Prefix Arguments + +See @ref{Prefix Command Arguments,,,elisp,}. + +@example + ,----------------------------------, + | | + v | +(c)-(+)---> prefix argument command --(c)-(+)-> any command --> (c) + | ^ | + | | | + `-- sets or changes --, ,-- maybe used --' | + | | | + v | | + prefix argument state | + ^ | + | | + `-------- discards --------' +@end example + +@anchor{Transients} +@subheading Transients + +(∩`-´)⊃━☆゚.*・。゚ + +This diagram ignores the infix value and external state: + +@example +(c) + | ,- @{stay@} ------<-,-<------------<-,-<---, +(+) | | | | + | | | | | + | | ,--> infix1 --| | | + | | | | | | + | | |--> infix2 --| | | + v v | | | | + prefix -(c)-(+)-> infix3 --' ^ | + | | | + |---------------> suffix1 -->--| | + | | | + |---------------> suffix2 ----@{1@}------> @{exit@} --> (c) + | | + |---------------> suffix3 -------------> @{exit@} --> (c) + | | + `--> any command --@{2@}-> @{warn@} -->--| + | | + |--> @{noop@} -->--| + | | + |--> @{call@} -->--' + | + `------------------> @{exit@} --> (c) +@end example + +This diagram takes the infix value into account to an extend, while +still ignoring external state: + +@example +(c) + | ,- @{stay@} ------<-,-<------------<-,-<---, +(+) | | | | + | | | | | + | | ,--> infix1 --| | | + | | | | | | | + | | ,--> infix2 --| | | + v v | | | | | + prefix -(c)-(+)-> infix3 --' | | + | | ^ | + | | | | + |---------------> suffix1 -->--| | + | | ^ | | + | | | | | + |---------------> suffix2 ----@{1@}------> @{exit@} --> (c) + | | ^ | | + | | | | v + | | | | | + |---------------> suffix3 -------------> @{exit@} --> (c) + | | ^ | | + | sets | | v + | | maybe | | + | | used | | + | | | | | + | | infix --' | | + | `---> value | | + | ^ | | + | | | | + | hides | | + | | | | + | `--------------------------<---| + | | | + `--> any command --@{2@}-> @{warn@} -->--| | + | | | + |--> @{noop@} -->--| | + | | | + |--> @{call@} -->--' ^ + | | + `------------------> @{exit@} --> (c) +@end example + +This diagram provides more information about the infix value +and also takes external state into account. + +@example + ,----sets--- "anything" + | + v + ,---------> external + | state + | | | + | initialized | ☉‿⚆ + sets from | + | | maybe + | ,----------' used + | | | +(c) | | v + | ,- @{stay@} --|---<-,-<------|-----<-,-<---, +(+) | | | | | | | + | | | v | | | | + | | ,--> infix1 --| | | | + | | | | | | | | | + | | | | v | | | | + | | ,--> infix2 --| | | | + | | | | ^ | | | | + v v | | | | | | | + prefix -(c)-(+)-> infix3 --' | | | + | | ^ | ^ | + | | | v | | + |---------------> suffix1 -->--| | + | | | ^ | | | + | | | | v | | + |---------------> suffix2 ----@{1@}------> @{exit@} --> (c) + | | | ^ | | | + | | | | | | v + | | | | v | | + |---------------> suffix3 -------------> @{exit@} --> (c) + | | | ^ | | + | sets | | | v + | | initialized maybe | | + | | from used | | + | | | | | | + | | `-- infix ---' | | + | `---> value -----------------------------> persistent + | ^ ^ | | across + | | | | | invocations -, + | hides | | | | + | | `----------------------------------------------' + | | | | + | `--------------------------<---| + | | | + `--> any command --@{2@}-> @{warn@} -->--| | + | | | + |--> @{noop@} -->--| | + | | | + |--> @{call@} -->--' ^ + | | + `------------------> @{exit@} --> (c) +@end example + +@itemize +@item +@code{@{1@}} Transients can be configured to be exited when a suffix command +is invoked. The default is to do so for all suffixes except for +those that are common to all transients and which are used to +perform tasks such as providing help and saving the value of the +infix arguments for future invocations. The behavior can also be +specified for individual suffix commands and may even depend on +state. + + +@item +@code{@{2@}} Transients can be configured to allow the user to invoke +non-suffix commands. The default is to not allow that and instead +warn the user. +@end itemize + +Despite already being rather complex, even the last diagram leaves out +many details. Most importantly it implies that the decision whether +to remain transient is made later than it actually is made (for the +most part a function on @code{pre-command-hook} is responsible). But such +implementation details are of little relevance to users and are +covered elsewhere. + +@node Comparison With Other Packages +@section Comparison With Other Packages + +@anchor{Magit-Popup} +@subheading Magit-Popup + +Transient is the successor to Magit-Popup (see @ref{Top,,,magit-popup,}). + +One major difference between these two implementations of the same +ideas is that while Transient uses transient keymaps and embraces the +command-loop, Magit-Popup implemented an inferior mechanism that does +not use transient keymaps and that instead of using the command-loop +implements a naive alternative based on @code{read-char}. + +Magit-Popup does not use classes and generic functions and defining a +new command type is near impossible as it involves adding hard-coded +special-cases to many functions. Because of that only a single new +type was added, which was not already part of Magit-Popup's initial +release. + +A lot of things are hard-coded in Magit-Popup. One random example is +that the key bindings for switches must begin with "-" and those for +options must begin with "=". + +@anchor{Hydra} +@subheading Hydra + +Hydra (see @uref{https://github.com/abo-abo/hydra}) is another package that +provides features similar to those of Transient. + +Both packages use transient keymaps to make a set of commands +temporarily available and show the available commands in a popup +buffer. + +A Hydra "body" is equivalent to a Transient "prefix" and a Hydra +"head" is equivalent to a Transient "suffix". Hydra has no equivalent +of a Transient "infix". + +Both hydras and transients can be used as simple command dispatchers. +Used like this they are similar to regular prefix commands and prefix +keys, except that the available commands are shown in the popup buffer. + +(Another package that does this is @code{which-key}. It does so automatically +for any incomplete key sequence. The advantage of that approach is +that no additional work is necessary; the disadvantage is that the +available commands are not organized semantically.) + +Both Hydra and Transient provide features that go beyond simple +command dispatchers: + +@itemize +@item +Invoking a command from a hydra does not necessarily exit the hydra. +That makes it possible to invoke the same command again, but using a +shorter key sequence (i.e. the key that was used to enter the hydra +does not have to be pressed again). + +Transient supports that too, but for now this feature is not a focus +and the interface is a bit more complicated. A very basic example +using the current interface: + +@lisp +(transient-define-prefix outline-navigate () + :transient-suffix 'transient--do-stay + :transient-non-suffix 'transient--do-warn + [("p" "previous visible heading" outline-previous-visible-heading) + ("n" "next visible heading" outline-next-visible-heading)]) +@end lisp + + +@item +Transient supports infix arguments; values that are set by infix +commands and then consumed by the invoked suffix command(s). + +To my knowledge, Hydra does not support that. +@end itemize + +Both packages make it possible to specify how exactly the available +commands are outlined: + +@itemize +@item +With Hydra this is often done using an explicit format string, which +gives authors a lot of flexibility and makes it possible to do fancy +things. + +The downside of this is that it becomes harder for a user to add +additional commands to an existing hydra and to change key bindings. + + +@item +Transient allows the author of a transient to organize the commands +into groups and the use of generic functions allows authors of +transients to control exactly how a certain command type is +displayed. + +However while Transient supports giving sections a heading it does +not currently support giving the displayed information more +structure by, for example, using box-drawing characters. + +That could be implemented by defining a new group class, which lets +the author specify a format string. It should be possible to +implement that without modifying any existing code, but it does not +currently exist. +@end itemize + +@node FAQ +@appendix FAQ + + + +@anchor{Can I control how the popup buffer is displayed?} +@appendixsec Can I control how the popup buffer is displayed? + +Yes, see @code{transient-display-buffer-action} in @ref{Other Options}. + +@anchor{Why did some of the key bindings change?} +@appendixsec Why did some of the key bindings change? + +You may have noticed that the bindings for some of the common commands +do @strong{not} have the prefix @code{C-x} and that furthermore some of these commands +are grayed out while others are not. That unfortunately is a bit +confusing if the section of common commands is not shown permanently, +making the following explanation necessary. + +The purpose of usually hiding that section but showing it after the +user pressed the respective prefix key is to conserve space and not +overwhelm users with too much noise, while allowing the user to +quickly list common bindings on demand. + +That however should not keep us from using the best possible key +bindings. The bindings that do use a prefix do so to avoid wasting +too many non-prefix bindings, keeping them available for use in +individual transients. The bindings that do not use a prefix and that +are @strong{not} grayed out are very important bindings that are @strong{always} +available, even when invoking the "common command key prefix" or @strong{any +other} transient-specific prefix. The non-prefix keys that @strong{are} grayed +out however, are not available when any incomplete prefix key sequence +is active. They do not use the "common command key prefix" because it +is likely that users want to invoke them several times in a row and +e.g. @code{M-p M-p M-p} is much more convenient than @code{C-x M-p C-x M-p C-x M-p}. + +You may also have noticed that the "Set" command is bound to @code{C-x s}, +while Magit-Popup used to bind @code{C-c C-c} instead. I have seen several +users praise the latter binding (sic), so I did not change it +willy-nilly. The reason that I changed it is that using different +prefix keys for different common commands, would have made the +temporary display of the common commands even more confusing, +i.e. after pressing @code{C-c} all the @code{C-x ...} bindings would be grayed out. + +Using a single prefix for common commands key means that all other +potential prefix keys can be used for transient-specific commands +@strong{without} the section of common commands also popping up. @code{C-c} in +particular is a prefix that I want to (and already do) use for Magit, and +also using that for a common command would prevent me from doing so. + +(Also see the next question.) + +@anchor{Why does @code{q} not quit popups anymore?} +@appendixsec Why does @code{q} not quit popups anymore? + +I agree that @code{q} is a good binding for commands that quit something. +This includes quitting whatever transient is currently active, but it +also includes quitting whatever it is that some specific transient is +controlling. The transient @code{magit-blame} for example binds @code{q} to the +command that turns @code{magit-blame-mode} off. + +So I had to decide if @code{q} should quit the active transient (like +Magit-Popup used to) or whether @code{C-g} should do that instead, so that @code{q} +could be bound in individual transient to whatever commands make sense +for them. Because all other letters are already reserved for use by +individual transients, I have decided to no longer make an exception +for @code{q}. + +If you want to get @code{q}'s old binding back then you can do so. Doing +that is a bit more complicated than changing a single key binding, so +I have implemented a function, @code{transient-bind-q-to-quit} that makes the +necessary changes. See its doc string for more information. + +@node Keystroke Index +@appendix Keystroke Index + +@printindex ky + +@node Command Index +@appendix Command Index + +@printindex cp + +@node Function Index +@appendix Function Index + +@printindex fn + +@node Variable Index +@appendix Variable Index + +@printindex vr + +@node GNU General Public License +@appendix GNU General Public License + +@include gpl.texi + +@bye commit df3492934639628f023049e032421b7beb80de57 Author: Kyle Meyer Date: Sun Feb 13 12:43:54 2022 -0500 Update to Org 9.5.2-15-gc5ceb6 diff --git a/lisp/org/ol-bibtex.el b/lisp/org/ol-bibtex.el index 218f8f17ed..81b99167b8 100644 --- a/lisp/org/ol-bibtex.el +++ b/lisp/org/ol-bibtex.el @@ -655,7 +655,8 @@ With a prefix arg, query for optional fields." (defun org-bibtex-read () "Read a bibtex entry and save to `org-bibtex-entries'. -This uses `bibtex-parse-entry'." +This uses `bibtex-parse-entry'. +Return the new value of `org-bibtex-entries'." (interactive) (let ((keyword (lambda (str) (intern (concat ":" (downcase str))))) (clean-space (lambda (str) (replace-regexp-in-string @@ -678,7 +679,8 @@ This uses `bibtex-parse-entry'." (funcall clean-space (funcall strip-delim (cdr pair))))) (save-excursion (bibtex-beginning-of-entry) (bibtex-parse-entry))) org-bibtex-entries) - (unless (car org-bibtex-entries) (pop org-bibtex-entries)))) + (unless (car org-bibtex-entries) (pop org-bibtex-entries)) + org-bibtex-entries)) (defun org-bibtex-read-buffer (buffer) "Read all bibtex entries in BUFFER and save to `org-bibtex-entries'. diff --git a/lisp/org/org-list.el b/lisp/org/org-list.el index 0dd8139a97..da309f8c6d 100644 --- a/lisp/org/org-list.el +++ b/lisp/org/org-list.el @@ -1442,7 +1442,7 @@ This function returns, destructively, the new list structure." (save-excursion (goto-char (org-list-get-last-item item struct prevs)) (point-at-eol))) - ((string-match-p "\\`[0-9]+\\'" dest) + ((and (stringp dest) (string-match-p "\\`[0-9]+\\'" dest)) (let* ((all (org-list-get-all-items item struct prevs)) (len (length all)) (index (mod (string-to-number dest) len))) diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 572203711c..336347b29c 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.2-13-gdd6486")) + (let ((org-git-version "release_9.5.2-15-gc5ceb6")) org-git-version)) (provide 'org-version) commit fe27479cad0d6d1f33605a5185bda0957a7f179b Author: Eli Zaretskii Date: Mon Jan 10 19:10:52 2022 +0200 Fix 'exchange-point-and-mark' in 'transient-mark-mode' * lisp/simple.el (exchange-point-and-mark): Don't deactivate mark when 'transient-mark-mode' is ON. (Bug#53150) (cherry picked from commit 415ed4b42515ff2e6dd9b94e964b479e50c6392e) diff --git a/lisp/simple.el b/lisp/simple.el index 2822a4a3c2..1f606556b6 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -6652,11 +6652,10 @@ mode temporarily." (user-error "No mark set in this buffer")) (set-mark (point)) (goto-char omark) - (cond ((and (not arg) (not temp-highlight)) - (setq-local transient-mark-mode (cons 'only transient-mark-mode))) - ((xor arg (not (region-active-p))) - (deactivate-mark)) - (t (activate-mark))) + (or temp-highlight + (cond ((xor arg (not (region-active-p))) + (deactivate-mark)) + (t (activate-mark)))) nil)) (defcustom shift-select-mode t commit 2289a7a271a78e5e4977745e4be6ae520be611ce Author: Eli Zaretskii Date: Fri Jan 7 20:30:17 2022 +0200 Fix "C-SPC C-SPC" after "C-x C-x" * lisp/simple.el (exchange-point-and-mark): Fix what the command does when 'transient-mark-mode' is OFF. (Bug#52896) (cherry picked from commit 19c6cad1821eb896b2ddd0f6eab030f0880ea254) diff --git a/lisp/simple.el b/lisp/simple.el index 9c17f0ea6d..2822a4a3c2 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -6652,7 +6652,7 @@ mode temporarily." (user-error "No mark set in this buffer")) (set-mark (point)) (goto-char omark) - (cond (temp-highlight + (cond ((and (not arg) (not temp-highlight)) (setq-local transient-mark-mode (cons 'only transient-mark-mode))) ((xor arg (not (region-active-p))) (deactivate-mark)) commit 29085a668ee0e245f2890f5dcb5eaa3ea7ea62d0 Author: Eli Zaretskii Date: Sun Feb 13 13:43:53 2022 +0200 Fix a typo in fontset.el * lisp/international/fontset.el (xlfd-regexp-spacing-subnum): Fix a typo. Reported by Greg A. Woods . diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el index 240def6c03..31ffaf157b 100644 --- a/lisp/international/fontset.el +++ b/lisp/international/fontset.el @@ -1132,7 +1132,7 @@ Internal use only. Should be called at startup time." (defconst xlfd-regexp-pointsize-subnum 6) ; POINT_SIZE (defconst xlfd-regexp-resx-subnum 7) ; RESOLUTION_X (defconst xlfd-regexp-resy-subnum 8) ; RESOLUTION_Y -(defconst xlfd-regexp-spacing-subnum 8) ; SPACING +(defconst xlfd-regexp-spacing-subnum 9) ; SPACING (defconst xlfd-regexp-avgwidth-subnum 10) ; AVERAGE_WIDTH (defconst xlfd-regexp-registry-subnum 11) ; REGISTRY and ENCODING commit cdcfeef13cf830e4a449e00845e7284438e5a30f Author: Eli Zaretskii Date: Sat Feb 12 14:28:45 2022 +0200 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) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index d1b61d3fb5..3fd54cb147 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -6467,7 +6467,9 @@ buffer's text. The argument @var{slice} specifies a slice of the image to insert. If @var{slice} is @code{nil} or omitted the whole image is inserted. -Otherwise, @var{slice} is a list @code{(@var{x} @var{y} @var{width} +(However, note that images are chopped on display at the window's +right edge, because wrapping images is not supported.) Otherwise, +@var{slice} is a list @code{(@var{x} @var{y} @var{width} @var{height})} which specifies the @var{x} and @var{y} positions and @var{width} and @var{height} of the image area to insert. Integer values are in units of pixels. A floating-point number in the range commit 6015d5e8eee9baa328f81dbcdf14fda2a21f2286 Author: Andrea Corallo Date: Fri Feb 11 15:00:57 2022 +0100 * lisp/mail/emacsbug.el (report-emacs-bug): Report libgccjit status. diff --git a/lisp/mail/emacsbug.el b/lisp/mail/emacsbug.el index f5559e39f6..1bda609d10 100644 --- a/lisp/mail/emacsbug.el +++ b/lisp/mail/emacsbug.el @@ -304,6 +304,9 @@ usually do not have translators for other languages.\n\n"))) (emacs-bug--system-description) (insert "Configured features:\n" system-configuration-features "\n\n") (fill-region (line-beginning-position -1) (point)) + (when (and (featurep 'native-compile) + (null (native-comp-available-p))) + (insert "(NATIVE_COMP present but libgccjit not available)\n\n")) (insert "Important settings:\n") (mapc (lambda (var) commit efaa0ebca9ec445329643fea2f9fe883d7ccdc3a Author: Andrea Corallo Date: Fri Feb 11 15:19:56 2022 +0100 * lisp/startup.el (normal-top-level): Small code move, improve 202d3be873. diff --git a/lisp/startup.el b/lisp/startup.el index d369f3ef84..9ebd4c1a70 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -540,15 +540,15 @@ It is the default value of the variable `top-level'." (setq user-emacs-directory (startup--xdg-or-homedot startup--xdg-config-home-emacs nil)) - (unless (native-comp-available-p) - ;; Disable deferred async compilation and trampoline synthesis - ;; in this session. This is necessary if libgccjit is not - ;; available on MS-Windows, but Emacs was built with - ;; native-compilation support. - (setq native-comp-deferred-compilation nil - comp-enable-subr-trampolines nil)) - (when (featurep 'native-compile) + (unless (native-comp-available-p) + ;; Disable deferred async compilation and trampoline synthesis + ;; in this session. This is necessary if libgccjit is not + ;; available on MS-Windows, but Emacs was built with + ;; native-compilation support. + (setq native-comp-deferred-compilation nil + comp-enable-subr-trampolines nil)) + ;; Form `native-comp-eln-load-path'. (let ((path-env (getenv "EMACSNATIVELOADPATH"))) (when path-env