branch: externals/lin commit d51e895b46116eeb4120ec909f61d2d092efad47 Author: Protesilaos Stavrou <i...@protesilaos.com> Commit: Protesilaos Stavrou <i...@protesilaos.com>
Upgrade to version 0.2.0 --- CHANGELOG.org | 67 ++++++++++++ README.org | 231 ++++++++++++++-------------------------- lin.el | 334 ++++++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 404 insertions(+), 228 deletions(-) diff --git a/CHANGELOG.org b/CHANGELOG.org new file mode 100644 index 0000000000..c43b888640 --- /dev/null +++ b/CHANGELOG.org @@ -0,0 +1,67 @@ +#+TITLE: Change log of lin.el +#+AUTHOR: Protesilaos Stavrou +#+EMAIL: i...@protesilaos.com +#+OPTIONS: ':nil toc:nil num:nil author:nil email:nil + +This document contains the release notes for each tagged commit on the +project's main git repository: <https://gitlab.com/protesilaos/lin>. + +The newest release is at the top. For further details, please consult +the manual: <https://protesilaos.com/emacs/lin>. + +* Version 0.2.0 on 2022-03-16 + +Rewrote the entirety of =lin.el= to make the configuration easier and +keep the code streamlined. The gist is that now Lin automatically +enables ~hl-line-mode~ in every mode implied by ~lin-mode-hooks~. Here +is how Lin should be set up henceforth: + +#+begin_src emacs-lisp +(require 'lin) + +(setq lin-face 'lin-blue) ; check doc string for alternative styles + +(lin-setup) ; Either run this or change `lin-mode-hooks' + +(customize-set-variable + 'lin-mode-hooks ; do not use `setq' with this; `customize-set-variable' runs `lin-setup' automatically + '(dired-mode-hook + elfeed-search-mode-hook + git-rebase-mode-hook + ibuffer-mode-hook + ilist-mode-hook + ledger-report-mode-hook + log-view-mode-hook + magit-log-mode-hook + mu4e-headers-mode + notmuch-search-mode-hook + notmuch-tree-mode-hook + occur-mode-hook + org-agenda-mode-hook + tabulated-list-mode-hook)) +#+end_src + +The manual has been updated to reflect those changes: +<https://protesilaos.com/emacs/lin>. + +Thanks to: + ++ Christian Tietze for showing how the Lin face can use colors from the + macOS palette. The original contribution was in merge request 2: + <https://gitlab.com/protesilaos/lin/-/merge_requests/2>. Now we + provide the ~lin-mac~ and ~lin-mac-override-fg~ faces. These can be + assigned as a value to the user option ~lin-face~. + ++ Damien Cassou for suggesting that Lin sets itself up for a list of + mode hooks. The original contribution was in merge request 3: + <https://gitlab.com/protesilaos/lin/-/merge_requests/3>. It has now + been rewritten as the ~lin-mode-hooks~ user option, though the idea is + the same. + ++ Federico Stilman for adding ~mu4e-headers-mode~ to the list that + Damien had provided and which now lives as ~lin-mode-hooks~. + Federico's contribution was sent as a patch via email. + +* Version 0.1.0 on 2022-03-14 + +Initial release of the package. Please read the manual. diff --git a/README.org b/README.org index bc4fb08f52..d2de39703b 100644 --- a/README.org +++ b/README.org @@ -5,9 +5,9 @@ #+options: ':t toc:nil author:t email:t num:t #+startup: content -#+macro: stable-version 0.1.0 -#+macro: release-date 2021-11-01 -#+macro: development-version 0.2.0-dev +#+macro: stable-version 0.2.0 +#+macro: release-date 2022-03-18 +#+macro: development-version 0.3.0-dev #+macro: file @@texinfo:@file{@@$1@@texinfo:}@@ #+macro: space @@texinfo:@: @@ #+macro: kbd @@texinfo:@kbd{@@$1@@texinfo:}@@ @@ -17,7 +17,7 @@ #+texinfo_filename: lin.info #+texinfo_dir_category: Emacs misc features #+texinfo_dir_title: LIN Is Noticeable: (lin) -#+texinfo_dir_desc: Buffer-local remapping of hl-line face +#+texinfo_dir_desc: Make 'hl-line-mode' more suitable for selection UIs #+texinfo_header: @set MAINTAINERSITE @uref{https://protesilaos.com,maintainer webpage} #+texinfo_header: @set MAINTAINER Protesilaos Stavrou #+texinfo_header: @set MAINTAINEREMAIL @email{i...@protesilaos.com} @@ -43,7 +43,7 @@ Current development target is {{{development-version}}}. :CUSTOM_ID: h:33b423a6-1b89-40a3-bbbc-1524138be3a4 :END: -Copyright (C) 2021 Free Software Foundation, Inc. +Copyright (C) 2021-2022 Free Software Foundation, Inc. #+begin_quote Permission is granted to copy, distribute and/or modify this document @@ -63,29 +63,63 @@ modify this GNU manual.” :END: #+cindex: Overview -LIN locally remaps the ~hl-line~ face to a style that is optimal for major -modes where line selection is the primary mode of interaction. - -The idea is that ~hl-line~ cannot work equally well for contexts with -competing priorities: (i) line selection, or (ii) simple line highlight. -In the former case, the current line needs to be made prominent because -it carries a specific meaning of some significance in the given context. -Whereas in the latter case, the primary mode of interaction does not -revolve around the line highlight itself: it may be because the focus is -on editing text or reading through the buffer's contents, so the current -line highlight is more of a gentle reminder of the point's location on -the vertical axis. - -~lin-mode~ only shows its effect when ~hl-line-mode~ is active or, more -specifically, when the ~hl-line~ face is used in the buffer. ~lin-mode~ -DOES NOT activate ~hl-line-mode~ and does not do anything other than the -aforementioned face remapping. +Lin is a stylistic enhancement for Emacs' built-in ~hl-line-mode~. It +remaps the ~hl-line~ face (or equivalent) buffer-locally to a style that +is optimal for major modes where line selection is the primary mode of +interaction. + +The idea is that ~hl-line-mode~ cannot work equally well for contexts +with competing priorities: (i) line selection, or (ii) simple line +highlight. In the former case, the current line needs to be made +prominent because it carries a specific meaning of some significance in +the given context: the user has to select a line. Whereas in the latter +case, the primary mode of interaction does not revolve around the line +highlight itself: it may be because the focus is on editing text or +reading through the buffer's contents, so the current line highlight is +more of a reminder of the point's location on the vertical axis. + +#+findex: lin-mode +#+vindex: lin-mode-hooks +#+findex: lin-setup +~lin-mode~ enables ~hl-line-mode~ by adding it to every hook specified +in the user option ~lin-mode-hooks~. Users are advised to configure +that variable with ~customize-set-variable~, or the Custom UI, or +equivalent as it has a function which automatically sets up Lin. Those +who prefer to set values with ~setq~ must handle the process manually, +by using the ~lin-setup~ function. + +#+vindex: lin-face +#+vindex: lin-blue +#+vindex: lin-red +#+vindex: lin-green +#+vindex: lin-yellow +#+vindex: lin-blue +#+vindex: lin-magenta +#+vindex: lin-cyan +#+vindex: lin-mac +#+vindex: lin-red-override-fg +#+vindex: lin-green-override-fg +#+vindex: lin-yellow-override-fg +#+vindex: lin-blue-override-fg +#+vindex: lin-magenta-override-fg +#+vindex: lin-cyan-override-fg +#+vindex: lin-mac-override-fg +Users can selected their preferred style by customizing the user option +~lin-face~. Options include the faces ~lin-red~, ~lin-green~, +~lin-yellow~, ~lin-blue~ (default), ~lin-magenta~, ~lin-cyan~, +~lin-mac~, ~lin-red-override-fg~, ~lin-green-override-fg~, +~lin-yellow-override-fg~, ~lin-blue-override-fg~, +~lin-magenta-override-fg~, ~lin-cyan-override-fg~, +~lin-mac-override-fg~, or any other face that preferably has a +background attribute. The Lin faces with the =-override-fg= suffix set +a foreground value which replaces that of the underlying text. Whereas +the others only specify a background attribute. * Installation :PROPERTIES: :CUSTOM_ID: h:7b68abd3-a854-4b72-b704-05ca013dfa7f :END: -#+cindex: Installation +#+cindex: Install Lin LIN is not in any package archive for the time being, though I plan to submit it to GNU ELPA (as such, any non-trivial patches require @@ -118,140 +152,35 @@ Finally, in your =init.el= (or equivalent) evaluate this: Everything is in place to set up the package. -* Sample usage +* Sample configuration :PROPERTIES: :CUSTOM_ID: h:7d63e6a9-5a49-4106-970c-ae8bdb06ae9d :END: -#+cindex: Sample configuration - -#+begin_src emacs-lisp -(require 'lin) -(add-hook 'elfeed-search-mode-hook #'lin-mode) -#+end_src - -To activate ~lin-mode~ on all modes where it makes sense: +#+cindex: Set up Lin #+begin_src emacs-lisp (require 'lin) -(lin-add-to-many-modes) -#+end_src - -The customization option ~lin-foreign-hooks~ lets you configure the -list of hooks affected by ~lin-add-to-many-modes~. - -Else invoke ~lin-mode~ interactively. - -#+vindex: lin-override-foreground -In terms of customization options, ~lin-foreground-override~ determines -whether LIN should also override the foreground colors on the current -line. By default, it refrains from doing so. - -* Customize LIN faces -:PROPERTIES: -:CUSTOM_ID: h:4598ee11-bd6d-4ed4-baca-883b896ac3d6 -:END: - -#+vindex: lin-hl -#+vindex: lin-hl-override-fg -The two faces that LIN defines are ~lin-hl~ and ~lin-hl-override-fg~. The -latter is used only when ~lin-override-foreground~ is non-nil. - -To change the attributes of a face, one can use ~set-face-attribute~. In -these examples, we change the background color to a shade of magenta -that is suitable for light themes and we also apply a colored underline: - -#+begin_src emacs-lisp -;; This changes the face that is meant NOT to override the foregrounds. -;; Check `lin-override-foreground'. -(set-face-attribute 'lin-hl nil :background "#f0d3ff" :underline "#e0a3ff") - -;; And this one is the face that DOES override the foregrounds -(set-face-attribute 'lin-hl-override-fg nil :background "#f0d3ff" :underline "#e0a3ff") -#+end_src -When using [[https://protesilaos.com/emacs/modus-themes][the Modus themes]] (built-in to Emacs version 28 or higher), it -is possible to retrieve values directly from the active theme's palette. -And, it is possible to have different values for either =modus-operandi= -(the light theme) or =modus-vivendi= (dark). Here we showcase the former -method which involves the function ~modus-themes-color~ (read its doc -string for the technicalities and/or consult the themes' manual for more -advanced customizations, such as to make the changes adapt to theme -switching between Modus Operandi and Vivendi): - -#+begin_src emacs-lisp -(set-face-attribute 'lin-hl nil - :background (modus-themes-color 'green-subtle-bg) - :underline (modus-themes-color 'green-intense)) -#+end_src - -** Use system colors on macOS -:PROPERTIES: -:CUSTOM_ID: h:6bb11a50-cca9-49ca-9ea0-9d26c9324068 -:END: - -On macOS, it is possible to use named system colors. For a list of -available colors, see [[https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/color/][Apple's Human Interface Guidelines]]. - -To use macOS's named colors for selections as LIN's background and -foreground instead of specifying color values directly, tweak the two -LIN faces: - -#+begin_src emacs-lisp -(when (memq window-system '(mac ns)) - (set-face-attribute 'lin-hl nil - :background "selectedContentBackgroundColor") - - ;; To also override the foreground (see `lin-override-foreground'): - (set-face-attribute 'lin-hl-override-fg nil - :foreground "alternateSelectedControlTextColor" - :background "selectedContentBackgroundColor")) -#+end_src - -Note that these named colors are "Dynamic System Colors": in dark -mode, they produce a different value than in light mode. That means -you don't need to pick dark and light colors individually. The same -color names will work. - -However, you need to trigger an update of LIN's faces to pick up the -color values if you change the appearance from dark to light, or light -to dark. macOS builds of Emacs have a hook for this, and you can -perform a color update by adding a function to -~ns-system-appearance-change-functions~: - -#+begin_src emacs-lisp -(defun my-lin-macos-system-colors () - (when (memq window-system '(mac ns)) - (set-face-attribute 'lin-hl nil - :background "selectedContentBackgroundColor") - - ;; To also override the foreground (see `lin-override-foreground'): - (set-face-attribute 'lin-hl-override-fg nil - :foreground "alternateSelectedControlTextColor" - :background "selectedContentBackgroundColor"))) - -(when (memq window-system '(mac ns)) - (add-hook 'ns-system-appearance-change-functions #'my-lin-macos-system-colors)) -#+end_src - -If you want to use a different color than the macOS selection colors -in dark mode, you can tweak this approach: - -#+begin_src emacs-lisp -(defun my-lin--macos-mode-color (light dark) - "Use LIGHT or DARK color value, depending on macOS mode." - (if (eq ns-system-appearance 'light) - light - dark)) - -(defun my-lin-custom-faces () - (when (memq window-system '(mac ns)) - (let ((bg (my-lin--macos-mode-color "selectedContentBackgroundColor" "#2a40b8")) - (fg (my-lin--macos-mode-color "alternateSelectedControlTextColor" "#ffffff"))) - (set-face-attribute 'lin-hl nil :background bg) - (set-face-attribute 'lin-hl-override-fg nil :background bg :foreground fg)))) - -(when (memq window-system '(mac ns)) - (add-hook 'ns-system-appearance-change-functions #'my-lin-custom-faces)) +(setq lin-face 'lin-blue) ; check doc string for alternative styles + +(lin-setup) ; Either run this or change `lin-mode-hooks' + +(customize-set-variable + 'lin-mode-hooks ; do not use `setq' with this; `customize-set-variable' runs `lin-setup' automatically + '(dired-mode-hook + elfeed-search-mode-hook + git-rebase-mode-hook + ibuffer-mode-hook + ilist-mode-hook + ledger-report-mode-hook + log-view-mode-hook + magit-log-mode-hook + mu4e-headers-mode + notmuch-search-mode-hook + notmuch-tree-mode-hook + occur-mode-hook + org-agenda-mode-hook + tabulated-list-mode-hook)) #+end_src * Acknowledgements @@ -260,7 +189,7 @@ in dark mode, you can tweak this approach: :END: #+cindex: Contributors -LIN is meant to be a collective effort. Every bit of help matters. +Lin is meant to be a collective effort. Every bit of help matters. + Author/maintainer :: Protesilaos Stavrou. diff --git a/lin.el b/lin.el index 25f2992c99..83c4519d6b 100644 --- a/lin.el +++ b/lin.el @@ -1,11 +1,12 @@ -;;; lin.el --- LIN Is Noticeable -*- lexical-binding: t -*- +;;; lin.el --- Make `hl-line-mode' more suitable for selection UIs -*- lexical-binding: t -*- -;; Copyright (C) 2021 Free Software Foundation, Inc. +;; Copyright (C) 2021-2022 Free Software Foundation, Inc. ;; Author: Protesilaos Stavrou <i...@protesilaos.com> ;; URL: https://gitlab.com/protesilaos/lin ;; Version: 0.1.0 ;; Package-Requires: ((emacs "27.1")) +;; Keywords: convenience, faces, theme ;; This file is NOT part of GNU Emacs. @@ -24,34 +25,63 @@ ;;; Commentary: ;; -;; LIN locally remaps the `hl-line' face to a style that is optimal for -;; major modes where line selection is the primary mode of interaction. +;; Lin is a stylistic enhancement for Emacs' built-in `hl-line-mode'. +;; It remaps the `hl-line face (or equivalent) buffer-locally to a style +;; that is optimal for major modes where line selection is the primary +;; mode of interaction. ;; -;; The idea is that `hl-line' cannot work equally well for contexts with -;; competing priorities: (i) line selection, or (ii) simple line +;; The idea is that `hl-line-mode' cannot work equally well for contexts +;; with competing priorities: (i) line selection, or (ii) simple line ;; highlight. In the former case, the current line needs to be made -;; prominent because it carries a specific meaning of some significance -;; in the given context. Whereas in the latter case, the primary mode -;; of interaction does not revolve around the line highlight itself: it -;; may be because the focus is on editing text or reading through the -;; buffer's contents, so the current line highlight is more of a gentle -;; reminder of the point's location on the vertical axis. +;; prominent because it carries a specific meaning of some significance in +;; the given context: the user has to select a line. Whereas in the latter +;; case, the primary mode of interaction does not revolve around the line +;; highlight itself: it may be because the focus is on editing text or +;; reading through the buffer's contents, so the current line highlight is +;; more of a reminder of the point's location on the vertical axis. ;; -;; `lin-mode' only shows its effect when `hl-line-mode' is active or, -;; more specifically, when the `hl-line' face is used in the buffer. -;; `lin-mode' DOES NOT activate `hl-line-mode' and does not do anything -;; other than the aforementioned face remapping. +;; `lin-mode' enables `hl-line-mode' by adding it to every hook specified +;; in the user option `lin-mode-hooks'. Users are advised to configure +;; that variable with `customize-set-variable', or the Custom UI, or +;; equivalent as it has a function which automatically sets up Lin. Those +;; who prefer to set values with `setq' must handle the process manually, +;; by using the `lin-setup' function. ;; -;; Sample usage: +;; Users can selected their preferred style by customizing the user +;; option `lin-face'. Options include the faces `lin-red', `lin-green', +;; `lin-yellow', `lin-blue' (default), `lin-magenta', `lin-cyan', +;; `lin-mac', `lin-red-override-fg', `lin-green-override-fg', +;; `lin-yellow-override-fg', `lin-blue-override-fg', +;; `lin-magenta-override-fg', `lin-cyan-override-fg', +;; `lin-mac-override-fg', or any other face that preferably has a +;; background attribute. The Lin faces with the =-override-fg= suffix +;; set a foreground value which replaces that of the underlying text. +;; Whereas the others only specify a background attribute. ;; -;; (add-hook 'elfeed-search-mode-hook #'lin-mode) +;; Sample configuration: ;; -;; Or for more mode hooks: +;; (require 'lin) ;; -;; (dolist (hook '(elfeed-search-mode-hook notmuch-search-mode-hook)) -;; (add-hook hook #'lin-mode)) +;; (setq lin-face 'lin-blue) ;; -;; Else invoke `lin-mode' interactively. +;; (lin-setup) +;; +;; (customize-set-variable +;; 'lin-mode-hooks +;; '(dired-mode-hook +;; elfeed-search-mode-hook +;; git-rebase-mode-hook +;; ibuffer-mode-hook +;; ilist-mode-hook +;; ledger-report-mode-hook +;; log-view-mode-hook +;; magit-log-mode-hook +;; mu4e-headers-mode +;; notmuch-search-mode-hook +;; notmuch-tree-mode-hook +;; occur-mode-hook +;; org-agenda-mode-hook +;; tabulated-list-mode-hook)) ;; ;; Consult the manual for further details. Or visit the documentation's ;; web page: <https://protesilaos.com/emacs/lin>. @@ -59,106 +89,256 @@ ;;; Code: (require 'face-remap) +(require 'hl-line) + +(make-obsolete 'lin--default-foreign-hooks 'lin-mode-hooks "0.2.0") + +(defgroup lin () + "Make `hl-line' appropriate for selection UIs." + :group 'convenience) -(defconst lin--default-foreign-hooks - ;; please keep the list sorted: - '(elfeed-search-mode-hook +(defcustom lin-mode-hooks + '(dired-mode-hook + elfeed-search-mode-hook git-rebase-mode-hook ibuffer-mode-hook + ilist-mode-hook ledger-report-mode-hook log-view-mode-hook magit-log-mode-hook mu4e-headers-mode notmuch-search-mode-hook notmuch-tree-mode-hook + occur-mode-hook org-agenda-mode-hook - ilist-mode-hook tabulated-list-mode-hook) - "List of default hooks in which to use `lin-mode'. -See also the user option `lin-override-foreground'.") + "List of hooks that should enable `lin-mode'. -(defgroup lin () - "Locally remap `hl-line' face for greater flexility." - :group 'convenience) +When Lin is set up, it activates `hl-line-mode' and remaps its +face to `lin-face'. This makes it possible to distinguish +between the two use-cases of permanent line highlighting: (i) +gentle reminder of where the point is while editing, (ii) current +selection. -(defcustom lin-override-foreground nil - "Do not override foreground colors. +Set this user option with `customize-set-variable', the Custom +UI, or equivalent. It has a custom setter function which +automatically sets things up when configured that way. Users who +prefer to use `setq' must run `lin-setup' manually. Consult its +doc string." + :type '(repeat variable) + :initialize #'custom-initialize-default + :set (lambda (symbol value) + (if (eq value (default-value symbol)) + (set-default symbol value) + (lin-setup 'reverse) + (set-default symbol value) + (lin-setup))) + :group 'lin) -Set to non-nil to always override the foreground colors on the -current line that is highlighted by `lin-mode'. +(defcustom lin-face 'lin-blue + "Face to use for the pulse line. +Users can select one among `lin-red', `lin-green', `lin-yellow', +`lin-blue' (default), `lin-magenta', `lin-cyan', `lin-mac', +`lin-red-override-fg', `lin-green-override-fg', +`lin-yellow-override-fg', `lin-blue-override-fg', +`lin-magenta-override-fg', `lin-cyan-override-fg', +`lin-mac-override-fg', or any other face that preferably has a +background attribute." + :type '(radio (face :tag "Red style" lin-red) + (face :tag "Green style" lin-green) + (face :tag "Yellow style" lin-yellow) + (face :tag "Blue style (default)" lin-blue) + (face :tag "Magenta style" lin-magenta) + (face :tag "Cyan style" lin-cyan) + (face :tag "macOS style" lin-mac) + (face :tag "Red style that also overrides the underlying foreground" lin-red-override-fg) + (face :tag "Green style that also overrides the underlying foreground" lin-green-override-fg) + (face :tag "Yellow style that also overrides the underlying foreground" lin-yellow-override-fg) + (face :tag "Blue style that also overrides the underlying foreground" lin-blue-override-fg) + (face :tag "Magenta style that also overrides the underlying foreground" lin-magenta-override-fg) + (face :tag "Cyan style that also overrides the underlying foreground" lin-cyan-override-fg) + (face :tag "macOS style that also overrides the underlying foreground" lin-mac-override-fg) + (face :tag "Other face (must have a background)")) + :group 'lin) -This requires `lin-mode' to be restarted wherever it is active. +;;;; Faces -When this option is nil, the `lin-hl' face is used. Otherwise -the `lin-hl-override-fg' is applied." - :type 'boolean +(defgroup lin-faces () + "Faces for `lin.el'." :group 'lin) -(defcustom lin-foreign-hooks lin--default-foreign-hooks - "List of hook variable names in which to use `lin-mode'. +(defface lin-red + '((default :foreground unspecified :underline nil :extend t) + (((class color) (min-colors 88) (background light)) + :background "#ffd3d3") + (((class color) (min-colors 88) (background dark)) + :background "#500f0f") + (t :background "red")) + "Alternative red face for `lin-face'." + :group 'lin-faces) -Call `lin-add-to-many-modes' to start `lin-mode' for all these -hooks." - :type '(repeat variable)) +(defface lin-red-override-fg + '((default :inherit lin-red) + (((background light)) + :foreground "black") + (((background dark)) + :foreground "white")) + "Like `lin-red' but also sets a foreground." + :group 'lin-faces) -(defface lin-hl +(defface lin-green '((default :foreground unspecified :underline nil :extend t) (((class color) (min-colors 88) (background light)) - :background "#b0d8ff") + :background "#bfeabf") (((class color) (min-colors 88) (background dark)) - :background "#103265") - (t :inherit highlight)) - "Like `lin-hl-override-fg', but does not override foreground color. -Used only when `lin-override-foreground' is nil." - :group 'lin) + :background "#0f300f") + (t :background "green")) + "Alternative green face for `lin-face'." + :group 'lin-faces) + +(defface lin-green-override-fg + '((default :inherit lin-green) + (((background light)) + :foreground "black") + (((background dark)) + :foreground "white")) + "Like `lin-green' but also sets a foreground." + :group 'lin-faces) -(defface lin-hl-override-fg - '((default :underline nil :extend t) +(defface lin-yellow + '((default :foreground unspecified :underline nil :extend t) (((class color) (min-colors 88) (background light)) - :background "#b0d8ff" :foreground "#000000") + :background "#ffecaa") (((class color) (min-colors 88) (background dark)) - :background "#103265" :foreground "#ffffff") - (t :inherit highlight)) - "Face for locally remapped `hl-line' face via `lin-mode'. -Used only when `lin-override-foreground' is non-nil." - :group 'lin) + :background "#412200") + (t :background "yellow")) + "Alternative yellow face for `lin-face'." + :group 'lin-faces) + +(defface lin-yellow-override-fg + '((default :inherit lin-yellow) + (((background light)) + :foreground "black") + (((background dark)) + :foreground "white")) + "Like `lin-yellow' but also sets a foreground." + :group 'lin-faces) + +(defface lin-blue + '((default :foreground unspecified :underline nil :extend t) + (((class color) (min-colors 88) (background light)) + :background "#c0e4ff") + (((class color) (min-colors 88) (background dark)) + :background "#002460") + (t :background "blue")) + "Alternative blue face for `lin-face'." + :group 'lin-faces) + +(defface lin-blue-override-fg + '((default :inherit lin-blue) + (((background light)) + :foreground "black") + (((background dark)) + :foreground "white")) + "Like `lin-blue' but also sets a foreground." + :group 'lin-faces) + +(defface lin-magenta + '((default :foreground unspecified :underline nil :extend t) + (((class color) (min-colors 88) (background light)) + :background "#ffd9ff") + (((class color) (min-colors 88) (background dark)) + :background "#401d40") + (t :background "magenta")) + "Alternative magenta face for `lin-face'." + :group 'lin-faces) + +(defface lin-magenta-override-fg + '((default :inherit lin-magenta) + (((background light)) + :foreground "black") + (((background dark)) + :foreground "white")) + "Like `lin-magenta' but also sets a foreground." + :group 'lin-faces) + +(defface lin-cyan + '((default :foreground unspecified :underline nil :extend t) + (((class color) (min-colors 88) (background light)) + :background "#baeaf8") + (((class color) (min-colors 88) (background dark)) + :background "#002f3f") + (t :background "cyan")) + "Alternative cyan face for `lin-face'." + :group 'lin-faces) + +(defface lin-cyan-override-fg + '((default :inherit lin-cyan) + (((background light)) + :foreground "black") + (((background dark)) + :foreground "white")) + "Like `lin-cyan' but also sets a foreground." + :group 'lin-faces) + +;; TODO 2022-03-18: Can we find all system styles? Then we can rename +;; this to `lin-system'. +(defface lin-mac + '((((type ns)) + ;; <https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/color/>. + :background "selectedContentBackgroundColor" :extend t) + (t :inherit lin-blue)) + "Alternative macOS-style face for `lin-face'." + :group 'lin-faces) + +(defface lin-mac-override-fg + '((t :inherit lin-mac :foreground "alternateSelectedControlTextColor")) + "Like `lin-mac' but also sets a foreground." + :group 'lin-faces) + +;;;; Lin setup (defvar-local lin--cookie nil "Cookie returned by `face-remap-add-relative'.") -(defvar hl-line-face) - (defun lin--source-face () "Determine the source face, what to remap." (cond ((derived-mode-p 'mu4e-headers-mode) 'mu4e-header-highlight-face) + ((derived-mode-p 'magit-mode) + 'magit-section-highlight) ;; Do not target `hl-line' directly, as it can be changed by ;; `hl-line-face'. ((bound-and-true-p hl-line-face) - hl-line-face) + hl-line-face) (t 'hl-line))) -(defun lin--dest-face () - "Determine the destination face, what source must remap to. -This is controlled by `lin-override-foreground', which see." - (if lin-override-foreground 'lin-hl-override-fg 'lin-hl)) - (define-minor-mode lin-mode - "Remap `hl-line' face to a local LIN face. -The overall style is controlled by `lin-override-foreground'." + "Enable `hl-line-mode' and remap its face to `lin-face'." :local t :init-value nil (if lin-mode - (setq lin--cookie - (face-remap-add-relative (lin--source-face) (lin--dest-face))) - (face-remap-remove-relative lin--cookie))) - -(defun lin-add-to-many-modes () - "Turn on `lin-mode' on every mode of `lin-foreign-hooks'." - (dolist (hook lin-foreign-hooks) - (add-hook hook #'lin-mode))) + (progn + (setq lin--cookie + (face-remap-add-relative (lin--source-face) lin-face)) + (hl-line-mode 1)) + (face-remap-remove-relative lin--cookie) + (hl-line-mode -1))) + +(defun lin-setup (&optional reverse) + "Set up Lin for select mode hooks. + +This adds `lin-mode' and `hl-line-mode' to every hook in +`lin-mode-hooks'. + +With optional non-nil REVERSE argument, remove those hooks." + (if reverse + (dolist (hook lin-mode-hooks) + (remove-hook hook #'lin-mode)) + (dolist (hook lin-mode-hooks) + (add-hook hook #'lin-mode)))) (provide 'lin)