Tim,
Attached is the REBOL mode lisp file (rebol.el) for emacs, and some
excellent comments/instructions posted by Jeff.
I have not had an opportunity to use REBOL mode extensively, but it
seems to work well.
Matt
[EMAIL PROTECTED] wrote:
> Hello:
> I believe that a thread on this ran over a week
> ago, and unfortunately, I didn't pay any attention to
> it at the time.
>
> I believe that someone connected to rebol has developed
> a mode file for emacs to handle rebol syntax.
>
> Does anyone know where it is available?
>
> TIA
> Tim
;;; rebol.el --- REBOL mode, and its idiosyncratic commands.
;; Copyright (C) 1986, 1987, 1988, 1998 Free Software Foundation, Inc.
;; Author: jrm <[EMAIL PROTECTED]>
;; Keywords: languages, lisp
;; This file is part of XEmacs.
;; XEmacs is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; XEmacs is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with XEmacs; see the file COPYING. If not, write to the Free
;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
;; 02111-1307, USA.
;;; Commentary:
;; Adapted from Scheme mode.
;; Initially a query replace of scheme mode.
;;; Code:
(defvar rebol nil
"Support for the REBOL programming language, <http://www.rebol.com/>")
; :group 'languages)
(defvar rebol-rebol-command "rebol"
"*Shell command used to start REBOL interpreter.")
; :type 'string
; :group 'rebol)
(defvar rebol-indent-offset 4
"*Amount of offset per level of indentation.")
; :type 'integer
; :group 'rebol)
(defvar rebol-backspace-function 'backward-delete-char-untabify
"*Function called by `rebol-electric-backspace' when deleting backwards.")
; :type 'function
; :group 'rebol)
(defvar rebol-delete-function 'delete-char
"*Function called by `rebol-electric-delete' when deleting forwards.")
; :type 'function
; :group 'rebol)
;;;###autoload
(defun rebol-mode ()
"Major mode for editing REBOL code.
In addition, if an inferior Rebol process is running, some additional
commands will be defined, for evaluating expressions and controlling
the interpreter, and the state of the process will be displayed in the
modeline of all Rebol buffers. The names of commands that interact
with the Rebol process start with \"xrebol-\". For more information
see the documentation for xrebol-interaction-mode.
Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs. Semicolons start comments.
\\{rebol-mode-map}
Entry to this mode calls the value of rebol-mode-hook
if that value is non-nil."
(interactive)
(column-number-mode nil)
(kill-all-local-variables)
(rebol-mode-initialize)
(rebol-mode-variables)
(run-hooks 'rebol-mode-hook))
(defun rebol-mode-initialize ()
(use-local-map rebol-mode-map)
(setq major-mode 'rebol-mode)
(setq tab-width 4) ; Added these two. -jeff
(setq tab-stop-list '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84
88 92 96 100 104 108 112 116 120))
(setq mode-name "REBOL"))
(defun beginning-of-rebol-definition ()
"Moves point to the beginning of the current REBOL definition"
(interactive)
(re-search-backward "^[a-zA-Z][a-zA-Z0-9---_]*:" nil 'move)
)
(defun rebol-comment-indent (&optional pos)
(save-excursion
(if pos (goto-char pos))
(cond ((looking-at ";;;") (current-column))
((looking-at ";;")
(let ((tem (guess-rebol-indent)))
(if (listp tem) (car tem) tem)))
(t
(skip-chars-backward " \t")
(max (if (bolp) 0 (1+ (current-column)))
comment-column)))))
(defvar rebol-indent-function 'rebol-indent-function "")
(defun rebol-indent-line (&optional whole-exp)
"Indent current line as REBOL code.
With argument, indent any additional lines of the same expression
rigidly along with this one."
(interactive "P")
(let ((indent (guess-rebol-indent)) shift-amt beg end
(pos (- (point-max) (point))))
(beginning-of-line)
(setq beg (point))
(skip-chars-forward " \t")
(if (looking-at "[ \t]*;;;")
;; Don't alter indentation of a ;;; comment line.
nil
(if (listp indent) (setq indent (car indent)))
(setq shift-amt (- indent (current-column)))
(if (zerop shift-amt)
nil
(delete-region beg (point))
(indent-to indent))
;; If initial point was within line's indentation,
;; position after the indentation. Else stay at same point in text.
(if (> (- (point-max) pos) (point))
(goto-char (- (point-max) pos)))
;; If desired, shift remaining lines of expression the same amount.
(and whole-exp (not (zerop shift-amt))
(save-excursion
(goto-char beg)
(forward-sexp 1)
(setq end (point))
(goto-char beg)
(forward-line 1)
(setq beg (point))
(> end beg))
(indent-code-rigidly beg end shift-amt)))))
(defun guess-rebol-indent (&optional parse-start)
"Return appropriate indentation for current line as rebol code.
In usual case returns an integer: the column to indent to.
Can instead return a list, whose car is the column to indent to.
This means that following lines at the same level of indentation
should not necessarily be indented the same way.
The second element of the list is the buffer position
of the start of the containing expression."
(save-excursion
(beginning-of-line)
(let ((indent-point (point))
indenting-block-p
state
block-depth
desired-indent
(retry t)
last-expr
containing-expr
first-expr-list-p)
(setq indenting-block-p (looking-at "^[ \t]*\\s("))
(if parse-start
(goto-char parse-start)
(beginning-of-rebol-definition))
;; Find outermost containing expr
(while (< (point) indent-point)
(setq state (parse-partial-sexp (point) indent-point 0)))
;; Find innermost containing sexp
(while (and retry (setq block-depth (car state)) (> block-depth 0))
(setq retry nil)
(setq last-expr (nth 2 state))
(setq containing-expr (car (cdr state)))
;; Position following last unclosed open.
(goto-char (1+ containing-expr))
;; Is there a complete sexp since then?
(if (and last-expr (> last-expr (point)))
;; Yes, but is there a containing expr after that?
(let ((peek (parse-partial-sexp last-expr indent-point 0)))
(if (setq retry (car (cdr peek))) (setq state peek))))
(if (not retry)
;; Innermost containing sexp found
(progn
(goto-char (1+ containing-expr))
(if (not last-expr)
;; indent-point immediately follows open paren.
;; Don't call hook.
(and (print block-depth)
(setq desired-indent (* block-depth rebol-indent-offset)))
(and (print (format "Close: %d" block-depth))
(setq desired-indent (- (* block-depth rebol-indent-offset) 4)))
;; Move to first expr after containing open paren
(parse-partial-sexp (point) last-expr 0 t)
(setq first-expr-list-p (looking-at "\\s("))
(cond
((> (save-excursion (forward-line 1) (point))
last-expr)
;; Last expr is on same line as containing expr.
;; It's almost certainly a function call.
(parse-partial-sexp (point) last-expr 0 t)
(if (/= (point) last-expr)
;; Indent beneath first argument or, if only one expr
;; on line, indent beneath that.
(progn (if indenting-block-p (forward-sexp 1))
(parse-partial-sexp (point) last-expr 0 t)))
(backward-prefix-chars))
(t
;; Indent beneath first expr on same line as last-expr.
;; Again, it's almost certainly a function call.
(goto-char last-expr)
(beginning-of-line)
(parse-partial-sexp (point) last-expr 0 t)
(backward-prefix-chars)))
))))
(cond ((car (nthcdr 3 state))
; ;; Inside a string, don't change indentation.
(goto-char indent-point)
(skip-chars-forward " \t")
(setq desired-indent (current-column)))
;
((not (or desired-indent
(and (boundp 'rebol-indent-function)
rebol-indent-function
(not retry)
(setq desired-indent
(funcall rebol-indent-function
indent-point state)))))
;; Use default indentation if not computed yet
(setq desired-indent (current-column))))
desired-indent
)))
(defun rebol-indent-function (indent-point state)
(let ((normal-indent (current-column)))
(save-excursion
(goto-char (1+ (car (cdr state))))
(re-search-forward "\\sw\\|\\s_")
(if (/= (point) (car (cdr state)))
(let ((function (buffer-substring (progn (forward-char -1) (point))
(progn (forward-sexp 1) (point))))
method)
;; Who cares about this, really?
;(if (not (string-match "\\\\\\||" function)))
(setq function (downcase function))
(setq method (get (intern-soft function) 'rebol-indent-function))
(cond ((integerp method)
(rebol-indent-specform method state indent-point))
(method
(funcall method state indent-point))
))))))
(defvar rebol-body-indent 2 "")
(defun rebol-indent-specform (count state indent-point)
(let ((containing-form-start (car (cdr state))) (i count)
body-indent containing-form-column)
;; Move to the start of containing form, calculate indentation
;; to use for non-distinguished forms (> count), and move past the
;; function symbol. rebol-indent-function guarantees that there is at
;; least one word or symbol character following open paren of containing
;; form.
(goto-char containing-form-start)
(setq containing-form-column (current-column))
(setq body-indent (+ rebol-body-indent containing-form-column))
(forward-char 1)
(forward-sexp 1)
;; Now find the start of the last form.
(parse-partial-sexp (point) indent-point 1 t)
(while (and (< (point) indent-point)
(condition-case nil
(progn
(setq count (1- count))
(forward-sexp 1)
(parse-partial-sexp (point) indent-point 1 t))
(error nil))))
;; Point is sitting on first character of last (or count) sexp.
(cond ((> count 0)
;; A distinguished form. Use double rebol-body-indent.
(list (+ containing-form-column (* 2 rebol-body-indent))
containing-form-start))
;; A non-distinguished form. Use body-indent if there are no
;; distinguished forms and this is the first undistinguished
;; form, or if this is the first undistinguished form and
;; the preceding distinguished form has indentation at least
;; as great as body-indent.
((and (= count 0)
(or (= i 0)
(<= body-indent normal-indent)))
body-indent)
(t
normal-indent))))
(defun rebol-indent-defform (state indent-point)
(goto-char (car (cdr state)))
(forward-line 1)
(if (> (point) (car (cdr (cdr state))))
(progn
(goto-char (car (cdr state)))
(+ rebol-body-indent (current-column)))))
;;; Let is different in Rebol
(defun would-be-symbol (string)
(not (string-equal (substring string 0 1) "(")))
(defun next-sexp-as-string ()
;; Assumes that protected by a save-excursion
(forward-sexp 1)
(let ((the-end (point)))
(backward-sexp 1)
(buffer-substring (point) the-end)))
(defun rebol-let-indent (state indent-point)
(skip-chars-forward " \t")
(if (looking-at "[-a-zA-Z0-9+*/?!@$%^&_:~]")
(rebol-indent-specform 2 state indent-point)
(rebol-indent-specform 1 state indent-point)))
(defun rebol-indent-expr ()
"Indent each line of the list starting just after point."
(interactive)
(let ((indent-stack (list nil)) (next-depth 0) bol
outer-loop-done inner-loop-done state this-indent)
(save-excursion (forward-sexp 1))
(save-excursion
(setq outer-loop-done nil)
(while (not outer-loop-done)
(setq last-depth next-depth
innerloop-done nil)
(while (and (not innerloop-done)
(not (setq outer-loop-done (eobp))))
(setq state (parse-partial-sexp (point) (progn (end-of-line) (point))
nil nil state))
(setq next-depth (car state))
(if (car (nthcdr 4 state))
(progn (indent-for-comment)
(end-of-line)
(setcar (nthcdr 4 state) nil)))
(if (car (nthcdr 3 state))
(progn
(forward-line 1)
(setcar (nthcdr 5 state) nil))
(setq innerloop-done t)))
(if (setq outer-loop-done (<= next-depth 0))
nil
(while (> last-depth next-depth)
(setq indent-stack (cdr indent-stack)
last-depth (1- last-depth)))
(while (< last-depth next-depth)
(setq indent-stack (cons nil indent-stack)
last-depth (1+ last-depth)))
(forward-line 1)
(setq bol (point))
(skip-chars-forward " \t")
(if (or (eobp) (looking-at "[;\n]"))
nil
(if (and (car indent-stack)
(>= (car indent-stack) 0))
(setq this-indent (car indent-stack))
(let ((val (guess-rebol-indent
(if (car indent-stack) (- (car indent-stack))))))
(if (integerp val)
(setcar indent-stack
(setq this-indent val))
(if (cdr val)
(setcar indent-stack (- (car (cdr val)))))
(setq this-indent (car val)))))
(if (/= (current-column) this-indent)
(progn (delete-region bol (point))
(indent-to this-indent)))))))))
(provide 'rebol)
;; Messing with these hasn't helped the
;; problem of curely braced strings munging
;; the mode. -jeff
(defvar rebol-font-lock-keywords
(list
'("\\<\\(%[^ \n\r]+\\)" 1 font-lock-string-face)
'("\\<\\(http\\|ftp\\|mailto\\|file\\):[^ \n\r]+" . 1)
'("\\<\\(make-[^\n\r]+\\)")
'("\\<\\(all\\|any\\|catch\\|do\\|else\\|for\\|forall\\|forskip\\||func\\|if\\|loop\\|make\\|reduce\\|repeat\\|shield\\|unset\\|use\\|while\\)\\>"
. 1)
'("\\(\\<foreach\\>\\)[ \t\n]+\\([^ \t\r\n()]+\\)" (1 font-lock-keyword-face) (2
font-lock-function-name-face nil t))
'("\\(:?[0-9---]+:[:.,0-9]+\\)" . 1)
'(":\\([^][ \t\r\n{}()]+\\)" 1 font-lock-variable-name-face)
'("\\([^][ \t\r\n{}()]+\\):" 1 font-lock-function-name-face)
'("\\(\\sw+!\\)" 1 font-lock-type-face)
;;; '("\\([a-zA-Z0-9---_]+:\\>\\)" 1 font-lock-function-name-face)
)
"Additional expressions to highlight in REBOL mode.")
(put 'rebol-mode 'font-lock-defaults '(rebol-font-lock-keywords))
(defvar rebol-mode-syntax-table nil
"Syntax table for REBOL buffers.")
(if (not rebol-mode-syntax-table)
(let ((i 0))
(setq rebol-mode-syntax-table (make-syntax-table))
(set-syntax-table rebol-mode-syntax-table)
;; Default is `word' constituent.
(while (< i 256)
(modify-syntax-entry i "_ ")
(setq i (1+ i)))
;; Digits are word components.
(setq i ?0)
(while (<= i ?9)
(modify-syntax-entry i "w ")
(setq i (1+ i)))
;; As are upper and lower case.
(setq i ?A)
(while (<= i ?Z)
(modify-syntax-entry i "w ")
(setq i (1+ i)))
(setq i ?a)
(while (<= i ?z)
(modify-syntax-entry i "w ")
(setq i (1+ i)))
;; Whitespace
(modify-syntax-entry ?\t " ")
(modify-syntax-entry ?\n "> ")
(modify-syntax-entry ?\f " ")
(modify-syntax-entry ?\r " ")
(modify-syntax-entry ? " ")
;; Delimiters
(modify-syntax-entry ?[ "(] ")
(modify-syntax-entry ?] ")[ ")
(modify-syntax-entry ?\( "() ")
(modify-syntax-entry ?\) ")( ")
;; comments
(modify-syntax-entry ?\; "< ")
(modify-syntax-entry ?\" "\" ")
(modify-syntax-entry ?{ " ")
(modify-syntax-entry ?} " ")
(modify-syntax-entry ?' " p")
(modify-syntax-entry ?` " p")
(modify-syntax-entry ?^ "\\ ")))
(defvar rebol-mode-abbrev-table nil
"*Abbrev table for rebol-mode buffers")
(define-abbrev-table 'rebol-mode-abbrev-table ())
(defun rebol-mode-variables ()
(set-syntax-table rebol-mode-syntax-table)
(setq local-abbrev-table rebol-mode-abbrev-table)
(make-local-variable 'paragraph-start)
(setq paragraph-start (concat "$\\|" page-delimiter))
(make-local-variable 'paragraph-separate)
(setq paragraph-separate paragraph-start)
(make-local-variable 'paragraph-ignore-fill-prefix)
(setq paragraph-ignore-fill-prefix t)
(make-local-variable 'indent-line-function)
(setq indent-line-function 'rebol-indent-line)
(make-local-variable 'parse-expr-ignore-comments)
(setq parse-expr-ignore-comments t)
(make-local-variable 'comment-start)
(setq comment-start ";")
(make-local-variable 'comment-start-skip)
;; Look within the line for a ; following an even number of backslashes
;; after either a non-backslash or the line beginning.
(setq comment-start-skip "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+[ \t]*")
(make-local-variable 'comment-column)
(setq comment-column 40)
(make-local-variable 'comment-indent-function)
(setq comment-indent-function 'rebol-comment-indent)
(make-local-variable 'parse-expr-ignore-comments)
(setq parse-expr-ignore-comments t)
(setq mode-line-process '("" rebol-mode-line-process)))
(defvar rebol-mode-line-process "")
(defun rebol-mode-commands (map)
(define-key map "\e\C-a" 'beginning-of-rebol-definition)
(define-key map "\t" 'rebol-indent-line)
(define-key map "\e\C-q" 'rebol-indent-expr))
(defvar rebol-mode-map nil)
(if (not rebol-mode-map)
(progn
(setq rebol-mode-map (make-sparse-keymap))
(rebol-mode-commands rebol-mode-map)))
Subject: [REBOL] emacs colors Re:(5)
Date: Wed, 17 May 2000 10:17:12 -0800
From: [EMAIL PROTECTED]
Reply-To: [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
Howdy, Fredrik
( and other brothers and sisters of the EMACS faith (-: ):
Okay, you may want to byte-compile the file first:
M-x byte-compile-file
This will produce "rebol.elc". Then you might put this in
your home directory. You may need to add your home
directory to the search path. Add this to your .emacs:
(setq load-path (cons "/path/to/your-home-dir" load-path))
After that you can add this line:
(load "rebol")
To associate the mode with .r files add:
(setq auto-mode-alist
(cons '("\\.r$" . rebol-mode)
auto-mode-alist))
Now here's a real handy piece of elisp to rebol glue code:
(defun go-rebol ()
(interactive)
(progn
(mark-whole-buffer)
(write-region (buffer-string) 0 "/path/to/somewhere/.temp.r")
(switch-to-buffer (process-buffer (setq proc (start-process "subrebol"
"subrebol" "/path/to/rebol" "-s"
"/path/to/somewhere/.temp.r"))))
(comint-mode)
)
)
(global-set-key "\M-e" (quote go-rebol))
;- changing all the paths to where ever they are.
Now you can be in a buffer making a script, type M-e and it
will pass your script to rebol and start it in a separate
buffer.
Good luck!
If any one out there has some experience dealing with emacs
modes, the rebol.el emacs mode could use your help. There
are still a couple things wrong with the way it parses
strings in particular and where it places close square
brackets.
-jeff
> src> print emacs-mode: read http://www.rebol.org/rebol.el
>
> Thank you.
>
> Now I'm not this good at emacs, the program is very good,
> but i cannot figure out where to put the rebol.el file and
> how to include/start it in emacs.
>
> I tried: ESC-x load-file <path>rebol.el (add-hook
> 'rebol-mode-hook 'turn-on-font-lock)
>
> neither one works, may be because this isn't the right way?
>
> Regards, Fredrik Bergstrom
>
> --
>
> [ PowerWebs have a good Webhotel for everyone, supports
> Rebol to =) ] [ www.powerwebs.se ]
>
> PowerWebs AB W��xn��sgatan 10 S-653 40 Karlstad Sweden Tel:
> +46-(0)54-103377 Fax: +46-(0)54-103376 ICQ# 7654213
>
>
>