;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Copyright (C) 1999 Juan Jose Garcia-Ripoll ;; ;; Warranty: ;; This package 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. ;; ;; To get a copy of the GNU General Public License, write to the Free ;; Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Authors: 1999 Juan Jose GARCIA-RIPOLL ;; Maintainer: worm@arrakis.es ;; Created: adapted from Olin Shiver's inferior lisp mode ;; Keywords: yorick inferior-yorick-mode ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; History: ;; $Log:$ ;; ;; $Id:$ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Yorick is a versatile, efficient and lightweight program which is ;; suitable both for doing numerics with tensors of any ranks and for ;; producing nice output from this type of data structures. ;; ;; This package provides a GNU Emacs major mode for interacting with any ;; variant of the Yorick program. It works much like inferior-lisp-mode, ;; from which it is derive. This means: ;; ;; 1) A variant of Yorick is run in the background. Commands are sent ;; to this process and its output is displayed on a separate buffer. ;; ;; 2) Commands and function and variable definitions can be sent from ;; any buffer which is in a yorick mode (see yorick-mode.el, which is ;; a separate package for editing yorick files). ;; ;; 3) The interaction is transpararent for the user. Once a region of ;; code is sent to Yorick, it is available for use in the interaction ;; buffer. This way you can code and try a function as many times as ;; you want. ;; ;; 4) The package filters out some of the garbage which is produced ;; by the interpreter: you will no longer see "cont>", "quot>", or ;; "com>" when sending code to the interpreter. ;; ;; INSTALLATION ;; ============ ;; ;; 1. Install yorick-mode.el. ;; ;; 2. Optionally byte-compile "inf-yorick.el" (see Emacs's doc). ;; ;; 3. Insert the following lines in your "~/.emacs" or public ;; "default.el": ;; ;; (autoload 'run-yorick "inf-yorick" "*Inferior mode for Yorick" t) ;; ;; 4. You can also add a hook for Yorick mode (the hook variable ;; `inferior-yorick-mode-hook' is run with no args, if that ;; variable is bound and has a non-nil value.) ;; ;; (add-hook 'inferior-yorick-mode-hook (function (lambda () ;; ...))) (require 'comint) (require 'yorick-mode) (defvar yorick-cont-prompt-ignore (let ((only-cont "\\(\\(cont\\|quot\\|comm\\)>[ \\t\\n\\r]*\\)") (all "\\(\\(cont\\|quot\\|comm\\|\\)>[ \\t\\n\\r]*\\)")) (concat "\\`" all "*" only-cont "\\'")) "") (defvar yorick-cont-prompt-simple (let ((important "\\(>[ \\t\\n\\r]*\\)") (all "\\(\\(cont\\|quot\\|comm\\|\\)>[ \\t\\n\\r]*\\)")) (concat "\\`" all "*" important "\\'")) "") (defvar yorick-cont-prompt-debug (let ((important "\\(debg>[ \\t\\n\\r]*\\)") (all "\\(\\(cont\\|quot\\|comm\\|\\)>[ \\t\\n\\r]*\\)")) (concat "\\`" all "*" important "\\'")) "") (defvar inferior-yorick-mode-map nil) (cond ((not inferior-yorick-mode-map) (setq inferior-yorick-mode-map (copy-keymap comint-mode-map)) (setq inferior-yorick-mode-map (nconc inferior-yorick-mode-map)) (define-key inferior-yorick-mode-map "\C-x\C-e" 'yorick-eval-line) (define-key inferior-yorick-mode-map "\C-c\C-l" 'yorick-load-file) ; (define-key inferior-yorick-mode-map "\C-c\C-k" 'yorick-compile-file) ; (define-key inferior-yorick-mode-map "\C-c\C-a" 'yorick-show-arglist) (define-key inferior-yorick-mode-map "\C-c\C-d" 'yorick-describe-sym) (define-key inferior-yorick-mode-map "\C-c\C-f" 'yorick-show-documentation) (define-key inferior-yorick-mode-map "\C-c\C-v" 'yorick-show-documentation))) (defvar inferior-yorick-buffer "*inferior-yorick*" "*The current inferior-yorick process buffer.") ;;; These commands augment Lisp mode, so you can process Lisp code in ;;; the source files. (define-key yorick-mode-map "\M-\C-x" 'yorick-eval-defun) ; Gnu convention (define-key yorick-mode-map "\C-x\C-e" 'yorick-eval-line) ; Gnu convention (define-key yorick-mode-map "\C-c\C-e" 'yorick-eval-defun) (define-key yorick-mode-map "\C-c\C-r" 'yorick-eval-region) ;(define-key yorick-mode-map "\C-c\C-c" 'yorick-compile-defun) (define-key yorick-mode-map "\C-c\C-z" 'switch-to-yorick) (define-key yorick-mode-map "\C-c\C-l" 'yorick-load-file) ;(define-key yorick-mode-map "\C-c\C-k" 'yorick-compile-file) ; "kompile" file ;(define-key yorick-mode-map "\C-c\C-a" 'yorick-show-arglist) (define-key yorick-mode-map "\C-c\C-d" 'yorick-describe-sym) (define-key yorick-mode-map "\C-c\C-f" 'yorick-show-documentation) (define-key yorick-mode-map "\C-c\C-v" 'yorick-show-documentation) (defvar inferior-yorick-program "yorick" "*Program name for invoking an inferior Yorick for Inferior Yorick mode.") (defvar inferior-yorick-load-command "include,\"%s\"\n" "*Format string for building an expresion to load a file.") (defvar inferior-yorick-prompt "^\\(\\(>\\|cont>\\|quot>\\|comm>\\|debg>\\)[ \\n\\r]*\\)+" "*Regexp to identify yoricks prompts") (defvar inferior-yorick-mode-hook '() "*Hook for customising Inferior Yorick mode.") (put 'inferior-yorick-mode 'mode-class 'special) (defun inferior-yorick-mode () "*Major mode for interacting with an inferior Yorick process. Runs a Yorick interpreter as a subprocess of Emacs, with Lisp I/O through an Emacs buffer. Variable `inferior-yorick-program' controls which interpreter is run. Variables `inferior-yorick-prompt', `yorick-cont-prompt-regexp' and `inferior-yorick-load-command' can customize this mode for different interpreters or environments. \\{inferior-yorick-mode-map} CUstomization: Entry to this mode runs the hooks on `comint-mode-hook' and `inferior-yorick-mode-hook' (in that order). You can send text to the inferior Yorick process from other buffers containing Yorick source and using yorick-mode. switch-to-yorick switches the current buffer to the interpreter. yorick-eval-line sends the current expression to the interpreter. yorick-eval-defun sends the current function to the interpreter. yorick-eval-region sends the current region to Yorick. Commands: Return after the end of the process' output sends the text from the end of the process to point. Return before the end of the process' output copies the sexp ending at point to the end of the process' output ands sends it. If you accidentally suspend your process, use \\[comint-continue-subjob] to continue it." (interactive) (comint-mode) (setq comint-prompt-regexp inferior-yorick-prompt) (setq major-mode 'inferior-yorick-mode) (setq mode-name "Inferior Yorick") (setq mode-line-process '(":%s")) ; (yorick-mode-variables t) (use-local-map inferior-yorick-mode-map) ; (setq comint-get-old-input (funtion yorick-get-old-input)) ; (setq comint-input-filter (function yorick-input-filter) ; (setq comint-input-sentinel 'ignore) (setq comint-process-echoes nil) (setq comint-preoutput-filter-functions '(inferior-yorick-output-filter)) (run-hooks 'inferior-yorick-mode-hook)) (defun inferior-yorick-output-filter (str) "Outputs \"\" if STR does match `inferior-yorick-filter-regexp'. Used to discard prompts." ; (print str) (cond ((string-match yorick-cont-prompt-simple str) ;(print 1) "> ") ((string-match yorick-cont-prompt-debug str) ;(print 2) "debg> ") ((string-match yorick-cont-prompt-ignore str) ;(print 3) "") (t (print 4) str))) (defun inferior-yorick (cmd) "Run an inferior Yorick process, input and output via buffer `*inferior-yorick*'. If there is a process already running in `*inferior-yorick*', jump to that buffer. With argument, allows you to edit the command line." (interactive (list (if current-prefix-arg (read-string "Run yorick: " inferior-yorick-program) inferior-yorick-program))) (if (not (comint-check-proc "*inferior-yorick*")) (let ((cmdlist (inferior-yorick-args-to-list cmd))) (set-buffer (apply (function make-comint) "inferior-yorick" (car cmdlist) nil (cdr cmdlist))) (inferior-yorick-mode))) (pop-to-buffer "*inferior-yorick*")) (defun run-yorick (&optional and-go) (interactive "P") (inferior-yorick inferior-yorick-program) (if and-go (switch-to-yorick t))) ;;; Break a string up into a list of arguments. ;;; This will break if you have an argument with whitespace, as in ;;; string = "-ab +c -x 'you lose'". (defun inferior-yorick-args-to-list (string) (let ((where (string-match "[ \t]" string))) (cond ((null where) (list string)) ((not (= where 0)) (cons (substring string 0 where) (inferior-yorick-args-to-list (substring string (+ 1 where) (length string))))) (t (let ((pos (string-match "[^ \t]" string))) (if (null pos) nil (inferior-yorick-args-to-list (substring string pos (length string))))))))) (defun inferior-yorick-proc () (let ((proc (get-buffer-process "*inferior-yorick*"))) (or proc (error "No Lisp subprocess; see variable `inferior-yorick-buffer'")))) (defun yorick-eval-region (start end &optional and-go) "Send the current region to the inferior Lisp process. Prefix argument means switch to the Lisp buffer afterwards." (interactive "r\nP") (comint-send-region (inferior-yorick-proc) start end) (comint-send-string (inferior-yorick-proc) "\n") (if and-go (switch-to-yorick t))) (defun yorick-eval-line (&optional and-go) "Send the current expression to the inferior Yorick process. Prefix argument means switch to the buffer afterwards." (interactive "P") (save-excursion (beginning-of-line 1) (let ((here (point))) (end-of-line 1) (yorick-eval-region here (point)))) (if and-go (switch-to-yorick t))) (defun yorick-eval-defun (&optional and-go) "Send the current defun to the inferior Lisp process. Prefix argument means switch to the Lisp buffer afterwards." (interactive "P") (save-excursion (c-beginning-of-defun 1) (search-backward "func ") (let ((start (point))) (c-end-of-defun 1) (yorick-eval-region start (point)))) (if and-go (switch-to-yorick t))) (defun switch-to-yorick (eob-p) "Switch to the inferior Yorick process buffer. With argument, positions cursor at end of buffer." (interactive "P") (if (get-buffer "*inferior-yorick*") (let ((pop-up-frames ;; Be willing to use another frame ;; that already has the window in it. (or pop-up-frames (get-buffer-window "*inferior-yorick*" t)))) (pop-to-buffer "*inferior-yorick*")) (error "No current inferior Lisp buffer")) (cond (eob-p (push-mark) (goto-char (point-max))))) ;;; Reads a string from the user. (defun yorick-symprompt (prompt default) (list (let* ((prompt (if default (format "%s (default %s): " prompt default) (concat prompt ": "))) (ans (read-string prompt))) (if (zerop (length ans)) default ans)))) (defun yorick-var-at-pt () (condition-case () (save-excursion (forward-sexp -1) (let ((obj (read (current-buffer)))) (and (symbolp obj) obj))) (error nil))) (defun yorick-describe-sym (sym) "Output the type of the symbol under the cursor." (interactive (yorick-symprompt "Describe" (yorick-var-at-pt))) (comint-proc-query (inferior-yorick-proc) (format "info,%s;\n" sym))) (defun yorick-show-documentation (sym) "Search the help database for the current symbol. Outputs text in the Yorick buffer." (interactive (yorick-symprompt "Describe" (yorick-var-at-pt))) (comint-proc-query (inferior-yorick-proc) (format "help,%s;\n" sym)))