101 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			EmacsLisp
		
	
	
;;; factor-smie.el --- Helper function for indenting factor code
 | 
						|
 | 
						|
;; Copyright (C) 2016  Björn Lindqvist
 | 
						|
;; See http://factorcode.org/license.txt for BSD license.
 | 
						|
 | 
						|
;;; Commentary:
 | 
						|
 | 
						|
;; Factor indentation using the SMIE framework.
 | 
						|
 | 
						|
;;; Code:
 | 
						|
(require 'smie)
 | 
						|
 | 
						|
(defcustom factor-block-offset 4
 | 
						|
  "Indentation of Factor statements."
 | 
						|
  :type 'integer
 | 
						|
  :safe 'integerp
 | 
						|
  :group 'factor)
 | 
						|
 | 
						|
;; These prefixes starts a definition and causes the indent-level to
 | 
						|
;; increase.
 | 
						|
(defconst factor-indent-def-starts
 | 
						|
  '("" ":"
 | 
						|
    "AFTER" "BEFORE"
 | 
						|
    "COM-INTERFACE" "CONSULT"
 | 
						|
    "ENUM" "ERROR"
 | 
						|
    "FROM"
 | 
						|
    "IDENTITY-MEMO"
 | 
						|
    "INTERSECTION"
 | 
						|
    "M" "M:" "MACRO" "MACRO:"
 | 
						|
    "MAIN-WINDOW" "MEMO" "MEMO:" "METHOD"
 | 
						|
    "SYNTAX"
 | 
						|
    "PREDICATE" "PROTOCOL"
 | 
						|
    "SINGLETONS"
 | 
						|
    "STRUCT" "SYMBOLS" "TAG" "TUPLE"
 | 
						|
    "TYPED" "TYPED:"
 | 
						|
    "UNIFORM-TUPLE"
 | 
						|
    "UNION-STRUCT" "UNION"
 | 
						|
    "VARIANT" "VERTEX-FORMAT"))
 | 
						|
 | 
						|
;; These prefixes starts a definition but does not cause the indent
 | 
						|
;; level to increase.
 | 
						|
(defconst factor-no-indent-def-starts
 | 
						|
  '("ARTICLE"
 | 
						|
    "FUNCTION" "FUNCTION-ALIAS"
 | 
						|
    "HELP"
 | 
						|
    "PRIMITIVE"
 | 
						|
    "SPECIALIZED-ARRAYS"))
 | 
						|
 | 
						|
(defconst factor-indent-def-regex
 | 
						|
  (format "^\\(%s:\\)$" (regexp-opt factor-indent-def-starts)))
 | 
						|
 | 
						|
(defconst factor-smie-grammar
 | 
						|
  (smie-prec2->grammar
 | 
						|
   (smie-bnf->prec2
 | 
						|
    '(
 | 
						|
      (exp (":" exp ";"))
 | 
						|
      ))))
 | 
						|
 | 
						|
(defun factor-smie-rules (kind token)
 | 
						|
  (pcase (cons kind token)
 | 
						|
    (`(:before . ";") factor-block-offset)
 | 
						|
    (`(:list-intro . ,_) t)
 | 
						|
    ))
 | 
						|
 | 
						|
(defun factor-smie-token (dir)
 | 
						|
  (pcase dir
 | 
						|
    (`forward (forward-comment (point-max)))
 | 
						|
    (`backward (forward-comment (- (point)))))
 | 
						|
  (let ((tok (buffer-substring-no-properties
 | 
						|
              (point)
 | 
						|
              (let ((syntax "w_\\\""))
 | 
						|
                (pcase dir
 | 
						|
                  (`forward (skip-syntax-forward syntax))
 | 
						|
                  (`backward (skip-syntax-backward syntax)))
 | 
						|
                (point)))))
 | 
						|
    ;; Token normalization. This way we only need one rule in
 | 
						|
    ;; factor-smie-grammar.
 | 
						|
    (cond ((string-match factor-indent-def-regex tok) ":")
 | 
						|
          (t tok))))
 | 
						|
 | 
						|
(defun factor-smie-forward-token ()
 | 
						|
  (factor-smie-token 'forward))
 | 
						|
 | 
						|
(defun factor-smie-backward-token ()
 | 
						|
  (factor-smie-token 'backward))
 | 
						|
 | 
						|
(defun factor-smie-indent ()
 | 
						|
  (unless (looking-at ";\\_>")
 | 
						|
    (save-excursion
 | 
						|
      (let ((x nil))
 | 
						|
        (while (progn (setq x (smie-backward-sexp))
 | 
						|
                      (null (car-safe x))))
 | 
						|
        (when (string-match factor-indent-def-regex
 | 
						|
                            (or (nth 2 x) ""))
 | 
						|
          (goto-char (nth 1 x))
 | 
						|
          (+ factor-block-offset (smie-indent-virtual)))))))
 | 
						|
 | 
						|
(provide 'factor-smie)
 | 
						|
 | 
						|
;;; factor-smie.el ends here
 |