X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/092af6d8677fa62567a0cf03502123cb177fb317..cb625535b532afa1017ed5b6ff7ca0b25f1e3b0a:/lisp/progmodes/octave-inf.el diff --git a/lisp/progmodes/octave-inf.el b/lisp/progmodes/octave-inf.el index cbe4ffcc89..791f42307f 100644 --- a/lisp/progmodes/octave-inf.el +++ b/lisp/progmodes/octave-inf.el @@ -1,17 +1,18 @@ ;;; octave-inf.el --- running Octave as an inferior Emacs process -;; Copyright (C) 1997 Free Software Foundation, Inc. +;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +;; Free Software Foundation, Inc. -;; Author: Kurt Hornik +;; Author: Kurt Hornik ;; Author: John Eaton -;; Maintainer: Kurt Hornik +;; Maintainer: Kurt Hornik ;; Keywords: languages ;; 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) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; GNU Emacs is distributed in the hope that it will be useful, @@ -21,55 +22,70 @@ ;; 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. +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: ;;; Code: (require 'octave-mod) (require 'comint) -(defvar inferior-octave-program "octave" - "*Program invoked by `inferior-octave'.") +(defgroup octave-inferior nil + "Running Octave as an inferior Emacs process." + :group 'octave) + +(defcustom inferior-octave-program "octave" + "Program invoked by `inferior-octave'." + :type 'string + :group 'octave-inferior) -(defvar inferior-octave-prompt "\\(^octave\\(:[0-9]+\\)?\\|^\\)>+ " - "*Regexp to match prompts for the inferior Octave process.") +(defcustom inferior-octave-prompt + "\\(^octave\\(\\|.bin\\|.exe\\)\\(-[.0-9]+\\)?\\(:[0-9]+\\)?\\|^debug\\|^\\)>+ " + "Regexp to match prompts for the inferior Octave process." + :type 'regexp + :group 'octave-inferior) -(defvar inferior-octave-startup-file nil - "*Name of the inferior Octave startup file. +(defcustom inferior-octave-startup-file nil + "Name of the inferior Octave startup file. The contents of this file are sent to the inferior Octave process on -startup.") +startup." + :type '(choice (const :tag "None" nil) + file) + :group 'octave-inferior) -(defvar inferior-octave-startup-args nil - "*List of command line arguments for the inferior Octave process. +(defcustom inferior-octave-startup-args nil + "List of command line arguments for the inferior Octave process. For example, for suppressing the startup message and using `traditional' -mode, set this to (\"-q\" \"--traditional\").") +mode, set this to (\"-q\" \"--traditional\")." + :type '(repeat string) + :group 'octave-inferior) -(defvar inferior-octave-mode-map nil - "Keymap used in Inferior Octave mode.") -(if inferior-octave-mode-map - () - (let ((map (copy-keymap comint-mode-map))) +(defvar inferior-octave-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map comint-mode-map) (define-key map "\t" 'comint-dynamic-complete) (define-key map "\M-?" 'comint-dynamic-list-filename-completions) (define-key map "\C-c\C-l" 'inferior-octave-dynamic-list-input-ring) (define-key map [menu-bar inout list-history] '("List Input History" . inferior-octave-dynamic-list-input-ring)) (define-key map "\C-c\C-h" 'octave-help) - (setq inferior-octave-mode-map map))) + map) + "Keymap used in Inferior Octave mode.") -(defvar inferior-octave-mode-syntax-table nil - "Syntax table in use in inferior-octave-mode buffers.") -(if inferior-octave-mode-syntax-table - () +(defvar inferior-octave-mode-syntax-table (let ((table (make-syntax-table))) (modify-syntax-entry ?\` "w" table) (modify-syntax-entry ?\# "<" table) (modify-syntax-entry ?\n ">" table) - (setq inferior-octave-mode-syntax-table table))) + table) + "Syntax table in use in inferior-octave-mode buffers.") -(defvar inferior-octave-mode-hook nil - "*Hook to be run when Inferior Octave mode is started.") +(defcustom inferior-octave-mode-hook nil + "*Hook to be run when Inferior Octave mode is started." + :type 'hook + :group 'octave-inferior) (defvar inferior-octave-font-lock-keywords (list @@ -77,6 +93,17 @@ mode, set this to (\"-q\" \"--traditional\").") ;; Could certainly do more font locking in inferior Octave ... "Additional expressions to highlight in Inferior Octave mode.") + +;;; Compatibility functions +(if (not (fboundp 'comint-line-beginning-position)) + ;; comint-line-beginning-position is defined in Emacs 21 + (defun comint-line-beginning-position () + "Returns the buffer position of the beginning of the line, after any prompt. +The prompt is assumed to be any text at the beginning of the line matching +the regular expression `comint-prompt-regexp', a buffer local variable." + (save-excursion (comint-bol nil) (point)))) + + (defvar inferior-octave-output-list nil) (defvar inferior-octave-output-string nil) (defvar inferior-octave-receive-in-progress nil) @@ -86,8 +113,11 @@ mode, set this to (\"-q\" \"--traditional\").") (defvar inferior-octave-complete-impossible nil "Non-nil means that `inferior-octave-complete' is impossible.") +(defvar inferior-octave-has-built-in-variables nil + "Non-nil means that Octave has built-in variables.") + (defvar inferior-octave-dynamic-complete-functions - '(inferior-octave-complete comint-dynamic-complete-filename) + '(inferior-octave-complete comint-dynamic-complete-filename) "List of functions called to perform completion for inferior Octave. This variable is used to initialize `comint-dynamic-complete-functions' in the Inferior Octave buffer.") @@ -100,7 +130,7 @@ buffer. Entry to this mode successively runs the hooks `comint-mode-hook' and `inferior-octave-mode-hook'." (interactive) - (comint-mode) + (delay-mode-hooks (comint-mode)) (setq comint-prompt-regexp inferior-octave-prompt major-mode 'inferior-octave-mode mode-name "Inferior Octave" @@ -109,12 +139,12 @@ Entry to this mode successively runs the hooks `comint-mode-hook' and (use-local-map inferior-octave-mode-map) (set-syntax-table inferior-octave-mode-syntax-table) - (make-local-variable 'comment-start) + (make-local-variable 'comment-start) (setq comment-start octave-comment-start) (make-local-variable 'comment-end) (setq comment-end "") (make-local-variable 'comment-column) - (setq comment-column 32) + (setq comment-column 32) (make-local-variable 'comment-start-skip) (setq comment-start-skip octave-comment-start-skip) @@ -123,13 +153,14 @@ Entry to this mode successively runs the hooks `comint-mode-hook' and (setq comint-input-ring-file-name (or (getenv "OCTAVE_HISTFILE") "~/.octave_hist") - comint-input-ring-size (or (getenv "OCTAVE_HISTSIZE") 1024) - comint-input-filter-functions '(inferior-octave-directory-tracker) - comint-dynamic-complete-functions - inferior-octave-dynamic-complete-functions) + comint-input-ring-size (or (getenv "OCTAVE_HISTSIZE") 1024)) + (set (make-local-variable 'comint-dynamic-complete-functions) + inferior-octave-dynamic-complete-functions) + (add-hook 'comint-input-filter-functions + 'inferior-octave-directory-tracker nil t) (comint-read-input-ring t) - (run-hooks 'inferior-octave-mode-hook)) + (run-mode-hooks 'inferior-octave-mode-hook)) ;;;###autoload (defun inferior-octave (&optional arg) @@ -166,7 +197,8 @@ startup file, `~/.emacs-octave'." (substring inferior-octave-buffer 1 -1) inferior-octave-buffer inferior-octave-program - inferior-octave-startup-args))) + (append (list "-i" "--no-line-editing") + inferior-octave-startup-args)))) (set-process-filter proc 'inferior-octave-output-digest) (setq comint-ptyp process-connection-type inferior-octave-process proc @@ -189,16 +221,34 @@ startup file, `~/.emacs-octave'." (concat (mapconcat 'identity inferior-octave-output-list "\n") "\n")))) + + ;; Find out whether Octave has built-in variables. + (inferior-octave-send-list-and-digest + (list "exist \"LOADPATH\"\n")) + (setq inferior-octave-has-built-in-variables + (string-match "101$" (car inferior-octave-output-list))) + + ;; An empty secondary prompt, as e.g. obtained by '--braindead', + ;; means trouble. + (inferior-octave-send-list-and-digest (list "PS2\n")) + (if (string-match "\\(PS2\\|ans\\) = *$" (car inferior-octave-output-list)) + (inferior-octave-send-list-and-digest + (list (if inferior-octave-has-built-in-variables + "PS2 = \"> \"\n" + "PS2 (\"> \");\n")))) + ;; O.k., now we are ready for the Inferior Octave startup commands. (let* (commands (program (file-name-nondirectory inferior-octave-program)) (file (or inferior-octave-startup-file (concat "~/.emacs-" program)))) (setq commands - (list "page_screen_output = 0;\n" + (list "more off;\n" (if (not (string-equal - inferior-octave-output-string ">> ")) - "PS1=\"\\\\s> \";\n") + inferior-octave-output-string ">> ")) + (if inferior-octave-has-built-in-variables + "PS1=\"\\\\s> \";\n" + "PS1 (\"\\\\s> \");\n")) (if (file-exists-p file) (format "source (\"%s\");\n" file)))) (inferior-octave-send-list-and-digest commands)) @@ -217,7 +267,11 @@ startup file, `~/.emacs-octave'." ;; And finally, everything is back to normal. (set-process-filter proc 'inferior-octave-output-filter) - (run-hooks 'inferior-octave-startup-hook))) + (run-hooks 'inferior-octave-startup-hook) + (run-hooks 'inferior-octave-startup-hook) + ;; Just in case, to be sure a cd in the startup file + ;; won't have detrimental effects. + (inferior-octave-resync-dirs))) (defun inferior-octave-complete () @@ -226,13 +280,11 @@ This is implemented using the Octave command `completion_matches' which is NOT available with versions of Octave prior to 2.0." (interactive) (let* ((end (point)) - (command (save-excursion - (skip-syntax-backward "w_") - (and (looking-at comint-prompt-regexp) - (goto-char (match-end 0))) - (buffer-substring-no-properties (point) end))) - (proc (get-buffer-process inferior-octave-buffer)) - (filter (process-filter proc))) + (command + (save-excursion + (skip-syntax-backward "w_" (comint-line-beginning-position)) + (buffer-substring-no-properties (point) end))) + (proc (get-buffer-process inferior-octave-buffer))) (cond (inferior-octave-complete-impossible (error (concat "Your Octave does not have `completion_matches'. " @@ -258,7 +310,7 @@ is NOT available with versions of Octave prior to 2.0." command inferior-octave-output-list))))) (defun inferior-octave-dynamic-list-input-ring () - "List the buffer's input history in a help buffer" + "List the buffer's input history in a help buffer." ;; We cannot use `comint-dynamic-list-input-ring', because it replaces ;; "completion" by "history reference" ... (interactive) @@ -335,20 +387,23 @@ output is passed to the filter `inferior-octave-output-digest'." (defun inferior-octave-directory-tracker (string) "Tracks `cd' commands issued to the inferior Octave process. Use \\[inferior-octave-resync-dirs] to resync if Emacs gets confused." - (if (string-match "[ \t]*cd[ \t]*\\([^ \t\n;]*\\)[ \t\n;]" - string) - (cd (substring string (match-beginning 1) (match-end 1))))) + (cond + ((string-match "^[ \t]*cd[ \t;]*$" string) + (cd "~")) + ((string-match "^[ \t]*cd[ \t]+\\([^ \t\n;]*\\)[ \t\n;]*" string) + (cd (substring string (match-beginning 1) (match-end 1)))))) (defun inferior-octave-resync-dirs () "Resync the buffer's idea of the current directory. This command queries the inferior Octave process about its current directory and makes this the current buffer's default directory." (interactive) - (inferior-octave-send-list-and-digest '("pwd\n")) + (inferior-octave-send-list-and-digest '("disp (pwd ())\n")) (cd (car inferior-octave-output-list))) ;;; provide ourself (provide 'octave-inf) +;; arch-tag: bdce0395-24d1-4bb4-bfba-6fb1eeb1a660 ;;; octave-inf.el ends here