I could see myself wanting to do specific things on specific filetypes, regardless of what major mode it falls into. Web mode attempts to “catch-all” but there are still unique aspects of some templating engines that I want to control. I also don’t want to write the same conditional every time, so let’s make it a function with a callback.
(defun on-filetype(pattern func) "Checks the extension and fires a callback if it matches"
(when (and (stringp buffer-file-name)
(string-match pattern buffer-file-name))
(funcall func)))
Use web-mode for html and liquid syntax. Tell web-mode that I don’t want to use their auto-pairing as it diverges from what I enjoy using (electric-pair)
(use-package web-mode
:ensure t
:config
(setq web-mode-enable-auto-pairing nil)
:mode
("\\.html\\'" . web-mode)
("\\.liquid\\'" . web-mode))
Configure my automatic modes for other liquid files. Yes, Shopify lets you use liquid in CSS and even JS modes. It makes Shopify dynamic but confuses the heck out of linters/language-servers. I live with a lot of red squiggles.
Here I define when and how I want electric pair to auto-pair the {% keyword %}
pattern in liquid files only.
(add-to-list 'auto-mode-alist '("\\.css.liquid\\'" . css-mode))
(add-to-list 'auto-mode-alist '("\\.scss.liquid\\'" . scss-mode))
(defvar liquid-electric-pairs '((?% . ?%)) "Electric pairs for liquid syntax.")
(defun liquid-add-electric-pairs ()
(setq-local electric-pair-pairs (append electric-pair-pairs liquid-electric-pairs))
(setq-local electric-pair-text-pairs electric-pair-pairs))
(add-hook 'web-mode-hook (lambda () (on-filetype "\\.liquid\\'" #'liquid-add-electric-pairs)))