From da6645e7d75065e170126785335a1de03afd7dff Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Tue, 28 Mar 2023 18:46:05 +0300 Subject: [PATCH 1/2] ninja-mode.el: fix variables highlighting The code previously did not take into account that between the name and assignment may be any number of space including no space at all. It was also incorrectly highlighting in a code like foo = bar = buzz the `bar` as a variable, even though the `bar = buzz` is just a text that gets assigned to `foo`, i.e. `bar` is not a variable. Fix that. --- misc/ninja-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/ninja-mode.el b/misc/ninja-mode.el index 8b975d5156..76abf811f5 100644 --- a/misc/ninja-mode.el +++ b/misc/ninja-mode.el @@ -28,7 +28,7 @@ "pool" "default") 'words)) . font-lock-keyword-face) - ("\\([[:alnum:]_]+\\) =" 1 font-lock-variable-name-face) + ("^[[:space:]]*\\([[:alnum:]_]+\\)[[:space:]]*=" 1 font-lock-variable-name-face) ;; Variable expansion. ("$[[:alnum:]_]+" . font-lock-variable-name-face) ("${[[:alnum:]._]+}" . font-lock-variable-name-face) From 74642c5a6fd68ae71545796f3f7a7ee3e641a2f7 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Tue, 28 Mar 2023 18:50:18 +0300 Subject: [PATCH 2/2] ninja-mode.el: add support for indentation We default `ninja-indent-offset` to `2` because Meson and CMake use `1` and `2` values accordingly, but `1` seems like too little, so use `2`. The correctness was tested in particular on two `build.ninja` files, one generated by Meson (1790 lines), and another by CMake (7777 lines). After setting `ninja-indent-offset` to the expected by the file value and re-indenting whole file the buffer was left unchanged, i.e. the calculated offset matched the ones already used. --- misc/ninja-mode.el | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/misc/ninja-mode.el b/misc/ninja-mode.el index 76abf811f5..d4f06e693f 100644 --- a/misc/ninja-mode.el +++ b/misc/ninja-mode.el @@ -19,15 +19,21 @@ ;;; Commentary: ;; Simple emacs mode for editing .ninja files. -;; Just some syntax highlighting for now. ;;; Code: +(defcustom ninja-indent-offset 2 + "*Amount of offset per level of indentation." + :type 'integer + :safe 'natnump + :group 'ninja) + +(defconst ninja-keywords-re + (concat "^" (regexp-opt '("rule" "build" "subninja" "include" "pool" "default") + 'words))) + (defvar ninja-keywords - `((,(concat "^" (regexp-opt '("rule" "build" "subninja" "include" - "pool" "default") - 'words)) - . font-lock-keyword-face) + `((,ninja-keywords-re . font-lock-keyword-face) ("^[[:space:]]*\\([[:alnum:]_]+\\)[[:space:]]*=" 1 font-lock-variable-name-face) ;; Variable expansion. ("$[[:alnum:]_]+" . font-lock-variable-name-face) @@ -69,11 +75,30 @@ (unless (= line-end (1+ (buffer-size))) (put-text-property line-end (1+ line-end) 'syntax-table '(12))))))))) +(defun ninja-compute-indentation () + "Calculate indentation for the current line." + (save-excursion + (beginning-of-line) + (if (or (looking-at ninja-keywords-re) + (= (line-number-at-pos) 1)) + 0 + (forward-line -1) + (if (looking-at ninja-keywords-re) + ninja-indent-offset + (current-indentation))))) + +(defun ninja-indent-line () + "Indent the current line. Uses previous indentation level if + available or `ninja-indent-offset'" + (interactive "*") + (indent-line-to (ninja-compute-indentation))) + ;;;###autoload (define-derived-mode ninja-mode prog-mode "ninja" (set (make-local-variable 'comment-start) "#") (set (make-local-variable 'parse-sexp-lookup-properties) t) (set (make-local-variable 'syntax-propertize-function) #'ninja-syntax-propertize) + (set (make-local-variable 'indent-line-function) 'ninja-indent-line) (setq font-lock-defaults '(ninja-keywords))) ;; Run ninja-mode for files ending in .ninja.