-;; octave-inf.el --- running Octave as an inferior Emacs process
+;;; 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
+;; Free Software Foundation, Inc.
-;; Author: Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>
+;; Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
;; Author: John Eaton <jwe@bevo.che.wisc.edu>
-;; Maintainer: Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>
+;; Maintainer: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
;; 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,
;; 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
;; 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)
(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.")
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"
(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)
(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)
(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
(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))
;; 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)))
\f
(defun inferior-octave-complete ()
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'. "
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)
(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)))
-;;; octave-inf.el ends here
\ No newline at end of file
+;;; provide ourself
+
+(provide 'octave-inf)
+
+;; arch-tag: bdce0395-24d1-4bb4-bfba-6fb1eeb1a660
+;;; octave-inf.el ends here