FUEL 0.0 : all factor.el functionality in place, plus evaluation.
parent
2e31f7d792
commit
6860285b07
|
@ -0,0 +1,2 @@
|
|||
Jose Antonio Ortega Ruiz <jao@gnu.org>
|
||||
Eduardo Cavazos <wayo.cavazos@gmail.com>
|
|
@ -0,0 +1,4 @@
|
|||
! Copyright (C) 2008 Your name.
|
||||
! See http://factorcode.org/license.txt for BSD license.
|
||||
USING: tools.test fuel ;
|
||||
IN: fuel.tests
|
|
@ -0,0 +1,119 @@
|
|||
! 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
|
|
@ -0,0 +1,60 @@
|
|||
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).
|
|
@ -0,0 +1,239 @@
|
|||
;;; 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)
|
||||
|
||||
|
||||
;;; 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)
|
||||
|
||||
|
||||
;;; 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))
|
||||
|
||||
|
||||
;;; 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))
|
||||
|
||||
|
||||
;;; 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)))))
|
||||
|
||||
|
||||
;;; 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))
|
||||
|
||||
|
||||
;;; 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))
|
||||
|
||||
|
||||
(provide 'factor-mode)
|
||||
;;; factor-mode.el ends here
|
|
@ -0,0 +1,26 @@
|
|||
;;; 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)
|
||||
|
||||
|
||||
|
||||
;;; fu.el ends here
|
|
@ -0,0 +1,63 @@
|
|||
;;; 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))
|
||||
|
||||
|
||||
;;; Customization:
|
||||
|
||||
;;;###autoload
|
||||
(defgroup fuel nil
|
||||
"Factor's Ultimate Emacs Library"
|
||||
:group 'language)
|
||||
|
||||
|
||||
;;; 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)))))))
|
||||
|
||||
|
||||
;;; 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
|
|
@ -0,0 +1,112 @@
|
|||
;;; 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)
|
||||
|
||||
|
||||
;;; 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))))))
|
||||
|
||||
|
||||
;;; 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))))
|
||||
|
||||
|
||||
(provide 'fuel-eval)
|
||||
;;; fuel-eval.el ends here
|
|
@ -0,0 +1,88 @@
|
|||
;;; 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)
|
||||
|
||||
|
||||
;;; 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)
|
||||
|
||||
|
||||
;;; 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))))))
|
||||
|
||||
|
||||
(provide 'fuel-font-lock)
|
||||
;;; fuel-font-lock.el ends here
|
|
@ -0,0 +1,208 @@
|
|||
;;; 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)
|
||||
|
||||
|
||||
;;; 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)
|
||||
|
||||
|
||||
;;; 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")))
|
||||
|
||||
|
||||
;;;; 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))))))
|
||||
|
||||
|
||||
;;; 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))
|
||||
|
||||
|
||||
(provide 'fuel-help)
|
||||
;;; fuel-help.el ends here
|
|
@ -0,0 +1,120 @@
|
|||
;;; 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)
|
||||
|
||||
|
||||
;;; 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)
|
||||
|
||||
|
||||
;;; 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)
|
||||
|
||||
|
||||
;;; 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))))
|
||||
|
||||
|
||||
;;; 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))
|
||||
|
||||
|
||||
(provide 'fuel-listener)
|
||||
;;; fuel-listener.el ends here
|
|
@ -0,0 +1,106 @@
|
|||
;;; 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)
|
||||
|
||||
|
||||
;;; 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)
|
||||
|
||||
|
||||
;;; 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)))
|
||||
|
||||
|
||||
;;; 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)))
|
||||
|
||||
|
||||
;;; 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)
|
||||
|
||||
|
||||
(provide 'fuel-mode)
|
||||
;;; fuel-mode.el ends here
|
|
@ -0,0 +1,281 @@
|
|||
;;; 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)
|
||||
|
||||
|
||||
;;; 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)))
|
||||
|
||||
|
||||
;;; 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))
|
||||
|
||||
;;; 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 "_"))))
|
||||
|
||||
|
||||
;;; 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))
|
||||
|
||||
|
||||
;;; 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)))
|
||||
|
||||
|
||||
(provide 'fuel-syntax)
|
||||
;;; fuel-syntax.el ends here
|
Loading…
Reference in New Issue