0

I have the following .dir-locals:

((nil . ((eval . (let ((project-root-dir (expand-file-name (locate-dominating-file default-directory ".dir-locals.el"))))
                   (defun tokenize-set-strings ()
                     "Parse the contents of res/set/string.set and process them into src/core/string.hpp tokens."
                     (let ((string-set-file (format "%s/res/set/string.set" project-root-dir))
                           (current-file (buffer-file-name (current-buffer)))
                           (target-file (format "%s/src/core/sstring.hpp" project-root-dir))
                           (tokenizer-prog (format "%s/bin/util/stokenizer" project-root-dir)))
                       (if (string= string-set-file current-file)
                           (if (not (file-exists-p target-file))
                               (error (format "%s does not exist." target-file))
                             (if (not (file-exists-p tokenizer-prog))
                                 (error (format "Could not find tokenizer at %s." tokenizer-prog))
                               (shell-command (format "%s %s %s" tokenizer-prog target-file string-set-file)))))))
                   (add-hook 'after-save-hook 'tokenize-set-strings))))))

The idea here is that whenever I edit a project-specific string.set file, it will then run an external program called stokenizer once the file is saved. I don't want this functionality anywhere else.

The function on its own works fine, but when it's called via the hook, Emacs complains:

let: Symbol’s value as variable is void: project-root-dir

I'm not sure why it's not working, and would appreciate any tips. In the mean time, I get around this issue by calling binding project-root-dir an additional time, this time with let*, inside the function.

4
  • 1
    Try adding ;;; -*- lexical-binding: t -*- at the top of your .dir-locals.el file. Commented May 15, 2022 at 5:18
  • @NickD Tried it, didn't work -- same issue. Commented May 16, 2022 at 1:53
  • M-x toggle-debug-on-error, open a file that will trigger the function and see if there is a backtrace produced. If yes, add it to your question. Commented May 16, 2022 at 2:16
  • 1
    @NickD Dir-local settings are not loaded, so hack-local-variables is not applied and your suggestion does not work. Dir-local settings are read and eval-ed. The eval is executed in hack-one-local-variable without the lexical argument. So, it creates lambdas and not closures. Maybe, backquoting would be a solution. Another strategy would be to use (eval '(let (...) ...) t) , i.e., eval with non-nil lexical-argument. Commented May 17, 2022 at 22:27

0

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.