Refill some copyright headers.
[bpt/emacs.git] / lisp / progmodes / octave-mod.el
CommitLineData
092af6d8 1;;; octave-mod.el --- editing Octave source files under Emacs
f2727dfb 2
e9bffc61
GM
3;; Copyright (C) 1997, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
4;; 2009, 2010, 2011 Free Software Foundation, Inc.
f2727dfb 5
f7fba1a8 6;; Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
c82d5b11 7;; Author: John Eaton <jwe@octave.org>
f7fba1a8 8;; Maintainer: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
f2727dfb
RS
9;; Keywords: languages
10
11;; This file is part of GNU Emacs.
12
b1fc2b50 13;; GNU Emacs is free software: you can redistribute it and/or modify
f2727dfb 14;; it under the terms of the GNU General Public License as published by
b1fc2b50
GM
15;; the Free Software Foundation, either version 3 of the License, or
16;; (at your option) any later version.
f2727dfb
RS
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
b1fc2b50 24;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
f2727dfb
RS
25
26;;; Commentary:
27
d1e49742
RS
28;; This package provides Emacs support for Octave.
29;; It defines Octave mode, a major mode for editing
30;; Octave code.
31
d1e49742
RS
32;; The file octave-inf.el contains code for interacting with an inferior
33;; Octave process using comint.
f2727dfb 34
5d8137ab 35;; See the documentation of `octave-mode' and
d1e49742 36;; `run-octave' for further information on usage and customization.
f2727dfb 37
d1e49742 38;;; Code:
2454554e 39(require 'custom)
f2727dfb 40
28d16ed3
AS
41(defgroup octave nil
42 "Major mode for editing Octave source files."
8ec3bce0 43 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
28d16ed3
AS
44 :group 'languages)
45
e09735aa
RS
46(defvar inferior-octave-output-list nil)
47(defvar inferior-octave-output-string nil)
48(defvar inferior-octave-receive-in-progress nil)
49
004a00f4
DN
50(declare-function inferior-octave-send-list-and-digest "octave-inf" (list))
51
e7017ef9 52(defconst octave-maintainer-address
f7fba1a8 53 "Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>, bug-gnu-emacs@gnu.org"
e7017ef9
RS
54 "Current maintainer of the Emacs Octave package.")
55
7210c33f
SM
56(define-abbrev-table 'octave-abbrev-table
57 (mapcar (lambda (e) (append e '(nil 0 t)))
58 '(("`a" "all_va_args")
59 ("`b" "break")
60 ("`cs" "case")
61 ("`ca" "catch")
62 ("`c" "continue")
63 ("`el" "else")
64 ("`eli" "elseif")
65 ("`et" "end_try_catch")
66 ("`eu" "end_unwind_protect")
67 ("`ef" "endfor")
68 ("`efu" "endfunction")
69 ("`ei" "endif")
70 ("`es" "endswitch")
71 ("`ew" "endwhile")
72 ("`f" "for")
73 ("`fu" "function")
74 ("`gl" "global")
75 ("`gp" "gplot")
76 ("`gs" "gsplot")
77 ("`if" "if ()")
78 ("`o" "otherwise")
79 ("`rp" "replot")
80 ("`r" "return")
81 ("`s" "switch")
82 ("`t" "try")
83 ("`u" "until ()")
84 ("`up" "unwind_protect")
85 ("`upc" "unwind_protect_cleanup")
86 ("`w" "while ()")))
e7017ef9 87 "Abbrev table for Octave's reserved words.
99158127 88Used in `octave-mode' and inferior-octave-mode buffers.
7210c33f
SM
89All Octave abbrevs start with a grave accent (`)."
90 :regexp "\\(?:[^`]\\|^\\)\\(\\(?:\\<\\|`\\)\\w+\\)\\W*")
e7017ef9
RS
91
92(defvar octave-comment-char ?#
93 "Character to start an Octave comment.")
94(defvar octave-comment-start
c82d5b11 95 (string octave-comment-char ?\s)
e7017ef9
RS
96 "String to insert to start a new Octave in-line comment.")
97(defvar octave-comment-start-skip "\\s<+\\s-*"
98 "Regexp to match the start of an Octave comment up to its body.")
99
100(defvar octave-begin-keywords
490a8abe 101 '("do" "for" "function" "if" "switch" "try" "unwind_protect" "while"))
e7017ef9 102(defvar octave-else-keywords
6e6d2764 103 '("case" "catch" "else" "elseif" "otherwise" "unwind_protect_cleanup"))
e7017ef9 104(defvar octave-end-keywords
490a8abe 105 '("endfor" "endfunction" "endif" "endswitch" "end_try_catch"
b2ad70b6 106 "end_unwind_protect" "endwhile" "until" "end"))
e7017ef9
RS
107
108(defvar octave-reserved-words
6e6d2764
KH
109 (append octave-begin-keywords
110 octave-else-keywords
111 octave-end-keywords
490a8abe 112 '("break" "continue" "end" "global" "persistent" "return"))
e7017ef9
RS
113 "Reserved words in Octave.")
114
115(defvar octave-text-functions
116 '("casesen" "cd" "chdir" "clear" "diary" "dir" "document" "echo"
490a8abe
GM
117 "edit_history" "format" "help" "history" "hold"
118 "load" "ls" "more" "run_history" "save" "type"
e7017ef9 119 "which" "who" "whos")
490a8abe 120 "Text functions in Octave.")
e7017ef9
RS
121
122(defvar octave-variables
490a8abe
GM
123 '("DEFAULT_EXEC_PATH" "DEFAULT_LOADPATH"
124 "EDITOR" "EXEC_PATH" "F_DUPFD" "F_GETFD" "F_GETFL" "F_SETFD"
125 "F_SETFL" "I" "IMAGE_PATH" "Inf" "J"
126 "NaN" "OCTAVE_VERSION" "O_APPEND" "O_CREAT" "O_EXCL"
e7017ef9
RS
127 "O_NONBLOCK" "O_RDONLY" "O_RDWR" "O_TRUNC" "O_WRONLY" "PAGER" "PS1"
128 "PS2" "PS4" "PWD" "SEEK_CUR" "SEEK_END" "SEEK_SET" "__F_DUPFD__"
129 "__F_GETFD__" "__F_GETFL__" "__F_SETFD__" "__F_SETFL__" "__I__"
130 "__Inf__" "__J__" "__NaN__" "__OCTAVE_VERSION__" "__O_APPEND__"
131 "__O_CREAT__" "__O_EXCL__" "__O_NONBLOCK__" "__O_RDONLY__"
132 "__O_RDWR__" "__O_TRUNC__" "__O_WRONLY__" "__PWD__" "__SEEK_CUR__"
133 "__SEEK_END__" "__SEEK_SET__" "__argv__" "__e__" "__eps__"
490a8abe 134 "__i__" "__inf__" "__j__" "__nan__" "__pi__"
e7017ef9
RS
135 "__program_invocation_name__" "__program_name__" "__realmax__"
136 "__realmin__" "__stderr__" "__stdin__" "__stdout__" "ans" "argv"
490a8abe
GM
137 "beep_on_error" "completion_append_char"
138 "crash_dumps_octave_core" "default_save_format"
139 "e" "echo_executing_commands" "eps"
140 "error_text" "gnuplot_binary" "history_file"
141 "history_size" "ignore_function_time_stamp"
142 "inf" "nan" "nargin" "output_max_field_width" "output_precision"
e7017ef9 143 "page_output_immediately" "page_screen_output" "pi"
e7017ef9 144 "print_answer_id_name" "print_empty_dimensions"
490a8abe
GM
145 "program_invocation_name" "program_name"
146 "realmax" "realmin" "return_last_computed_value" "save_precision"
147 "saving_history" "sighup_dumps_octave_core" "sigterm_dumps_octave_core"
e7017ef9
RS
148 "silent_functions" "split_long_rows" "stderr" "stdin" "stdout"
149 "string_fill_char" "struct_levels_to_print"
490a8abe 150 "suppress_verbose_help_message")
e7017ef9
RS
151 "Builtin variables in Octave.")
152
153(defvar octave-function-header-regexp
154 (concat "^\\s-*\\<\\(function\\)\\>"
155 "\\([^=;\n]*=[ \t]*\\|[ \t]*\\)\\(\\w+\\)\\>")
156 "Regexp to match an Octave function header.
157The string `function' and its name are given by the first and third
158parenthetical grouping.")
159
160(defvar octave-font-lock-keywords
161 (list
162 ;; Fontify all builtin keywords.
163 (cons (concat "\\<\\("
e17b68ed
SM
164 (regexp-opt (append octave-reserved-words
165 octave-text-functions))
e7017ef9
RS
166 "\\)\\>")
167 'font-lock-keyword-face)
168 ;; Fontify all builtin operators.
169 (cons "\\(&\\||\\|<=\\|>=\\|==\\|<\\|>\\|!=\\|!\\)"
cb41203e
GM
170 (if (boundp 'font-lock-builtin-face)
171 'font-lock-builtin-face
172 'font-lock-preprocessor-face))
e7017ef9 173 ;; Fontify all builtin variables.
ff80a446 174 (cons (concat "\\<" (regexp-opt octave-variables) "\\>")
e7017ef9
RS
175 'font-lock-variable-name-face)
176 ;; Fontify all function declarations.
177 (list octave-function-header-regexp
178 '(1 font-lock-keyword-face)
179 '(3 font-lock-function-name-face nil t)))
180 "Additional Octave expressions to highlight.")
181
cf38dd42
SM
182(defun octave-syntax-propertize-function (start end)
183 (goto-char start)
184 (octave-syntax-propertize-sqs end)
185 (funcall (syntax-propertize-rules
ff80a446 186 ;; Try to distinguish the string-quotes from the transpose-quotes.
cf38dd42
SM
187 ("[[({,; ]\\('\\)"
188 (1 (prog1 "\"'" (octave-syntax-propertize-sqs end)))))
189 (point) end))
190
191(defun octave-syntax-propertize-sqs (end)
192 "Propertize the content/end of single-quote strings."
193 (when (eq (nth 3 (syntax-ppss)) ?\')
ff80a446 194 ;; A '..' string.
cf38dd42
SM
195 (when (re-search-forward
196 "\\(?:\\=\\|[^']\\)\\(?:''\\)*\\('\\)\\($\\|[^']\\)" end 'move)
197 (goto-char (match-beginning 2))
89acf735
SM
198 (when (eq (char-before (match-beginning 1)) ?\\)
199 ;; Backslash cannot escape a single quote.
200 (put-text-property (1- (match-beginning 1)) (match-beginning 1)
201 'syntax-table (string-to-syntax ".")))
ff80a446 202 (put-text-property (match-beginning 1) (match-end 1)
cf38dd42 203 'syntax-table (string-to-syntax "\"'")))))
ff80a446 204
28d16ed3 205(defcustom inferior-octave-buffer "*Inferior Octave*"
e22bbd48 206 "Name of buffer for running an inferior Octave process."
28d16ed3
AS
207 :type 'string
208 :group 'octave-inferior)
e7017ef9
RS
209
210(defvar inferior-octave-process nil)
211\f
e22bbd48 212(defvar octave-mode-map
f2727dfb
RS
213 (let ((map (make-sparse-keymap)))
214 (define-key map "`" 'octave-abbrev-start)
a1506d29 215 (define-key map "\e\n" 'octave-indent-new-comment-line)
a1506d29 216 (define-key map "\M-\C-q" 'octave-indent-defun)
f2727dfb
RS
217 (define-key map "\C-c\C-b" 'octave-submit-bug-report)
218 (define-key map "\C-c\C-p" 'octave-previous-code-line)
219 (define-key map "\C-c\C-n" 'octave-next-code-line)
220 (define-key map "\C-c\C-a" 'octave-beginning-of-line)
a1506d29 221 (define-key map "\C-c\C-e" 'octave-end-of-line)
ec5d3ff7 222 (define-key map [remap down-list] 'smie-down-list)
f2727dfb 223 (define-key map "\C-c\M-\C-h" 'octave-mark-block)
e17b68ed
SM
224 (define-key map "\C-c]" 'smie-close-block)
225 (define-key map "\C-c/" 'smie-close-block)
34a463f1 226 (define-key map "\C-c\C-f" 'octave-insert-defun)
f2727dfb 227 (define-key map "\C-c\C-h" 'octave-help)
34a463f1
RS
228 (define-key map "\C-c\C-il" 'octave-send-line)
229 (define-key map "\C-c\C-ib" 'octave-send-block)
230 (define-key map "\C-c\C-if" 'octave-send-defun)
a1506d29 231 (define-key map "\C-c\C-ir" 'octave-send-region)
34a463f1
RS
232 (define-key map "\C-c\C-is" 'octave-show-process-buffer)
233 (define-key map "\C-c\C-ih" 'octave-hide-process-buffer)
234 (define-key map "\C-c\C-ik" 'octave-kill-process)
235 (define-key map "\C-c\C-i\C-l" 'octave-send-line)
236 (define-key map "\C-c\C-i\C-b" 'octave-send-block)
237 (define-key map "\C-c\C-i\C-f" 'octave-send-defun)
a1506d29 238 (define-key map "\C-c\C-i\C-r" 'octave-send-region)
34a463f1
RS
239 (define-key map "\C-c\C-i\C-s" 'octave-show-process-buffer)
240 (define-key map "\C-c\C-i\C-h" 'octave-hide-process-buffer)
241 (define-key map "\C-c\C-i\C-k" 'octave-kill-process)
e22bbd48
SM
242 map)
243 "Keymap used in Octave mode.")
244
f2727dfb 245
ff80a446
SM
246
247(easy-menu-define octave-mode-menu octave-mode-map
248 "Menu for Octave mode."
e22bbd48 249 '("Octave"
67885e8c 250 ("Lines"
e22bbd48
SM
251 ["Previous Code Line" octave-previous-code-line t]
252 ["Next Code Line" octave-next-code-line t]
253 ["Begin of Continuation" octave-beginning-of-line t]
254 ["End of Continuation" octave-end-of-line t]
255 ["Split Line at Point" octave-indent-new-comment-line t])
67885e8c 256 ("Blocks"
e22bbd48 257 ["Mark Block" octave-mark-block t]
e17b68ed 258 ["Close Block" smie-close-block t])
67885e8c 259 ("Functions"
e22bbd48
SM
260 ["Indent Function" octave-indent-defun t]
261 ["Insert Function" octave-insert-defun t])
262 "-"
67885e8c 263 ("Debug"
e22bbd48
SM
264 ["Send Current Line" octave-send-line t]
265 ["Send Current Block" octave-send-block t]
266 ["Send Current Function" octave-send-defun t]
267 ["Send Region" octave-send-region t]
268 ["Show Process Buffer" octave-show-process-buffer t]
269 ["Hide Process Buffer" octave-hide-process-buffer t]
270 ["Kill Process" octave-kill-process t])
271 "-"
272 ["Indent Line" indent-according-to-mode t]
c82d5b11 273 ["Complete Symbol" completion-at-point t]
e22bbd48 274 "-"
b5ba2d6f
SM
275 ["Toggle Abbrev Mode" abbrev-mode
276 :style toggle :selected abbrev-mode]
277 ["Toggle Auto-Fill Mode" auto-fill-mode
278 :style toggle :selected auto-fill-function]
e22bbd48
SM
279 "-"
280 ["Submit Bug Report" octave-submit-bug-report t]
281 "-"
c82d5b11 282 ["Describe Octave Mode" describe-mode t]
ff80a446 283 ["Lookup Octave Index" info-lookup-symbol t]))
f2727dfb 284
cb3d3ec1 285(defvar octave-mode-syntax-table
f2727dfb
RS
286 (let ((table (make-syntax-table)))
287 (modify-syntax-entry ?\r " " table)
288 (modify-syntax-entry ?+ "." table)
289 (modify-syntax-entry ?- "." table)
290 (modify-syntax-entry ?= "." table)
291 (modify-syntax-entry ?* "." table)
292 (modify-syntax-entry ?/ "." table)
293 (modify-syntax-entry ?> "." table)
294 (modify-syntax-entry ?< "." table)
295 (modify-syntax-entry ?& "." table)
296 (modify-syntax-entry ?| "." table)
297 (modify-syntax-entry ?! "." table)
298 (modify-syntax-entry ?\\ "\\" table)
299 (modify-syntax-entry ?\' "." table)
7210c33f
SM
300 ;; Was "w" for abbrevs, but now that it's not necessary any more,
301 (modify-syntax-entry ?\` "." table)
f2727dfb
RS
302 (modify-syntax-entry ?\" "\"" table)
303 (modify-syntax-entry ?. "w" table)
304 (modify-syntax-entry ?_ "w" table)
c5683ceb 305 ;; The "b" flag only applies to the second letter of the comstart
7e82caa7
SM
306 ;; and the first letter of the comend, i.e. the "4b" below is ineffective.
307 ;; If we try to put `b' on the single-line comments, we get a similar
308 ;; problem where the % and # chars appear as first chars of the 2-char
309 ;; comend, so the multi-line ender is also turned into style-b.
c5683ceb 310 ;; So we need the new "c" comment style.
c82d5b11
SM
311 (modify-syntax-entry ?\% "< 13" table)
312 (modify-syntax-entry ?\# "< 13" table)
c5683ceb
SM
313 (modify-syntax-entry ?\{ "(} 2c" table)
314 (modify-syntax-entry ?\} "){ 4c" table)
f2727dfb 315 (modify-syntax-entry ?\n ">" table)
cb3d3ec1
SM
316 table)
317 "Syntax table in use in `octave-mode' buffers.")
f2727dfb 318
28d16ed3 319(defcustom octave-blink-matching-block t
e22bbd48 320 "Control the blinking of matching Octave block keywords.
f2727dfb 321Non-nil means show matching begin of block when inserting a space,
28d16ed3
AS
322newline or semicolon after an else or end keyword."
323 :type 'boolean
324 :group 'octave)
ff80a446 325
28d16ed3 326(defcustom octave-block-offset 2
e22bbd48 327 "Extra indentation applied to statements in Octave block structures."
28d16ed3
AS
328 :type 'integer
329 :group 'octave)
f2727dfb 330
f2727dfb
RS
331(defvar octave-block-comment-start
332 (concat (make-string 2 octave-comment-char) " ")
333 "String to insert to start a new Octave comment on an empty line.")
334
28d16ed3 335(defcustom octave-continuation-offset 4
e22bbd48 336 "Extra indentation applied to Octave continuation lines."
28d16ed3
AS
337 :type 'integer
338 :group 'octave)
e17b68ed
SM
339(eval-and-compile
340 (defconst octave-continuation-marker-regexp "\\\\\\|\\.\\.\\."))
f2727dfb 341(defvar octave-continuation-regexp
e17b68ed
SM
342 (concat "[^#%\n]*\\(" octave-continuation-marker-regexp
343 "\\)\\s-*\\(\\s<.*\\)?$"))
28d16ed3 344(defcustom octave-continuation-string "\\"
e22bbd48 345 "Character string used for Octave continuation lines. Normally \\."
28d16ed3
AS
346 :type 'string
347 :group 'octave)
f2727dfb
RS
348
349(defvar octave-completion-alist nil
350 "Alist of Octave symbols for completion in Octave mode.
351Each element looks like (VAR . VAR), where the car and cdr are the same
352symbol (an Octave command or variable name).
a1506d29 353Currently, only builtin variables can be completed.")
f2727dfb
RS
354
355(defvar octave-mode-imenu-generic-expression
356 (list
357 ;; Functions
358 (list nil octave-function-header-regexp 3))
359 "Imenu expression for Octave mode. See `imenu-generic-expression'.")
360
28d16ed3 361(defcustom octave-mode-hook nil
e22bbd48 362 "Hook to be run when Octave mode is started."
28d16ed3
AS
363 :type 'hook
364 :group 'octave)
365
366(defcustom octave-send-show-buffer t
e22bbd48 367 "Non-nil means display `inferior-octave-buffer' after sending to it."
28d16ed3
AS
368 :type 'boolean
369 :group 'octave)
370(defcustom octave-send-line-auto-forward t
e22bbd48 371 "Control auto-forward after sending to the inferior Octave process.
28d16ed3
AS
372Non-nil means always go to the next Octave code line after sending."
373 :type 'boolean
374 :group 'octave)
375(defcustom octave-send-echo-input t
e22bbd48 376 "Non-nil means echo input sent to the inferior Octave process."
28d16ed3
AS
377 :type 'boolean
378 :group 'octave)
f2727dfb
RS
379
380\f
e17b68ed
SM
381;;; SMIE indentation
382
383(require 'smie)
384
385(defconst octave-operator-table
386 '((assoc ";" "\n") (assoc ",") ; The doc claims they have equal precedence!?
387 (right "=" "+=" "-=" "*=" "/=")
388 (assoc "&&") (assoc "||") ; The doc claims they have equal precedence!?
389 (assoc "&") (assoc "|") ; The doc claims they have equal precedence!?
390 (nonassoc "<" "<=" "==" ">=" ">" "!=" "~=")
391 (nonassoc ":") ;No idea what this is.
392 (assoc "+" "-")
393 (assoc "*" "/" "\\" ".\\" ".*" "./")
394 (nonassoc "'" ".'")
395 (nonassoc "++" "--" "!" "~") ;And unary "+" and "-".
396 (right "^" "**" ".^" ".**")
397 ;; It's not really an operator, but for indentation purposes it
398 ;; could be convenient to treat it as one.
399 (assoc "...")))
400
89acf735
SM
401(defconst octave-smie-bnf-table
402 '((atom)
403 ;; We can't distinguish the first element in a sequence with
404 ;; precedence grammars, so we can't distinguish the condition
405 ;; if the `if' from the subsequent body, for example.
406 ;; This has to be done later in the indentation rules.
407 (exp (exp "\n" exp)
408 ;; We need to mention at least one of the operators in this part
409 ;; of the grammar: if the BNF and the operator table have
410 ;; no overlap, SMIE can't know how they relate.
411 (exp ";" exp)
412 ("try" exp "catch" exp "end_try_catch")
413 ("try" exp "catch" exp "end")
414 ("unwind_protect" exp
415 "unwind_protect_cleanup" exp "end_unwind_protect")
416 ("unwind_protect" exp "unwind_protect_cleanup" exp "end")
417 ("for" exp "endfor")
418 ("for" exp "end")
419 ("do" exp "until" atom)
420 ("while" exp "endwhile")
421 ("while" exp "end")
422 ("if" exp "endif")
423 ("if" exp "else" exp "endif")
424 ("if" exp "elseif" exp "else" exp "endif")
425 ("if" exp "elseif" exp "elseif" exp "else" exp "endif")
426 ("if" exp "elseif" exp "elseif" exp "else" exp "end")
427 ("switch" exp "case" exp "endswitch")
428 ("switch" exp "case" exp "otherwise" exp "endswitch")
429 ("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
430 ("switch" exp "case" exp "case" exp "otherwise" exp "end")
431 ("function" exp "endfunction")
432 ("function" exp "end"))
433 ;; (fundesc (atom "=" atom))
434 ))
435
674728d4
SM
436(defconst octave-smie-grammar
437 (smie-prec2->grammar
e17b68ed 438 (smie-merge-prec2s
674728d4
SM
439 (smie-bnf->prec2 octave-smie-bnf-table
440 '((assoc "\n" ";")))
e17b68ed 441
674728d4 442 (smie-precs->prec2 octave-operator-table))))
e17b68ed
SM
443
444;; Tokenizing needs to be refined so that ";;" is treated as two
445;; tokens and also so as to recognize the \n separator (and
446;; corresponding continuation lines).
447
448(defconst octave-operator-regexp
449 (regexp-opt (apply 'append (mapcar 'cdr octave-operator-table))))
450
451(defun octave-smie-backward-token ()
452 (let ((pos (point)))
453 (forward-comment (- (point)))
454 (cond
455 ((and (not (eq (char-before) ?\;)) ;Coalesce ";" and "\n".
456 (> pos (line-end-position))
457 (if (looking-back octave-continuation-marker-regexp (- (point) 3))
458 (progn
459 (goto-char (match-beginning 0))
460 (forward-comment (- (point)))
461 nil)
462 t)
463 ;; Ignore it if it's within parentheses.
464 (let ((ppss (syntax-ppss)))
465 (not (and (nth 1 ppss)
466 (eq ?\( (char-after (nth 1 ppss)))))))
467 (skip-chars-forward " \t")
468 ;; Why bother distinguishing \n and ;?
469 ";") ;;"\n"
470 ((and (looking-back octave-operator-regexp (- (point) 3) 'greedy)
471 ;; Don't mistake a string quote for a transpose.
472 (not (looking-back "\\s\"" (1- (point)))))
473 (goto-char (match-beginning 0))
474 (match-string-no-properties 0))
475 (t
476 (smie-default-backward-token)))))
477
478(defun octave-smie-forward-token ()
479 (skip-chars-forward " \t")
480 (when (looking-at (eval-when-compile
481 (concat "\\(" octave-continuation-marker-regexp
482 "\\)[ \t]*\\($\\|[%#]\\)")))
483 (goto-char (match-end 1))
484 (forward-comment 1))
485 (cond
486 ((and (looking-at "$\\|[%#]")
487 ;; Ignore it if it's within parentheses.
488 (prog1 (let ((ppss (syntax-ppss)))
489 (not (and (nth 1 ppss)
490 (eq ?\( (char-after (nth 1 ppss))))))
491 (forward-comment (point-max))))
492 ;; Why bother distinguishing \n and ;?
493 ";") ;;"\n"
494 ((looking-at ";[ \t]*\\($\\|[%#]\\)")
495 ;; Combine the ; with the subsequent \n.
496 (goto-char (match-beginning 1))
497 (forward-comment 1)
498 ";")
499 ((and (looking-at octave-operator-regexp)
500 ;; Don't mistake a string quote for a transpose.
501 (not (looking-at "\\s\"")))
502 (goto-char (match-end 0))
503 (match-string-no-properties 0))
504 (t
505 (smie-default-forward-token))))
506
c4d17d50
SM
507(defun octave-smie-rules (kind token)
508 (pcase (cons kind token)
674728d4
SM
509 ;; We could set smie-indent-basic instead, but that would have two
510 ;; disadvantages:
511 ;; - changes to octave-block-offset wouldn't take effect immediately.
512 ;; - edebug wouldn't show the use of this variable.
c4d17d50 513 (`(:elem . basic) octave-block-offset)
674728d4
SM
514 ;; Since "case" is in the same BNF rules as switch..end, SMIE by default
515 ;; aligns it with "switch".
516 (`(:before . "case") (if (not (smie-rule-sibling-p)) octave-block-offset))
c4d17d50 517 (`(:after . ";")
674728d4
SM
518 (if (smie-rule-parent-p "function" "if" "while" "else" "elseif" "for"
519 "otherwise" "case" "try" "catch" "unwind_protect"
520 "unwind_protect_cleanup")
521 (smie-rule-parent octave-block-offset)
c4d17d50
SM
522 ;; For (invalid) code between switch and case.
523 ;; (if (smie-parent-p "switch") 4)
524 0))))
e17b68ed 525
03f70355 526(defvar electric-layout-rules)
b073dc4b 527
f2727dfb 528;;;###autoload
c82d5b11 529(define-derived-mode octave-mode prog-mode "Octave"
f2727dfb
RS
530 "Major mode for editing Octave code.
531
532This mode makes it easier to write Octave code by helping with
533indentation, doing some of the typing for you (with Abbrev mode) and by
0472835f 534showing keywords, comments, strings, etc. in different faces (with
f2727dfb
RS
535Font Lock mode on terminals that support it).
536
537Octave itself is a high-level language, primarily intended for numerical
538computations. It provides a convenient command line interface for
539solving linear and nonlinear problems numerically. Function definitions
540can also be stored in files, and it can be used in a batch mode (which
541is why you need this mode!).
542
543The latest released version of Octave is always available via anonymous
490a8abe 544ftp from ftp.octave.org in the directory `/pub/octave'. Complete
f2727dfb
RS
545source and binaries for several popular systems are available.
546
547Type \\[list-abbrevs] to display the built-in abbrevs for Octave keywords.
548
549Keybindings
550===========
551
552\\{octave-mode-map}
553
554Variables you can use to customize Octave mode
555==============================================
556
e22bbd48 557`octave-blink-matching-block'
f2727dfb
RS
558 Non-nil means show matching begin of block when inserting a space,
559 newline or semicolon after an else or end keyword. Default is t.
560
e22bbd48 561`octave-block-offset'
f2727dfb
RS
562 Extra indentation applied to statements in block structures.
563 Default is 2.
564
e22bbd48 565`octave-continuation-offset'
f2727dfb
RS
566 Extra indentation applied to Octave continuation lines.
567 Default is 4.
568
e22bbd48 569`octave-continuation-string'
f2727dfb
RS
570 String used for Octave continuation lines.
571 Default is a backslash.
572
e22bbd48 573`octave-send-echo-input'
f2727dfb
RS
574 Non-nil means always display `inferior-octave-buffer' after sending a
575 command to the inferior Octave process.
576
e22bbd48 577`octave-send-line-auto-forward'
f2727dfb
RS
578 Non-nil means always go to the next unsent line of Octave code after
579 sending a line to the inferior Octave process.
580
e22bbd48 581`octave-send-echo-input'
f2727dfb
RS
582 Non-nil means echo input sent to the inferior Octave process.
583
584Turning on Octave mode runs the hook `octave-mode-hook'.
585
586To begin using this mode for all `.m' files that you edit, add the
587following lines to your `.emacs' file:
588
e22bbd48 589 (add-to-list 'auto-mode-alist '(\"\\\\.m\\\\'\" . octave-mode))
f2727dfb 590
490a8abe 591To automatically turn on the abbrev and auto-fill features,
f2727dfb
RS
592add the following lines to your `.emacs' file as well:
593
594 (add-hook 'octave-mode-hook
595 (lambda ()
596 (abbrev-mode 1)
e22bbd48 597 (auto-fill-mode 1)))
f2727dfb
RS
598
599To submit a problem report, enter \\[octave-submit-bug-report] from \
600an Octave mode buffer.
601This automatically sets up a mail buffer with version information
602already added. You just need to add a description of the problem,
603including a reproducible test case and send the message."
f2727dfb 604 (setq local-abbrev-table octave-abbrev-table)
c82d5b11 605
674728d4 606 (smie-setup octave-smie-grammar #'octave-smie-rules
c4d17d50
SM
607 :forward-token #'octave-smie-forward-token
608 :backward-token #'octave-smie-backward-token)
e17b68ed 609 (set (make-local-variable 'smie-indent-basic) 'octave-block-offset)
c4d17d50 610
89acf735 611 (set (make-local-variable 'smie-blink-matching-triggers)
c4d17d50
SM
612 (cons ?\; smie-blink-matching-triggers))
613 (unless octave-blink-matching-block
614 (remove-hook 'post-self-insert-hook #'smie-blink-matching-open 'local))
89acf735 615
2122161f
SM
616 (set (make-local-variable 'electric-indent-chars)
617 (cons ?\; electric-indent-chars))
03f70355
SM
618 ;; IIUC matlab-mode takes the opposite approach: it makes RET insert
619 ;; a ";" at those places where it's correct (i.e. outside of parens).
620 (set (make-local-variable 'electric-layout-rules) '((?\; . after)))
c82d5b11
SM
621
622 (set (make-local-variable 'comment-start) octave-comment-start)
623 (set (make-local-variable 'comment-end) "")
624 ;; Don't set it here: it's not really a property of the language,
625 ;; just a personal preference of the author.
626 ;; (set (make-local-variable 'comment-column) 32)
627 (set (make-local-variable 'comment-start-skip) "\\s<+\\s-*")
dc94fc85 628 (set (make-local-variable 'comment-add) 1)
f2727dfb 629
c82d5b11
SM
630 (set (make-local-variable 'parse-sexp-ignore-comments) t)
631 (set (make-local-variable 'paragraph-start)
632 (concat "\\s-*$\\|" page-delimiter))
633 (set (make-local-variable 'paragraph-separate) paragraph-start)
634 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
635 (set (make-local-variable 'fill-paragraph-function) 'octave-fill-paragraph)
636 ;; FIXME: Why disable it?
637 ;; (set (make-local-variable 'adaptive-fill-regexp) nil)
638 ;; Again, this is not a property of the language, don't set it here.
639 ;; (set (make-local-variable 'fill-column) 72)
640 (set (make-local-variable 'normal-auto-fill-function) 'octave-auto-fill)
641
642 (set (make-local-variable 'font-lock-defaults)
cf38dd42
SM
643 '(octave-font-lock-keywords))
644
645 (set (make-local-variable 'syntax-propertize-function)
646 #'octave-syntax-propertize-function)
c82d5b11
SM
647
648 (set (make-local-variable 'imenu-generic-expression)
649 octave-mode-imenu-generic-expression)
650 (set (make-local-variable 'imenu-case-fold-search) nil)
651
652 (add-hook 'completion-at-point-functions
653 'octave-completion-at-point-function nil t)
ff80a446
SM
654 (set (make-local-variable 'beginning-of-defun-function)
655 'octave-beginning-of-defun)
f2727dfb 656
ff80a446 657 (easy-menu-add octave-mode-menu)
175069ef 658 (octave-initialize-completions))
5d8137ab 659
ff80a446
SM
660(defvar info-lookup-mode)
661
5d8137ab
SM
662(defun octave-help ()
663 "Get help on Octave symbols from the Octave info files.
664Look up symbol in the function, operator and variable indices of the info files."
665 (let ((info-lookup-mode 'octave-mode))
666 (call-interactively 'info-lookup-symbol)))
f2727dfb
RS
667\f
668;;; Miscellaneous useful functions
f2727dfb 669
f2727dfb 670(defsubst octave-in-comment-p ()
e7f767c2 671 "Return t if point is inside an Octave comment."
f2727dfb 672 (save-excursion
c82d5b11 673 ;; FIXME: use syntax-ppss?
cb3d3ec1 674 (nth 4 (parse-partial-sexp (line-beginning-position) (point)))))
f2727dfb
RS
675
676(defsubst octave-in-string-p ()
e7f767c2 677 "Return t if point is inside an Octave string."
f2727dfb 678 (save-excursion
c82d5b11 679 ;; FIXME: use syntax-ppss?
cb3d3ec1 680 (nth 3 (parse-partial-sexp (line-beginning-position) (point)))))
f2727dfb
RS
681
682(defsubst octave-not-in-string-or-comment-p ()
e7f767c2 683 "Return t if point is not inside an Octave string or comment."
c82d5b11 684 ;; FIXME: Use syntax-ppss?
cb3d3ec1 685 (let ((pps (parse-partial-sexp (line-beginning-position) (point))))
f2727dfb
RS
686 (not (or (nth 3 pps) (nth 4 pps)))))
687
f2727dfb 688
a584f30f 689(defun octave-looking-at-kw (regexp)
050a4b35 690 "Like `looking-at', but sets `case-fold-search' nil."
a584f30f
GM
691 (let ((case-fold-search nil))
692 (looking-at regexp)))
693
d83ee578
KH
694(defun octave-maybe-insert-continuation-string ()
695 (if (or (octave-in-comment-p)
696 (save-excursion
697 (beginning-of-line)
698 (looking-at octave-continuation-regexp)))
699 nil
700 (delete-horizontal-space)
701 (insert (concat " " octave-continuation-string))))
702
f2727dfb
RS
703\f
704;;; Indentation
f2727dfb
RS
705
706(defun octave-indent-new-comment-line ()
707 "Break Octave line at point, continuing comment if within one.
708If within code, insert `octave-continuation-string' before breaking the
a1506d29
JB
709line. If within a string, signal an error.
710The new line is properly indented."
f2727dfb
RS
711 (interactive)
712 (delete-horizontal-space)
713 (cond
714 ((octave-in-comment-p)
715 (indent-new-comment-line))
716 ((octave-in-string-p)
717 (error "Cannot split a code line inside a string"))
718 (t
719 (insert (concat " " octave-continuation-string))
03f70355 720 (reindent-then-newline-and-indent))))
f2727dfb
RS
721
722(defun octave-indent-defun ()
e22bbd48 723 "Properly indent the Octave function which contains point."
f2727dfb
RS
724 (interactive)
725 (save-excursion
ff80a446 726 (mark-defun)
f2727dfb
RS
727 (message "Indenting function...")
728 (indent-region (point) (mark) nil))
729 (message "Indenting function...done."))
730
731\f
732;;; Motion
733(defun octave-next-code-line (&optional arg)
734 "Move ARG lines of Octave code forward (backward if ARG is negative).
735Skips past all empty and comment lines. Default for ARG is 1.
736
737On success, return 0. Otherwise, go as far as possible and return -1."
738 (interactive "p")
739 (or arg (setq arg 1))
740 (beginning-of-line)
741 (let ((n 0)
742 (inc (if (> arg 0) 1 -1)))
743 (while (and (/= arg 0) (= n 0))
744 (setq n (forward-line inc))
745 (while (and (= n 0)
746 (looking-at "\\s-*\\($\\|\\s<\\)"))
747 (setq n (forward-line inc)))
748 (setq arg (- arg inc)))
749 n))
a1506d29 750
f2727dfb
RS
751(defun octave-previous-code-line (&optional arg)
752 "Move ARG lines of Octave code backward (forward if ARG is negative).
753Skips past all empty and comment lines. Default for ARG is 1.
754
755On success, return 0. Otherwise, go as far as possible and return -1."
756 (interactive "p")
757 (or arg (setq arg 1))
758 (octave-next-code-line (- arg)))
759
760(defun octave-beginning-of-line ()
761 "Move point to beginning of current Octave line.
762If on an empty or comment line, go to the beginning of that line.
763Otherwise, move backward to the beginning of the first Octave code line
764which is not inside a continuation statement, i.e., which does not
765follow a code line ending in `...' or `\\', or is inside an open
766parenthesis list."
767 (interactive)
768 (beginning-of-line)
769 (if (not (looking-at "\\s-*\\($\\|\\s<\\)"))
770 (while (or (condition-case nil
771 (progn
772 (up-list -1)
773 (beginning-of-line)
774 t)
775 (error nil))
776 (and (or (looking-at "\\s-*\\($\\|\\s<\\)")
777 (save-excursion
778 (if (zerop (octave-previous-code-line))
779 (looking-at octave-continuation-regexp))))
780 (zerop (forward-line -1)))))))
781
782(defun octave-end-of-line ()
783 "Move point to end of current Octave line.
784If on an empty or comment line, go to the end of that line.
785Otherwise, move forward to the end of the first Octave code line which
786does not end in `...' or `\\' or is inside an open parenthesis list."
787 (interactive)
788 (end-of-line)
789 (if (save-excursion
790 (beginning-of-line)
791 (looking-at "\\s-*\\($\\|\\s<\\)"))
792 ()
793 (while (or (condition-case nil
794 (progn
795 (up-list 1)
796 (end-of-line)
797 t)
798 (error nil))
799 (and (save-excursion
800 (beginning-of-line)
801 (or (looking-at "\\s-*\\($\\|\\s<\\)")
802 (looking-at octave-continuation-regexp)))
803 (zerop (forward-line 1)))))
804 (end-of-line)))
a1506d29 805
f2727dfb
RS
806(defun octave-mark-block ()
807 "Put point at the beginning of this Octave block, mark at the end.
808The block marked is the one that contains point or follows point."
809 (interactive)
ec5d3ff7
SM
810 (unless (or (looking-at "\\s(")
811 (save-excursion
812 (let* ((token (funcall smie-forward-token-function))
6d2a1e35 813 (level (assoc token smie-grammar)))
ec5d3ff7
SM
814 (and level (null (cadr level))))))
815 (backward-up-list 1))
816 (mark-sexp))
f2727dfb 817
f2727dfb
RS
818(defun octave-beginning-of-defun (&optional arg)
819 "Move backward to the beginning of an Octave function.
820With positive ARG, do it that many times. Negative argument -N means
821move forward to Nth following beginning of a function.
822Returns t unless search stops at the beginning or end of the buffer."
f2727dfb
RS
823 (let* ((arg (or arg 1))
824 (inc (if (> arg 0) 1 -1))
ff80a446
SM
825 (found nil)
826 (case-fold-search nil))
f2727dfb 827 (and (not (eobp))
ff80a446 828 (not (and (> arg 0) (looking-at "\\<function\\>")))
f2727dfb
RS
829 (skip-syntax-forward "w"))
830 (while (and (/= arg 0)
831 (setq found
ff80a446 832 (re-search-backward "\\<function\\>" inc)))
f2727dfb
RS
833 (if (octave-not-in-string-or-comment-p)
834 (setq arg (- arg inc))))
835 (if found
836 (progn
837 (and (< inc 0) (goto-char (match-beginning 0)))
838 t))))
839
f2727dfb
RS
840\f
841;;; Filling
842(defun octave-auto-fill ()
d83ee578
KH
843 "Perform auto-fill in Octave mode.
844Returns nil if no feasible place to break the line could be found, and t
845otherwise."
846 (let (fc give-up)
847 (if (or (null (setq fc (current-fill-column)))
848 (save-excursion
a1506d29 849 (beginning-of-line)
d83ee578 850 (and auto-fill-inhibit-regexp
a584f30f 851 (octave-looking-at-kw auto-fill-inhibit-regexp))))
d83ee578
KH
852 nil ; Can't do anything
853 (if (and (not (octave-in-comment-p))
854 (> (current-column) fc))
855 (setq fc (- fc (+ (length octave-continuation-string) 1))))
856 (while (and (not give-up) (> (current-column) fc))
857 (let* ((opoint (point))
858 (fpoint
859 (save-excursion
860 (move-to-column (+ fc 1))
861 (skip-chars-backward "^ \t\n")
862 ;; If we're at the beginning of the line, break after
863 ;; the first word
864 (if (bolp)
865 (re-search-forward "[ \t]" opoint t))
866 ;; If we're in a comment line, don't break after the
867 ;; comment chars
868 (if (save-excursion
869 (skip-syntax-backward " <")
870 (bolp))
cb3d3ec1 871 (re-search-forward "[ \t]" (line-end-position)
d83ee578
KH
872 'move))
873 ;; If we're not in a comment line and just ahead the
874 ;; continuation string, don't break here.
875 (if (and (not (octave-in-comment-p))
876 (looking-at
877 (concat "\\s-*"
878 (regexp-quote
879 octave-continuation-string)
880 "\\s-*$")))
881 (end-of-line))
882 (skip-chars-backward " \t")
883 (point))))
884 (if (save-excursion
885 (goto-char fpoint)
886 (not (or (bolp) (eolp))))
887 (let ((prev-column (current-column)))
888 (if (save-excursion
889 (skip-chars-backward " \t")
890 (= (point) fpoint))
891 (progn
892 (octave-maybe-insert-continuation-string)
893 (indent-new-comment-line t))
894 (save-excursion
895 (goto-char fpoint)
896 (octave-maybe-insert-continuation-string)
897 (indent-new-comment-line t)))
898 (if (>= (current-column) prev-column)
899 (setq give-up t)))
900 (setq give-up t))))
901 (not give-up))))
f2727dfb
RS
902
903(defun octave-fill-paragraph (&optional arg)
ec5d3ff7
SM
904 "Fill paragraph of Octave code, handling Octave comments."
905 ;; FIXME: difference with generic fill-paragraph:
906 ;; - code lines are only split, never joined.
907 ;; - \n that end comments are never removed.
908 ;; - insert continuation marker when splitting code lines.
909 (interactive "P")
910 (save-excursion
911 (let ((end (progn (forward-paragraph) (copy-marker (point) t)))
912 (beg (progn
913 (forward-paragraph -1)
914 (skip-chars-forward " \t\n")
915 (beginning-of-line)
916 (point)))
917 (cfc (current-fill-column))
918 comment-prefix)
919 (goto-char beg)
920 (while (< (point) end)
921 (condition-case nil
922 (indent-according-to-mode)
923 (error nil))
924 (move-to-column cfc)
925 ;; First check whether we need to combine non-empty comment lines
926 (if (and (< (current-column) cfc)
927 (octave-in-comment-p)
928 (not (save-excursion
929 (beginning-of-line)
930 (looking-at "^\\s-*\\s<+\\s-*$"))))
931 ;; This is a nonempty comment line which does not extend
932 ;; past the fill column. If it is followed by a nonempty
933 ;; comment line with the same comment prefix, try to
934 ;; combine them, and repeat this until either we reach the
935 ;; fill-column or there is nothing more to combine.
936 (progn
937 ;; Get the comment prefix
938 (save-excursion
939 (beginning-of-line)
940 (while (and (re-search-forward "\\s<+")
941 (not (octave-in-comment-p))))
942 (setq comment-prefix (match-string 0)))
943 ;; And keep combining ...
944 (while (and (< (current-column) cfc)
945 (save-excursion
946 (forward-line 1)
947 (and (looking-at
948 (concat "^\\s-*"
949 comment-prefix
950 "\\S<"))
951 (not (looking-at
952 (concat "^\\s-*"
953 comment-prefix
954 "\\s-*$"))))))
955 (delete-char 1)
956 (re-search-forward comment-prefix)
957 (delete-region (match-beginning 0) (match-end 0))
958 (fixup-whitespace)
959 (move-to-column cfc))))
960 ;; We might also try to combine continued code lines> Perhaps
961 ;; some other time ...
962 (skip-chars-forward "^ \t\n")
963 (delete-horizontal-space)
964 (if (or (< (current-column) cfc)
965 (and (= (current-column) cfc) (eolp)))
966 (forward-line 1)
967 (if (not (eolp)) (insert " "))
968 (or (octave-auto-fill)
969 (forward-line 1))))
970 t)))
f2727dfb
RS
971
972\f
973;;; Completions
974(defun octave-initialize-completions ()
975 "Create an alist for Octave completions."
976 (if octave-completion-alist
977 ()
978 (setq octave-completion-alist
c82d5b11
SM
979 (append octave-reserved-words
980 octave-text-functions
981 octave-variables))))
982
983(defun octave-completion-at-point-function ()
984 "Find the text to complete and the corresponding table."
7e82caa7 985 (let* ((beg (save-excursion (backward-sexp 1) (point)))
ff80a446
SM
986 (end (point)))
987 (if (< beg (point))
988 ;; Extend region past point, if applicable.
989 (save-excursion (goto-char beg) (forward-sexp 1)
990 (setq end (max end (point)))))
c82d5b11 991 (list beg end octave-completion-alist)))
f2727dfb
RS
992
993(defun octave-complete-symbol ()
994 "Perform completion on Octave symbol preceding point.
995Compare that symbol against Octave's reserved words and builtin
996variables."
f2727dfb 997 (interactive)
c82d5b11 998 (apply 'completion-in-region (octave-completion-at-point-function)))
f2727dfb
RS
999\f
1000;;; Electric characters && friends
f2727dfb
RS
1001
1002(defun octave-abbrev-start ()
1003 "Start entering an Octave abbreviation.
1004If Abbrev mode is turned on, typing ` (grave accent) followed by ? or
1005\\[help-command] lists all Octave abbrevs. Any other key combination is
1006executed normally.
1007Note that all Octave mode abbrevs start with a grave accent."
1008 (interactive)
1009 (if (not abbrev-mode)
1010 (self-insert-command 1)
1011 (let (c)
1ba983e8 1012 (insert last-command-event)
f8246027 1013 (if (if (featurep 'xemacs)
aa82f4fb
KH
1014 (or (eq (event-to-character (setq c (next-event))) ??)
1015 (eq (event-to-character c) help-char))
1016 (or (eq (setq c (read-event)) ??)
1017 (eq c help-char)))
1018 (let ((abbrev-table-name-list '(octave-abbrev-table)))
f2727dfb
RS
1019 (list-abbrevs))
1020 (setq unread-command-events (list c))))))
1021
c82d5b11 1022(define-skeleton octave-insert-defun
f2727dfb
RS
1023 "Insert an Octave function skeleton.
1024Prompt for the function's name, arguments and return values (to be
1025entered without parens)."
c82d5b11
SM
1026 (let* ((defname (substring (buffer-name) 0 -2))
1027 (name (read-string (format "Function name (default %s): " defname)
1028 nil nil defname))
1029 (args (read-string "Arguments: "))
1030 (vals (read-string "Return values: ")))
1031 (format "%s%s (%s)"
1032 (cond
1033 ((string-equal vals "") vals)
1034 ((string-match "[ ,]" vals) (concat "[" vals "] = "))
1035 (t (concat vals " = ")))
1036 name
1037 args))
1038 \n "function " > str \n \n
1039 octave-block-comment-start "usage: " str \n
1040 octave-block-comment-start \n octave-block-comment-start
1041 \n _ \n
1042 "endfunction" > \n)
f2727dfb 1043\f
f2727dfb
RS
1044;;; Communication with the inferior Octave process
1045(defun octave-kill-process ()
1046 "Kill inferior Octave process and its buffer."
1047 (interactive)
1048 (if inferior-octave-process
1049 (progn
1050 (process-send-string inferior-octave-process "quit;\n")
1051 (accept-process-output inferior-octave-process)))
1052 (if inferior-octave-buffer
1053 (kill-buffer inferior-octave-buffer)))
1054
1055(defun octave-show-process-buffer ()
1056 "Make sure that `inferior-octave-buffer' is displayed."
1057 (interactive)
1058 (if (get-buffer inferior-octave-buffer)
1059 (display-buffer inferior-octave-buffer)
1060 (message "No buffer named %s" inferior-octave-buffer)))
1061
1062(defun octave-hide-process-buffer ()
1063 "Delete all windows that display `inferior-octave-buffer'."
1064 (interactive)
1065 (if (get-buffer inferior-octave-buffer)
1066 (delete-windows-on inferior-octave-buffer)
1067 (message "No buffer named %s" inferior-octave-buffer)))
1068
1069(defun octave-send-region (beg end)
1070 "Send current region to the inferior Octave process."
1071 (interactive "r")
a1506d29 1072 (inferior-octave t)
f2727dfb
RS
1073 (let ((proc inferior-octave-process)
1074 (string (buffer-substring-no-properties beg end))
1075 line)
5d8137ab 1076 (with-current-buffer inferior-octave-buffer
f2727dfb
RS
1077 (setq inferior-octave-output-list nil)
1078 (while (not (string-equal string ""))
1079 (if (string-match "\n" string)
1080 (setq line (substring string 0 (match-beginning 0))
1081 string (substring string (match-end 0)))
1082 (setq line string string ""))
1083 (setq inferior-octave-receive-in-progress t)
1084 (inferior-octave-send-list-and-digest (list (concat line "\n")))
1085 (while inferior-octave-receive-in-progress
1086 (accept-process-output proc))
1087 (insert-before-markers
1088 (mapconcat 'identity
1089 (append
1090 (if octave-send-echo-input (list line) (list ""))
1091 (mapcar 'inferior-octave-strip-ctrl-g
1092 inferior-octave-output-list)
1093 (list inferior-octave-output-string))
1094 "\n")))))
1095 (if octave-send-show-buffer
1096 (display-buffer inferior-octave-buffer)))
1097
1098(defun octave-send-block ()
a1506d29 1099 "Send current Octave block to the inferior Octave process."
f2727dfb
RS
1100 (interactive)
1101 (save-excursion
1102 (octave-mark-block)
1103 (octave-send-region (point) (mark))))
1104
1105(defun octave-send-defun ()
1106 "Send current Octave function to the inferior Octave process."
1107 (interactive)
1108 (save-excursion
ff80a446 1109 (mark-defun)
f2727dfb
RS
1110 (octave-send-region (point) (mark))))
1111
1112(defun octave-send-line (&optional arg)
1113 "Send current Octave code line to the inferior Octave process.
1114With positive prefix ARG, send that many lines.
1115If `octave-send-line-auto-forward' is non-nil, go to the next unsent
1116code line."
1117 (interactive "P")
1118 (or arg (setq arg 1))
1119 (if (> arg 0)
1120 (let (beg end)
1121 (beginning-of-line)
1122 (setq beg (point))
1123 (octave-next-code-line (- arg 1))
1124 (end-of-line)
1125 (setq end (point))
1126 (if octave-send-line-auto-forward
1127 (octave-next-code-line 1))
1128 (octave-send-region beg end))))
1129
1130(defun octave-eval-print-last-sexp ()
1131 "Evaluate Octave sexp before point and print value into current buffer."
1132 (interactive)
1133 (inferior-octave t)
1134 (let ((standard-output (current-buffer))
1135 (print-escape-newlines nil)
1136 (opoint (point)))
1137 (terpri)
a1506d29 1138 (prin1
f2727dfb
RS
1139 (save-excursion
1140 (forward-sexp -1)
1141 (inferior-octave-send-list-and-digest
1142 (list (concat (buffer-substring-no-properties (point) opoint)
1143 "\n")))
1144 (mapconcat 'identity inferior-octave-output-list "\n")))
1145 (terpri)))
d1e49742 1146\f
d1e49742
RS
1147;;; Bug reporting
1148(defun octave-submit-bug-report ()
1149 "Submit a bug report on the Emacs Octave package via mail."
1150 (interactive)
1151 (require 'reporter)
1152 (and
1153 (y-or-n-p "Do you want to submit a bug report? ")
1154 (reporter-submit-bug-report
1155 octave-maintainer-address
1156 (concat "Emacs version " emacs-version)
1157 (list
d1e49742
RS
1158 'octave-blink-matching-block
1159 'octave-block-offset
1160 'octave-comment-char
1161 'octave-continuation-offset
1162 'octave-continuation-string
d1e49742
RS
1163 'octave-send-echo-input
1164 'octave-send-line-auto-forward
1165 'octave-send-show-buffer))))
1166
5d8137ab 1167;; provide ourself
d1e49742 1168
e7017ef9 1169(provide 'octave-mod)
d1e49742
RS
1170
1171;;; octave-mod.el ends here