From 66180dfc333ced5112c1ecfc25b9aff76bd0222c Mon Sep 17 00:00:00 2001 From: cxxxr Date: Mon, 4 Nov 2024 23:56:48 +0900 Subject: [PATCH] add nix-mode --- extensions/nix-mode/indent.lisp | 22 +++++++++++ extensions/nix-mode/lem-nix-mode.asd | 5 +++ extensions/nix-mode/nix-mode.lisp | 59 ++++++++++++++++++++++++++++ lem.asd | 1 + 4 files changed, 87 insertions(+) create mode 100644 extensions/nix-mode/indent.lisp create mode 100644 extensions/nix-mode/lem-nix-mode.asd create mode 100644 extensions/nix-mode/nix-mode.lisp diff --git a/extensions/nix-mode/indent.lisp b/extensions/nix-mode/indent.lisp new file mode 100644 index 000000000..f3fd19d54 --- /dev/null +++ b/extensions/nix-mode/indent.lisp @@ -0,0 +1,22 @@ +(defpackage :lem-nix-mode/indent + (:use :cl + :lem + :lem/language-mode) + (:export :beginning-of-defun + :end-of-defun + :calc-indent)) +(in-package :lem-nix-mode/indent) + +(defun beginning-of-defun (point n) + (loop :repeat n :do (search-backward-regexp point "^\\{"))) + +(defun end-of-defun (point n) + (if (minusp n) + (beginning-of-defun point (- n)) + (search-forward-regexp point "^\\}"))) + +(defun calc-indent (point) + (with-point ((point point)) + (let ((tab-width (variable-value 'tab-width :default point)) + (column (point-column point))) + (+ column (- tab-width (rem column tab-width)))))) diff --git a/extensions/nix-mode/lem-nix-mode.asd b/extensions/nix-mode/lem-nix-mode.asd new file mode 100644 index 000000000..9a6c9b1be --- /dev/null +++ b/extensions/nix-mode/lem-nix-mode.asd @@ -0,0 +1,5 @@ +(defsystem "lem-nix-mode" + :depends-on ("lem") + :serial t + :components ((:file "indent") + (:file "nix-mode"))) diff --git a/extensions/nix-mode/nix-mode.lisp b/extensions/nix-mode/nix-mode.lisp new file mode 100644 index 000000000..2fc3e6111 --- /dev/null +++ b/extensions/nix-mode/nix-mode.lisp @@ -0,0 +1,59 @@ +(defpackage :lem-nix-mode + (:use :cl + :lem + :lem/language-mode + :lem/language-mode-tools) + (:local-nicknames (:indent :lem-nix-mode/indent)) + (:export :nix-mode)) +(in-package :lem-nix-mode) + +(defun tokens (boundary strings) + (let ((alternation + `(:alternation ,@(sort (copy-list strings) #'> :key #'length)))) + (if boundary + `(:sequence ,boundary ,alternation ,boundary) + alternation))) + +(defun make-tmlanguage-nix () + (let ((patterns (make-tm-patterns + (make-tm-region '(:sequence "#") "$" :name 'syntax-comment-attribute) + (make-tm-region '(:sequence "''") + '(:sequence "''") + :name 'syntax-string-attribute) + (make-tm-match (tokens :word-boundary + '("true" + "false" + "null")) + :name 'syntax-keyword-attribute) + (make-tm-string-region "''") + (make-tm-string-region "\"")))) + (make-tmlanguage :patterns patterns))) + +(defvar *syntax-table* + (let ((table (make-syntax-table + :space-chars '(#\space #\tab #\newline) + :symbol-chars '(#\_) + :paren-pairs '((#\( . #\)) + (#\{ . #\}) + (#\[ . #\])) + :string-quote-chars '(#\") + :block-string-pairs '(("''" . "''")) + :line-comment-string "#"))) + (set-syntax-parser table (make-tmlanguage-nix)) + table)) + +(define-major-mode nix-mode language-mode + (:name "Nix" + :keymap *nix-mode-keymap* + :syntax-table *syntax-table* + :mode-hook *nix-mode-hook*) + (setf (variable-value 'enable-syntax-highlight) t + (variable-value 'indent-tabs-mode) nil + (variable-value 'tab-width) 2 + (variable-value 'calc-indent-function) 'indent:calc-indent + (variable-value 'line-comment) "#" + (variable-value 'beginning-of-defun-function) 'indent:beginning-of-defun + (variable-value 'end-of-defun-function) 'indent:end-of-defun + )) + +(define-file-type ("nix") nix-mode) diff --git a/lem.asd b/lem.asd index 5348acaf3..ad1b01263 100644 --- a/lem.asd +++ b/lem.asd @@ -258,6 +258,7 @@ "lem-documentation-mode" "lem-elisp-mode" "lem-terraform-mode" + "lem-nix-mode" "lem-markdown-mode" "lem-color-preview" "lem-lua-mode"