]> gitweb.factorcode.org Git - factor.git/commitdiff
Indentation in Emacs factor-mode: customizable width and no tabs.
authorJose A. Ortega Ruiz <jao@gnu.org>
Sun, 16 Nov 2008 15:21:47 +0000 (16:21 +0100)
committerJose A. Ortega Ruiz <jao@gnu.org>
Sun, 16 Nov 2008 15:21:47 +0000 (16:21 +0100)
misc/factor.el

index b25493dd5e3065ca2ae25bf5782ce592846648b7..2d222187e49ccefc6f5c2fc4c6d719c5cd227bf3 100644 (file)
 
 ;; M-x run-factor === Start a Factor listener inside Emacs
 
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Customization
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defgroup factor nil
   "Factor mode"
   :group 'languages)
 
-(defvar factor-mode-syntax-table nil
-  "Syntax table used while in Factor mode.")
+(defcustom factor-default-indent-width 4
+  "Default indentantion width for factor-mode.
+
+This value will be used for the local variable
+`factor-indent-width' in new factor buffers. For existing code,
+we first check if `factor-indent-width' is set explicitly in a
+local variable section or line (e.g. '! -*- factor-indent-witdth: 2 -*-').
+If that's not the case, `factor-mode' tries to infer its correct
+value from the existing code in the buffer."
+  :type 'integer
+  :group 'factor)
 
 (defcustom factor-display-compilation-output t
   "Display the REPL buffer before compiling files."
   :type '(choice (const :tag "Enable" t) (const :tag "Disable" nil))
   :group 'factor)
 
+(defcustom factor-mode-hook nil
+  "Hook run when entering Factor mode."
+  :type 'hook
+  :group 'factor)
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; factor-mode syntax
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+(defvar factor-mode-syntax-table nil
+  "Syntax table used while in Factor mode.")
+
 (if factor-mode-syntax-table
     ()
   (let ((i 0))
     (modify-syntax-entry ?\) ")(" factor-mode-syntax-table)
     (modify-syntax-entry ?\" "\"    " factor-mode-syntax-table)))
 
-(defcustom factor-mode-hook nil
-  "Hook run when entering Factor mode."
-  :type 'hook
-  :group 'factor)
-
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; factor-mode font lock
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                 "initial:" "inline" "parsing" "read-only" "recursive")
               'words))
 
-(defun factor--regex-second-word (prefixes)
+(defsubst factor--regex-second-word (prefixes)
   (format "^%s +\\([^ \r\n]+\\)" (regexp-opt prefixes t)))
 
 (defconst factor--regex-word-definition
 ;; factor-mode indentation
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun factor-indent-line ()
-  "Indent current line as Factor code"
-  (indent-line-to (+ (current-indentation) 4)))
-
 (defconst factor-word-starting-keywords
   '("" ":" "TUPLE" "MACRO" "MACRO:" "M"))
 
     "^\\(%s\\): "
     (mapconcat 'identity ,keywords "\\|")))
 
+(defvar factor-indent-width factor-default-indent-width
+  "Indentation width in factor buffers. A local variable.")
+
+(make-variable-buffer-local 'factor-indent-width)
+
+(defun factor--guess-indent-width ()
+  "Chooses an indentation value from existing code."
+  (let ((word-def (factor-word-start-re factor-word-starting-keywords))
+        (word-cont "^ +[^ ]")
+        (iw))
+    (save-excursion
+      (beginning-of-buffer)
+      (while (not iw)
+        (if (not (re-search-forward word-def nil t))
+            (setq iw factor-default-indent-width)
+          (forward-line)
+          (when (looking-at word-cont)
+            (setq iw (current-indentation))))))
+    iw))
+
 (defun factor-calculate-indentation ()
   "Calculate Factor indentation for line at point."
   (let ((not-indented t)
               (let ((cur-depth (factor-brackets-depth)))
                 (forward-line -1)
                 (setq cur-indent (+ (current-indentation)
-                                    (* default-tab-width
+                                    (* factor-indent-width
                                        (- cur-depth (factor-brackets-depth)))))
                 (setq not-indented nil)))
             (forward-line -1)
               ;; Check that we are after the end of previous word
               (if (looking-at ".*;[ \t]*$")
                   (progn
-                    (setq cur-indent (- (current-indentation) default-tab-width))
+                    (setq cur-indent (- (current-indentation) factor-indent-width))
                     (setq not-indented nil))
                 ;; Check that we are after the start of word
                 (if (looking-at (factor-word-start-re factor-word-starting-keywords))
 ;                (if (looking-at "^[A-Z:]*: ")
                     (progn
                       (message "inword")
-                      (setq cur-indent (+ (current-indentation) default-tab-width))
+                      (setq cur-indent (+ (current-indentation) factor-indent-width))
                       (setq not-indented nil))
                   (if (bobp)
                       (setq not-indented nil))))))))
   (setq major-mode 'factor-mode)
   (setq mode-name "Factor")
   (set (make-local-variable 'indent-line-function) #'factor-indent-line)
-  (make-local-variable 'comment-start)
-  (setq comment-start "! ")
-  (make-local-variable 'font-lock-defaults)
-  (setq font-lock-defaults
-        '(factor-font-lock-keywords t nil nil nil))
+  (set (make-local-variable 'comment-start) "! ")
+  (set (make-local-variable 'font-lock-defaults)
+       '(factor-font-lock-keywords t nil nil nil))
   (set-syntax-table factor-mode-syntax-table)
-  (make-local-variable 'indent-line-function)
-  (setq indent-line-function 'factor-indent-line)
+  (set (make-local-variable 'indent-line-function) 'factor-indent-line)
+  (setq factor-indent-width (factor--guess-indent-width))
+  (setq indent-tabs-mode nil)
   (run-hooks 'factor-mode-hook))
 
 (add-to-list 'auto-mode-alist '("\\.factor\\'" . factor-mode))