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?

3
  • 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. Commented Feb 14, 2023 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) Commented Feb 14, 2023 at 17:49
  • I agree that both of these suggestions would improve the code, thank you. Commented Feb 15, 2023 at 2:06

1 Answer 1

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))))))
4
  • 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
    Commented Feb 8, 2023 at 12:49
  • @nichijou what is the difference between an alist by definition and an alist by convention? Commented Feb 8, 2023 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
    Commented Feb 8, 2023 at 15:42
  • That is very helpful information, thank you. Commented Feb 8, 2023 at 22:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.