2013-04-26 04:16:37 +00:00
|
|
|
|
;;; octave.el --- editing octave source files under emacs -*- lexical-binding: t; -*-
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-01-01 09:11:05 +00:00
|
|
|
|
;; Copyright (C) 1997, 2001-2013 Free Software Foundation, Inc.
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2005-08-26 13:41:26 +00:00
|
|
|
|
;; Author: Kurt Hornik <Kurt.Hornik@wu-wien.ac.at>
|
2012-02-20 20:24:24 +00:00
|
|
|
|
;; John Eaton <jwe@octave.org>
|
2011-10-26 01:18:13 +00:00
|
|
|
|
;; Maintainer: FSF
|
1997-01-21 00:29:57 +00:00
|
|
|
|
;; Keywords: languages
|
|
|
|
|
|
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
|
|
2008-05-06 07:25:26 +00:00
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
1997-01-21 00:29:57 +00:00
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
2008-05-06 07:25:26 +00:00
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
;; (at your option) any later version.
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
2008-05-06 07:25:26 +00:00
|
|
|
|
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
2013-05-05 15:29:51 +00:00
|
|
|
|
;; This package provides emacs support for Octave. It defines a major
|
|
|
|
|
;; mode for editing Octave code and contains code for interacting with
|
|
|
|
|
;; an inferior Octave process using comint.
|
1997-01-21 00:40:19 +00:00
|
|
|
|
|
2013-04-25 14:51:08 +00:00
|
|
|
|
;; See the documentation of `octave-mode' and `run-octave' for further
|
|
|
|
|
;; information on usage and customization.
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
1997-01-21 00:40:19 +00:00
|
|
|
|
;;; Code:
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(require 'comint)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-05-01 17:25:03 +00:00
|
|
|
|
;;; For emacs < 24.3.
|
|
|
|
|
(require 'newcomment)
|
2013-05-03 07:52:17 +00:00
|
|
|
|
(eval-and-compile
|
|
|
|
|
(unless (fboundp 'user-error)
|
2013-05-17 02:43:41 +00:00
|
|
|
|
(defalias 'user-error 'error))
|
|
|
|
|
(unless (fboundp 'delete-consecutive-dups)
|
|
|
|
|
(defalias 'delete-consecutive-dups 'delete-dups)))
|
2013-05-01 17:25:03 +00:00
|
|
|
|
(eval-when-compile
|
|
|
|
|
(unless (fboundp 'setq-local)
|
|
|
|
|
(defmacro setq-local (var val)
|
|
|
|
|
"Set variable VAR to value VAL in current buffer."
|
|
|
|
|
(list 'set (list 'make-local-variable (list 'quote var)) val))))
|
|
|
|
|
|
1998-01-26 11:29:46 +00:00
|
|
|
|
(defgroup octave nil
|
2013-04-25 14:51:08 +00:00
|
|
|
|
"Editing Octave code."
|
2005-11-17 07:40:11 +00:00
|
|
|
|
:link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
|
1998-01-26 11:29:46 +00:00
|
|
|
|
:group 'languages)
|
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(define-obsolete-function-alias 'octave-submit-bug-report
|
|
|
|
|
'report-emacs-bug "24.4")
|
1997-01-21 04:43:45 +00:00
|
|
|
|
|
2013-05-01 06:13:20 +00:00
|
|
|
|
(define-abbrev-table 'octave-abbrev-table nil
|
1997-01-21 04:43:45 +00:00
|
|
|
|
"Abbrev table for Octave's reserved words.
|
2013-05-01 06:13:20 +00:00
|
|
|
|
Used in `octave-mode' and `inferior-octave-mode' buffers.")
|
1997-01-21 04:43:45 +00:00
|
|
|
|
|
|
|
|
|
(defvar octave-comment-char ?#
|
|
|
|
|
"Character to start an Octave comment.")
|
2013-05-01 06:13:20 +00:00
|
|
|
|
|
2013-05-17 22:46:10 +00:00
|
|
|
|
(defvar octave-comment-start (char-to-string octave-comment-char)
|
|
|
|
|
"Octave-specific `comment-start' (which see).")
|
2013-05-01 06:13:20 +00:00
|
|
|
|
|
2013-05-17 22:46:10 +00:00
|
|
|
|
(defvar octave-comment-start-skip "\\(^\\|\\S<\\)\\(?:%!\\|\\s<+\\)\\s-*"
|
|
|
|
|
"Octave-specific `comment-start-skip' (which see).")
|
1997-01-21 04:43:45 +00:00
|
|
|
|
|
|
|
|
|
(defvar octave-begin-keywords
|
2013-05-11 07:39:59 +00:00
|
|
|
|
'("classdef" "do" "enumeration" "events" "for" "function" "if" "methods"
|
|
|
|
|
"parfor" "properties" "switch" "try" "unwind_protect" "while"))
|
2013-05-01 06:13:20 +00:00
|
|
|
|
|
1997-01-21 04:43:45 +00:00
|
|
|
|
(defvar octave-else-keywords
|
1997-03-12 00:35:32 +00:00
|
|
|
|
'("case" "catch" "else" "elseif" "otherwise" "unwind_protect_cleanup"))
|
2013-05-01 06:13:20 +00:00
|
|
|
|
|
1997-01-21 04:43:45 +00:00
|
|
|
|
(defvar octave-end-keywords
|
2013-05-11 07:39:59 +00:00
|
|
|
|
'("endclassdef" "endenumeration" "endevents" "endfor" "endfunction" "endif"
|
|
|
|
|
"endmethods" "endparfor" "endproperties" "endswitch" "end_try_catch"
|
2010-01-02 19:40:59 +00:00
|
|
|
|
"end_unwind_protect" "endwhile" "until" "end"))
|
1997-01-21 04:43:45 +00:00
|
|
|
|
|
|
|
|
|
(defvar octave-reserved-words
|
1997-03-12 00:35:32 +00:00
|
|
|
|
(append octave-begin-keywords
|
|
|
|
|
octave-else-keywords
|
|
|
|
|
octave-end-keywords
|
2013-05-11 07:39:59 +00:00
|
|
|
|
'("break" "continue" "global" "persistent" "return"))
|
1997-01-21 04:43:45 +00:00
|
|
|
|
"Reserved words in Octave.")
|
|
|
|
|
|
|
|
|
|
(defvar octave-function-header-regexp
|
2011-04-25 16:29:31 +00:00
|
|
|
|
(concat "^\\s-*\\_<\\(function\\)\\_>"
|
2013-06-07 13:00:47 +00:00
|
|
|
|
"\\([^=;(\n]*=[ \t]*\\|[ \t]*\\)\\(\\(?:\\w\\|\\s_\\)+\\)\\_>")
|
1997-01-21 04:43:45 +00:00
|
|
|
|
"Regexp to match an Octave function header.
|
|
|
|
|
The string `function' and its name are given by the first and third
|
|
|
|
|
parenthetical grouping.")
|
|
|
|
|
|
|
|
|
|
|
2007-09-19 14:47:51 +00:00
|
|
|
|
(defvar octave-mode-map
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(let ((map (make-sparse-keymap)))
|
2013-05-13 01:36:42 +00:00
|
|
|
|
(define-key map "\M-." 'octave-find-definition)
|
|
|
|
|
(define-key map "\M-\C-j" 'octave-indent-new-comment-line)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(define-key map "\C-c\C-p" 'octave-previous-code-line)
|
|
|
|
|
(define-key map "\C-c\C-n" 'octave-next-code-line)
|
|
|
|
|
(define-key map "\C-c\C-a" 'octave-beginning-of-line)
|
2003-02-04 13:24:35 +00:00
|
|
|
|
(define-key map "\C-c\C-e" 'octave-end-of-line)
|
Remove old indentation and navigation code on octave-mode.
* lisp/progmodes/octave-mod.el (octave-mode-map): Remap down-list to
smie-down-list rather than add a binding for octave-down-block.
(octave-mark-block, octave-blink-matching-block-open):
Rely on forward-sexp-function.
(octave-fill-paragraph): Don't narrow, so you can use
indent-according-to-mode.
(octave-block-begin-regexp, octave-block-begin-or-end-regexp): Remove.
(octave-in-block-p, octave-re-search-forward-kw)
(octave-re-search-backward-kw, octave-indent-calculate)
(octave-end-as-array-index-p, octave-block-end-offset)
(octave-scan-blocks, octave-forward-block, octave-backward-block)
(octave-down-block, octave-backward-up-block, octave-up-block)
(octave-before-magic-comment-p, octave-indent-line): Remove.
2010-08-31 12:13:51 +00:00
|
|
|
|
(define-key map [remap down-list] 'smie-down-list)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(define-key map "\C-c\M-\C-h" 'octave-mark-block)
|
2010-08-30 20:34:52 +00:00
|
|
|
|
(define-key map "\C-c]" 'smie-close-block)
|
|
|
|
|
(define-key map "\C-c/" 'smie-close-block)
|
2013-04-27 17:07:01 +00:00
|
|
|
|
(define-key map "\C-c;" 'octave-update-function-file-comment)
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(define-key map "\C-hd" 'octave-help)
|
2003-01-20 08:59:40 +00:00
|
|
|
|
(define-key map "\C-c\C-f" 'octave-insert-defun)
|
|
|
|
|
(define-key map "\C-c\C-il" 'octave-send-line)
|
|
|
|
|
(define-key map "\C-c\C-ib" 'octave-send-block)
|
|
|
|
|
(define-key map "\C-c\C-if" 'octave-send-defun)
|
2003-02-04 13:24:35 +00:00
|
|
|
|
(define-key map "\C-c\C-ir" 'octave-send-region)
|
2003-01-20 08:59:40 +00:00
|
|
|
|
(define-key map "\C-c\C-is" 'octave-show-process-buffer)
|
2013-04-17 01:49:22 +00:00
|
|
|
|
(define-key map "\C-c\C-iq" 'octave-hide-process-buffer)
|
2003-01-20 08:59:40 +00:00
|
|
|
|
(define-key map "\C-c\C-ik" 'octave-kill-process)
|
|
|
|
|
(define-key map "\C-c\C-i\C-l" 'octave-send-line)
|
|
|
|
|
(define-key map "\C-c\C-i\C-b" 'octave-send-block)
|
|
|
|
|
(define-key map "\C-c\C-i\C-f" 'octave-send-defun)
|
2003-02-04 13:24:35 +00:00
|
|
|
|
(define-key map "\C-c\C-i\C-r" 'octave-send-region)
|
2003-01-20 08:59:40 +00:00
|
|
|
|
(define-key map "\C-c\C-i\C-s" 'octave-show-process-buffer)
|
2013-04-17 01:46:26 +00:00
|
|
|
|
(define-key map "\C-c\C-i\C-q" 'octave-hide-process-buffer)
|
2003-01-20 08:59:40 +00:00
|
|
|
|
(define-key map "\C-c\C-i\C-k" 'octave-kill-process)
|
2007-09-19 14:47:51 +00:00
|
|
|
|
map)
|
|
|
|
|
"Keymap used in Octave mode.")
|
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2010-08-17 15:49:30 +00:00
|
|
|
|
|
|
|
|
|
(easy-menu-define octave-mode-menu octave-mode-map
|
|
|
|
|
"Menu for Octave mode."
|
2007-09-19 14:47:51 +00:00
|
|
|
|
'("Octave"
|
2013-05-21 23:05:16 +00:00
|
|
|
|
["Split Line at Point" octave-indent-new-comment-line t]
|
|
|
|
|
["Previous Code Line" octave-previous-code-line t]
|
|
|
|
|
["Next Code Line" octave-next-code-line t]
|
|
|
|
|
["Begin of Line" octave-beginning-of-line t]
|
|
|
|
|
["End of Line" octave-end-of-line t]
|
|
|
|
|
["Mark Block" octave-mark-block t]
|
|
|
|
|
["Close Block" smie-close-block t]
|
|
|
|
|
"---"
|
|
|
|
|
["Start Octave Process" run-octave t]
|
2013-05-21 23:19:03 +00:00
|
|
|
|
["Documentation Lookup" info-lookup-symbol t]
|
2013-05-21 23:05:16 +00:00
|
|
|
|
["Help on Function" octave-help t]
|
|
|
|
|
["Find Function Definition" octave-find-definition t]
|
|
|
|
|
["Insert Function" octave-insert-defun t]
|
|
|
|
|
["Update Function File Comment" octave-update-function-file-comment t]
|
|
|
|
|
"---"
|
|
|
|
|
["Function Syntax Hints" (call-interactively
|
|
|
|
|
(if (fboundp 'eldoc-post-insert-mode)
|
|
|
|
|
'eldoc-post-insert-mode
|
|
|
|
|
'eldoc-mode))
|
|
|
|
|
:style toggle :selected (or eldoc-post-insert-mode eldoc-mode)
|
|
|
|
|
:help "Display function signatures after typing `SPC' or `('"]
|
2013-06-05 07:40:02 +00:00
|
|
|
|
["Delimiter Matching" show-paren-mode
|
|
|
|
|
:style toggle :selected show-paren-mode
|
2013-05-21 23:05:16 +00:00
|
|
|
|
:help "Highlight matched pairs such as `if ... end'"
|
2013-06-05 07:40:02 +00:00
|
|
|
|
:visible (fboundp 'smie--matching-block-data)]
|
2013-05-21 23:05:16 +00:00
|
|
|
|
["Auto Fill" auto-fill-mode
|
|
|
|
|
:style toggle :selected auto-fill-function
|
|
|
|
|
:help "Automatic line breaking"]
|
|
|
|
|
["Electric Layout" electric-layout-mode
|
|
|
|
|
:style toggle :selected electric-layout-mode
|
|
|
|
|
:help "Automatically insert newlines around some chars"]
|
|
|
|
|
"---"
|
2008-09-25 22:10:31 +00:00
|
|
|
|
("Debug"
|
2013-05-21 23:05:16 +00:00
|
|
|
|
["Send Current Line" octave-send-line t]
|
|
|
|
|
["Send Current Block" octave-send-block t]
|
|
|
|
|
["Send Current Function" octave-send-defun t]
|
|
|
|
|
["Send Region" octave-send-region t]
|
|
|
|
|
["Show Process Buffer" octave-show-process-buffer t]
|
|
|
|
|
["Hide Process Buffer" octave-hide-process-buffer t]
|
|
|
|
|
["Kill Process" octave-kill-process t])
|
|
|
|
|
"---"
|
|
|
|
|
["Customize Octave" (customize-group 'octave) t]
|
|
|
|
|
["Submit Bug Report" report-emacs-bug t]))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2003-10-24 18:58:28 +00:00
|
|
|
|
(defvar octave-mode-syntax-table
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(let ((table (make-syntax-table)))
|
|
|
|
|
(modify-syntax-entry ?\r " " table)
|
|
|
|
|
(modify-syntax-entry ?+ "." table)
|
|
|
|
|
(modify-syntax-entry ?- "." table)
|
|
|
|
|
(modify-syntax-entry ?= "." table)
|
|
|
|
|
(modify-syntax-entry ?* "." table)
|
|
|
|
|
(modify-syntax-entry ?/ "." table)
|
|
|
|
|
(modify-syntax-entry ?> "." table)
|
|
|
|
|
(modify-syntax-entry ?< "." table)
|
|
|
|
|
(modify-syntax-entry ?& "." table)
|
|
|
|
|
(modify-syntax-entry ?| "." table)
|
|
|
|
|
(modify-syntax-entry ?! "." table)
|
2013-05-02 23:03:00 +00:00
|
|
|
|
(modify-syntax-entry ?\\ "." table)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(modify-syntax-entry ?\' "." table)
|
2008-05-02 18:32:18 +00:00
|
|
|
|
(modify-syntax-entry ?\` "." table)
|
2013-06-01 03:38:36 +00:00
|
|
|
|
(modify-syntax-entry ?. "." table)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(modify-syntax-entry ?\" "\"" table)
|
2011-04-25 16:29:31 +00:00
|
|
|
|
(modify-syntax-entry ?_ "_" table)
|
2010-08-12 14:44:16 +00:00
|
|
|
|
;; The "b" flag only applies to the second letter of the comstart
|
2010-08-12 12:46:24 +00:00
|
|
|
|
;; and the first letter of the comend, i.e. the "4b" below is ineffective.
|
|
|
|
|
;; If we try to put `b' on the single-line comments, we get a similar
|
|
|
|
|
;; problem where the % and # chars appear as first chars of the 2-char
|
|
|
|
|
;; comend, so the multi-line ender is also turned into style-b.
|
2010-08-12 14:44:16 +00:00
|
|
|
|
;; So we need the new "c" comment style.
|
2010-08-12 11:22:16 +00:00
|
|
|
|
(modify-syntax-entry ?\% "< 13" table)
|
|
|
|
|
(modify-syntax-entry ?\# "< 13" table)
|
2010-08-12 14:44:16 +00:00
|
|
|
|
(modify-syntax-entry ?\{ "(} 2c" table)
|
|
|
|
|
(modify-syntax-entry ?\} "){ 4c" table)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(modify-syntax-entry ?\n ">" table)
|
2003-10-24 18:58:28 +00:00
|
|
|
|
table)
|
|
|
|
|
"Syntax table in use in `octave-mode' buffers.")
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-04-30 14:23:03 +00:00
|
|
|
|
(defcustom octave-font-lock-texinfo-comment t
|
|
|
|
|
"Control whether to highlight the texinfo comment block."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'octave
|
|
|
|
|
:version "24.4")
|
|
|
|
|
|
1998-01-26 11:29:46 +00:00
|
|
|
|
(defcustom octave-blink-matching-block t
|
2007-09-19 14:47:51 +00:00
|
|
|
|
"Control the blinking of matching Octave block keywords.
|
1997-01-21 00:29:57 +00:00
|
|
|
|
Non-nil means show matching begin of block when inserting a space,
|
1998-01-26 11:29:46 +00:00
|
|
|
|
newline or semicolon after an else or end keyword."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'octave)
|
2010-08-17 15:49:30 +00:00
|
|
|
|
|
1998-01-26 11:29:46 +00:00
|
|
|
|
(defcustom octave-block-offset 2
|
2007-09-19 14:47:51 +00:00
|
|
|
|
"Extra indentation applied to statements in Octave block structures."
|
1998-01-26 11:29:46 +00:00
|
|
|
|
:type 'integer
|
|
|
|
|
:group 'octave)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
(defvar octave-block-comment-start
|
|
|
|
|
(concat (make-string 2 octave-comment-char) " ")
|
|
|
|
|
"String to insert to start a new Octave comment on an empty line.")
|
|
|
|
|
|
1998-01-26 11:29:46 +00:00
|
|
|
|
(defcustom octave-continuation-offset 4
|
2007-09-19 14:47:51 +00:00
|
|
|
|
"Extra indentation applied to Octave continuation lines."
|
1998-01-26 11:29:46 +00:00
|
|
|
|
:type 'integer
|
|
|
|
|
:group 'octave)
|
2013-04-29 20:09:18 +00:00
|
|
|
|
|
2010-08-30 20:34:52 +00:00
|
|
|
|
(eval-and-compile
|
|
|
|
|
(defconst octave-continuation-marker-regexp "\\\\\\|\\.\\.\\."))
|
2013-04-29 20:09:18 +00:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(defvar octave-continuation-regexp
|
2010-08-30 20:34:52 +00:00
|
|
|
|
(concat "[^#%\n]*\\(" octave-continuation-marker-regexp
|
|
|
|
|
"\\)\\s-*\\(\\s<.*\\)?$"))
|
2013-04-29 20:09:18 +00:00
|
|
|
|
|
|
|
|
|
;; Char \ is considered a bad decision for continuing a line.
|
|
|
|
|
(defconst octave-continuation-string "..."
|
|
|
|
|
"Character string used for Octave continuation lines.")
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
(defvar octave-mode-imenu-generic-expression
|
|
|
|
|
(list
|
|
|
|
|
;; Functions
|
|
|
|
|
(list nil octave-function-header-regexp 3))
|
|
|
|
|
"Imenu expression for Octave mode. See `imenu-generic-expression'.")
|
|
|
|
|
|
1998-01-26 11:29:46 +00:00
|
|
|
|
(defcustom octave-mode-hook nil
|
2007-09-19 14:47:51 +00:00
|
|
|
|
"Hook to be run when Octave mode is started."
|
1998-01-26 11:29:46 +00:00
|
|
|
|
:type 'hook
|
|
|
|
|
:group 'octave)
|
|
|
|
|
|
|
|
|
|
(defcustom octave-send-show-buffer t
|
2007-09-19 14:47:51 +00:00
|
|
|
|
"Non-nil means display `inferior-octave-buffer' after sending to it."
|
1998-01-26 11:29:46 +00:00
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'octave)
|
2013-05-01 06:13:20 +00:00
|
|
|
|
|
1998-01-26 11:29:46 +00:00
|
|
|
|
(defcustom octave-send-line-auto-forward t
|
2007-09-19 14:47:51 +00:00
|
|
|
|
"Control auto-forward after sending to the inferior Octave process.
|
1998-01-26 11:29:46 +00:00
|
|
|
|
Non-nil means always go to the next Octave code line after sending."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'octave)
|
2013-05-01 06:13:20 +00:00
|
|
|
|
|
1998-01-26 11:29:46 +00:00
|
|
|
|
(defcustom octave-send-echo-input t
|
2007-09-19 14:47:51 +00:00
|
|
|
|
"Non-nil means echo input sent to the inferior Octave process."
|
1998-01-26 11:29:46 +00:00
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'octave)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
|
2010-08-30 20:34:52 +00:00
|
|
|
|
;;; SMIE indentation
|
|
|
|
|
|
|
|
|
|
(require 'smie)
|
|
|
|
|
|
2013-05-06 23:46:07 +00:00
|
|
|
|
;; Use '__operators__' in Octave REPL to get a full list.
|
2010-08-30 20:34:52 +00:00
|
|
|
|
(defconst octave-operator-table
|
|
|
|
|
'((assoc ";" "\n") (assoc ",") ; The doc claims they have equal precedence!?
|
|
|
|
|
(right "=" "+=" "-=" "*=" "/=")
|
|
|
|
|
(assoc "&&") (assoc "||") ; The doc claims they have equal precedence!?
|
|
|
|
|
(assoc "&") (assoc "|") ; The doc claims they have equal precedence!?
|
|
|
|
|
(nonassoc "<" "<=" "==" ">=" ">" "!=" "~=")
|
|
|
|
|
(nonassoc ":") ;No idea what this is.
|
|
|
|
|
(assoc "+" "-")
|
|
|
|
|
(assoc "*" "/" "\\" ".\\" ".*" "./")
|
|
|
|
|
(nonassoc "'" ".'")
|
|
|
|
|
(nonassoc "++" "--" "!" "~") ;And unary "+" and "-".
|
|
|
|
|
(right "^" "**" ".^" ".**")
|
|
|
|
|
;; It's not really an operator, but for indentation purposes it
|
|
|
|
|
;; could be convenient to treat it as one.
|
|
|
|
|
(assoc "...")))
|
|
|
|
|
|
2010-09-03 13:28:09 +00:00
|
|
|
|
(defconst octave-smie-bnf-table
|
|
|
|
|
'((atom)
|
|
|
|
|
;; We can't distinguish the first element in a sequence with
|
|
|
|
|
;; precedence grammars, so we can't distinguish the condition
|
|
|
|
|
;; if the `if' from the subsequent body, for example.
|
|
|
|
|
;; This has to be done later in the indentation rules.
|
|
|
|
|
(exp (exp "\n" exp)
|
|
|
|
|
;; We need to mention at least one of the operators in this part
|
|
|
|
|
;; of the grammar: if the BNF and the operator table have
|
|
|
|
|
;; no overlap, SMIE can't know how they relate.
|
|
|
|
|
(exp ";" exp)
|
|
|
|
|
("try" exp "catch" exp "end_try_catch")
|
|
|
|
|
("try" exp "catch" exp "end")
|
|
|
|
|
("unwind_protect" exp
|
|
|
|
|
"unwind_protect_cleanup" exp "end_unwind_protect")
|
|
|
|
|
("unwind_protect" exp "unwind_protect_cleanup" exp "end")
|
|
|
|
|
("for" exp "endfor")
|
|
|
|
|
("for" exp "end")
|
2013-05-11 07:39:59 +00:00
|
|
|
|
("parfor" exp "endparfor")
|
|
|
|
|
("parfor" exp "end")
|
2010-09-03 13:28:09 +00:00
|
|
|
|
("do" exp "until" atom)
|
|
|
|
|
("while" exp "endwhile")
|
|
|
|
|
("while" exp "end")
|
|
|
|
|
("if" exp "endif")
|
|
|
|
|
("if" exp "else" exp "endif")
|
|
|
|
|
("if" exp "elseif" exp "else" exp "endif")
|
|
|
|
|
("if" exp "elseif" exp "elseif" exp "else" exp "endif")
|
|
|
|
|
("if" exp "elseif" exp "elseif" exp "else" exp "end")
|
|
|
|
|
("switch" exp "case" exp "endswitch")
|
|
|
|
|
("switch" exp "case" exp "otherwise" exp "endswitch")
|
|
|
|
|
("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
|
|
|
|
|
("switch" exp "case" exp "case" exp "otherwise" exp "end")
|
|
|
|
|
("function" exp "endfunction")
|
2013-05-11 07:39:59 +00:00
|
|
|
|
("function" exp "end")
|
|
|
|
|
("enumeration" exp "endenumeration")
|
|
|
|
|
("enumeration" exp "end")
|
|
|
|
|
("events" exp "endevents")
|
|
|
|
|
("events" exp "end")
|
|
|
|
|
("methods" exp "endmethods")
|
|
|
|
|
("methods" exp "end")
|
|
|
|
|
("properties" exp "endproperties")
|
|
|
|
|
("properties" exp "end")
|
|
|
|
|
("classdef" exp "endclassdef")
|
|
|
|
|
("classdef" exp "end"))
|
2010-09-03 13:28:09 +00:00
|
|
|
|
;; (fundesc (atom "=" atom))
|
|
|
|
|
))
|
|
|
|
|
|
2010-11-07 15:45:45 +00:00
|
|
|
|
(defconst octave-smie-grammar
|
|
|
|
|
(smie-prec2->grammar
|
2010-08-30 20:34:52 +00:00
|
|
|
|
(smie-merge-prec2s
|
2010-11-07 15:45:45 +00:00
|
|
|
|
(smie-bnf->prec2 octave-smie-bnf-table
|
|
|
|
|
'((assoc "\n" ";")))
|
2010-08-30 20:34:52 +00:00
|
|
|
|
|
2010-11-07 15:45:45 +00:00
|
|
|
|
(smie-precs->prec2 octave-operator-table))))
|
2010-08-30 20:34:52 +00:00
|
|
|
|
|
|
|
|
|
;; Tokenizing needs to be refined so that ";;" is treated as two
|
|
|
|
|
;; tokens and also so as to recognize the \n separator (and
|
|
|
|
|
;; corresponding continuation lines).
|
|
|
|
|
|
|
|
|
|
(defconst octave-operator-regexp
|
|
|
|
|
(regexp-opt (apply 'append (mapcar 'cdr octave-operator-table))))
|
|
|
|
|
|
|
|
|
|
(defun octave-smie-backward-token ()
|
|
|
|
|
(let ((pos (point)))
|
|
|
|
|
(forward-comment (- (point)))
|
|
|
|
|
(cond
|
|
|
|
|
((and (not (eq (char-before) ?\;)) ;Coalesce ";" and "\n".
|
|
|
|
|
(> pos (line-end-position))
|
|
|
|
|
(if (looking-back octave-continuation-marker-regexp (- (point) 3))
|
|
|
|
|
(progn
|
|
|
|
|
(goto-char (match-beginning 0))
|
|
|
|
|
(forward-comment (- (point)))
|
|
|
|
|
nil)
|
|
|
|
|
t)
|
|
|
|
|
;; Ignore it if it's within parentheses.
|
|
|
|
|
(let ((ppss (syntax-ppss)))
|
|
|
|
|
(not (and (nth 1 ppss)
|
|
|
|
|
(eq ?\( (char-after (nth 1 ppss)))))))
|
|
|
|
|
(skip-chars-forward " \t")
|
|
|
|
|
;; Why bother distinguishing \n and ;?
|
|
|
|
|
";") ;;"\n"
|
|
|
|
|
((and (looking-back octave-operator-regexp (- (point) 3) 'greedy)
|
|
|
|
|
;; Don't mistake a string quote for a transpose.
|
|
|
|
|
(not (looking-back "\\s\"" (1- (point)))))
|
|
|
|
|
(goto-char (match-beginning 0))
|
|
|
|
|
(match-string-no-properties 0))
|
|
|
|
|
(t
|
|
|
|
|
(smie-default-backward-token)))))
|
|
|
|
|
|
|
|
|
|
(defun octave-smie-forward-token ()
|
|
|
|
|
(skip-chars-forward " \t")
|
|
|
|
|
(when (looking-at (eval-when-compile
|
|
|
|
|
(concat "\\(" octave-continuation-marker-regexp
|
|
|
|
|
"\\)[ \t]*\\($\\|[%#]\\)")))
|
|
|
|
|
(goto-char (match-end 1))
|
|
|
|
|
(forward-comment 1))
|
|
|
|
|
(cond
|
2013-05-07 04:05:43 +00:00
|
|
|
|
((and (looking-at "[%#\n]")
|
|
|
|
|
(not (or (save-excursion (skip-chars-backward " \t")
|
|
|
|
|
;; Only add implicit ; when needed.
|
2013-05-07 04:53:31 +00:00
|
|
|
|
(or (bolp) (eq (char-before) ?\;)))
|
2013-05-07 04:05:43 +00:00
|
|
|
|
;; Ignore it if it's within parentheses.
|
|
|
|
|
(let ((ppss (syntax-ppss)))
|
|
|
|
|
(and (nth 1 ppss)
|
|
|
|
|
(eq ?\( (char-after (nth 1 ppss))))))))
|
|
|
|
|
(if (eolp) (forward-char 1) (forward-comment 1))
|
2010-08-30 20:34:52 +00:00
|
|
|
|
;; Why bother distinguishing \n and ;?
|
|
|
|
|
";") ;;"\n"
|
2013-05-07 04:05:43 +00:00
|
|
|
|
((progn (forward-comment (point-max)) nil))
|
2010-08-30 20:34:52 +00:00
|
|
|
|
((looking-at ";[ \t]*\\($\\|[%#]\\)")
|
|
|
|
|
;; Combine the ; with the subsequent \n.
|
|
|
|
|
(goto-char (match-beginning 1))
|
|
|
|
|
(forward-comment 1)
|
|
|
|
|
";")
|
|
|
|
|
((and (looking-at octave-operator-regexp)
|
|
|
|
|
;; Don't mistake a string quote for a transpose.
|
|
|
|
|
(not (looking-at "\\s\"")))
|
|
|
|
|
(goto-char (match-end 0))
|
|
|
|
|
(match-string-no-properties 0))
|
|
|
|
|
(t
|
|
|
|
|
(smie-default-forward-token))))
|
|
|
|
|
|
2010-10-29 19:20:28 +00:00
|
|
|
|
(defun octave-smie-rules (kind token)
|
|
|
|
|
(pcase (cons kind token)
|
2010-11-07 15:45:45 +00:00
|
|
|
|
;; We could set smie-indent-basic instead, but that would have two
|
|
|
|
|
;; disadvantages:
|
|
|
|
|
;; - changes to octave-block-offset wouldn't take effect immediately.
|
|
|
|
|
;; - edebug wouldn't show the use of this variable.
|
2010-10-29 19:20:28 +00:00
|
|
|
|
(`(:elem . basic) octave-block-offset)
|
2010-11-07 15:45:45 +00:00
|
|
|
|
;; Since "case" is in the same BNF rules as switch..end, SMIE by default
|
|
|
|
|
;; aligns it with "switch".
|
|
|
|
|
(`(:before . "case") (if (not (smie-rule-sibling-p)) octave-block-offset))
|
2010-10-29 19:20:28 +00:00
|
|
|
|
(`(:after . ";")
|
2013-05-11 07:39:59 +00:00
|
|
|
|
(if (smie-rule-parent-p "classdef" "events" "enumeration" "function" "if"
|
|
|
|
|
"while" "else" "elseif" "for" "parfor"
|
|
|
|
|
"properties" "methods" "otherwise" "case"
|
|
|
|
|
"try" "catch" "unwind_protect"
|
2010-11-07 15:45:45 +00:00
|
|
|
|
"unwind_protect_cleanup")
|
|
|
|
|
(smie-rule-parent octave-block-offset)
|
2010-10-29 19:20:28 +00:00
|
|
|
|
;; For (invalid) code between switch and case.
|
|
|
|
|
;; (if (smie-parent-p "switch") 4)
|
2013-05-24 19:37:55 +00:00
|
|
|
|
nil))))
|
2010-08-30 20:34:52 +00:00
|
|
|
|
|
2013-05-11 06:20:10 +00:00
|
|
|
|
(defun octave-indent-comment ()
|
|
|
|
|
"A function for `smie-indent-functions' (which see)."
|
|
|
|
|
(save-excursion
|
|
|
|
|
(back-to-indentation)
|
2013-05-13 00:07:18 +00:00
|
|
|
|
(cond
|
|
|
|
|
((octave-in-string-or-comment-p) nil)
|
2013-05-29 06:50:48 +00:00
|
|
|
|
((looking-at-p "\\(\\s<\\)\\1\\{2,\\}")
|
2013-05-13 00:07:18 +00:00
|
|
|
|
0)
|
2013-05-13 07:24:22 +00:00
|
|
|
|
;; Exclude %{, %} and %!.
|
|
|
|
|
((and (looking-at-p "\\s<\\(?:[^{}!]\\|$\\)")
|
2013-05-29 06:50:48 +00:00
|
|
|
|
(not (looking-at-p "\\(\\s<\\)\\1")))
|
2013-05-13 00:07:18 +00:00
|
|
|
|
(comment-choose-indent)))))
|
2013-05-11 06:20:10 +00:00
|
|
|
|
|
2013-05-06 23:46:07 +00:00
|
|
|
|
|
|
|
|
|
(defvar octave-font-lock-keywords
|
|
|
|
|
(list
|
|
|
|
|
;; Fontify all builtin keywords.
|
|
|
|
|
(cons (concat "\\_<\\("
|
|
|
|
|
(regexp-opt octave-reserved-words)
|
|
|
|
|
"\\)\\_>")
|
|
|
|
|
'font-lock-keyword-face)
|
|
|
|
|
;; Note: 'end' also serves as the last index in an indexing expression.
|
|
|
|
|
;; Ref: http://www.mathworks.com/help/matlab/ref/end.html
|
|
|
|
|
(list (lambda (limit)
|
|
|
|
|
(while (re-search-forward "\\_<end\\_>" limit 'move)
|
|
|
|
|
(let ((beg (match-beginning 0))
|
|
|
|
|
(end (match-end 0)))
|
|
|
|
|
(unless (octave-in-string-or-comment-p)
|
2013-05-14 05:19:29 +00:00
|
|
|
|
(condition-case nil
|
2013-05-06 23:46:07 +00:00
|
|
|
|
(progn
|
|
|
|
|
(goto-char beg)
|
|
|
|
|
(backward-up-list)
|
|
|
|
|
(when (memq (char-after) '(?\( ?\[ ?\{))
|
2013-05-14 05:19:29 +00:00
|
|
|
|
(put-text-property beg end 'face nil))
|
|
|
|
|
(goto-char end))
|
|
|
|
|
(error (goto-char end))))))
|
2013-05-06 23:46:07 +00:00
|
|
|
|
nil))
|
|
|
|
|
;; Fontify all operators.
|
|
|
|
|
(cons octave-operator-regexp 'font-lock-builtin-face)
|
|
|
|
|
;; Fontify all function declarations.
|
|
|
|
|
(list octave-function-header-regexp
|
|
|
|
|
'(1 font-lock-keyword-face)
|
|
|
|
|
'(3 font-lock-function-name-face nil t)))
|
|
|
|
|
"Additional Octave expressions to highlight.")
|
|
|
|
|
|
|
|
|
|
(defun octave-syntax-propertize-function (start end)
|
|
|
|
|
(goto-char start)
|
|
|
|
|
(octave-syntax-propertize-sqs end)
|
|
|
|
|
(funcall (syntax-propertize-rules
|
|
|
|
|
("\\\\" (0 (when (eq (nth 3 (save-excursion
|
|
|
|
|
(syntax-ppss (match-beginning 0))))
|
|
|
|
|
?\")
|
|
|
|
|
(string-to-syntax "\\"))))
|
|
|
|
|
;; Try to distinguish the string-quotes from the transpose-quotes.
|
|
|
|
|
("\\(?:^\\|[[({,; ]\\)\\('\\)"
|
|
|
|
|
(1 (prog1 "\"'" (octave-syntax-propertize-sqs end)))))
|
|
|
|
|
(point) end))
|
|
|
|
|
|
|
|
|
|
(defun octave-syntax-propertize-sqs (end)
|
|
|
|
|
"Propertize the content/end of single-quote strings."
|
|
|
|
|
(when (eq (nth 3 (syntax-ppss)) ?\')
|
|
|
|
|
;; A '..' string.
|
|
|
|
|
(when (re-search-forward
|
|
|
|
|
"\\(?:\\=\\|[^']\\)\\(?:''\\)*\\('\\)\\($\\|[^']\\)" end 'move)
|
|
|
|
|
(goto-char (match-beginning 2))
|
|
|
|
|
(when (eq (char-before (match-beginning 1)) ?\\)
|
|
|
|
|
;; Backslash cannot escape a single quote.
|
|
|
|
|
(put-text-property (1- (match-beginning 1)) (match-beginning 1)
|
|
|
|
|
'syntax-table (string-to-syntax ".")))
|
|
|
|
|
(put-text-property (match-beginning 1) (match-end 1)
|
|
|
|
|
'syntax-table (string-to-syntax "\"'")))))
|
|
|
|
|
|
2010-11-16 21:19:34 +00:00
|
|
|
|
(defvar electric-layout-rules)
|
2010-09-08 16:21:23 +00:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
;;;###autoload
|
2010-08-12 11:22:16 +00:00
|
|
|
|
(define-derived-mode octave-mode prog-mode "Octave"
|
1997-01-21 00:29:57 +00:00
|
|
|
|
"Major mode for editing Octave code.
|
|
|
|
|
|
2013-04-27 17:07:01 +00:00
|
|
|
|
Octave is a high-level language, primarily intended for numerical
|
|
|
|
|
computations. It provides a convenient command line interface
|
|
|
|
|
for solving linear and nonlinear problems numerically. Function
|
|
|
|
|
definitions can also be stored in files and used in batch mode."
|
2013-05-01 06:13:20 +00:00
|
|
|
|
:abbrev-table octave-abbrev-table
|
2010-08-12 11:22:16 +00:00
|
|
|
|
|
2010-11-07 15:45:45 +00:00
|
|
|
|
(smie-setup octave-smie-grammar #'octave-smie-rules
|
2010-10-29 19:20:28 +00:00
|
|
|
|
:forward-token #'octave-smie-forward-token
|
|
|
|
|
:backward-token #'octave-smie-backward-token)
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local smie-indent-basic 'octave-block-offset)
|
2013-05-11 06:20:10 +00:00
|
|
|
|
(add-hook 'smie-indent-functions #'octave-indent-comment nil t)
|
2010-10-29 19:20:28 +00:00
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local smie-blink-matching-triggers
|
|
|
|
|
(cons ?\; smie-blink-matching-triggers))
|
2010-10-29 19:20:28 +00:00
|
|
|
|
(unless octave-blink-matching-block
|
|
|
|
|
(remove-hook 'post-self-insert-hook #'smie-blink-matching-open 'local))
|
2010-09-03 13:28:09 +00:00
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local electric-indent-chars
|
|
|
|
|
(cons ?\; electric-indent-chars))
|
2010-11-16 21:19:34 +00:00
|
|
|
|
;; IIUC matlab-mode takes the opposite approach: it makes RET insert
|
|
|
|
|
;; a ";" at those places where it's correct (i.e. outside of parens).
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local electric-layout-rules '((?\; . after)))
|
2010-08-12 11:22:16 +00:00
|
|
|
|
|
2013-06-07 11:48:28 +00:00
|
|
|
|
(setq-local comment-use-global-state t)
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local comment-start octave-comment-start)
|
|
|
|
|
(setq-local comment-end "")
|
2013-05-13 07:24:22 +00:00
|
|
|
|
(setq-local comment-start-skip octave-comment-start-skip)
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local comment-add 1)
|
|
|
|
|
|
|
|
|
|
(setq-local parse-sexp-ignore-comments t)
|
|
|
|
|
(setq-local paragraph-start (concat "\\s-*$\\|" page-delimiter))
|
|
|
|
|
(setq-local paragraph-separate paragraph-start)
|
|
|
|
|
(setq-local paragraph-ignore-fill-prefix t)
|
|
|
|
|
(setq-local fill-paragraph-function 'octave-fill-paragraph)
|
2013-05-21 09:43:14 +00:00
|
|
|
|
|
2013-05-21 23:05:16 +00:00
|
|
|
|
(setq-local fill-nobreak-predicate
|
|
|
|
|
(lambda () (eq (octave-in-string-p) ?')))
|
2013-06-21 06:45:37 +00:00
|
|
|
|
(with-no-warnings
|
|
|
|
|
(if (fboundp 'add-function) ; new in 24.4
|
|
|
|
|
(add-function :around (local 'comment-line-break-function)
|
|
|
|
|
#'octave--indent-new-comment-line)
|
|
|
|
|
(setq-local comment-line-break-function
|
|
|
|
|
(apply-partially #'octave--indent-new-comment-line
|
|
|
|
|
#'comment-indent-new-line))))
|
2010-08-12 11:22:16 +00:00
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq font-lock-defaults '(octave-font-lock-keywords))
|
New syntax-propertize functionality.
* lisp/font-lock.el (font-lock-syntactic-keywords): Make obsolete.
(font-lock-fontify-syntactic-keywords-region): Move handling of
font-lock-syntactically-fontified to...
(font-lock-default-fontify-region): ...here.
Let syntax-propertize-function take precedence.
(font-lock-fontify-syntactically-region): Cal syntax-propertize.
* lisp/emacs-lisp/regexp-opt.el (regexp-opt-depth): Skip named groups.
* lisp/emacs-lisp/syntax.el (syntax-propertize-function)
(syntax-propertize-chunk-size, syntax-propertize--done)
(syntax-propertize-extend-region-functions): New vars.
(syntax-propertize-wholelines, syntax-propertize-multiline)
(syntax-propertize--shift-groups, syntax-propertize-via-font-lock)
(syntax-propertize): New functions.
(syntax-propertize-rules): New macro.
(syntax-ppss-flush-cache): Set syntax-propertize--done.
(syntax-ppss): Call syntax-propertize.
* lisp/progmodes/ada-mode.el (ada-set-syntax-table-properties)
(ada-after-change-function, ada-initialize-syntax-table-properties)
(ada-handle-syntax-table-properties): Only define when
syntax-propertize is not available.
(ada-mode): Use syntax-propertize-function.
* lisp/progmodes/autoconf.el (autoconf-mode):
Use syntax-propertize-function.
(autoconf-font-lock-syntactic-keywords): Remove.
* lisp/progmodes/cfengine.el (cfengine-mode):
Use syntax-propertize-function.
(cfengine-font-lock-syntactic-keywords): Remove.
* lisp/progmodes/cperl-mode.el (cperl-mode): Use syntax-propertize-function.
* lisp/progmodes/fortran.el (fortran-mode): Use syntax-propertize-function.
(fortran--font-lock-syntactic-keywords): New var.
(fortran-line-length): Update syntax-propertize-function and
fortran--font-lock-syntactic-keywords.
* lisp/progmodes/gud.el (gdb-script-syntax-propertize-function): New var;
replaces gdb-script-font-lock-syntactic-keywords.
(gdb-script-mode): Use it.
* lisp/progmodes/js.el (js--regexp-literal): Define while compiling.
(js-syntax-propertize-function): New var; replaces
js-font-lock-syntactic-keywords.
(js-mode): Use it.
* lisp/progmodes/make-mode.el (makefile-syntax-propertize-function):
New var; replaces makefile-font-lock-syntactic-keywords.
(makefile-mode): Use it.
(makefile-imake-mode): Adjust.
* lisp/progmodes/mixal-mode.el (mixal-syntax-propertize-function): New var;
replaces mixal-font-lock-syntactic-keywords.
(mixal-mode): Use it.
* lisp/progmodes/octave-mod.el (octave-syntax-propertize-sqs): New function
to replace octave-font-lock-close-quotes.
(octave-syntax-propertize-function): New function to replace
octave-font-lock-syntactic-keywords.
(octave-mode): Use it.
* lisp/progmodes/perl-mode.el (perl-syntax-propertize-function): New fun to
replace perl-font-lock-syntactic-keywords.
(perl-syntax-propertize-special-constructs): New fun to replace
perl-font-lock-special-syntactic-constructs.
(perl-font-lock-syntactic-face-function): New fun.
(perl-mode): Use it.
* lisp/progmodes/python.el (python-syntax-propertize-function): New var to
replace python-font-lock-syntactic-keywords.
(python-mode): Use it.
(python-quote-syntax): Simplify and adjust to new use.
* lisp/progmodes/ruby-mode.el (ruby-here-doc-beg-re):
Define while compiling.
(ruby-here-doc-end-re, ruby-here-doc-beg-match)
(ruby-font-lock-syntactic-keywords, ruby-comment-beg-syntax)
(syntax-ppss, ruby-in-ppss-context-p, ruby-in-here-doc-p)
(ruby-here-doc-find-end, ruby-here-doc-beg-syntax)
(ruby-here-doc-end-syntax): Only define when
syntax-propertize is not available.
(ruby-syntax-propertize-function, ruby-syntax-propertize-heredoc):
New functions.
(ruby-in-ppss-context-p): Update to new syntax of heredocs.
(electric-indent-chars): Silence bytecompiler.
(ruby-mode): Use prog-mode, syntax-propertize-function, and
electric-indent-chars.
* lisp/progmodes/sh-script.el (sh-st-symbol): Remove.
(sh-font-lock-close-heredoc, sh-font-lock-open-heredoc): Add eol arg.
(sh-font-lock-flush-syntax-ppss-cache, sh-font-lock-here-doc): Remove.
(sh-font-lock-quoted-subshell): Assume we've already matched $(.
(sh-font-lock-paren): Set syntax-multiline.
(sh-font-lock-syntactic-keywords): Remove.
(sh-syntax-propertize-function): New function to replace it.
(sh-mode): Use it.
* lisp/progmodes/simula.el (simula-syntax-propertize-function): New var to
replace simula-font-lock-syntactic-keywords.
(simula-mode): Use it.
* lisp/progmodes/tcl.el (tcl-syntax-propertize-function): New var to
replace tcl-font-lock-syntactic-keywords.
(tcl-mode): Use it.
* lisp/progmodes/vhdl-mode.el (vhdl-mode): Use syntax-propertize-function
if available.
(vhdl-fontify-buffer): Adjust.
* lisp/textmodes/bibtex.el (bibtex-mode): Use syntax-propertize-function.
* lisp/textmodes/reftex.el (font-lock-syntactic-keywords): Don't declare
since we don't use it.
* lisp/textmodes/sgml-mode.el (sgml-syntax-propertize-function): New var to
replace sgml-font-lock-syntactic-keywords.
(sgml-mode): Use it.
* lisp/textmodes/tex-mode.el (tex-common-initialization, doctex-mode):
Use syntax-propertize-function.
* lisp/textmodes/texinfo.el (texinfo-syntax-propertize-function): New fun
to replace texinfo-font-lock-syntactic-keywords.
(texinfo-mode): Use it.
* test/indent/octave.m: Remove some `fixindent' not needed any more.
2010-09-10 23:13:42 +00:00
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local syntax-propertize-function #'octave-syntax-propertize-function)
|
2010-08-12 11:22:16 +00:00
|
|
|
|
|
2013-05-05 15:29:51 +00:00
|
|
|
|
(setq-local imenu-generic-expression octave-mode-imenu-generic-expression)
|
|
|
|
|
(setq-local imenu-case-fold-search nil)
|
2010-08-12 11:22:16 +00:00
|
|
|
|
|
2013-06-08 13:35:55 +00:00
|
|
|
|
(setq-local add-log-current-defun-function #'octave-add-log-current-defun)
|
|
|
|
|
|
2013-05-06 23:46:07 +00:00
|
|
|
|
(add-hook 'completion-at-point-functions 'octave-completion-at-point nil t)
|
2013-04-26 16:44:38 +00:00
|
|
|
|
(add-hook 'before-save-hook 'octave-sync-function-file-names nil t)
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local beginning-of-defun-function 'octave-beginning-of-defun)
|
2013-04-30 14:23:03 +00:00
|
|
|
|
(and octave-font-lock-texinfo-comment (octave-font-lock-texinfo-comment))
|
2013-05-11 13:22:06 +00:00
|
|
|
|
(setq-local eldoc-documentation-function 'octave-eldoc-function)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-04-25 16:23:56 +00:00
|
|
|
|
(easy-menu-add octave-mode-menu))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defcustom inferior-octave-program "octave"
|
|
|
|
|
"Program invoked by `inferior-octave'."
|
|
|
|
|
:type 'string
|
|
|
|
|
:group 'octave)
|
|
|
|
|
|
|
|
|
|
(defcustom inferior-octave-buffer "*Inferior Octave*"
|
|
|
|
|
"Name of buffer for running an inferior Octave process."
|
|
|
|
|
:type 'string
|
|
|
|
|
:group 'octave)
|
|
|
|
|
|
|
|
|
|
(defcustom inferior-octave-prompt
|
|
|
|
|
"\\(^octave\\(\\|.bin\\|.exe\\)\\(-[.0-9]+\\)?\\(:[0-9]+\\)?\\|^debug\\|^\\)>+ "
|
|
|
|
|
"Regexp to match prompts for the inferior Octave process."
|
|
|
|
|
:type 'regexp
|
|
|
|
|
:group 'octave)
|
|
|
|
|
|
2013-04-30 16:27:36 +00:00
|
|
|
|
(defcustom inferior-octave-prompt-read-only comint-prompt-read-only
|
2013-04-30 15:20:46 +00:00
|
|
|
|
"If non-nil, the Octave prompt is read only.
|
2013-04-30 16:27:36 +00:00
|
|
|
|
See `comint-prompt-read-only' for details."
|
2013-04-30 15:20:46 +00:00
|
|
|
|
:type 'boolean
|
|
|
|
|
:group 'octave
|
|
|
|
|
:version "24.4")
|
|
|
|
|
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(defcustom inferior-octave-startup-file
|
|
|
|
|
(convert-standard-filename
|
|
|
|
|
(concat "~/.emacs-" (file-name-nondirectory inferior-octave-program)))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
"Name of the inferior Octave startup file.
|
|
|
|
|
The contents of this file are sent to the inferior Octave process on
|
|
|
|
|
startup."
|
2013-05-02 21:34:53 +00:00
|
|
|
|
:type '(choice (const :tag "None" nil) file)
|
|
|
|
|
:group 'octave
|
|
|
|
|
:version "24.4")
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(defcustom inferior-octave-startup-args '("-i" "--no-line-editing")
|
2013-04-25 14:51:08 +00:00
|
|
|
|
"List of command line arguments for the inferior Octave process.
|
|
|
|
|
For example, for suppressing the startup message and using `traditional'
|
2013-06-12 02:37:38 +00:00
|
|
|
|
mode, include \"-q\" and \"--traditional\"."
|
2013-04-25 14:51:08 +00:00
|
|
|
|
:type '(repeat string)
|
2013-06-12 02:37:38 +00:00
|
|
|
|
:group 'octave
|
|
|
|
|
:version "24.4")
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
(defcustom inferior-octave-mode-hook nil
|
|
|
|
|
"Hook to be run when Inferior Octave mode is started."
|
|
|
|
|
:type 'hook
|
|
|
|
|
:group 'octave)
|
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-process nil)
|
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-mode-map
|
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
|
(set-keymap-parent map comint-mode-map)
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(define-key map "\M-." 'octave-find-definition)
|
2013-05-05 04:49:27 +00:00
|
|
|
|
(define-key map "\t" 'completion-at-point)
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(define-key map "\C-hd" 'octave-help)
|
2013-05-05 04:49:27 +00:00
|
|
|
|
;; Same as in `shell-mode'.
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(define-key map "\M-?" 'comint-dynamic-list-filename-completions)
|
|
|
|
|
(define-key map "\C-c\C-l" 'inferior-octave-dynamic-list-input-ring)
|
|
|
|
|
(define-key map [menu-bar inout list-history]
|
|
|
|
|
'("List Input History" . inferior-octave-dynamic-list-input-ring))
|
|
|
|
|
map)
|
|
|
|
|
"Keymap used in Inferior Octave mode.")
|
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-mode-syntax-table
|
|
|
|
|
(let ((table (make-syntax-table octave-mode-syntax-table)))
|
|
|
|
|
table)
|
|
|
|
|
"Syntax table in use in inferior-octave-mode buffers.")
|
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-font-lock-keywords
|
|
|
|
|
(list
|
|
|
|
|
(cons inferior-octave-prompt 'font-lock-type-face))
|
|
|
|
|
;; Could certainly do more font locking in inferior Octave ...
|
|
|
|
|
"Additional expressions to highlight in Inferior Octave mode.")
|
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-output-list nil)
|
|
|
|
|
(defvar inferior-octave-output-string nil)
|
|
|
|
|
(defvar inferior-octave-receive-in-progress nil)
|
|
|
|
|
|
2013-04-29 04:37:36 +00:00
|
|
|
|
(define-obsolete-variable-alias 'inferior-octave-startup-hook
|
|
|
|
|
'inferior-octave-mode-hook "24.4")
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-dynamic-complete-functions
|
|
|
|
|
'(inferior-octave-completion-at-point comint-filename-completion)
|
|
|
|
|
"List of functions called to perform completion for inferior Octave.
|
|
|
|
|
This variable is used to initialize `comint-dynamic-complete-functions'
|
|
|
|
|
in the Inferior Octave buffer.")
|
|
|
|
|
|
|
|
|
|
(defvar info-lookup-mode)
|
|
|
|
|
|
|
|
|
|
(define-derived-mode inferior-octave-mode comint-mode "Inferior Octave"
|
2013-04-27 17:07:01 +00:00
|
|
|
|
"Major mode for interacting with an inferior Octave process."
|
2013-05-01 06:13:20 +00:00
|
|
|
|
:abbrev-table octave-abbrev-table
|
|
|
|
|
(setq comint-prompt-regexp inferior-octave-prompt)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
2013-06-07 11:48:28 +00:00
|
|
|
|
(setq-local comment-use-global-state t)
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local comment-start octave-comment-start)
|
|
|
|
|
(setq-local comment-end "")
|
|
|
|
|
(setq comment-column 32)
|
|
|
|
|
(setq-local comment-start-skip octave-comment-start-skip)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq font-lock-defaults '(inferior-octave-font-lock-keywords nil nil))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
2013-05-05 15:29:51 +00:00
|
|
|
|
(setq-local info-lookup-mode 'octave-mode)
|
2013-05-11 13:22:06 +00:00
|
|
|
|
(setq-local eldoc-documentation-function 'octave-eldoc-function)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
(setq comint-input-ring-file-name
|
2013-06-01 03:38:36 +00:00
|
|
|
|
(or (getenv "OCTAVE_HISTFILE") "~/.octave_hist")
|
|
|
|
|
comint-input-ring-size (or (getenv "OCTAVE_HISTSIZE") 1024))
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(setq-local comint-dynamic-complete-functions
|
|
|
|
|
inferior-octave-dynamic-complete-functions)
|
2013-04-30 15:20:46 +00:00
|
|
|
|
(setq-local comint-prompt-read-only inferior-octave-prompt-read-only)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(add-hook 'comint-input-filter-functions
|
2013-05-06 23:46:07 +00:00
|
|
|
|
'inferior-octave-directory-tracker nil t)
|
2013-06-01 03:38:36 +00:00
|
|
|
|
;; http://thread.gmane.org/gmane.comp.gnu.octave.general/48572
|
|
|
|
|
(add-hook 'window-configuration-change-hook
|
|
|
|
|
'inferior-octave-track-window-width-change nil t)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(comint-read-input-ring t))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun inferior-octave (&optional arg)
|
|
|
|
|
"Run an inferior Octave process, I/O via `inferior-octave-buffer'.
|
|
|
|
|
This buffer is put in Inferior Octave mode. See `inferior-octave-mode'.
|
|
|
|
|
|
|
|
|
|
Unless ARG is non-nil, switches to this buffer.
|
|
|
|
|
|
|
|
|
|
The elements of the list `inferior-octave-startup-args' are sent as
|
|
|
|
|
command line arguments to the inferior Octave process on startup.
|
|
|
|
|
|
|
|
|
|
Additional commands to be executed on startup can be provided either in
|
|
|
|
|
the file specified by `inferior-octave-startup-file' or by the default
|
|
|
|
|
startup file, `~/.emacs-octave'."
|
|
|
|
|
(interactive "P")
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(let ((buffer (get-buffer-create inferior-octave-buffer)))
|
2013-05-21 23:05:16 +00:00
|
|
|
|
(unless arg
|
|
|
|
|
(pop-to-buffer buffer))
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(unless (comint-check-proc buffer)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(with-current-buffer buffer
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(inferior-octave-startup)
|
|
|
|
|
(inferior-octave-mode)))
|
|
|
|
|
buffer))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defalias 'run-octave 'inferior-octave)
|
|
|
|
|
|
|
|
|
|
(defun inferior-octave-startup ()
|
|
|
|
|
"Start an inferior Octave process."
|
|
|
|
|
(let ((proc (comint-exec-1
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(substring inferior-octave-buffer 1 -1)
|
|
|
|
|
inferior-octave-buffer
|
|
|
|
|
inferior-octave-program
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(append
|
|
|
|
|
inferior-octave-startup-args
|
|
|
|
|
;; --no-gui is introduced in Octave > 3.7
|
|
|
|
|
(and (not (member "--no-gui" inferior-octave-startup-args))
|
|
|
|
|
(zerop (process-file inferior-octave-program
|
|
|
|
|
nil nil nil "--no-gui" "--help"))
|
|
|
|
|
'("--no-gui"))))))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(set-process-filter proc 'inferior-octave-output-digest)
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(setq inferior-octave-process proc
|
|
|
|
|
inferior-octave-output-list nil
|
|
|
|
|
inferior-octave-output-string nil
|
|
|
|
|
inferior-octave-receive-in-progress t)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
;; This may look complicated ... However, we need to make sure that
|
|
|
|
|
;; we additional startup code only AFTER Octave is ready (otherwise,
|
|
|
|
|
;; output may be mixed up). Hence, we need to digest the Octave
|
|
|
|
|
;; output to see when it issues a prompt.
|
|
|
|
|
(while inferior-octave-receive-in-progress
|
2013-05-21 23:05:16 +00:00
|
|
|
|
(or (process-live-p inferior-octave-process)
|
|
|
|
|
(error "Process `%s' died" inferior-octave-process))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(accept-process-output inferior-octave-process))
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(set-marker (process-mark proc) (point))
|
|
|
|
|
(insert-before-markers
|
|
|
|
|
(concat
|
|
|
|
|
(if (not (bobp)) "\n")
|
|
|
|
|
(if inferior-octave-output-list
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(concat (mapconcat
|
|
|
|
|
'identity inferior-octave-output-list "\n")
|
|
|
|
|
"\n"))))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
;; An empty secondary prompt, as e.g. obtained by '--braindead',
|
|
|
|
|
;; means trouble.
|
|
|
|
|
(inferior-octave-send-list-and-digest (list "PS2\n"))
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(when (string-match "\\(PS2\\|ans\\) = *$"
|
|
|
|
|
(car inferior-octave-output-list))
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(inferior-octave-send-list-and-digest (list "PS2 ('> ');\n")))
|
2013-05-02 21:34:53 +00:00
|
|
|
|
|
2013-05-12 04:10:40 +00:00
|
|
|
|
(inferior-octave-send-list-and-digest
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(list "disp (getenv ('OCTAVE_SRCDIR'))\n"))
|
2013-05-18 01:17:50 +00:00
|
|
|
|
(process-put proc 'octave-srcdir
|
|
|
|
|
(unless (equal (car inferior-octave-output-list) "")
|
|
|
|
|
(car inferior-octave-output-list)))
|
2013-05-12 04:10:40 +00:00
|
|
|
|
|
2013-05-02 21:34:53 +00:00
|
|
|
|
;; O.K., now we are ready for the Inferior Octave startup commands.
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
|
|
|
|
(list "more off;\n"
|
|
|
|
|
(unless (equal inferior-octave-output-string ">> ")
|
2013-06-12 02:58:03 +00:00
|
|
|
|
"PS1 ('\\s> ');\n")
|
2013-05-02 21:34:53 +00:00
|
|
|
|
(when (and inferior-octave-startup-file
|
|
|
|
|
(file-exists-p inferior-octave-startup-file))
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(format "source ('%s');\n" inferior-octave-startup-file))))
|
2013-05-22 15:28:42 +00:00
|
|
|
|
(when inferior-octave-output-list
|
|
|
|
|
(insert-before-markers
|
|
|
|
|
(mapconcat 'identity inferior-octave-output-list "\n")))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
;; And finally, everything is back to normal.
|
2013-05-05 04:49:27 +00:00
|
|
|
|
(set-process-filter proc 'comint-output-filter)
|
2013-06-12 02:37:38 +00:00
|
|
|
|
;; Just in case, to be sure a cd in the startup file won't have
|
|
|
|
|
;; detrimental effects.
|
|
|
|
|
(with-demoted-errors (inferior-octave-resync-dirs))
|
2013-05-22 15:28:42 +00:00
|
|
|
|
;; Generate a proper prompt, which is critical to
|
|
|
|
|
;; `comint-history-isearch-backward-regexp'. Bug#14433.
|
2013-05-09 00:52:49 +00:00
|
|
|
|
(comint-send-string proc "\n")))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
2013-05-10 06:26:42 +00:00
|
|
|
|
(defvar inferior-octave-completion-table
|
|
|
|
|
;;
|
2013-05-12 04:10:40 +00:00
|
|
|
|
;; Use cache to avoid repetitive computation of completions due to
|
2013-05-10 06:26:42 +00:00
|
|
|
|
;; bug#11906 - http://debbugs.gnu.org/11906 - which may cause
|
|
|
|
|
;; noticeable delay. CACHE: (CMD TIME VALUE).
|
|
|
|
|
(let ((cache))
|
|
|
|
|
(completion-table-dynamic
|
|
|
|
|
(lambda (command)
|
|
|
|
|
(unless (and (equal (car cache) command)
|
|
|
|
|
(< (float-time) (+ 5 (cadr cache))))
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(list (format "completion_matches ('%s');\n" command)))
|
2013-05-10 06:26:42 +00:00
|
|
|
|
(setq cache (list command (float-time)
|
2013-05-17 02:43:41 +00:00
|
|
|
|
(delete-consecutive-dups
|
|
|
|
|
(sort inferior-octave-output-list 'string-lessp)))))
|
2013-05-10 06:26:42 +00:00
|
|
|
|
(car (cddr cache))))))
|
2013-04-25 16:23:56 +00:00
|
|
|
|
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(defun inferior-octave-completion-at-point ()
|
|
|
|
|
"Return the data to complete the Octave symbol at point."
|
2013-05-09 00:52:49 +00:00
|
|
|
|
;; http://debbugs.gnu.org/14300
|
|
|
|
|
(let* ((filecomp (string-match-p
|
|
|
|
|
"/" (or (comint--match-partial-filename) "")))
|
|
|
|
|
(end (point))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(start
|
2013-05-09 00:52:49 +00:00
|
|
|
|
(unless filecomp
|
|
|
|
|
(save-excursion
|
|
|
|
|
(skip-syntax-backward "w_" (comint-line-beginning-position))
|
|
|
|
|
(point)))))
|
|
|
|
|
(when (and start (> end start))
|
|
|
|
|
(list start end (completion-table-in-turn
|
2013-05-10 06:26:42 +00:00
|
|
|
|
inferior-octave-completion-table
|
2013-05-09 00:52:49 +00:00
|
|
|
|
'comint-completion-file-name-table)))))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
|
|
|
|
(define-obsolete-function-alias 'inferior-octave-complete
|
|
|
|
|
'completion-at-point "24.1")
|
|
|
|
|
|
|
|
|
|
(defun inferior-octave-dynamic-list-input-ring ()
|
|
|
|
|
"List the buffer's input history in a help buffer."
|
|
|
|
|
;; We cannot use `comint-dynamic-list-input-ring', because it replaces
|
|
|
|
|
;; "completion" by "history reference" ...
|
|
|
|
|
(interactive)
|
|
|
|
|
(if (or (not (ring-p comint-input-ring))
|
|
|
|
|
(ring-empty-p comint-input-ring))
|
|
|
|
|
(message "No history")
|
|
|
|
|
(let ((history nil)
|
|
|
|
|
(history-buffer " *Input History*")
|
|
|
|
|
(index (1- (ring-length comint-input-ring)))
|
|
|
|
|
(conf (current-window-configuration)))
|
|
|
|
|
;; We have to build up a list ourselves from the ring vector.
|
|
|
|
|
(while (>= index 0)
|
|
|
|
|
(setq history (cons (ring-ref comint-input-ring index) history)
|
|
|
|
|
index (1- index)))
|
|
|
|
|
;; Change "completion" to "history reference"
|
|
|
|
|
;; to make the display accurate.
|
|
|
|
|
(with-output-to-temp-buffer history-buffer
|
|
|
|
|
(display-completion-list history)
|
|
|
|
|
(set-buffer history-buffer))
|
|
|
|
|
(message "Hit space to flush")
|
|
|
|
|
(let ((ch (read-event)))
|
|
|
|
|
(if (eq ch ?\ )
|
|
|
|
|
(set-window-configuration conf)
|
|
|
|
|
(setq unread-command-events (list ch)))))))
|
|
|
|
|
|
|
|
|
|
(defun inferior-octave-output-digest (_proc string)
|
|
|
|
|
"Special output filter for the inferior Octave process.
|
|
|
|
|
Save all output between newlines into `inferior-octave-output-list', and
|
|
|
|
|
the rest to `inferior-octave-output-string'."
|
|
|
|
|
(setq string (concat inferior-octave-output-string string))
|
|
|
|
|
(while (string-match "\n" string)
|
|
|
|
|
(setq inferior-octave-output-list
|
|
|
|
|
(append inferior-octave-output-list
|
|
|
|
|
(list (substring string 0 (match-beginning 0))))
|
|
|
|
|
string (substring string (match-end 0))))
|
|
|
|
|
(if (string-match inferior-octave-prompt string)
|
|
|
|
|
(setq inferior-octave-receive-in-progress nil))
|
|
|
|
|
(setq inferior-octave-output-string string))
|
|
|
|
|
|
2013-05-12 04:10:40 +00:00
|
|
|
|
(defun inferior-octave-check-process ()
|
|
|
|
|
(or (and inferior-octave-process
|
|
|
|
|
(process-live-p inferior-octave-process))
|
|
|
|
|
(error (substitute-command-keys
|
|
|
|
|
"No inferior octave process running. Type \\[run-octave]"))))
|
|
|
|
|
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(defun inferior-octave-send-list-and-digest (list)
|
|
|
|
|
"Send LIST to the inferior Octave process and digest the output.
|
|
|
|
|
The elements of LIST have to be strings and are sent one by one. All
|
|
|
|
|
output is passed to the filter `inferior-octave-output-digest'."
|
2013-05-12 04:10:40 +00:00
|
|
|
|
(inferior-octave-check-process)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(let* ((proc inferior-octave-process)
|
|
|
|
|
(filter (process-filter proc))
|
|
|
|
|
string)
|
|
|
|
|
(set-process-filter proc 'inferior-octave-output-digest)
|
|
|
|
|
(setq inferior-octave-output-list nil)
|
|
|
|
|
(unwind-protect
|
|
|
|
|
(while (setq string (car list))
|
|
|
|
|
(setq inferior-octave-output-string nil
|
|
|
|
|
inferior-octave-receive-in-progress t)
|
|
|
|
|
(comint-send-string proc string)
|
|
|
|
|
(while inferior-octave-receive-in-progress
|
|
|
|
|
(accept-process-output proc))
|
|
|
|
|
(setq list (cdr list)))
|
|
|
|
|
(set-process-filter proc filter))))
|
|
|
|
|
|
2013-05-27 05:08:04 +00:00
|
|
|
|
(defvar inferior-octave-directory-tracker-resync nil)
|
|
|
|
|
(make-variable-buffer-local 'inferior-octave-directory-tracker-resync)
|
|
|
|
|
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(defun inferior-octave-directory-tracker (string)
|
|
|
|
|
"Tracks `cd' commands issued to the inferior Octave process.
|
|
|
|
|
Use \\[inferior-octave-resync-dirs] to resync if Emacs gets confused."
|
2013-05-27 05:08:04 +00:00
|
|
|
|
(when inferior-octave-directory-tracker-resync
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(or (inferior-octave-resync-dirs 'noerror)
|
|
|
|
|
(setq inferior-octave-directory-tracker-resync nil)))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(cond
|
|
|
|
|
((string-match "^[ \t]*cd[ \t;]*$" string)
|
|
|
|
|
(cd "~"))
|
|
|
|
|
((string-match "^[ \t]*cd[ \t]+\\([^ \t\n;]*\\)[ \t\n;]*" string)
|
2013-05-27 05:08:04 +00:00
|
|
|
|
(condition-case err
|
|
|
|
|
(cd (match-string 1 string))
|
|
|
|
|
(error (setq inferior-octave-directory-tracker-resync t)
|
|
|
|
|
(message "%s: `%s'"
|
|
|
|
|
(error-message-string err)
|
|
|
|
|
(match-string 1 string)))))))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(defun inferior-octave-resync-dirs (&optional noerror)
|
2013-04-25 14:51:08 +00:00
|
|
|
|
"Resync the buffer's idea of the current directory.
|
|
|
|
|
This command queries the inferior Octave process about its current
|
|
|
|
|
directory and makes this the current buffer's default directory."
|
|
|
|
|
(interactive)
|
|
|
|
|
(inferior-octave-send-list-and-digest '("disp (pwd ())\n"))
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(condition-case err
|
|
|
|
|
(progn
|
|
|
|
|
(cd (car inferior-octave-output-list))
|
|
|
|
|
t)
|
|
|
|
|
(error (unless noerror (signal (car err) (cdr err))))))
|
2013-04-25 14:51:08 +00:00
|
|
|
|
|
2013-06-01 03:38:36 +00:00
|
|
|
|
(defcustom inferior-octave-minimal-columns 80
|
|
|
|
|
"The minimal column width for the inferior Octave process."
|
|
|
|
|
:type 'integer
|
|
|
|
|
:group 'octave
|
|
|
|
|
:version "24.4")
|
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-last-column-width nil)
|
|
|
|
|
|
|
|
|
|
(defun inferior-octave-track-window-width-change ()
|
|
|
|
|
;; http://thread.gmane.org/gmane.comp.gnu.octave.general/48572
|
|
|
|
|
(let ((width (max inferior-octave-minimal-columns (window-width))))
|
|
|
|
|
(unless (eq inferior-octave-last-column-width width)
|
|
|
|
|
(setq-local inferior-octave-last-column-width width)
|
|
|
|
|
(when (and inferior-octave-process
|
|
|
|
|
(process-live-p inferior-octave-process))
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(list (format "putenv ('COLUMNS', '%s');\n" width)))))))
|
2013-06-01 03:38:36 +00:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
;;; Miscellaneous useful functions
|
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(defun octave-in-comment-p ()
|
|
|
|
|
"Return non-nil if point is inside an Octave comment."
|
2011-04-19 15:33:34 +00:00
|
|
|
|
(nth 4 (syntax-ppss)))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(defun octave-in-string-p ()
|
|
|
|
|
"Return non-nil if point is inside an Octave string."
|
2011-04-19 15:33:34 +00:00
|
|
|
|
(nth 3 (syntax-ppss)))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(defun octave-in-string-or-comment-p ()
|
|
|
|
|
"Return non-nil if point is inside an Octave string or comment."
|
|
|
|
|
(nth 8 (syntax-ppss)))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2007-10-13 20:01:54 +00:00
|
|
|
|
(defun octave-looking-at-kw (regexp)
|
2007-10-13 20:09:14 +00:00
|
|
|
|
"Like `looking-at', but sets `case-fold-search' nil."
|
2007-10-13 20:01:54 +00:00
|
|
|
|
(let ((case-fold-search nil))
|
|
|
|
|
(looking-at regexp)))
|
|
|
|
|
|
1997-10-24 20:11:44 +00:00
|
|
|
|
(defun octave-maybe-insert-continuation-string ()
|
|
|
|
|
(if (or (octave-in-comment-p)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(looking-at octave-continuation-regexp)))
|
|
|
|
|
nil
|
|
|
|
|
(delete-horizontal-space)
|
|
|
|
|
(insert (concat " " octave-continuation-string))))
|
2013-04-26 16:44:38 +00:00
|
|
|
|
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(defun octave-completing-read ()
|
|
|
|
|
(let ((def (or (thing-at-point 'symbol)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(skip-syntax-backward "-(")
|
|
|
|
|
(thing-at-point 'symbol)))))
|
|
|
|
|
(completing-read
|
|
|
|
|
(format (if def "Function (default %s): "
|
|
|
|
|
"Function: ") def)
|
2013-05-10 06:26:42 +00:00
|
|
|
|
inferior-octave-completion-table
|
2013-05-03 07:22:26 +00:00
|
|
|
|
nil nil nil nil def)))
|
|
|
|
|
|
2013-05-15 08:17:22 +00:00
|
|
|
|
(defun octave-goto-function-definition (fn)
|
|
|
|
|
"Go to the function definition of FN in current buffer."
|
|
|
|
|
(let ((search
|
|
|
|
|
(lambda (re sub)
|
2013-06-08 13:35:55 +00:00
|
|
|
|
(let ((orig (point)) found)
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(while (and (not found) (re-search-forward re nil t))
|
2013-05-15 08:17:22 +00:00
|
|
|
|
(when (and (equal (match-string sub) fn)
|
|
|
|
|
(not (nth 8 (syntax-ppss))))
|
2013-06-08 13:35:55 +00:00
|
|
|
|
(setq found t)))
|
|
|
|
|
(unless found (goto-char orig))
|
|
|
|
|
found))))
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(pcase (and buffer-file-name (file-name-extension buffer-file-name))
|
2013-05-15 08:17:22 +00:00
|
|
|
|
(`"cc" (funcall search
|
2013-05-21 09:43:14 +00:00
|
|
|
|
"\\_<DEFUN\\(?:_DLD\\)?\\s-*(\\s-*\\(\\(?:\\sw\\|\\s_\\)+\\)" 1))
|
2013-05-15 08:17:22 +00:00
|
|
|
|
(t (funcall search octave-function-header-regexp 3)))))
|
2013-05-03 07:22:26 +00:00
|
|
|
|
|
2013-04-27 17:07:01 +00:00
|
|
|
|
(defun octave-function-file-p ()
|
|
|
|
|
"Return non-nil if the first token is \"function\".
|
|
|
|
|
The value is (START END NAME-START NAME-END) of the function."
|
|
|
|
|
(save-excursion
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(when (equal (funcall smie-forward-token-function) "function")
|
|
|
|
|
(forward-word -1)
|
|
|
|
|
(let* ((start (point))
|
|
|
|
|
(end (progn (forward-sexp 1) (point)))
|
|
|
|
|
(name (when (progn
|
|
|
|
|
(goto-char start)
|
|
|
|
|
(re-search-forward octave-function-header-regexp
|
|
|
|
|
end t))
|
|
|
|
|
(list (match-beginning 3) (match-end 3)))))
|
|
|
|
|
(cons start (cons end name))))))
|
|
|
|
|
|
|
|
|
|
;; Like forward-comment but stop at non-comment blank
|
|
|
|
|
(defun octave-skip-comment-forward (limit)
|
|
|
|
|
(let ((ppss (syntax-ppss)))
|
|
|
|
|
(if (nth 4 ppss)
|
|
|
|
|
(goto-char (nth 8 ppss))
|
|
|
|
|
(goto-char (or (comment-search-forward limit t) (point)))))
|
|
|
|
|
(while (and (< (point) limit) (looking-at-p "\\s<"))
|
|
|
|
|
(forward-comment 1)))
|
|
|
|
|
|
|
|
|
|
;;; First non-copyright comment block
|
|
|
|
|
(defun octave-function-file-comment ()
|
2013-04-29 04:37:36 +00:00
|
|
|
|
"Beginning and end positions of the function file comment."
|
2013-04-27 17:07:01 +00:00
|
|
|
|
(save-excursion
|
|
|
|
|
(goto-char (point-min))
|
2013-04-29 20:09:18 +00:00
|
|
|
|
;; Copyright block: octave/libinterp/parse-tree/lex.ll around line 1634
|
|
|
|
|
(while (save-excursion
|
|
|
|
|
(when (comment-search-forward (point-max) t)
|
|
|
|
|
(when (eq (char-after) ?\{) ; case of block comment
|
|
|
|
|
(forward-char 1))
|
|
|
|
|
(skip-syntax-forward "-")
|
|
|
|
|
(let ((case-fold-search t))
|
|
|
|
|
(looking-at-p "\\(?:copyright\\|author\\)\\_>"))))
|
|
|
|
|
(octave-skip-comment-forward (point-max)))
|
|
|
|
|
(let ((beg (comment-search-forward (point-max) t)))
|
|
|
|
|
(when beg
|
|
|
|
|
(goto-char beg)
|
|
|
|
|
(octave-skip-comment-forward (point-max))
|
|
|
|
|
(list beg (point))))))
|
2013-04-27 17:07:01 +00:00
|
|
|
|
|
2013-04-26 16:44:38 +00:00
|
|
|
|
(defun octave-sync-function-file-names ()
|
|
|
|
|
"Ensure function name agree with function file name.
|
|
|
|
|
See Info node `(octave)Function Files'."
|
|
|
|
|
(interactive)
|
2013-04-27 17:07:01 +00:00
|
|
|
|
(when buffer-file-name
|
|
|
|
|
(pcase-let ((`(,start ,_end ,name-start ,name-end)
|
|
|
|
|
(octave-function-file-p)))
|
|
|
|
|
(when (and start name-start)
|
2013-04-29 04:37:36 +00:00
|
|
|
|
(let* ((func (buffer-substring name-start name-end))
|
|
|
|
|
(file (file-name-sans-extension
|
|
|
|
|
(file-name-nondirectory buffer-file-name)))
|
|
|
|
|
(help-form (format "\
|
|
|
|
|
a: Use function name `%s'
|
|
|
|
|
b: Use file name `%s'
|
|
|
|
|
q: Don't fix\n" func file))
|
|
|
|
|
(c (unless (equal file func)
|
|
|
|
|
(save-window-excursion
|
|
|
|
|
(help-form-show)
|
|
|
|
|
(read-char-choice
|
|
|
|
|
"Which name to use? (a/b/q) " '(?a ?b ?q))))))
|
|
|
|
|
(pcase c
|
|
|
|
|
(`?a (let ((newname (expand-file-name
|
|
|
|
|
(concat func (file-name-extension
|
|
|
|
|
buffer-file-name t)))))
|
|
|
|
|
(when (or (not (file-exists-p newname))
|
|
|
|
|
(yes-or-no-p
|
|
|
|
|
(format "Target file %s exists; proceed? " newname)))
|
|
|
|
|
(when (file-exists-p buffer-file-name)
|
|
|
|
|
(rename-file buffer-file-name newname t))
|
|
|
|
|
(set-visited-file-name newname))))
|
|
|
|
|
(`?b (save-excursion
|
|
|
|
|
(goto-char name-start)
|
|
|
|
|
(delete-region name-start name-end)
|
|
|
|
|
(insert file)))))))))
|
2013-04-27 17:07:01 +00:00
|
|
|
|
|
|
|
|
|
(defun octave-update-function-file-comment (beg end)
|
|
|
|
|
"Query replace function names in function file comment."
|
|
|
|
|
(interactive
|
|
|
|
|
(progn
|
|
|
|
|
(barf-if-buffer-read-only)
|
|
|
|
|
(if (use-region-p)
|
|
|
|
|
(list (region-beginning) (region-end))
|
|
|
|
|
(or (octave-function-file-comment)
|
|
|
|
|
(error "No function file comment found")))))
|
2013-04-26 16:44:38 +00:00
|
|
|
|
(save-excursion
|
2013-04-27 17:07:01 +00:00
|
|
|
|
(let* ((bounds (or (octave-function-file-p)
|
|
|
|
|
(error "Not in a function file buffer")))
|
|
|
|
|
(func (if (cddr bounds)
|
|
|
|
|
(apply #'buffer-substring (cddr bounds))
|
|
|
|
|
(error "Function name not found")))
|
|
|
|
|
(old-func (progn
|
|
|
|
|
(goto-char beg)
|
2013-04-29 20:09:18 +00:00
|
|
|
|
(when (re-search-forward
|
|
|
|
|
"[=}]\\s-*\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>"
|
|
|
|
|
(min (line-end-position 4) end)
|
|
|
|
|
t)
|
2013-04-27 17:07:01 +00:00
|
|
|
|
(match-string 1))))
|
|
|
|
|
(old-func (read-string (format (if old-func
|
|
|
|
|
"Name to replace (default %s): "
|
|
|
|
|
"Name to replace: ")
|
|
|
|
|
old-func)
|
|
|
|
|
nil nil old-func)))
|
|
|
|
|
(if (and func old-func (not (equal func old-func)))
|
|
|
|
|
(perform-replace old-func func 'query
|
|
|
|
|
nil 'delimited nil nil beg end)
|
|
|
|
|
(message "Function names match")))))
|
2013-04-26 16:44:38 +00:00
|
|
|
|
|
2013-04-30 14:23:03 +00:00
|
|
|
|
(defface octave-function-comment-block
|
|
|
|
|
'((t (:inherit font-lock-doc-face)))
|
|
|
|
|
"Face used to highlight function comment block."
|
|
|
|
|
:group 'octave)
|
|
|
|
|
|
2013-05-06 02:29:42 +00:00
|
|
|
|
(eval-when-compile (require 'texinfo))
|
|
|
|
|
|
2013-04-30 14:23:03 +00:00
|
|
|
|
(defun octave-font-lock-texinfo-comment ()
|
2013-05-06 02:29:42 +00:00
|
|
|
|
(let ((kws
|
|
|
|
|
(eval-when-compile
|
|
|
|
|
(delq nil (mapcar
|
|
|
|
|
(lambda (kw)
|
|
|
|
|
(if (numberp (nth 1 kw))
|
|
|
|
|
`(,(nth 0 kw) ,(nth 1 kw) ,(nth 2 kw) prepend)
|
|
|
|
|
(message "Ignoring Texinfo highlight: %S" kw)))
|
|
|
|
|
texinfo-font-lock-keywords)))))
|
|
|
|
|
(font-lock-add-keywords
|
|
|
|
|
nil
|
|
|
|
|
`((,(lambda (limit)
|
2013-05-14 10:11:56 +00:00
|
|
|
|
(while (and (< (point) limit)
|
|
|
|
|
(search-forward "-*- texinfo -*-" limit t)
|
2013-05-06 02:29:42 +00:00
|
|
|
|
(octave-in-comment-p))
|
|
|
|
|
(let ((beg (nth 8 (syntax-ppss)))
|
|
|
|
|
(end (progn
|
|
|
|
|
(octave-skip-comment-forward (point-max))
|
|
|
|
|
(point))))
|
|
|
|
|
(put-text-property beg end 'font-lock-multiline t)
|
|
|
|
|
(font-lock-prepend-text-property
|
|
|
|
|
beg end 'face 'octave-function-comment-block)
|
|
|
|
|
(dolist (kw kws)
|
|
|
|
|
(goto-char beg)
|
|
|
|
|
(while (re-search-forward (car kw) end 'move)
|
|
|
|
|
(font-lock-apply-highlight (cdr kw))))))
|
|
|
|
|
nil)))
|
|
|
|
|
'append)))
|
2013-04-30 14:23:03 +00:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
;;; Indentation
|
|
|
|
|
|
2013-05-21 09:43:14 +00:00
|
|
|
|
(defun octave-indent-new-comment-line (&optional soft)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
"Break Octave line at point, continuing comment if within one.
|
2013-05-21 09:43:14 +00:00
|
|
|
|
Insert `octave-continuation-string' before breaking the line
|
|
|
|
|
unless inside a list. Signal an error if within a single-quoted
|
|
|
|
|
string."
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(interactive)
|
2013-05-24 19:37:55 +00:00
|
|
|
|
(funcall comment-line-break-function soft))
|
|
|
|
|
|
|
|
|
|
(defun octave--indent-new-comment-line (orig &rest args)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(cond
|
2013-05-21 09:43:14 +00:00
|
|
|
|
((octave-in-comment-p) nil)
|
|
|
|
|
((eq (octave-in-string-p) ?')
|
|
|
|
|
(error "Cannot split a single-quoted string"))
|
|
|
|
|
((eq (octave-in-string-p) ?\")
|
|
|
|
|
(insert octave-continuation-string))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(t
|
2013-05-21 09:43:14 +00:00
|
|
|
|
(delete-horizontal-space)
|
|
|
|
|
(unless (and (cadr (syntax-ppss))
|
|
|
|
|
(eq (char-after (cadr (syntax-ppss))) ?\())
|
|
|
|
|
(insert " " octave-continuation-string))))
|
2013-05-24 19:37:55 +00:00
|
|
|
|
(apply orig args)
|
2013-05-21 09:43:14 +00:00
|
|
|
|
(indent-according-to-mode))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-05-16 08:52:02 +00:00
|
|
|
|
(define-obsolete-function-alias
|
|
|
|
|
'octave-indent-defun 'prog-indent-sexp "24.4")
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
;;; Motion
|
|
|
|
|
(defun octave-next-code-line (&optional arg)
|
|
|
|
|
"Move ARG lines of Octave code forward (backward if ARG is negative).
|
|
|
|
|
Skips past all empty and comment lines. Default for ARG is 1.
|
|
|
|
|
|
|
|
|
|
On success, return 0. Otherwise, go as far as possible and return -1."
|
|
|
|
|
(interactive "p")
|
|
|
|
|
(or arg (setq arg 1))
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(let ((n 0)
|
|
|
|
|
(inc (if (> arg 0) 1 -1)))
|
|
|
|
|
(while (and (/= arg 0) (= n 0))
|
|
|
|
|
(setq n (forward-line inc))
|
|
|
|
|
(while (and (= n 0)
|
|
|
|
|
(looking-at "\\s-*\\($\\|\\s<\\)"))
|
|
|
|
|
(setq n (forward-line inc)))
|
|
|
|
|
(setq arg (- arg inc)))
|
|
|
|
|
n))
|
2003-02-04 13:24:35 +00:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(defun octave-previous-code-line (&optional arg)
|
|
|
|
|
"Move ARG lines of Octave code backward (forward if ARG is negative).
|
|
|
|
|
Skips past all empty and comment lines. Default for ARG is 1.
|
|
|
|
|
|
|
|
|
|
On success, return 0. Otherwise, go as far as possible and return -1."
|
|
|
|
|
(interactive "p")
|
|
|
|
|
(or arg (setq arg 1))
|
|
|
|
|
(octave-next-code-line (- arg)))
|
|
|
|
|
|
|
|
|
|
(defun octave-beginning-of-line ()
|
|
|
|
|
"Move point to beginning of current Octave line.
|
|
|
|
|
If on an empty or comment line, go to the beginning of that line.
|
|
|
|
|
Otherwise, move backward to the beginning of the first Octave code line
|
|
|
|
|
which is not inside a continuation statement, i.e., which does not
|
2013-05-11 03:50:34 +00:00
|
|
|
|
follow a code line ending with `...' or is inside an open
|
1997-01-21 00:29:57 +00:00
|
|
|
|
parenthesis list."
|
|
|
|
|
(interactive)
|
|
|
|
|
(beginning-of-line)
|
2013-05-11 03:50:34 +00:00
|
|
|
|
(unless (looking-at "\\s-*\\($\\|\\s<\\)")
|
|
|
|
|
(while (or (when (cadr (syntax-ppss))
|
|
|
|
|
(goto-char (cadr (syntax-ppss)))
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
t)
|
|
|
|
|
(and (or (looking-at "\\s-*\\($\\|\\s<\\)")
|
|
|
|
|
(save-excursion
|
|
|
|
|
(if (zerop (octave-previous-code-line))
|
|
|
|
|
(looking-at octave-continuation-regexp))))
|
|
|
|
|
(zerop (forward-line -1)))))))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
(defun octave-end-of-line ()
|
|
|
|
|
"Move point to end of current Octave line.
|
|
|
|
|
If on an empty or comment line, go to the end of that line.
|
|
|
|
|
Otherwise, move forward to the end of the first Octave code line which
|
2013-05-11 03:50:34 +00:00
|
|
|
|
does not end with `...' or is inside an open parenthesis list."
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(interactive)
|
|
|
|
|
(end-of-line)
|
2013-05-11 03:50:34 +00:00
|
|
|
|
(unless (save-excursion
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(looking-at "\\s-*\\($\\|\\s<\\)"))
|
|
|
|
|
(while (or (when (cadr (syntax-ppss))
|
|
|
|
|
(condition-case nil
|
|
|
|
|
(progn
|
|
|
|
|
(up-list 1)
|
|
|
|
|
(end-of-line)
|
|
|
|
|
t)
|
|
|
|
|
(error nil)))
|
|
|
|
|
(and (save-excursion
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(or (looking-at "\\s-*\\($\\|\\s<\\)")
|
|
|
|
|
(looking-at octave-continuation-regexp)))
|
|
|
|
|
(zerop (forward-line 1)))))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(end-of-line)))
|
2003-02-04 13:24:35 +00:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(defun octave-mark-block ()
|
|
|
|
|
"Put point at the beginning of this Octave block, mark at the end.
|
|
|
|
|
The block marked is the one that contains point or follows point."
|
|
|
|
|
(interactive)
|
2012-12-05 05:30:58 +00:00
|
|
|
|
(if (and (looking-at "\\sw\\|\\s_")
|
|
|
|
|
(looking-back "\\sw\\|\\s_" (1- (point))))
|
|
|
|
|
(skip-syntax-forward "w_"))
|
Remove old indentation and navigation code on octave-mode.
* lisp/progmodes/octave-mod.el (octave-mode-map): Remap down-list to
smie-down-list rather than add a binding for octave-down-block.
(octave-mark-block, octave-blink-matching-block-open):
Rely on forward-sexp-function.
(octave-fill-paragraph): Don't narrow, so you can use
indent-according-to-mode.
(octave-block-begin-regexp, octave-block-begin-or-end-regexp): Remove.
(octave-in-block-p, octave-re-search-forward-kw)
(octave-re-search-backward-kw, octave-indent-calculate)
(octave-end-as-array-index-p, octave-block-end-offset)
(octave-scan-blocks, octave-forward-block, octave-backward-block)
(octave-down-block, octave-backward-up-block, octave-up-block)
(octave-before-magic-comment-p, octave-indent-line): Remove.
2010-08-31 12:13:51 +00:00
|
|
|
|
(unless (or (looking-at "\\s(")
|
|
|
|
|
(save-excursion
|
|
|
|
|
(let* ((token (funcall smie-forward-token-function))
|
2010-11-10 08:21:06 +00:00
|
|
|
|
(level (assoc token smie-grammar)))
|
2012-12-05 05:30:58 +00:00
|
|
|
|
(and level (not (numberp (cadr level)))))))
|
Remove old indentation and navigation code on octave-mode.
* lisp/progmodes/octave-mod.el (octave-mode-map): Remap down-list to
smie-down-list rather than add a binding for octave-down-block.
(octave-mark-block, octave-blink-matching-block-open):
Rely on forward-sexp-function.
(octave-fill-paragraph): Don't narrow, so you can use
indent-according-to-mode.
(octave-block-begin-regexp, octave-block-begin-or-end-regexp): Remove.
(octave-in-block-p, octave-re-search-forward-kw)
(octave-re-search-backward-kw, octave-indent-calculate)
(octave-end-as-array-index-p, octave-block-end-offset)
(octave-scan-blocks, octave-forward-block, octave-backward-block)
(octave-down-block, octave-backward-up-block, octave-up-block)
(octave-before-magic-comment-p, octave-indent-line): Remove.
2010-08-31 12:13:51 +00:00
|
|
|
|
(backward-up-list 1))
|
|
|
|
|
(mark-sexp))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
(defun octave-beginning-of-defun (&optional arg)
|
2013-05-10 06:26:42 +00:00
|
|
|
|
"Octave-specific `beginning-of-defun-function' (which see)."
|
|
|
|
|
(or arg (setq arg 1))
|
|
|
|
|
;; Move out of strings or comments.
|
|
|
|
|
(when (octave-in-string-or-comment-p)
|
|
|
|
|
(goto-char (octave-in-string-or-comment-p)))
|
|
|
|
|
(letrec ((orig (point))
|
|
|
|
|
(toplevel (lambda (pos)
|
|
|
|
|
(condition-case nil
|
|
|
|
|
(progn
|
|
|
|
|
(backward-up-list 1)
|
|
|
|
|
(funcall toplevel (point)))
|
|
|
|
|
(scan-error pos)))))
|
|
|
|
|
(goto-char (funcall toplevel (point)))
|
|
|
|
|
(when (and (> arg 0) (/= orig (point)))
|
|
|
|
|
(setq arg (1- arg)))
|
|
|
|
|
(forward-sexp (- arg))
|
2013-05-21 09:43:14 +00:00
|
|
|
|
(and (< arg 0) (forward-sexp -1))
|
2013-05-10 06:26:42 +00:00
|
|
|
|
(/= orig (point))))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2011-04-22 18:44:26 +00:00
|
|
|
|
(defun octave-fill-paragraph (&optional _arg)
|
Remove old indentation and navigation code on octave-mode.
* lisp/progmodes/octave-mod.el (octave-mode-map): Remap down-list to
smie-down-list rather than add a binding for octave-down-block.
(octave-mark-block, octave-blink-matching-block-open):
Rely on forward-sexp-function.
(octave-fill-paragraph): Don't narrow, so you can use
indent-according-to-mode.
(octave-block-begin-regexp, octave-block-begin-or-end-regexp): Remove.
(octave-in-block-p, octave-re-search-forward-kw)
(octave-re-search-backward-kw, octave-indent-calculate)
(octave-end-as-array-index-p, octave-block-end-offset)
(octave-scan-blocks, octave-forward-block, octave-backward-block)
(octave-down-block, octave-backward-up-block, octave-up-block)
(octave-before-magic-comment-p, octave-indent-line): Remove.
2010-08-31 12:13:51 +00:00
|
|
|
|
"Fill paragraph of Octave code, handling Octave comments."
|
|
|
|
|
;; FIXME: difference with generic fill-paragraph:
|
|
|
|
|
;; - code lines are only split, never joined.
|
|
|
|
|
;; - \n that end comments are never removed.
|
|
|
|
|
;; - insert continuation marker when splitting code lines.
|
|
|
|
|
(interactive "P")
|
|
|
|
|
(save-excursion
|
|
|
|
|
(let ((end (progn (forward-paragraph) (copy-marker (point) t)))
|
|
|
|
|
(beg (progn
|
|
|
|
|
(forward-paragraph -1)
|
|
|
|
|
(skip-chars-forward " \t\n")
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(point)))
|
|
|
|
|
(cfc (current-fill-column))
|
|
|
|
|
comment-prefix)
|
|
|
|
|
(goto-char beg)
|
|
|
|
|
(while (< (point) end)
|
|
|
|
|
(condition-case nil
|
|
|
|
|
(indent-according-to-mode)
|
|
|
|
|
(error nil))
|
|
|
|
|
(move-to-column cfc)
|
|
|
|
|
;; First check whether we need to combine non-empty comment lines
|
|
|
|
|
(if (and (< (current-column) cfc)
|
|
|
|
|
(octave-in-comment-p)
|
|
|
|
|
(not (save-excursion
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(looking-at "^\\s-*\\s<+\\s-*$"))))
|
|
|
|
|
;; This is a nonempty comment line which does not extend
|
|
|
|
|
;; past the fill column. If it is followed by a nonempty
|
|
|
|
|
;; comment line with the same comment prefix, try to
|
|
|
|
|
;; combine them, and repeat this until either we reach the
|
|
|
|
|
;; fill-column or there is nothing more to combine.
|
|
|
|
|
(progn
|
|
|
|
|
;; Get the comment prefix
|
|
|
|
|
(save-excursion
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(while (and (re-search-forward "\\s<+")
|
|
|
|
|
(not (octave-in-comment-p))))
|
|
|
|
|
(setq comment-prefix (match-string 0)))
|
|
|
|
|
;; And keep combining ...
|
|
|
|
|
(while (and (< (current-column) cfc)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(forward-line 1)
|
|
|
|
|
(and (looking-at
|
|
|
|
|
(concat "^\\s-*"
|
|
|
|
|
comment-prefix
|
|
|
|
|
"\\S<"))
|
|
|
|
|
(not (looking-at
|
|
|
|
|
(concat "^\\s-*"
|
|
|
|
|
comment-prefix
|
|
|
|
|
"\\s-*$"))))))
|
|
|
|
|
(delete-char 1)
|
|
|
|
|
(re-search-forward comment-prefix)
|
|
|
|
|
(delete-region (match-beginning 0) (match-end 0))
|
|
|
|
|
(fixup-whitespace)
|
|
|
|
|
(move-to-column cfc))))
|
|
|
|
|
;; We might also try to combine continued code lines> Perhaps
|
|
|
|
|
;; some other time ...
|
|
|
|
|
(skip-chars-forward "^ \t\n")
|
|
|
|
|
(delete-horizontal-space)
|
|
|
|
|
(if (or (< (current-column) cfc)
|
|
|
|
|
(and (= (current-column) cfc) (eolp)))
|
|
|
|
|
(forward-line 1)
|
|
|
|
|
(if (not (eolp)) (insert " "))
|
2013-05-21 23:05:16 +00:00
|
|
|
|
(or (funcall normal-auto-fill-function)
|
Remove old indentation and navigation code on octave-mode.
* lisp/progmodes/octave-mod.el (octave-mode-map): Remap down-list to
smie-down-list rather than add a binding for octave-down-block.
(octave-mark-block, octave-blink-matching-block-open):
Rely on forward-sexp-function.
(octave-fill-paragraph): Don't narrow, so you can use
indent-according-to-mode.
(octave-block-begin-regexp, octave-block-begin-or-end-regexp): Remove.
(octave-in-block-p, octave-re-search-forward-kw)
(octave-re-search-backward-kw, octave-indent-calculate)
(octave-end-as-array-index-p, octave-block-end-offset)
(octave-scan-blocks, octave-forward-block, octave-backward-block)
(octave-down-block, octave-backward-up-block, octave-up-block)
(octave-before-magic-comment-p, octave-indent-line): Remove.
2010-08-31 12:13:51 +00:00
|
|
|
|
(forward-line 1))))
|
|
|
|
|
t)))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-05-06 23:46:07 +00:00
|
|
|
|
(defun octave-completion-at-point ()
|
2010-08-12 11:22:16 +00:00
|
|
|
|
"Find the text to complete and the corresponding table."
|
2011-04-25 16:29:31 +00:00
|
|
|
|
(let* ((beg (save-excursion (skip-syntax-backward "w_") (point)))
|
2010-08-17 15:49:30 +00:00
|
|
|
|
(end (point)))
|
|
|
|
|
(if (< beg (point))
|
|
|
|
|
;; Extend region past point, if applicable.
|
2011-04-25 16:29:31 +00:00
|
|
|
|
(save-excursion (skip-syntax-forward "w_")
|
|
|
|
|
(setq end (point))))
|
2013-05-06 23:46:07 +00:00
|
|
|
|
(when (> end beg)
|
|
|
|
|
(list beg end (or (and inferior-octave-process
|
|
|
|
|
(process-live-p inferior-octave-process)
|
2013-05-10 06:26:42 +00:00
|
|
|
|
inferior-octave-completion-table)
|
2013-05-06 23:46:07 +00:00
|
|
|
|
octave-reserved-words)))))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
Use completion-at-point rather than completion-in-region.
* lisp/wid-edit.el: Use lexical scoping and move towards completion-at-point.
(widget-complete): Use new :completion-function property.
(widget-completions-at-point): New function.
(default): Use :completion-function instead of :complete.
(widget-default-completions): Rename from widget-default-complete, rewrite.
(widget-string-complete, widget-file-complete, widget-color-complete):
Remove functions.
(file, symbol, function, variable, coding-system, color):
* lisp/international/mule-cmds.el (default-input-method, charset)
(language-info-custom-alist):
* lisp/cus-edit.el (face): Use new property :completions.
* lisp/progmodes/pascal.el (pascal-completions-at-point): New function.
(pascal-mode): Use it.
(pascal-mode-map): Use completion-at-point.
(pascal-toggle-completions): Make obsolete.
(pascal-complete-word, pascal-show-completions):
* lisp/progmodes/octave-mod.el (octave-complete-symbol):
Redefine as obsolete alias.
* lisp/progmodes/octave-inf.el (inferior-octave-completion-at-point):
Signal absence of completion info for old Octave,
(inferior-octave-complete): Redefine as obsolete alias.
* lisp/progmodes/meta-mode.el: Use lexical-binding and completion-at-point.
(meta-completions-at-point): Rename from meta-complete-symbol and
adapt it for use on completion-at-point-functions.
(meta-common-mode): Use it.
(meta-looking-at-backward, meta-match-buffer): Remove.
(meta-complete-symbol): Redefine as obsolete alias.
(meta-common-mode-map): Use completion-at-point.
* lisp/progmodes/make-mode.el: Use lexical-binding and completion-at-point.
(makefile-mode-map): Use completion-at-point.
(makefile-completions-at-point): Rename from makefile-complete and
adapt it for use on completion-at-point-functions.
(makefile-mode): Use it.
(makefile-complete): Redefine as obsolete alias.
2011-06-20 16:02:31 +00:00
|
|
|
|
(define-obsolete-function-alias 'octave-complete-symbol
|
|
|
|
|
'completion-at-point "24.1")
|
2013-06-08 13:35:55 +00:00
|
|
|
|
|
|
|
|
|
(defun octave-add-log-current-defun ()
|
|
|
|
|
"A function for `add-log-current-defun-function' (which see)."
|
|
|
|
|
(save-excursion
|
|
|
|
|
(end-of-line)
|
|
|
|
|
(and (beginning-of-defun)
|
|
|
|
|
(re-search-forward octave-function-header-regexp
|
|
|
|
|
(line-end-position) t)
|
|
|
|
|
(match-string 3))))
|
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
;;; Electric characters && friends
|
2010-08-12 11:22:16 +00:00
|
|
|
|
(define-skeleton octave-insert-defun
|
1997-01-21 00:29:57 +00:00
|
|
|
|
"Insert an Octave function skeleton.
|
|
|
|
|
Prompt for the function's name, arguments and return values (to be
|
|
|
|
|
entered without parens)."
|
2013-04-26 04:16:37 +00:00
|
|
|
|
(let* ((defname (file-name-sans-extension (buffer-name)))
|
2010-08-12 11:22:16 +00:00
|
|
|
|
(name (read-string (format "Function name (default %s): " defname)
|
|
|
|
|
nil nil defname))
|
|
|
|
|
(args (read-string "Arguments: "))
|
|
|
|
|
(vals (read-string "Return values: ")))
|
|
|
|
|
(format "%s%s (%s)"
|
|
|
|
|
(cond
|
|
|
|
|
((string-equal vals "") vals)
|
|
|
|
|
((string-match "[ ,]" vals) (concat "[" vals "] = "))
|
|
|
|
|
(t (concat vals " = ")))
|
|
|
|
|
name
|
|
|
|
|
args))
|
2013-04-27 17:07:01 +00:00
|
|
|
|
\n octave-block-comment-start "usage: " str \n
|
|
|
|
|
octave-block-comment-start '(delete-horizontal-space) \n
|
|
|
|
|
octave-block-comment-start '(delete-horizontal-space) \n
|
|
|
|
|
"function " > str \n
|
|
|
|
|
_ \n
|
2010-08-12 11:22:16 +00:00
|
|
|
|
"endfunction" > \n)
|
2013-06-08 13:35:55 +00:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
;;; Communication with the inferior Octave process
|
|
|
|
|
(defun octave-kill-process ()
|
|
|
|
|
"Kill inferior Octave process and its buffer."
|
|
|
|
|
(interactive)
|
|
|
|
|
(if inferior-octave-process
|
|
|
|
|
(progn
|
|
|
|
|
(process-send-string inferior-octave-process "quit;\n")
|
|
|
|
|
(accept-process-output inferior-octave-process)))
|
|
|
|
|
(if inferior-octave-buffer
|
|
|
|
|
(kill-buffer inferior-octave-buffer)))
|
|
|
|
|
|
|
|
|
|
(defun octave-show-process-buffer ()
|
|
|
|
|
"Make sure that `inferior-octave-buffer' is displayed."
|
|
|
|
|
(interactive)
|
|
|
|
|
(if (get-buffer inferior-octave-buffer)
|
|
|
|
|
(display-buffer inferior-octave-buffer)
|
|
|
|
|
(message "No buffer named %s" inferior-octave-buffer)))
|
|
|
|
|
|
|
|
|
|
(defun octave-hide-process-buffer ()
|
|
|
|
|
"Delete all windows that display `inferior-octave-buffer'."
|
|
|
|
|
(interactive)
|
|
|
|
|
(if (get-buffer inferior-octave-buffer)
|
|
|
|
|
(delete-windows-on inferior-octave-buffer)
|
|
|
|
|
(message "No buffer named %s" inferior-octave-buffer)))
|
|
|
|
|
|
|
|
|
|
(defun octave-send-region (beg end)
|
|
|
|
|
"Send current region to the inferior Octave process."
|
|
|
|
|
(interactive "r")
|
2003-02-04 13:24:35 +00:00
|
|
|
|
(inferior-octave t)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(let ((proc inferior-octave-process)
|
2013-05-05 04:49:27 +00:00
|
|
|
|
(string (buffer-substring-no-properties beg end))
|
|
|
|
|
line)
|
2008-04-30 08:48:02 +00:00
|
|
|
|
(with-current-buffer inferior-octave-buffer
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(setq inferior-octave-output-list nil)
|
|
|
|
|
(while (not (string-equal string ""))
|
2013-05-05 04:49:27 +00:00
|
|
|
|
(if (string-match "\n" string)
|
|
|
|
|
(setq line (substring string 0 (match-beginning 0))
|
|
|
|
|
string (substring string (match-end 0)))
|
|
|
|
|
(setq line string string ""))
|
|
|
|
|
(setq inferior-octave-receive-in-progress t)
|
|
|
|
|
(inferior-octave-send-list-and-digest (list (concat line "\n")))
|
|
|
|
|
(while inferior-octave-receive-in-progress
|
|
|
|
|
(accept-process-output proc))
|
|
|
|
|
(insert-before-markers
|
|
|
|
|
(mapconcat 'identity
|
|
|
|
|
(append
|
|
|
|
|
(if octave-send-echo-input (list line) (list ""))
|
|
|
|
|
inferior-octave-output-list
|
|
|
|
|
(list inferior-octave-output-string))
|
|
|
|
|
"\n")))))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(if octave-send-show-buffer
|
|
|
|
|
(display-buffer inferior-octave-buffer)))
|
|
|
|
|
|
|
|
|
|
(defun octave-send-block ()
|
2003-02-04 13:24:35 +00:00
|
|
|
|
"Send current Octave block to the inferior Octave process."
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(interactive)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(octave-mark-block)
|
|
|
|
|
(octave-send-region (point) (mark))))
|
|
|
|
|
|
|
|
|
|
(defun octave-send-defun ()
|
|
|
|
|
"Send current Octave function to the inferior Octave process."
|
|
|
|
|
(interactive)
|
|
|
|
|
(save-excursion
|
2010-08-17 15:49:30 +00:00
|
|
|
|
(mark-defun)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(octave-send-region (point) (mark))))
|
|
|
|
|
|
|
|
|
|
(defun octave-send-line (&optional arg)
|
|
|
|
|
"Send current Octave code line to the inferior Octave process.
|
|
|
|
|
With positive prefix ARG, send that many lines.
|
|
|
|
|
If `octave-send-line-auto-forward' is non-nil, go to the next unsent
|
|
|
|
|
code line."
|
|
|
|
|
(interactive "P")
|
|
|
|
|
(or arg (setq arg 1))
|
|
|
|
|
(if (> arg 0)
|
|
|
|
|
(let (beg end)
|
|
|
|
|
(beginning-of-line)
|
|
|
|
|
(setq beg (point))
|
|
|
|
|
(octave-next-code-line (- arg 1))
|
|
|
|
|
(end-of-line)
|
|
|
|
|
(setq end (point))
|
|
|
|
|
(if octave-send-line-auto-forward
|
|
|
|
|
(octave-next-code-line 1))
|
|
|
|
|
(octave-send-region beg end))))
|
|
|
|
|
|
|
|
|
|
(defun octave-eval-print-last-sexp ()
|
|
|
|
|
"Evaluate Octave sexp before point and print value into current buffer."
|
|
|
|
|
(interactive)
|
|
|
|
|
(inferior-octave t)
|
|
|
|
|
(let ((standard-output (current-buffer))
|
|
|
|
|
(print-escape-newlines nil)
|
|
|
|
|
(opoint (point)))
|
|
|
|
|
(terpri)
|
2003-02-04 13:24:35 +00:00
|
|
|
|
(prin1
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(save-excursion
|
|
|
|
|
(forward-sexp -1)
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
|
|
|
|
(list (concat (buffer-substring-no-properties (point) opoint)
|
|
|
|
|
"\n")))
|
|
|
|
|
(mapconcat 'identity inferior-octave-output-list "\n")))
|
|
|
|
|
(terpri)))
|
2013-04-26 04:16:37 +00:00
|
|
|
|
|
2013-05-03 07:22:26 +00:00
|
|
|
|
|
|
|
|
|
|
2013-05-11 13:22:06 +00:00
|
|
|
|
(defcustom octave-eldoc-message-style 'auto
|
|
|
|
|
"Octave eldoc message style: auto, oneline, multiline."
|
|
|
|
|
:type '(choice (const :tag "Automatic" auto)
|
|
|
|
|
(const :tag "One Line" oneline)
|
|
|
|
|
(const :tag "Multi Line" multiline))
|
|
|
|
|
:group 'octave
|
|
|
|
|
:version "24.4")
|
|
|
|
|
|
|
|
|
|
;; (FN SIGNATURE1 SIGNATURE2 ...)
|
|
|
|
|
(defvar octave-eldoc-cache nil)
|
|
|
|
|
|
|
|
|
|
(defun octave-eldoc-function-signatures (fn)
|
|
|
|
|
(unless (equal fn (car octave-eldoc-cache))
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(list (format "print_usage ('%s');\n" fn)))
|
2013-05-11 13:22:06 +00:00
|
|
|
|
(let (result)
|
|
|
|
|
(dolist (line inferior-octave-output-list)
|
|
|
|
|
(when (string-match
|
|
|
|
|
"\\s-*\\(?:--[^:]+\\|usage\\):\\s-*\\(.*\\)$"
|
|
|
|
|
line)
|
|
|
|
|
(push (match-string 1 line) result)))
|
|
|
|
|
(setq octave-eldoc-cache
|
|
|
|
|
(cons (substring-no-properties fn)
|
|
|
|
|
(nreverse result)))))
|
|
|
|
|
(cdr octave-eldoc-cache))
|
|
|
|
|
|
|
|
|
|
(defun octave-eldoc-function ()
|
|
|
|
|
"A function for `eldoc-documentation-function' (which see)."
|
|
|
|
|
(when (and inferior-octave-process
|
|
|
|
|
(process-live-p inferior-octave-process))
|
|
|
|
|
(let* ((ppss (syntax-ppss))
|
|
|
|
|
(paren-pos (cadr ppss))
|
|
|
|
|
(fn (save-excursion
|
|
|
|
|
(if (and paren-pos
|
|
|
|
|
;; PAREN-POS must be after the prompt
|
|
|
|
|
(>= paren-pos
|
|
|
|
|
(if (eq (get-buffer-process (current-buffer))
|
|
|
|
|
inferior-octave-process)
|
|
|
|
|
(process-mark inferior-octave-process)
|
|
|
|
|
(point-min)))
|
|
|
|
|
(or (not (eq (get-buffer-process (current-buffer))
|
|
|
|
|
inferior-octave-process))
|
|
|
|
|
(< (process-mark inferior-octave-process)
|
|
|
|
|
paren-pos))
|
|
|
|
|
(eq (char-after paren-pos) ?\())
|
|
|
|
|
(goto-char paren-pos)
|
|
|
|
|
(setq paren-pos nil))
|
|
|
|
|
(when (or (< (skip-syntax-backward "-") 0) paren-pos)
|
|
|
|
|
(thing-at-point 'symbol))))
|
|
|
|
|
(sigs (and fn (octave-eldoc-function-signatures fn)))
|
|
|
|
|
(oneline (mapconcat 'identity sigs
|
|
|
|
|
(propertize " | " 'face 'warning)))
|
|
|
|
|
(multiline (mapconcat (lambda (s) (concat "-- " s)) sigs "\n")))
|
|
|
|
|
;;
|
|
|
|
|
;; Return the value according to style.
|
|
|
|
|
(pcase octave-eldoc-message-style
|
|
|
|
|
(`auto (if (< (length oneline) (window-width (minibuffer-window)))
|
|
|
|
|
oneline
|
|
|
|
|
multiline))
|
|
|
|
|
(`oneline oneline)
|
|
|
|
|
(`multiline multiline)))))
|
|
|
|
|
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(defcustom octave-help-buffer "*Octave Help*"
|
|
|
|
|
"Buffer name for `octave-help'."
|
|
|
|
|
:type 'string
|
|
|
|
|
:group 'octave
|
|
|
|
|
:version "24.4")
|
|
|
|
|
|
|
|
|
|
(define-button-type 'octave-help-file
|
|
|
|
|
'follow-link t
|
|
|
|
|
'action #'help-button-action
|
2013-05-05 04:49:27 +00:00
|
|
|
|
'help-function 'octave-find-definition)
|
2013-05-03 07:22:26 +00:00
|
|
|
|
|
|
|
|
|
(define-button-type 'octave-help-function
|
|
|
|
|
'follow-link t
|
|
|
|
|
'action (lambda (b)
|
|
|
|
|
(octave-help
|
|
|
|
|
(buffer-substring (button-start b) (button-end b)))))
|
|
|
|
|
|
2013-05-20 22:52:40 +00:00
|
|
|
|
(defvar octave-help-mode-map
|
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
|
(define-key map "\M-." 'octave-find-definition)
|
|
|
|
|
(define-key map "\C-hd" 'octave-help)
|
|
|
|
|
map))
|
|
|
|
|
|
|
|
|
|
(define-derived-mode octave-help-mode help-mode "OctHelp"
|
|
|
|
|
"Major mode for displaying Octave documentation."
|
|
|
|
|
:abbrev-table nil
|
|
|
|
|
:syntax-table octave-mode-syntax-table
|
|
|
|
|
(eval-and-compile (require 'help-mode))
|
|
|
|
|
;; Mostly stolen from `help-make-xrefs'.
|
|
|
|
|
(let ((inhibit-read-only t))
|
|
|
|
|
(setq-local info-lookup-mode 'octave-mode)
|
|
|
|
|
;; Delete extraneous newlines at the end of the docstring
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(while (and (not (bobp)) (bolp))
|
|
|
|
|
(delete-char -1))
|
|
|
|
|
(insert "\n")
|
|
|
|
|
(when (or help-xref-stack help-xref-forward-stack)
|
|
|
|
|
(insert "\n"))
|
|
|
|
|
(when help-xref-stack
|
|
|
|
|
(help-insert-xref-button help-back-label 'help-back
|
|
|
|
|
(current-buffer)))
|
|
|
|
|
(when help-xref-forward-stack
|
|
|
|
|
(when help-xref-stack
|
|
|
|
|
(insert "\t"))
|
|
|
|
|
(help-insert-xref-button help-forward-label 'help-forward
|
|
|
|
|
(current-buffer)))
|
|
|
|
|
(when (or help-xref-stack help-xref-forward-stack)
|
|
|
|
|
(insert "\n"))))
|
|
|
|
|
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(defun octave-help (fn)
|
|
|
|
|
"Display the documentation of FN."
|
|
|
|
|
(interactive (list (octave-completing-read)))
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(list (format "help ('%s');\n" fn)))
|
2013-05-20 22:52:40 +00:00
|
|
|
|
(let ((lines inferior-octave-output-list)
|
|
|
|
|
(inhibit-read-only t))
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(when (string-match "error: \\(.*\\)$" (car lines))
|
|
|
|
|
(error "%s" (match-string 1 (car lines))))
|
|
|
|
|
(with-help-window octave-help-buffer
|
|
|
|
|
(princ (mapconcat 'identity lines "\n"))
|
|
|
|
|
(with-current-buffer octave-help-buffer
|
|
|
|
|
;; Bound to t so that `help-buffer' returns current buffer for
|
|
|
|
|
;; `help-setup-xref'.
|
|
|
|
|
(let ((help-xref-following t))
|
|
|
|
|
(help-setup-xref (list 'octave-help fn)
|
|
|
|
|
(called-interactively-p 'interactive)))
|
|
|
|
|
;; Note: can be turned off by suppress_verbose_help_message.
|
|
|
|
|
;;
|
|
|
|
|
;; Remove boring trailing text: Additional help for built-in functions
|
|
|
|
|
;; and operators ...
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(when (search-backward "\n\n\n" nil t)
|
|
|
|
|
(goto-char (match-beginning 0))
|
|
|
|
|
(delete-region (point) (point-max)))
|
|
|
|
|
;; File name highlight
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(when (re-search-forward "from the file \\(.*\\)$"
|
|
|
|
|
(line-end-position)
|
|
|
|
|
t)
|
2013-05-21 09:43:14 +00:00
|
|
|
|
(let* ((file (match-string 1))
|
|
|
|
|
(dir (file-name-directory
|
|
|
|
|
(directory-file-name (file-name-directory file)))))
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(replace-match "" nil nil nil 1)
|
|
|
|
|
(insert "`")
|
2013-05-21 09:43:14 +00:00
|
|
|
|
;; Include the parent directory which may be regarded as
|
|
|
|
|
;; the category for the FN.
|
|
|
|
|
(help-insert-xref-button (file-relative-name file dir)
|
2013-05-05 04:49:27 +00:00
|
|
|
|
'octave-help-file fn)
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(insert "'")))
|
2013-06-12 02:37:38 +00:00
|
|
|
|
;; Make 'See also' clickable.
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(with-syntax-table octave-mode-syntax-table
|
|
|
|
|
(when (re-search-forward "^\\s-*See also:" nil t)
|
2013-05-29 06:50:48 +00:00
|
|
|
|
(let ((end (save-excursion (re-search-forward "^\\s-*$" nil t))))
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(while (re-search-forward
|
2013-06-19 02:02:30 +00:00
|
|
|
|
"\\s-*\\([^,\n]+?\\)\\s-*\\(?:[,]\\|[.]?$\\)" end t)
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(make-text-button (match-beginning 1) (match-end 1)
|
2013-05-27 05:08:04 +00:00
|
|
|
|
:type 'octave-help-function)))))
|
2013-05-20 22:52:40 +00:00
|
|
|
|
(octave-help-mode)))))
|
2013-05-03 07:22:26 +00:00
|
|
|
|
|
2013-05-12 04:10:40 +00:00
|
|
|
|
(defcustom octave-source-directories nil
|
2013-05-18 01:17:50 +00:00
|
|
|
|
"A list of directories for Octave sources.
|
|
|
|
|
If the environment variable OCTAVE_SRCDIR is set, it is searched first."
|
2013-05-12 04:10:40 +00:00
|
|
|
|
:type '(repeat directory)
|
2013-05-05 04:49:27 +00:00
|
|
|
|
:group 'octave
|
|
|
|
|
:version "24.4")
|
|
|
|
|
|
2013-05-12 04:10:40 +00:00
|
|
|
|
(defun octave-source-directories ()
|
2013-05-18 01:17:50 +00:00
|
|
|
|
(let ((srcdir (or (and inferior-octave-process
|
|
|
|
|
(process-get inferior-octave-process 'octave-srcdir))
|
|
|
|
|
(getenv "OCTAVE_SRCDIR"))))
|
2013-05-12 04:10:40 +00:00
|
|
|
|
(if srcdir
|
|
|
|
|
(cons srcdir octave-source-directories)
|
|
|
|
|
octave-source-directories)))
|
|
|
|
|
|
|
|
|
|
(defvar octave-find-definition-filename-function
|
|
|
|
|
#'octave-find-definition-default-filename)
|
|
|
|
|
|
|
|
|
|
(defun octave-find-definition-default-filename (name)
|
|
|
|
|
"Default value for `octave-find-definition-filename-function'."
|
|
|
|
|
(pcase (file-name-extension name)
|
|
|
|
|
(`"oct"
|
|
|
|
|
(octave-find-definition-default-filename
|
|
|
|
|
(concat "libinterp/dldfcn/"
|
|
|
|
|
(file-name-sans-extension (file-name-nondirectory name))
|
|
|
|
|
".cc")))
|
|
|
|
|
(`"cc"
|
|
|
|
|
(let ((file (or (locate-file name (octave-source-directories))
|
|
|
|
|
(locate-file (file-name-nondirectory name)
|
|
|
|
|
(octave-source-directories)))))
|
|
|
|
|
(or (and file (file-exists-p file))
|
|
|
|
|
(error "File `%s' not found" name))
|
|
|
|
|
file))
|
|
|
|
|
(`"mex"
|
|
|
|
|
(if (yes-or-no-p (format "File `%s' may be binary; open? "
|
|
|
|
|
(file-name-nondirectory name)))
|
|
|
|
|
name
|
|
|
|
|
(user-error "Aborted")))
|
|
|
|
|
(t name)))
|
|
|
|
|
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(defvar find-tag-marker-ring)
|
|
|
|
|
|
|
|
|
|
(defun octave-find-definition (fn)
|
2013-05-12 04:10:40 +00:00
|
|
|
|
"Find the definition of FN.
|
2013-05-18 01:17:50 +00:00
|
|
|
|
Functions implemented in C++ can be found if
|
2013-05-12 04:10:40 +00:00
|
|
|
|
`octave-source-directories' is set correctly."
|
2013-05-03 07:22:26 +00:00
|
|
|
|
(interactive (list (octave-completing-read)))
|
2013-06-08 13:35:55 +00:00
|
|
|
|
(require 'etags)
|
|
|
|
|
(let ((orig (point)))
|
2013-06-12 02:37:38 +00:00
|
|
|
|
(if (and (derived-mode-p 'octave-mode)
|
|
|
|
|
(octave-goto-function-definition fn))
|
2013-06-08 13:35:55 +00:00
|
|
|
|
(ring-insert find-tag-marker-ring (copy-marker orig))
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
|
|
|
|
;; help NAME is more verbose
|
|
|
|
|
(list (format "\
|
2013-06-12 02:37:38 +00:00
|
|
|
|
if iskeyword('%s') disp('`%s'' is a keyword') else which('%s') endif\n"
|
2013-06-08 13:35:55 +00:00
|
|
|
|
fn fn fn)))
|
|
|
|
|
(let (line file)
|
|
|
|
|
;; Skip garbage lines such as
|
|
|
|
|
;; warning: fmincg.m: possible Matlab-style ....
|
|
|
|
|
(while (and (not file) (consp inferior-octave-output-list))
|
|
|
|
|
(setq line (pop inferior-octave-output-list))
|
|
|
|
|
(when (string-match "from the file \\(.*\\)$" line)
|
|
|
|
|
(setq file (match-string 1 line))))
|
|
|
|
|
(if (not file)
|
|
|
|
|
(user-error "%s" (or line (format "`%s' not found" fn)))
|
|
|
|
|
(ring-insert find-tag-marker-ring (point-marker))
|
|
|
|
|
(setq file (funcall octave-find-definition-filename-function file))
|
|
|
|
|
(when file
|
|
|
|
|
(find-file file)
|
|
|
|
|
(octave-goto-function-definition fn)))))))
|
2013-05-03 07:22:26 +00:00
|
|
|
|
|
2013-04-25 14:51:08 +00:00
|
|
|
|
(provide 'octave)
|
|
|
|
|
;;; octave.el ends here
|