2026 Apr 04It was really fun to learn about advising Lisp functionsto extend functionality in Emacs. My first use case was to run a custom function every time a certain function inBastian Bechtold’sorg-static-blog is called. Of course, I could customize that function directly in my own fork, but Lisp advice allows you to modify functions without clobbering them directly. This approach has aesthetic and practical advantages.But I’ve struggled to understand the concepts and implementation of advice. Today I posted to Mastodonabout how excited I was to get my first working use, and Philip asked me to share the code.My problem was specifying HTML boilerplate that org-static-blog puts in each post when it publishes all the static files, using string variables like org-static-blog-page-header. These strings are complex enough that I put them in their own files, like these lines in the #header.html file that specifies the page metadata:First, Stack Exchange and I solved the problem of reading a file into a string. (?! How is this not a native function!? Maybe I missed something obvious.)(defun jeh/file-to-string (file) "Return a string that is the contents of FILE." (with-temp-buffer (insert-file-contents file) (buffer-string)))And then, for example:(setq org-static-blog-page-header (jeh/file-to-string (expand-file-name "#header.html" org-static-blog-template-blocks-directory)))The unscratched itch was that every time I edit one of these files, I always, but always, forget to update the appropriate variable with the contents of the file! And so publishing doesn’t reflect the changes, and I get confused, and then I remember….Here is the solution:(defun jeh/org-static-blog-read-templates (&rest ignore) "Set org-static-blog-page -header, -preamble, -postamble variablesby reading files from `org-static-blog-template-blocks-directory'." (setq org-static-blog-page-header ;;; HTML to put in the of each page. (jeh/file-to-string (expand-file-name "#header.html" org-static-blog-template-blocks-directory))) (setq org-static-blog-page-preamble ;;; HTML to put before the content of each page. (jeh/file-to-string (expand-file-name "#preamble.html" org-static-blog-template-blocks-directory))) (setq org-static-blog-page-postamble ;;; HTML to put after the content of each page. (format (jeh/file-to-string (expand-file-name "#postamble.html" org-static-blog-template-blocks-directory)) (number-to-string emacs-major-version) (number-to-string emacs-minor-version) org-version)));;; Re-read the template files before publishing,;;; so changes will be included in output.(advice-add #'org-static-blog-publish :before #'jeh/org-static-blog-read-templates)The function jeh/org-static-blog-read-templates sets the variablesorg-static-blog-page-header,org-static-blog-page-preamble, andorg-static-blog-page-postamble to the contents of the appropriate files. Making that function a hook to the function which generates all the static pages, org-static-blog-publish, solves my problem. But there is no hook for it! I had a suspicion that add-advice could give me the same result, and—I hope you’re sitting down—Iread the fine manualand learned that the syntax of the last line accomplishes that very thing.Of course, advice-add (and related functions) can do much more! Maybe as I learn I will be able to customize functions from other packages without just banging on a local fork.tags: emacs