2013-09-28 11:15:56 +08:00
|
|
|
|
;;; octave.el --- editing octave source files under emacs -*- lexical-binding: t; -*-
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2020-01-01 00:19:43 +00:00
|
|
|
|
;; Copyright (C) 1997, 2001-2020 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 12:24:24 -08:00
|
|
|
|
;; John Eaton <jwe@octave.org>
|
2019-05-25 13:43:06 -07:00
|
|
|
|
;; Maintainer: emacs-devel@gnu.org
|
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
|
2017-09-13 15:52:52 -07:00
|
|
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
2013-09-28 10:41:48 +08:00
|
|
|
|
;; This package provides Emacs support for Octave. It defines a major
|
2013-05-05 23:29:51 +08:00
|
|
|
|
;; 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 22:51:08 +08: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 22:51:08 +08:00
|
|
|
|
(require 'comint)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
1998-01-26 11:29:46 +00:00
|
|
|
|
(defgroup octave nil
|
2013-04-25 22:51:08 +08:00
|
|
|
|
"Editing Octave code."
|
2013-12-20 02:50:46 +01:00
|
|
|
|
:link '(custom-manual "(octave-mode)Top")
|
2017-09-13 15:52:52 -07:00
|
|
|
|
:link '(url-link "https://www.gnu.org/s/octave")
|
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 12:16:37 +08: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 14:13:20 +08: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 14:13:20 +08: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 14:13:20 +08:00
|
|
|
|
|
2013-05-18 06:46:10 +08:00
|
|
|
|
(defvar octave-comment-start (char-to-string octave-comment-char)
|
|
|
|
|
"Octave-specific `comment-start' (which see).")
|
2013-05-01 14:13:20 +08:00
|
|
|
|
|
2013-05-18 06:46:10 +08: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-function-header-regexp
|
2011-04-25 13:29:31 -03:00
|
|
|
|
(concat "^\\s-*\\_<\\(function\\)\\_>"
|
2013-06-07 21:00:47 +08: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 09:36:42 +08: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 14:13:51 +02: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 22:34:52 +02:00
|
|
|
|
(define-key map "\C-c]" 'smie-close-block)
|
|
|
|
|
(define-key map "\C-c/" 'smie-close-block)
|
2013-04-28 01:07:01 +08:00
|
|
|
|
(define-key map "\C-c;" 'octave-update-function-file-comment)
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(define-key map "\C-hd" 'octave-help)
|
2013-09-28 10:30:37 +08:00
|
|
|
|
(define-key map "\C-ha" 'octave-lookfor)
|
2013-11-22 01:18:25 +08:00
|
|
|
|
(define-key map "\C-c\C-l" 'octave-source-file)
|
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)
|
2013-09-28 10:41:48 +08:00
|
|
|
|
(define-key map "\C-c\C-ia" 'octave-send-buffer)
|
2003-01-20 08:59:40 +00:00
|
|
|
|
(define-key map "\C-c\C-is" 'octave-show-process-buffer)
|
2013-04-17 09:49:22 +08: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)
|
2013-09-28 10:41:48 +08:00
|
|
|
|
(define-key map "\C-c\C-i\C-a" 'octave-send-buffer)
|
2003-01-20 08:59:40 +00:00
|
|
|
|
(define-key map "\C-c\C-i\C-s" 'octave-show-process-buffer)
|
2013-04-17 09:46:26 +08: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 17:49:30 +02: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-22 07:05:16 +08: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-22 07:19:03 +08:00
|
|
|
|
["Documentation Lookup" info-lookup-symbol t]
|
2013-05-22 07:05:16 +08:00
|
|
|
|
["Help on Function" octave-help t]
|
2013-09-28 10:30:37 +08:00
|
|
|
|
["Search help" octave-lookfor t]
|
2013-05-22 07:05:16 +08:00
|
|
|
|
["Find Function Definition" octave-find-definition t]
|
|
|
|
|
["Insert Function" octave-insert-defun t]
|
|
|
|
|
["Update Function File Comment" octave-update-function-file-comment t]
|
|
|
|
|
"---"
|
2014-01-12 12:00:03 +08:00
|
|
|
|
["Function Syntax Hints" (eldoc-mode 'toggle)
|
|
|
|
|
:style toggle :selected (bound-and-true-p eldoc-mode)
|
2013-05-22 07:05:16 +08:00
|
|
|
|
:help "Display function signatures after typing `SPC' or `('"]
|
2013-06-05 15:40:02 +08:00
|
|
|
|
["Delimiter Matching" show-paren-mode
|
|
|
|
|
:style toggle :selected show-paren-mode
|
2013-05-22 07:05:16 +08:00
|
|
|
|
:help "Highlight matched pairs such as `if ... end'"
|
2013-06-05 15:40:02 +08:00
|
|
|
|
:visible (fboundp 'smie--matching-block-data)]
|
2013-05-22 07:05:16 +08: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-22 07:05:16 +08: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]
|
2013-09-28 10:41:48 +08:00
|
|
|
|
["Send Buffer" octave-send-buffer t]
|
2013-11-22 01:18:25 +08:00
|
|
|
|
["Source Current File" octave-source-file t]
|
2013-05-22 07:05:16 +08:00
|
|
|
|
["Show Process Buffer" octave-show-process-buffer t]
|
|
|
|
|
["Hide Process Buffer" octave-hide-process-buffer t]
|
|
|
|
|
["Kill Process" octave-kill-process t])
|
|
|
|
|
"---"
|
2013-12-20 02:50:46 +01:00
|
|
|
|
["Octave Mode Manual" (info "(octave-mode)Top") t]
|
2013-05-22 07:05:16 +08:00
|
|
|
|
["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-03 07:03:00 +08: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 11:38:36 +08:00
|
|
|
|
(modify-syntax-entry ?. "." table)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(modify-syntax-entry ?\" "\"" table)
|
2011-04-25 13:29:31 -03:00
|
|
|
|
(modify-syntax-entry ?_ "_" table)
|
2018-10-15 21:24:14 -04:00
|
|
|
|
;; The "b" flag only applies to the second letter of the comstart and
|
|
|
|
|
;; the first letter of the comend, i.e. a "4b" below would be ineffective.
|
2010-08-12 14:46:24 +02:00
|
|
|
|
;; 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 16:44:16 +02:00
|
|
|
|
;; So we need the new "c" comment style.
|
2010-08-12 13:22:16 +02:00
|
|
|
|
(modify-syntax-entry ?\% "< 13" table)
|
|
|
|
|
(modify-syntax-entry ?\# "< 13" table)
|
2010-08-12 16:44:16 +02: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 22:23:03 +08:00
|
|
|
|
(defcustom octave-font-lock-texinfo-comment t
|
|
|
|
|
"Control whether to highlight the texinfo comment block."
|
|
|
|
|
:type 'boolean
|
|
|
|
|
: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."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'boolean)
|
2010-08-17 17:49:30 +02: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."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'integer)
|
2019-07-15 00:01:09 +02:00
|
|
|
|
(put 'octave-block-offset 'safe-local-variable 'integerp)
|
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."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'integer)
|
2013-04-30 04:09:18 +08:00
|
|
|
|
|
2010-08-30 22:34:52 +02:00
|
|
|
|
(eval-and-compile
|
|
|
|
|
(defconst octave-continuation-marker-regexp "\\\\\\|\\.\\.\\."))
|
2013-04-30 04:09:18 +08:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(defvar octave-continuation-regexp
|
2010-08-30 22:34:52 +02:00
|
|
|
|
(concat "[^#%\n]*\\(" octave-continuation-marker-regexp
|
|
|
|
|
"\\)\\s-*\\(\\s<.*\\)?$"))
|
2013-04-30 04:09:18 +08: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."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'hook)
|
1998-01-26 11:29:46 +00:00
|
|
|
|
|
|
|
|
|
(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."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'boolean)
|
2013-05-01 14:13:20 +08: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."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'boolean)
|
2013-05-01 14:13:20 +08: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."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'boolean)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
|
2010-08-30 22:34:52 +02:00
|
|
|
|
;;; SMIE indentation
|
|
|
|
|
|
|
|
|
|
(require 'smie)
|
|
|
|
|
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(let-when-compile
|
|
|
|
|
((operator-table
|
|
|
|
|
;; Use '__operators__' in Octave REPL to get a full list?
|
|
|
|
|
'((assoc ";" "\n") (assoc ",") ;The doc says 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 "...")))
|
|
|
|
|
|
|
|
|
|
(matchedrules
|
|
|
|
|
;; We can't distinguish the first element in a sequence with
|
|
|
|
|
;; precedence grammars, so we can't distinguish the condition
|
|
|
|
|
;; of the `if' from the subsequent body, for example.
|
|
|
|
|
;; This has to be done later in the indentation rules.
|
|
|
|
|
'(("try" exp "catch" exp "end_try_catch")
|
|
|
|
|
("unwind_protect" exp
|
|
|
|
|
"unwind_protect_cleanup" exp "end_unwind_protect")
|
|
|
|
|
("for" exp "endfor")
|
|
|
|
|
("parfor" exp "endparfor")
|
|
|
|
|
("while" exp "endwhile")
|
|
|
|
|
("if" exp "endif")
|
|
|
|
|
("if" exp "else" exp "endif")
|
|
|
|
|
("if" exp "elseif" exp "else" exp "endif")
|
|
|
|
|
("if" exp "elseif" exp "elseif" exp "else" exp "endif")
|
|
|
|
|
("switch" exp "case" exp "endswitch")
|
|
|
|
|
("switch" exp "case" exp "otherwise" exp "endswitch")
|
|
|
|
|
("switch" exp "case" exp "case" exp "otherwise" exp "endswitch")
|
|
|
|
|
("function" exp "endfunction")
|
|
|
|
|
("enumeration" exp "endenumeration")
|
|
|
|
|
("events" exp "endevents")
|
|
|
|
|
("methods" exp "endmethods")
|
|
|
|
|
("properties" exp "endproperties")
|
|
|
|
|
("classdef" exp "endclassdef")
|
2019-07-20 12:05:07 -04:00
|
|
|
|
("spmd" exp "endspmd")
|
2015-09-29 15:13:44 -04:00
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
(bnf-table
|
|
|
|
|
`((atom)
|
|
|
|
|
;; FIXME: We don't parse these declarations correctly since
|
|
|
|
|
;; SMIE *really* likes to parse "a b = 2 c" as "(a b) = (2 c)".
|
|
|
|
|
;; IOW to do it right, we'd need to change octave-smie-*ward-token
|
|
|
|
|
;; so that the spaces between vars in var-decls are lexed as
|
|
|
|
|
;; something like ",".
|
|
|
|
|
;; Doesn't seem worth the trouble/slowdown for now.
|
|
|
|
|
;; We could hack smie-rules so as to work around the bad parse,
|
|
|
|
|
;; but even that doesn't seem worth the trouble.
|
|
|
|
|
(var-decls (atom "=" atom)) ;; (var-decls "," var-decls)
|
|
|
|
|
(single-exp (atom "=" atom))
|
|
|
|
|
(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)
|
|
|
|
|
("do" exp "until" single-exp)
|
|
|
|
|
,@matchedrules
|
|
|
|
|
;; For every rule that ends in "endfoo", add a corresponding
|
|
|
|
|
;; rule which uses "end" instead.
|
|
|
|
|
,@(mapcar (lambda (rule) (nconc (butlast rule) '("end")))
|
|
|
|
|
matchedrules)
|
|
|
|
|
("global" var-decls) ("persistent" var-decls)
|
|
|
|
|
;; These aren't super-important, but having them here
|
|
|
|
|
;; makes it easier to extract all keywords.
|
|
|
|
|
("break") ("continue") ("return")
|
|
|
|
|
;; The following rules do not correspond to valid code AFAIK,
|
|
|
|
|
;; but they lead to a grammar that degrades more gracefully
|
|
|
|
|
;; on incomplete/incorrect code. It also helps us in
|
|
|
|
|
;; computing octave--block-offset-keywords.
|
|
|
|
|
("try" exp "end") ("unwind_protect" exp "end")
|
|
|
|
|
)
|
|
|
|
|
;; (fundesc (atom "=" atom))
|
|
|
|
|
)))
|
2010-09-03 15:28:09 +02:00
|
|
|
|
|
2010-11-07 10:45:45 -05:00
|
|
|
|
(defconst octave-smie-grammar
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(eval-when-compile
|
|
|
|
|
(smie-prec2->grammar
|
|
|
|
|
(smie-merge-prec2s
|
|
|
|
|
(smie-bnf->prec2 bnf-table '((assoc "\n" ";")))
|
|
|
|
|
(smie-precs->prec2 operator-table)))))
|
2010-08-30 22:34:52 +02:00
|
|
|
|
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(defconst octave-operator-regexp
|
|
|
|
|
(eval-when-compile
|
|
|
|
|
(regexp-opt (remove "\n" (apply #'append
|
|
|
|
|
(mapcar #'cdr operator-table)))))))
|
2010-08-30 22:34:52 +02: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).
|
|
|
|
|
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(defun octave-smie--funcall-p ()
|
|
|
|
|
"Return non-nil if we're in an expression context. Moves point."
|
|
|
|
|
(looking-at "[ \t]*("))
|
|
|
|
|
|
|
|
|
|
(defun octave-smie--end-index-p ()
|
|
|
|
|
(let ((ppss (syntax-ppss)))
|
|
|
|
|
(and (nth 1 ppss)
|
|
|
|
|
(memq (char-after (nth 1 ppss)) '(?\( ?\[ ?\{)))))
|
|
|
|
|
|
|
|
|
|
(defun octave-smie--in-parens-p ()
|
|
|
|
|
(let ((ppss (syntax-ppss)))
|
|
|
|
|
(and (nth 1 ppss)
|
|
|
|
|
(eq ?\( (char-after (nth 1 ppss))))))
|
2010-08-30 22:34:52 +02:00
|
|
|
|
|
|
|
|
|
(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)
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(not (octave-smie--in-parens-p)))
|
2010-08-30 22:34:52 +02:00
|
|
|
|
(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
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(let ((tok (smie-default-backward-token)))
|
|
|
|
|
(cond
|
|
|
|
|
((equal tok "enumeration")
|
|
|
|
|
(if (save-excursion (smie-default-forward-token)
|
|
|
|
|
(octave-smie--funcall-p))
|
|
|
|
|
"enumeration (function)"
|
|
|
|
|
tok))
|
|
|
|
|
((equal tok "end") (if (octave-smie--end-index-p) "end (index)" tok))
|
|
|
|
|
(t tok)))))))
|
2010-08-30 22:34:52 +02:00
|
|
|
|
|
|
|
|
|
(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 00:05:43 -04:00
|
|
|
|
((and (looking-at "[%#\n]")
|
|
|
|
|
(not (or (save-excursion (skip-chars-backward " \t")
|
|
|
|
|
;; Only add implicit ; when needed.
|
2013-05-07 12:53:31 +08:00
|
|
|
|
(or (bolp) (eq (char-before) ?\;)))
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(octave-smie--in-parens-p))))
|
2013-05-07 00:05:43 -04:00
|
|
|
|
(if (eolp) (forward-char 1) (forward-comment 1))
|
2010-08-30 22:34:52 +02:00
|
|
|
|
;; Why bother distinguishing \n and ;?
|
|
|
|
|
";") ;;"\n"
|
2013-05-07 00:05:43 -04:00
|
|
|
|
((progn (forward-comment (point-max)) nil))
|
2010-08-30 22:34:52 +02: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
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(let ((tok (smie-default-forward-token)))
|
|
|
|
|
(cond
|
|
|
|
|
((equal tok "enumeration")
|
|
|
|
|
(if (octave-smie--funcall-p)
|
|
|
|
|
"enumeration (function)"
|
|
|
|
|
tok))
|
|
|
|
|
((equal tok "end") (if (octave-smie--end-index-p) "end (index)" tok))
|
|
|
|
|
(t tok))))))
|
|
|
|
|
|
|
|
|
|
(defconst octave--block-offset-keywords
|
|
|
|
|
(let* ((end-prec (nth 1 (assoc "end" octave-smie-grammar)))
|
|
|
|
|
(end-matchers
|
|
|
|
|
(delq nil
|
|
|
|
|
(mapcar (lambda (x) (if (eq end-prec (nth 2 x)) (car x)))
|
|
|
|
|
octave-smie-grammar))))
|
|
|
|
|
;; Not sure if it would harm to keep "switch", but the previous code
|
|
|
|
|
;; excluded it, presumably because there shouldn't be any code on
|
|
|
|
|
;; the lines between "switch" and "case".
|
|
|
|
|
(delete "switch" end-matchers)))
|
2010-08-30 22:34:52 +02:00
|
|
|
|
|
2010-10-29 15:20:28 -04:00
|
|
|
|
(defun octave-smie-rules (kind token)
|
|
|
|
|
(pcase (cons kind token)
|
2010-11-07 10:45:45 -05: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.
|
2018-11-05 01:22:15 +01:00
|
|
|
|
('(:elem . basic) octave-block-offset)
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(`(:list-intro . ,(or "global" "persistent")) t)
|
2010-11-07 10:45:45 -05:00
|
|
|
|
;; Since "case" is in the same BNF rules as switch..end, SMIE by default
|
|
|
|
|
;; aligns it with "switch".
|
2018-11-05 01:22:15 +01:00
|
|
|
|
('(:before . "case") (if (not (smie-rule-sibling-p)) octave-block-offset))
|
|
|
|
|
('(:after . ";")
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(if (apply #'smie-rule-parent-p octave--block-offset-keywords)
|
2010-11-07 10:45:45 -05:00
|
|
|
|
(smie-rule-parent octave-block-offset)
|
2010-10-29 15:20:28 -04:00
|
|
|
|
;; For (invalid) code between switch and case.
|
2013-12-06 12:26:17 +08:00
|
|
|
|
;; (if (smie-rule-parent-p "switch") 4)
|
2013-05-24 15:37:55 -04:00
|
|
|
|
nil))))
|
2010-08-30 22:34:52 +02:00
|
|
|
|
|
2013-05-11 14:20:10 +08:00
|
|
|
|
(defun octave-indent-comment ()
|
|
|
|
|
"A function for `smie-indent-functions' (which see)."
|
|
|
|
|
(save-excursion
|
|
|
|
|
(back-to-indentation)
|
2013-05-13 08:07:18 +08:00
|
|
|
|
(cond
|
|
|
|
|
((octave-in-string-or-comment-p) nil)
|
2013-05-29 14:50:48 +08:00
|
|
|
|
((looking-at-p "\\(\\s<\\)\\1\\{2,\\}")
|
2013-05-13 08:07:18 +08:00
|
|
|
|
0)
|
2013-05-13 15:24:22 +08:00
|
|
|
|
;; Exclude %{, %} and %!.
|
|
|
|
|
((and (looking-at-p "\\s<\\(?:[^{}!]\\|$\\)")
|
2013-05-29 14:50:48 +08:00
|
|
|
|
(not (looking-at-p "\\(\\s<\\)\\1")))
|
2013-05-13 08:07:18 +08:00
|
|
|
|
(comment-choose-indent)))))
|
2013-05-11 14:20:10 +08:00
|
|
|
|
|
2013-05-07 07:46:07 +08:00
|
|
|
|
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(defvar octave-reserved-words
|
|
|
|
|
(delq nil
|
|
|
|
|
(mapcar (lambda (x)
|
|
|
|
|
(setq x (car x))
|
|
|
|
|
(and (stringp x) (string-match "\\`[[:alpha:]]" x) x))
|
|
|
|
|
octave-smie-grammar))
|
|
|
|
|
"Reserved words in Octave.")
|
|
|
|
|
|
2013-05-07 07:46:07 +08:00
|
|
|
|
(defvar octave-font-lock-keywords
|
|
|
|
|
(list
|
|
|
|
|
;; Fontify all builtin keywords.
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(cons (concat "\\_<" (regexp-opt octave-reserved-words) "\\_>")
|
2013-05-07 07:46:07 +08:00
|
|
|
|
'font-lock-keyword-face)
|
2015-09-29 15:13:44 -04:00
|
|
|
|
;; Note: 'end' also serves as the last index in an indexing expression,
|
|
|
|
|
;; and 'enumerate' is also a function.
|
2013-05-07 07:46:07 +08:00
|
|
|
|
;; Ref: http://www.mathworks.com/help/matlab/ref/end.html
|
2015-09-29 15:13:44 -04:00
|
|
|
|
;; Ref: http://www.mathworks.com/help/matlab/ref/enumeration.html
|
2013-05-07 07:46:07 +08:00
|
|
|
|
(list (lambda (limit)
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(while (re-search-forward "\\_<en\\(?:d\\|umeratio\\(n\\)\\)\\_>"
|
|
|
|
|
limit 'move)
|
2013-05-07 07:46:07 +08:00
|
|
|
|
(let ((beg (match-beginning 0))
|
|
|
|
|
(end (match-end 0)))
|
|
|
|
|
(unless (octave-in-string-or-comment-p)
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(when (if (match-end 1)
|
|
|
|
|
(octave-smie--funcall-p)
|
|
|
|
|
(octave-smie--end-index-p))
|
|
|
|
|
(put-text-property beg end 'face nil)))))
|
2013-05-07 07:46:07 +08: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 16:19:34 -05:00
|
|
|
|
(defvar electric-layout-rules)
|
2010-09-08 18:21:23 +02:00
|
|
|
|
|
2018-10-15 21:24:14 -04:00
|
|
|
|
;; FIXME: cc-mode.el also adds an entry for .m files, mapping them to
|
|
|
|
|
;; objc-mode. We here rely on the fact that loaddefs.el is filled in
|
|
|
|
|
;; alphabetical order, so cc-mode.el comes before octave-mode.el, which lets
|
|
|
|
|
;; our entry come first!
|
|
|
|
|
;;;###autoload (add-to-list 'auto-mode-alist '("\\.m\\'" . octave-maybe-mode))
|
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun octave-maybe-mode ()
|
|
|
|
|
"Select `octave-mode' if the current buffer seems to hold Octave code."
|
|
|
|
|
(if (save-excursion
|
|
|
|
|
(with-syntax-table octave-mode-syntax-table
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(forward-comment (point-max))
|
|
|
|
|
;; FIXME: What about Octave files which don't start with "function"?
|
|
|
|
|
(looking-at "function")))
|
|
|
|
|
(octave-mode)
|
|
|
|
|
(let ((x (rassq 'octave-maybe-mode auto-mode-alist)))
|
|
|
|
|
(when x
|
|
|
|
|
(let ((auto-mode-alist (remove x auto-mode-alist)))
|
|
|
|
|
(set-auto-mode))))))
|
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
;;;###autoload
|
2010-08-12 13:22:16 +02: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-28 01:07:01 +08: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
|
2013-12-11 14:50:46 +01:00
|
|
|
|
definitions can also be stored in files and used in batch mode.
|
|
|
|
|
|
|
|
|
|
See Info node `(octave-mode) Using Octave Mode' for more details.
|
|
|
|
|
|
|
|
|
|
Key bindings:
|
|
|
|
|
\\{octave-mode-map}"
|
2013-05-01 14:13:20 +08:00
|
|
|
|
:abbrev-table octave-abbrev-table
|
2013-12-11 14:50:46 +01:00
|
|
|
|
:group 'octave
|
2010-08-12 13:22:16 +02:00
|
|
|
|
|
2010-11-07 10:45:45 -05:00
|
|
|
|
(smie-setup octave-smie-grammar #'octave-smie-rules
|
2010-10-29 15:20:28 -04:00
|
|
|
|
:forward-token #'octave-smie-forward-token
|
|
|
|
|
:backward-token #'octave-smie-backward-token)
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(setq-local smie-indent-basic 'octave-block-offset)
|
2013-05-11 14:20:10 +08:00
|
|
|
|
(add-hook 'smie-indent-functions #'octave-indent-comment nil t)
|
2010-10-29 15:20:28 -04:00
|
|
|
|
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(setq-local smie-blink-matching-triggers
|
|
|
|
|
(cons ?\; smie-blink-matching-triggers))
|
2010-10-29 15:20:28 -04:00
|
|
|
|
(unless octave-blink-matching-block
|
|
|
|
|
(remove-hook 'post-self-insert-hook #'smie-blink-matching-open 'local))
|
2010-09-03 15:28:09 +02:00
|
|
|
|
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(setq-local electric-indent-chars
|
|
|
|
|
(cons ?\; electric-indent-chars))
|
2010-11-16 16:19:34 -05: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 12:16:37 +08:00
|
|
|
|
(setq-local electric-layout-rules '((?\; . after)))
|
2010-08-12 13:22:16 +02:00
|
|
|
|
|
2013-11-22 01:33:30 +08:00
|
|
|
|
(setq-local comment-use-syntax t)
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(setq-local comment-start octave-comment-start)
|
|
|
|
|
(setq-local comment-end "")
|
2013-05-13 15:24:22 +08:00
|
|
|
|
(setq-local comment-start-skip octave-comment-start-skip)
|
2013-04-26 12:16:37 +08: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 17:43:14 +08:00
|
|
|
|
|
2013-05-22 07:05:16 +08:00
|
|
|
|
(setq-local fill-nobreak-predicate
|
|
|
|
|
(lambda () (eq (octave-in-string-p) ?')))
|
2016-06-25 08:57:51 +08:00
|
|
|
|
(add-function :around (local 'comment-line-break-function)
|
|
|
|
|
#'octave--indent-new-comment-line)
|
2010-08-12 13:22:16 +02:00
|
|
|
|
|
2013-04-26 12:16:37 +08: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-11 01:13:42 +02:00
|
|
|
|
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(setq-local syntax-propertize-function #'octave-syntax-propertize-function)
|
2010-08-12 13:22:16 +02:00
|
|
|
|
|
2013-05-05 23:29:51 +08:00
|
|
|
|
(setq-local imenu-generic-expression octave-mode-imenu-generic-expression)
|
|
|
|
|
(setq-local imenu-case-fold-search nil)
|
2010-08-12 13:22:16 +02:00
|
|
|
|
|
2013-06-08 21:35:55 +08:00
|
|
|
|
(setq-local add-log-current-defun-function #'octave-add-log-current-defun)
|
|
|
|
|
|
2013-05-07 07:46:07 +08:00
|
|
|
|
(add-hook 'completion-at-point-functions 'octave-completion-at-point nil t)
|
2013-04-27 00:44:38 +08:00
|
|
|
|
(add-hook 'before-save-hook 'octave-sync-function-file-names nil t)
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(setq-local beginning-of-defun-function 'octave-beginning-of-defun)
|
2013-04-30 22:23:03 +08:00
|
|
|
|
(and octave-font-lock-texinfo-comment (octave-font-lock-texinfo-comment))
|
2016-07-18 02:17:06 +03:00
|
|
|
|
(add-function :before-until (local 'eldoc-documentation-function)
|
|
|
|
|
'octave-eldoc-function)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-04-26 00:23:56 +08:00
|
|
|
|
(easy-menu-add octave-mode-menu))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(defcustom inferior-octave-program "octave"
|
|
|
|
|
"Program invoked by `inferior-octave'."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'string)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
(defcustom inferior-octave-buffer "*Inferior Octave*"
|
|
|
|
|
"Name of buffer for running an inferior Octave process."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'string)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
(defcustom inferior-octave-prompt
|
2013-12-06 12:26:17 +08:00
|
|
|
|
;; For Octave >= 3.8, default is always 'octave', see
|
2017-09-13 15:52:52 -07:00
|
|
|
|
;; https://hg.savannah.gnu.org/hgweb/octave/rev/708173343c50
|
2013-12-06 12:26:17 +08:00
|
|
|
|
"\\(?:^octave\\(?:.bin\\|.exe\\)?\\(?:-[.0-9]+\\)?\\(?::[0-9]+\\)?\\|^debug\\|^\\)>+ "
|
2013-04-25 22:51:08 +08:00
|
|
|
|
"Regexp to match prompts for the inferior Octave process."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'regexp)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2013-05-01 00:27:36 +08:00
|
|
|
|
(defcustom inferior-octave-prompt-read-only comint-prompt-read-only
|
2013-04-30 23:20:46 +08:00
|
|
|
|
"If non-nil, the Octave prompt is read only.
|
2013-05-01 00:27:36 +08:00
|
|
|
|
See `comint-prompt-read-only' for details."
|
2013-04-30 23:20:46 +08:00
|
|
|
|
:type 'boolean
|
|
|
|
|
:version "24.4")
|
|
|
|
|
|
2013-05-03 05:34:53 +08:00
|
|
|
|
(defcustom inferior-octave-startup-file
|
2013-09-30 09:13:19 +08:00
|
|
|
|
(let ((n (file-name-nondirectory inferior-octave-program)))
|
|
|
|
|
(locate-user-emacs-file (format "init_%s.m" n) (format ".emacs-%s" n)))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
"Name of the inferior Octave startup file.
|
|
|
|
|
The contents of this file are sent to the inferior Octave process on
|
|
|
|
|
startup."
|
2013-05-03 05:34:53 +08:00
|
|
|
|
:type '(choice (const :tag "None" nil) file)
|
|
|
|
|
:version "24.4")
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(defcustom inferior-octave-startup-args '("-i" "--no-line-editing")
|
2013-04-25 22:51:08 +08:00
|
|
|
|
"List of command line arguments for the inferior Octave process.
|
|
|
|
|
For example, for suppressing the startup message and using `traditional'
|
2013-06-12 10:37:38 +08:00
|
|
|
|
mode, include \"-q\" and \"--traditional\"."
|
2013-04-25 22:51:08 +08:00
|
|
|
|
:type '(repeat string)
|
2013-06-12 10:37:38 +08:00
|
|
|
|
:version "24.4")
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2018-04-20 18:34:39 -04:00
|
|
|
|
(define-obsolete-variable-alias 'inferior-octave-startup-hook
|
|
|
|
|
'inferior-octave-mode-hook "24.4")
|
|
|
|
|
|
2013-04-25 22:51:08 +08:00
|
|
|
|
(defcustom inferior-octave-mode-hook nil
|
|
|
|
|
"Hook to be run when Inferior Octave mode is started."
|
2015-09-29 15:13:44 -04:00
|
|
|
|
:type 'hook)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2013-10-04 17:45:25 +08:00
|
|
|
|
(defcustom inferior-octave-error-regexp-alist
|
|
|
|
|
'(("error:\\s-*\\(.*?\\) at line \\([0-9]+\\), column \\([0-9]+\\)"
|
|
|
|
|
1 2 3 2 1)
|
|
|
|
|
("warning:\\s-*\\([^:\n]+\\):.*at line \\([0-9]+\\), column \\([0-9]+\\)"
|
|
|
|
|
1 2 3 1 1))
|
|
|
|
|
"Value for `compilation-error-regexp-alist' in inferior octave."
|
2013-12-27 18:16:05 -08:00
|
|
|
|
:version "24.4"
|
2013-10-04 17:45:25 +08:00
|
|
|
|
:type '(repeat (choice (symbol :tag "Predefined symbol")
|
2015-09-29 15:13:44 -04:00
|
|
|
|
(sexp :tag "Error specification"))))
|
2013-10-04 17:45:25 +08:00
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-compilation-font-lock-keywords
|
|
|
|
|
'(("\\_<PASS\\_>" . compilation-info-face)
|
|
|
|
|
("\\_<FAIL\\_>" . compilation-error-face)
|
|
|
|
|
("\\_<\\(warning\\):" 1 compilation-warning-face)
|
|
|
|
|
("\\_<\\(error\\):" 1 compilation-error-face)
|
|
|
|
|
("^\\s-*!!!!!.*\\|^.*failed$" . compilation-error-face))
|
|
|
|
|
"Value for `compilation-mode-font-lock-keywords' in inferior octave.")
|
|
|
|
|
|
2013-04-25 22:51:08 +08:00
|
|
|
|
(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 15:22:26 +08:00
|
|
|
|
(define-key map "\M-." 'octave-find-definition)
|
2013-05-05 12:49:27 +08:00
|
|
|
|
(define-key map "\t" 'completion-at-point)
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(define-key map "\C-hd" 'octave-help)
|
2013-09-28 10:30:37 +08:00
|
|
|
|
(define-key map "\C-ha" 'octave-lookfor)
|
2013-05-05 12:49:27 +08:00
|
|
|
|
;; Same as in `shell-mode'.
|
2013-04-25 22:51:08 +08: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)
|
2013-09-28 10:41:48 +08:00
|
|
|
|
"Syntax table in use in `inferior-octave-mode' buffers.")
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-font-lock-keywords
|
|
|
|
|
(list
|
|
|
|
|
(cons inferior-octave-prompt 'font-lock-type-face))
|
|
|
|
|
;; Could certainly do more font locking in inferior Octave ...
|
|
|
|
|
"Additional expressions to highlight in Inferior Octave mode.")
|
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-output-list nil)
|
|
|
|
|
(defvar inferior-octave-output-string nil)
|
|
|
|
|
(defvar inferior-octave-receive-in-progress nil)
|
|
|
|
|
|
|
|
|
|
(defvar inferior-octave-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)
|
2013-10-04 17:45:25 +08:00
|
|
|
|
(defvar compilation-error-regexp-alist)
|
|
|
|
|
(defvar compilation-mode-font-lock-keywords)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2013-10-04 23:11:13 +08:00
|
|
|
|
(declare-function compilation-forget-errors "compile" ())
|
|
|
|
|
|
2013-11-22 10:02:42 +08:00
|
|
|
|
(defun inferior-octave-process-live-p ()
|
2013-12-02 15:13:01 +08:00
|
|
|
|
(process-live-p inferior-octave-process))
|
2013-11-22 10:02:42 +08:00
|
|
|
|
|
2013-04-25 22:51:08 +08:00
|
|
|
|
(define-derived-mode inferior-octave-mode comint-mode "Inferior Octave"
|
2013-12-11 14:50:46 +01:00
|
|
|
|
"Major mode for interacting with an inferior Octave process.
|
|
|
|
|
|
|
|
|
|
See Info node `(octave-mode) Running Octave from Within Emacs' for more
|
|
|
|
|
details.
|
|
|
|
|
|
|
|
|
|
Key bindings:
|
|
|
|
|
\\{inferior-octave-mode-map}"
|
2013-05-01 14:13:20 +08:00
|
|
|
|
:abbrev-table octave-abbrev-table
|
2013-12-11 14:50:46 +01:00
|
|
|
|
:group 'octave
|
|
|
|
|
|
2013-05-01 14:13:20 +08:00
|
|
|
|
(setq comint-prompt-regexp inferior-octave-prompt)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2013-11-22 01:33:30 +08:00
|
|
|
|
(setq-local comment-use-syntax t)
|
2013-04-26 12:16:37 +08: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 22:51:08 +08:00
|
|
|
|
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(setq font-lock-defaults '(inferior-octave-font-lock-keywords nil nil))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2013-05-05 23:29:51 +08:00
|
|
|
|
(setq-local info-lookup-mode 'octave-mode)
|
2016-07-18 02:17:06 +03:00
|
|
|
|
(setq-local eldoc-documentation-function 'octave-eldoc-function)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2014-07-03 21:35:23 -04:00
|
|
|
|
(setq-local comint-input-ring-file-name
|
|
|
|
|
(or (getenv "OCTAVE_HISTFILE") "~/.octave_hist"))
|
|
|
|
|
(setq-local comint-input-ring-size
|
|
|
|
|
(string-to-number (or (getenv "OCTAVE_HISTSIZE") "1024")))
|
2013-10-04 23:11:13 +08:00
|
|
|
|
(comint-read-input-ring t)
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(setq-local comint-dynamic-complete-functions
|
|
|
|
|
inferior-octave-dynamic-complete-functions)
|
2013-04-30 23:20:46 +08:00
|
|
|
|
(setq-local comint-prompt-read-only inferior-octave-prompt-read-only)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
(add-hook 'comint-input-filter-functions
|
2013-05-07 07:46:07 +08:00
|
|
|
|
'inferior-octave-directory-tracker nil t)
|
2013-06-01 11:38:36 +08: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-10-04 17:45:25 +08:00
|
|
|
|
(setq-local compilation-error-regexp-alist inferior-octave-error-regexp-alist)
|
|
|
|
|
(setq-local compilation-mode-font-lock-keywords
|
|
|
|
|
inferior-octave-compilation-font-lock-keywords)
|
2013-10-04 23:11:13 +08:00
|
|
|
|
(compilation-shell-minor-mode 1)
|
|
|
|
|
(compilation-forget-errors))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
;;;###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-03 05:34:53 +08:00
|
|
|
|
(let ((buffer (get-buffer-create inferior-octave-buffer)))
|
2013-05-22 07:05:16 +08:00
|
|
|
|
(unless arg
|
|
|
|
|
(pop-to-buffer buffer))
|
2013-05-03 05:34:53 +08:00
|
|
|
|
(unless (comint-check-proc buffer)
|
2013-04-25 22:51:08 +08:00
|
|
|
|
(with-current-buffer buffer
|
2013-05-03 05:34:53 +08:00
|
|
|
|
(inferior-octave-startup)
|
|
|
|
|
(inferior-octave-mode)))
|
|
|
|
|
buffer))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
|
(defalias 'run-octave 'inferior-octave)
|
|
|
|
|
|
|
|
|
|
(defun inferior-octave-startup ()
|
|
|
|
|
"Start an inferior Octave process."
|
|
|
|
|
(let ((proc (comint-exec-1
|
2013-05-03 05:34:53 +08:00
|
|
|
|
(substring inferior-octave-buffer 1 -1)
|
|
|
|
|
inferior-octave-buffer
|
|
|
|
|
inferior-octave-program
|
2013-06-12 10:37:38 +08: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 22:51:08 +08:00
|
|
|
|
(set-process-filter proc 'inferior-octave-output-digest)
|
2013-05-03 05:34:53 +08: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 22:51:08 +08: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-11-22 22:17:48 +08:00
|
|
|
|
(unless (inferior-octave-process-live-p)
|
|
|
|
|
;; Spit out the error messages.
|
|
|
|
|
(when inferior-octave-output-list
|
|
|
|
|
(princ (concat (mapconcat 'identity inferior-octave-output-list "\n")
|
|
|
|
|
"\n")
|
|
|
|
|
(process-mark inferior-octave-process)))
|
|
|
|
|
(error "Process `%s' died" inferior-octave-process))
|
2013-04-25 22:51:08 +08: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-03 05:34:53 +08:00
|
|
|
|
(concat (mapconcat
|
|
|
|
|
'identity inferior-octave-output-list "\n")
|
|
|
|
|
"\n"))))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
;; An empty secondary prompt, as e.g. obtained by '--braindead',
|
|
|
|
|
;; means trouble.
|
|
|
|
|
(inferior-octave-send-list-and-digest (list "PS2\n"))
|
2013-05-03 05:34:53 +08:00
|
|
|
|
(when (string-match "\\(PS2\\|ans\\) = *$"
|
|
|
|
|
(car inferior-octave-output-list))
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(inferior-octave-send-list-and-digest (list "PS2 ('> ');\n")))
|
2013-05-03 05:34:53 +08:00
|
|
|
|
|
2013-05-12 12:10:40 +08:00
|
|
|
|
(inferior-octave-send-list-and-digest
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(list "disp (getenv ('OCTAVE_SRCDIR'))\n"))
|
2013-05-18 09:17:50 +08:00
|
|
|
|
(process-put proc 'octave-srcdir
|
|
|
|
|
(unless (equal (car inferior-octave-output-list) "")
|
|
|
|
|
(car inferior-octave-output-list)))
|
2013-05-12 12:10:40 +08:00
|
|
|
|
|
2013-05-03 05:34:53 +08: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 ">> ")
|
2017-09-13 15:52:52 -07:00
|
|
|
|
;; See https://hg.savannah.gnu.org/hgweb/octave/rev/708173343c50
|
2013-12-06 12:26:17 +08:00
|
|
|
|
"PS1 ('octave> ');\n")
|
2013-05-03 05:34:53 +08:00
|
|
|
|
(when (and inferior-octave-startup-file
|
|
|
|
|
(file-exists-p inferior-octave-startup-file))
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(format "source ('%s');\n" inferior-octave-startup-file))))
|
2013-05-22 23:28:42 +08:00
|
|
|
|
(when inferior-octave-output-list
|
|
|
|
|
(insert-before-markers
|
|
|
|
|
(mapconcat 'identity inferior-octave-output-list "\n")))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
;; And finally, everything is back to normal.
|
2013-05-05 12:49:27 +08:00
|
|
|
|
(set-process-filter proc 'comint-output-filter)
|
2013-06-12 10:37:38 +08: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 23:28:42 +08:00
|
|
|
|
;; Generate a proper prompt, which is critical to
|
|
|
|
|
;; `comint-history-isearch-backward-regexp'. Bug#14433.
|
2013-05-09 08:52:49 +08:00
|
|
|
|
(comint-send-string proc "\n")))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2013-12-06 02:48:52 +02:00
|
|
|
|
(defun inferior-octave-completion-table ()
|
|
|
|
|
(completion-table-with-cache
|
|
|
|
|
(lambda (command)
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
|
|
|
|
(list (format "completion_matches ('%s');\n" command)))
|
|
|
|
|
(delete-consecutive-dups
|
|
|
|
|
(sort inferior-octave-output-list 'string-lessp)))))
|
2013-04-26 00:23:56 +08:00
|
|
|
|
|
2013-04-25 22:51:08 +08:00
|
|
|
|
(defun inferior-octave-completion-at-point ()
|
|
|
|
|
"Return the data to complete the Octave symbol at point."
|
2017-09-13 15:52:52 -07:00
|
|
|
|
;; https://debbugs.gnu.org/14300
|
2013-09-28 11:15:56 +08:00
|
|
|
|
(unless (string-match-p "/" (or (comint--match-partial-filename) ""))
|
|
|
|
|
(let ((beg (save-excursion
|
|
|
|
|
(skip-syntax-backward "w_" (comint-line-beginning-position))
|
|
|
|
|
(point)))
|
|
|
|
|
(end (point)))
|
|
|
|
|
(when (and beg (> end beg))
|
|
|
|
|
(list beg end (completion-table-in-turn
|
2013-12-06 02:48:52 +02:00
|
|
|
|
(inferior-octave-completion-table)
|
2013-09-28 11:15:56 +08:00
|
|
|
|
'comint-completion-file-name-table))))))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
(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)
|
2015-07-25 18:54:42 +02:00
|
|
|
|
(push ch unread-command-events))))))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
|
|
|
|
(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 12:10:40 +08:00
|
|
|
|
(defun inferior-octave-check-process ()
|
2013-11-22 10:02:42 +08:00
|
|
|
|
(or (inferior-octave-process-live-p)
|
2013-05-12 12:10:40 +08:00
|
|
|
|
(error (substitute-command-keys
|
|
|
|
|
"No inferior octave process running. Type \\[run-octave]"))))
|
|
|
|
|
|
2013-04-25 22:51:08 +08: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 12:10:40 +08:00
|
|
|
|
(inferior-octave-check-process)
|
2013-04-25 22:51:08 +08: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 13:08:04 +08:00
|
|
|
|
(defvar inferior-octave-directory-tracker-resync nil)
|
|
|
|
|
(make-variable-buffer-local 'inferior-octave-directory-tracker-resync)
|
|
|
|
|
|
2013-04-25 22:51:08 +08: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 13:08:04 +08:00
|
|
|
|
(when inferior-octave-directory-tracker-resync
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(or (inferior-octave-resync-dirs 'noerror)
|
|
|
|
|
(setq inferior-octave-directory-tracker-resync nil)))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
(cond
|
|
|
|
|
((string-match "^[ \t]*cd[ \t;]*$" string)
|
|
|
|
|
(cd "~"))
|
|
|
|
|
((string-match "^[ \t]*cd[ \t]+\\([^ \t\n;]*\\)[ \t\n;]*" string)
|
2013-05-27 13:08:04 +08: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 22:51:08 +08:00
|
|
|
|
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(defun inferior-octave-resync-dirs (&optional noerror)
|
2013-04-25 22:51:08 +08: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 10:37:38 +08:00
|
|
|
|
(condition-case err
|
|
|
|
|
(progn
|
|
|
|
|
(cd (car inferior-octave-output-list))
|
|
|
|
|
t)
|
|
|
|
|
(error (unless noerror (signal (car err) (cdr err))))))
|
2013-04-25 22:51:08 +08:00
|
|
|
|
|
2013-06-01 11:38:36 +08:00
|
|
|
|
(defcustom inferior-octave-minimal-columns 80
|
|
|
|
|
"The minimal column width for the inferior Octave process."
|
|
|
|
|
:type 'integer
|
|
|
|
|
: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)
|
2013-11-22 10:02:42 +08:00
|
|
|
|
(when (inferior-octave-process-live-p)
|
2013-06-01 11:38:36 +08:00
|
|
|
|
(inferior-octave-send-list-and-digest
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(list (format "putenv ('COLUMNS', '%s');\n" width)))))))
|
2013-06-01 11:38:36 +08:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
;;; Miscellaneous useful functions
|
|
|
|
|
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(defun octave-in-comment-p ()
|
|
|
|
|
"Return non-nil if point is inside an Octave comment."
|
2011-04-19 12:33:34 -03:00
|
|
|
|
(nth 4 (syntax-ppss)))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-04-26 12:16:37 +08:00
|
|
|
|
(defun octave-in-string-p ()
|
|
|
|
|
"Return non-nil if point is inside an Octave string."
|
2011-04-19 12:33:34 -03:00
|
|
|
|
(nth 3 (syntax-ppss)))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-04-26 12:16:37 +08: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-27 00:44:38 +08:00
|
|
|
|
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(defun octave-completing-read ()
|
|
|
|
|
(let ((def (or (thing-at-point 'symbol)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(skip-syntax-backward "-(")
|
|
|
|
|
(thing-at-point 'symbol)))))
|
|
|
|
|
(completing-read
|
2016-06-25 08:57:51 +08:00
|
|
|
|
(format (if def "Function (default %s): " "Function: ") def)
|
2013-12-06 02:48:52 +02:00
|
|
|
|
(inferior-octave-completion-table)
|
2013-05-03 15:22:26 +08:00
|
|
|
|
nil nil nil nil def)))
|
|
|
|
|
|
2013-05-15 16:17:22 +08: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 21:35:55 +08:00
|
|
|
|
(let ((orig (point)) found)
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(while (and (not found) (re-search-forward re nil t))
|
2013-05-15 16:17:22 +08:00
|
|
|
|
(when (and (equal (match-string sub) fn)
|
|
|
|
|
(not (nth 8 (syntax-ppss))))
|
2013-06-08 21:35:55 +08:00
|
|
|
|
(setq found t)))
|
|
|
|
|
(unless found (goto-char orig))
|
|
|
|
|
found))))
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(pcase (and buffer-file-name (file-name-extension buffer-file-name))
|
2018-10-27 01:48:35 +02:00
|
|
|
|
("cc" (funcall search
|
|
|
|
|
"\\_<DEFUN\\(?:_DLD\\)?\\s-*(\\s-*\\(\\(?:\\sw\\|\\s_\\)+\\)" 1))
|
2015-06-16 20:04:35 -04:00
|
|
|
|
(_ (funcall search octave-function-header-regexp 3)))))
|
2013-05-03 15:22:26 +08:00
|
|
|
|
|
2013-04-28 01:07:01 +08: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")
|
Fix problems caused by new implementation of sub-word mode
* lisp/subr.el (forward-word-strictly, backward-word-strictly):
New functions.
(word-move-empty-char-table): New variable.
* etc/NEWS: Mention 'forward-word-strictly' and
'backward-word-strictly'.
* doc/lispref/positions.texi (Word Motion): Document
'find-word-boundary-function-table', 'forward-word-strictly', and
'backward-word-strictly'. (Bug#22560)
* src/syntax.c (syms_of_syntax)
<find-word-boundary-function-table>: Doc fix.
* lisp/wdired.el (wdired-xcase-word):
* lisp/textmodes/texnfo-upd.el (texinfo-copy-node-name)
(texinfo-copy-section-title, texinfo-start-menu-description)
(texinfo-copy-menu-title, texinfo-specific-section-type)
(texinfo-insert-node-lines, texinfo-copy-next-section-title):
* lisp/textmodes/texinfo.el (texinfo-clone-environment)
(texinfo-insert-@end):
* lisp/textmodes/texinfmt.el (texinfo-format-scan)
(texinfo-anchor, texinfo-multitable-widths)
(texinfo-multitable-item):
* lisp/textmodes/tex-mode.el (latex-env-before-change):
* lisp/textmodes/flyspell.el (texinfo-mode-flyspell-verify):
* lisp/skeleton.el (skeleton-insert):
* lisp/simple.el (count-words):
* lisp/progmodes/vhdl-mode.el (vhdl-beginning-of-libunit)
(vhdl-beginning-of-defun, vhdl-beginning-of-statement-1)
(vhdl-update-sensitivity-list, vhdl-template-block)
(vhdl-template-break, vhdl-template-case, vhdl-template-default)
(vhdl-template-default-indent, vhdl-template-for-loop)
(vhdl-template-if-then-use, vhdl-template-bare-loop)
(vhdl-template-nature, vhdl-template-procedural)
(vhdl-template-process, vhdl-template-selected-signal-asst)
(vhdl-template-type, vhdl-template-variable)
(vhdl-template-while-loop, vhdl-beginning-of-block)
(vhdl-hooked-abbrev, vhdl-port-copy, vhdl-hs-forward-sexp-func):
* lisp/progmodes/verilog-mode.el (verilog-backward-sexp)
(verilog-forward-sexp, verilog-beg-of-statement)
(verilog-set-auto-endcomments, verilog-backward-token)
(verilog-do-indent):
* lisp/progmodes/vera-mode.el (vera-guess-basic-syntax)
(vera-indent-block-closing):
* lisp/progmodes/simula.el (simula-context)
(simula-backward-up-level, simula-forward-down-level)
(simula-previous-statement, simula-next-statement)
(simula-skip-comment-backward, simula-calculate-indent)
(simula-find-if, simula-electric-keyword):
* lisp/progmodes/sh-script.el (sh-smie--rc-newline-semi-p):
* lisp/progmodes/ruby-mode.el (ruby-smie--redundant-do-p)
(ruby-smie--forward-token, ruby-smie--backward-token)
(ruby-singleton-class-p, ruby-calculate-indent)
(ruby-forward-sexp, ruby-backward-sexp):
* lisp/progmodes/ps-mode.el (ps-run-goto-error):
* lisp/progmodes/perl-mode.el (perl-syntax-propertize-function)
(perl-syntax-propertize-special-constructs)
(perl-backward-to-start-of-continued-exp):
* lisp/progmodes/pascal.el (pascal-indent-declaration):
* lisp/progmodes/octave.el (octave-function-file-p):
* lisp/progmodes/mantemp.el (mantemp-insert-cxx-syntax):
* lisp/progmodes/js.el (js--forward-function-decl):
* lisp/progmodes/idlwave.el (idlwave-show-begin-check)
(idlwave-beginning-of-block, idlwave-end-of-block)
(idlwave-block-jump-out, idlwave-determine-class):
* lisp/progmodes/icon.el (icon-is-continuation-line)
(icon-backward-to-start-of-continued-exp, end-of-icon-defun):
* lisp/progmodes/hideif.el (hide-ifdef-define):
* lisp/progmodes/f90.el (f90-change-keywords):
* lisp/progmodes/cperl-mode.el (cperl-electric-pod)
(cperl-linefeed, cperl-electric-terminator)
(cperl-find-pods-heres, cperl-fix-line-spacing)
(cperl-invert-if-unless):
* lisp/progmodes/cc-engine.el (c-forward-<>-arglist-recur):
* lisp/progmodes/cc-align.el (c-lineup-java-inher):
* lisp/progmodes/ada-mode.el (ada-compile-goto-error)
(ada-adjust-case-skeleton, ada-create-case-exception)
(ada-create-case-exception-substring)
(ada-case-read-exceptions-from-file, ada-after-keyword-p)
(ada-scan-paramlist, ada-get-current-indent, ada-get-indent-end)
(ada-get-indent-if, ada-get-indent-block-start)
(ada-get-indent-loop, ada-get-indent-type)
(ada-search-prev-end-stmt, ada-check-defun-name)
(ada-goto-decl-start, ada-goto-matching-start)
(ada-goto-matching-end, ada-looking-at-semi-or)
(ada-looking-at-semi-private, ada-in-paramlist-p)
(ada-search-ignore-complex-boolean, ada-move-to-start)
(ada-move-to-end, ada-which-function, ada-gen-treat-proc):
* lisp/net/quickurl.el (quickurl-grab-url):
* lisp/mail/sendmail.el (mail-do-fcc):
* lisp/mail/rmail.el (rmail-resend):
* lisp/mail/mailabbrev.el (mail-abbrev-complete-alias):
* lisp/mail/mail-extr.el (mail-extract-address-components):
* lisp/json.el (json-read-keyword):
* lisp/files.el (insert-directory):
* lisp/emacs-lisp/checkdoc.el (checkdoc-this-string-valid-engine):
* lisp/completion.el (symbol-under-point, symbol-before-point)
(symbol-before-point-for-complete, next-cdabbrev)
(add-completions-from-c-buffer):
* lisp/cedet/semantic/texi.el (semantic-up-context)
(semantic-beginning-of-context):
* lisp/cedet/semantic/bovine/el.el (semantic-get-local-variables):
use 'forward-word-strictly' and 'backward-word-strictly' instead
of 'forward-word' and 'backward-word'.
[This reapplies commit c1d32a65372c72d7de4808d620eefd3214a8e92a,
which was inadvertently lost by merge commit
c71e7cc113ed0d5f01aaa2e441a3e3c9fbeb9fa5.]
2016-03-21 17:42:35 -07:00
|
|
|
|
(forward-word-strictly -1)
|
2013-04-28 01:07:01 +08:00
|
|
|
|
(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 12:37:36 +08:00
|
|
|
|
"Beginning and end positions of the function file comment."
|
2013-04-28 01:07:01 +08:00
|
|
|
|
(save-excursion
|
|
|
|
|
(goto-char (point-min))
|
2013-04-30 04:09:18 +08: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-28 01:07:01 +08:00
|
|
|
|
|
2013-04-27 00:44:38 +08:00
|
|
|
|
(defun octave-sync-function-file-names ()
|
|
|
|
|
"Ensure function name agree with function file name.
|
|
|
|
|
See Info node `(octave)Function Files'."
|
|
|
|
|
(interactive)
|
2013-04-28 01:07:01 +08: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 12:37:36 +08:00
|
|
|
|
(let* ((func (buffer-substring name-start name-end))
|
|
|
|
|
(file (file-name-sans-extension
|
|
|
|
|
(file-name-nondirectory buffer-file-name)))
|
2015-08-30 22:05:43 -07:00
|
|
|
|
(help-form (format-message "\
|
2013-04-29 12:37:36 +08:00
|
|
|
|
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
|
2018-10-27 01:48:35 +02:00
|
|
|
|
(?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-28 01:07:01 +08: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-27 00:44:38 +08:00
|
|
|
|
(save-excursion
|
2013-04-28 01:07:01 +08: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-30 04:09:18 +08:00
|
|
|
|
(when (re-search-forward
|
|
|
|
|
"[=}]\\s-*\\(\\(?:\\sw\\|\\s_\\)+\\)\\_>"
|
|
|
|
|
(min (line-end-position 4) end)
|
|
|
|
|
t)
|
2013-04-28 01:07:01 +08: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-27 00:44:38 +08:00
|
|
|
|
|
2013-04-30 22:23:03 +08:00
|
|
|
|
(defface octave-function-comment-block
|
|
|
|
|
'((t (:inherit font-lock-doc-face)))
|
2015-09-29 15:13:44 -04:00
|
|
|
|
"Face used to highlight function comment block.")
|
2013-04-30 22:23:03 +08:00
|
|
|
|
|
2013-05-05 22:29:42 -04:00
|
|
|
|
(eval-when-compile (require 'texinfo))
|
2018-02-28 15:50:37 -05:00
|
|
|
|
;; Undo the effects of texinfo loading tex-mode loading compile.
|
|
|
|
|
(declare-function compilation-forget-errors "compile" ())
|
2013-05-05 22:29:42 -04:00
|
|
|
|
|
2013-04-30 22:23:03 +08:00
|
|
|
|
(defun octave-font-lock-texinfo-comment ()
|
2013-05-05 22:29:42 -04: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 18:11:56 +08:00
|
|
|
|
(while (and (< (point) limit)
|
|
|
|
|
(search-forward "-*- texinfo -*-" limit t)
|
2013-05-05 22:29:42 -04: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 22:23:03 +08:00
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
;;; Indentation
|
|
|
|
|
|
2013-05-21 17:43:14 +08: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 17:43:14 +08: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 15:37:55 -04: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 17:43:14 +08: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 17:43:14 +08:00
|
|
|
|
(delete-horizontal-space)
|
|
|
|
|
(unless (and (cadr (syntax-ppss))
|
|
|
|
|
(eq (char-after (cadr (syntax-ppss))) ?\())
|
|
|
|
|
(insert " " octave-continuation-string))))
|
2013-05-24 15:37:55 -04:00
|
|
|
|
(apply orig args)
|
2013-05-21 17:43:14 +08:00
|
|
|
|
(indent-according-to-mode))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-05-16 16:52:02 +08: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 11:50:34 +08: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 11:50:34 +08: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 11:50:34 +08: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 11:50:34 +08: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 00:30:58 -05: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 14:13:51 +02:00
|
|
|
|
(unless (or (looking-at "\\s(")
|
|
|
|
|
(save-excursion
|
|
|
|
|
(let* ((token (funcall smie-forward-token-function))
|
2010-11-10 00:21:06 -08:00
|
|
|
|
(level (assoc token smie-grammar)))
|
2012-12-05 00:30:58 -05: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 14:13:51 +02: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 14:26:42 +08: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 17:43:14 +08:00
|
|
|
|
(and (< arg 0) (forward-sexp -1))
|
2013-05-10 14:26:42 +08:00
|
|
|
|
(/= orig (point))))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2011-04-22 20:44:26 +02: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 14:13:51 +02: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-22 07:05:16 +08: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 14:13:51 +02:00
|
|
|
|
(forward-line 1))))
|
|
|
|
|
t)))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-05-07 07:46:07 +08:00
|
|
|
|
(defun octave-completion-at-point ()
|
2010-08-12 13:22:16 +02:00
|
|
|
|
"Find the text to complete and the corresponding table."
|
2011-04-25 13:29:31 -03:00
|
|
|
|
(let* ((beg (save-excursion (skip-syntax-backward "w_") (point)))
|
2010-08-17 17:49:30 +02:00
|
|
|
|
(end (point)))
|
|
|
|
|
(if (< beg (point))
|
|
|
|
|
;; Extend region past point, if applicable.
|
2011-04-25 13:29:31 -03:00
|
|
|
|
(save-excursion (skip-syntax-forward "w_")
|
|
|
|
|
(setq end (point))))
|
2013-05-07 07:46:07 +08:00
|
|
|
|
(when (> end beg)
|
2013-11-22 10:02:42 +08:00
|
|
|
|
(list beg end (or (and (inferior-octave-process-live-p)
|
2013-12-06 02:48:52 +02:00
|
|
|
|
(inferior-octave-completion-table))
|
2013-05-07 07:46:07 +08:00
|
|
|
|
octave-reserved-words)))))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
2013-06-08 21:35:55 +08: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 13:22:16 +02: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 12:16:37 +08:00
|
|
|
|
(let* ((defname (file-name-sans-extension (buffer-name)))
|
2010-08-12 13:22:16 +02: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-28 01:07:01 +08: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 13:22:16 +02:00
|
|
|
|
"endfunction" > \n)
|
2013-06-08 21:35:55 +08: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)
|
2013-11-22 17:50:41 +08:00
|
|
|
|
(when (and (buffer-live-p (get-buffer inferior-octave-buffer))
|
|
|
|
|
(or (yes-or-no-p (format "Kill %S and its buffer? "
|
|
|
|
|
inferior-octave-process))
|
|
|
|
|
(user-error "Aborted")))
|
|
|
|
|
(when (inferior-octave-process-live-p)
|
|
|
|
|
(set-process-query-on-exit-flag inferior-octave-process nil)
|
|
|
|
|
(process-send-string inferior-octave-process "quit;\n")
|
|
|
|
|
(accept-process-output inferior-octave-process))
|
2013-11-22 10:02:42 +08:00
|
|
|
|
(kill-buffer inferior-octave-buffer)))
|
1997-01-21 00:29:57 +00:00
|
|
|
|
|
|
|
|
|
(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)))
|
|
|
|
|
|
2013-11-22 01:18:25 +08:00
|
|
|
|
(defun octave-source-file (file)
|
|
|
|
|
"Execute FILE in the inferior Octave process.
|
|
|
|
|
This is done using Octave's source function. FILE defaults to
|
|
|
|
|
current buffer file unless called with a prefix arg \\[universal-argument]."
|
|
|
|
|
(interactive (list (or (and (not current-prefix-arg) buffer-file-name)
|
|
|
|
|
(read-file-name "File: " nil nil t))))
|
|
|
|
|
(or (stringp file)
|
|
|
|
|
(signal 'wrong-type-argument (list 'stringp file)))
|
|
|
|
|
(inferior-octave t)
|
|
|
|
|
(with-current-buffer inferior-octave-buffer
|
|
|
|
|
(comint-send-string inferior-octave-process
|
|
|
|
|
(format "source '%s'\n" file))))
|
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(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 12:49:27 +08:00
|
|
|
|
(string (buffer-substring-no-properties beg end))
|
|
|
|
|
line)
|
2008-04-30 08:48:02 +00:00
|
|
|
|
(with-current-buffer inferior-octave-buffer
|
2017-11-25 22:45:41 -08:00
|
|
|
|
;; https://lists.gnu.org/r/emacs-devel/2013-10/msg00095.html
|
2013-10-05 10:45:24 +08:00
|
|
|
|
(compilation-forget-errors)
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(setq inferior-octave-output-list nil)
|
|
|
|
|
(while (not (string-equal string ""))
|
2013-05-05 12:49:27 +08: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)))
|
|
|
|
|
|
2013-09-28 10:41:48 +08:00
|
|
|
|
(defun octave-send-buffer ()
|
|
|
|
|
"Send current buffer to the inferior Octave process."
|
|
|
|
|
(interactive)
|
|
|
|
|
(octave-send-region (point-min) (point-max)))
|
|
|
|
|
|
1997-01-21 00:29:57 +00:00
|
|
|
|
(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 17:49:30 +02: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 12:16:37 +08:00
|
|
|
|
|
2013-05-03 15:22:26 +08:00
|
|
|
|
|
|
|
|
|
|
2013-05-11 21:22:06 +08: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))
|
|
|
|
|
: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 10:37:38 +08:00
|
|
|
|
(list (format "print_usage ('%s');\n" fn)))
|
2013-05-11 21:22:06 +08:00
|
|
|
|
(let (result)
|
|
|
|
|
(dolist (line inferior-octave-output-list)
|
2019-08-06 12:45:28 -03:00
|
|
|
|
;; The help output has changed a few times in GNU Octave.
|
|
|
|
|
;; Earlier versions output "usage: " before the function signature.
|
|
|
|
|
;; After deprecating the usage function, and up until GNU Octave 4.0.3,
|
|
|
|
|
;; the output looks like this:
|
|
|
|
|
;; -- Mapping Function: abs (Z).
|
|
|
|
|
;; After GNU Octave 4.2.0, the output is less verbose and it looks like
|
|
|
|
|
;; this:
|
|
|
|
|
;; -- abs (Z)
|
|
|
|
|
;; The following regexp matches these three formats.
|
|
|
|
|
;; The "usage: " alternative matches the symbol, because a call to
|
|
|
|
|
;; print_usage with a non-existent function (e.g., print_usage ('A'))
|
|
|
|
|
;; would output:
|
|
|
|
|
;; error: print_usage: 'A' not found
|
|
|
|
|
;; and we wouldn't like to match anything in this case.
|
|
|
|
|
;; See bug #36459.
|
2013-05-11 21:22:06 +08:00
|
|
|
|
(when (string-match
|
2019-08-06 12:45:28 -03:00
|
|
|
|
"\\s-*\\(?:--[^:]+:\\|\\_<usage:\\|--\\)\\s-*\\(.*\\)$"
|
2013-05-11 21:22:06 +08:00
|
|
|
|
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)."
|
2013-11-22 10:02:42 +08:00
|
|
|
|
(when (inferior-octave-process-live-p)
|
2013-05-11 21:22:06 +08:00
|
|
|
|
(let* ((ppss (syntax-ppss))
|
|
|
|
|
(paren-pos (cadr ppss))
|
|
|
|
|
(fn (save-excursion
|
|
|
|
|
(if (and paren-pos
|
2019-07-08 19:22:20 -03:00
|
|
|
|
;; PAREN-POS must be after the prompt.
|
2013-05-11 21:22:06 +08:00
|
|
|
|
(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
|
2018-11-05 01:22:15 +01:00
|
|
|
|
('auto (if (< (length oneline) (window-width (minibuffer-window)))
|
2013-05-11 21:22:06 +08:00
|
|
|
|
oneline
|
|
|
|
|
multiline))
|
2018-11-05 01:22:15 +01:00
|
|
|
|
('oneline oneline)
|
|
|
|
|
('multiline multiline)))))
|
2013-05-11 21:22:06 +08:00
|
|
|
|
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(defcustom octave-help-buffer "*Octave Help*"
|
|
|
|
|
"Buffer name for `octave-help'."
|
|
|
|
|
:type 'string
|
|
|
|
|
:version "24.4")
|
|
|
|
|
|
2013-09-11 22:43:23 -07:00
|
|
|
|
;; Used in a mode derived from help-mode.
|
|
|
|
|
(declare-function help-button-action "help-mode" (button))
|
|
|
|
|
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(define-button-type 'octave-help-file
|
|
|
|
|
'follow-link t
|
|
|
|
|
'action #'help-button-action
|
2013-05-05 12:49:27 +08:00
|
|
|
|
'help-function 'octave-find-definition)
|
2013-05-03 15:22:26 +08: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-21 06:52:40 +08:00
|
|
|
|
(defvar octave-help-mode-map
|
|
|
|
|
(let ((map (make-sparse-keymap)))
|
2013-11-22 16:09:40 +08:00
|
|
|
|
(define-key map "\M-." 'octave-find-definition)
|
2013-05-21 06:52:40 +08:00
|
|
|
|
(define-key map "\C-hd" 'octave-help)
|
2013-09-28 10:30:37 +08:00
|
|
|
|
(define-key map "\C-ha" 'octave-lookfor)
|
2013-05-21 06:52:40 +08:00
|
|
|
|
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))
|
2013-11-22 16:09:40 +08:00
|
|
|
|
;; Don't highlight `EXAMPLE' as elisp symbols by using a regexp that
|
|
|
|
|
;; can never match.
|
Add standard unmatchable regexp
Add `regexp-unmatchable' as a standard unmatchable regexp, defined as
"\\`a\\`". Use it where such a regexp is needed, replacing slower
expressions in several places.
From a suggestion by Philippe Schnoebelen.
* lisp/subr.el (regexp-unmatchable): New defconst.
* etc/NEWS (Lisp Changes): Mention `regexp-unmatchable'.
* doc/lispref/searching.texi (Regexp Functions): Document it.
* lisp/emacs-lisp/regexp-opt.el (regexp-opt)
* lisp/progmodes/cc-defs.el (cc-conditional-require-after-load)
(c-make-keywords-re)
* lisp/progmodes/cc-engine.el (c-beginning-of-statement-1)
(c-forward-<>-arglist-recur, c-forward-decl-or-cast-1)
(c-looking-at-decl-block)
* lisp/progmodes/cc-fonts.el (c-doc-line-join-re)
(c-doc-bright-comment-start-re)
* lisp/progmodes/cc-langs.el (c-populate-syntax-table)
(c-assignment-op-regexp)
(c-block-comment-ender-regexp, c-font-lock-comment-end-skip)
(c-block-comment-start-regexp, c-line-comment-start-regexp)
(c-doc-comment-start-regexp, c-decl-start-colon-kwd-re)
(c-type-decl-prefix-key, c-type-decl-operator-prefix-key)
(c-pre-id-bracelist-key, c-enum-clause-introduction-re)
(c-nonlabel-token-2-key)
* lisp/progmodes/cc-mode.el (c-doc-fl-decl-start, c-doc-fl-decl-end)
* lisp/progmodes/cc-vars.el (c-noise-macro-with-parens-name-re)
(c-noise-macro-name-re, c-make-noise-macro-regexps)
* lisp/progmodes/octave.el (octave-help-mode)
* lisp/vc/vc-bzr.el (vc-bzr-log-view-mode, vc-bzr-revision-completion-table)
* lisp/vc/vc-git.el (vc-git-log-view-mode)
* lisp/vc/vc-hg.el (vc-hg-log-view-mode)
* lisp/vc/vc-mtn.el (vc-mtn-log-view-mode):
Use `regexp-unmatchable'.
* lisp/textmodes/ispell.el (ispell-non-empty-string):
Use `regexp-unmatchable', fixing a broken never-match regexp.
2019-05-14 11:43:49 +02:00
|
|
|
|
(setq-local help-xref-symbol-regexp regexp-unmatchable))
|
2013-05-21 06:52:40 +08:00
|
|
|
|
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(defun octave-help (fn)
|
|
|
|
|
"Display the documentation of FN."
|
|
|
|
|
(interactive (list (octave-completing-read)))
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(list (format "help ('%s');\n" fn)))
|
2013-05-21 06:52:40 +08:00
|
|
|
|
(let ((lines inferior-octave-output-list)
|
|
|
|
|
(inhibit-read-only t))
|
2013-05-03 15:22:26 +08: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 17:43:14 +08:00
|
|
|
|
(let* ((file (match-string 1))
|
|
|
|
|
(dir (file-name-directory
|
|
|
|
|
(directory-file-name (file-name-directory file)))))
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(replace-match "" nil nil nil 1)
|
2015-08-30 22:05:43 -07:00
|
|
|
|
(insert (substitute-command-keys "`"))
|
2013-05-21 17:43:14 +08: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 12:49:27 +08:00
|
|
|
|
'octave-help-file fn)
|
2015-08-30 22:05:43 -07:00
|
|
|
|
(insert (substitute-command-keys "'"))))
|
2013-06-12 10:37:38 +08:00
|
|
|
|
;; Make 'See also' clickable.
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(with-syntax-table octave-mode-syntax-table
|
|
|
|
|
(when (re-search-forward "^\\s-*See also:" nil t)
|
2013-05-29 14:50:48 +08:00
|
|
|
|
(let ((end (save-excursion (re-search-forward "^\\s-*$" nil t))))
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(while (re-search-forward
|
2013-06-19 10:02:30 +08:00
|
|
|
|
"\\s-*\\([^,\n]+?\\)\\s-*\\(?:[,]\\|[.]?$\\)" end t)
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(make-text-button (match-beginning 1) (match-end 1)
|
2013-05-27 13:08:04 +08:00
|
|
|
|
:type 'octave-help-function)))))
|
2013-05-21 06:52:40 +08:00
|
|
|
|
(octave-help-mode)))))
|
2013-05-03 15:22:26 +08:00
|
|
|
|
|
2013-09-28 10:30:37 +08:00
|
|
|
|
(defun octave-lookfor (str &optional all)
|
|
|
|
|
"Search for the string STR in all function help strings.
|
|
|
|
|
If ALL is non-nil search the entire help string else only search the first
|
|
|
|
|
sentence."
|
|
|
|
|
(interactive "sSearch for: \nP")
|
|
|
|
|
(inferior-octave-send-list-and-digest
|
|
|
|
|
(list (format "lookfor (%s'%s');\n"
|
|
|
|
|
(if all "'-all', " "")
|
|
|
|
|
str)))
|
|
|
|
|
(let ((lines inferior-octave-output-list))
|
2013-10-25 08:49:33 +08:00
|
|
|
|
(when (and (stringp (car lines))
|
|
|
|
|
(string-match "error: \\(.*\\)$" (car lines)))
|
2013-09-28 10:30:37 +08:00
|
|
|
|
(error "%s" (match-string 1 (car lines))))
|
|
|
|
|
(with-help-window octave-help-buffer
|
|
|
|
|
(with-current-buffer octave-help-buffer
|
2013-10-25 08:49:33 +08:00
|
|
|
|
(if lines
|
|
|
|
|
(insert (mapconcat 'identity lines "\n"))
|
|
|
|
|
(insert (format "Nothing found for \"%s\".\n" str)))
|
2013-09-28 10:30:37 +08:00
|
|
|
|
;; Bound to t so that `help-buffer' returns current buffer for
|
|
|
|
|
;; `help-setup-xref'.
|
|
|
|
|
(let ((help-xref-following t))
|
|
|
|
|
(help-setup-xref (list 'octave-lookfor str all)
|
|
|
|
|
(called-interactively-p 'interactive)))
|
|
|
|
|
(goto-char (point-min))
|
2013-10-25 08:49:33 +08:00
|
|
|
|
(when lines
|
|
|
|
|
(while (re-search-forward "^\\([^[:blank:]]+\\) " nil 'noerror)
|
|
|
|
|
(make-text-button (match-beginning 1) (match-end 1)
|
|
|
|
|
:type 'octave-help-function)))
|
|
|
|
|
(unless all
|
|
|
|
|
(goto-char (point-max))
|
|
|
|
|
(insert "\nRetry with ")
|
|
|
|
|
(insert-text-button "'-all'"
|
|
|
|
|
'follow-link t
|
2013-10-25 08:52:26 +08:00
|
|
|
|
'action #'(lambda (_b)
|
2013-10-25 08:49:33 +08:00
|
|
|
|
(octave-lookfor str '-all)))
|
|
|
|
|
(insert ".\n"))
|
2013-09-28 10:30:37 +08:00
|
|
|
|
(octave-help-mode)))))
|
|
|
|
|
|
2013-05-12 12:10:40 +08:00
|
|
|
|
(defcustom octave-source-directories nil
|
2013-05-18 09:17:50 +08:00
|
|
|
|
"A list of directories for Octave sources.
|
|
|
|
|
If the environment variable OCTAVE_SRCDIR is set, it is searched first."
|
2013-05-12 12:10:40 +08:00
|
|
|
|
:type '(repeat directory)
|
2013-05-05 12:49:27 +08:00
|
|
|
|
:version "24.4")
|
|
|
|
|
|
2013-05-12 12:10:40 +08:00
|
|
|
|
(defun octave-source-directories ()
|
2013-05-18 09:17:50 +08:00
|
|
|
|
(let ((srcdir (or (and inferior-octave-process
|
|
|
|
|
(process-get inferior-octave-process 'octave-srcdir))
|
|
|
|
|
(getenv "OCTAVE_SRCDIR"))))
|
2013-05-12 12:10:40 +08: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)
|
2018-10-27 01:48:35 +02:00
|
|
|
|
("oct"
|
2013-05-12 12:10:40 +08:00
|
|
|
|
(octave-find-definition-default-filename
|
|
|
|
|
(concat "libinterp/dldfcn/"
|
|
|
|
|
(file-name-sans-extension (file-name-nondirectory name))
|
|
|
|
|
".cc")))
|
2018-10-27 01:48:35 +02:00
|
|
|
|
("cc"
|
2013-05-12 12:10:40 +08:00
|
|
|
|
(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))
|
2018-10-27 01:48:35 +02:00
|
|
|
|
("mex"
|
2015-08-30 22:05:43 -07:00
|
|
|
|
(if (yes-or-no-p (format-message "File `%s' may be binary; open? "
|
|
|
|
|
(file-name-nondirectory name)))
|
2013-05-12 12:10:40 +08:00
|
|
|
|
name
|
|
|
|
|
(user-error "Aborted")))
|
2015-06-16 20:04:35 -04:00
|
|
|
|
(_ name)))
|
2013-05-12 12:10:40 +08:00
|
|
|
|
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(defvar find-tag-marker-ring)
|
|
|
|
|
|
|
|
|
|
(defun octave-find-definition (fn)
|
2013-05-12 12:10:40 +08:00
|
|
|
|
"Find the definition of FN.
|
2013-05-18 09:17:50 +08:00
|
|
|
|
Functions implemented in C++ can be found if
|
2013-09-28 10:41:48 +08:00
|
|
|
|
variable `octave-source-directories' is set correctly."
|
2013-05-03 15:22:26 +08:00
|
|
|
|
(interactive (list (octave-completing-read)))
|
2013-06-08 21:35:55 +08:00
|
|
|
|
(require 'etags)
|
|
|
|
|
(let ((orig (point)))
|
2013-06-12 10:37:38 +08:00
|
|
|
|
(if (and (derived-mode-p 'octave-mode)
|
|
|
|
|
(octave-goto-function-definition fn))
|
2013-06-08 21:35:55 +08: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 10:37:38 +08:00
|
|
|
|
if iskeyword('%s') disp('`%s'' is a keyword') else which('%s') endif\n"
|
2013-06-08 21:35:55 +08: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)
|
2015-08-30 22:05:43 -07:00
|
|
|
|
(user-error "%s" (or line (format-message "`%s' not found" fn)))
|
2013-06-08 21:35:55 +08:00
|
|
|
|
(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 15:22:26 +08:00
|
|
|
|
|
2013-04-25 22:51:08 +08:00
|
|
|
|
(provide 'octave)
|
|
|
|
|
;;; octave.el ends here
|