diff options
author | Timo Wilken | 2022-11-22 00:12:36 +0100 |
---|---|---|
committer | Timo Wilken | 2022-11-22 00:13:25 +0100 |
commit | 699b6fd0b4279170ed62af13af549c7ec188af12 (patch) | |
tree | 8afa65ef944f775a815203b1aa0e7631892cba94 /emacs-packages/alidist-mode.el | |
parent | f6b442e3d9d5c634fb578dc45d632c37e56a1fac (diff) |
Track custom Emacs packages in guix home
Diffstat (limited to 'emacs-packages/alidist-mode.el')
-rw-r--r-- | emacs-packages/alidist-mode.el | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/emacs-packages/alidist-mode.el b/emacs-packages/alidist-mode.el new file mode 100644 index 00000000..594fe2d1 --- /dev/null +++ b/emacs-packages/alidist-mode.el @@ -0,0 +1,91 @@ +;;; alidist-mode.el --- Major mode for alidist recipes +;;; Commentary: +;;; alidist recipes are shell scripts with a YAML header in front. +;;; We want both these parts highlighted properly, and to lint the +;;; whole thing with a custom script that glues together yamllint and +;;; shellcheck with a few custom checks. +;;; Code: + +(require 'flycheck) +(require 'sh-script) +(require 'mmm-auto) + +(flycheck-def-executable-var alidist "alidistlint") + +(flycheck-define-checker alidist + "A syntax checker and linter for alidist recipes." + ;; `flycheck-alidist-executable' automatically overrides the car of the + ;; :command list if set and non-nil. + :command ("alidistlint" "--format=gcc" source) + :error-patterns + ((error line-start (file-name) ":" line ":" column ": error: " (message) + " [" (id (minimal-match (one-or-more not-newline))) "]" line-end) + (warning line-start (file-name) ":" line ":" column ": warning: " (message) + " [" (id (minimal-match (one-or-more not-newline))) "]" line-end) + (info line-start (file-name) ":" line ":" column ": note: " (message) + " [" (id (minimal-match (one-or-more not-newline))) "]" line-end)) + :modes (alidist-mode alidist-script-mode)) + +(add-to-list 'flycheck-checkers 'alidist) + +(defvar-local alidist-mode-mmm-refresh-timer nil + "An idle timer for the current buffer, to make `mmm-mode' reparse it.") +(put 'alidist-mode-mmm-refresh-timer 'risky-local-variable t) + +(defun alidist-mode-cancel-refresh-timer () + "Cancel and delete the timer that reparses the buffer. +It is stored in `alidist-mode-mmm-refresh-timer'." + (when alidist-mode-mmm-refresh-timer + (cancel-timer alidist-mode-mmm-refresh-timer) + (setq alidist-mode-mmm-refresh-timer nil))) + +(define-derived-mode alidist-mode yaml-mode "alidist" + "An outer mode for alidist recipes, handling the metadata." + (mmm-mode) + ;; `mmm-mode' doesn't refresh its submodes when the buffer changes (e.g. when + ;; a *_recipe key is added to the YAML header), so refresh manually when idle. + (alidist-mode-cancel-refresh-timer) + (add-hook 'kill-buffer-hook #'alidist-mode-cancel-refresh-timer 0 t) + (setq alidist-mode-mmm-refresh-timer + (run-with-idle-timer + 2 t (lambda (original-buffer) + (when (eq original-buffer (current-buffer)) + ;; Silence `mmm-parse-buffer''s annoying message. + (let ((inhibit-message t)) + (mmm-parse-buffer)))) + ;; Idle timers are global, so make sure we only run the timer in the + ;; right buffer. Save the buffer now to enable this, and compare every + ;; time the timer ticks over. + (current-buffer)))) + +(define-derived-mode alidist-script-mode sh-mode "Script" + "A mode for scripts in alidist recipes with some default settings." + (sh-set-shell "bash")) + +(mmm-add-group 'alidist-recipe + '((alidist-main-script + :submode alidist-script-mode + :face mmm-default-submode-face + :front "^---\n" + :back "\\'") ; end of buffer + (alidist-option-script + :submode alidist-script-mode + :face mmm-default-submode-face + ;; Any *_recipe key with a multiline string value is probably a script. + :front "^[[:space:]]*[a-z_]+_recipe: [|>]-?\n" + ;; End of YAML header, or another YAML key. + :back "^---\n\\|^[[:space:]]*[a-z_]+:\\($\\| \\)"))) + +;; Add sh-mode's indentation variables to mmm-mode's list. +(setq mmm-save-local-variables + `(,@(mapcar + (lambda (var) `(,var () (sh-mode))) + sh-var-list) + . ,mmm-save-local-variables)) + +(mmm-add-mode-ext-class 'alidist-mode nil 'alidist-recipe) +(add-to-list 'auto-mode-alist (cons "\\(\\`\\|/\\)alidist/.+\\.sh\\'" + #'alidist-mode)) + +(provide 'alidist-mode) +;;; alidist-mode.el ends here |