diff --git a/TODO.md b/TODO.md index fa4eeab3..dba4042a 100644 --- a/TODO.md +++ b/TODO.md @@ -75,7 +75,7 @@ level and how many hours you'd like to spend on the patch. - [ ] automatic language formatter, ala `gofmt` - [ ] gedit/gnome-builder/gtksourceview syntax highlighting - [ ] vim syntax highlighting -- [ ] emacs syntax highlighting +- [x] emacs syntax highlighting: see `misc/emacs/` ## Other diff --git a/misc/emacs/README.md b/misc/emacs/README.md new file mode 100644 index 00000000..38a9eebf --- /dev/null +++ b/misc/emacs/README.md @@ -0,0 +1,12 @@ +[![MELPA](https://melpa.org/packages/mgmtconfig-mode-badge.svg)](https://melpa.org/#/mgmtconfig-mode) +[![MELPA Stable](https://stable.melpa.org/packages/mgmtconfig-mode-badge.svg)](https://stable.melpa.org/#/mgmtconfig-mode) + +# `mgmtconfig-mode` + +[Mgmt](https://github.com/purpleidea/mgmt/) is a distributed, event-driven, parallel configuration management tool. + +`mgmtconfig-mode` is an Emacs major mode for editing the [mgmt language](https://purpleidea.com/blog/2018/02/05/mgmt-configuration-language/). + +## Installation + +See the MELPA Emacs Lisp package archive’s [getting started](https://melpa.org/#/getting-started) guide. Then, select “Options → Manage Emacs Packages” from the menu in Emacs. diff --git a/misc/emacs/mgmtconfig-mode.el b/misc/emacs/mgmtconfig-mode.el new file mode 100644 index 00000000..1ac1ed02 --- /dev/null +++ b/misc/emacs/mgmtconfig-mode.el @@ -0,0 +1,131 @@ +;;; mgmtconfig-mode.el --- mgmt configuration management language + +;; Copyright (C) 2013-2018+ James Shubin and the project contributors +;; Written by James Shubin and the project contributors +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;; Author: Peter Oliver +;; Maintainer: Mgmt contributors +;; Keywords: languages +;; URL: https://github.com/purpleidea/mgmt/misc/emacs +;; Package-Requires: ((emacs "24.3")) + +;;; Commentary: +;; +;; Major mode for editing the mgmt config language. Mgmt is a +;; distributed, event-driven, parallel configuration management tool. +;; +;; https://github.com/purpleidea/mgmt + +;;; Code: + +(require 'smie) + +(defconst mgmtconfig-smie-grammar + (smie-prec2->grammar + (smie-bnf->prec2 + '((map ("{" pairs "}")) + (pairs (pair) (pair "," pairs)) + (pair (key "=>" value)) + (key) + (value))))) + +(defun mgmtconfig-smie-rules (method token) + "Rules for indenting the mgmt language. +METHOD and TOKEN are as for `smie-rules-function'." + (pcase (cons method token) + ;; Statements in mgmt end at the end of a line. This causes SMIE + ;; not to indent every line as if it were a continuation of the + ;; statement on the previous line: + (`(:list-intro . ,_) t))) + +(defconst mgmtconfig-mode-syntax-table + (let ((st (make-syntax-table))) + (modify-syntax-entry ?# "<" st) + (modify-syntax-entry ?\n ">" st) + st)) + +(defconst mgmtconfig-mode-highlights + ;; Keywords and types cribbed from + ;; https://github.com/purpleidea/mgmt/blob/master/lang/lexer.nex. + ;; Resources from + ;; https://github.com/purpleidea/mgmt/tree/master/resources. + `((,(regexp-opt (list "if" + "else" + "in" + "true" + "false") + 'words) + . font-lock-keyword-face) + (,(concat "^\\s-*" (regexp-opt (list "actions" + "augeas" + "autoedge" + "autogroup" + "aws_ec2" + "edge" + "exec" + "file" + "graph" + "group" + "hostname" + "interfaces" + "kv" + "metaparams" + "mgraph" + "msg" + "noop" + "nspawn" + "password" + "pkg" + "print" + "refresh" + "resources" + "semaphore" + "sendrecv" + "svc" + "timer" + "uid" + "user" + "util" + "virt") + 'words)) + . font-lock-builtin-face) + (,(regexp-opt (list "bool" + "str" + "int" + "float" + "struct" + "variant") + 'words) + . font-lock-type-face) + ("\\$\\w+" . font-lock-variable-name-face))) + +;;;###autoload +(define-derived-mode mgmtconfig-mode prog-mode "mgmt" + "Major mode for editing the mgmt config language." + + (setq-local comment-start "# ") + (setq-local comment-start-skip "#+\\s-*") + + (setq font-lock-defaults '(mgmtconfig-mode-highlights)) + + (smie-setup mgmtconfig-smie-grammar #'mgmtconfig-smie-rules)) + +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.mcl\\'" . mgmtconfig-mode)) + +(provide 'mgmtconfig-mode) + +;;; mgmtconfig-mode.el ends here