Search code examples
variablesemacselisp-macro

How to use local variable in Elisp defmacro?


I write a elisp macro in my configuration file of emacs, but like something shown below ,(intern (format "%s-display-table" name)) is used several times, how can I use a something like variable to represent it?

;; Change the glyphs of "wrap", "truncation" and "vertical-border" in the display table specified by
;; parameter "name", obviously "↩", "…" and "ǁ" is better choice than the default values "\", "$"
;; and "|".
(defmacro change-glyphs-of-display-table (name)
  `(lambda ()
   (interactive)
   (unless ,(intern (format "%s-display-table" name))
     (setq ,(intern (format "%s-display-table" name)) (make-display-table)))
   (set-display-table-slot ,(intern (format "%s-display-table" name)) 'wrap ?\↩)
   (set-display-table-slot ,(intern (format "%s-display-table" name)) 'truncation ?\…)
   (set-display-table-slot ,(intern (format "%s-display-table" name)) 'vertical-border ?\ǁ)))

Solution

  • With name being an argument to the macro, you know it's always available at expansion time, and so you can process it outside of the backquoted form:

    ;; Change the glyphs of "wrap", "truncation" and "vertical-border" in the display table specified by
    ;; parameter "name", obviously "↩", "…" and "ǁ" is better choice than the default values "\", "$"
    ;; and "|".
    (defmacro change-glyphs-of-display-table (name)
      (let ((namedisplaytable (intern (format "%s-display-table" name))))
        `(lambda ()
           (interactive)
           (unless ,namedisplaytable
             (setq ,namedisplaytable (make-display-table)))
           (set-display-table-slot ,namedisplaytable 'wrap ?\↩)
           (set-display-table-slot ,namedisplaytable 'truncation ?\…)
           (set-display-table-slot ,namedisplaytable 'vertical-border ?\ǁ))))