--- /dev/null
+Jose Antonio Ortega Ruiz <jao@gnu.org>
+Eduardo Cavazos <wayo.cavazos@gmail.com>
--- /dev/null
+! Copyright (C) 2008 Your name.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.test fuel ;
+IN: fuel.tests
--- /dev/null
+! Copyright (C) 2008 Jose Antonio Ortega Ruiz.
+! See http://factorcode.org/license.txt for BSD license.
+
+USING: accessors arrays classes.tuple compiler.units continuations debugger
+eval io io.streams.string kernel listener listener.private
+make math namespaces parser prettyprint quotations sequences strings
+vectors vocabs.loader ;
+
+IN: fuel
+
+! <PRIVATE
+
+TUPLE: fuel-status in use ds? ;
+
+SYMBOL: fuel-status-stack
+V{ } clone fuel-status-stack set-global
+
+: push-fuel-status ( -- )
+ in get use get clone display-stacks? get
+ fuel-status boa
+ fuel-status-stack get push ;
+
+: pop-fuel-status ( -- )
+ fuel-status-stack get empty? [
+ fuel-status-stack get pop
+ [ in>> in set ]
+ [ use>> clone use set ]
+ [ ds?>> display-stacks? swap [ on ] [ off ] if ] tri
+ ] unless ;
+
+SYMBOL: fuel-eval-result
+f clone fuel-eval-result set-global
+
+SYMBOL: fuel-eval-output
+f clone fuel-eval-result set-global
+
+! PRIVATE>
+
+GENERIC: fuel-pprint ( obj -- )
+
+M: object fuel-pprint pprint ;
+
+M: f fuel-pprint drop "nil" write ;
+
+M: integer fuel-pprint pprint ;
+
+M: string fuel-pprint pprint ;
+
+M: sequence fuel-pprint
+ dup empty? [ drop f fuel-pprint ] [
+ "(" write
+ [ " " write ] [ fuel-pprint ] interleave
+ ")" write
+ ] if ;
+
+M: tuple fuel-pprint tuple>array fuel-pprint ;
+
+M: continuation fuel-pprint drop "~continuation~" write ;
+
+: fuel-eval-set-result ( obj -- )
+ clone fuel-eval-result set-global ;
+
+: fuel-retort ( -- )
+ error get
+ fuel-eval-result get-global
+ fuel-eval-output get-global
+ 3array fuel-pprint ;
+
+: fuel-forget-error ( -- )
+ f error set-global ;
+
+: (fuel-begin-eval) ( -- )
+ push-fuel-status
+ display-stacks? off
+ fuel-forget-error
+ f fuel-eval-result set-global
+ f fuel-eval-output set-global ;
+
+: (fuel-end-eval) ( quot -- )
+ with-string-writer fuel-eval-output set-global
+ fuel-retort
+ pop-fuel-status ;
+
+: (fuel-eval) ( lines -- )
+ [ [ parse-lines ] with-compilation-unit call ] curry [ drop ] recover ;
+
+: (fuel-eval-each) ( lines -- )
+ [ 1vector (fuel-eval) ] each ;
+
+: (fuel-eval-usings) ( usings -- )
+ [ "USING: " prepend " ;" append ] map
+ (fuel-eval-each) fuel-forget-error ;
+
+: (fuel-eval-in) ( in -- )
+ [ dup "IN: " prepend 1vector (fuel-eval) in set ] when* ;
+
+: fuel-eval-in-context ( lines in usings -- )
+ (fuel-begin-eval) [
+ (fuel-eval-usings)
+ (fuel-eval-in)
+ (fuel-eval)
+ ] (fuel-end-eval) ;
+
+: fuel-begin-eval ( in -- )
+ (fuel-begin-eval)
+ (fuel-eval-in)
+ fuel-retort ;
+
+: fuel-eval ( lines -- )
+ (fuel-begin-eval) [ (fuel-eval) ] (fuel-end-eval) ;
+
+: fuel-end-eval ( -- )
+ [ ] (fuel-end-eval) ;
+
+
+: fuel-startup ( -- )
+ "listener" run ;
+
+MAIN: fuel-startup
--- /dev/null
+FUEL, Factor's Ultimate Emacs Library
+-------------------------------------
+
+FUEL provides a complete environment for your Factor coding pleasure
+inside Emacs, including source code edition and interaction with a
+Factor listener instance running within Emacs.
+
+FUEL was started by Jose A Ortega as an extension to Ed Cavazos'
+original factor.el code.
+
+Installation
+------------
+
+FUEL comes bundled with Factor's distribution. The folder misc/fuel
+contains Elisp code, and there's a fuel vocabulary in extras/fuel.
+
+To install FUEL, either add this line to your Emacs initialisation:
+
+ (load-file "<path/to/factor/installation>/misc/fuel/fu.el")
+
+or
+
+ (add-to-list load-path "<path/to/factor/installation>/fuel")
+ (require 'fuel)
+
+If all you want is a major mode for editing Factor code with pretty
+font colors and indentation, without running the factor listener
+inside Emacs, you can use instead:
+
+ (add-to-list load-path "<path/to/factor/installation>/fuel")
+ (setq factor-mode-use-fuel nil)
+ (require 'factor-mode)
+
+Basic usage
+-----------
+
+If you're using the default factor binary and images locations inside
+the Factor's source tree, that should be enough to start using FUEL.
+Editing any file with the extension .factor will put you in
+factor-mode; try C-hm for a summary of available commands.
+
+To start the listener, try M-x run-factor.
+
+Many aspects of the environment can be customized:
+M-x customize-group fuel will show you how many.
+
+Quick key reference
+-------------------
+
+ - C-cz : switch to listener
+ - C-co : cycle between code, tests and docs factor files
+
+ - C-M-x, C-cC-ed : eval definition around point
+
+ - C-cC-da : toggle autodoc mode
+ - C-cC-dd : help for word at point
+ - C-cC-ds : short help word at point
+
+Chords ending in a single letter <x> accept also C-<x> (e.g. C-cC-z is
+the same as C-cz).
--- /dev/null
+;;; factor-mode.el -- mode for editing Factor source
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages, fuel, factor
+;; Start date: Tue Dec 02, 2008 21:32
+
+;;; Comentary:
+
+;; Definition of factor-mode, a major Emacs for editing Factor source
+;; code.
+
+;;; Code:
+
+(require 'fuel-base)
+(require 'fuel-syntax)
+(require 'fuel-font-lock)
+
+(require 'ring)
+
+\f
+;;; Customization:
+
+(defgroup factor-mode nil
+ "Major mode for Factor source code"
+ :group 'fuel)
+
+(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-mode)
+
+(defcustom factor-mode-default-indent-width 4
+ "Default indentation width for factor-mode.
+
+This value will be used for the local variable
+`factor-mode-indent-width' in new factor buffers. For existing
+code, we first check if `factor-mode-indent-width' is set
+explicitly in a local variable section or line (e.g.
+'! -*- factor-mode-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 'fuel)
+
+(defcustom factor-mode-hook nil
+ "Hook run when entering Factor mode."
+ :type 'hook
+ :group 'factor-mode)
+
+\f
+;;; Syntax table:
+
+(defun factor-mode--syntax-setup ()
+ (set-syntax-table fuel-syntax--syntax-table)
+ (set (make-local-variable 'beginning-of-defun-function)
+ 'fuel-syntax--beginning-of-defun)
+ (set (make-local-variable 'end-of-defun-function) 'fuel-syntax--end-of-defun)
+ (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil)
+ (fuel-syntax--enable-usings))
+
+\f
+;;; Indentation:
+
+(make-variable-buffer-local
+ (defvar factor-mode-indent-width factor-mode-default-indent-width
+ "Indentation width in factor buffers. A local variable."))
+
+(defun factor-mode--guess-indent-width ()
+ "Chooses an indentation value from existing code."
+ (let ((word-cont "^ +[^ ]")
+ (iw))
+ (save-excursion
+ (beginning-of-buffer)
+ (while (not iw)
+ (if (not (re-search-forward fuel-syntax--definition-start-regex nil t))
+ (setq iw factor-mode-default-indent-width)
+ (forward-line)
+ (when (looking-at word-cont)
+ (setq iw (current-indentation))))))
+ iw))
+
+(defun factor-mode--indent-in-brackets ()
+ (save-excursion
+ (beginning-of-line)
+ (when (> (fuel-syntax--brackets-depth) 0)
+ (let ((op (fuel-syntax--brackets-start))
+ (cl (fuel-syntax--brackets-end))
+ (ln (line-number-at-pos)))
+ (when (> ln (line-number-at-pos op))
+ (if (and (> cl 0) (= ln (line-number-at-pos cl)))
+ (fuel-syntax--indentation-at op)
+ (fuel-syntax--increased-indentation (fuel-syntax--indentation-at op))))))))
+
+(defun factor-mode--indent-definition ()
+ (save-excursion
+ (beginning-of-line)
+ (when (fuel-syntax--at-begin-of-def) 0)))
+
+(defun factor-mode--indent-setter-line ()
+ (when (fuel-syntax--at-setter-line)
+ (save-excursion
+ (let ((indent (and (fuel-syntax--at-constructor-line) (current-indentation))))
+ (while (not (or indent
+ (bobp)
+ (fuel-syntax--at-begin-of-def)
+ (fuel-syntax--at-end-of-def)))
+ (if (fuel-syntax--at-constructor-line)
+ (setq indent (fuel-syntax--increased-indentation))
+ (forward-line -1)))
+ indent))))
+
+(defun factor-mode--indent-continuation ()
+ (save-excursion
+ (forward-line -1)
+ (while (and (not (bobp))
+ (fuel-syntax--looking-at-emptiness))
+ (forward-line -1))
+ (cond ((or (fuel-syntax--at-end-of-def)
+ (fuel-syntax--at-setter-line))
+ (fuel-syntax--decreased-indentation))
+ ((and (fuel-syntax--at-begin-of-def)
+ (not (fuel-syntax--at-using)))
+ (fuel-syntax--increased-indentation))
+ (t (current-indentation)))))
+
+(defun factor-mode--calculate-indentation ()
+ "Calculate Factor indentation for line at point."
+ (or (and (bobp) 0)
+ (factor-mode--indent-definition)
+ (factor-mode--indent-in-brackets)
+ (factor-mode--indent-setter-line)
+ (factor-mode--indent-continuation)
+ 0))
+
+(defun factor-mode--indent-line ()
+ "Indent current line as Factor code"
+ (let ((target (factor-mode--calculate-indentation))
+ (pos (- (point-max) (point))))
+ (if (= target (current-indentation))
+ (if (< (current-column) (current-indentation))
+ (back-to-indentation))
+ (beginning-of-line)
+ (delete-horizontal-space)
+ (indent-to target)
+ (if (> (- (point-max) pos) (point))
+ (goto-char (- (point-max) pos))))))
+
+(defun factor-mode--indentation-setup ()
+ (set (make-local-variable 'indent-line-function) 'factor-mode--indent-line)
+ (setq factor-indent-width (factor-mode--guess-indent-width))
+ (setq indent-tabs-mode nil))
+
+\f
+;;; Buffer cycling:
+
+(defconst factor-mode--cycle-endings
+ '(".factor" "-tests.factor" "-docs.factor"))
+
+(defconst factor-mode--regex-cycle-endings
+ (format "\\(.*?\\)\\(%s\\)$"
+ (regexp-opt factor-mode--cycle-endings)))
+
+(defconst factor-mode--cycle-endings-ring
+ (let ((ring (make-ring (length factor-mode--cycle-endings))))
+ (dolist (e factor-mode--cycle-endings ring)
+ (ring-insert ring e))))
+
+(defun factor-mode--cycle-next (file)
+ (let* ((match (string-match factor-mode--regex-cycle-endings file))
+ (base (and match (match-string-no-properties 1 file)))
+ (ending (and match (match-string-no-properties 2 file)))
+ (idx (and ending (ring-member factor-mode--cycle-endings-ring ending)))
+ (gfl (lambda (i) (concat base (ring-ref factor-mode--cycle-endings-ring i)))))
+ (if (not idx) file
+ (let ((l (length factor-mode--cycle-endings)) (i 1) next)
+ (while (and (not next) (< i l))
+ (when (file-exists-p (funcall gfl (+ idx i)))
+ (setq next (+ idx i)))
+ (setq i (1+ i)))
+ (funcall gfl (or next idx))))))
+
+(defun factor-mode-visit-other-file (&optional file)
+ "Cycle between code, tests and docs factor files."
+ (interactive)
+ (find-file (factor-mode--cycle-next (or file (buffer-file-name)))))
+
+\f
+;;; Keymap:
+
+(defun factor-mode-insert-and-indent (n)
+ (interactive "p")
+ (self-insert-command n)
+ (indent-for-tab-command))
+
+(defvar factor-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map [?\]] 'factor-mode-insert-and-indent)
+ (define-key map [?}] 'factor-mode-insert-and-indent)
+ (define-key map "\C-m" 'newline-and-indent)
+ (define-key map "\C-co" 'factor-mode-visit-other-file)
+ (define-key map "\C-c\C-o" 'factor-mode-visit-other-file)
+ map))
+
+(defun factor-mode--keymap-setup ()
+ (use-local-map factor-mode-map))
+
+\f
+;;; Factor mode:
+
+;;;###autoload
+(defun factor-mode ()
+ "A mode for editing programs written in the Factor programming language.
+\\{factor-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (setq major-mode 'factor-mode)
+ (setq mode-name "Factor")
+ (fuel-font-lock--font-lock-setup)
+ (factor-mode--keymap-setup)
+ (factor-mode--indentation-setup)
+ (factor-mode--syntax-setup)
+ (when factor-mode-use-fuel (require 'fuel-mode) (fuel-mode))
+ (run-hooks 'factor-mode-hook))
+
+\f
+(provide 'factor-mode)
+;;; factor-mode.el ends here
--- /dev/null
+;;; fu.el --- Startup file for FUEL
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages
+
+;;; Code:
+
+(add-to-list 'load-path (file-name-directory load-file-name))
+
+(add-to-list 'auto-mode-alist '("\\.factor\\'" . factor-mode))
+(autoload 'factor-mode "factor-mode.el"
+ "Major mode for editing Factor source." t)
+
+(autoload 'run-factor "fuel-listener.el"
+ "Start a Factor listener, or switch to a running one." t)
+
+(autoload 'fuel-autodoc-mode "fuel-help.el"
+ "Minor mode showing in the minibuffer a synopsis of Factor word at point."
+ t)
+
+
+\f
+;;; fu.el ends here
--- /dev/null
+;;; fuel-base.el --- Basic FUEL support code
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages
+
+;;; Commentary:
+
+;; Basic definitions likely to be used by all FUEL modules.
+
+;;; Code:
+
+(defconst fuel-version "1.0")
+
+;;;###autoload
+(defsubst fuel-version ()
+ "Echoes FUEL's version."
+ (interactive)
+ (message "FUEL %s" fuel-version))
+
+\f
+;;; Customization:
+
+;;;###autoload
+(defgroup fuel nil
+ "Factor's Ultimate Emacs Library"
+ :group 'language)
+
+\f
+;;; Emacs compatibility:
+
+(eval-after-load "ring"
+ '(when (not (fboundp 'ring-member))
+ (defun ring-member (ring item)
+ (catch 'found
+ (dotimes (ind (ring-length ring) nil)
+ (when (equal item (ring-ref ring ind))
+ (throw 'found ind)))))))
+
+\f
+;;; Utilities
+
+(defun fuel--shorten-str (str len)
+ (let ((sl (length str)))
+ (if (<= sl len) str
+ (let* ((sep " ... ")
+ (sepl (length sep))
+ (segl (/ (- len sepl) 2)))
+ (format "%s%s%s"
+ (substring str 0 segl)
+ sep
+ (substring str (- sl segl)))))))
+
+(defun fuel--shorten-region (begin end len)
+ (fuel--shorten-str (mapconcat 'identity
+ (split-string (buffer-substring begin end) nil t)
+ " ")
+ len))
+
+(provide 'fuel-base)
+;;; fuel-base.el ends here
--- /dev/null
+;;; fuel-eval.el --- utilities for communication with fuel-listener
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages
+;; Start date: Tue Dec 02, 2008
+
+;;; Commentary:
+
+;; Protocols for handling communications via a comint buffer running a
+;; factor listener.
+
+;;; Code:
+
+(require 'fuel-base)
+(require 'fuel-syntax)
+
+\f
+;;; Syncronous string sending:
+
+(defvar fuel-eval-log-max-length 16000)
+
+(defvar fuel-eval--default-proc-function nil)
+(defsubst fuel-eval--default-proc ()
+ (and fuel-eval--default-proc-function
+ (funcall fuel-eval--default-proc-function)))
+
+(defvar fuel-eval--proc nil)
+(defvar fuel-eval--log t)
+
+(defun fuel-eval--send-string (str)
+ (let ((proc (or fuel-eval--proc (fuel-eval--default-proc))))
+ (when proc
+ (with-current-buffer (get-buffer-create "*factor messages*")
+ (goto-char (point-max))
+ (when (and (> fuel-eval-log-max-length 0)
+ (> (point) fuel-eval-log-max-length))
+ (erase-buffer))
+ (when fuel-eval--log (insert "\n>> " (fuel--shorten-str str 75) "\n"))
+ (let ((beg (point)))
+ (comint-redirect-send-command-to-process str (current-buffer) proc nil t)
+ (with-current-buffer (process-buffer proc)
+ (while (not comint-redirect-completed) (sleep-for 0 1)))
+ (goto-char beg)
+ (current-buffer))))))
+
+\f
+;;; Evaluation protocol
+
+(defsubst fuel-eval--retort-make (err result &optional output)
+ (list err result output))
+
+(defsubst fuel-eval--retort-error (ret) (nth 0 ret))
+(defsubst fuel-eval--retort-result (ret) (nth 1 ret))
+(defsubst fuel-eval--retort-output (ret) (nth 2 ret))
+
+(defsubst fuel-eval--retort-p (ret) (listp ret))
+
+(defsubst fuel-eval--error-name (err) (car err))
+
+(defsubst fuel-eval--make-parse-error-retort (str)
+ (fuel-eval--retort-make 'parse-retort-error nil str))
+
+(defun fuel-eval--parse-retort (buffer)
+ (save-current-buffer
+ (set-buffer buffer)
+ (condition-case nil
+ (read (current-buffer))
+ (error (fuel-eval--make-parse-error-retort
+ (buffer-substring-no-properties (point) (point-max)))))))
+
+(defsubst fuel-eval--send/retort (str)
+ (fuel-eval--parse-retort (fuel-eval--send-string str)))
+
+(defsubst fuel-eval--eval-begin ()
+ (fuel-eval--send/retort "fuel-begin-eval"))
+
+(defsubst fuel-eval--eval-end ()
+ (fuel-eval--send/retort "fuel-begin-eval"))
+
+(defsubst fuel-eval--factor-array (strs)
+ (format "V{ %S }" (mapconcat 'identity strs " ")))
+
+(defsubst fuel-eval--eval-strings (strs)
+ (let ((str (format "%s fuel-eval" (fuel-eval--factor-array strs))))
+ (fuel-eval--send/retort str)))
+
+(defsubst fuel-eval--eval-string (str)
+ (fuel-eval--eval-strings (list str)))
+
+(defun fuel-eval--eval-strings/context (strs)
+ (let ((usings (fuel-syntax--usings-update)))
+ (fuel-eval--send/retort
+ (format "%s %S %s fuel-eval-in-context"
+ (fuel-eval--factor-array strs)
+ (or fuel-syntax--current-vocab "f")
+ (if usings (fuel-eval--factor-array usings) "f")))))
+
+(defsubst fuel-eval--eval-string/context (str)
+ (fuel-eval--eval-strings/context (list str)))
+
+(defun fuel-eval--eval-region/context (begin end)
+ (let ((lines (split-string (buffer-substring-no-properties begin end)
+ "[\f\n\r\v]+" t)))
+ (when (> (length lines) 0)
+ (fuel-eval--eval-strings/context lines))))
+
+\f
+(provide 'fuel-eval)
+;;; fuel-eval.el ends here
--- /dev/null
+;;; fuel-font-lock.el -- font lock for factor code
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages, fuel, factor
+;; Start date: Wed Dec 03, 2008 21:40
+
+;;; Comentary:
+
+;; Font lock setup for highlighting Factor code.
+
+;;; Code:
+
+(require 'fuel-base)
+(require 'fuel-syntax)
+
+(require 'font-lock)
+
+\f
+;;; Faces:
+
+(defmacro fuel-font-lock--face (face def doc)
+ (let ((face (intern (format "factor-font-lock-%s" (symbol-name face))))
+ (def (intern (format "font-lock-%s-face" (symbol-name def)))))
+ `(defface ,face (face-default-spec ,def)
+ ,(format "Face for %s." doc)
+ :group 'factor-mode
+ :group 'faces)))
+
+(defmacro fuel-font-lock--faces-setup ()
+ (cons 'progn
+ (mapcar (lambda (f) (cons 'fuel-font-lock--face f))
+ '((comment comment "comments")
+ (constructor type "constructors (<foo>)")
+ (declaration keyword "declaration words")
+ (parsing-word keyword "parsing words")
+ (setter-word function-name "setter words (>>foo)")
+ (stack-effect comment "stack effect specifications")
+ (string string "strings")
+ (symbol variable-name "name of symbol being defined")
+ (type-name type "type names")
+ (vocabulary-name constant "vocabulary names")
+ (word function-name "word, generic or method being defined")))))
+
+(fuel-font-lock--faces-setup)
+
+\f
+;;; Font lock:
+
+(defconst fuel-font-lock--parsing-lock-keywords
+ (cons '("\\(P\\|SBUF\\)\"" 1 'factor-font-lock-parsing-word)
+ (mapcar (lambda (w) `(,(format "\\(^\\| \\)\\(%s\\)\\($\\| \\)" w)
+ 2 'factor-font-lock-parsing-word))
+ fuel-syntax--parsing-words)))
+
+(defconst fuel-font-lock--font-lock-keywords
+ `(,@fuel-font-lock--parsing-lock-keywords
+ (,fuel-syntax--stack-effect-regex . 'factor-font-lock-stack-effect)
+ (,fuel-syntax--parsing-words-ext-regex . 'factor-font-lock-parsing-word)
+ (,fuel-syntax--declaration-words-regex 1 'factor-font-lock-declaration)
+ (,fuel-syntax--word-definition-regex 2 'factor-font-lock-word)
+ (,fuel-syntax--type-definition-regex 2 'factor-font-lock-type-name)
+ (,fuel-syntax--method-definition-regex (1 'factor-font-lock-type-name)
+ (2 'factor-font-lock-word))
+ (,fuel-syntax--parent-type-regex 1 'factor-font-lock-type)
+ (,fuel-syntax--constructor-regex . 'factor-font-lock-constructor)
+ (,fuel-syntax--setter-regex . 'factor-font-lock-setter-word)
+ (,fuel-syntax--symbol-definition-regex 2 'factor-font-lock-symbol)
+ (,fuel-syntax--use-line-regex 1 'factor-font-lock-vocabulary-name))
+ "Font lock keywords definition for Factor mode.")
+
+(defun fuel-font-lock--font-lock-setup (&optional keywords no-syntax)
+ (set (make-local-variable 'comment-start) "! ")
+ (set (make-local-variable 'parse-sexp-lookup-properties) t)
+ (set (make-local-variable 'font-lock-comment-face) 'factor-font-lock-comment)
+ (set (make-local-variable 'font-lock-string-face) 'factor-font-lock-string)
+ (set (make-local-variable 'font-lock-defaults)
+ `(,(or keywords 'fuel-font-lock--font-lock-keywords)
+ nil nil nil nil
+ ,@(if no-syntax nil
+ (list (cons 'font-lock-syntactic-keywords
+ fuel-syntax--syntactic-keywords))))))
+
+\f
+(provide 'fuel-font-lock)
+;;; fuel-font-lock.el ends here
--- /dev/null
+;;; fuel-help.el -- accessing Factor's help system
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages, fuel, factor
+;; Start date: Wed Dec 03, 2008 21:41
+
+;;; Comentary:
+
+;; Modes and functions interfacing Factor's 'see' and 'help'
+;; utilities, as well as an ElDoc-based autodoc mode.
+
+;;; Code:
+
+(require 'fuel-base)
+(require 'fuel-font-lock)
+(require 'fuel-eval)
+
+\f
+;;; Customization:
+
+(defgroup fuel-help nil
+ "Options controlling FUEL's help system"
+ :group 'fuel)
+
+(defcustom fuel-help-minibuffer-font-lock t
+ "Whether to use font lock for info messages in the minibuffer."
+ :group 'fuel-help
+ :type 'boolean)
+
+(defcustom fuel-help-always-ask t
+ "When enabled, always ask for confirmation in help prompts."
+ :type 'boolean
+ :group 'fuel-help)
+
+(defcustom fuel-help-use-minibuffer t
+ "When enabled, use the minibuffer for short help messages."
+ :type 'boolean
+ :group 'fuel-help)
+
+(defcustom fuel-help-mode-hook nil
+ "Hook run by `factor-help-mode'."
+ :type 'hook
+ :group 'fuel-help)
+
+(defface fuel-help-font-lock-headlines '((t (:bold t :weight bold)))
+ "Face for headlines in help buffers."
+ :group 'fuel-help
+ :group 'faces)
+
+\f
+;;; Autodoc mode:
+
+(defvar fuel-help--font-lock-buffer
+ (let ((buffer (get-buffer-create " *fuel help minibuffer messages*")))
+ (set-buffer buffer)
+ (fuel-font-lock--font-lock-setup)
+ buffer))
+
+(defun fuel-help--font-lock-str (str)
+ (set-buffer fuel-help--font-lock-buffer)
+ (erase-buffer)
+ (insert str)
+ (let ((font-lock-verbose nil)) (font-lock-fontify-buffer))
+ (buffer-string))
+
+(defun fuel-help--word-synopsis (&optional word)
+ (let ((word (or word (fuel-syntax-symbol-at-point)))
+ (fuel-eval--log nil))
+ (when word
+ (let ((ret (fuel-eval--eval-string/context
+ (format "\\ %s synopsis fuel-eval-set-result" word))))
+ (when (not (fuel-eval--retort-error ret))
+ (if fuel-help-minibuffer-font-lock
+ (fuel-help--font-lock-str (fuel-eval--retort-result ret))
+ (fuel-eval--retort-result ret)))))))
+
+(make-variable-buffer-local
+ (defvar fuel-autodoc-mode-string " A"
+ "Modeline indicator for fuel-autodoc-mode"))
+
+(define-minor-mode fuel-autodoc-mode
+ "Toggle Fuel's Autodoc mode.
+With no argument, this command toggles the mode.
+Non-null prefix argument turns on the mode.
+Null prefix argument turns off the mode.
+
+When Autodoc mode is enabled, a synopsis of the word at point is
+displayed in the minibuffer."
+ :init-value nil
+ :lighter fuel-autodoc-mode-string
+ :group 'fuel
+
+ (set (make-local-variable 'eldoc-documentation-function)
+ (when fuel-autodoc-mode 'fuel-help--word-synopsis))
+ (set (make-local-variable 'eldoc-minor-mode-string) nil)
+ (eldoc-mode fuel-autodoc-mode)
+ (message "Fuel Autodoc %s" (if fuel-autodoc-mode "enabled" "disabled")))
+
+\f
+;;;; Factor help mode:
+
+(defvar fuel-help-mode-map (make-sparse-keymap)
+ "Keymap for Factor help mode.")
+
+(define-key fuel-help-mode-map [(return)] 'fuel-help)
+
+(defconst fuel-help--headlines
+ (regexp-opt '("Class description"
+ "Definition"
+ "Examples"
+ "Generic word contract"
+ "Inputs and outputs"
+ "Methods"
+ "Notes"
+ "Parent topics:"
+ "See also"
+ "Syntax"
+ "Vocabulary"
+ "Warning"
+ "Word description")
+ t))
+
+(defconst fuel-help--headlines-regexp (format "^%s" fuel-help--headlines))
+
+(defconst fuel-help--font-lock-keywords
+ `(,@fuel-font-lock--font-lock-keywords
+ (,fuel-help--headlines-regexp . 'fuel-help-font-lock-headlines)))
+
+(defun fuel-help-mode ()
+ "Major mode for displaying Factor documentation.
+\\{fuel-help-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map fuel-help-mode-map)
+ (setq mode-name "Factor Help")
+ (setq major-mode 'fuel-help-mode)
+
+ (fuel-font-lock--font-lock-setup fuel-help--font-lock-keywords t)
+
+ (set (make-local-variable 'view-no-disable-on-exit) t)
+ (view-mode)
+ (setq view-exit-action
+ (lambda (buffer)
+ ;; Use `with-current-buffer' to make sure that `bury-buffer'
+ ;; also removes BUFFER from the selected window.
+ (with-current-buffer buffer
+ (bury-buffer))))
+
+ (setq fuel-autodoc-mode-string "")
+ (fuel-autodoc-mode)
+ (run-mode-hooks 'fuel-help-mode-hook))
+
+(defun fuel-help--help-buffer ()
+ (with-current-buffer (get-buffer-create "*fuel-help*")
+ (fuel-help-mode)
+ (current-buffer)))
+
+(defvar fuel-help--history nil)
+
+(defun fuel-help--show-help (&optional see)
+ (let* ((def (fuel-syntax-symbol-at-point))
+ (prompt (format "See%s help on%s: " (if see " short" "")
+ (if def (format " (%s)" def) "")))
+ (ask (or (not (memq major-mode '(factor-mode fuel-help-mode)))
+ (not def)
+ fuel-help-always-ask))
+ (def (if ask (read-string prompt nil 'fuel-help--history def) def))
+ (cmd (format "\\ %s %s" def (if see "see" "help")))
+ (fuel-eval--log nil)
+ (ret (fuel-eval--eval-string/context cmd))
+ (out (fuel-eval--retort-output ret)))
+ (if (or (fuel-eval--retort-error ret) (empty-string-p out))
+ (message "No help for '%s'" def)
+ (let ((hb (fuel-help--help-buffer))
+ (inhibit-read-only t)
+ (font-lock-verbose nil))
+ (set-buffer hb)
+ (erase-buffer)
+ (insert out)
+ (set-buffer-modified-p nil)
+ (pop-to-buffer hb)
+ (goto-char (point-min))))))
+
+\f
+;;; Interface: see/help commands
+
+(defun fuel-help-short (&optional arg)
+ "See a help summary of symbol at point.
+By default, the information is shown in the minibuffer. When
+called with a prefix argument, the information is displayed in a
+separate help buffer."
+ (interactive "P")
+ (if (if fuel-help-use-minibuffer (not arg) arg)
+ (fuel-help--word-synopsis)
+ (fuel-help--show-help t)))
+
+(defun fuel-help ()
+ "Show extended help about the symbol at point, using a help
+buffer."
+ (interactive)
+ (fuel-help--show-help))
+
+\f
+(provide 'fuel-help)
+;;; fuel-help.el ends here
--- /dev/null
+;;; fuel-listener.el --- starting the fuel listener
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages
+
+;;; Commentary:
+
+;; Utilities to maintain and switch to a factor listener comint
+;; buffer, with an accompanying major fuel-listener-mode.
+
+;;; Code:
+
+(require 'fuel-eval)
+(require 'fuel-base)
+(require 'comint)
+
+\f
+;;; Customization:
+
+(defgroup fuel-listener nil
+ "Interacting with a Factor listener inside Emacs"
+ :group 'fuel)
+
+(defcustom fuel-listener-factor-binary "~/factor/factor"
+ "Full path to the factor executable to use when starting a listener."
+ :type '(file :must-match t)
+ :group 'fuel-listener)
+
+(defcustom fuel-listener-factor-image "~/factor/factor.image"
+ "Full path to the factor image to use when starting a listener."
+ :type '(file :must-match t)
+ :group 'fuel-listener)
+
+(defcustom fuel-listener-use-other-window t
+ "Use a window other than the current buffer's when switching to
+the factor-listener buffer."
+ :type 'boolean
+ :group 'fuel-listener)
+
+(defcustom fuel-listener-window-allow-split t
+ "Allow window splitting when switching to the fuel listener
+buffer."
+ :type 'boolean
+ :group 'fuel-listener)
+
+\f
+;;; Fuel listener buffer/process:
+
+(defvar fuel-listener-buffer nil
+ "The buffer in which the Factor listener is running.")
+
+(defun fuel-listener--start-process ()
+ (let ((factor (expand-file-name fuel-listener-factor-binary))
+ (image (expand-file-name fuel-listener-factor-image)))
+ (unless (file-executable-p factor)
+ (error "Could not run factor: %s is not executable" factor))
+ (unless (file-readable-p image)
+ (error "Could not run factor: image file %s not readable" image))
+ (setq fuel-listener-buffer
+ (make-comint "fuel listener" factor nil "-run=fuel" (format "-i=%s" image)))
+ (with-current-buffer fuel-listener-buffer
+ (fuel-listener-mode))))
+
+(defun fuel-listener--process (&optional start)
+ (or (and (buffer-live-p fuel-listener-buffer)
+ (get-buffer-process fuel-listener-buffer))
+ (if (not start)
+ (error "No running factor listener (try M-x run-factor)")
+ (fuel-listener--start-process)
+ (fuel-listener--process))))
+
+(setq fuel-eval--default-proc-function 'fuel-listener--process)
+
+\f
+;;; Interface: starting fuel listener
+
+(defalias 'switch-to-factor 'run-factor)
+(defalias 'switch-to-fuel-listener 'run-factor)
+;;;###autoload
+(defun run-factor (&optional arg)
+ "Show the fuel-listener buffer, starting the process if needed."
+ (interactive)
+ (let ((buf (process-buffer (fuel-listener--process t)))
+ (pop-up-windows fuel-listener-window-allow-split))
+ (if fuel-listener-use-other-window
+ (pop-to-buffer buf)
+ (switch-to-buffer buf))))
+
+\f
+;;; Fuel listener mode:
+
+(defconst fuel-listener--prompt-regex "( [^)]* ) ")
+
+(defun fuel-listener--wait-for-prompt (&optional timeout)
+ (let ((proc (fuel-listener--process)))
+ (with-current-buffer fuel-listener-buffer
+ (goto-char comint-last-input-end)
+ (while (not (or (re-search-forward comint-prompt-regexp nil t)
+ (not (accept-process-output proc timeout))))
+ (goto-char comint-last-input-end))
+ (goto-char (point-max)))))
+
+(defun fuel-listener--startup ()
+ (fuel-listener--wait-for-prompt)
+ (fuel-eval--send-string "USE: fuel")
+ (message "FUEL listener up and running!"))
+
+(define-derived-mode fuel-listener-mode comint-mode "Fuel Listener"
+ "Major mode for interacting with an inferior Factor listener process.
+\\{fuel-listener-mode-map}"
+ (set (make-local-variable 'comint-prompt-regexp)
+ fuel-listener--prompt-regex)
+ (fuel-listener--startup))
+
+\f
+(provide 'fuel-listener)
+;;; fuel-listener.el ends here
--- /dev/null
+;;; fuel-mode.el -- Minor mode enabling FUEL niceties
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages, fuel, factor
+;; Start date: Sat Dec 06, 2008 00:52
+
+;;; Comentary:
+
+;; Enhancements to vanilla factor-mode (notably, listener interaction)
+;; enabled by means of a minor mode.
+
+;;; Code:
+
+(require 'factor-mode)
+(require 'fuel-base)
+(require 'fuel-syntax)
+(require 'fuel-font-lock)
+(require 'fuel-help)
+(require 'fuel-eval)
+(require 'fuel-listener)
+
+\f
+;;; Customization:
+
+(defgroup fuel-mode nil
+ "Mode enabling FUEL's ultimate abilities."
+ :group 'fuel)
+
+(defcustom fuel-mode-autodoc-p t
+ "Whether `fuel-autodoc-mode' gets enable by default in fuel buffers."
+ :group 'fuel-mode
+ :type 'boolean)
+
+\f
+;;; User commands
+
+(defun fuel-eval-definition (&optional arg)
+ "Sends definition around point to Fuel's listener for evaluation.
+With prefix, switchs the the listener's buffer."
+ (interactive "P")
+ (save-excursion
+ (mark-defun)
+ (let* ((begin (point))
+ (end (mark)))
+ (unless (< begin end) (error "No evaluable definition around point"))
+ (let* ((msg (match-string 0))
+ (ret (fuel-eval--eval-region/context begin end))
+ (err (fuel-eval--retort-error ret)))
+ (when err (error "%s" err))
+ (message "%s" (fuel--shorten-region begin end 70)))))
+ (when arg (pop-to-buffer fuel-listener-buffer)))
+
+\f
+;;; Minor mode definition:
+
+(make-variable-buffer-local
+ (defvar fuel-mode-string " F"
+ "Modeline indicator for fuel-mode"))
+
+(defvar fuel-mode-map (make-sparse-keymap)
+ "Key map for fuel-mode")
+
+(define-minor-mode fuel-mode
+ "Toggle Fuel's mode.
+With no argument, this command toggles the mode.
+Non-null prefix argument turns on the mode.
+Null prefix argument turns off the mode.
+
+When Fuel mode is enabled, a host of nice utilities for
+interacting with a factor listener is at your disposal.
+\\{fuel-mode-map}"
+ :init-value nil
+ :lighter fuel-mode-string
+ :group 'fuel
+ :keymap fuel-mode-map
+
+ (setq fuel-autodoc-mode-string "/A")
+ (when fuel-mode-autodoc-p (fuel-autodoc-mode fuel-mode)))
+
+\f
+;;; Keys:
+
+(defun fuel-mode--key-1 (k c)
+ (define-key fuel-mode-map (vector '(control ?c) k) c)
+ (define-key fuel-mode-map (vector '(control ?c) `(control ,k)) c))
+
+(defun fuel-mode--key (p k c)
+ (define-key fuel-mode-map (vector '(control ?c) `(control ,p) k) c)
+ (define-key fuel-mode-map (vector '(control ?c) `(control ,p) `(control ,k)) c))
+
+(fuel-mode--key-1 ?z 'run-factor)
+
+(define-key fuel-mode-map "\C-\M-x" 'fuel-eval-definition)
+
+(fuel-mode--key ?e ?d 'fuel-eval-definition)
+
+(fuel-mode--key ?d ?a 'fuel-autodoc-mode)
+(fuel-mode--key ?d ?d 'fuel-help)
+(fuel-mode--key ?d ?s 'fuel-help-short)
+
+\f
+(provide 'fuel-mode)
+;;; fuel-mode.el ends here
--- /dev/null
+;;; fuel-syntax.el --- auxiliar definitions for factor code navigation.
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages
+
+;;; Commentary:
+
+;; Auxiliar constants and functions to parse factor code.
+
+;;; Code:
+
+(require 'thingatpt)
+
+\f
+;;; Thing-at-point support for factor symbols:
+
+(defun fuel-syntax--beginning-of-symbol ()
+ "Move point to the beginning of the current symbol."
+ (while (eq (char-before) ?:) (backward-char))
+ (skip-syntax-backward "w_"))
+
+(defun fuel-syntax--end-of-symbol ()
+ "Move point to the end of the current symbol."
+ (skip-syntax-forward "w_")
+ (while (looking-at ":") (forward-char)))
+
+(put 'factor-symbol 'end-op 'fuel-syntax--end-of-symbol)
+(put 'factor-symbol 'beginning-op 'fuel-syntax--beginning-of-symbol)
+
+(defsubst fuel-syntax-symbol-at-point ()
+ (let ((s (substring-no-properties (thing-at-point 'factor-symbol))))
+ (and (> (length s) 0) s)))
+
+\f
+;;; Regexps galore:
+
+(defconst fuel-syntax--parsing-words
+ '("{" "}" "^:" "^::" ";" "<<" "<PRIVATE" ">>"
+ "BIN:" "BV{" "B{" "C:" "C-STRUCT:" "C-UNION:" "CHAR:" "CS{" "C{"
+ "DEFER:" "ERROR:" "EXCLUDE:" "FORGET:"
+ "GENERIC#" "GENERIC:" "HEX:" "HOOK:" "H{"
+ "IN:" "INSTANCE:" "INTERSECTION:"
+ "M:" "MACRO:" "MACRO::" "MAIN:" "MATH:" "METHOD:" "MIXIN:"
+ "OCT:" "POSTPONE:" "PREDICATE:" "PRIMITIVE:" "PRIVATE>" "PROVIDE:"
+ "REQUIRE:" "REQUIRES:" "SINGLETON:" "SLOT:" "SYMBOL:" "SYMBOLS:"
+ "TUPLE:" "T{" "t\\??" "TYPEDEF:"
+ "UNION:" "USE:" "USING:" "V{" "VARS:" "W{"))
+
+(defconst fuel-syntax--parsing-words-ext-regex
+ (regexp-opt '("B" "call-next-method" "delimiter" "f" "initial:" "read-only")
+ 'words))
+
+(defconst fuel-syntax--declaration-words
+ '("flushable" "foldable" "inline" "parsing" "recursive"))
+
+(defconst fuel-syntax--declaration-words-regex
+ (regexp-opt fuel-syntax--declaration-words 'words))
+
+(defsubst fuel-syntax--second-word-regex (prefixes)
+ (format "^%s +\\([^ \r\n]+\\)" (regexp-opt prefixes t)))
+
+(defconst fuel-syntax--method-definition-regex
+ "^M: +\\([^ ]+\\) +\\([^ ]+\\)")
+
+(defconst fuel-syntax--word-definition-regex
+ (fuel-syntax--second-word-regex '(":" "::" "GENERIC:")))
+
+(defconst fuel-syntax--type-definition-regex
+ (fuel-syntax--second-word-regex '("TUPLE:" "SINGLETON:")))
+
+(defconst fuel-syntax--parent-type-regex "^TUPLE: +[^ ]+ +< +\\([^ ]+\\)")
+
+(defconst fuel-syntax--constructor-regex "<[^ >]+>")
+
+(defconst fuel-syntax--setter-regex "\\W>>[^ ]+\\b")
+
+(defconst fuel-syntax--symbol-definition-regex
+ (fuel-syntax--second-word-regex '("SYMBOL:" "VAR:")))
+
+(defconst fuel-syntax--stack-effect-regex " ( .* )")
+
+(defconst fuel-syntax--using-lines-regex "^USING: +\\([^;]+\\);")
+
+(defconst fuel-syntax--use-line-regex "^USE: +\\(.*\\)$")
+
+(defconst fuel-syntax--current-vocab-regex "^IN: +\\([^ \r\n\f]+\\)")
+
+(defconst fuel-syntax--sub-vocab-regex "^<\\([^ \n]+\\) *$")
+
+(defconst fuel-syntax--definition-starters-regex
+ (regexp-opt '("VARS" "TUPLE" "MACRO" "MACRO:" "M" ":" "")))
+
+(defconst fuel-syntax--definition-start-regex
+ (format "^\\(%s:\\) " fuel-syntax--definition-starters-regex))
+
+(defconst fuel-syntax--definition-end-regex
+ (format "\\(\\(^\\| +\\);\\( +%s\\)*\\($\\| +\\)\\)"
+ fuel-syntax--declaration-words-regex))
+
+(defconst fuel-syntax--single-liner-regex
+ (format "^%s" (regexp-opt '("DEFER:" "GENERIC:" "IN:"
+ "PRIVATE>" "<PRIVATE"
+ "SINGLETON:" "SYMBOL:" "USE:" "VAR:"))))
+
+(defconst fuel-syntax--begin-of-def-regex
+ (format "^USING: \\|\\(%s\\)\\|\\(%s .*\\)"
+ fuel-syntax--definition-start-regex
+ fuel-syntax--single-liner-regex))
+
+(defconst fuel-syntax--end-of-def-line-regex
+ (format "^.*%s" fuel-syntax--definition-end-regex))
+
+(defconst fuel-syntax--end-of-def-regex
+ (format "\\(%s\\)\\|\\(%s .*\\)"
+ fuel-syntax--end-of-def-line-regex
+ fuel-syntax--single-liner-regex))
+\f
+;;; Factor syntax table
+
+(defvar fuel-syntax--syntax-table
+ (let ((i 0)
+ (table (make-syntax-table)))
+ ;; Default is atom-constituent
+ (while (< i 256)
+ (modify-syntax-entry i "_ " table)
+ (setq i (1+ i)))
+
+ ;; Word components.
+ (setq i ?0)
+ (while (<= i ?9)
+ (modify-syntax-entry i "w " table)
+ (setq i (1+ i)))
+ (setq i ?A)
+ (while (<= i ?Z)
+ (modify-syntax-entry i "w " table)
+ (setq i (1+ i)))
+ (setq i ?a)
+ (while (<= i ?z)
+ (modify-syntax-entry i "w " table)
+ (setq i (1+ i)))
+
+ ;; Whitespace
+ (modify-syntax-entry ?\t " " table)
+ (modify-syntax-entry ?\f " " table)
+ (modify-syntax-entry ?\r " " table)
+ (modify-syntax-entry ? " " table)
+
+ ;; (end of) Comments
+ (modify-syntax-entry ?\n ">" table)
+
+ ;; Parenthesis
+ (modify-syntax-entry ?\[ "(] " table)
+ (modify-syntax-entry ?\] ")[ " table)
+ (modify-syntax-entry ?{ "(} " table)
+ (modify-syntax-entry ?} "){ " table)
+
+ (modify-syntax-entry ?\( "()" table)
+ (modify-syntax-entry ?\) ")(" table)
+
+ ;; Strings
+ (modify-syntax-entry ?\" "\"" table)
+ (modify-syntax-entry ?\\ "/" table)
+ table)
+ "Syntax table used while in Factor mode.")
+
+(defconst fuel-syntax--syntactic-keywords
+ `(("\\(#!\\)" (1 "<"))
+ (" \\(!\\)" (1 "<"))
+ ("^\\(!\\)" (1 "<"))
+ ("\\(!(\\) .* \\()\\)" (1 "<") (2 ">"))
+ ("\\([[({]\\)\\([^ \"\n]\\)" (1 "_") (2 "_"))
+ ("\\([^ \"\n]\\)\\([])}]\\)" (1 "_") (2 "_"))))
+
+\f
+;;; Source code analysis:
+
+(defsubst fuel-syntax--brackets-depth ()
+ (nth 0 (syntax-ppss)))
+
+(defsubst fuel-syntax--brackets-start ()
+ (nth 1 (syntax-ppss)))
+
+(defun fuel-syntax--brackets-end ()
+ (save-excursion
+ (goto-char (fuel-syntax--brackets-start))
+ (condition-case nil
+ (progn (forward-sexp)
+ (1- (point)))
+ (error -1))))
+
+(defsubst fuel-syntax--indentation-at (pos)
+ (save-excursion (goto-char pos) (current-indentation)))
+
+(defsubst fuel-syntax--increased-indentation (&optional i)
+ (+ (or i (current-indentation)) factor-indent-width))
+(defsubst fuel-syntax--decreased-indentation (&optional i)
+ (- (or i (current-indentation)) factor-indent-width))
+
+(defsubst fuel-syntax--at-begin-of-def ()
+ (looking-at fuel-syntax--begin-of-def-regex))
+
+(defsubst fuel-syntax--at-end-of-def ()
+ (looking-at fuel-syntax--end-of-def-regex))
+
+(defsubst fuel-syntax--looking-at-emptiness ()
+ (looking-at "^[ \t]*$"))
+
+(defun fuel-syntax--at-setter-line ()
+ (save-excursion
+ (beginning-of-line)
+ (if (not (fuel-syntax--looking-at-emptiness))
+ (re-search-forward fuel-syntax--setter-regex (line-end-position) t)
+ (forward-line -1)
+ (or (fuel-syntax--at-constructor-line)
+ (fuel-syntax--at-setter-line)))))
+
+(defun fuel-syntax--at-constructor-line ()
+ (save-excursion
+ (beginning-of-line)
+ (re-search-forward fuel-syntax--constructor-regex (line-end-position) t)))
+
+(defsubst fuel-syntax--at-using ()
+ (looking-at fuel-syntax--using-lines-regex))
+
+(defsubst fuel-syntax--beginning-of-defun (&optional times)
+ (re-search-backward fuel-syntax--begin-of-def-regex nil t times))
+
+(defsubst fuel-syntax--end-of-defun ()
+ (re-search-forward fuel-syntax--end-of-def-regex nil t))
+
+\f
+;;; USING/IN:
+
+(make-variable-buffer-local
+ (defvar fuel-syntax--current-vocab nil))
+
+(make-variable-buffer-local
+ (defvar fuel-syntax--usings nil))
+
+(defun fuel-syntax--current-vocab ()
+ (let ((ip
+ (save-excursion
+ (when (re-search-backward fuel-syntax--current-vocab-regex nil t)
+ (setq fuel-syntax--current-vocab (match-string-no-properties 1))
+ (point)))))
+ (when ip
+ (let ((pp (save-excursion
+ (when (re-search-backward fuel-syntax--sub-vocab-regex ip t)
+ (point)))))
+ (when (and pp (> pp ip))
+ (let ((sub (match-string-no-properties 1)))
+ (unless (save-excursion (search-backward (format "%s>" sub) pp t))
+ (setq fuel-syntax--current-vocab
+ (format "%s.%s" fuel-syntax--current-vocab (downcase sub)))))))))
+ fuel-syntax--current-vocab)
+
+(defun fuel-syntax--usings-update ()
+ (save-excursion
+ (setq fuel-syntax--usings (list (fuel-syntax--current-vocab)))
+ (while (re-search-backward fuel-syntax--using-lines-regex nil t)
+ (dolist (u (split-string (match-string-no-properties 1) nil t))
+ (push u fuel-syntax--usings)))
+ fuel-syntax--usings))
+
+(defsubst fuel-syntax--usings-update-hook ()
+ (fuel-syntax--usings-update)
+ nil)
+
+(defun fuel-syntax--enable-usings ()
+ (add-hook 'before-save-hook 'fuel-syntax--usings-update-hook nil t)
+ (fuel-syntax--usings-update))
+
+(defsubst fuel-syntax--usings ()
+ (or fuel-syntax--usings (fuel-syntax--usings-update)))
+
+\f
+(provide 'fuel-syntax)
+;;; fuel-syntax.el ends here