]> git.eshelyaron.com Git - emacs.git/commitdiff
Initial revision
authorRichard M. Stallman <rms@gnu.org>
Tue, 21 Jan 1997 00:35:48 +0000 (00:35 +0000)
committerRichard M. Stallman <rms@gnu.org>
Tue, 21 Jan 1997 00:35:48 +0000 (00:35 +0000)
lisp/progmodes/octave-hlp.el [new file with mode: 0644]
lisp/progmodes/octave-inf.el [new file with mode: 0644]

diff --git a/lisp/progmodes/octave-hlp.el b/lisp/progmodes/octave-hlp.el
new file mode 100644 (file)
index 0000000..2295cb5
--- /dev/null
@@ -0,0 +1,133 @@
+;; octave-hlp.el --- getting help on Octave symbols using info
+
+;;; Copyright (C) 1997 Free Software Foundation, Inc.
+
+;; Author: Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>
+;; Author: John Eaton <jwe@bevo.che.wisc.edu>
+;; Maintainer: Kurt Hornik <Kurt.Hornik@ci.tuwien.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)
+;; 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:
+
+;; Provides the command `octave-help' which allows index lookup of a
+;; symbol in the Octave-related info files, as specified by the list
+;; `octave-help-files'.
+
+;; Other features may be added in future versions.
+
+;;; Code:
+
+(require 'octave)
+(require 'info)
+
+(defvar octave-help-files '("octave")
+  "List of info files with documentation for Octave.
+Default is (\"octave\").")
+
+(defvar octave-help-lookup-alist nil
+  "Alist of Octave index entries for lookup.")
+
+(defvar octave-help-completion-alist nil
+  "Alist of Octave index entries for completion.
+The entries are of the form (VAR . VAR), where VAR runs through all
+different keys in `octave-help-lookup-alist'.")
+
+;;;###autoload
+(defun octave-help (key)
+  "Get help on Octave symbols from the Octave info files.
+Look up KEY in the function, operator and variable indices of the files
+specified by `octave-help-files'.
+If KEY is not a string, prompt for it with completion."
+  (interactive
+   (list
+    (completing-read (format "Describe Octave symbol: ")
+                    (octave-help-get-completion-alist)
+                    nil t)))
+  (if (get-buffer "*info*")
+      (set-buffer "*info*"))
+  (if (zerop (length key))
+      (Info-find-node (car octave-help-files) "Top")
+    (let ((alist (copy-alist (octave-help-get-lookup-alist)))
+         entry matches)
+      (while (setq entry (car alist))
+       (if (string-match key (car entry))
+           (add-to-list 'matches entry))
+       (setq alist (cdr alist)))
+      (if matches
+         (progn
+           (setq Info-index-alternatives matches)
+           (Info-index-next 0))))))
+
+(defun octave-help-get-lookup-alist ()
+  "Build the index lookup alist from all Octave info files.
+The files specified by `octave-help-files' are searched."
+  (if octave-help-lookup-alist
+      ()
+    (message "Building help lookup alist...")    
+    (let ((files octave-help-files) file key node)
+      (save-window-excursion
+       (while files
+         (setq file (car files))
+         (Info-goto-node (concat "(" file ")"))
+         (condition-case nil
+             (progn
+               (Info-index "")
+               (while
+                   (progn
+                     (while (re-search-forward
+                             "^\\* \\([^(:]+\\)[^:]*: *\\(.+\\)\\.$"
+                             nil t)
+                       (setq key (match-string 1)
+                             node (concat "(" file ")" (match-string 2)))
+                       (and (string-match "\\(.*\\>\\) *$" key)
+                            (setq key (replace-match "\\1" t nil key)))
+                       (add-to-list 'octave-help-lookup-alist
+                                    (list key
+                                          node
+                                          (concat (concat "(" file ")")
+                                                  Info-current-node)
+                                          0)))
+                     (and (setq node (Info-extract-pointer "next" t))
+                          (string-match
+                           (concat "\\(Function\\|Operator\\|Variable\\) "
+                                   "\\<Index\\>")
+                           node)))
+                 (Info-goto-node node)))
+           (error nil))
+         (setq files (cdr files)))))
+    (message "Building help lookup alist...done"))
+  octave-help-lookup-alist)
+
+(defun octave-help-get-completion-alist ()
+  "Build the index completion alist from all Octave info files.
+The files specified by `octave-help-files' are searched."
+  (if octave-help-completion-alist
+      ()
+    (message "Building help completion alist...")
+    (let ((alist (octave-help-get-lookup-alist)) entry)
+      (while alist
+       (setq entry (car alist))
+       (add-to-list 'octave-help-completion-alist
+                    (cons (car entry) (car entry)))
+       (setq alist (cdr alist))))
+    (message "Building help completion alist...done"))    
+  octave-help-completion-alist)
+
+;;; octave-hlp.el ends here
\ No newline at end of file
diff --git a/lisp/progmodes/octave-inf.el b/lisp/progmodes/octave-inf.el
new file mode 100644 (file)
index 0000000..acf0df3
--- /dev/null
@@ -0,0 +1,352 @@
+;; octave-inf.el --- running Octave as an inferior Emacs process
+
+;;; Copyright (C) 1997 Free Software Foundation, Inc.
+
+;; Author: Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at>
+;; Author: John Eaton <jwe@bevo.che.wisc.edu>
+;; Maintainer: Kurt Hornik <Kurt.Hornik@ci.tuwien.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)
+;; 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:
+
+;;; Code:
+
+(require 'octave)
+(require 'comint)
+
+(defvar inferior-octave-program "octave"
+  "*Program invoked by `inferior-octave'.")
+
+(defvar inferior-octave-prompt "\\(^octave\\(:[0-9]+\\)?\\|^\\)>+ "
+  "*Regexp to match prompts for the inferior Octave process.")
+
+(defvar 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.")
+
+(defvar 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\").")
+
+(defvar inferior-octave-mode-map nil
+  "Keymap used in Inferior Octave mode.")
+(if inferior-octave-mode-map
+    ()
+  (let ((map (copy-keymap 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)))
+
+(defvar inferior-octave-mode-syntax-table nil
+  "Syntax table in use in inferior-octave-mode buffers.")
+(if 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)))
+
+(defvar inferior-octave-mode-hook nil
+  "*Hook to be run when Inferior Octave mode is started.")
+
+(defvar inferior-octave-font-lock-keywords
+  (list
+   (cons inferior-octave-prompt 'font-lock-type-face))
+  ;; Could certainly do more font locking in inferior Octave ...
+  "Additional expressions to highlight in Inferior Octave mode.")
+
+(defvar inferior-octave-output-list nil)
+(defvar inferior-octave-output-string nil)
+(defvar inferior-octave-receive-in-progress nil)
+
+(defvar inferior-octave-startup-hook nil)
+
+(defvar inferior-octave-complete-impossible nil
+  "Non-nil means that `inferior-octave-complete' is impossible.")
+
+(defvar inferior-octave-dynamic-complete-functions
+  '(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.")
+
+(defun inferior-octave-mode ()
+  "Major mode for interacting with an inferior Octave process.
+Runs Octave as a subprocess of Emacs, with Octave I/O through an Emacs
+buffer.
+
+Entry to this mode successively runs the hooks `comint-mode-hook' and
+`inferior-octave-mode-hook'."
+  (interactive)
+  (comint-mode)
+  (setq comint-prompt-regexp inferior-octave-prompt
+       major-mode 'inferior-octave-mode
+       mode-name "Inferior Octave"
+       mode-line-process '(":%s")
+       local-abbrev-table octave-abbrev-table)
+  (use-local-map inferior-octave-mode-map)
+  (set-syntax-table inferior-octave-mode-syntax-table)
+
+  (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)    
+  (make-local-variable 'comment-start-skip)
+  (setq comment-start-skip octave-comment-start-skip)
+
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults '(inferior-octave-font-lock-keywords nil nil))
+
+  (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-read-input-ring t)
+
+  (run-hooks 'inferior-octave-mode-hook))
+
+;;;###autoload
+(defun inferior-octave (&optional arg)
+  "Run an inferior Octave process, I/O via `inferior-octave-buffer'.
+This buffer is put in Inferior Octave mode.  See `inferior-octave-mode'.
+
+Unless ARG is non-nil, switches to this buffer.
+
+The elements of the list `inferior-octave-startup-args' are sent as
+command line arguments to the inferior Octave process on startup.
+
+Additional commands to be executed on startup can be provided either in
+the file specified by `inferior-octave-startup-file' or by the default
+startup file, `~/.emacs-octave'."
+  (interactive "P")
+  (let ((buffer inferior-octave-buffer))
+    (get-buffer-create buffer)
+    (if (comint-check-proc buffer)
+       ()
+      (save-excursion
+       (set-buffer buffer)
+       (comint-mode)
+       (inferior-octave-startup)
+       (inferior-octave-mode)))
+    (if (not arg)
+       (pop-to-buffer buffer))))
+
+;;;###autoload
+(defalias 'run-octave 'inferior-octave)
+
+(defun inferior-octave-startup ()
+  "Start an inferior Octave process."
+  (let ((proc (comint-exec-1
+              (substring inferior-octave-buffer 1 -1)
+              inferior-octave-buffer
+              inferior-octave-program
+              inferior-octave-startup-args)))
+    (set-process-filter proc 'inferior-octave-output-digest)
+    (setq comint-ptyp process-connection-type
+         inferior-octave-process proc
+         inferior-octave-output-list nil
+         inferior-octave-output-string nil
+         inferior-octave-receive-in-progress t)
+
+    ;; This may look complicated ... However, we need to make sure that
+    ;; we additional startup code only AFTER Octave is ready (otherwise,
+    ;; output may be mixed up).  Hence, we need to digest the Octave
+    ;; output to see when it issues a prompt.
+    (while inferior-octave-receive-in-progress
+      (accept-process-output inferior-octave-process))
+    (goto-char (point-max))
+    (set-marker (process-mark proc) (point))
+    (insert-before-markers
+     (concat
+      (if (not (bobp)) "\f\n")
+      (if inferior-octave-output-list
+         (concat (mapconcat
+                  'identity inferior-octave-output-list "\n")
+                 "\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"
+                 (if (not (string-equal
+                           inferior-octave-output-string ">> ")) 
+                     "PS1=\"\\\\s> \";\n")
+                 (if (file-exists-p file)
+                     (format "source (\"%s\");\n" file))))
+      (inferior-octave-send-list-and-digest commands))
+    (insert-before-markers
+     (concat
+      (if inferior-octave-output-list
+         (concat (mapconcat
+                  'identity inferior-octave-output-list "\n")
+                 "\n"))
+      inferior-octave-output-string))
+    ;; Next, we check whether Octave supports `completion_matches' ...
+    (inferior-octave-send-list-and-digest
+     (list "exist \"completion_matches\"\n"))
+    (setq inferior-octave-complete-impossible
+         (not (string-match "5$" (car inferior-octave-output-list))))
+
+    ;; And finally, everything is back to normal.
+    (set-process-filter proc 'inferior-octave-output-filter)
+    (run-hooks 'inferior-octave-startup-hook)))
+
+\f
+(defun inferior-octave-complete ()
+  "Perform completion on the Octave symbol preceding point.
+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)))
+    (cond (inferior-octave-complete-impossible
+          (error (concat
+                  "Your Octave does not have `completion_matches'.  "
+                  "Please upgrade to version 2.X.")))
+         ((string-equal command "")
+          (message "Cannot complete an empty string"))
+         (t
+          (inferior-octave-send-list-and-digest
+           (list (concat "completion_matches (\"" command "\");\n")))
+          ;; Sort the list
+          (setq inferior-octave-output-list
+                (sort inferior-octave-output-list 'string-lessp))
+          ;; Remove duplicates
+          (let* ((x inferior-octave-output-list)
+                 (y (cdr x)))
+            (while y
+              (if (string-equal (car x) (car y))
+                  (setcdr x (setq y (cdr y)))
+                (setq x y
+                      y (cdr y)))))
+          ;; And let comint handle the rest
+          (comint-dynamic-simple-complete
+           command inferior-octave-output-list)))))
+
+(defun inferior-octave-dynamic-list-input-ring ()
+  "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)
+  (if (or (not (ring-p comint-input-ring))
+          (ring-empty-p comint-input-ring))
+      (message "No history")
+    (let ((history nil)
+          (history-buffer " *Input History*")
+          (index (1- (ring-length comint-input-ring)))
+          (conf (current-window-configuration)))
+      ;; We have to build up a list ourselves from the ring vector.
+      (while (>= index 0)
+        (setq history (cons (ring-ref comint-input-ring index) history)
+              index (1- index)))
+      ;; Change "completion" to "history reference"
+      ;; to make the display accurate.
+      (with-output-to-temp-buffer history-buffer
+        (display-completion-list history)
+        (set-buffer history-buffer))
+      (message "Hit space to flush")
+      (let ((ch (read-event)))
+        (if (eq ch ?\ )
+            (set-window-configuration conf)
+          (setq unread-command-events (list ch)))))))
+
+(defun inferior-octave-strip-ctrl-g (string)
+  "Strip leading `^G' character.
+If STRING starts with a `^G', ring the bell and strip it."
+  (if (string-match "^\a" string)
+      (progn
+        (ding)
+        (setq string (substring string 1))))
+  string)
+
+(defun inferior-octave-output-filter (proc string)
+  "Standard output filter for the inferior Octave process.
+Ring Emacs bell if process output starts with an ASCII bell, and pass
+the rest to `comint-output-filter'."
+  (comint-output-filter proc (inferior-octave-strip-ctrl-g string)))
+
+(defun inferior-octave-output-digest (proc string)
+  "Special output filter for the inferior Octave process.
+Save all output between newlines into `inferior-octave-output-list', and
+the rest to `inferior-octave-output-string'."
+  (setq string (concat inferior-octave-output-string string))
+  (while (string-match "\n" string)
+    (setq inferior-octave-output-list
+         (append inferior-octave-output-list
+                 (list (substring string 0 (match-beginning 0))))
+         string (substring string (match-end 0))))
+  (if (string-match inferior-octave-prompt string)
+      (setq inferior-octave-receive-in-progress nil))
+  (setq inferior-octave-output-string string))
+
+(defun inferior-octave-send-list-and-digest (list)
+  "Send LIST to the inferior Octave process and digest the output.
+The elements of LIST have to be strings and are sent one by one.  All
+output is passed to the filter `inferior-octave-output-digest'."
+  (let* ((proc inferior-octave-process)
+        (filter (process-filter proc))
+        string)
+    (set-process-filter proc 'inferior-octave-output-digest)
+    (setq inferior-octave-output-list nil)
+    (unwind-protect
+       (while (setq string (car list))
+         (setq inferior-octave-output-string nil
+               inferior-octave-receive-in-progress t)
+         (comint-send-string proc string)
+         (while inferior-octave-receive-in-progress
+           (accept-process-output proc))
+         (setq list (cdr list)))
+      (set-process-filter proc filter))))
+
+(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)))))
+
+(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"))
+  (cd (car inferior-octave-output-list)))
+
+;;; octave-inf.el ends here
\ No newline at end of file