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