branch: scratch/editorconfig
commit 583bcb13dfa9e59d128e0b0aa29fb34b1e25e48a
Author: Stefan Monnier <monn...@iro.umontreal.ca>
Commit: Stefan Monnier <monn...@iro.umontreal.ca>

    (editorconfig-indentation-alist): Make it more declarative
    
    Make the functions in `editorconfig-indentation-alist` return the list
    of (VAR . VAL) to set rather than letting them set the vars directly.
    This makes it possible to obey `editorconfig--should-set` for those
    vars, and more importantly makes it usable within for Emacs's
    hack-dir-local system where we manipulate such lists of settings
    before we apply them.
---
 editorconfig.el | 75 +++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 49 insertions(+), 26 deletions(-)

diff --git a/editorconfig.el b/editorconfig.el
index 6cbc76a5d7..12874d670c 100644
--- a/editorconfig.el
+++ b/editorconfig.el
@@ -38,6 +38,11 @@
 ;; EditorConfig files are easily readable and they work nicely with
 ;; version control systems.
 
+;; News:
+
+;; In `editorconfig-indentation-alist', if a mode is associated to a function
+;; that function should not set the vars but should instead *return* them.
+
 ;;; Code:
 
 (require 'cl-lib)
@@ -244,7 +249,7 @@ This hook will be run even when there are no matching 
sections in
     (julia-mode julia-indent-offset)
     (kotlin-mode kotlin-tab-width)
     (kotlin-ts-mode kotlin-ts-mode-indent-offset)
-    (latex-mode . editorconfig-set-indentation-latex-mode)
+    (latex-mode . editorconfig--indentation-latex-mode)
     (lisp-mode lisp-indent-offset)
     (livescript-mode livescript-tab-width)
     (lua-mode lua-indent-level)
@@ -272,8 +277,8 @@ This hook will be run even when there are no matching 
sections in
     (ps-mode ps-mode-tab)
     (pug-mode pug-tab-width)
     (puppet-mode puppet-indent-level)
-    (python-mode . editorconfig-set-indentation-python-mode)
-    (python-ts-mode . editorconfig-set-indentation-python-mode)
+    (python-mode . editorconfig--indentation-python-mode)
+    (python-ts-mode . editorconfig--indentation-python-mode)
     (rjsx-mode js-indent-level sgml-basic-offset)
     (ruby-mode ruby-indent-level)
     (ruby-ts-mode ruby-indent-level)
@@ -319,7 +324,8 @@ This hook will be run even when there are no matching 
sections in
 Each element looks like (MODE . FUNCTION) or (MODE . INDENT-SPEC-LIST).
 
 If FUNCTION is provided, it will be called when setting the
-indentation.  The indent size will be passed.
+indentation.  The indent size will be passed and it should return
+a list of settings of the form (VAR . VAL).
 
 If INDENT-SPEC-LIST is provided, each element of it must have one of the
 following forms:
@@ -426,26 +432,21 @@ Make a message by passing ARGS to `format-message'."
   (and (stringp string)
        (string-match-p "\\`[0-9]+\\'" string)))
 
-(defun editorconfig-set-indentation-python-mode (size)
-  "Set `python-mode' indent size to SIZE."
-  (when (boundp 'python-indent-offset)
-    (setq-local python-indent-offset size))
-  ;; For https://gitlab.com/python-mode-devs/python-mode
-  (when (boundp 'py-indent-offset)
-    (setq-local py-indent-offset size)))
-
-(defun editorconfig-set-indentation-latex-mode (size)
-  "Set `latex-mode' indent size to SIZE."
-  (setq-local tex-indent-basic size)
-  (setq-local tex-indent-item size)
-  (setq-local tex-indent-arg (* 2 size))
-  ;; For AUCTeX
-  (when (boundp 'TeX-brace-indent-level)
-    (setq-local TeX-brace-indent-level size))
-  (when (boundp 'LaTeX-indent-level)
-    (setq-local LaTeX-indent-level size))
-  (when (boundp 'LaTeX-item-indent)
-    (setq-local LaTeX-item-indent (- size))))
+(defun editorconfig--indentation-python-mode (size)
+  "Var to set `python-mode' indent size to SIZE."
+  `((python-indent-offset . ,size)
+    ;; For https://gitlab.com/python-mode-devs/python-mode
+    (py-indent-offset . ,size)))
+
+(defun editorconfig--indentation-latex-mode (size)
+  "Vars to set `latex-mode' indent size to SIZE."
+  `((tex-indent-basic . ,size)
+    (tex-indent-item . ,size)
+    (tex-indent-arg . ,(* 2 size))
+    ;; For AUCTeX
+    (TeX-brace-indent-level . ,size)
+    (LaTeX-indent-level . ,size)
+    (LaTeX-item-indent . ,(- size))))
 
 (cl-defun editorconfig--should-set (symbol &optional size)
   "Determine if editorconfig should set SYMBOL.
@@ -516,7 +517,10 @@ See `editorconfig-lisp-use-default-indent' for details."
                   (setq parent (get parent 'derived-mode-parent))))
       (when entry
         (let ((fn-or-list (cdr entry)))
-          (cond ((functionp fn-or-list) (funcall fn-or-list size))
+          (cond ((functionp fn-or-list)
+                 (pcase-dolist (`(,var . ,val) (funcall fn-or-list size))
+                   (when (editorconfig--should-set var size)
+                     (set (make-local-variable var) val))))
                 ((listp fn-or-list)
                  (dolist (elem fn-or-list)
                    (cond ((and (symbolp elem)
@@ -865,7 +869,26 @@ F is that function, and FILENAME and ARGS are arguments 
passed to F."
 (defvar editorconfig-indent-vars-function
   ;; FIXME: Obey `editorconfig-indentation-alist' as best as we can?
   ;; Set `smie-indent-basic' if all else fails?
-  #'ignore)
+  ;; FIXME: Change `editorconfig-indentation-alist' so that the functions
+  ;; therein return an list of (VAR . VAL) instead of setting the vars 
directly.
+  #'editorconfig--get-indent-vars)
+
+(defun editorconfig--get-indent-vars (size)
+  (let ((parents (derived-mode-all-parents major-mode))
+        (entry ()))
+    (while (and parents (not entry))
+      (setq entry (assq (pop parents) editorconfig-indentation-alist)))
+    (if (functionp (cdr entry))
+        (funcall (cdr entry))
+      (mapcar (lambda (elem)
+                (if (consp elem)
+                    (let ((spec (cdr elem)))
+                      (cons (car elem)
+                            (cond ((functionp spec) (funcall spec size))
+                                  ((integerp spec) (* spec size))
+                                  (t spec))))
+                  (cons elem size)))
+              (cdr entry)))))
 
 (defun editorconfig--get-dir-local-variables ()
   (when (and (stringp buffer-file-name)

Reply via email to