diff options
| author | Richard M. Stallman | 1997-01-21 00:29:57 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-01-21 00:29:57 +0000 |
| commit | f2727dfb21fd63bd9c1cae2c24ac6f4c5b787a66 (patch) | |
| tree | e279be0ef2b55cc57aeffafb1f7ea1ec0f5edcf1 | |
| parent | f8f5c5f4448c66a48ac092879aa2ad4c9d0d5338 (diff) | |
| download | emacs-f2727dfb21fd63bd9c1cae2c24ac6f4c5b787a66.tar.gz emacs-f2727dfb21fd63bd9c1cae2c24ac6f4c5b787a66.zip | |
Initial revision
| -rw-r--r-- | lisp/progmodes/octave-mod.el | 1227 |
1 files changed, 1227 insertions, 0 deletions
diff --git a/lisp/progmodes/octave-mod.el b/lisp/progmodes/octave-mod.el new file mode 100644 index 00000000000..d640154748b --- /dev/null +++ b/lisp/progmodes/octave-mod.el | |||
| @@ -0,0 +1,1227 @@ | |||
| 1 | ;; octave-mod.el --- editing Octave source files under Emacs | ||
| 2 | |||
| 3 | ;;; Copyright (C) 1997 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at> | ||
| 6 | ;; Author: John Eaton <jwe@bevo.che.wisc.edu> | ||
| 7 | ;; Maintainer: Kurt Hornik <Kurt.Hornik@ci.tuwien.ac.at> | ||
| 8 | ;; Keywords: languages | ||
| 9 | |||
| 10 | ;; This file is part of GNU Emacs. | ||
| 11 | |||
| 12 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 13 | ;; it under the terms of the GNU General Public License as published by | ||
| 14 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 15 | ;; any later version. | ||
| 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 | ||
| 23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 24 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 25 | ;; Boston, MA 02111-1307, USA. | ||
| 26 | |||
| 27 | ;;; Commentary: | ||
| 28 | |||
| 29 | ;;; Code: | ||
| 30 | |||
| 31 | (require 'octave) | ||
| 32 | |||
| 33 | ;; Keep the debugger quiet | ||
| 34 | (eval-when-compile (load "octave-inf")) | ||
| 35 | |||
| 36 | (defvar octave-mode-map nil | ||
| 37 | "Keymap used in Octave mode.") | ||
| 38 | (if octave-mode-map | ||
| 39 | () | ||
| 40 | (let ((map (make-sparse-keymap))) | ||
| 41 | (define-key map "`" 'octave-abbrev-start) | ||
| 42 | (define-key map ";" 'octave-electric-semi) | ||
| 43 | (define-key map " " 'octave-electric-space) | ||
| 44 | (define-key map "\n" 'octave-reindent-then-newline-and-indent) | ||
| 45 | (define-key map "\t" 'indent-according-to-mode) | ||
| 46 | (define-key map "\e;" 'octave-indent-for-comment) | ||
| 47 | (define-key map "\e\n" 'octave-indent-new-comment-line) | ||
| 48 | (define-key map "\e\t" 'octave-complete-symbol) | ||
| 49 | (define-key map "\M-\C-a" 'octave-beginning-of-defun) | ||
| 50 | (define-key map "\M-\C-e" 'octave-end-of-defun) | ||
| 51 | (define-key map "\M-\C-h" 'octave-mark-defun) | ||
| 52 | (define-key map "\M-\C-q" 'octave-indent-defun) | ||
| 53 | (define-key map "\C-c;" 'octave-comment-region) | ||
| 54 | (define-key map "\C-c:" 'octave-uncomment-region) | ||
| 55 | (define-key map "\C-c\C-b" 'octave-submit-bug-report) | ||
| 56 | (define-key map "\C-c\C-p" 'octave-previous-code-line) | ||
| 57 | (define-key map "\C-c\C-n" 'octave-next-code-line) | ||
| 58 | (define-key map "\C-c\C-a" 'octave-beginning-of-line) | ||
| 59 | (define-key map "\C-c\C-e" 'octave-end-of-line) | ||
| 60 | (define-key map "\C-c\M-\C-n" 'octave-forward-block) | ||
| 61 | (define-key map "\C-c\M-\C-p" 'octave-backward-block) | ||
| 62 | (define-key map "\C-c\M-\C-u" 'octave-backward-up-block) | ||
| 63 | (define-key map "\C-c\M-\C-d" 'octave-down-block) | ||
| 64 | (define-key map "\C-c\M-\C-h" 'octave-mark-block) | ||
| 65 | (define-key map "\C-c]" 'octave-close-block) | ||
| 66 | (define-key map "\C-cf" 'octave-insert-defun) | ||
| 67 | (define-key map "\C-c\C-h" 'octave-help) | ||
| 68 | (define-key map "\C-cil" 'octave-send-line) | ||
| 69 | (define-key map "\C-cib" 'octave-send-block) | ||
| 70 | (define-key map "\C-cif" 'octave-send-defun) | ||
| 71 | (define-key map "\C-cir" 'octave-send-region) | ||
| 72 | (define-key map "\C-cis" 'octave-show-process-buffer) | ||
| 73 | (define-key map "\C-cih" 'octave-hide-process-buffer) | ||
| 74 | (define-key map "\C-cik" 'octave-kill-process) | ||
| 75 | (setq octave-mode-map map))) | ||
| 76 | |||
| 77 | (defvar octave-mode-menu | ||
| 78 | (list "Octave" | ||
| 79 | (list "Lines" | ||
| 80 | ["Previous Code Line" octave-previous-code-line t] | ||
| 81 | ["Next Code Line" octave-next-code-line t] | ||
| 82 | ["Begin of Continuation" octave-beginning-of-line t] | ||
| 83 | ["End of Continuation" octave-end-of-line t] | ||
| 84 | ["Split Line at Point" octave-indent-new-comment-line t]) | ||
| 85 | (list "Blocks" | ||
| 86 | ["Next Block" octave-forward-block t] | ||
| 87 | ["Previous Block" octave-backward-block t] | ||
| 88 | ["Down Block" octave-down-block t] | ||
| 89 | ["Up Block" octave-backward-up-block t] | ||
| 90 | ["Mark Block" octave-mark-block t] | ||
| 91 | ["Close Block" octave-close-block t]) | ||
| 92 | (list "Functions" | ||
| 93 | ["Begin of Function" octave-beginning-of-defun t] | ||
| 94 | ["End of Function" octave-end-of-defun t] | ||
| 95 | ["Mark Function" octave-mark-defun t] | ||
| 96 | ["Indent Function" octave-indent-defun t] | ||
| 97 | ["Insert Function" octave-insert-defun t]) | ||
| 98 | "-" | ||
| 99 | (list "Debug" | ||
| 100 | ["Send Current Line" octave-send-line t] | ||
| 101 | ["Send Current Block" octave-send-block t] | ||
| 102 | ["Send Current Function" octave-send-defun t] | ||
| 103 | ["Send Region" octave-send-region t] | ||
| 104 | ["Show Process Buffer" octave-show-process-buffer t] | ||
| 105 | ["Hide Process Buffer" octave-hide-process-buffer t] | ||
| 106 | ["Kill Process" octave-kill-process t]) | ||
| 107 | "-" | ||
| 108 | ["Indent Line" indent-according-to-mode t] | ||
| 109 | ["Complete Symbol" octave-complete-symbol t] | ||
| 110 | "-" | ||
| 111 | ["Toggle Abbrev Mode" abbrev-mode t] | ||
| 112 | ["Toggle Auto-Fill Mode" auto-fill-mode t] | ||
| 113 | "-" | ||
| 114 | ["Submit Bug Report" octave-submit-bug-report t] | ||
| 115 | "-" | ||
| 116 | ["Describe Octave Mode" octave-describe-major-mode t] | ||
| 117 | ["Lookup Octave Index" octave-help t]) | ||
| 118 | "Menu for Octave mode.") | ||
| 119 | |||
| 120 | (defvar octave-mode-syntax-table nil | ||
| 121 | "Syntax table in use in octave-mode buffers.") | ||
| 122 | (if octave-mode-syntax-table | ||
| 123 | () | ||
| 124 | (let ((table (make-syntax-table))) | ||
| 125 | (modify-syntax-entry ?\r " " table) | ||
| 126 | (modify-syntax-entry ?+ "." table) | ||
| 127 | (modify-syntax-entry ?- "." table) | ||
| 128 | (modify-syntax-entry ?= "." table) | ||
| 129 | (modify-syntax-entry ?* "." table) | ||
| 130 | (modify-syntax-entry ?/ "." table) | ||
| 131 | (modify-syntax-entry ?> "." table) | ||
| 132 | (modify-syntax-entry ?< "." table) | ||
| 133 | (modify-syntax-entry ?& "." table) | ||
| 134 | (modify-syntax-entry ?| "." table) | ||
| 135 | (modify-syntax-entry ?! "." table) | ||
| 136 | (modify-syntax-entry ?\\ "\\" table) | ||
| 137 | (modify-syntax-entry ?\' "." table) | ||
| 138 | (modify-syntax-entry ?\` "w" table) | ||
| 139 | (modify-syntax-entry ?\" "\"" table) | ||
| 140 | (modify-syntax-entry ?. "w" table) | ||
| 141 | (modify-syntax-entry ?_ "w" table) | ||
| 142 | (modify-syntax-entry ?\% "." table) | ||
| 143 | (modify-syntax-entry ?\# "<" table) | ||
| 144 | (modify-syntax-entry ?\n ">" table) | ||
| 145 | (setq octave-mode-syntax-table table))) | ||
| 146 | |||
| 147 | (defvar octave-auto-newline nil | ||
| 148 | "*Non-nil means automatically newline after a semicolon in Octave mode.") | ||
| 149 | |||
| 150 | (defvar octave-blink-matching-block t | ||
| 151 | "*Control the blinking of matching Octave block keywords. | ||
| 152 | Non-nil means show matching begin of block when inserting a space, | ||
| 153 | newline or semicolon after an else or end keyword.") | ||
| 154 | (defvar octave-block-offset 2 | ||
| 155 | "*Extra indentation applied to statements in Octave block structures.") | ||
| 156 | |||
| 157 | (defvar octave-block-begin-regexp | ||
| 158 | (concat "\\<\\(" | ||
| 159 | (mapconcat 'identity octave-begin-keywords "\\|") | ||
| 160 | "\\)\\>")) | ||
| 161 | (defvar octave-block-else-regexp | ||
| 162 | (concat "\\<\\(" | ||
| 163 | (mapconcat 'identity octave-else-keywords "\\|") | ||
| 164 | "\\)\\>")) | ||
| 165 | (defvar octave-block-end-regexp | ||
| 166 | (concat "\\<\\(" | ||
| 167 | (mapconcat 'identity octave-end-keywords "\\|") | ||
| 168 | "\\)\\>")) | ||
| 169 | (defvar octave-block-begin-or-end-regexp | ||
| 170 | (concat octave-block-begin-regexp "\\|" octave-block-end-regexp)) | ||
| 171 | (defvar octave-block-else-or-end-regexp | ||
| 172 | (concat octave-block-else-regexp "\\|" octave-block-end-regexp)) | ||
| 173 | (defvar octave-block-match-alist | ||
| 174 | '(("for" . ("end" "endfor")) | ||
| 175 | ("function" . ("end" "endfunction")) | ||
| 176 | ("if" . ("else" "elseif" "end" "endif")) | ||
| 177 | ("try" . ("catch" "end" "end_try_catch")) | ||
| 178 | ("unwind_protect" . ("unwind_protect_cleanup" "end" | ||
| 179 | "end_unwind_protect")) | ||
| 180 | ("while" . ("end" "endwhile"))) | ||
| 181 | "Alist with Octave's matching block keywords. | ||
| 182 | Has Octave's begin keywords as keys and a list of the matching else or | ||
| 183 | end keywords as associated values.") | ||
| 184 | |||
| 185 | (defvar octave-block-comment-start | ||
| 186 | (concat (make-string 2 octave-comment-char) " ") | ||
| 187 | "String to insert to start a new Octave comment on an empty line.") | ||
| 188 | |||
| 189 | (defvar octave-continuation-offset 4 | ||
| 190 | "*Extra indentation applied to Octave continuation lines.") | ||
| 191 | (defvar octave-continuation-regexp | ||
| 192 | "[^#%\n]*\\(\\\\\\|\\.\\.\\.\\)\\s-*\\(\\s<.*\\)?$") | ||
| 193 | (defvar octave-continuation-string "\\" | ||
| 194 | "*Character string used for Octave continuation lines. Normally \\.") | ||
| 195 | |||
| 196 | (defvar octave-completion-alist nil | ||
| 197 | "Alist of Octave symbols for completion in Octave mode. | ||
| 198 | Each element looks like (VAR . VAR), where the car and cdr are the same | ||
| 199 | symbol (an Octave command or variable name). | ||
| 200 | Currently, only builtin variables can be completed.") | ||
| 201 | |||
| 202 | (defvar octave-mode-imenu-generic-expression | ||
| 203 | (list | ||
| 204 | ;; Functions | ||
| 205 | (list nil octave-function-header-regexp 3)) | ||
| 206 | "Imenu expression for Octave mode. See `imenu-generic-expression'.") | ||
| 207 | |||
| 208 | (defvar octave-mode-startup-message t | ||
| 209 | "*Nil means do not display the Octave mode startup message.") | ||
| 210 | |||
| 211 | (defvar octave-mode-hook nil | ||
| 212 | "*Hook to be run when Octave mode is started.") | ||
| 213 | |||
| 214 | (defvar octave-send-show-buffer t | ||
| 215 | "*Non-nil means display `inferior-octave-buffer' after sending to it.") | ||
| 216 | (defvar octave-send-line-auto-forward t | ||
| 217 | "*Control auto-forward after sending to the inferior Octave process. | ||
| 218 | Non-nil means always go to the next Octave code line after sending.") | ||
| 219 | (defvar octave-send-echo-input t | ||
| 220 | "*Non-nil means echo input sent to the inferior Octave process.") | ||
| 221 | |||
| 222 | |||
| 223 | ;;;###autoload | ||
| 224 | (defun octave-mode () | ||
| 225 | "Major mode for editing Octave code. | ||
| 226 | |||
| 227 | This mode makes it easier to write Octave code by helping with | ||
| 228 | indentation, doing some of the typing for you (with Abbrev mode) and by | ||
| 229 | showing keywords, comments, strings, etc. in different faces (with | ||
| 230 | Font Lock mode on terminals that support it). | ||
| 231 | |||
| 232 | Octave itself is a high-level language, primarily intended for numerical | ||
| 233 | computations. It provides a convenient command line interface for | ||
| 234 | solving linear and nonlinear problems numerically. Function definitions | ||
| 235 | can also be stored in files, and it can be used in a batch mode (which | ||
| 236 | is why you need this mode!). | ||
| 237 | |||
| 238 | The latest released version of Octave is always available via anonymous | ||
| 239 | ftp from bevo.che.wisc.edu in the directory `/pub/octave'. Complete | ||
| 240 | source and binaries for several popular systems are available. | ||
| 241 | |||
| 242 | Type \\[list-abbrevs] to display the built-in abbrevs for Octave keywords. | ||
| 243 | |||
| 244 | Keybindings | ||
| 245 | =========== | ||
| 246 | |||
| 247 | \\{octave-mode-map} | ||
| 248 | |||
| 249 | Variables you can use to customize Octave mode | ||
| 250 | ============================================== | ||
| 251 | |||
| 252 | octave-auto-newline | ||
| 253 | Non-nil means auto-insert a newline and indent after a semicolon. | ||
| 254 | Default is nil. | ||
| 255 | |||
| 256 | octave-blink-matching-block | ||
| 257 | Non-nil means show matching begin of block when inserting a space, | ||
| 258 | newline or semicolon after an else or end keyword. Default is t. | ||
| 259 | |||
| 260 | octave-block-offset | ||
| 261 | Extra indentation applied to statements in block structures. | ||
| 262 | Default is 2. | ||
| 263 | |||
| 264 | octave-continuation-offset | ||
| 265 | Extra indentation applied to Octave continuation lines. | ||
| 266 | Default is 4. | ||
| 267 | |||
| 268 | octave-continuation-string | ||
| 269 | String used for Octave continuation lines. | ||
| 270 | Default is a backslash. | ||
| 271 | |||
| 272 | octave-mode-startup-message | ||
| 273 | Nil means do not display the Octave mode startup message. | ||
| 274 | Default is t. | ||
| 275 | |||
| 276 | octave-send-echo-input | ||
| 277 | Non-nil means always display `inferior-octave-buffer' after sending a | ||
| 278 | command to the inferior Octave process. | ||
| 279 | |||
| 280 | octave-send-line-auto-forward | ||
| 281 | Non-nil means always go to the next unsent line of Octave code after | ||
| 282 | sending a line to the inferior Octave process. | ||
| 283 | |||
| 284 | octave-send-echo-input | ||
| 285 | Non-nil means echo input sent to the inferior Octave process. | ||
| 286 | |||
| 287 | Turning on Octave mode runs the hook `octave-mode-hook'. | ||
| 288 | |||
| 289 | To begin using this mode for all `.m' files that you edit, add the | ||
| 290 | following lines to your `.emacs' file: | ||
| 291 | |||
| 292 | (autoload 'octave-mode \"octave-mod\" nil t) | ||
| 293 | (setq auto-mode-alist | ||
| 294 | (cons '(\"\\\\.m$\" . octave-mode) auto-mode-alist)) | ||
| 295 | |||
| 296 | To automatically turn on the abbrev, auto-fill and font-lock features, | ||
| 297 | add the following lines to your `.emacs' file as well: | ||
| 298 | |||
| 299 | (add-hook 'octave-mode-hook | ||
| 300 | (lambda () | ||
| 301 | (abbrev-mode 1) | ||
| 302 | (auto-fill-mode 1) | ||
| 303 | (if (eq window-system 'x) | ||
| 304 | (font-lock-mode 1)))) | ||
| 305 | |||
| 306 | To submit a problem report, enter \\[octave-submit-bug-report] from \ | ||
| 307 | an Octave mode buffer. | ||
| 308 | This automatically sets up a mail buffer with version information | ||
| 309 | already added. You just need to add a description of the problem, | ||
| 310 | including a reproducible test case and send the message." | ||
| 311 | (interactive) | ||
| 312 | (kill-all-local-variables) | ||
| 313 | |||
| 314 | (use-local-map octave-mode-map) | ||
| 315 | (setq major-mode 'octave-mode) | ||
| 316 | (setq mode-name "Octave") | ||
| 317 | (setq local-abbrev-table octave-abbrev-table) | ||
| 318 | (set-syntax-table octave-mode-syntax-table) | ||
| 319 | |||
| 320 | (make-local-variable 'indent-line-function) | ||
| 321 | (setq indent-line-function 'octave-indent-line) | ||
| 322 | |||
| 323 | (make-local-variable 'comment-start) | ||
| 324 | (setq comment-start octave-comment-start) | ||
| 325 | (make-local-variable 'comment-end) | ||
| 326 | (setq comment-end "") | ||
| 327 | (make-local-variable 'comment-column) | ||
| 328 | (setq comment-column 32) | ||
| 329 | (make-local-variable 'comment-start-skip) | ||
| 330 | (setq comment-start-skip "\\s<+\\s-*") | ||
| 331 | (make-local-variable 'comment-indent-function) | ||
| 332 | (setq comment-indent-function 'octave-comment-indent) | ||
| 333 | |||
| 334 | (make-local-variable 'parse-sexp-ignore-comments) | ||
| 335 | (setq parse-sexp-ignore-comments t) | ||
| 336 | (make-local-variable 'paragraph-start) | ||
| 337 | (setq paragraph-start (concat "\\s-*$\\|" page-delimiter)) | ||
| 338 | (make-local-variable 'paragraph-separate) | ||
| 339 | (setq paragraph-separate paragraph-start) | ||
| 340 | (make-local-variable 'paragraph-ignore-fill-prefix) | ||
| 341 | (setq paragraph-ignore-fill-prefix t) | ||
| 342 | (make-local-variable 'fill-paragraph-function) | ||
| 343 | (setq fill-paragraph-function 'octave-fill-paragraph) | ||
| 344 | (make-local-variable 'adaptive-fill-regexp) | ||
| 345 | (setq adaptive-fill-regexp nil) | ||
| 346 | (make-local-variable 'fill-column) | ||
| 347 | (setq fill-column 72) | ||
| 348 | (make-local-variable 'normal-auto-fill-function) | ||
| 349 | (setq normal-auto-fill-function 'octave-auto-fill) | ||
| 350 | |||
| 351 | (make-local-variable 'font-lock-defaults) | ||
| 352 | (setq font-lock-defaults '(octave-font-lock-keywords nil nil)) | ||
| 353 | |||
| 354 | (make-local-variable 'imenu-generic-expression) | ||
| 355 | (setq imenu-generic-expression octave-mode-imenu-generic-expression) | ||
| 356 | |||
| 357 | (octave-add-octave-menu) | ||
| 358 | (octave-initialize-completions) | ||
| 359 | (run-hooks 'octave-mode-hook) | ||
| 360 | (if octave-mode-startup-message | ||
| 361 | (message "Octave mode %s. Bugs to %s" | ||
| 362 | octave-version octave-maintainer-address))) | ||
| 363 | |||
| 364 | |||
| 365 | ;;; Miscellaneous useful functions | ||
| 366 | (defun octave-describe-major-mode () | ||
| 367 | "Describe the current major mode." | ||
| 368 | (interactive) | ||
| 369 | (describe-function major-mode)) | ||
| 370 | |||
| 371 | (defun octave-point (position) | ||
| 372 | "Returns the value of point at certain positions." | ||
| 373 | (save-excursion | ||
| 374 | (cond | ||
| 375 | ((eq position 'bol) (beginning-of-line)) | ||
| 376 | ((eq position 'eol) (end-of-line)) | ||
| 377 | ((eq position 'boi) (back-to-indentation)) | ||
| 378 | ((eq position 'bonl) (forward-line 1)) | ||
| 379 | ((eq position 'bopl) (forward-line -1)) | ||
| 380 | (t (error "unknown buffer position requested: %s" position))) | ||
| 381 | (point))) | ||
| 382 | |||
| 383 | (defsubst octave-in-comment-p () | ||
| 384 | "Returns t if point is inside an Octave comment, nil otherwise." | ||
| 385 | (interactive) | ||
| 386 | (save-excursion | ||
| 387 | (nth 4 (parse-partial-sexp (octave-point 'bol) (point))))) | ||
| 388 | |||
| 389 | (defsubst octave-in-string-p () | ||
| 390 | "Returns t if point is inside an Octave string, nil otherwise." | ||
| 391 | (interactive) | ||
| 392 | (save-excursion | ||
| 393 | (nth 3 (parse-partial-sexp (octave-point 'bol) (point))))) | ||
| 394 | |||
| 395 | (defsubst octave-not-in-string-or-comment-p () | ||
| 396 | "Returns t iff point is not inside an Octave string or comment." | ||
| 397 | (let ((pps (parse-partial-sexp (octave-point 'bol) (point)))) | ||
| 398 | (not (or (nth 3 pps) (nth 4 pps))))) | ||
| 399 | |||
| 400 | (defun octave-in-block-p () | ||
| 401 | "Returns t if point is inside an Octave block, nil otherwise. | ||
| 402 | The block is taken to start at the first letter of the begin keyword and | ||
| 403 | to end after the end keyword." | ||
| 404 | (let ((pos (point))) | ||
| 405 | (save-excursion | ||
| 406 | (condition-case nil | ||
| 407 | (progn | ||
| 408 | (skip-syntax-forward "w") | ||
| 409 | (octave-up-block -1) | ||
| 410 | (octave-forward-block) | ||
| 411 | t) | ||
| 412 | (error nil)) | ||
| 413 | (< pos (point))))) | ||
| 414 | |||
| 415 | (defun octave-in-defun-p () | ||
| 416 | "Returns t iff point is inside an Octave function declaration. | ||
| 417 | The function is taken to start at the `f' of `function' and to end after | ||
| 418 | the end keyword." | ||
| 419 | (let ((pos (point))) | ||
| 420 | (save-excursion | ||
| 421 | (or (and (looking-at "\\<function\\>") | ||
| 422 | (octave-not-in-string-or-comment-p)) | ||
| 423 | (and (octave-beginning-of-defun) | ||
| 424 | (condition-case nil | ||
| 425 | (progn | ||
| 426 | (octave-forward-block) | ||
| 427 | t) | ||
| 428 | (error nil)) | ||
| 429 | (< pos (point))))))) | ||
| 430 | |||
| 431 | ;;; Comments | ||
| 432 | (defun octave-comment-region (beg end &optional arg) | ||
| 433 | "Comment or uncomment each line in the region as Octave code. | ||
| 434 | See `comment-region'." | ||
| 435 | (interactive "r\nP") | ||
| 436 | (let ((comment-start (char-to-string octave-comment-char))) | ||
| 437 | (comment-region beg end arg))) | ||
| 438 | |||
| 439 | (defun octave-uncomment-region (beg end &optional arg) | ||
| 440 | "Uncomment each line in the region as Octave code." | ||
| 441 | (interactive "r\nP") | ||
| 442 | (or arg (setq arg 1)) | ||
| 443 | (octave-comment-region beg end (- arg))) | ||
| 444 | |||
| 445 | |||
| 446 | ;;; Indentation | ||
| 447 | (defun calculate-octave-indent () | ||
| 448 | "Return appropriate indentation for current line as Octave code. | ||
| 449 | Returns an integer (the column to indent to) unless the line is a | ||
| 450 | comment line with fixed goal golumn. In that case, returns a list whose | ||
| 451 | car is the column to indent to, and whose cdr is the current indentation | ||
| 452 | level." | ||
| 453 | (let ((is-continuation-line | ||
| 454 | (save-excursion | ||
| 455 | (if (zerop (octave-previous-code-line)) | ||
| 456 | (looking-at octave-continuation-regexp)))) | ||
| 457 | (icol 0)) | ||
| 458 | (save-excursion | ||
| 459 | (beginning-of-line) | ||
| 460 | ;; If we can move backward out one level of parentheses, take 1 | ||
| 461 | ;; plus the indentation of that parenthesis. Otherwise, go back | ||
| 462 | ;; to the beginning of the previous code line, and compute the | ||
| 463 | ;; offset this line gives. | ||
| 464 | (if (condition-case nil | ||
| 465 | (progn | ||
| 466 | (up-list -1) | ||
| 467 | t) | ||
| 468 | (error nil)) | ||
| 469 | (setq icol (+ 1 (current-column))) | ||
| 470 | (if (zerop (octave-previous-code-line)) | ||
| 471 | (progn | ||
| 472 | (octave-beginning-of-line) | ||
| 473 | (back-to-indentation) | ||
| 474 | (setq icol (current-column)) | ||
| 475 | (let ((bot (point)) | ||
| 476 | (eol (octave-point 'eol))) | ||
| 477 | (while (< (point) eol) | ||
| 478 | (if (octave-not-in-string-or-comment-p) | ||
| 479 | (cond | ||
| 480 | ((looking-at octave-block-begin-regexp) | ||
| 481 | (setq icol (+ icol octave-block-offset))) | ||
| 482 | ((looking-at octave-block-else-regexp) | ||
| 483 | (if (= bot (point)) | ||
| 484 | (setq icol (+ icol octave-block-offset)))) | ||
| 485 | ((looking-at octave-block-end-regexp) | ||
| 486 | (if (not (= bot (point))) | ||
| 487 | (setq icol (- icol octave-block-offset)))))) | ||
| 488 | (forward-char))) | ||
| 489 | (if is-continuation-line | ||
| 490 | (setq icol (+ icol octave-continuation-offset))))))) | ||
| 491 | (save-excursion | ||
| 492 | (back-to-indentation) | ||
| 493 | (cond | ||
| 494 | ((and (or (looking-at octave-block-else-regexp) | ||
| 495 | (looking-at octave-block-end-regexp)) | ||
| 496 | (octave-not-in-string-or-comment-p)) | ||
| 497 | (setq icol (- icol octave-block-offset))) | ||
| 498 | ((looking-at "\\s<\\s<\\s<\\S<") | ||
| 499 | (setq icol (list 0 icol))) | ||
| 500 | ((looking-at "\\s<\\S<") | ||
| 501 | (setq icol (list comment-column icol))))) | ||
| 502 | icol)) | ||
| 503 | |||
| 504 | (defun octave-comment-indent () | ||
| 505 | (if (looking-at "\\s<\\s<\\s<") | ||
| 506 | 0 | ||
| 507 | (if (looking-at "\\s<\\s<") | ||
| 508 | (calculate-octave-indent) | ||
| 509 | (skip-syntax-backward " ") | ||
| 510 | (max (if (bolp) 0 (+ (current-column))) | ||
| 511 | comment-column)))) | ||
| 512 | |||
| 513 | (defun octave-indent-for-comment () | ||
| 514 | "Maybe insert and indent an Octave comment. | ||
| 515 | If there is no comment already on this line, create a code-level comment | ||
| 516 | (started by two comment characters) if the line is empty, or an in-line | ||
| 517 | comment (started by one comment character) otherwise. | ||
| 518 | Point is left after the start of the comment which is properly aligned." | ||
| 519 | (interactive) | ||
| 520 | (indent-for-comment) | ||
| 521 | (indent-according-to-mode)) | ||
| 522 | |||
| 523 | (defun octave-indent-line (&optional arg) | ||
| 524 | "Indent current line as Octave code. | ||
| 525 | With optional ARG, use this as offset unless this line is a comment with | ||
| 526 | fixed goal column." | ||
| 527 | (interactive) | ||
| 528 | (or arg (setq arg 0)) | ||
| 529 | (let ((icol (calculate-octave-indent)) | ||
| 530 | (relpos (- (current-column) (current-indentation)))) | ||
| 531 | (if (listp icol) | ||
| 532 | (setq icol (car icol)) | ||
| 533 | (setq icol (+ icol arg))) | ||
| 534 | (if (< icol 0) | ||
| 535 | (error "Unmatched end keyword") | ||
| 536 | (indent-line-to icol) | ||
| 537 | (if (> relpos 0) | ||
| 538 | (move-to-column (+ icol relpos)))))) | ||
| 539 | |||
| 540 | (defun octave-indent-new-comment-line () | ||
| 541 | "Break Octave line at point, continuing comment if within one. | ||
| 542 | If within code, insert `octave-continuation-string' before breaking the | ||
| 543 | line. If within a string, signal an error. | ||
| 544 | The new line is properly indented." | ||
| 545 | (interactive) | ||
| 546 | (delete-horizontal-space) | ||
| 547 | (cond | ||
| 548 | ((octave-in-comment-p) | ||
| 549 | (indent-new-comment-line)) | ||
| 550 | ((octave-in-string-p) | ||
| 551 | (error "Cannot split a code line inside a string")) | ||
| 552 | (t | ||
| 553 | (insert (concat " " octave-continuation-string)) | ||
| 554 | (octave-reindent-then-newline-and-indent)))) | ||
| 555 | |||
| 556 | (defun octave-indent-defun () | ||
| 557 | "Properly indents the Octave function which contains point." | ||
| 558 | (interactive) | ||
| 559 | (save-excursion | ||
| 560 | (octave-mark-defun) | ||
| 561 | (message "Indenting function...") | ||
| 562 | (indent-region (point) (mark) nil)) | ||
| 563 | (message "Indenting function...done.")) | ||
| 564 | |||
| 565 | |||
| 566 | ;;; Motion | ||
| 567 | (defun octave-next-code-line (&optional arg) | ||
| 568 | "Move ARG lines of Octave code forward (backward if ARG is negative). | ||
| 569 | Skips past all empty and comment lines. Default for ARG is 1. | ||
| 570 | |||
| 571 | On success, return 0. Otherwise, go as far as possible and return -1." | ||
| 572 | (interactive "p") | ||
| 573 | (or arg (setq arg 1)) | ||
| 574 | (beginning-of-line) | ||
| 575 | (let ((n 0) | ||
| 576 | (inc (if (> arg 0) 1 -1))) | ||
| 577 | (while (and (/= arg 0) (= n 0)) | ||
| 578 | (setq n (forward-line inc)) | ||
| 579 | (while (and (= n 0) | ||
| 580 | (looking-at "\\s-*\\($\\|\\s<\\)")) | ||
| 581 | (setq n (forward-line inc))) | ||
| 582 | (setq arg (- arg inc))) | ||
| 583 | n)) | ||
| 584 | |||
| 585 | (defun octave-previous-code-line (&optional arg) | ||
| 586 | "Move ARG lines of Octave code backward (forward if ARG is negative). | ||
| 587 | Skips past all empty and comment lines. Default for ARG is 1. | ||
| 588 | |||
| 589 | On success, return 0. Otherwise, go as far as possible and return -1." | ||
| 590 | (interactive "p") | ||
| 591 | (or arg (setq arg 1)) | ||
| 592 | (octave-next-code-line (- arg))) | ||
| 593 | |||
| 594 | (defun octave-beginning-of-line () | ||
| 595 | "Move point to beginning of current Octave line. | ||
| 596 | If on an empty or comment line, go to the beginning of that line. | ||
| 597 | Otherwise, move backward to the beginning of the first Octave code line | ||
| 598 | which is not inside a continuation statement, i.e., which does not | ||
| 599 | follow a code line ending in `...' or `\\', or is inside an open | ||
| 600 | parenthesis list." | ||
| 601 | (interactive) | ||
| 602 | (beginning-of-line) | ||
| 603 | (if (not (looking-at "\\s-*\\($\\|\\s<\\)")) | ||
| 604 | (while (or (condition-case nil | ||
| 605 | (progn | ||
| 606 | (up-list -1) | ||
| 607 | (beginning-of-line) | ||
| 608 | t) | ||
| 609 | (error nil)) | ||
| 610 | (and (or (looking-at "\\s-*\\($\\|\\s<\\)") | ||
| 611 | (save-excursion | ||
| 612 | (if (zerop (octave-previous-code-line)) | ||
| 613 | (looking-at octave-continuation-regexp)))) | ||
| 614 | (zerop (forward-line -1))))))) | ||
| 615 | |||
| 616 | (defun octave-end-of-line () | ||
| 617 | "Move point to end of current Octave line. | ||
| 618 | If on an empty or comment line, go to the end of that line. | ||
| 619 | Otherwise, move forward to the end of the first Octave code line which | ||
| 620 | does not end in `...' or `\\' or is inside an open parenthesis list." | ||
| 621 | (interactive) | ||
| 622 | (end-of-line) | ||
| 623 | (if (save-excursion | ||
| 624 | (beginning-of-line) | ||
| 625 | (looking-at "\\s-*\\($\\|\\s<\\)")) | ||
| 626 | () | ||
| 627 | (while (or (condition-case nil | ||
| 628 | (progn | ||
| 629 | (up-list 1) | ||
| 630 | (end-of-line) | ||
| 631 | t) | ||
| 632 | (error nil)) | ||
| 633 | (and (save-excursion | ||
| 634 | (beginning-of-line) | ||
| 635 | (or (looking-at "\\s-*\\($\\|\\s<\\)") | ||
| 636 | (looking-at octave-continuation-regexp))) | ||
| 637 | (zerop (forward-line 1))))) | ||
| 638 | (end-of-line))) | ||
| 639 | |||
| 640 | (defun octave-scan-blocks (from count depth) | ||
| 641 | "Scan from character number FROM by COUNT Octave begin-end blocks. | ||
| 642 | Returns the character number of the position thus found. | ||
| 643 | |||
| 644 | If DEPTH is nonzero, block depth begins counting from that value. | ||
| 645 | Only places where the depth in blocks becomes zero are candidates for | ||
| 646 | stopping; COUNT such places are counted. | ||
| 647 | |||
| 648 | If the beginning or end of the buffer is reached and the depth is wrong, | ||
| 649 | an error is signaled." | ||
| 650 | (let ((min-depth (if (> depth 0) 0 depth)) | ||
| 651 | (inc (if (> count 0) 1 -1))) | ||
| 652 | (save-excursion | ||
| 653 | (while (/= count 0) | ||
| 654 | (catch 'foo | ||
| 655 | (while (or (re-search-forward | ||
| 656 | octave-block-begin-or-end-regexp nil 'move inc) | ||
| 657 | (if (/= depth 0) | ||
| 658 | (error "Unbalanced block"))) | ||
| 659 | (if (octave-not-in-string-or-comment-p) | ||
| 660 | (progn | ||
| 661 | (cond | ||
| 662 | ((match-end 1) | ||
| 663 | (setq depth (+ depth inc))) | ||
| 664 | ((match-end 2) | ||
| 665 | (setq depth (- depth inc)))) | ||
| 666 | (if (< depth min-depth) | ||
| 667 | (error "Containing expression ends prematurely")) | ||
| 668 | (if (= depth 0) | ||
| 669 | (throw 'foo nil)))))) | ||
| 670 | (setq count (- count inc))) | ||
| 671 | (point)))) | ||
| 672 | |||
| 673 | (defun octave-forward-block (&optional arg) | ||
| 674 | "Move forward across one balanced Octave begin-end block. | ||
| 675 | With argument, do it that many times. | ||
| 676 | Negative arg -N means move backward across N blocks." | ||
| 677 | (interactive "p") | ||
| 678 | (or arg (setq arg 1)) | ||
| 679 | (goto-char (or (octave-scan-blocks (point) arg 0) (buffer-end arg)))) | ||
| 680 | |||
| 681 | (defun octave-backward-block (&optional arg) | ||
| 682 | "Move backward across one balanced Octave begin-end block. | ||
| 683 | With argument, do it that many times. | ||
| 684 | Negative arg -N means move forward across N blocks." | ||
| 685 | (interactive "p") | ||
| 686 | (or arg (setq arg 1)) | ||
| 687 | (octave-forward-block (- arg))) | ||
| 688 | |||
| 689 | (defun octave-down-block (arg) | ||
| 690 | "Move forward down one begin-end block level of Octave code. | ||
| 691 | With argument, do this that many times. | ||
| 692 | A negative argument means move backward but still go down a level. | ||
| 693 | In Lisp programs, an argument is required." | ||
| 694 | (interactive "p") | ||
| 695 | (let ((inc (if (> arg 0) 1 -1))) | ||
| 696 | (while (/= arg 0) | ||
| 697 | (goto-char (or (octave-scan-blocks (point) inc -1) | ||
| 698 | (buffer-end arg))) | ||
| 699 | (setq arg (- arg inc))))) | ||
| 700 | |||
| 701 | (defun octave-backward-up-block (arg) | ||
| 702 | "Move backward out of one begin-end block level of Octave code. | ||
| 703 | With argument, do this that many times. | ||
| 704 | A negative argument means move forward but still to a less deep spot. | ||
| 705 | In Lisp programs, an argument is required." | ||
| 706 | (interactive "p") | ||
| 707 | (octave-up-block (- arg))) | ||
| 708 | |||
| 709 | (defun octave-up-block (arg) | ||
| 710 | "Move forward out of one begin-end block level of Octave code. | ||
| 711 | With argument, do this that many times. | ||
| 712 | A negative argument means move backward but still to a less deep spot. | ||
| 713 | In Lisp programs, an argument is required." | ||
| 714 | (interactive "p") | ||
| 715 | (let ((inc (if (> arg 0) 1 -1))) | ||
| 716 | (while (/= arg 0) | ||
| 717 | (goto-char (or (octave-scan-blocks (point) inc 1) | ||
| 718 | (buffer-end arg))) | ||
| 719 | (setq arg (- arg inc))))) | ||
| 720 | |||
| 721 | (defun octave-mark-block () | ||
| 722 | "Put point at the beginning of this Octave block, mark at the end. | ||
| 723 | The block marked is the one that contains point or follows point." | ||
| 724 | (interactive) | ||
| 725 | (let ((pos (point))) | ||
| 726 | (if (or (and (octave-in-block-p) | ||
| 727 | (skip-syntax-forward "w")) | ||
| 728 | (condition-case nil | ||
| 729 | (progn | ||
| 730 | (octave-down-block 1) | ||
| 731 | (octave-in-block-p)) | ||
| 732 | (error nil))) | ||
| 733 | (progn | ||
| 734 | (octave-up-block -1) | ||
| 735 | (push-mark (point)) | ||
| 736 | (octave-forward-block) | ||
| 737 | (exchange-point-and-mark)) | ||
| 738 | (goto-char pos) | ||
| 739 | (message "No block to mark found")))) | ||
| 740 | |||
| 741 | (defun octave-close-block () | ||
| 742 | "Close the current Octave block on a separate line. | ||
| 743 | An error is signaled if no block to close is found." | ||
| 744 | (interactive) | ||
| 745 | (let (bb-keyword) | ||
| 746 | (condition-case nil | ||
| 747 | (progn | ||
| 748 | (save-excursion | ||
| 749 | (octave-backward-up-block 1) | ||
| 750 | (setq bb-keyword (buffer-substring-no-properties | ||
| 751 | (match-beginning 1) (match-end 1)))) | ||
| 752 | (if (save-excursion | ||
| 753 | (beginning-of-line) | ||
| 754 | (looking-at "^\\s-*$")) | ||
| 755 | (indent-according-to-mode) | ||
| 756 | (octave-reindent-then-newline-and-indent)) | ||
| 757 | (insert (car (reverse | ||
| 758 | (assoc bb-keyword | ||
| 759 | octave-block-match-alist)))) | ||
| 760 | (octave-reindent-then-newline-and-indent) | ||
| 761 | t) | ||
| 762 | (error (message "No block to close found"))))) | ||
| 763 | |||
| 764 | (defun octave-blink-matching-block-open () | ||
| 765 | "Blink the matching Octave begin block keyword. | ||
| 766 | If point is right after an Octave else or end type block keyword, move | ||
| 767 | cursor momentarily to the corresponding begin keyword. | ||
| 768 | Signal an error if the keywords are incompatible." | ||
| 769 | (interactive) | ||
| 770 | (let (bb-keyword bb-arg eb-keyword pos eol) | ||
| 771 | (if (and (octave-not-in-string-or-comment-p) | ||
| 772 | (looking-at "\\>") | ||
| 773 | (save-excursion | ||
| 774 | (skip-syntax-backward "w") | ||
| 775 | (looking-at octave-block-else-or-end-regexp))) | ||
| 776 | (save-excursion | ||
| 777 | (cond | ||
| 778 | ((match-end 1) | ||
| 779 | (setq eb-keyword | ||
| 780 | (buffer-substring-no-properties | ||
| 781 | (match-beginning 1) (match-end 1))) | ||
| 782 | (octave-backward-up-block 1)) | ||
| 783 | ((match-end 2) | ||
| 784 | (setq eb-keyword | ||
| 785 | (buffer-substring-no-properties | ||
| 786 | (match-beginning 2) (match-end 2))) | ||
| 787 | (octave-backward-block))) | ||
| 788 | (setq pos (match-end 0) | ||
| 789 | bb-keyword | ||
| 790 | (buffer-substring-no-properties | ||
| 791 | (match-beginning 0) pos) | ||
| 792 | pos (+ pos 1) | ||
| 793 | eol (octave-point 'eol) | ||
| 794 | bb-arg | ||
| 795 | (save-excursion | ||
| 796 | (save-restriction | ||
| 797 | (goto-char pos) | ||
| 798 | (while (and (skip-syntax-forward "^<" eol) | ||
| 799 | (octave-in-string-p) | ||
| 800 | (not (forward-char 1)))) | ||
| 801 | (skip-syntax-backward " ") | ||
| 802 | (buffer-substring-no-properties pos (point))))) | ||
| 803 | (if (member eb-keyword | ||
| 804 | (cdr (assoc bb-keyword octave-block-match-alist))) | ||
| 805 | (progn | ||
| 806 | (message "Matches `%s %s'" bb-keyword bb-arg) | ||
| 807 | (if (pos-visible-in-window-p) | ||
| 808 | (sit-for blink-matching-delay))) | ||
| 809 | (error "Block keywords `%s' and `%s' do not match" | ||
| 810 | bb-keyword eb-keyword)))))) | ||
| 811 | |||
| 812 | (defun octave-beginning-of-defun (&optional arg) | ||
| 813 | "Move backward to the beginning of an Octave function. | ||
| 814 | With positive ARG, do it that many times. Negative argument -N means | ||
| 815 | move forward to Nth following beginning of a function. | ||
| 816 | Returns t unless search stops at the beginning or end of the buffer." | ||
| 817 | (interactive "p") | ||
| 818 | (let* ((arg (or arg 1)) | ||
| 819 | (inc (if (> arg 0) 1 -1)) | ||
| 820 | (found)) | ||
| 821 | (and (not (eobp)) | ||
| 822 | (not (and (> arg 0) (looking-at "\\<function\\>"))) | ||
| 823 | (skip-syntax-forward "w")) | ||
| 824 | (while (and (/= arg 0) | ||
| 825 | (setq found | ||
| 826 | (re-search-backward "\\<function\\>" nil 'move inc))) | ||
| 827 | (if (octave-not-in-string-or-comment-p) | ||
| 828 | (setq arg (- arg inc)))) | ||
| 829 | (if found | ||
| 830 | (progn | ||
| 831 | (and (< inc 0) (goto-char (match-beginning 0))) | ||
| 832 | t)))) | ||
| 833 | |||
| 834 | (defun octave-end-of-defun (&optional arg) | ||
| 835 | "Move forward to the end of an Octave function. | ||
| 836 | With positive ARG, do it that many times. Negative argument -N means | ||
| 837 | move back to Nth preceding end of a function. | ||
| 838 | |||
| 839 | An end of a function occurs right after the end keyword matching the | ||
| 840 | `function' keyword that starts the function." | ||
| 841 | (interactive "p") | ||
| 842 | (or arg (setq arg 1)) | ||
| 843 | (and (< arg 0) (skip-syntax-backward "w")) | ||
| 844 | (and (> arg 0) (skip-syntax-forward "w")) | ||
| 845 | (if (octave-in-defun-p) | ||
| 846 | (setq arg (- arg 1))) | ||
| 847 | (if (= arg 0) (setq arg -1)) | ||
| 848 | (if (octave-beginning-of-defun (- arg)) | ||
| 849 | (octave-forward-block))) | ||
| 850 | |||
| 851 | (defun octave-mark-defun () | ||
| 852 | "Put point at the beginning of this Octave function, mark at its end. | ||
| 853 | The function marked is the one containing point or following point." | ||
| 854 | (interactive) | ||
| 855 | (let ((pos (point))) | ||
| 856 | (if (or (octave-in-defun-p) | ||
| 857 | (and (octave-beginning-of-defun -1) | ||
| 858 | (octave-in-defun-p))) | ||
| 859 | (progn | ||
| 860 | (skip-syntax-forward "w") | ||
| 861 | (octave-beginning-of-defun) | ||
| 862 | (push-mark (point)) | ||
| 863 | (octave-end-of-defun) | ||
| 864 | (exchange-point-and-mark)) | ||
| 865 | (goto-char pos) | ||
| 866 | (message "No function to mark found")))) | ||
| 867 | |||
| 868 | |||
| 869 | ;;; Filling | ||
| 870 | (defun octave-auto-fill () | ||
| 871 | "Perform auto-fill in Octave mode." | ||
| 872 | (if (> (current-column) (current-fill-column)) | ||
| 873 | (if (octave-in-comment-p) | ||
| 874 | (do-auto-fill) | ||
| 875 | (if (> (current-column) (current-fill-column)) | ||
| 876 | (let ((fill-column (- (current-fill-column) | ||
| 877 | (length octave-continuation-string)))) | ||
| 878 | (do-auto-fill) | ||
| 879 | (save-excursion | ||
| 880 | (forward-line -1) | ||
| 881 | (end-of-line) | ||
| 882 | (insert (concat " " octave-continuation-string))) | ||
| 883 | (indent-according-to-mode)))))) | ||
| 884 | |||
| 885 | (defun octave-fill-paragraph (&optional arg) | ||
| 886 | "Fill paragraph of Octave code, handling Octave comments." | ||
| 887 | (interactive "P") | ||
| 888 | (save-excursion | ||
| 889 | (let ((end (progn (forward-paragraph) (point))) | ||
| 890 | (beg (progn | ||
| 891 | (forward-paragraph -1) | ||
| 892 | (skip-chars-forward " \t\n") | ||
| 893 | (beginning-of-line) | ||
| 894 | (point))) | ||
| 895 | (cfc (current-fill-column)) | ||
| 896 | (ind (calculate-octave-indent)) | ||
| 897 | comment-prefix) | ||
| 898 | (save-restriction | ||
| 899 | (goto-char beg) | ||
| 900 | (narrow-to-region beg end) | ||
| 901 | (if (listp ind) (setq ind (nth 1 ind))) | ||
| 902 | (while (not (eobp)) | ||
| 903 | (condition-case nil | ||
| 904 | (octave-indent-line ind) | ||
| 905 | (error nil)) | ||
| 906 | (if (and (> ind 0) | ||
| 907 | (not | ||
| 908 | (save-excursion | ||
| 909 | (beginning-of-line) | ||
| 910 | (looking-at "^\\s-*\\($\\|\\s<+\\)")))) | ||
| 911 | (setq ind 0)) | ||
| 912 | (move-to-column cfc) | ||
| 913 | ;; First check whether we need to combine non-empty comment lines | ||
| 914 | (if (and (< (current-column) cfc) | ||
| 915 | (octave-in-comment-p) | ||
| 916 | (not (save-excursion | ||
| 917 | (beginning-of-line) | ||
| 918 | (looking-at "^\\s-*\\s<+\\s-*$")))) | ||
| 919 | ;; This is a nonempty comment line which does not extend | ||
| 920 | ;; past the fill column. If it is followed by an nonempty | ||
| 921 | ;; comment line with the same comment prefix, try to | ||
| 922 | ;; combine them, and repeat this until either we reach the | ||
| 923 | ;; fill-column or there is nothing more to combine. | ||
| 924 | (progn | ||
| 925 | ;; Get the comment prefix | ||
| 926 | (save-excursion | ||
| 927 | (beginning-of-line) | ||
| 928 | (while (and (re-search-forward "\\s<+") | ||
| 929 | (not (octave-in-comment-p)))) | ||
| 930 | (setq comment-prefix (match-string 0))) | ||
| 931 | ;; And keep combining ... | ||
| 932 | (while (and (< (current-column) cfc) | ||
| 933 | (save-excursion | ||
| 934 | (forward-line 1) | ||
| 935 | (and (looking-at | ||
| 936 | (concat "^\\s-*" | ||
| 937 | comment-prefix | ||
| 938 | "\\S<")) | ||
| 939 | (not (looking-at | ||
| 940 | (concat "^\\s-*" | ||
| 941 | comment-prefix | ||
| 942 | "\\s-*$")))))) | ||
| 943 | (delete-char 1) | ||
| 944 | (re-search-forward comment-prefix) | ||
| 945 | (delete-region (match-beginning 0) (match-end 0)) | ||
| 946 | (fixup-whitespace) | ||
| 947 | (move-to-column cfc)))) | ||
| 948 | (skip-chars-forward "^ \t\n") | ||
| 949 | (delete-horizontal-space) | ||
| 950 | (if (or (< (current-column) cfc) | ||
| 951 | (and (= (current-column) cfc) (eolp))) | ||
| 952 | (forward-line 1) | ||
| 953 | (if (not (eolp)) (insert " ")) | ||
| 954 | (octave-auto-fill)))) | ||
| 955 | t))) | ||
| 956 | |||
| 957 | |||
| 958 | ;;; Completions | ||
| 959 | (defun octave-initialize-completions () | ||
| 960 | "Create an alist for Octave completions." | ||
| 961 | (if octave-completion-alist | ||
| 962 | () | ||
| 963 | (setq octave-completion-alist | ||
| 964 | (mapcar '(lambda (var) (cons var var)) | ||
| 965 | (append octave-reserved-words | ||
| 966 | octave-text-functions | ||
| 967 | octave-variables))))) | ||
| 968 | |||
| 969 | (defun octave-complete-symbol () | ||
| 970 | "Perform completion on Octave symbol preceding point. | ||
| 971 | Compare that symbol against Octave's reserved words and builtin | ||
| 972 | variables." | ||
| 973 | ;; This code taken from lisp-complete-symbol | ||
| 974 | (interactive) | ||
| 975 | (let* ((end (point)) | ||
| 976 | (beg (save-excursion (backward-sexp 1) (point))) | ||
| 977 | (string (buffer-substring-no-properties beg end)) | ||
| 978 | (completion (try-completion string octave-completion-alist))) | ||
| 979 | (cond ((eq completion t)) ; ??? | ||
| 980 | ((null completion) | ||
| 981 | (message "Can't find completion for \"%s\"" string) | ||
| 982 | (ding)) | ||
| 983 | ((not (string= string completion)) | ||
| 984 | (delete-region beg end) | ||
| 985 | (insert completion)) | ||
| 986 | (t | ||
| 987 | (let ((list (all-completions string octave-completion-alist)) | ||
| 988 | (conf (current-window-configuration))) | ||
| 989 | ;; Taken from comint.el | ||
| 990 | (message "Making completion list...") | ||
| 991 | (with-output-to-temp-buffer "*Completions*" | ||
| 992 | (display-completion-list list)) | ||
| 993 | (message "Hit space to flush") | ||
| 994 | (let (key first) | ||
| 995 | (if (save-excursion | ||
| 996 | (set-buffer (get-buffer "*Completions*")) | ||
| 997 | (setq key (read-key-sequence nil) | ||
| 998 | first (aref key 0)) | ||
| 999 | (and (consp first) (consp (event-start first)) | ||
| 1000 | (eq (window-buffer (posn-window (event-start | ||
| 1001 | first))) | ||
| 1002 | (get-buffer "*Completions*")) | ||
| 1003 | (eq (key-binding key) 'mouse-choose-completion))) | ||
| 1004 | (progn | ||
| 1005 | (mouse-choose-completion first) | ||
| 1006 | (set-window-configuration conf)) | ||
| 1007 | (if (eq first ?\ ) | ||
| 1008 | (set-window-configuration conf) | ||
| 1009 | (setq unread-command-events | ||
| 1010 | (listify-key-sequence key)))))))))) | ||
| 1011 | |||
| 1012 | |||
| 1013 | ;;; Electric characters && friends | ||
| 1014 | (defun octave-reindent-then-newline-and-indent () | ||
| 1015 | "Reindent current Octave line, insert newline, and indent the new line. | ||
| 1016 | If Abbrev mode is on, expand abbrevs first." | ||
| 1017 | (interactive) | ||
| 1018 | (if abbrev-mode (expand-abbrev)) | ||
| 1019 | (if octave-blink-matching-block | ||
| 1020 | (octave-blink-matching-block-open)) | ||
| 1021 | (save-excursion | ||
| 1022 | (delete-region (point) (progn (skip-chars-backward " \t") (point))) | ||
| 1023 | (indent-according-to-mode)) | ||
| 1024 | (insert "\n") | ||
| 1025 | (indent-according-to-mode)) | ||
| 1026 | |||
| 1027 | (defun octave-electric-semi () | ||
| 1028 | "Insert a semicolon in Octave mode. | ||
| 1029 | Always reindent the line. Insert a newline if `octave-auto-newline' is | ||
| 1030 | non-nil." | ||
| 1031 | (interactive) | ||
| 1032 | (if (not (octave-not-in-string-or-comment-p)) | ||
| 1033 | (insert ";") | ||
| 1034 | (if abbrev-mode (expand-abbrev)) | ||
| 1035 | (if octave-blink-matching-block | ||
| 1036 | (octave-blink-matching-block-open)) | ||
| 1037 | (indent-according-to-mode) | ||
| 1038 | (insert ";") | ||
| 1039 | (if octave-auto-newline | ||
| 1040 | (newline-and-indent)))) | ||
| 1041 | |||
| 1042 | (defun octave-electric-space () | ||
| 1043 | "Insert a space in Octave mode. | ||
| 1044 | Maybe expand abbrevs and blink matching block open keywords." | ||
| 1045 | (interactive) | ||
| 1046 | (setq last-command-char ? ) | ||
| 1047 | (if (not (octave-not-in-string-or-comment-p)) | ||
| 1048 | (progn | ||
| 1049 | (indent-according-to-mode) | ||
| 1050 | (self-insert-command 1)) | ||
| 1051 | (if abbrev-mode (expand-abbrev)) | ||
| 1052 | (if octave-blink-matching-block | ||
| 1053 | (octave-blink-matching-block-open)) | ||
| 1054 | (if (save-excursion | ||
| 1055 | (skip-syntax-backward " ") | ||
| 1056 | (not (bolp))) | ||
| 1057 | (indent-according-to-mode)) | ||
| 1058 | (self-insert-command 1))) | ||
| 1059 | |||
| 1060 | (defun octave-abbrev-start () | ||
| 1061 | "Start entering an Octave abbreviation. | ||
| 1062 | If Abbrev mode is turned on, typing ` (grave accent) followed by ? or | ||
| 1063 | \\[help-command] lists all Octave abbrevs. Any other key combination is | ||
| 1064 | executed normally. | ||
| 1065 | Note that all Octave mode abbrevs start with a grave accent." | ||
| 1066 | (interactive) | ||
| 1067 | (if (not abbrev-mode) | ||
| 1068 | (self-insert-command 1) | ||
| 1069 | (let (c) | ||
| 1070 | (insert last-command-char) | ||
| 1071 | (if (or (eq (setq c (read-event)) ??) | ||
| 1072 | (eq c help-char)) | ||
| 1073 | (let ((abbrev-table-name-list '(octave-mode-abbrev-table))) | ||
| 1074 | (list-abbrevs)) | ||
| 1075 | (setq unread-command-events (list c)))))) | ||
| 1076 | |||
| 1077 | (defun octave-insert-defun (name args vals) | ||
| 1078 | "Insert an Octave function skeleton. | ||
| 1079 | Prompt for the function's name, arguments and return values (to be | ||
| 1080 | entered without parens)." | ||
| 1081 | (interactive | ||
| 1082 | (list | ||
| 1083 | (read-from-minibuffer "Function name: " | ||
| 1084 | (substring (buffer-name) 0 -2)) | ||
| 1085 | (read-from-minibuffer "Arguments: ") | ||
| 1086 | (read-from-minibuffer "Return values: "))) | ||
| 1087 | (let ((string (format "%s %s (%s)" | ||
| 1088 | (cond | ||
| 1089 | ((string-equal vals "") | ||
| 1090 | vals) | ||
| 1091 | ((string-match "[ ,]" vals) | ||
| 1092 | (concat " [" vals "] =")) | ||
| 1093 | (t | ||
| 1094 | (concat " " vals " ="))) | ||
| 1095 | name | ||
| 1096 | args)) | ||
| 1097 | (prefix octave-block-comment-start)) | ||
| 1098 | (if (not (bobp)) (newline)) | ||
| 1099 | (insert "function" string) | ||
| 1100 | (indent-according-to-mode) | ||
| 1101 | (newline 2) | ||
| 1102 | (insert prefix "usage: " string) | ||
| 1103 | (reindent-then-newline-and-indent) | ||
| 1104 | (insert prefix) | ||
| 1105 | (reindent-then-newline-and-indent) | ||
| 1106 | (insert prefix) | ||
| 1107 | (indent-according-to-mode) | ||
| 1108 | (save-excursion | ||
| 1109 | (newline 2) | ||
| 1110 | (insert "endfunction") | ||
| 1111 | (indent-according-to-mode)))) | ||
| 1112 | |||
| 1113 | |||
| 1114 | ;;; Menu | ||
| 1115 | (defun octave-add-octave-menu () | ||
| 1116 | "Adds the `Octave' menu to the menu bar in Octave mode." | ||
| 1117 | (require 'easymenu) | ||
| 1118 | (easy-menu-define octave-mode-menu-map octave-mode-map | ||
| 1119 | "Menu keymap for Octave mode." octave-mode-menu) | ||
| 1120 | (easy-menu-add octave-mode-menu-map octave-mode-map)) | ||
| 1121 | |||
| 1122 | |||
| 1123 | ;;; Communication with the inferior Octave process | ||
| 1124 | (defun octave-kill-process () | ||
| 1125 | "Kill inferior Octave process and its buffer." | ||
| 1126 | (interactive) | ||
| 1127 | (if inferior-octave-process | ||
| 1128 | (progn | ||
| 1129 | (process-send-string inferior-octave-process "quit;\n") | ||
| 1130 | (accept-process-output inferior-octave-process))) | ||
| 1131 | (if inferior-octave-buffer | ||
| 1132 | (kill-buffer inferior-octave-buffer))) | ||
| 1133 | |||
| 1134 | (defun octave-show-process-buffer () | ||
| 1135 | "Make sure that `inferior-octave-buffer' is displayed." | ||
| 1136 | (interactive) | ||
| 1137 | (if (get-buffer inferior-octave-buffer) | ||
| 1138 | (display-buffer inferior-octave-buffer) | ||
| 1139 | (message "No buffer named %s" inferior-octave-buffer))) | ||
| 1140 | |||
| 1141 | (defun octave-hide-process-buffer () | ||
| 1142 | "Delete all windows that display `inferior-octave-buffer'." | ||
| 1143 | (interactive) | ||
| 1144 | (if (get-buffer inferior-octave-buffer) | ||
| 1145 | (delete-windows-on inferior-octave-buffer) | ||
| 1146 | (message "No buffer named %s" inferior-octave-buffer))) | ||
| 1147 | |||
| 1148 | (defun octave-send-region (beg end) | ||
| 1149 | "Send current region to the inferior Octave process." | ||
| 1150 | (interactive "r") | ||
| 1151 | (inferior-octave t) | ||
| 1152 | (let ((proc inferior-octave-process) | ||
| 1153 | (string (buffer-substring-no-properties beg end)) | ||
| 1154 | line) | ||
| 1155 | (save-excursion | ||
| 1156 | (set-buffer inferior-octave-buffer) | ||
| 1157 | (setq inferior-octave-output-list nil) | ||
| 1158 | (while (not (string-equal string "")) | ||
| 1159 | (if (string-match "\n" string) | ||
| 1160 | (setq line (substring string 0 (match-beginning 0)) | ||
| 1161 | string (substring string (match-end 0))) | ||
| 1162 | (setq line string string "")) | ||
| 1163 | (setq inferior-octave-receive-in-progress t) | ||
| 1164 | (inferior-octave-send-list-and-digest (list (concat line "\n"))) | ||
| 1165 | (while inferior-octave-receive-in-progress | ||
| 1166 | (accept-process-output proc)) | ||
| 1167 | (insert-before-markers | ||
| 1168 | (mapconcat 'identity | ||
| 1169 | (append | ||
| 1170 | (if octave-send-echo-input (list line) (list "")) | ||
| 1171 | (mapcar 'inferior-octave-strip-ctrl-g | ||
| 1172 | inferior-octave-output-list) | ||
| 1173 | (list inferior-octave-output-string)) | ||
| 1174 | "\n"))))) | ||
| 1175 | (if octave-send-show-buffer | ||
| 1176 | (display-buffer inferior-octave-buffer))) | ||
| 1177 | |||
| 1178 | (defun octave-send-block () | ||
| 1179 | "Send current Octave block to the inferior Octave process." | ||
| 1180 | (interactive) | ||
| 1181 | (save-excursion | ||
| 1182 | (octave-mark-block) | ||
| 1183 | (octave-send-region (point) (mark)))) | ||
| 1184 | |||
| 1185 | (defun octave-send-defun () | ||
| 1186 | "Send current Octave function to the inferior Octave process." | ||
| 1187 | (interactive) | ||
| 1188 | (save-excursion | ||
| 1189 | (octave-mark-defun) | ||
| 1190 | (octave-send-region (point) (mark)))) | ||
| 1191 | |||
| 1192 | (defun octave-send-line (&optional arg) | ||
| 1193 | "Send current Octave code line to the inferior Octave process. | ||
| 1194 | With positive prefix ARG, send that many lines. | ||
| 1195 | If `octave-send-line-auto-forward' is non-nil, go to the next unsent | ||
| 1196 | code line." | ||
| 1197 | (interactive "P") | ||
| 1198 | (or arg (setq arg 1)) | ||
| 1199 | (if (> arg 0) | ||
| 1200 | (let (beg end) | ||
| 1201 | (beginning-of-line) | ||
| 1202 | (setq beg (point)) | ||
| 1203 | (octave-next-code-line (- arg 1)) | ||
| 1204 | (end-of-line) | ||
| 1205 | (setq end (point)) | ||
| 1206 | (if octave-send-line-auto-forward | ||
| 1207 | (octave-next-code-line 1)) | ||
| 1208 | (octave-send-region beg end)))) | ||
| 1209 | |||
| 1210 | (defun octave-eval-print-last-sexp () | ||
| 1211 | "Evaluate Octave sexp before point and print value into current buffer." | ||
| 1212 | (interactive) | ||
| 1213 | (inferior-octave t) | ||
| 1214 | (let ((standard-output (current-buffer)) | ||
| 1215 | (print-escape-newlines nil) | ||
| 1216 | (opoint (point))) | ||
| 1217 | (terpri) | ||
| 1218 | (prin1 | ||
| 1219 | (save-excursion | ||
| 1220 | (forward-sexp -1) | ||
| 1221 | (inferior-octave-send-list-and-digest | ||
| 1222 | (list (concat (buffer-substring-no-properties (point) opoint) | ||
| 1223 | "\n"))) | ||
| 1224 | (mapconcat 'identity inferior-octave-output-list "\n"))) | ||
| 1225 | (terpri))) | ||
| 1226 | |||
| 1227 | ;;; octave-mod.el ends here \ No newline at end of file | ||