Slang-mode
- slang-mode.el --- a major-mode for editing slang scripts
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
- Modified By
- Joe Robertson <jmrobert@sbcs.com>
- Modified From
- tcl-mode.el
- Original Author
- Gregor Schmid <schmid@fb3-s7.math.tu-berlin.de>
- Keywords
- languages, processes, tools
- This file is part of GNU Emacs.
- GNU Emacs 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.
- GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- Commentary
- Add these lines to your .emacs file to enable slang mode
- slang mode
- (autoload 'slang-mode "slang-mode"
- "Mode for editing slang source files")
- (setq auto-mode-alist
- (append '(("\\.sl$" . slang-mode)) auto-mode-alist))
- Special Thanks to Simon Marshall <simonm@mail.esrin.esa.it> for
- font-lock patches.
- This file was written with emacs using Jamie Lokier's folding mode
- That's what the funny ;;{{{ marks are there for
- {{{ Usage
- Slang-mode supports c-mode style formatting and sending of
- lines/regions/files to a slang interpreter. An interpreter (see
- variable `slang-default-application') will be started if you try to
- send some code and none is running. You can use the process-buffer
- (named after the application you chose) as if it were an
- interactive shell. See the documentation for `comint.el' for
- details.
- }}}
- {{{ Key-bindings
- To see all the keybindings for folding mode, look at `slang-setup-keymap'
- or start `slang-mode' and type `\C-h m'.
- The keybindings may seem strange, since I prefer to use them with
- slang-prefix-key set to nil, but since those keybindings are already used
- the default for `slang-prefix-key' is `\C-c', which is the conventional
- prefix for major-mode commands.
- You can customise the keybindings either by setting `slang-prefix-key'
- or by putting the following in your .emacs
- (setq slang-mode-map (make-sparse-keymap))
- and
- (define-key slang-mode-map <your-key> <function>)
- for all the functions you need.
- }}}
- {{{ Variables
- You may want to customize the following variables
- slang-indent-level
- slang-always-show
- slang-mode-map
- slang-prefix-key
- slang-mode-hook
- slang-default-application
- slang-default-command-switches
- }}}
- Code
- We need that !
(require 'comint)
- class\\
- {{{ slang-mode
- autoload
(defun slang-mode ()
"Major mode for editing slang scripts.
The following keys are bound: \\{slang-mode-map} "
(interactive) (let ((switches nil)
s)
(kill-all-local-variables) (setq major-mode 'slang-mode) (setq mode-name "SLANG") (set (make-local-variable 'slang-process) nil) (set (make-local-variable 'slang-process-buffer) nil) (make-local-variable 'slang-default-command-switches) (set (make-local-variable 'indent-line-function) 'slang-indent-line)
(set (make-local-variable 'comment-start) "% ") (set (make-local-variable 'comment-start-skip) "% *") (set (make-local-variable 'font-lock-defaults)
'(slang-font-lock-keywords nil nil ((?_ . "w") (?: . "w"))))
(set (make-local-variable 'imenu-generic-expression)
slang-imenu-generic-expression)
(setq imenu-case-fold-search nil) (setq imenu-syntax-alist '((?: . "w"))) (make-local-variable 'slang-default-eval) (or slang-mode-map
(slang-setup-keymap))
(use-local-map slang-mode-map) (set-syntax-table (copy-syntax-table)) ;;real comment keys is right here (modify-syntax-entry ?# "<") (modify-syntax-entry ?% "<") (modify-syntax-entry ?\n ">") ;; look for a #!.../wish -f line at bob (save-excursion (goto-char (point-min)) (if (looking-at "#![ \t]*\\([^ \t]*\\)[ \t]\\(.*[ \t]\\)-f")
(progn (set (make-local-variable 'slang-default-application) (buffer-substring (match-beginning 1) (match-end 1))) (if (match-beginning 2) (progn (goto-char (match-beginning 2)) (set (make-local-variable 'slang-default-command-switches) nil) (while (< (point) (match-end 2)) (setq s (read (current-buffer))) (if (<= (point) (match-end 2)) (setq slang-default-command-switches (append slang-default-command-switches (list (prin1-to-string s))))))))) ;; if this fails, look for the #!/bin/csh ... exec hack (while (eq (following-char) ?#) (forward-line 1)) (or (bobp) (forward-char -1)) (if (eq (preceding-char) ?\\) (progn (forward-char 1) (if (looking-at "exec[ \t]+\\([^ \t]*\\)[ \t]\\(.*[ \t]\\)*-f") (progn (set (make-local-variable 'slang-default-application) (buffer-substring (match-beginning 1) (match-end 1))) (if (match-beginning 2) (progn (goto-char (match-beginning 2)) (set (make-local-variable 'slang-default-command-switches) nil) (while (< (point) (match-end 2)) (setq s (read (current-buffer))) (if (<= (point) (match-end 2)) (setq slang-default-command-switches (append slang-default-command-switches (list (prin1-to-string s))))))))) )))))
(run-hooks 'slang-mode-hook)))
- }}}
- {{{ slang-setup-keymap
(defun slang-setup-keymap ()
"Set up keymap for slang mode.
If the variable `slang-prefix-key' is nil, the bindings go directly to `slang-mode-map', otherwise they are prefixed with `slang-prefix-key'."
(setq slang-mode-map (make-sparse-keymap)) (define-key slang-mode-map [menu-bar slang-mode] (cons "Slang-Mode" slang-mode-menu)) (let ((map (if slang-prefix-key
(make-sparse-keymap) slang-mode-map)))
;; indentation (define-key slang-mode-map [?}] 'slang-electric-brace) ;; communication (define-key map "\M-e" 'slang-send-current-line) (define-key map "\M-r" 'slang-send-region) (define-key map "\M-w" 'slang-send-proc) (define-key map "\M-a" 'slang-send-buffer) (define-key map "\M-q" 'slang-kill-process) (define-key map "\M-u" 'slang-restart-with-whole-file) (define-key map "\M-s" 'slang-show-process-buffer) (define-key map "\M-h" 'slang-hide-process-buffer) (define-key map "\M-i" 'slang-get-error-info) (define-key map "\M-[" 'slang-beginning-of-proc) (define-key map "\M-]" 'slang-end-of-proc) (define-key map "\C-\M-s" 'slang-set-slang-region-start) (define-key map "\C-\M-e" 'slang-set-slang-region-end) (define-key map "\C-\M-r" 'slang-send-slang-region) (if slang-prefix-key (define-key slang-mode-map slang-prefix-key map)) ))
- }}}
- {{{ indentation
- {{{ slang-indent-line
(defun slang-indent-line ()
"Indent current line as slang code.
Return the amount the indentation changed by."
(let ((indent (slang-calculate-indentation nil))
beg shift-amt (case-fold-search nil) (pos (- (point-max) (point))))
(beginning-of-line) (setq beg (point)) (skip-chars-forward " \t") (save-excursion (while (eq (following-char) ?})
(setq indent (max (- indent slang-indent-level) 0)) (forward-char 1) (if (looking-at "\\([ \t]*\\)}") (progn (delete-region (match-beginning 1) (match-end 1)) (insert-char ? (1- slang-indent-level))))))
(setq shift-amt (- indent (current-column))) (if (zerop shift-amt)
(if (> (- (point-max) pos) (point)) (goto-char (- (point-max) pos)))
(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))))
shift-amt))
- }}}
- \\({\\s *[%\n]\\)\\
- {{{ slang-electric-brace
(defun slang-electric-brace (arg)
"Insert `}' and indent line for slang." (interactive "P") (insert-char ?} (prefix-numeric-value arg)) (slang-indent-line) (blink-matching-open))
- }}}
- }}}
- {{{ searching
- {{{ slang-beginning-of-proc
(defun slang-beginning-of-proc (&optional arg)
"Move backward to the beginning of a slang proc (or similar).
With argument, do it that many times. Negative arg -N means move forward to Nth following beginning of proc. Returns t unless search stops due to beginning or end of buffer."
(interactive "P") (or arg (setq arg 1)) (let ((found nil)
(ret t))
(if (and (< arg 0)
(looking-at "^[^ \t\n%][^\n]*{[ \t]*$")) (forward-char 1))
(while (< arg 0) (if (re-search-forward "^[^ \t\n%][^\n]*{[ \t]*$" nil t)
(setq arg (1+ arg) found t) (setq ret nil arg 0)))
(if found
(beginning-of-line))
(while (> arg 0) (if (re-search-backward "^[^ \t\n%][^\n]*{[ \t]*$" nil t)
(setq arg (1- arg)) (setq ret nil arg 0)))
ret))
- }}}
- {{{ slang-end-of-proc
(defun slang-end-of-proc (&optional arg)
"Move forward to next end of slang proc (or similar).
With argument, do it that many times. Negative argument -N means move back to Nth preceding end of proc.
This function just searches for a `}' at the beginning of a line."
(interactive "P") (or arg (setq arg 1)) (let ((found nil)
(ret t))
(if (and (< arg 0)
(not (bolp)) (save-excursion (beginning-of-line) (eq (following-char) ?}))) (forward-char -1))
(while (> arg 0) (if (re-search-forward "^}" nil t)
(setq arg (1- arg) found t) (setq ret nil arg 0)))
(while (< arg 0) (if (re-search-backward "^}" nil t)
(setq arg (1+ arg) found t) (setq ret nil arg 0)))
(if found
(end-of-line))
ret))
- }}}
- }}}
- {{{ communication with a inferior process via comint
- {{{ slang-start-process
(defun slang-start-process (name program &optional startfile &rest switches)
"Start a slang process named NAME, running PROGRAM." (or switches (setq switches slang-default-command-switches)) (setq slang-process-buffer (apply 'make-comint name program startfile switches)) (setq slang-process (get-buffer-process slang-process-buffer)) (save-excursion (set-buffer slang-process-buffer) (setq comint-prompt-regexp "^[^% ]*\\(\\)* *") ) )
- }}}
- {{{ slang-kill-process
(defun slang-kill-process ()
"Kill slang subprocess and its buffer." (interactive) (if slang-process-buffer (kill-buffer slang-process-buffer)))
- }}}
- {{{ slang-set-slang-region-start
(defun slang-set-slang-region-start (&optional arg)
"Set start of region for use with `slang-send-slang-region'." (interactive) (set-marker slang-region-start (or arg (point))))
- }}}
- {{{ slang-set-slang-region-end
(defun slang-set-slang-region-end (&optional arg)
"Set end of region for use with `slang-send-slang-region'." (interactive) (set-marker slang-region-end (or arg (point))))
- }}}
- {{{ send line/region/buffer to slang-process
- {{{ slang-send-current-line
(defun slang-send-current-line ()
"Send current line to slang subprocess, found in `slang-process'.
If `slang-process' is nil or dead, start a new process first."
(interactive) (let ((start (save-excursion (beginning-of-line) (point)))
(end (save-excursion (end-of-line) (point))))
(or (and slang-process
(eq (process-status slang-process) 'run)) (slang-start-process slang-default-application slang-default-application))
(comint-simple-send slang-process (buffer-substring start end)) (forward-line 1) (if slang-always-show
(display-buffer slang-process-buffer))))
- }}}
- {{{ slang-send-region
(defun slang-send-region (start end)
"Send region to slang subprocess, wrapped in `eval { ... }'." (interactive "r") (or (and slang-process
(comint-check-proc slang-process-buffer))
(slang-start-process slang-default-application slang-default-application)) (comint-simple-send slang-process
(concat slang-default-eval " {\n"(buffer-substring start end) "\n}"))
(if slang-always-show (display-buffer slang-process-buffer)))
- }}}
- {{{ slang-send-slang-region
(defun slang-send-slang-region ()
"Send preset slang region to slang subprocess, wrapped in `eval { ... }'." (interactive) (or (and slang-region-start slang-region-end) (error "slang-region not set")) (or (and slang-process
(comint-check-proc slang-process-buffer))
(slang-start-process slang-default-application slang-default-application)) (comint-simple-send slang-process
(concat slang-default-eval " {\n" (buffer-substring slang-region-start slang-region-end) "\n}"))
(if slang-always-show (display-buffer slang-process-buffer)))
- }}}
- {{{ slang-send-proc
(defun slang-send-proc ()
"Send proc around point to slang subprocess, wrapped in `eval { ... }'." (interactive) (let (beg end) (save-excursion (slang-beginning-of-proc) (setq beg (point)) (slang-end-of-proc) (setq end (point))) (or (and slang-process
(comint-check-proc slang-process-buffer)) (slang-start-process slang-default-application slang-default-application))
(comint-simple-send slang-process
(concat slang-default-eval " {\n" (buffer-substring beg end) "\n}"))
(if slang-always-show
(display-buffer slang-process-buffer))))
- }}}
- {{{ slang-send-buffer
(defun slang-send-buffer ()
"Send whole buffer to slang subprocess, wrapped in `eval { ... }'." (interactive) (or (and slang-process
(comint-check-proc slang-process-buffer))
(slang-start-process slang-default-application slang-default-application)) (if (buffer-modified-p) (comint-simple-send slang-process
(concat slang-default-eval " {\n" (buffer-substring (point-min) (point-max)) "\n}"))
(comint-simple-send slang-process
(concat "source " (buffer-file-name) "\n")))
(if slang-always-show (display-buffer slang-process-buffer)))
- }}}
- }}}
- {{{ slang-get-error-info
(defun slang-get-error-info ()
"Send string `set errorInfo' to slang subprocess and display the slang buffer." (interactive) (or (and slang-process
(comint-check-proc slang-process-buffer))
(slang-start-process slang-default-application slang-default-application)) (comint-simple-send slang-process "set errorInfo\n") (display-buffer slang-process-buffer))
- }}}
- {{{ slang-restart-with-whole-file
(defun slang-restart-with-whole-file ()
"Restart slang subprocess and send whole file as input." (interactive) (slang-kill-process) (slang-start-process slang-default-application slang-default-application) (slang-send-buffer))
- }}}
- {{{ slang-show-process-buffer
(defun slang-show-process-buffer ()
"Make sure `slang-process-buffer' is being displayed." (interactive) (display-buffer slang-process-buffer))
- }}}
- {{{ slang-hide-process-buffer
(defun slang-hide-process-buffer ()
"Delete all windows that display `slang-process-buffer'." (interactive) (delete-windows-on slang-process-buffer))
- }}}
- }}}
- {{{ menu bar
(define-key slang-mode-menu [restart-with-whole-file]
'("Restart With Whole File" . slang-restart-with-whole-file))
(define-key slang-mode-menu [kill-process]
'("Kill Process" . slang-kill-process))
(define-key slang-mode-menu [hide-process-buffer]
'("Hide Process Buffer" . slang-hide-process-buffer))
(define-key slang-mode-menu [get-error-info]
'("Get Error Info" . slang-get-error-info))
(define-key slang-mode-menu [show-process-buffer]
'("Show Process Buffer" . slang-show-process-buffer))
(define-key slang-mode-menu [end-of-proc]
'("End Of Proc" . slang-end-of-proc))
(define-key slang-mode-menu [beginning-of-proc]
'("Beginning Of Proc" . slang-beginning-of-proc))
(define-key slang-mode-menu [send-slang-region]
'("Send Slang-Region" . slang-send-slang-region))
(define-key slang-mode-menu [set-slang-regio-end]
'("Set Slang-Region End" . slang-set-slang-region-end))
(define-key slang-mode-menu [set-slang-region-start]
'("Set Slang-Region Start" . slang-set-slang-region-start))
(define-key slang-mode-menu [send-current-line]
'("Send Current Line" . slang-send-current-line))
(define-key slang-mode-menu [send-region]
'("Send Region" . slang-send-region))
(define-key slang-mode-menu [send-proc]
'("Send Proc" . slang-send-proc))
(define-key slang-mode-menu [send-buffer]
'("Send Buffer" . slang-send-buffer))
- }}}
(provide 'slang-mode)
- {{{ Emacs local variables
- Local Variables
- folded-file
- t
- End
- }}}
- slang-mode.el ends here