2013-05-07 02:03:26 -04:00
|
|
|
|
;;; factor-mode.el --- Major mode for editing Factor programs.
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
;; Copyright (C) 2013 Erik Charlebois
|
2010-08-12 22:25:57 -04:00
|
|
|
|
;; Copyright (C) 2008, 2009, 2010 Jose Antonio Ortega Ruiz
|
2008-12-05 22:34:25 -05:00
|
|
|
|
;; See http://factorcode.org/license.txt for BSD license.
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
;; Maintainer: Erik Charlebois <erikcharlebois@gmail.com>
|
2008-12-05 22:34:25 -05:00
|
|
|
|
;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
|
2013-05-05 00:48:12 -04:00
|
|
|
|
;; Keywords: languages, factor
|
2008-12-05 22:34:25 -05:00
|
|
|
|
;; Start date: Tue Dec 02, 2008 21:32
|
|
|
|
|
|
2013-05-07 02:03:26 -04:00
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
|
|
;; A major mode for editing Factor programs. It provides indenting and
|
|
|
|
|
;; font-lock support.
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(require 'thingatpt)
|
|
|
|
|
(require 'font-lock)
|
2008-12-05 22:34:25 -05:00
|
|
|
|
(require 'ring)
|
2013-07-13 13:13:39 -04:00
|
|
|
|
(require 'fuel-base)
|
2016-07-01 21:24:46 -04:00
|
|
|
|
(require 'factor-smie)
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
|
|
|
|
;;; Customization:
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
;;;###autoload
|
|
|
|
|
(defgroup factor nil
|
2008-12-21 21:07:45 -05:00
|
|
|
|
"Major mode for Factor source code."
|
|
|
|
|
:group 'languages)
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defcustom factor-cycling-no-ask nil
|
|
|
|
|
"Whether to never create source/doc/tests file when cycling."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'factor)
|
2009-01-08 17:52:38 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defcustom factor-cycle-always-ask-p t
|
|
|
|
|
"Whether to always ask for file creation when cycling to a
|
|
|
|
|
source/docs/tests file. When set to false, you'll be asked only once."
|
2009-01-08 17:52:38 -05:00
|
|
|
|
:type 'boolean
|
2013-05-05 00:48:12 -04:00
|
|
|
|
:group 'factor)
|
2009-01-08 17:52:38 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defcustom factor-comment-column 32
|
|
|
|
|
"Indentation column of comments."
|
2008-12-05 22:34:25 -05:00
|
|
|
|
:type 'integer
|
2013-05-05 00:48:12 -04:00
|
|
|
|
:safe 'integerp
|
|
|
|
|
:group 'factor)
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2013-08-06 07:43:39 -04:00
|
|
|
|
(defcustom factor-mode-use-fuel t
|
|
|
|
|
"Whether to use the full FUEL facilities in factor mode.
|
|
|
|
|
|
|
|
|
|
Set this variable to nil if you just want to use Emacs as the
|
|
|
|
|
external editor of your Factor environment, e.g., by putting
|
|
|
|
|
these lines in your .emacs:
|
|
|
|
|
|
|
|
|
|
(add-to-list 'load-path \"/path/to/factor/misc/fuel\")
|
|
|
|
|
(setq factor-mode-use-fuel nil)
|
|
|
|
|
(require 'factor-mode)
|
|
|
|
|
"
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'factor)
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
;;; Faces:
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defgroup factor-faces nil
|
|
|
|
|
"Faces used by factor-mode."
|
|
|
|
|
:group 'factor
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-constructor '((t (:inherit font-lock-type-face)))
|
|
|
|
|
"Factor for constructor words."
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-constant '((t (:inherit font-lock-constant-face)))
|
|
|
|
|
"Face for constant and literal values."
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-number '((t (:inherit font-lock-constant-face)))
|
|
|
|
|
"Face for integer and floating-point constants."
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-ratio '((t (:inherit font-lock-constant-face)))
|
|
|
|
|
"Face for ratio constants."
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-parsing-word '((t (:inherit font-lock-keyword-face)))
|
|
|
|
|
"parsing words"
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-setter-word
|
|
|
|
|
'((t (:inherit font-lock-function-name-face)))
|
|
|
|
|
"setter words (>>foo)"
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-getter-word
|
|
|
|
|
'((t (:inherit font-lock-function-name-face)))
|
|
|
|
|
"getter words (foo>>)"
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-string '((t (:inherit font-lock-string-face)))
|
|
|
|
|
"strings"
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-symbol '((t (:inherit font-lock-variable-name-face)))
|
|
|
|
|
"name of symbol being defined"
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-type-name '((t (:inherit font-lock-type-face)))
|
|
|
|
|
"type names"
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-vocabulary-name
|
|
|
|
|
'((t (:inherit font-lock-constant-face)))
|
|
|
|
|
"vocabulary names"
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-word
|
|
|
|
|
'((t (:inherit font-lock-function-name-face)))
|
|
|
|
|
"Face for the word, generic or method being defined."
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-invalid-syntax
|
|
|
|
|
'((t (:inherit font-lock-warning-face)))
|
|
|
|
|
"syntactically invalid constructs"
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-comment '((t (:inherit font-lock-comment-face)))
|
|
|
|
|
"Face for Factor comments."
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
|
|
|
|
(defface factor-font-lock-stack-effect '((t :inherit font-lock-comment-face))
|
|
|
|
|
"Face for Factor stack effect declarations."
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2013-09-20 10:35:49 -04:00
|
|
|
|
(defface factor-font-lock-type-in-stack-effect '((t :inherit font-lock-comment-face
|
|
|
|
|
:bold t))
|
|
|
|
|
"Face for Factor types in stack effect declarations."
|
|
|
|
|
:group 'factor-faces
|
|
|
|
|
:group 'faces)
|
|
|
|
|
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
;;; Thing-at-point:
|
|
|
|
|
|
|
|
|
|
(defun factor-beginning-of-symbol ()
|
|
|
|
|
"Move point to the beginning of the current symbol."
|
2016-03-13 03:36:31 -04:00
|
|
|
|
(skip-syntax-backward "w_()\""))
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defun factor-end-of-symbol ()
|
|
|
|
|
"Move point to the end of the current symbol."
|
2016-03-13 03:36:31 -04:00
|
|
|
|
(skip-syntax-forward "w_()\""))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2016-03-27 18:17:01 -04:00
|
|
|
|
(put 'factor-symbol 'end-op 'factor-end-of-symbol)
|
|
|
|
|
(put 'factor-symbol 'beginning-op 'factor-beginning-of-symbol)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2016-03-13 03:36:31 -04:00
|
|
|
|
(defun factor-symbol-at-point ()
|
2016-03-27 18:17:01 -04:00
|
|
|
|
(let ((thing (thing-at-point 'factor-symbol t)))
|
2016-03-13 03:36:31 -04:00
|
|
|
|
(and (> (length thing) 0) thing)))
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
;;; Regexps galore:
|
|
|
|
|
|
2013-09-20 08:09:10 -04:00
|
|
|
|
;; Utility regexp used by other regexps to match a Factor symbol name
|
2016-07-01 21:28:19 -04:00
|
|
|
|
(setq-local symbol-nc "\\(?:\\sw\\|\\s_\\|\"\\|\\s(\\|\\s)\\|\\s\\\\)+")
|
2016-06-29 20:42:23 -04:00
|
|
|
|
(setq-local symbol (format "\\(%s\\)" symbol-nc))
|
2016-08-19 21:41:51 -04:00
|
|
|
|
(setq-local c-symbol-nc "\\(?:\\sw\\|\\s_\\|\\[\\|\\]\\)+")
|
|
|
|
|
(setq-local c-symbol (format "\\(%s\\)" c-symbol-nc))
|
2015-07-12 20:04:27 -04:00
|
|
|
|
(setq-local ws+ "[ \n\t]+")
|
|
|
|
|
(setq-local symbols-to-semicolon "\\([^;\t]*\\)\\(;\\)")
|
|
|
|
|
|
|
|
|
|
(defun one-symbol (content)
|
|
|
|
|
(concat "\\_<\\(" content "\\)\\_>"))
|
|
|
|
|
|
|
|
|
|
(defun syntax-begin (content)
|
|
|
|
|
(one-symbol (concat (regexp-opt content) ":")))
|
|
|
|
|
|
2015-08-04 20:28:07 -04:00
|
|
|
|
(defun syntax-and-1-symbol (prefixes)
|
2015-07-12 20:04:27 -04:00
|
|
|
|
(concat (syntax-begin prefixes) ws+ symbol))
|
2013-09-20 08:09:10 -04:00
|
|
|
|
|
2015-08-04 20:28:07 -04:00
|
|
|
|
(defun syntax-and-2-symbols (prefixes)
|
2015-08-05 07:57:53 -04:00
|
|
|
|
(concat (syntax-and-1-symbol prefixes) ws+ symbol))
|
2015-08-04 20:28:07 -04:00
|
|
|
|
|
2013-12-01 08:37:23 -05:00
|
|
|
|
;; Used to font-lock stack effect declarations with may be nested.
|
|
|
|
|
(defun factor-match-brackets (limit)
|
|
|
|
|
(let ((start (point)))
|
|
|
|
|
(when (re-search-forward "[ \n]([ \n]" limit t)
|
|
|
|
|
(backward-char 2)
|
|
|
|
|
(let ((bracket-start (point)))
|
2013-12-03 09:47:40 -05:00
|
|
|
|
(when (condition-case nil
|
|
|
|
|
(progn (forward-sexp) 't)
|
|
|
|
|
('scan-error nil))
|
|
|
|
|
(let ((bracket-stop (point)))
|
|
|
|
|
(goto-char bracket-start)
|
2015-08-04 19:41:33 -04:00
|
|
|
|
(re-search-forward "\\(.\\|\n\\)+" bracket-stop 'mv)))))))
|
2013-12-01 08:37:23 -05:00
|
|
|
|
|
2013-08-05 12:39:11 -04:00
|
|
|
|
;; Excludes parsing words that are handled by other regexps
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defconst factor-parsing-words
|
2015-07-12 19:30:59 -04:00
|
|
|
|
'(":" "::" ";" ":>" "&:" "<<" "<PRIVATE" ">>"
|
2015-08-05 10:58:27 -04:00
|
|
|
|
"ABOUT:" "ARTICLE:"
|
|
|
|
|
"B"
|
2013-05-05 00:48:12 -04:00
|
|
|
|
"CONSULT:" "call-next-method"
|
2016-08-25 05:54:28 -04:00
|
|
|
|
";EBNF"
|
2013-12-01 08:17:14 -05:00
|
|
|
|
"FOREIGN-ATOMIC-TYPE:" "FOREIGN-ENUM-TYPE:" "FOREIGN-RECORD-TYPE:" "FUNCTION-ALIAS:"
|
2016-08-25 05:54:28 -04:00
|
|
|
|
";FUNCTOR"
|
2015-10-28 19:44:08 -04:00
|
|
|
|
"GIR:"
|
2013-05-05 00:48:12 -04:00
|
|
|
|
"GLSL-SHADER:" "GLSL-PROGRAM:"
|
2016-03-11 01:36:23 -05:00
|
|
|
|
"initial:" "IMPLEMENT-STRUCTS:"
|
2015-12-04 06:43:01 -05:00
|
|
|
|
"MATH:"
|
2015-10-14 20:41:40 -04:00
|
|
|
|
"METHOD:"
|
2015-08-05 07:57:53 -04:00
|
|
|
|
"PRIVATE>" "PROTOCOL:" "PROVIDE:"
|
2016-03-11 01:36:23 -05:00
|
|
|
|
"read-only"
|
|
|
|
|
"STRING:" "SYNTAX:"
|
2015-06-07 18:59:12 -04:00
|
|
|
|
"UNIFORM-TUPLE:"
|
2013-05-05 00:48:12 -04:00
|
|
|
|
"VARIANT:" "VERTEX-FORMAT:"))
|
|
|
|
|
|
|
|
|
|
(defconst factor-parsing-words-regex
|
2015-07-12 20:04:27 -04:00
|
|
|
|
(format "\\(?:^\\| \\)%s" (regexp-opt factor-parsing-words 'symbols)))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-constant-words
|
|
|
|
|
'("f" "t"))
|
|
|
|
|
|
|
|
|
|
(defconst factor-constant-words-regex
|
|
|
|
|
(regexp-opt factor-constant-words 'symbols))
|
|
|
|
|
|
|
|
|
|
(defconst factor-bracer-words
|
2016-08-19 21:41:51 -04:00
|
|
|
|
'("B" "BV" "C" "CS" "HEX" "H" "HS" "S" "T" "V" "W" "flags"))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-brace-words-regex
|
|
|
|
|
(format "%s{" (regexp-opt factor-bracer-words t)))
|
|
|
|
|
|
|
|
|
|
(defconst factor-declaration-words
|
2014-04-17 20:47:28 -04:00
|
|
|
|
'("deprecated"
|
2015-10-14 20:41:40 -04:00
|
|
|
|
"final"
|
2014-04-17 20:47:28 -04:00
|
|
|
|
"flushable"
|
|
|
|
|
"foldable"
|
|
|
|
|
"inline"
|
|
|
|
|
"parsing"
|
|
|
|
|
"recursive"
|
|
|
|
|
"delimiter"))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-declaration-words-regex
|
|
|
|
|
(regexp-opt factor-declaration-words 'symbols))
|
|
|
|
|
|
|
|
|
|
(defconst factor-integer-regex
|
2016-05-25 16:03:05 -04:00
|
|
|
|
(one-symbol "-?\\(?:0[xob][0-9a-fA-F][0-9a-fA-F,]*\\|[0-9][0-9,]*\\)"))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-raw-float-regex
|
|
|
|
|
"[0-9]*\\.[0-9]*\\([eEpP][+-]?[0-9]+\\)?")
|
|
|
|
|
|
|
|
|
|
(defconst factor-float-regex
|
|
|
|
|
(format "\\_<-?%s\\_>" factor-raw-float-regex))
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defconst factor-number-regex
|
|
|
|
|
(format "\\([0-9]+\\|%s\\)" factor-raw-float-regex))
|
|
|
|
|
|
|
|
|
|
(defconst factor-ratio-regex
|
|
|
|
|
(format "\\_<[+-]?%s/-?%s\\_>" factor-number-regex factor-number-regex))
|
|
|
|
|
|
|
|
|
|
(defconst factor-bad-string-regex
|
|
|
|
|
"\\_<\"[^>]\\([^\"\n]\\|\\\\\"\\)*\n")
|
|
|
|
|
|
|
|
|
|
(defconst factor-word-definition-regex
|
2015-08-05 07:57:53 -04:00
|
|
|
|
(concat
|
2016-07-02 09:27:33 -04:00
|
|
|
|
(one-symbol (regexp-opt
|
2017-06-01 15:05:15 -04:00
|
|
|
|
'(":" "::" "GENERIC:" "GENERIC#:" "DEFER:" "HOOK:"
|
2016-08-25 05:54:28 -04:00
|
|
|
|
"IDENTITY-MEMO:" "MACRO:" "MACRO::" "MATH:" "MEMO:" "MEMO::"
|
2016-07-02 09:27:33 -04:00
|
|
|
|
"POSTPONE:" "PRIMITIVE:" "SYNTAX:" "TYPED:" "TYPED::")))
|
2015-08-05 07:57:53 -04:00
|
|
|
|
ws+ symbol))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2016-07-02 09:27:33 -04:00
|
|
|
|
(defconst factor-method-definition-regex
|
|
|
|
|
(syntax-and-2-symbols '("M" "M:" "BEFORE" "AFTER")))
|
|
|
|
|
|
2015-06-07 18:59:12 -04:00
|
|
|
|
;; [parsing-word] [vocab-word]
|
2013-08-05 12:39:11 -04:00
|
|
|
|
(defconst factor-vocab-ref-regex
|
2015-08-05 07:57:53 -04:00
|
|
|
|
(syntax-and-1-symbol '("IN" "USE" "QUALIFIED")))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2015-07-12 20:04:27 -04:00
|
|
|
|
(defconst factor-using-lines-regex
|
|
|
|
|
(concat (syntax-begin '("USING")) ws+ symbols-to-semicolon))
|
2013-08-05 12:39:11 -04:00
|
|
|
|
|
2015-06-07 18:59:12 -04:00
|
|
|
|
;; [parsing-word] [symbol-word]
|
2013-12-03 09:28:21 -05:00
|
|
|
|
(defconst factor-symbol-definition-regex
|
2015-08-04 20:28:07 -04:00
|
|
|
|
(syntax-and-1-symbol
|
2016-08-25 05:54:28 -04:00
|
|
|
|
'("&" "CONSTANT" "DESTRUCTOR" "EBNF" "FORGET" "FUNCTOR"
|
|
|
|
|
"GAME" "HELP" "LIBRARY" "MAIN" "MAIN-WINDOW" "SLOT" "STRING"
|
|
|
|
|
"SYMBOL" "VAR")))
|
2013-12-03 09:28:21 -05:00
|
|
|
|
|
2015-06-07 18:59:12 -04:00
|
|
|
|
;; [parsing-word] [symbol-word]* ;
|
2015-07-12 20:04:27 -04:00
|
|
|
|
(defconst factor-symbols-lines-regex
|
|
|
|
|
(concat (syntax-begin '("SYMBOLS")) ws+ symbols-to-semicolon))
|
2013-12-03 09:28:21 -05:00
|
|
|
|
|
2015-10-28 19:44:08 -04:00
|
|
|
|
(defconst factor-types-lines-regex
|
2016-03-11 01:36:23 -05:00
|
|
|
|
(concat
|
|
|
|
|
(syntax-begin '("INTERSECTION" "SINGLETONS" "SPECIALIZED-ARRAYS"))
|
|
|
|
|
ws+ symbols-to-semicolon))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-type-definition-regex
|
2015-08-04 20:28:07 -04:00
|
|
|
|
(syntax-and-1-symbol
|
2015-10-14 20:41:40 -04:00
|
|
|
|
'("COM-INTERFACE" "C-TYPE" "MIXIN" "SINGLETON" "SPECIALIZED-ARRAY"
|
|
|
|
|
"TUPLE-ARRAY")))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-constructor-regex
|
2015-08-05 10:58:27 -04:00
|
|
|
|
(one-symbol "<[^ >]+>"))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-getter-regex
|
2016-06-29 20:42:23 -04:00
|
|
|
|
(one-symbol (concat symbol-nc ">>")))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-setter-regex
|
2016-06-29 20:42:23 -04:00
|
|
|
|
(one-symbol (format ">>%s\\|%s<<" symbol-nc symbol-nc)))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-stack-effect-regex
|
2013-09-20 10:35:49 -04:00
|
|
|
|
"\\( ( [^)]* )\\)\\|\\( (( [^)]* ))\\)")
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-use-line-regex "^USE: +\\(.*\\)$")
|
|
|
|
|
|
|
|
|
|
(defconst factor-current-vocab-regex "^IN: +\\([^ \r\n\f]+\\)")
|
|
|
|
|
|
|
|
|
|
(defconst factor-sub-vocab-regex "^<\\([^ \n]+\\) *$")
|
|
|
|
|
|
|
|
|
|
(defconst factor-definition-start-regex
|
|
|
|
|
(format "^\\(%s:\\) " (regexp-opt (append factor-no-indent-def-starts
|
|
|
|
|
factor-indent-def-starts))))
|
|
|
|
|
|
|
|
|
|
(defconst factor-single-liner-regex
|
|
|
|
|
(regexp-opt '("ABOUT:"
|
|
|
|
|
"ALIAS:"
|
2015-04-24 05:40:06 -04:00
|
|
|
|
"CONSTANT:" "C-GLOBAL:" "C-TYPE:"
|
2013-05-05 00:48:12 -04:00
|
|
|
|
"DEFER:" "DESTRUCTOR:"
|
|
|
|
|
"FORGET:"
|
2017-06-01 15:05:15 -04:00
|
|
|
|
"GAME:" "GENERIC:" "GENERIC#:" "GLSL-PROGRAM:"
|
2013-05-05 00:48:12 -04:00
|
|
|
|
"HOOK:"
|
|
|
|
|
"IN:" "INSTANCE:"
|
|
|
|
|
"LIBRARY:"
|
|
|
|
|
"MAIN:" "MATH:" "MIXIN:"
|
|
|
|
|
"NAN:"
|
|
|
|
|
"POSTPONE:" "PRIVATE>" "<PRIVATE"
|
|
|
|
|
"QUALIFIED-WITH:" "QUALIFIED:"
|
|
|
|
|
"RENAME:"
|
2013-08-05 12:39:11 -04:00
|
|
|
|
"SINGLETON:" "SLOT:" "SPECIALIZED-ARRAY:"
|
2013-05-05 00:48:12 -04:00
|
|
|
|
"TYPEDEF:"
|
2013-08-05 12:39:11 -04:00
|
|
|
|
"USE:")))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-begin-of-def-regex
|
|
|
|
|
(format "^USING: \\|\\(%s\\)\\|\\(^%s .*\\)"
|
|
|
|
|
factor-definition-start-regex
|
|
|
|
|
factor-single-liner-regex))
|
|
|
|
|
|
2016-06-18 21:23:35 -04:00
|
|
|
|
(defconst factor-definition-end-regex
|
|
|
|
|
(format "\\(^\\| +\\);\\( *%s\\)*\\($\\| +\\)"
|
|
|
|
|
factor-declaration-words-regex))
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defconst factor-end-of-def-regex
|
2016-06-26 07:36:03 -04:00
|
|
|
|
(format "^.*%s\\|^%s .*"
|
|
|
|
|
factor-definition-end-regex
|
2013-05-05 00:48:12 -04:00
|
|
|
|
factor-single-liner-regex))
|
|
|
|
|
|
|
|
|
|
(defconst factor-word-signature-regex
|
|
|
|
|
(format ":[^ ]* \\([^ ]+\\)\\(%s\\)*" factor-stack-effect-regex))
|
|
|
|
|
|
|
|
|
|
(defconst factor-defun-signature-regex
|
|
|
|
|
(format "\\(%s\\|%s\\)"
|
|
|
|
|
factor-word-signature-regex
|
|
|
|
|
"M[^:]*: [^ ]+ [^ ]+"))
|
|
|
|
|
|
|
|
|
|
(defconst factor-typedef-regex
|
2015-08-04 20:28:07 -04:00
|
|
|
|
(syntax-and-2-symbols '("TYPEDEF" "INSTANCE")))
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defconst factor-rename-regex
|
2015-08-04 20:28:07 -04:00
|
|
|
|
(concat (syntax-and-2-symbols '("RENAME")) ws+ "\\(=>\\)" ws+ symbol))
|
2015-07-12 20:04:27 -04:00
|
|
|
|
|
|
|
|
|
(defconst factor-from/exclude-regex
|
|
|
|
|
(concat (syntax-begin '("FROM" "EXCLUDE")) ws+
|
|
|
|
|
symbol ws+
|
|
|
|
|
"\\(=>\\)" ws+ symbols-to-semicolon))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2015-10-28 19:44:08 -04:00
|
|
|
|
(defconst factor-predicate-regex
|
|
|
|
|
(concat (syntax-begin '("PREDICATE")) ws+ symbol ws+ "\\(<\\)" ws+ symbol))
|
|
|
|
|
|
2015-12-04 06:43:01 -05:00
|
|
|
|
(defconst factor-alien-function-regex
|
2016-07-01 21:28:19 -04:00
|
|
|
|
(concat (syntax-begin '("CALLBACK"
|
|
|
|
|
"FUNCTION"
|
|
|
|
|
"GL-CALLBACK"
|
|
|
|
|
"GL-FUNCTION"
|
|
|
|
|
"X-FUNCTION"))
|
2015-12-04 06:43:01 -05:00
|
|
|
|
ws+ symbol
|
|
|
|
|
ws+ symbol ws+))
|
|
|
|
|
|
2016-08-19 21:41:51 -04:00
|
|
|
|
;; Regexp from hell that puts every type name in the first group,
|
|
|
|
|
;; names and brackets in the second and third.
|
|
|
|
|
(defconst factor-function-params-regex
|
|
|
|
|
(format "\\(?:%s%s\\(%s,?\\(?:%s)\\)?\\)\\|\\([()]\\)\\)" c-symbol ws+ c-symbol-nc ws+))
|
|
|
|
|
|
2015-12-04 06:43:01 -05:00
|
|
|
|
(defconst factor-function-alias-regex
|
|
|
|
|
(concat (syntax-begin '("FUNCTION-ALIAS"))
|
|
|
|
|
ws+ symbol
|
|
|
|
|
ws+ symbol
|
|
|
|
|
ws+ symbol ws+))
|
|
|
|
|
|
2015-08-05 10:58:27 -04:00
|
|
|
|
(defconst factor-group-name-to-face
|
|
|
|
|
#s(hash-table test equal data
|
|
|
|
|
("C" 'factor-font-lock-comment
|
|
|
|
|
"CO" 'factor-font-lock-constructor
|
|
|
|
|
"CT" 'factor-font-lock-constant
|
|
|
|
|
"P" 'factor-font-lock-parsing-word
|
|
|
|
|
"V" 'factor-font-lock-vocabulary-name
|
|
|
|
|
"T" 'factor-font-lock-type-name
|
2016-05-25 16:03:05 -04:00
|
|
|
|
"N" 'factor-font-lock-number
|
2015-08-05 10:58:27 -04:00
|
|
|
|
"W" 'factor-font-lock-word)))
|
|
|
|
|
|
|
|
|
|
(defun factor-group-name-to-face (group-name)
|
|
|
|
|
(gethash group-name factor-group-name-to-face))
|
|
|
|
|
|
|
|
|
|
(defun factor-groups-to-font-lock (groups)
|
|
|
|
|
(let ((i 0))
|
|
|
|
|
(mapcar (lambda (x)
|
|
|
|
|
(setq i (1+ i))
|
|
|
|
|
(list i (factor-group-name-to-face x)))
|
|
|
|
|
groups)))
|
|
|
|
|
|
|
|
|
|
(defun factor-syntax (regex groups)
|
|
|
|
|
(append (list regex) (factor-groups-to-font-lock groups)))
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
;;; Font lock:
|
|
|
|
|
|
|
|
|
|
(defconst factor-font-lock-keywords
|
2015-07-12 20:04:27 -04:00
|
|
|
|
`(
|
2015-08-05 10:58:27 -04:00
|
|
|
|
,(factor-syntax factor-brace-words-regex '("P"))
|
|
|
|
|
,(factor-syntax factor-vocab-ref-regex '("P" "V"))
|
|
|
|
|
,(factor-syntax factor-using-lines-regex '("P" "V" "P"))
|
|
|
|
|
,(factor-syntax factor-symbols-lines-regex '("P" "W" "P"))
|
|
|
|
|
,(factor-syntax factor-from/exclude-regex '("P" "V" "P" "W" "P"))
|
|
|
|
|
,(factor-syntax (syntax-and-2-symbols '("C")) '("P" "W" "T"))
|
|
|
|
|
,(factor-syntax factor-symbol-definition-regex '("P" "W"))
|
|
|
|
|
,(factor-syntax factor-typedef-regex '("P" "T" "T"))
|
|
|
|
|
,(factor-syntax (syntax-and-2-symbols '("C-GLOBAL")) '("P" "T" "W"))
|
|
|
|
|
,(factor-syntax (syntax-and-2-symbols '("QUALIFIED-WITH")) '("P" "V" "W"))
|
|
|
|
|
,(factor-syntax factor-rename-regex '("P" "W" "V" "P" "W"))
|
|
|
|
|
,(factor-syntax factor-declaration-words-regex '("C"))
|
|
|
|
|
,(factor-syntax factor-word-definition-regex '("P" "W"))
|
|
|
|
|
,(factor-syntax (syntax-and-2-symbols '("ALIAS")) '("P" "W" "W"))
|
2016-10-08 01:13:46 -04:00
|
|
|
|
,(factor-syntax (syntax-and-2-symbols '("HINTS" "LOG")) '("P" "W" ""))
|
2016-08-20 20:23:31 -04:00
|
|
|
|
,(factor-syntax (syntax-and-1-symbol '("ALIEN" "CHAR" "COLOR" "NAN" "HEXCOLOR")) '("P" "CT"))
|
2015-10-28 19:44:08 -04:00
|
|
|
|
,(factor-syntax factor-types-lines-regex '("P" "T"))
|
2016-08-19 21:41:51 -04:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(,factor-float-regex . 'factor-font-lock-number)
|
|
|
|
|
(,factor-ratio-regex . 'factor-font-lock-ratio)
|
2015-08-05 10:58:27 -04:00
|
|
|
|
,(factor-syntax factor-type-definition-regex '("P" "T"))
|
2016-07-02 09:27:33 -04:00
|
|
|
|
,(factor-syntax factor-method-definition-regex '("P" "T" "W"))
|
2013-08-05 12:39:11 -04:00
|
|
|
|
|
2013-09-20 08:09:10 -04:00
|
|
|
|
;; Highlights tuple and struct definitions. The TUPLE/STRUCT
|
|
|
|
|
;; parsing word, class name and optional parent classes are
|
|
|
|
|
;; matched in three groups. Then the text up until the end of the
|
|
|
|
|
;; definition that is terminated with ";" is searched for words
|
|
|
|
|
;; that are slot names which are highlighted with the face
|
|
|
|
|
;; factor-font-lock-symbol.
|
|
|
|
|
(,(format
|
2015-07-12 20:04:27 -04:00
|
|
|
|
"\\(%s:\\)[ \n]+%s\\(?:[ \n]+\\(<\\)[ \n]+%s\\)?"
|
|
|
|
|
(regexp-opt '("BUILTIN"
|
|
|
|
|
"ENUM"
|
2015-07-12 20:18:53 -04:00
|
|
|
|
"ERROR"
|
2015-07-12 20:04:27 -04:00
|
|
|
|
"PROTOCOL"
|
|
|
|
|
"STRUCT"
|
|
|
|
|
"TUPLE"
|
|
|
|
|
"UNION"
|
|
|
|
|
"UNION-STRUCT"))
|
2013-09-20 08:09:10 -04:00
|
|
|
|
symbol
|
|
|
|
|
symbol)
|
2013-08-13 16:46:17 -04:00
|
|
|
|
(1 'factor-font-lock-parsing-word)
|
|
|
|
|
(2 'factor-font-lock-type-name)
|
2015-07-12 20:04:27 -04:00
|
|
|
|
(3 'factor-font-lock-parsing-word nil t)
|
|
|
|
|
(4 'factor-font-lock-type-name nil t)
|
2016-07-30 13:00:14 -04:00
|
|
|
|
;; This allows three different slot styles:
|
|
|
|
|
;; 1) foo 2) { foo initial: 123 } 3) { foo initial: { 123 } }
|
2016-06-29 20:42:23 -04:00
|
|
|
|
(,(format
|
2016-07-30 13:00:14 -04:00
|
|
|
|
"{%s%s[^}]+}%s}\\|{%s%s[^}]+}\\|%s"
|
|
|
|
|
ws+ symbol ws+
|
|
|
|
|
ws+ symbol
|
|
|
|
|
symbol)
|
2013-09-20 10:35:49 -04:00
|
|
|
|
(factor-find-end-of-def)
|
2013-08-13 16:46:17 -04:00
|
|
|
|
nil
|
|
|
|
|
(1 'factor-font-lock-symbol nil t)
|
2016-07-30 13:00:14 -04:00
|
|
|
|
(2 'factor-font-lock-symbol nil t)
|
|
|
|
|
(3 'factor-font-lock-symbol nil t)))
|
2015-10-28 19:44:08 -04:00
|
|
|
|
,(factor-syntax factor-predicate-regex '("P" "T" "P" "T"))
|
2013-09-20 10:35:49 -04:00
|
|
|
|
;; Highlights alien function definitions. Types in stack effect
|
|
|
|
|
;; declarations are given a bold face.
|
2015-12-04 06:43:01 -05:00
|
|
|
|
(,factor-alien-function-regex
|
2013-09-20 10:35:49 -04:00
|
|
|
|
(1 'factor-font-lock-parsing-word)
|
|
|
|
|
(2 'factor-font-lock-type-name)
|
|
|
|
|
(3 'factor-font-lock-word)
|
2016-08-19 21:41:51 -04:00
|
|
|
|
(,factor-function-params-regex
|
2015-08-04 20:35:09 -04:00
|
|
|
|
(factor-find-ending-bracket)
|
2013-09-20 10:35:49 -04:00
|
|
|
|
nil
|
|
|
|
|
(1 'factor-font-lock-type-in-stack-effect nil t)
|
|
|
|
|
(2 'factor-font-lock-stack-effect nil t)
|
|
|
|
|
(3 'factor-font-lock-stack-effect nil t)))
|
|
|
|
|
|
|
|
|
|
;; Almost identical to the previous one, but for function aliases.
|
2015-12-04 06:43:01 -05:00
|
|
|
|
(,factor-function-alias-regex
|
2013-09-20 10:35:49 -04:00
|
|
|
|
(1 'factor-font-lock-parsing-word)
|
|
|
|
|
(2 'factor-font-lock-word)
|
|
|
|
|
(3 'factor-font-lock-type-name)
|
|
|
|
|
(4 'factor-font-lock-word)
|
2016-08-19 21:41:51 -04:00
|
|
|
|
(,factor-function-params-regex
|
2015-08-04 20:35:09 -04:00
|
|
|
|
(factor-find-ending-bracket)
|
2013-09-20 10:35:49 -04:00
|
|
|
|
nil
|
|
|
|
|
(1 'factor-font-lock-type-in-stack-effect nil t)
|
|
|
|
|
(2 'factor-font-lock-stack-effect nil t)
|
|
|
|
|
(3 'factor-font-lock-stack-effect nil t)))
|
2016-08-19 21:41:51 -04:00
|
|
|
|
,(factor-syntax factor-integer-regex '("N"))
|
2013-12-01 08:37:23 -05:00
|
|
|
|
(factor-match-brackets . 'factor-font-lock-stack-effect)
|
2015-08-05 10:58:27 -04:00
|
|
|
|
,(factor-syntax factor-constructor-regex '("CO"))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(,factor-setter-regex . 'factor-font-lock-setter-word)
|
|
|
|
|
(,factor-getter-regex . 'factor-font-lock-getter-word)
|
|
|
|
|
(,factor-bad-string-regex . 'factor-font-lock-invalid-syntax)
|
|
|
|
|
("\\_<\\(P\\|SBUF\\|DLL\\)\"" 1 'factor-font-lock-parsing-word)
|
|
|
|
|
(,factor-constant-words-regex . 'factor-font-lock-constant)
|
2015-08-05 10:58:27 -04:00
|
|
|
|
,(factor-syntax factor-parsing-words-regex '("P"))
|
2013-08-07 17:53:24 -04:00
|
|
|
|
(,"\t" . 'whitespace-highlight-face)))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2013-08-07 12:27:59 -04:00
|
|
|
|
;; Handling of multi-line constructs
|
|
|
|
|
(defun factor-font-lock-extend-region ()
|
|
|
|
|
(eval-when-compile (defvar font-lock-beg) (defvar font-lock-end))
|
|
|
|
|
(save-excursion
|
|
|
|
|
(goto-char font-lock-beg)
|
|
|
|
|
(let ((found (or (re-search-backward "\n\n" nil t) (point-min))))
|
|
|
|
|
(goto-char font-lock-end)
|
|
|
|
|
(when (re-search-forward "\n\n" nil t)
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(setq font-lock-end (point)))
|
|
|
|
|
(setq font-lock-beg found))))
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
;;; Source code analysis:
|
|
|
|
|
|
|
|
|
|
(defsubst factor-brackets-depth ()
|
|
|
|
|
(nth 0 (syntax-ppss)))
|
|
|
|
|
|
|
|
|
|
(defsubst factor-brackets-start ()
|
|
|
|
|
(nth 1 (syntax-ppss)))
|
|
|
|
|
|
|
|
|
|
(defsubst factor-beginning-of-defun (&optional times)
|
|
|
|
|
(re-search-backward factor-begin-of-def-regex nil t times))
|
|
|
|
|
|
|
|
|
|
(defsubst factor-end-of-defun ()
|
|
|
|
|
(re-search-forward factor-end-of-def-regex nil t))
|
|
|
|
|
|
2016-07-01 21:24:46 -04:00
|
|
|
|
(defsubst factor-end-of-defun-pos ()
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(save-excursion
|
2016-07-01 21:24:46 -04:00
|
|
|
|
(re-search-forward factor-end-of-def-regex nil t)
|
|
|
|
|
(point)))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2014-04-17 12:39:10 -04:00
|
|
|
|
(defun factor-on-vocab ()
|
|
|
|
|
"t if point is on a vocab name. We just piggyback on
|
|
|
|
|
font-lock's pretty accurate information."
|
|
|
|
|
(eq (get-char-property (point) 'face) 'factor-font-lock-vocabulary-name))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2015-08-04 20:35:09 -04:00
|
|
|
|
(defun factor-find-end-of-def (&rest foo)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(re-search-forward "[ \n];" nil t)
|
|
|
|
|
(1- (point))))
|
|
|
|
|
|
|
|
|
|
(defun factor-find-ending-bracket (&rest foo)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(re-search-forward "[ \n]\)" nil t)
|
|
|
|
|
(point)))
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defun factor-beginning-of-body ()
|
|
|
|
|
(let ((p (point)))
|
|
|
|
|
(and (factor-beginning-of-defun)
|
|
|
|
|
(re-search-forward factor-defun-signature-regex p t)
|
|
|
|
|
(not (re-search-forward factor-end-of-def-regex p t)))))
|
|
|
|
|
|
|
|
|
|
(defun factor-beginning-of-sexp ()
|
|
|
|
|
(if (> (factor-brackets-depth) 0)
|
|
|
|
|
(goto-char (factor-brackets-start))
|
|
|
|
|
(factor-beginning-of-body)))
|
|
|
|
|
|
|
|
|
|
(defsubst factor-beginning-of-sexp-pos ()
|
|
|
|
|
(save-excursion (factor-beginning-of-sexp) (point)))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; USING/IN:
|
|
|
|
|
|
2014-04-13 10:34:47 -04:00
|
|
|
|
(defvar-local factor-current-vocab-function 'factor-find-vocab-name)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(defsubst factor-current-vocab ()
|
|
|
|
|
(funcall factor-current-vocab-function))
|
|
|
|
|
|
|
|
|
|
(defun factor-find-in ()
|
|
|
|
|
(save-excursion
|
2014-04-17 21:06:34 -04:00
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(if (re-search-backward factor-current-vocab-regex nil t)
|
|
|
|
|
(match-string-no-properties 1)
|
|
|
|
|
(when (re-search-forward factor-current-vocab-regex nil t)
|
|
|
|
|
(match-string-no-properties 1)))))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2014-04-13 10:34:47 -04:00
|
|
|
|
(defun factor-in-private? ()
|
|
|
|
|
"t if point is withing a PRIVATE-block, nil otherwise."
|
|
|
|
|
(save-excursion
|
|
|
|
|
(when (re-search-backward "\\_<<?PRIVATE>?\\_>" nil t)
|
|
|
|
|
(string= (match-string-no-properties 0) "<PRIVATE"))))
|
|
|
|
|
|
|
|
|
|
(defun factor-find-vocab-name ()
|
2014-04-14 08:49:34 -04:00
|
|
|
|
"Name of the vocab with possible .private suffix"
|
2014-04-13 10:34:47 -04:00
|
|
|
|
(concat (factor-find-in) (if (factor-in-private?) ".private" "")))
|
|
|
|
|
|
2014-04-14 08:49:34 -04:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defvar-local factor-usings-function 'factor-find-usings)
|
|
|
|
|
|
|
|
|
|
(defsubst factor-usings ()
|
|
|
|
|
(funcall factor-usings-function))
|
|
|
|
|
|
|
|
|
|
(defun factor-file-has-private ()
|
|
|
|
|
(save-excursion
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(and (re-search-forward "\\_<<PRIVATE\\_>" nil t)
|
|
|
|
|
(re-search-forward "\\_<PRIVATE>\\_>" nil t))))
|
|
|
|
|
|
|
|
|
|
(defun factor-find-usings (&optional no-private)
|
2014-04-14 08:49:34 -04:00
|
|
|
|
"Lists all vocabs used by the vocab."
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(save-excursion
|
|
|
|
|
(let ((usings))
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(while (re-search-backward factor-using-lines-regex nil t)
|
2014-04-14 08:49:34 -04:00
|
|
|
|
(dolist (u (split-string (match-string-no-properties 2) nil t))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(push u usings)))
|
|
|
|
|
(when (and (not no-private) (factor-file-has-private))
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(push (concat (factor-find-in) ".private") usings))
|
|
|
|
|
usings)))
|
|
|
|
|
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
|
|
|
|
;;; Buffer cycling:
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defconst factor-cycle-endings
|
2008-12-05 22:34:25 -05:00
|
|
|
|
'(".factor" "-tests.factor" "-docs.factor"))
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defvar factor-cycle-ring
|
|
|
|
|
(let ((ring (make-ring (length factor-cycle-endings))))
|
|
|
|
|
(dolist (e factor-cycle-endings ring)
|
2009-01-08 17:52:38 -05:00
|
|
|
|
(ring-insert ring e))
|
|
|
|
|
ring))
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defconst factor-cycle-basename-regex
|
|
|
|
|
(format "\\(.+?\\)\\(%s\\)$" (regexp-opt factor-cycle-endings)))
|
2009-01-08 17:52:38 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defun factor-cycle-split (basename)
|
|
|
|
|
(when (string-match factor-cycle-basename-regex basename)
|
2009-01-08 17:52:38 -05:00
|
|
|
|
(cons (match-string 1 basename) (match-string 2 basename))))
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defun factor-cycle-next (file skip)
|
2009-01-08 17:52:38 -05:00
|
|
|
|
(let* ((dir (file-name-directory file))
|
|
|
|
|
(basename (file-name-nondirectory file))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(p/s (factor-cycle-split basename))
|
2009-01-08 17:52:38 -05:00
|
|
|
|
(prefix (car p/s))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(ring factor-cycle-ring)
|
2009-01-08 17:52:38 -05:00
|
|
|
|
(idx (or (ring-member ring (cdr p/s)) 0))
|
|
|
|
|
(len (ring-size ring))
|
|
|
|
|
(i 1)
|
|
|
|
|
(result nil))
|
|
|
|
|
(while (and (< i len) (not result))
|
|
|
|
|
(let* ((suffix (ring-ref ring (+ i idx)))
|
|
|
|
|
(path (expand-file-name (concat prefix suffix) dir)))
|
|
|
|
|
(when (or (file-exists-p path)
|
2009-02-22 14:20:46 -05:00
|
|
|
|
(and (not skip)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(not (member suffix factor-cycling-no-ask))
|
2009-01-08 17:52:38 -05:00
|
|
|
|
(y-or-n-p (format "Create %s? " path))))
|
|
|
|
|
(setq result path))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(when (and (not factor-cycle-always-ask-p)
|
|
|
|
|
(not (member suffix factor-cycling-no-ask)))
|
|
|
|
|
(setq factor-cycling-no-ask
|
|
|
|
|
(cons name factor-cycling-no-ask))))
|
2009-01-08 17:52:38 -05:00
|
|
|
|
(setq i (1+ i)))
|
|
|
|
|
result))
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defun factor-visit-other-file (&optional create)
|
2009-02-22 14:20:46 -05:00
|
|
|
|
"Cycle between code, tests and docs factor files.
|
2010-02-21 06:27:16 -05:00
|
|
|
|
With prefix, non-existing files will be created."
|
2009-02-22 14:20:46 -05:00
|
|
|
|
(interactive "P")
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(let ((file (factor-cycle-next (buffer-file-name) (not create))))
|
2009-01-08 17:52:38 -05:00
|
|
|
|
(unless file (error "No other file found"))
|
|
|
|
|
(find-file file)
|
|
|
|
|
(unless (file-exists-p file)
|
|
|
|
|
(set-buffer-modified-p t)
|
|
|
|
|
(save-buffer))))
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
;;; factor-mode:
|
|
|
|
|
|
2013-08-05 12:39:11 -04:00
|
|
|
|
;; I think it is correct to put almost all punctuation characters in
|
|
|
|
|
;; the word class because Factor words can be made up of almost
|
|
|
|
|
;; anything. Otherwise you get incredibly annoying regexps.
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(defvar factor-mode-syntax-table
|
|
|
|
|
(let ((table (make-syntax-table prog-mode-syntax-table)))
|
|
|
|
|
(modify-syntax-entry ?\" "\"" table)
|
2015-06-07 14:36:34 -04:00
|
|
|
|
(modify-syntax-entry ?# "_" table)
|
2015-04-24 05:40:06 -04:00
|
|
|
|
(modify-syntax-entry ?! "_" table)
|
2015-06-07 14:36:34 -04:00
|
|
|
|
(modify-syntax-entry ?\n "> " table)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(modify-syntax-entry ?$ "_" table)
|
|
|
|
|
(modify-syntax-entry ?@ "_" table)
|
|
|
|
|
(modify-syntax-entry ?? "_" table)
|
2013-08-14 11:41:36 -04:00
|
|
|
|
(modify-syntax-entry ?_ "_" table)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(modify-syntax-entry ?: "_" table)
|
|
|
|
|
(modify-syntax-entry ?< "_" table)
|
|
|
|
|
(modify-syntax-entry ?> "_" table)
|
2013-08-14 11:41:36 -04:00
|
|
|
|
(modify-syntax-entry ?. "_" table)
|
|
|
|
|
(modify-syntax-entry ?, "_" table)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(modify-syntax-entry ?& "_" table)
|
|
|
|
|
(modify-syntax-entry ?| "_" table)
|
|
|
|
|
(modify-syntax-entry ?% "_" table)
|
|
|
|
|
(modify-syntax-entry ?= "_" table)
|
|
|
|
|
(modify-syntax-entry ?/ "_" table)
|
|
|
|
|
(modify-syntax-entry ?+ "_" table)
|
2013-08-14 11:41:36 -04:00
|
|
|
|
(modify-syntax-entry ?* "_" table)
|
|
|
|
|
(modify-syntax-entry ?- "_" table)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(modify-syntax-entry ?\; "_" table)
|
2014-04-17 21:53:42 -04:00
|
|
|
|
(modify-syntax-entry ?\' "_" table)
|
|
|
|
|
(modify-syntax-entry ?^ "_" table)
|
|
|
|
|
(modify-syntax-entry ?~ "_" table)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(modify-syntax-entry ?\( "()" table)
|
|
|
|
|
(modify-syntax-entry ?\) ")(" table)
|
|
|
|
|
(modify-syntax-entry ?\{ "(}" table)
|
|
|
|
|
(modify-syntax-entry ?\} "){" table)
|
|
|
|
|
(modify-syntax-entry ?\[ "(]" table)
|
|
|
|
|
(modify-syntax-entry ?\] ")[" table)
|
|
|
|
|
table))
|
|
|
|
|
|
|
|
|
|
(defun factor-font-lock-string (str)
|
|
|
|
|
"Fontify STR as if it was Factor code."
|
|
|
|
|
(with-temp-buffer
|
|
|
|
|
(set-syntax-table factor-mode-syntax-table)
|
|
|
|
|
(setq-local parse-sexp-ignore-comments t)
|
|
|
|
|
(setq-local parse-sexp-lookup-properties t)
|
|
|
|
|
(setq-local font-lock-defaults '(factor-font-lock-keywords nil nil nil nil))
|
|
|
|
|
|
|
|
|
|
(insert str)
|
|
|
|
|
(let ((font-lock-verbose nil))
|
|
|
|
|
(font-lock-fontify-buffer))
|
|
|
|
|
(buffer-string)))
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
2015-06-07 14:36:34 -04:00
|
|
|
|
(defun factor-syntax-propertize (start end)
|
|
|
|
|
(funcall
|
|
|
|
|
(syntax-propertize-rules
|
|
|
|
|
("\\(^\\| \\|\t\\)\\(!\\|#!\\)\\($\\| \\|\t\\)" (2 "< ")))
|
|
|
|
|
start end))
|
|
|
|
|
|
2008-12-05 22:34:25 -05:00
|
|
|
|
;;;###autoload
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(define-derived-mode factor-mode prog-mode "Factor"
|
2008-12-05 22:34:25 -05:00
|
|
|
|
"A mode for editing programs written in the Factor programming language.
|
|
|
|
|
\\{factor-mode-map}"
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(setq-local comment-start "! ")
|
|
|
|
|
(setq-local comment-end "")
|
|
|
|
|
(setq-local comment-column factor-comment-column)
|
|
|
|
|
(setq-local comment-start-skip "!+ *")
|
|
|
|
|
(setq-local parse-sexp-ignore-comments t)
|
|
|
|
|
(setq-local parse-sexp-lookup-properties t)
|
2013-08-07 12:27:59 -04:00
|
|
|
|
(setq-local font-lock-defaults '(factor-font-lock-keywords))
|
|
|
|
|
;; Some syntactic constructs are often split over multiple lines so
|
|
|
|
|
;; we need to setup multiline font-lock.
|
|
|
|
|
(setq-local font-lock-multiline t)
|
|
|
|
|
(add-hook 'font-lock-extend-region-functions 'factor-font-lock-extend-region)
|
2015-06-07 14:36:34 -04:00
|
|
|
|
(setq-local syntax-propertize-function 'factor-syntax-propertize)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
(define-key factor-mode-map [remap ff-get-other-file]
|
|
|
|
|
'factor-visit-other-file)
|
|
|
|
|
|
|
|
|
|
(setq-local electric-indent-chars
|
|
|
|
|
(append '(?\] ?\} ?\n) electric-indent-chars))
|
|
|
|
|
|
2013-08-07 17:53:24 -04:00
|
|
|
|
;; No tabs for you!!
|
|
|
|
|
(setq-local indent-tabs-mode nil)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2016-07-01 21:24:46 -04:00
|
|
|
|
(add-hook 'smie-indent-functions #'factor-smie-indent nil t)
|
|
|
|
|
(smie-setup factor-smie-grammar #'factor-smie-rules
|
|
|
|
|
:forward-token #'factor-smie-forward-token
|
|
|
|
|
:backward-token #'factor-smie-backward-token)
|
|
|
|
|
(setq-local smie-indent-basic factor-block-offset)
|
|
|
|
|
|
2013-05-05 00:48:12 -04:00
|
|
|
|
(setq-local beginning-of-defun-function 'factor-beginning-of-defun)
|
2013-08-06 07:43:39 -04:00
|
|
|
|
(setq-local end-of-defun-function 'factor-end-of-defun)
|
|
|
|
|
;; Load fuel-mode too if factor-mode-use-fuel is t.
|
|
|
|
|
(when factor-mode-use-fuel (require 'fuel-mode) (fuel-mode)))
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(add-to-list 'auto-mode-alist '("\\.factor\\'" . factor-mode))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(add-to-list 'interpreter-mode-alist '("factor" . factor-mode))
|
2008-12-05 22:34:25 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(provide 'factor-mode)
|
2013-05-05 00:48:12 -04:00
|
|
|
|
|
2008-12-05 22:34:25 -05:00
|
|
|
|
;;; factor-mode.el ends here
|