4

The theme modus-vivendi exports an alist of named colors:

(deftheme modus-vivendi
    "Elegant, highly legible and customizable dark theme.
Conforms with the highest legibility standard for color contrast
between background and foreground in any given piece of text,
which corresponds to a minimum contrast in relative luminance of
7:1 (WCAG AAA standard).")

  (defconst modus-vivendi-palette
    '(
;;; Basic values

      (bg-main          "#000000")
      (bg-dim           "#1e1e1e")
      (fg-main          "#ffffff")
      (fg-dim           "#989898")
      (fg-alt           "#c6daff")
      ...

I am trying to access these colors by name so that I can use them in some face specifications. Here is the working code that I came up with:

(let-alist modus-vivendi-palette
  (let ((code-bg (car .bg-blue-nuanced)))
    (custom-set-faces
     `(org-block-begin-line ((t (:background ,code-bg :extend t))))
     `(org-block-end-line ((t (:background ,code-bg :extend t))))
     `(org-block ((t (:background ,code-bg :extend t))))
     )))

I am a new Lisp programmer who is used to languages such as Python, Java and JavaScript. This solution feels wrong to me because it requires a lot of work just to get some data from the equivalent of a Python dictionary. Is there a better way to implement this code, or is this considered idiomatic?

  • First, if you're interested in developing your elisp chops, you may find `dash.el` useful. It's in both the Gnu and MELPA repos. The downside is that you've introduced a dependency and your code is no longer portable/vanilla elisp, but `dash` is very widely known and used, so that's not a big risk. It's a library of functional list-processing functions and Lisp macros. You may find you already have it installed as lots of packages use it. Anyway, the `-let` macro from `dash.el` could condense your first two lines into one. – Phil Hudson Feb 14 '23 at 17:45
  • Second, you have the identical expression being repeatedly assembled and assigned to the three faces. I would do it once using `let` (or `-let`) to assign that expression to a variable named say `my-face-def`. You then assemble each face redefinition thus: `\`(org-block ,my-face-def)` – Phil Hudson Feb 14 '23 at 17:49
  • I agree that both of these suggestions would improve the code, thank you. – firstname gklsodascb Feb 15 '23 at 02:06

1 Answers1

3

I'm not an experienced Lisp programmer but using alist-get makes your code look cleaner to me

(let ((code-bg (alist-get 'bg-blue-nuanced modus-vivendi-palette)))
  (custom-set-faces
   `(org-block-begin-line ((t (:background ,code-bg :extend t))))
   `(org-block-end-line ((t (:background ,code-bg :extend t))))
   `(org-block ((t (:background ,code-bg :extend t))))))
matteol
  • 1,868
  • 1
  • 9
  • 11
  • modus-vivendi-palette is an alist by definition but not one by convention. the value retrieved from it by alist-get is something like `("#000000")` – nichijou Feb 08 '23 at 12:49
  • @nichijou what is the difference between an alist by definition and an alist by convention? – firstname gklsodascb Feb 08 '23 at 14:58
  • 1
    You would normally write alist in the form of `((key1 . value2) (key2 . value2))`, you can get `value1` with `(alist-get 'key1 alist)`. The code you provide `((key1 value1) (key2 value2)`, actually is `((key1 . (value1)) (key2 . (value2)))`, with alist-get, you receive `(value1)`, you have to further use `car` to get `value1` out. – nichijou Feb 08 '23 at 15:42
  • That is very helpful information, thank you. – firstname gklsodascb Feb 08 '23 at 22:25