;;; inf-snd.el -- Inferior Snd Process (Ruby/Guile/Forth)
;; Copyright (C) 2002--2006 Michael Scholz
;; Author: Michael Scholz <scholz-micha@gmx.de>
;; Created: Wed Nov 27 20:52:54 CET 2002
;; Changed: Sun Jan 15 12:10:40 CET 2006
;; Keywords: processes, snd, ruby, guile, forth
;; This file is not part of GNU Emacs.
;; This program 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 of the
;; License, or (at your option) any later version.
;; This program 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 this program; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
;; USA
;;; Commentary:
;; This file defines a snd-in-a-buffer package built on top of
;; comint-mode. It includes inferior mode for Snd-Ruby
;; (inf-snd-ruby-mode), Snd-Guile (inf-snd-guile-mode) and Snd-Forth
;; (inf-snd-forth-mode), furthermore a Snd-Ruby mode (snd-ruby-mode),
;; a Snd-Guile mode (snd-guile-mode) and a Snd-Forth mode
;; (snd-forth-mode) for editing source files. It is tested with
;; Snd-Ruby, Snd-Guile and Snd-Forth 7.18 and GNU Emacs 21.2/22.0.50.
;; Since this mode is built on top of the general command-interpreter-
;; in-a-buffer mode (comint-mode), it shares a common base
;; functionality, and a common set of bindings, with all modes derived
;; from comint mode. This makes these modes easier to use. For
;; documentation on the functionality provided by comint-mode, and the
;; hooks available for customizing it, see the file comint.el.
;; A nice feature may be the commands `inf-snd-help' and `snd-help',
;; which shows the description which Snd provides for many functions.
;; With tab-completion in the minibuffer you can scan all functions at
;; a glance. It should be easy to extent this mode with new commands
;; and key bindings; the example below and the code in this file may
;; show the way.
;; There exist six main modes in this file: the three inferior
;; Snd-process-modes (inf-snd-ruby-mode, inf-snd-guile-mode and
;; inf-snd-forth-mode) and the replacements of ruby-mode
;; (snd-ruby-mode), of scheme-mode (snd-guile-mode) and of gforth-mode
;; (snd-forth-mode).
;; Variables of the inferior Snd-process-modes
;; inf-snd-ruby|guile|forth-mode (defaults):
;;
;; inf-snd-ruby-program-name "snd-ruby" Snd-Ruby program name
;; inf-snd-guile-program-name "snd-guile" Snd-Guile program name
;; inf-snd-forth-program-name "snd-forth" Snd-Forth program name
;; inf-snd-working-directory "~/" where Ruby, Guile or Forth scripts reside
;; inf-snd-ruby-mode-hook nil to customize inf-snd-ruby-mode
;; inf-snd-guile-mode-hook nil to customize inf-snd-guile-mode
;; inf-snd-forth-mode-hook nil to customize inf-snd-forth-mode
;; inf-snd-ruby-quit-hook nil to reset snd variables before exit
;; inf-snd-guile-quit-hook nil to reset snd variables before exit
;; inf-snd-forth-quit-hook nil to reset snd variables before exit
;; inf-snd-index-path "~/" path to snd-xref.c
;; inf-snd-prompt ">" listener prompt
;; Variables of the editing modes snd-ruby|guile|forth-mode
;; (defaults):
;;
;; snd-ruby-mode-hook nil to customize snd-ruby-mode
;; snd-guile-mode-hook nil to customize snd-guile-mode
;; snd-forth-mode-hook nil to customize snd-forth-mode
;; You can start inf-snd-ruby-mode interactive either with prefix-key
;; (C-u M-x run-snd-ruby)--you will be ask for program name and
;; optional arguments--or direct (M-x run-snd-ruby). In the latter
;; case, variable inf-snd-ruby-program-name should be set correctly.
;; The same usage goes for inf-snd-guile-mode and inf-snd-forth-mode.
;; Example for your .emacs file:
;;
;; (autoload 'run-snd-ruby "inf-snd" "Start inferior Snd-Ruby process" t)
;; (autoload 'run-snd-guile "inf-snd" "Start inferior Snd-Guile process" t)
;; (autoload 'run-snd-forth "inf-snd" "Start inferior Snd-Forth process" t)
;; (autoload 'snd-ruby-mode "inf-snd" "Load snd-ruby-mode." t)
;; (autoload 'snd-guile-mode "inf-snd" "Load snd-guile-mode." t)
;; (autoload 'snd-forth-mode "inf-snd" "Load snd-forth-mode." t)
;;
;; ;; These variables should be set to your needs!
;; (setq inf-snd-ruby-program-name "snd-ruby -notebook")
;; (setq inf-snd-guile-program-name "snd-guile -separate")
;; (setq inf-snd-forth-program-name "snd-forth")
;; (setq inf-snd-working-directory "~/Snd/")
;; (setq inf-snd-index-path "~/Snd/snd/")
;; The hook-variables may be used to set new key bindings and menu
;; entries etc. in your .emacs file, e.g.:
;;
;; (defun snd-sounds ()
;; (interactive)
;; (inf-snd-send-string "(sounds)"))
;;
;; (add-hook 'inf-snd-ruby-mode-hook
;; '(lambda ()
;; (define-key (current-local-map) [menu-bar inf-snd-ruby-mode foo]
;; '("Sounds" . snd-sounds))
;; (define-key (current-local-map) "\C-c\C-t" 'snd-sounds)))
;;
;; To edit source code with special key bindings:
;;
;; (add-hook 'snd-ruby-mode-hook
;; '(lambda ()
;; (define-key (current-local-map) "\C-co" 'snd-send-buffer)
;; (define-key (current-local-map) "\C-cb" 'snd-send-block)
;; (define-key (current-local-map) "\C-cr" 'snd-send-region)
;; (define-key (current-local-map) "\C-ce" 'snd-send-definition)))
;;
;; (add-hook 'snd-guile-mode-hook
;; '(lambda ()
;; (define-key (current-local-map) "\C-co" 'snd-send-buffer)
;; (define-key (current-local-map) "\C-cr" 'snd-send-region)
;; (define-key (current-local-map) "\C-ce" 'snd-send-definition)))
;;
;; (add-hook 'snd-forth-mode-hook
;; '(lambda ()
;; (define-key (current-local-map) "\C-co" 'snd-send-buffer)
;; (define-key (current-local-map) "\C-cr" 'snd-send-region)
;; (define-key (current-local-map) "\C-ce" 'snd-send-definition)))
;; You can change the mode in a source file by M-x snd-ruby-mode (or
;; snd-guile-mode, snd-forth-mode). To determine automatically which
;; mode to set, you can decide to use special file-extensions. One
;; may use file-extension `.rbs' for Snd-Ruby source files and `.cms'
;; for Snd-Guile.
;;
;; (set-default 'auto-mode-alist
;; (append '(("\\.rbs$" . snd-ruby-mode)
;; ("\\.cms$" . snd-guile-mode))
;; auto-mode-alist))
;;
;; Or you can use the local mode variable in source files, e.g. by
;; `-*- snd-ruby -*-', `-*- snd-guile -*-' or `-*- snd-forth -*-' in
;; first line.
;; Key bindings for inf-* and snd-*-modes
;;
;; \e\TAB snd-completion symbol completion at point
;; C-h m describe-mode describe current major mode
;; Key binding of inf-snd-ruby|guile|forth-mode:
;;
;; C-c C-s inf-snd-run-snd (Snd-Ruby|Guile|Forth from a dead Snd process buffer)
;; M-C-l inf-snd-load load script in current working directory
;; C-c C-f inf-snd-file open view-files-dialog of Snd
;; M-C-p inf-snd-play play current sound file
;; C-c C-t inf-snd-stop stop playing all sound files
;; C-c C-i inf-snd-help help on Snd-function (snd-help)
;; C-u C-c C-i inf-snd-help-html help on Snd-function (html)
;; C-c C-q inf-snd-quit send exit to Snd process
;; C-c C-k inf-snd-kill kill Snd process and buffer
;; Key bindings of snd-ruby|guile|forth-mode editing source
;; files:
;;
;; C-c C-s snd-run-snd
;; M-C-x snd-send-definition
;; C-x C-e snd-send-last-sexp
;; C-c M-e snd-send-definition
;; C-c C-e snd-send-definition-and-go
;; C-c M-r snd-send-region
;; C-c C-r snd-send-region-and-go
;; C-c M-o snd-send-buffer
;; C-c C-o snd-send-buffer-and-go
;; C-c M-b snd-send-block (Ruby only)
;; C-c C-b snd-send-block-and-go (Ruby only)
;; C-c C-z snd-switch-to-snd
;; C-c C-l snd-load-file
;; C-u C-c C-l snd-load-file-protected (Ruby only)
;;
;; and in addition:
;;
;; C-c C-f snd-file open view-files-dialog of Snd
;; C-c C-p snd-play play current sound file
;; C-c C-t snd-stop stop playing all sound files
;; C-c C-i snd-help help on Snd-function (snd-help)
;; C-u C-c C-i snd-help-html help on Snd-function (html)
;; C-c C-q snd-quit send exit to Snd process
;; C-c C-k snd-kill kill Snd process and buffer
;;; Code:
;;;; The inf-snd-ruby-mode, inf-snd-guile-mode, and inf-snd-forth-mode.
(require 'comint)
(require 'ruby-mode)
(require 'scheme)
(require 'inf-ruby)
(require 'cmuscheme)
(require 'forth-mode "gforth")
(defconst inf-snd-version "15-Jan-2006"
"Version of inf-snd.el.")
;; snd-ruby
(defvar inf-snd-ruby-buffer "*Snd-Ruby*"
"Inferior Snd-Ruby process buffer.")
(defvar inf-snd-ruby-buffer-name "Snd-Ruby"
"Inferior Snd-Ruby process buffer name.")
(defvar inf-snd-ruby-mode-hook nil
"User hook variable of `inf-snd-ruby-mode'.
Will be called after `comint-mode-hook' and before starting
inferior Snd-Ruby process.")
(defvar inf-snd-ruby-quit-hook nil
"User hook variable of `inf-snd-ruby-mode'.
Will be called before finishing inferior Snd-Ruby process.")
(defvar inf-snd-ruby-program-name "snd-ruby"
"*User variable to set Snd-Ruby-program name and optional arguments.")
;; snd-forth
(defvar inf-snd-forth-buffer "*Snd-Forth*"
"Inferior Snd-Forth process buffer.")
(defvar inf-snd-forth-buffer-name "Snd-Forth"
"Inferior Snd-Forth process buffer name.")
(defvar inf-snd-forth-mode-hook nil
"User hook variable of `inf-snd-forth-mode'.
Will be called after `comint-mode-hook' and before starting
inferior Snd-Forth process.")
(defvar inf-snd-forth-quit-hook nil
"User hook variable of `inf-snd-forth-mode'.
Will be called before finishing inferior Snd-Forth process.")
(defvar inf-snd-forth-program-name "snd-forth"
"*User variable to set Snd-Forth-program name and optional arguments.")
;; snd-guile
(defvar inf-snd-guile-buffer "*Snd-Guile*"
"Inferior Snd-Guile process buffer.")
(defvar inf-snd-guile-buffer-name "Snd-Guile"
"Inferior Snd-Guile process buffer name.")
(defvar inf-snd-guile-mode-hook nil
"User hook variable of `inf-snd-guile-mode'.
Will be called after `comint-mode-hook' and before starting
inferior Snd-Guile process.")
(defvar inf-snd-guile-quit-hook nil
"User hook variable of `inf-snd-guile-mode'.
Will be called before finishing inferior Snd-Guile process.")
(defvar inf-snd-guile-program-name "snd-guile"
"*User variable to set Snd-Guile-program name and optional args.")
;; general
(defvar snd-completions-buffer "*Completions*"
"Snd completions buffer.")
(defvar inf-snd-prompt ">"
"*User variable to determine Snd's listener prompt.
Example: (setq inf-snd-prompt \"snd> \")")
(defvar inf-snd-working-directory "~/"
"*User variable where Emacs will find the Ruby, Forth, or Guile scripts.")
(defvar inf-snd-kind nil
"Options are 'ruby, 'forth, or 'guile.
Needed to determine which extension language to use. This variable is
buffer-local.")
(defvar inf-snd-index-path "~/"
"*User variable to path where snd-xref.c is located.")
(defvar snd-send-eval-file (expand-file-name
(concat
(user-login-name) "-snd-eval-file.rb") temporary-file-directory)
"*User variable of `inf-snd-ruby-mode' and `snd-ruby-mode'.
File where the commands will be collected before sending to
inferior Snd process.")
(defvar inf-snd-to-comment-regexp "^\\(Exception\\|undefined\\|([-A-Za-z]+)\\)"
"*User variable of `inf-snd-ruby-mode'.
Lines with regexp will be prepended by ruby's comment sign and space '# '.")
(defvar inf-snd-ruby-keywords nil
"Snd keywords providing online help.
\\<inf-snd-ruby-mode-map> Will be used by
`inf-snd-help' (\\[inf-snd-help], \\[universal-argument]
\\[inf-snd-help]) and `snd-help' (\\[snd-help],
\\[universal-argument] \\[snd-help]), taken from
snd/snd-xref.c. The user variable `inf-snd-index-path' should
point to the correct path where snd-xref.c is located.")
(defvar inf-snd-guile-keywords nil
"Snd keywords providing online help.
\\<inf-snd-guile-mode-map> Will be used by
`inf-snd-help' (\\[inf-snd-help], \\[universal-argument]
\\[inf-snd-help]) and `snd-help' (\\[snd-help],
\\[universal-argument] \\[snd-help]), taken from
snd/snd-xref.c. The user variable `inf-snd-index-path' should
point to the correct path where snd-xref.c is located.")
(defvar inf-snd-ruby-keyword-regexp "^ \"\\([A-Za-z0-9$_?!()]+?\\)\"[,}]+?"
"*User variable to find Snd-Ruby's keywords in snd-xref.c.")
(defvar inf-snd-guile-keyword-regexp "^ \"\\([-A-Za-z0-9*>?!()]+?\\)\"[,}]+?"
"*User variable to find Snd-Guile's and Snd-Forth's keywords in snd-xref.c.")
(defun inf-snd-set-keywords ()
"Set the keywords for `inf-snd-help'.
The user variable `inf-snd-index-path' should point to the
correct path of snd-xref.c to create valid keywords."
(let ((fbuf (find-file-noselect (concat (expand-file-name inf-snd-index-path) "snd-xref.c")))
(regex (if (eq 'ruby inf-snd-kind)
inf-snd-ruby-keyword-regexp
inf-snd-guile-keyword-regexp))
(keys '()))
(with-current-buffer fbuf
(goto-char (point-min))
(setq case-fold-search nil)
(while (re-search-forward regex nil t)
(let ((val (match-string 1)))
(or (member val keys)
(setq keys (cons val keys))))))
(kill-buffer fbuf)
keys))
;;; from share/emacs/22.0.50/lisp/thingatpt.el
;;; lisp-complete-symbol (&optional predicate)
(defun snd-completion ()
"Perform completion on Scheme or Ruby symbol preceding point.
Compare that symbol against the known Snd symbols.
If no characters can be completed, display a list of possible completions.
Repeating the command at that point scrolls the list."
(interactive)
(let ((window (get-buffer-window snd-completions-buffer)))
(if (and (eq last-command this-command)
window (window-live-p window) (window-buffer window)
(buffer-name (window-buffer window)))
;; If this command was repeated, and
;; there's a fresh completion window with a live buffer,
;; and this command is repeated, scroll that window.
(with-current-buffer (window-buffer window)
(if (pos-visible-in-window-p (point-max) window)
(set-window-start window (point-min))
(save-selected-window
(select-window window)
(scroll-up))))
;; Do completion.
(let* ((end (point))
(beg (save-excursion
(backward-sexp 1)
(while (= (char-syntax (following-char)) ?\')
(forward-char 1))
(point)))
(pattern (buffer-substring-no-properties beg end))
(key-list (if (eq 'ruby inf-snd-kind) inf-snd-ruby-keywords inf-snd-guile-keywords))
(completion (try-completion pattern key-list)))
(cond ((eq completion t))
((null completion)
(message "Can't find completion for \"%s\"" pattern))
((not (string= pattern completion))
(delete-region beg end)
(insert completion))
(t
(let ((list (all-completions pattern key-list)))
(setq list (sort list 'string<))
(with-output-to-temp-buffer snd-completions-buffer
(display-completion-list list)))))))))
(defun inf-snd-set-keys (mode name)
"Set the key bindings and menu entries for MODE.
Menu name is NAME. You can extend the key bindings and menu entries
here or via hook variables in .emacs file."
;; key bindings
(define-key (current-local-map) "\C-c\C-f" 'inf-snd-file)
(define-key (current-local-map) "\M-\C-l" 'inf-snd-load)
(define-key (current-local-map) "\M-\C-p" 'inf-snd-play)
(define-key (current-local-map) "\C-c\C-s" 'inf-snd-run-snd)
(define-key (current-local-map) "\C-c\C-t" 'inf-snd-stop)
(define-key (current-local-map) "\C-c\C-i" 'inf-snd-help)
(define-key (current-local-map) "\C-c\C-k" 'inf-snd-kill)
(define-key (current-local-map) "\C-c\C-q" 'inf-snd-quit)
(define-key (current-local-map) "\e\C-i" 'snd-completion)
;; menu entries in reverse order of appearance
(define-key (current-local-map) [menu-bar mode]
(cons name (make-sparse-keymap name)))
(define-key (current-local-map) [menu-bar mode kill]
'(menu-item "Kill Snd Process and Buffer" inf-snd-kill
:enable (inf-snd-proc-p)))
(define-key (current-local-map) [menu-bar mode quit]
'(menu-item "Send exit to Snd Process" inf-snd-quit
:enable (inf-snd-proc-p)))
(define-key (current-local-map) [menu-bar mode start-r]
'(menu-item "Start Snd-Ruby Process" inf-snd-run-snd
:enable (not (inf-snd-proc-p))
:visible (eq 'ruby inf-snd-kind)))
(define-key (current-local-map) [menu-bar mode start-f]
'(menu-item "Start Snd-Forth Process" inf-snd-run-snd
:enable (not (inf-snd-proc-p))
:visible (eq 'forth inf-snd-kind)))
(define-key (current-local-map) [menu-bar mode start-g]
'(menu-item "Start Snd-Guile Process" inf-snd-run-snd
:enable (not (inf-snd-proc-p))
:visible (eq 'guile inf-snd-kind)))
(define-key (current-local-map) [menu-bar mode sep-quit] '(menu-item "--"))
(define-key (current-local-map) [menu-bar mode desc]
'(menu-item "Describe Mode" describe-mode))
(define-key (current-local-map) [menu-bar mode help-html]
'(menu-item "Describe Snd Function (html) ..." inf-snd-help-html
:enable (inf-snd-proc-p)
:visible (not (eq 'ruby inf-snd-kind))))
(define-key (current-local-map) [menu-bar mode help]
'(menu-item "Describe Snd Function (snd-help) ..." inf-snd-help
:enable (inf-snd-proc-p)))
(define-key (current-local-map) [menu-bar mode sep-reset] '(menu-item "--"))
(define-key (current-local-map) [menu-bar mode stop]
'(menu-item "Stop Playing" inf-snd-stop
:enable (inf-snd-proc-p)))
(define-key (current-local-map) [menu-bar mode play]
'(menu-item "Start Playing" inf-snd-play
:enable (inf-snd-proc-p)))
(define-key (current-local-map) [menu-bar mode file]
'(menu-item "Open Snd-File Dialog" inf-snd-file
:enable (inf-snd-proc-p)))
(define-key (current-local-map) [menu-bar mode sep-play] '(menu-item "--"))
(define-key (current-local-map) [menu-bar mode load-r]
'(menu-item "Load Ruby Script ..." inf-snd-load
:enable (inf-snd-proc-p)
:visible (eq 'ruby inf-snd-kind)))
(define-key (current-local-map) [menu-bar mode load-f]
'(menu-item "Load Forth Script ..." inf-snd-load
:enable (inf-snd-proc-p)
:visible (eq 'forth inf-snd-kind)))
(define-key (current-local-map) [menu-bar mode load-g]
'(menu-item "Load Guile Script ..." inf-snd-load
:enable (inf-snd-proc-p)
:visible (eq 'guile inf-snd-kind))))
(defun inf-snd-send-string (str &optional no-strip-p)
"Print STR in buffer and send it to the inferior Snd process.
If NO-STRIP-P is nil, the default, all dashes (-) will be translated
to underlines (_), if `inf-snd-kind' is 'ruby. If NO-STRIP-P is
non-nil, it won't translate. See `inf-snd-load' for the latter case."
(interactive)
(and (not no-strip-p)
(eq 'ruby inf-snd-kind)
(while (string-match "-" str)
(setq str (replace-match "_" t nil str))))
(if (eq 'guile inf-snd-kind)
(setq str (concat "(" str ")")))
(with-current-buffer (inf-snd-proc-buffer)
(insert str)
(comint-send-input)))
(defun inf-snd-run-snd ()
"Start inferior Snd-Ruby, Snd-Forth, or Snd-Guile process.
Started from dead Snd process buffer."
(interactive)
(cond ((eq 'ruby inf-snd-kind)
(run-snd-ruby inf-snd-ruby-program-name))
((eq 'forth inf-snd-kind)
(run-snd-forth inf-snd-forth-program-name))
(t
(run-snd-guile inf-snd-guile-program-name))))
(defun inf-snd-file ()
"Open Snd's view-files-dialog widget."
(interactive)
(inf-snd-send-string "view-files-dialog"))
(defun inf-snd-load (file)
"Load the required Ruby, Forth, or Guile script.
Asks for FILE interactively in minibuffer."
(interactive "fLoad Snd Script: ")
(unless (file-directory-p file)
(inf-snd-send-string
(if (eq 'forth inf-snd-kind)
(format "include %s" (car (file-expand-wildcards file t)))
(format "load %S" (car (file-expand-wildcards file t)))) t)))
(defun inf-snd-play ()
"Play current sound."
(interactive)
(inf-snd-send-string "play"))
(defun inf-snd-stop ()
"Stop playing of all sound files."
(interactive)
(inf-snd-send-string "stop-playing"))
(defun inf-snd-help (&optional html-help)
"Receive a string in minibuffer and show corresponding help.
\\<inf-snd-ruby-mode-map>\\<inf-snd-forth-mode-map>\\<inf-snd-guile-mode-map>
This is done via Snd's function snd_help() or html() if HTML-HELP
is non-nil, i.e. it's called by \\[universal-argument]
\\[inf-snd-help], putting result at the end of the inferior Snd
process buffer. If point is near a function name in inferior Snd
process buffer, that function will be used as default value in
minibuffer; tab-completion is activated. `inf-snd-ruby-keywords'
and `inf-snd-guile-keywords' hold the help strings, the user
variable `inf-snd-index-path' should point to the correct path of
snd-xref.c."
(interactive "P")
(let ((prompt (format "Snd%s Help: " (if html-help " HTML" "")))
(default (thing-at-point 'sexp)))
(if default
(setq prompt (format "%s(default %s): " prompt default)))
(let ((str (completing-read prompt
(if (eq 'ruby inf-snd-kind)
inf-snd-ruby-keywords
inf-snd-guile-keywords)
nil nil nil nil default)))
(unless (string= str "")
(unless html-help
(while (string-match " " str)
(setq str (replace-match "" t nil str))))
(let ((inf-str (if (and html-help
(not (eq 'forth inf-snd-kind)))
(format "(html \"%s\")" str)
(cond ((eq 'ruby inf-snd-kind)
(format "Snd.display(snd_help(\"%s\", true))" str))
((eq 'forth inf-snd-kind)
(format "\"%s\" #t snd-help" str))
(t
(format "snd-help \"%s\" #t" str))))))
(with-current-buffer (inf-snd-proc-buffer)
(goto-char (point-max))
(if (and (string= (char-to-string (preceding-char)) inf-snd-prompt)
(eobp))
(inf-snd-send-string inf-str t)
(beginning-of-line)
(kill-region (point) (point-max))
(inf-snd-send-string inf-str t)
(yank))))))))
(defun inf-snd-help-html ()
"Start html help."
(interactive)
(inf-snd-help t))
(defun inf-snd-quit ()
"Send exit to inferior Snd process."
(interactive)
(cond ((eq 'ruby inf-snd-kind)
(run-hooks 'inf-snd-ruby-quit-hook))
((eq 'forth inf-snd-kind)
(run-hooks 'inf-snd-forth-quit-hook))
(t
(run-hooks 'inf-snd-guile-quit-hook)))
(if (bufferp snd-completions-buffer)
(kill-buffer snd-completions-buffer))
(get-buffer-process (inf-snd-proc-buffer))
(goto-char (point-max))
(cond ((eq 'ruby inf-snd-kind)
(snd-send-invisible "exit(0)"))
((eq 'forth inf-snd-kind)
(snd-send-invisible "0 snd-exit drop"))
(t
(snd-send-invisible "(exit 0)")))
(and (file-exists-p snd-send-eval-file)
(delete-file snd-send-eval-file)))
(defun inf-snd-kill ()
"Kill current inferior Snd process and buffer."
(interactive)
(inf-snd-quit)
(delete-process (get-buffer-process (inf-snd-proc-buffer)))
(kill-buffer (current-buffer))
(unless (one-window-p)
(delete-window (get-buffer-window (inf-snd-proc-buffer)))))
(defun inf-snd-proc-buffer ()
"Return the current process buffer."
(cond ((eq 'ruby inf-snd-kind)
inf-snd-ruby-buffer)
((eq 'forth inf-snd-kind)
inf-snd-forth-buffer)
(t
inf-snd-guile-buffer)))
(defun inf-snd-proc-p ()
"Return non-nil if process buffer is available."
(save-current-buffer
(comint-check-proc (inf-snd-proc-buffer))))
(defun snd-send-invisible (str &optional no-newline)
"Send a STR to the process running in the current buffer.
Non-nil NO-NEWLINE means string without carriage return append."
(let ((proc (get-buffer-process (current-buffer))))
(cond ((not proc)
(error "Current buffer has no process"))
((stringp str)
(comint-snapshot-last-prompt)
(if no-newline
(comint-send-string proc str)
(comint-simple-send proc str))))))
(defun inf-snd-comint-put-prompt-ruby (string)
"Look for `inf-snd-to-comment-regexp' in STRING in the current output.
Prepends matching lines with ruby's comment sign and space `# '.
Showing a prompt is forced by run_emacs_eval_hook() in
snd/examp.rb. This function could be on the so called abnormal
hook with one arg `comint-preoutput-filter-functions'."
(if (eq 'ruby inf-snd-kind)
(progn
(if (string-match "\\(nil\n$\\)" string)
(setq string (replace-match "" t nil string 1)))
(while (string-match inf-snd-to-comment-regexp string)
(setq string (replace-match "# \\1" t nil string 1)))))
string)
(defun inf-snd-comint-put-prompt-forth (string)
"Append `inf-snd-prompt' to STRING.
Furthermore looks for `inf-snd-to-comment-regexp' in STRING in
the current output. Prepends matching lines with ruby's comment
sign and space `# '. This function could be on the so called
abnormal hook with one arg `comint-preoutput-filter-functions'."
(if (eq 'forth inf-snd-kind)
(if (string-match "\\(nil\n\\)" string)
(setq string (replace-match inf-snd-prompt t nil string 1))))
string)
(defun inf-snd-comint-put-prompt-guile (string)
"Append `inf-snd-prompt' to STRING.
This function could be on the so called abnormal hook with one
arg `comint-preoutput-filter-functions'."
(if (eq 'guile inf-snd-kind)
(concat string inf-snd-prompt)
string))
(defun inf-snd-comint-snd-send (proc line)
"Special function for sending input LINE to PROC.
Variable `comint-input-sender' is set to this function. Running
Snd-Ruby it is necessary to load snd/examp.rb in your ~/.snd file
which contains run_emacs_eval_hook(line). Running Snd-Forth
run-emacs-eval-hook is in FTH's C-core. inf-snd.el uses this
function to evaluate one line or multi-line input (Ruby only)."
(if (= (length line) 0)
(if (eq 'guile inf-snd-kind) ;guile-1.7.x discards nil
(setq line "#f")
(setq line "nil")))
(comint-send-string proc
(cond ((eq 'ruby inf-snd-kind)
(format "run_emacs_eval_hook(%%(%s))\n" line))
((eq 'forth inf-snd-kind)
(format "%S run-emacs-eval-hook\n" (substring-no-properties line)))
(t
(concat line "\n")))))
(defun inf-snd-get-old-input ()
"Snarf the whole pointed line."
(save-excursion
(end-of-line)
(let ((end (point)))
(beginning-of-line)
(buffer-substring-no-properties (point) end))))
(defun inf-snd-args-to-list (string)
"Return a list containing the program and optional arguments list.
Argument STRING is the Snd command and optional arguments."
(let ((where (string-match "[ \t]" string)))
(cond ((null where) (list string))
((not (= where 0))
(cons (substring string 0 where)
(inf-snd-args-to-list (substring string (+ 1 where)
(length string)))))
(t (let ((pos (string-match "[^ \t]" string)))
(if (null pos)
nil
(inf-snd-args-to-list (substring string pos
(length string)))))))))
(define-derived-mode inf-snd-ruby-mode comint-mode inf-snd-ruby-buffer-name
"Inferior mode running Snd-Ruby, derived from `comint-mode'.
Snd is a sound editor created by Bill Schottstaedt
\(bil@ccrma.Stanford.EDU). You can find it on
ftp://ccrma-ftp.stanford.edu/pub/Lisp/snd-7.tar.gz.
You can type in Ruby commands in inferior Snd process buffer which
will be sent via `comint-send-string' to the inferior Snd process.
The return value will be shown in the process buffer, other output
goes to the listener of Snd.
You should set variable `inf-snd-ruby-program-name' and
`inf-snd-working-directory' in your .emacs file to set the appropriate
program name and optional arguments and to direct Snd to the Ruby
scripts directory, you have.
The hook variables `comint-mode-hook' and
`inf-snd-ruby-mode-hook' will be called in that special order
after calling the inferior Snd process. You can use them e.g. to
set additional key bindings. The hook variable
`inf-snd-ruby-quit-hook' will be called before finishing the
inferior Snd process. You may use it for resetting Snd
variables, e.g. the listener prompt.
\\<inf-snd-ruby-mode-map> Interactive start is possible either by
\\[universal-argument] \\[run-snd-ruby], you will be ask for the Snd
program name, or by \\[run-snd-ruby]. Emacs shows an additional menu
entry ``Snd-Ruby'' in the menu bar.
The following key bindings are defined:
\\{inf-snd-ruby-mode-map}"
(ruby-mode-variables)
(add-hook 'comint-preoutput-filter-functions 'inf-snd-comint-put-prompt-ruby nil t)
(add-hook 'comint-input-filter-functions 'ruby-input-filter nil t)
(setq comint-get-old-input (function inf-snd-get-old-input))
(setq comint-input-sender (function inf-snd-comint-snd-send))
(setq default-directory inf-snd-working-directory)
(make-local-variable 'inf-snd-prompt)
(make-local-variable 'inf-snd-kind)
(setq comint-prompt-regexp (concat "^\\(" inf-snd-prompt "\\)+"))
(setq inf-snd-kind 'ruby)
(setq mode-line-process '(":%s"))
(unless inf-snd-ruby-keywords
(setq inf-snd-ruby-keywords (inf-snd-set-keywords)))
(inf-snd-set-keys 'inf-snd-ruby-mode inf-snd-ruby-buffer-name)
(pop-to-buffer inf-snd-ruby-buffer)
(goto-char (point-max))
(run-hooks 'inf-snd-ruby-mode-hook))
(define-derived-mode inf-snd-forth-mode comint-mode inf-snd-forth-buffer-name
"Inferior mode running Snd-Forth, derived from `comint-mode'.
Snd is a sound editor created by Bill Schottstaedt
\(bil@ccrma.Stanford.EDU). You can find it on
ftp://ccrma-ftp.stanford.edu/pub/Lisp/snd-7.tar.gz.
You can type in Forth commands in inferior Snd process buffer which
will be sent via `comint-send-string' to the inferior Snd process.
The return value will be shown in the process buffer, other output
goes to the listener of Snd.
You should set variable `inf-snd-forth-program-name' and
`inf-snd-working-directory' in your .emacs file to set the appropriate
program name and optional arguments and to direct Snd to the Forth
scripts directory, you have.
The hook variables `comint-mode-hook' and
`inf-snd-forth-mode-hook' will be called in that special order
after calling the inferior Snd process. You can use them e.g. to
set additional key bindings. The hook variable
`inf-snd-forth-quit-hook' will be called before finishing the
inferior Snd process. You may use it for resetting Snd
variables, e.g. the listener prompt.
\\<inf-snd-forth-mode-map> Interactive start is possible either by
\\[universal-argument] \\[run-snd-forth], you will be ask for the Snd
program name, or by \\[run-snd-forth]. Emacs shows an additional menu
entry ``Snd-Forth'' in the menu bar.
The following key bindings are defined:
\\{inf-snd-forth-mode-map}"
(add-hook 'comint-preoutput-filter-functions 'inf-snd-comint-put-prompt-forth nil t)
(setq comint-get-old-input (function inf-snd-get-old-input))
(setq comint-input-sender (function inf-snd-comint-snd-send))
(setq default-directory inf-snd-working-directory)
(make-local-variable 'inf-snd-prompt)
(make-local-variable 'inf-snd-kind)
(setq comint-prompt-regexp (concat "^\\(" inf-snd-prompt "\\)+"))
(setq inf-snd-kind 'forth)
(setq mode-line-process '(":%s"))
(unless inf-snd-guile-keywords
(setq inf-snd-guile-keywords (inf-snd-set-keywords)))
(inf-snd-set-keys 'inf-snd-forth-mode inf-snd-forth-buffer-name)
(pop-to-buffer inf-snd-forth-buffer)
(goto-char (point-max))
(run-hooks 'inf-snd-forth-mode-hook))
(define-derived-mode inf-snd-guile-mode comint-mode inf-snd-guile-buffer-name
"Inferior mode running Snd-Guile, derived from `comint-mode'.
Snd is a sound editor created by Bill Schottstaedt
\(bil@ccrma.Stanford.EDU). You can find it on
ftp://ccrma-ftp.stanford.edu/pub/Lisp/snd-7.tar.gz.
You can type in Guile commands in inferior Snd process buffer which
will be sent via `comint-send-string' to the inferior Snd process.
The return value will be shown in the process buffer, other output
goes to the listener of Snd.
You sould set variable `inf-snd-guile-program-name' and
`inf-snd-working-directory' in your .emacs file to set the appropriate
program name and optional arguments and to direct Snd to the Guile
scripts directory, you have.
The hook variables `comint-mode-hook' and
`inf-snd-guile-mode-hook' will be called in that special order
after calling the inferior Snd process. You can use them e.g. to
set additional key bindings. The hook variable
`inf-snd-guile-quit-hook' will be called before finishing the
inferior Snd process. You may use it for resetting Snd
variables, e.g. the listener prompt.
\\<inf-snd-guile-mode-map> Interactive start is possible either by
\\[universal-argument] \\[run-snd-guile], you will be ask for the Snd
program name, or by \\[run-snd-guile]. Emacs shows an additional menu
entry ``Snd-Guile'' in the menu bar.
The following key bindings are defined:
\\{inf-snd-guile-mode-map}"
(scheme-mode-variables)
(add-hook 'comint-preoutput-filter-functions 'inf-snd-comint-put-prompt-guile nil t)
(add-hook 'comint-input-filter-functions 'scheme-input-filter nil t)
(setq comint-get-old-input (function scheme-get-old-input))
(setq comint-input-sender (function inf-snd-comint-snd-send))
(setq default-directory inf-snd-working-directory)
(make-local-variable 'inf-snd-prompt)
(make-local-variable 'inf-snd-kind)
(setq comint-prompt-regexp (concat "^\\(" inf-snd-prompt "\\)+"))
(setq inf-snd-kind 'guile)
(setq mode-line-process '(":%s"))
(unless inf-snd-guile-keywords
(setq inf-snd-guile-keywords (inf-snd-set-keywords)))
(inf-snd-set-keys 'inf-snd-guile-mode inf-snd-guile-buffer-name)
(pop-to-buffer inf-snd-guile-buffer)
(goto-char (point-max))
(run-hooks 'inf-snd-guile-mode-hook))
(defun run-snd-ruby (cmd)
"Start inferior Snd-Ruby process.
CMD is used for determine which program to run. If interactively
called, one will be asked for program name to run."
(interactive (list (if current-prefix-arg
(read-string "Run Snd Ruby: " inf-snd-ruby-program-name)
inf-snd-ruby-program-name)))
(unless (comint-check-proc inf-snd-ruby-buffer)
(let ((cmdlist (inf-snd-args-to-list cmd)))
(setq inf-snd-ruby-program-name cmd)
(set-buffer (apply 'make-comint inf-snd-ruby-buffer-name (car cmdlist) nil (cdr cmdlist))))
(inf-snd-ruby-mode)))
(defun run-snd-forth (cmd)
"Start inferior Snd-Forth process.
CMD is used for determine which program to run. If interactively
called, one will be asked for program name to run."
(interactive (list (if current-prefix-arg
(read-string "Run Snd Forth: " inf-snd-forth-program-name)
inf-snd-forth-program-name)))
(unless (comint-check-proc inf-snd-forth-buffer)
(let ((cmdlist (inf-snd-args-to-list cmd)))
(setq inf-snd-forth-program-name cmd)
(set-buffer (apply 'make-comint inf-snd-forth-buffer-name (car cmdlist) nil (cdr cmdlist))))
(inf-snd-forth-mode)
(snd-send-invisible "nil")))
(defun run-snd-guile (cmd)
"Start inferior Snd-Guile process.
CMD is used for determine which program to run. If interactively
called, one will be asked for program name to run."
(interactive (list (if current-prefix-arg
(read-string "Run Snd Guile: " inf-snd-guile-program-name)
inf-snd-guile-program-name)))
(unless (comint-check-proc inf-snd-guile-buffer)
(let ((cmdlist (inf-snd-args-to-list cmd)))
(setq inf-snd-guile-program-name cmd)
(set-buffer (apply 'make-comint inf-snd-guile-buffer-name (car cmdlist) nil (cdr cmdlist))))
(inf-snd-guile-mode)
(snd-send-invisible "#f")))
;;;; The snd-ruby-, snd-guile-, and snd-forth-mode
;;; Commentary:
;; These three modes are derived from ruby-mode, scheme-mode, and
;; forth-mode. The main changes are the key bindings, which now refer
;; to special Snd-process-buffer-related ones. I took commands from
;; inf-ruby.el, from cmuscheme.el and from gforth.el and changed them
;; appropriately.
(defvar snd-ruby-buffer-name "Snd/Ruby"
"Buffer name of `snd-ruby-mode'.")
(defvar snd-forth-buffer-name "Snd/Forth"
"Buffer name of `snd-forth-mode'.")
(defvar snd-guile-buffer-name "Snd/Guile"
"Buffer name of `snd-guile-mode'.")
(defvar snd-ruby-mode-hook nil
"User hook variable.
Called after `ruby-mode-hook' and before starting inferior Snd
process.")
(defvar snd-forth-mode-hook nil
"User hook variable.
Called after `forth-mode-hook' and before starting inferior Snd
process.")
(defvar snd-guile-mode-hook nil
"User hook variable.
Called after `scheme-mode-hook' and before starting inferior Snd
process.")
(defvar snd-source-modes '(snd-ruby-mode)
"Used to determine if a buffer contains Snd source code.
If it's loaded into a buffer that is in one of these major modes, it's
considered a Snd source file by `snd-load-file'. Used by this command
to determine defaults. This variable is buffer-local in
`snd-ruby-mode', `snd-forth-mode' and `snd-guile-mode'.")
(defvar snd-inf-kind 'ruby
"Options are 'ruby, 'forth, and 'guile.
Needed to determine which extension language should be used.
This variable is buffer-local in `snd-ruby-mode',
`snd-forth-mode', and `snd-guile-mode'.")
(defvar snd-prev-l/c-dir/file nil
"Cache the (directory . file) pair used in the last `snd-load-file'.
Used for determining the default in the next one.")
(define-derived-mode snd-ruby-mode ruby-mode snd-ruby-buffer-name
"Major mode for editing Snd-Ruby code.
Editing commands are similar to those of `ruby-mode'.
In addition, you can start an inferior Snd process and some
additional commands will be defined for evaluating expressions.
A menu ``Snd/Ruby'' appears in the menu bar. Entries in this
menu are disabled if no inferior Snd process exist.
You can use the hook variables `ruby-mode-hook' and
`snd-ruby-mode-hook', which will be called in that order.
The current key bindings are:
\\{snd-ruby-mode-map}"
(make-local-variable 'snd-inf-kind)
(make-local-variable 'snd-source-modes)
(setq snd-inf-kind 'ruby)
(setq snd-source-modes '(snd-ruby-mode))
(unless inf-snd-ruby-keywords
(setq inf-snd-ruby-keywords (inf-snd-set-keywords)))
(snd-set-keys 'snd-ruby-mode snd-ruby-buffer-name)
(run-hooks 'snd-ruby-mode-hook))
(define-derived-mode snd-forth-mode forth-mode snd-forth-buffer-name
"Major mode for editing Snd-Forth code.
Editing commands are similar to those of `forth-mode'.
In addition, you can start an inferior Snd process and some
additional commands will be defined for evaluating expressions.
A menu ``Snd/Forth'' appears in the menu bar. Entries in this
menu are disabled if no inferior Snd process exist.
You can use the hook variables `forth-mode-hook' and
`snd-forth-mode-hook', which will be called in that order.
The current key bindings are:
\\{snd-forth-mode-map}"
(make-local-variable 'snd-inf-kind)
(make-local-variable 'snd-source-modes)
(setq snd-inf-kind 'forth)
(setq snd-source-modes '(snd-forth-mode))
(unless inf-snd-guile-keywords
(setq inf-snd-guile-keywords (inf-snd-set-keywords)))
(snd-set-keys 'snd-forth-mode snd-forth-buffer-name)
(run-hooks 'snd-forth-mode-hook))
(define-derived-mode snd-guile-mode scheme-mode snd-guile-buffer-name
"Major mode for editing Snd-Guile code.
Editing commands are similar to those of `scheme-mode'.
In addition, you can start an inferior Snd process and some
additional commands will be defined for evaluating expressions.
A menu ``Snd/Guile'' appears in the menu bar. Entries in this
menu are disabled if no inferior Snd process exist.
You can use variables `scheme-mode-hook' and
`snd-guile-mode-hook', which will be called in that order.
The current key bindings are:
\\{snd-guile-mode-map}"
(make-local-variable 'snd-inf-kind)
(make-local-variable 'snd-source-modes)
(setq snd-inf-kind 'guile)
(setq snd-source-modes '(snd-guile-mode))
(unless inf-snd-guile-keywords
(setq inf-snd-guile-keywords (inf-snd-set-keywords)))
(snd-set-keys 'snd-guile-mode snd-guile-buffer-name)
(run-hooks 'snd-guile-mode-hook))
(defun snd-send-region (start end)
"Send the current region to the inferior Snd process.
START and END define the region."
(interactive "r")
(if (eq 'ruby snd-inf-kind)
(progn
(write-region start end snd-send-eval-file nil 0)
(comint-send-string
(snd-proc)
(format "eval(File.open(%S).read, TOPLEVEL_BINDING, \"(emacs-eval-region)\", 1).inspect \
rescue message(\"(emacs-eval-region): %%s (%%s)\\n%%s\", \
$!.message, $!.class, $!.backtrace.join(\"\\n\"))\n"
snd-send-eval-file)))
(comint-send-region (snd-proc) start end)
(comint-send-string (snd-proc) "\n")))
(defun snd-send-region-and-go (start end)
"Send the current region to the inferior Snd process.
Switch to the process buffer. START and END define the region."
(interactive "r")
(snd-send-region start end)
(snd-switch-to-snd t))
(defun snd-send-definition (&optional cnt)
"Send the current or CNT definition to the inferior Snd process."
(interactive "p")
(save-excursion
(if (eq 'ruby snd-inf-kind)
(ruby-beginning-of-defun cnt)
(beginning-of-defun cnt))
(let ((beg (point)))
(if (eq 'ruby snd-inf-kind)
(ruby-end-of-defun)
(end-of-defun))
(snd-send-region beg (point)))))
(defun snd-send-definition-and-go (&optional cnt)
"Send the current or CNT definition to the inferior Snd process.
Switch to the process buffer."
(interactive "p")
(snd-send-definition cnt)
(snd-switch-to-snd t))
(defun snd-send-last-sexp (&optional cnt)
"Send the previous or CNT sexp to the inferior Snd process."
(interactive "p")
(snd-send-region (save-excursion
(if (eq 'ruby snd-inf-kind)
(ruby-backward-sexp cnt)
(backward-sexp cnt))
(point))
(point)))
(defun snd-send-block (&optional cnt)
"Send the current or CNT block to the inferior Snd-Ruby process.
Works only in `snd-ruby-mode'."
(interactive "p")
(save-excursion
(ruby-beginning-of-block cnt)
(let ((beg (point)))
(ruby-end-of-block)
(end-of-line)
(snd-send-region beg (point)))))
(defun snd-send-block-and-go (&optional cnt)
"Send the current or CNT block to the inferior Snd-Ruby process.
Switch to the process buffer. Works only in `snd-ruby-mode'."
(interactive "p")
(snd-send-block cnt)
(snd-switch-to-snd t))
(defun snd-send-buffer ()
"Send the current buffer to the inferior Snd process."
(interactive)
(snd-send-region (point-min) (point-max)))
(defun snd-send-buffer-and-go ()
"Send the current buffer to the inferior Snd process.
Switch to the process buffer."
(interactive)
(snd-send-buffer)
(snd-switch-to-snd t))
(defun snd-switch-to-snd (&optional eob-p)
"If inferior Snd process exists, switch to process buffer, else start Snd.
Non-nil EOB-P positions cursor at end of buffer."
(interactive "P")
(let ((buf (snd-proc-buffer)))
(if (get-buffer buf)
(pop-to-buffer buf)
(snd-run-snd))
(if eob-p
(push-mark)
(goto-char (point-max)))))
(defun snd-run-snd ()
"If inferior Snd process exists, switch to process buffer, else start Snd.
Started from `snd-ruby-mode', `snd-forth-mode' or `snd-guile-mode'."
(interactive)
(if (snd-proc-p)
(progn
(pop-to-buffer (snd-proc-buffer))
(push-mark)
(goto-char (point-max)))
(cond ((eq 'ruby snd-inf-kind)
(run-snd-ruby inf-snd-ruby-program-name))
((eq 'forth snd-inf-kind)
(run-snd-forth inf-snd-forth-program-name))
(t
(run-snd-guile inf-snd-guile-program-name)))))
(defun snd-load-file-protected (filename)
"Load a Ruby script FILENAME as an anonymous module into the inferior Snd process."
(interactive (comint-get-source "Load Snd script file: "
snd-prev-l/c-dir/file snd-source-modes t))
(comint-check-source filename)
(setq snd-prev-l/c-dir/file (cons (file-name-directory filename)
(file-name-nondirectory filename)))
(comint-send-string (snd-proc) (concat "load(\"" filename "\", true)\n")))
(defun snd-load-file (filename)
"Load a Snd script FILENAME into the inferior Snd process."
(interactive (comint-get-source "Load Snd script file: "
snd-prev-l/c-dir/file snd-source-modes t))
(comint-check-source filename)
(setq snd-prev-l/c-dir/file (cons (file-name-directory filename)
(file-name-nondirectory filename)))
(if (eq 'forth snd-inf-kind)
(comint-send-string (snd-proc) (concat "listener-off include " filename " listener-on\n"))
(comint-send-string (snd-proc) (concat "(load \"" filename"\"\)\n"))))
(defun snd-save-state ()
"Synchronize the inferior Snd process with the edit buffer."
(and (snd-proc)
(setq inf-snd-kind snd-inf-kind)))
(defun snd-file ()
"Open Snd's view-files-dialog widget."
(interactive)
(snd-save-state)
(inf-snd-file))
(defun snd-play ()
"Play current sound."
(interactive)
(snd-save-state)
(inf-snd-play))
(defun snd-stop ()
"Stop playing of all sounds."
(interactive)
(snd-save-state)
(inf-snd-stop))
(defun snd-help (&optional html-help)
"Receive a string in minibuffer and show corresponding help.
\\<inf-snd-ruby-mode-map>\\<inf-snd-forth-mode-map>\\<inf-snd-guile-mode-map>
This is done via Snd's function snd_help() or html() if HTML-HELP
is non-nil, i.e. it's called by \\[universal-argument]
\\[snd-help], putting result at the end of the inferior Snd
process buffer. If point is near a function name in inferior Snd
process buffer, that function will be used as default value in
minibuffer; tab-completion is activated. `inf-snd-ruby-keywords'
and `inf-snd-guile-keywords' hold the help strings, the user
variable `inf-snd-index-path' should point to the correct path of
snd-xref.c."
(interactive "P")
(snd-save-state)
(inf-snd-help html-help))
(defun snd-help-html ()
"Start html help."
(interactive)
(snd-help t))
(defun snd-quit ()
"Send exit to current inferior Snd process."
(interactive)
(snd-save-state)
(save-excursion
(snd-switch-to-snd t)
(inf-snd-quit)))
(defun snd-kill ()
"Kill current inferior Snd process buffer."
(interactive)
(snd-save-state)
(save-excursion
(snd-switch-to-snd t)
(inf-snd-kill)))
(defun snd-proc-buffer ()
"Return the current process buffer."
(cond ((eq 'ruby snd-inf-kind)
inf-snd-ruby-buffer)
((eq 'forth snd-inf-kind)
inf-snd-forth-buffer)
(t
inf-snd-guile-buffer)))
(defun snd-proc ()
"Return the process buffer."
(let* ((buf (snd-proc-buffer))
(proc (get-buffer-process (if (eq major-mode
(cond ((eq 'ruby snd-inf-kind)
'inf-snd-ruby-mode)
((eq 'forth snd-inf-kind)
'inf-snd-forth-mode)
('
'inf-snd-guile-mode)))
(current-buffer)
buf))))
(or proc
(error "No current process. See variable inf-snd-ruby|inf-snd-forth|guile-buffer"))))
(defun snd-proc-p ()
"Return non-nil if no process buffer available."
(save-current-buffer
(comint-check-proc (snd-proc-buffer))))
(defun snd-set-keys (mode name)
"Set the key bindings and menu entries for MODE.
Menu name is NAME. You can extend the key bindings and menu entries
here or via hook variables in .emacs file."
(define-key (current-local-map) "\M-\C-x" 'snd-send-definition)
(define-key (current-local-map) "\C-x\C-e" 'snd-send-last-sexp)
(define-key (current-local-map) "\C-c\M-e" 'snd-send-definition)
(define-key (current-local-map) "\C-c\C-e" 'snd-send-definition-and-go)
(define-key (current-local-map) "\C-c\M-r" 'snd-send-region)
(define-key (current-local-map) "\C-c\C-r" 'snd-send-region-and-go)
(define-key (current-local-map) "\C-c\M-o" 'snd-send-buffer)
(define-key (current-local-map) "\C-c\C-o" 'snd-send-buffer-and-go)
(define-key (current-local-map) "\C-c\C-z" 'snd-switch-to-snd)
(define-key (current-local-map) "\C-c\C-s" 'snd-run-snd)
(define-key (current-local-map) "\C-c\C-l" 'snd-load-file)
(define-key (current-local-map) "\C-c\C-f" 'snd-file)
(define-key (current-local-map) "\C-c\C-p" 'snd-play)
(define-key (current-local-map) "\C-c\C-t" 'snd-stop)
(define-key (current-local-map) "\C-c\C-i" 'snd-help)
(define-key (current-local-map) "\C-c\C-k" 'snd-kill)
(define-key (current-local-map) "\C-c\C-q" 'snd-quit)
(define-key (current-local-map) "\e\C-i" 'snd-completion)
(if (eq 'ruby snd-inf-kind)
(progn
(define-key (current-local-map) "\C-c\M-b" 'snd-send-block)
(define-key (current-local-map) "\C-c\C-b" 'snd-send-block-and-go)
(define-key (current-local-map) "\C-cb" 'undefined) ;overwrite inf-ruby-commands
(define-key (current-local-map) "\C-cr" 'undefined) ;C-c + single letter key
(define-key (current-local-map) "\C-ce" 'undefined) ;is reserved for user
(define-key (current-local-map) "\C-c\C-x" 'undefined) ;key bindings
(define-key (current-local-map) "\C-c\M-x" 'undefined))
(define-key (current-local-map) "\C-c\C-c" 'undefined) ;no compile
(define-key (current-local-map) "\C-c\M-c" 'undefined))
(define-key (current-local-map) [menu-bar mode]
(cons name (make-sparse-keymap name)))
(define-key (current-local-map) [menu-bar mode kill]
'(menu-item "Kill Snd Process and Buffer" snd-kill
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode quit]
'(menu-item "Send exit to Snd Process" snd-quit
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode sep-quit] '(menu-item "--"))
(define-key (current-local-map) [menu-bar mode desc]
'(menu-item "Describe Mode" describe-mode))
(define-key (current-local-map) [menu-bar mode help-html]
'(menu-item "Describe Snd Function (html) ..." snd-help-html
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode help]
'(menu-item "Describe Snd Function (snd-help) ..." snd-help
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode sep-desc] '(menu-item "--"))
(define-key (current-local-map) [menu-bar mode stop]
'(menu-item "Stop Playing" snd-stop
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode play]
'(menu-item "Start Playing" snd-play
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode file]
'(menu-item "Open Snd-File Dialog" snd-file
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode sep-load] '(menu-item "--"))
(define-key (current-local-map) [menu-bar mode start-r]
'(menu-item "Start Snd-Ruby Process" snd-run-snd
:enable (not (snd-proc-p))
:visible (eq 'ruby snd-inf-kind)))
(define-key (current-local-map) [menu-bar mode start-f]
'(menu-item "Start Snd-Forth Process" snd-run-snd
:enable (not (snd-proc-p))
:visible (eq 'forth snd-inf-kind)))
(define-key (current-local-map) [menu-bar mode start-g]
'(menu-item "Start Snd-Guile Process" snd-run-snd
:enable (not (snd-proc-p))
:visible (eq 'guile snd-inf-kind)))
(define-key (current-local-map) [menu-bar mode switch]
'(menu-item "Switch to Snd Process" snd-switch-to-snd
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode sep-proc] '(menu-item "--"))
(define-key (current-local-map) [menu-bar mode block-go]
'(menu-item "Send Block and Go" snd-send-block-and-go
:enable (snd-proc-p)
:visible (eq 'ruby snd-inf-kind)))
(define-key (current-local-map) [menu-bar mode block]
'(menu-item "Send Block" snd-send-block
:enable (snd-proc-p)
:visible (eq 'ruby snd-inf-kind)))
(define-key (current-local-map) [menu-bar mode buffer-go]
'(menu-item "Send Buffer and Go" snd-send-buffer-and-go
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode buffer]
'(menu-item "Send Buffer" snd-send-buffer
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode region-go]
'(menu-item "Send Region and Go" snd-send-region-and-go
:enable (and (snd-proc-p) mark-active)))
(define-key (current-local-map) [menu-bar mode region]
'(menu-item "Send Region" snd-send-region
:enable (and (snd-proc-p) mark-active)))
(define-key (current-local-map) [menu-bar mode def-go]
'(menu-item "Send Definition and Go" snd-send-definition-and-go
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode def]
'(menu-item "Send Definition" snd-send-definition
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode last-sexp]
'(menu-item "Send last Sexp" snd-send-last-sexp
:enable (snd-proc-p)))
(define-key (current-local-map) [menu-bar mode sep-load] '(menu-item "--"))
(define-key (current-local-map) [menu-bar mode load-sec]
'(menu-item "Load Ruby Script (protected) ..." snd-load-file-protected
:enable (snd-proc-p)
:visible (eq 'ruby snd-inf-kind)))
(define-key (current-local-map) [menu-bar mode load-r]
'(menu-item "Load Ruby Script ..." snd-load-file
:enable (snd-proc-p)
:visible (eq 'ruby snd-inf-kind)))
(define-key (current-local-map) [menu-bar mode load-f]
'(menu-item "Load Forth Script ..." snd-load-file
:enable (snd-proc-p)
:visible (eq 'forth snd-inf-kind)))
(define-key (current-local-map) [menu-bar mode load-g]
'(menu-item "Load Guile Script ..." snd-load-file
:enable (snd-proc-p)
:visible (eq 'guile snd-inf-kind))))
(provide 'inf-snd)
;;; inf-snd.el ends here