David Maus

Setting up Emacs for VuFind® development

I've gotten more involved in PHP development lately, mostly working on VuFind®-related packages. My editor of choice is GNU Emacs, and today I finally finished my Emacs setup. Lo and behold!

(use-package php-mode  :ensure t  :hook  (php-mode . eglot-ensure)  (php-mode . completion-preview-mode)  (php-mode . subword-mode)  :custom  (php-manual-url "http://127.0.0.1:8118/php/")  (php-manual-path (expand-file-name "webdocs/php/" user-emacs-directory))  (php-search-documentation-function 'php-local-manual-search)  (php-search-documentation-browser-function 'eww-browse-url)  (lsp-phpactor-path (executable-find "phpactor")))

I use php-mode for editing pure PHP code and web-mode (not shown here) for working with PHP templates. I run the latest Emacs version (GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.35, cairo version 1.18.0) of 2024-02-17) which ships with Eglot, the built-in Emacs Client for LSP servers. A local copy of the PHP manual is installed inside my GNU Emacs user directory and served by a Simple http server in Rust.

To make working with project files easier I define a PHP project type. This project type allows me to execute project-specific commands such as finding a project file (project-find-file or execute local tests project-compile.

(use-package project  :config  (setq project-find-functions        (cons #'project-try-maven              (cons #'project-try-composer project-find-functions)))  :init  (put 'project-name 'safe-local-variable 'stringp)  (put 'project-owner 'safe-local-variable 'stringp)  (defun project-try-maven (dir)    (let ((root (locate-dominating-file dir "pom.xml")))      (when root        (list 'java root))))  (cl-defmethod project-root ((project (head java)))    (nth 1 project))  (defun project-try-composer (dir)    (let ((root (locate-dominating-file dir "composer.json")))      (when root        (list 'php root))))  (cl-defmethod project-root ((project (head php)))    (nth 1 project)))

In the project definition you also see me declaring two symbols project-name and project-owner as safe local variables. I use those when inserting the license blurb (defined as a Skeleton) and define them as directory-local variables at the project root.

;;; Directory Local Variables         -*- no-byte-compile: t; -*-;;; For more information see (info "(emacs) Directory Variables")((nil . ((project-name . "DAIA Model")         (project-owner . "Staats- und Universitätsbibliothek Hamburg"))))

Combine all this with Magit and the versality of a mature text editor & putting architecture into code is a breeze.