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"
|
|
"GLSL-PROGRAM"
|
|
"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
|