1

I want to change my colour scheme to a random color scheme. Consider this elisp function:

(defun random-colour-theme () ;; written 2017-04-02
  "Pick a random colour theme."
  (interactive)
  (setq randomNumber (random 2))
  (setq randomColourScheme (nth randomNumber '(
"color-theme-dark"
"color-theme-light")))
(randomColourScheme)
  )

Everything works except the last line, (randomColourScheme). randomColourScheme is a string representing either "color-theme-dark" or "color-theme-light". If the command were (color-theme-dark), then it would work. How do you execute a command that is currently in a variable as a string? I don't know how to get started on this one.

1
  • 1
    Use funcall on intern of the selected string. Or (as @sds mentioned) use symbols instead of strings, in which case no need to use intern to get the symbol. Then your code will work fine (even in older Emacs versions that don't have function seq-random-elt).
    – Drew
    Apr 4 '17 at 20:52
3

Use symbols instead of strings:

(require 'seq)
(defvar theme-selection
  '(color-theme-dark
    color-theme-light))
(defun random-theme ()
  "Pick a random colour theme."
  (interactive)
  (funcall (seq-random-elt theme-selection)))

See also funcall and Sequence Functions.

PS. Note that if you compile your function, you will get warnings about undeclared globals. You should use let instead of setq for your local variables.

PPS. Older Emacsen lack seq, so you can roll your own:

(defun random-theme ()
  "Pick a random colour theme."
  (interactive)
  (funcall (nth (random (length theme-selection)) theme-selection)))
9
  • I am trying this. I downloaded and installed github.com/NicolasPetton/seq.el but it does not appear to have a function seq-random-elt. So I get "Symbol's function definition is void: seq-random-elt. --> thank you for the answer though and the suggestion to try symbols! Apr 4 '17 at 20:43
  • No need to download and install anything. Just evaluate the code in a modern emacs (wfm with e26).
    – sds
    Apr 4 '17 at 20:48
  • You may need to (require 'seq) first. Apr 4 '17 at 22:00
  • 1
    @TianxiangXiong: I have (require 'seq) in my answer!
    – sds
    Apr 4 '17 at 22:02
  • 1
    Currently widely deployed versions of Emacs (i.e. Emacs 23.1–24.5) don't have seq. (Yes, 23.1, that's the version in CentOS 6 which is still a popular distribution) Apr 4 '17 at 22:36
1
(defun random-colour-theme () ;; written 2017-04-02
  "Pick a random colour theme."
  (interactive)
  (let* ((color-schemes '("color-theme-dark"
                          "color-theme-light"))
         (random-number (random (length color-schemes)))
         (random-colour-scheme
          (nth random-number color-schemes)))
    (funcall (intern random-colour-scheme))))
2
  • This works! Thanks, politza and sds. Apr 4 '17 at 22:19
  • 1
    But as indicated by sds and Drew, it's pointless writing these as strings in the first place when their sole use-case requires them to be in symbol form. Unless there is some unstated reason for wanting string input then just use (let* ((color-schemes '(color-theme-dark color-theme-light)) ... and ditch the intern call.
    – phils
    Apr 4 '17 at 22:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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