comparison lisp/progmodes/octave-mod.el @ 110066:5ef877197e04

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.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Tue, 31 Aug 2010 14:13:51 +0200
parents 6939db1ee97b
children da442f29c7b6
comparison
equal deleted inserted replaced
110065:b0de94d21a73 110066:5ef877197e04
221 (define-key map "\C-c\C-b" 'octave-submit-bug-report) 221 (define-key map "\C-c\C-b" 'octave-submit-bug-report)
222 (define-key map "\C-c\C-p" 'octave-previous-code-line) 222 (define-key map "\C-c\C-p" 'octave-previous-code-line)
223 (define-key map "\C-c\C-n" 'octave-next-code-line) 223 (define-key map "\C-c\C-n" 'octave-next-code-line)
224 (define-key map "\C-c\C-a" 'octave-beginning-of-line) 224 (define-key map "\C-c\C-a" 'octave-beginning-of-line)
225 (define-key map "\C-c\C-e" 'octave-end-of-line) 225 (define-key map "\C-c\C-e" 'octave-end-of-line)
226 (define-key map "\C-c\M-\C-d" 'octave-down-block) 226 (define-key map [remap down-list] 'smie-down-list)
227 (define-key map "\C-c\M-\C-h" 'octave-mark-block) 227 (define-key map "\C-c\M-\C-h" 'octave-mark-block)
228 (define-key map "\C-c]" 'smie-close-block) 228 (define-key map "\C-c]" 'smie-close-block)
229 (define-key map "\C-c/" 'smie-close-block) 229 (define-key map "\C-c/" 'smie-close-block)
230 (define-key map "\C-c\C-f" 'octave-insert-defun) 230 (define-key map "\C-c\C-f" 'octave-insert-defun)
231 (define-key map "\C-c\C-h" 'octave-help) 231 (define-key map "\C-c\C-h" 'octave-help)
256 ["Next Code Line" octave-next-code-line t] 256 ["Next Code Line" octave-next-code-line t]
257 ["Begin of Continuation" octave-beginning-of-line t] 257 ["Begin of Continuation" octave-beginning-of-line t]
258 ["End of Continuation" octave-end-of-line t] 258 ["End of Continuation" octave-end-of-line t]
259 ["Split Line at Point" octave-indent-new-comment-line t]) 259 ["Split Line at Point" octave-indent-new-comment-line t])
260 ("Blocks" 260 ("Blocks"
261 ["Down Block" octave-down-block t]
262 ["Mark Block" octave-mark-block t] 261 ["Mark Block" octave-mark-block t]
263 ["Close Block" smie-close-block t]) 262 ["Close Block" smie-close-block t])
264 ("Functions" 263 ("Functions"
265 ["Indent Function" octave-indent-defun t] 264 ["Indent Function" octave-indent-defun t]
266 ["Insert Function" octave-insert-defun t]) 265 ["Insert Function" octave-insert-defun t])
341 (defcustom octave-block-offset 2 340 (defcustom octave-block-offset 2
342 "Extra indentation applied to statements in Octave block structures." 341 "Extra indentation applied to statements in Octave block structures."
343 :type 'integer 342 :type 'integer
344 :group 'octave) 343 :group 'octave)
345 344
346 (defvar octave-block-begin-regexp
347 (concat "\\<\\("
348 (mapconcat 'identity octave-begin-keywords "\\|")
349 "\\)\\>"))
350 (defvar octave-block-else-regexp 345 (defvar octave-block-else-regexp
351 (concat "\\<\\(" 346 (concat "\\<\\("
352 (mapconcat 'identity octave-else-keywords "\\|") 347 (mapconcat 'identity octave-else-keywords "\\|")
353 "\\)\\>")) 348 "\\)\\>"))
354 (defvar octave-block-end-regexp 349 (defvar octave-block-end-regexp
355 (concat "\\<\\(" 350 (concat "\\<\\("
356 (mapconcat 'identity octave-end-keywords "\\|") 351 (mapconcat 'identity octave-end-keywords "\\|")
357 "\\)\\>")) 352 "\\)\\>"))
358 (defvar octave-block-begin-or-end-regexp
359 (concat octave-block-begin-regexp "\\|" octave-block-end-regexp))
360 (defvar octave-block-else-or-end-regexp 353 (defvar octave-block-else-or-end-regexp
361 (concat octave-block-else-regexp "\\|" octave-block-end-regexp)) 354 (concat octave-block-else-regexp "\\|" octave-block-end-regexp))
362 (defvar octave-block-match-alist 355 (defvar octave-block-match-alist
363 '(("do" . ("until")) 356 '(("do" . ("until"))
364 ("for" . ("end" "endfor")) 357 ("for" . ("end" "endfor"))
721 "Return t if point is not inside an Octave string or comment." 714 "Return t if point is not inside an Octave string or comment."
722 ;; FIXME: Use syntax-ppss? 715 ;; FIXME: Use syntax-ppss?
723 (let ((pps (parse-partial-sexp (line-beginning-position) (point)))) 716 (let ((pps (parse-partial-sexp (line-beginning-position) (point))))
724 (not (or (nth 3 pps) (nth 4 pps))))) 717 (not (or (nth 3 pps) (nth 4 pps)))))
725 718
726 (defun octave-in-block-p ()
727 "Return t if point is inside an Octave block.
728 The block is taken to start at the first letter of the begin keyword and
729 to end after the end keyword."
730 (let ((pos (point)))
731 (save-excursion
732 (condition-case nil
733 (progn
734 (skip-syntax-forward "w")
735 (octave-up-block -1)
736 (octave-forward-block)
737 t)
738 (error nil))
739 (< pos (point)))))
740 719
741 (defun octave-looking-at-kw (regexp) 720 (defun octave-looking-at-kw (regexp)
742 "Like `looking-at', but sets `case-fold-search' nil." 721 "Like `looking-at', but sets `case-fold-search' nil."
743 (let ((case-fold-search nil)) 722 (let ((case-fold-search nil))
744 (looking-at regexp))) 723 (looking-at regexp)))
745
746 (defun octave-re-search-forward-kw (regexp count)
747 "Like `re-search-forward', but sets `case-fold-search' nil, and moves point."
748 (let ((case-fold-search nil))
749 (re-search-forward regexp nil 'move count)))
750
751 (defun octave-re-search-backward-kw (regexp count)
752 "Like `re-search-backward', but sets `case-fold-search' nil, and moves point."
753 (let ((case-fold-search nil))
754 (re-search-backward regexp nil 'move count)))
755 724
756 (defun octave-maybe-insert-continuation-string () 725 (defun octave-maybe-insert-continuation-string ()
757 (if (or (octave-in-comment-p) 726 (if (or (octave-in-comment-p)
758 (save-excursion 727 (save-excursion
759 (beginning-of-line) 728 (beginning-of-line)
762 (delete-horizontal-space) 731 (delete-horizontal-space)
763 (insert (concat " " octave-continuation-string)))) 732 (insert (concat " " octave-continuation-string))))
764 733
765 734
766 ;;; Indentation 735 ;;; Indentation
767 (defun octave-indent-calculate ()
768 "Return appropriate indentation for current line as Octave code.
769 Returns an integer (the column to indent to) unless the line is a
770 comment line with fixed goal golumn. In that case, returns a list whose
771 car is the column to indent to, and whose cdr is the current indentation
772 level."
773 (let ((is-continuation-line
774 (save-excursion
775 (if (zerop (octave-previous-code-line))
776 (looking-at octave-continuation-regexp))))
777 (icol 0))
778 (save-excursion
779 (beginning-of-line)
780 ;; If we can move backward out one level of parentheses, take 1
781 ;; plus the indentation of that parenthesis. Otherwise, go back
782 ;; to the beginning of the previous code line, and compute the
783 ;; offset this line gives.
784 (if (condition-case nil
785 (progn
786 (up-list -1)
787 t)
788 (error nil))
789 (setq icol (+ 1 (current-column)))
790 (if (zerop (octave-previous-code-line))
791 (progn
792 (octave-beginning-of-line)
793 (back-to-indentation)
794 (setq icol (current-column))
795 (let ((bot (point))
796 (eol (line-end-position)))
797 (while (< (point) eol)
798 (if (octave-not-in-string-or-comment-p)
799 (cond
800 ((octave-looking-at-kw "\\<switch\\>")
801 (setq icol (+ icol (* 2 octave-block-offset))))
802 ((octave-looking-at-kw octave-block-begin-regexp)
803 (setq icol (+ icol octave-block-offset)))
804 ((octave-looking-at-kw octave-block-else-regexp)
805 (if (= bot (point))
806 (setq icol (+ icol octave-block-offset))))
807 ((octave-looking-at-kw octave-block-end-regexp)
808 (if (and (not (= bot (point)))
809 ;; special case for `end' keyword,
810 ;; applied to all keywords
811 (not (octave-end-as-array-index-p)))
812 (setq icol (- icol
813 (octave-block-end-offset)))))))
814 (forward-char)))
815 (if is-continuation-line
816 (setq icol (+ icol octave-continuation-offset)))))))
817 (save-excursion
818 (back-to-indentation)
819 (cond
820 ((and (octave-looking-at-kw octave-block-else-regexp)
821 (octave-not-in-string-or-comment-p))
822 (setq icol (- icol octave-block-offset)))
823 ((and (octave-looking-at-kw octave-block-end-regexp)
824 (octave-not-in-string-or-comment-p))
825 (setq icol (- icol (octave-block-end-offset))))
826 ((or (looking-at "\\s<\\s<\\s<\\S<")
827 (octave-before-magic-comment-p))
828 (setq icol (list 0 icol)))
829 ((looking-at "\\s<\\S<")
830 (setq icol (list comment-column icol)))))
831 icol))
832
833 ;; FIXME: this should probably also make sure we are actually looking
834 ;; at the "end" keyword.
835 (defun octave-end-as-array-index-p ()
836 (save-excursion
837 (condition-case nil
838 ;; Check if point is between parens
839 (progn (up-list 1) t)
840 (error nil))))
841
842 (defun octave-block-end-offset ()
843 (save-excursion
844 (octave-backward-up-block 1)
845 (* octave-block-offset
846 (if (string-match (match-string 0) "switch") 2 1))))
847
848 (defun octave-before-magic-comment-p ()
849 (save-excursion
850 (beginning-of-line)
851 (and (bobp) (looking-at "\\s-*#!"))))
852
853 (defun octave-indent-line (&optional arg)
854 "Indent current line as Octave code.
855 With optional ARG, use this as offset unless this line is a comment with
856 fixed goal column."
857 (interactive)
858 (or arg (setq arg 0))
859 (let ((icol (octave-indent-calculate))
860 (relpos (- (current-column) (current-indentation))))
861 (if (listp icol)
862 (setq icol (car icol))
863 (setq icol (+ icol arg)))
864 (if (< icol 0)
865 (error "Unmatched end keyword")
866 (indent-line-to icol)
867 (if (> relpos 0)
868 (move-to-column (+ icol relpos))))))
869 736
870 (defun octave-indent-new-comment-line () 737 (defun octave-indent-new-comment-line ()
871 "Break Octave line at point, continuing comment if within one. 738 "Break Octave line at point, continuing comment if within one.
872 If within code, insert `octave-continuation-string' before breaking the 739 If within code, insert `octave-continuation-string' before breaking the
873 line. If within a string, signal an error. 740 line. If within a string, signal an error.
965 (or (looking-at "\\s-*\\($\\|\\s<\\)") 832 (or (looking-at "\\s-*\\($\\|\\s<\\)")
966 (looking-at octave-continuation-regexp))) 833 (looking-at octave-continuation-regexp)))
967 (zerop (forward-line 1))))) 834 (zerop (forward-line 1)))))
968 (end-of-line))) 835 (end-of-line)))
969 836
970 (defun octave-scan-blocks (count depth)
971 "Scan from point by COUNT Octave begin-end blocks.
972 Returns the character number of the position thus found.
973
974 If DEPTH is nonzero, block depth begins counting from that value.
975 Only places where the depth in blocks becomes zero are candidates for
976 stopping; COUNT such places are counted.
977
978 If the beginning or end of the buffer is reached and the depth is wrong,
979 an error is signaled."
980 (let ((min-depth (if (> depth 0) 0 depth))
981 (inc (if (> count 0) 1 -1)))
982 (save-excursion
983 (while (/= count 0)
984 (catch 'foo
985 (while (or (octave-re-search-forward-kw
986 octave-block-begin-or-end-regexp inc)
987 (if (/= depth 0)
988 (error "Unbalanced block")))
989 (if (octave-not-in-string-or-comment-p)
990 (progn
991 (cond
992 ((match-end 1)
993 (setq depth (+ depth inc)))
994 ((match-end 2)
995 (setq depth (- depth inc))))
996 (if (< depth min-depth)
997 (error "Containing expression ends prematurely"))
998 (if (= depth 0)
999 (throw 'foo nil))))))
1000 (setq count (- count inc)))
1001 (point))))
1002
1003 (defun octave-forward-block (&optional arg)
1004 "Move forward across one balanced Octave begin-end block.
1005 With argument, do it that many times.
1006 Negative arg -N means move backward across N blocks."
1007 (interactive "p")
1008 (or arg (setq arg 1))
1009 (goto-char (or (octave-scan-blocks arg 0) (buffer-end arg))))
1010
1011 (defun octave-backward-block (&optional arg)
1012 "Move backward across one balanced Octave begin-end block.
1013 With argument, do it that many times.
1014 Negative arg -N means move forward across N blocks."
1015 (interactive "p")
1016 (or arg (setq arg 1))
1017 (octave-forward-block (- arg)))
1018
1019 (defun octave-down-block (arg)
1020 "Move forward down one begin-end block level of Octave code.
1021 With argument, do this that many times.
1022 A negative argument means move backward but still go down a level.
1023 In Lisp programs, an argument is required."
1024 (interactive "p")
1025 (let ((inc (if (> arg 0) 1 -1)))
1026 (while (/= arg 0)
1027 (goto-char (or (octave-scan-blocks inc -1)
1028 (buffer-end arg)))
1029 (setq arg (- arg inc)))))
1030
1031 (defun octave-backward-up-block (arg)
1032 "Move backward out of one begin-end block level of Octave code.
1033 With argument, do this that many times.
1034 A negative argument means move forward but still to a less deep spot.
1035 In Lisp programs, an argument is required."
1036 (interactive "p")
1037 (octave-up-block (- arg)))
1038
1039 (defun octave-up-block (arg)
1040 "Move forward out of one begin-end block level of Octave code.
1041 With argument, do this that many times.
1042 A negative argument means move backward but still to a less deep spot.
1043 In Lisp programs, an argument is required."
1044 (interactive "p")
1045 (let ((inc (if (> arg 0) 1 -1)))
1046 (while (/= arg 0)
1047 (goto-char (or (octave-scan-blocks inc 1)
1048 (buffer-end arg)))
1049 (setq arg (- arg inc)))))
1050
1051 (defun octave-mark-block () 837 (defun octave-mark-block ()
1052 "Put point at the beginning of this Octave block, mark at the end. 838 "Put point at the beginning of this Octave block, mark at the end.
1053 The block marked is the one that contains point or follows point." 839 The block marked is the one that contains point or follows point."
1054 (interactive) 840 (interactive)
1055 (let ((pos (point))) 841 (unless (or (looking-at "\\s(")
1056 (if (or (and (octave-in-block-p) 842 (save-excursion
1057 (skip-syntax-forward "w")) 843 (let* ((token (funcall smie-forward-token-function))
1058 (condition-case nil 844 (level (assoc token smie-op-levels)))
1059 (progn 845 (and level (null (cadr level))))))
1060 (octave-down-block 1) 846 (backward-up-list 1))
1061 (octave-in-block-p)) 847 (mark-sexp))
1062 (error nil)))
1063 (progn
1064 (octave-up-block -1)
1065 (push-mark (point))
1066 (octave-forward-block)
1067 (exchange-point-and-mark))
1068 (goto-char pos)
1069 (message "No block to mark found"))))
1070 848
1071 (defun octave-blink-matching-block-open () 849 (defun octave-blink-matching-block-open ()
1072 "Blink the matching Octave begin block keyword. 850 "Blink the matching Octave begin block keyword.
1073 If point is right after an Octave else or end type block keyword, move 851 If point is right after an Octave else or end type block keyword, move
1074 cursor momentarily to the corresponding begin keyword. 852 cursor momentarily to the corresponding begin keyword.
1084 (cond 862 (cond
1085 ((match-end 1) 863 ((match-end 1)
1086 (setq eb-keyword 864 (setq eb-keyword
1087 (buffer-substring-no-properties 865 (buffer-substring-no-properties
1088 (match-beginning 1) (match-end 1))) 866 (match-beginning 1) (match-end 1)))
1089 (octave-backward-up-block 1)) 867 (backward-up-list 1))
1090 ((match-end 2) 868 ((match-end 2)
1091 (setq eb-keyword 869 (setq eb-keyword
1092 (buffer-substring-no-properties 870 (buffer-substring-no-properties
1093 (match-beginning 2) (match-end 2))) 871 (match-beginning 2) (match-end 2)))
1094 (octave-backward-block))) 872 (backward-sexp 1)))
1095 (setq pos (match-end 0) 873 (setq pos (match-end 0)
1096 bb-keyword 874 bb-keyword
1097 (buffer-substring-no-properties 875 (buffer-substring-no-properties
1098 (match-beginning 0) pos) 876 (match-beginning 0) pos)
1099 pos (+ pos 1) 877 pos (+ pos 1)
1200 (setq give-up t))) 978 (setq give-up t)))
1201 (setq give-up t)))) 979 (setq give-up t))))
1202 (not give-up)))) 980 (not give-up))))
1203 981
1204 (defun octave-fill-paragraph (&optional arg) 982 (defun octave-fill-paragraph (&optional arg)
1205 "Fill paragraph of Octave code, handling Octave comments." 983 "Fill paragraph of Octave code, handling Octave comments."
1206 ;; FIXME: now that the default fill-paragraph takes care of similar issues, 984 ;; FIXME: difference with generic fill-paragraph:
1207 ;; this seems obsolete. --Stef 985 ;; - code lines are only split, never joined.
1208 (interactive "P") 986 ;; - \n that end comments are never removed.
1209 (save-excursion 987 ;; - insert continuation marker when splitting code lines.
1210 (let ((end (progn (forward-paragraph) (point))) 988 (interactive "P")
1211 (beg (progn 989 (save-excursion
1212 (forward-paragraph -1) 990 (let ((end (progn (forward-paragraph) (copy-marker (point) t)))
1213 (skip-chars-forward " \t\n") 991 (beg (progn
1214 (beginning-of-line) 992 (forward-paragraph -1)
1215 (point))) 993 (skip-chars-forward " \t\n")
1216 (cfc (current-fill-column)) 994 (beginning-of-line)
1217 (ind (octave-indent-calculate)) 995 (point)))
1218 comment-prefix) 996 (cfc (current-fill-column))
1219 (save-restriction 997 comment-prefix)
1220 (goto-char beg) 998 (goto-char beg)
1221 (narrow-to-region beg end) 999 (while (< (point) end)
1222 (if (listp ind) (setq ind (nth 1 ind))) 1000 (condition-case nil
1223 (while (not (eobp)) 1001 (indent-according-to-mode)
1224 (condition-case nil 1002 (error nil))
1225 (octave-indent-line ind) 1003 (move-to-column cfc)
1226 (error nil)) 1004 ;; First check whether we need to combine non-empty comment lines
1227 (if (and (> ind 0) 1005 (if (and (< (current-column) cfc)
1228 (not 1006 (octave-in-comment-p)
1229 (save-excursion 1007 (not (save-excursion
1230 (beginning-of-line) 1008 (beginning-of-line)
1231 (looking-at "^\\s-*\\($\\|\\s<+\\)")))) 1009 (looking-at "^\\s-*\\s<+\\s-*$"))))
1232 (setq ind 0)) 1010 ;; This is a nonempty comment line which does not extend
1233 (move-to-column cfc) 1011 ;; past the fill column. If it is followed by a nonempty
1234 ;; First check whether we need to combine non-empty comment lines 1012 ;; comment line with the same comment prefix, try to
1235 (if (and (< (current-column) cfc) 1013 ;; combine them, and repeat this until either we reach the
1236 (octave-in-comment-p) 1014 ;; fill-column or there is nothing more to combine.
1237 (not (save-excursion 1015 (progn
1238 (beginning-of-line) 1016 ;; Get the comment prefix
1239 (looking-at "^\\s-*\\s<+\\s-*$")))) 1017 (save-excursion
1240 ;; This is a nonempty comment line which does not extend 1018 (beginning-of-line)
1241 ;; past the fill column. If it is followed by a nonempty 1019 (while (and (re-search-forward "\\s<+")
1242 ;; comment line with the same comment prefix, try to 1020 (not (octave-in-comment-p))))
1243 ;; combine them, and repeat this until either we reach the 1021 (setq comment-prefix (match-string 0)))
1244 ;; fill-column or there is nothing more to combine. 1022 ;; And keep combining ...
1245 (progn 1023 (while (and (< (current-column) cfc)
1246 ;; Get the comment prefix 1024 (save-excursion
1247 (save-excursion 1025 (forward-line 1)
1248 (beginning-of-line) 1026 (and (looking-at
1249 (while (and (re-search-forward "\\s<+") 1027 (concat "^\\s-*"
1250 (not (octave-in-comment-p)))) 1028 comment-prefix
1251 (setq comment-prefix (match-string 0))) 1029 "\\S<"))
1252 ;; And keep combining ... 1030 (not (looking-at
1253 (while (and (< (current-column) cfc) 1031 (concat "^\\s-*"
1254 (save-excursion 1032 comment-prefix
1255 (forward-line 1) 1033 "\\s-*$"))))))
1256 (and (looking-at 1034 (delete-char 1)
1257 (concat "^\\s-*" 1035 (re-search-forward comment-prefix)
1258 comment-prefix 1036 (delete-region (match-beginning 0) (match-end 0))
1259 "\\S<")) 1037 (fixup-whitespace)
1260 (not (looking-at 1038 (move-to-column cfc))))
1261 (concat "^\\s-*" 1039 ;; We might also try to combine continued code lines> Perhaps
1262 comment-prefix 1040 ;; some other time ...
1263 "\\s-*$")))))) 1041 (skip-chars-forward "^ \t\n")
1264 (delete-char 1) 1042 (delete-horizontal-space)
1265 (re-search-forward comment-prefix) 1043 (if (or (< (current-column) cfc)
1266 (delete-region (match-beginning 0) (match-end 0)) 1044 (and (= (current-column) cfc) (eolp)))
1267 (fixup-whitespace) 1045 (forward-line 1)
1268 (move-to-column cfc)))) 1046 (if (not (eolp)) (insert " "))
1269 ;; We might also try to combine continued code lines> Perhaps 1047 (or (octave-auto-fill)
1270 ;; some other time ... 1048 (forward-line 1))))
1271 (skip-chars-forward "^ \t\n") 1049 t)))
1272 (delete-horizontal-space)
1273 (if (or (< (current-column) cfc)
1274 (and (= (current-column) cfc) (eolp)))
1275 (forward-line 1)
1276 (if (not (eolp)) (insert " "))
1277 (or (octave-auto-fill)
1278 (forward-line 1)))))
1279 t)))
1280 1050
1281 1051
1282 ;;; Completions 1052 ;;; Completions
1283 (defun octave-initialize-completions () 1053 (defun octave-initialize-completions ()
1284 "Create an alist for Octave completions." 1054 "Create an alist for Octave completions."