diff options
| -rw-r--r-- | lisp/progmodes/f90.el | 101 |
1 files changed, 76 insertions, 25 deletions
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el index a1c4d539dd7..0f97e3f0012 100644 --- a/lisp/progmodes/f90.el +++ b/lisp/progmodes/f90.el | |||
| @@ -217,9 +217,12 @@ | |||
| 217 | :group 'f90) | 217 | :group 'f90) |
| 218 | 218 | ||
| 219 | (defcustom f90-smart-end 'blink | 219 | (defcustom f90-smart-end 'blink |
| 220 | "*From an END statement, check and fill the end using matching block start. | 220 | "*Qualification of END statements according to the matching block start. |
| 221 | Allowed values are 'blink, 'no-blink, and nil, which determine | 221 | For example, the END that closes an IF block is changed to END |
| 222 | whether to blink the matching beginning." | 222 | IF. If the block has a label, this is added as well. Allowed |
| 223 | values are 'blink, 'no-blink, and nil. If nil, nothing is done. | ||
| 224 | The other two settings have the same effect, but 'blink | ||
| 225 | additionally blinks the cursor to the start of the block." | ||
| 223 | :type '(choice (const blink) (const no-blink) (const nil)) | 226 | :type '(choice (const blink) (const no-blink) (const nil)) |
| 224 | :group 'f90) | 227 | :group 'f90) |
| 225 | 228 | ||
| @@ -428,6 +431,9 @@ Can be overridden by the value of `font-lock-maximum-decoration'.") | |||
| 428 | (modify-syntax-entry ?= "." table) | 431 | (modify-syntax-entry ?= "." table) |
| 429 | (modify-syntax-entry ?* "." table) | 432 | (modify-syntax-entry ?* "." table) |
| 430 | (modify-syntax-entry ?/ "." table) | 433 | (modify-syntax-entry ?/ "." table) |
| 434 | ;; I think that the f95 standard leaves the behaviour of \ | ||
| 435 | ;; unspecified, but that f2k will require it to be non-special. | ||
| 436 | ;; Use `f90-backslash-not-special' to change. | ||
| 431 | (modify-syntax-entry ?\\ "\\" table) ; escape chars | 437 | (modify-syntax-entry ?\\ "\\" table) ; escape chars |
| 432 | table) | 438 | table) |
| 433 | "Syntax table used in F90 mode.") | 439 | "Syntax table used in F90 mode.") |
| @@ -967,6 +973,7 @@ NAME is non-nil only for type." | |||
| 967 | 973 | ||
| 968 | (defsubst f90-looking-at-program-block-start () | 974 | (defsubst f90-looking-at-program-block-start () |
| 969 | "Return (KIND NAME) if a program block with name NAME starts after point." | 975 | "Return (KIND NAME) if a program block with name NAME starts after point." |
| 976 | ;;;NAME is nil for an un-named main PROGRAM block." | ||
| 970 | (cond | 977 | (cond |
| 971 | ((looking-at "\\(program\\)[ \t]+\\(\\sw+\\)\\>") | 978 | ((looking-at "\\(program\\)[ \t]+\\(\\sw+\\)\\>") |
| 972 | (list (match-string 1) (match-string 2))) | 979 | (list (match-string 1) (match-string 2))) |
| @@ -977,6 +984,13 @@ NAME is non-nil only for type." | |||
| 977 | (looking-at "[^!'\"\&\n]*\\(function\\|subroutine\\)[ \t]+\ | 984 | (looking-at "[^!'\"\&\n]*\\(function\\|subroutine\\)[ \t]+\ |
| 978 | \\(\\sw+\\)")) | 985 | \\(\\sw+\\)")) |
| 979 | (list (match-string 1) (match-string 2))))) | 986 | (list (match-string 1) (match-string 2))))) |
| 987 | ;; Following will match an un-named main program block; however | ||
| 988 | ;; one needs to check if there is an actual PROGRAM statement after | ||
| 989 | ;; point (and before any END program). Adding this will require | ||
| 990 | ;; change to eg f90-calculate-indent. | ||
| 991 | ;;; ((save-excursion | ||
| 992 | ;;; (not (f90-previous-statement))) | ||
| 993 | ;;; '("program" nil)))) | ||
| 980 | 994 | ||
| 981 | (defsubst f90-looking-at-program-block-end () | 995 | (defsubst f90-looking-at-program-block-end () |
| 982 | "Return (KIND NAME) if a block with name NAME ends after point." | 996 | "Return (KIND NAME) if a block with name NAME ends after point." |
| @@ -1104,7 +1118,13 @@ Does not check type and subprogram indentation." | |||
| 1104 | (let (icol cont (case-fold-search t) (pnt (point))) | 1118 | (let (icol cont (case-fold-search t) (pnt (point))) |
| 1105 | (save-excursion | 1119 | (save-excursion |
| 1106 | (if (not (f90-previous-statement)) | 1120 | (if (not (f90-previous-statement)) |
| 1107 | (setq icol 0) | 1121 | ;; First statement in buffer. |
| 1122 | (setq icol (if (save-excursion | ||
| 1123 | (f90-next-statement) | ||
| 1124 | (f90-looking-at-program-block-start)) | ||
| 1125 | 0 | ||
| 1126 | ;; No explicit PROGRAM start statement. | ||
| 1127 | f90-program-indent)) | ||
| 1108 | (setq cont (f90-present-statement-cont)) | 1128 | (setq cont (f90-present-statement-cont)) |
| 1109 | (if (eq cont 'end) | 1129 | (if (eq cont 'end) |
| 1110 | (while (not (eq 'begin (f90-present-statement-cont))) | 1130 | (while (not (eq 'begin (f90-present-statement-cont))) |
| @@ -1151,8 +1171,10 @@ Does not check type and subprogram indentation." | |||
| 1151 | 1171 | ||
| 1152 | (defun f90-previous-statement () | 1172 | (defun f90-previous-statement () |
| 1153 | "Move point to beginning of the previous F90 statement. | 1173 | "Move point to beginning of the previous F90 statement. |
| 1154 | Return nil if no previous statement is found. | 1174 | If no previous statement is found (i.e. if called from the first |
| 1155 | A statement is a line which is neither blank nor a comment." | 1175 | statement in the buffer), move to the start of the buffer and |
| 1176 | return nil. A statement is a line which is neither blank nor a | ||
| 1177 | comment." | ||
| 1156 | (interactive) | 1178 | (interactive) |
| 1157 | (let (not-first-statement) | 1179 | (let (not-first-statement) |
| 1158 | (beginning-of-line) | 1180 | (beginning-of-line) |
| @@ -1189,6 +1211,8 @@ Return (TYPE NAME), or nil if not found." | |||
| 1189 | (beginning-of-line) | 1211 | (beginning-of-line) |
| 1190 | (if (zerop count) | 1212 | (if (zerop count) |
| 1191 | matching-beg | 1213 | matching-beg |
| 1214 | ;; Note this includes the case of an un-named main program, | ||
| 1215 | ;; in which case we go to (point-min). | ||
| 1192 | (message "No beginning found.") | 1216 | (message "No beginning found.") |
| 1193 | nil))) | 1217 | nil))) |
| 1194 | 1218 | ||
| @@ -1221,18 +1245,17 @@ Return (TYPE NAME), or nil if not found." | |||
| 1221 | (defun f90-end-of-block (&optional num) | 1245 | (defun f90-end-of-block (&optional num) |
| 1222 | "Move point forward to the end of the current code block. | 1246 | "Move point forward to the end of the current code block. |
| 1223 | With optional argument NUM, go forward that many balanced blocks. | 1247 | With optional argument NUM, go forward that many balanced blocks. |
| 1224 | If NUM is negative, go backward to the start of a block. | 1248 | If NUM is negative, go backward to the start of a block. Checks |
| 1225 | Checks for consistency of block types and labels (if present), | 1249 | for consistency of block types and labels (if present), and |
| 1226 | and completes outermost block if necessary. | 1250 | completes outermost block if `f90-smart-end' is non-nil. |
| 1227 | Some of these things (which?) are not done if NUM is nil, | 1251 | Interactively, pushes mark before moving point." |
| 1228 | which only happens in a noninteractive call." | ||
| 1229 | (interactive "p") | 1252 | (interactive "p") |
| 1230 | (if (and num (< num 0)) (f90-beginning-of-block (- num))) | 1253 | (if (interactive-p) (push-mark (point) t)) ; can move some distance |
| 1231 | (let ((f90-smart-end nil) ; for the final `f90-match-end' | 1254 | (and num (< num 0) (f90-beginning-of-block (- num))) |
| 1255 | (let ((f90-smart-end (if f90-smart-end 'no-blink)) ; for final match-end | ||
| 1232 | (case-fold-search t) | 1256 | (case-fold-search t) |
| 1233 | (count (or num 1)) | 1257 | (count (or num 1)) |
| 1234 | start-list start-this start-type start-label end-type end-label) | 1258 | start-list start-this start-type start-label end-type end-label) |
| 1235 | (if num (push-mark (point) t)) | ||
| 1236 | (end-of-line) ; probably want this | 1259 | (end-of-line) ; probably want this |
| 1237 | (while (and (> count 0) (re-search-forward f90-blocks-re nil 'move)) | 1260 | (while (and (> count 0) (re-search-forward f90-blocks-re nil 'move)) |
| 1238 | (beginning-of-line) | 1261 | (beginning-of-line) |
| @@ -1268,20 +1291,21 @@ which only happens in a noninteractive call." | |||
| 1268 | (end-of-line)) | 1291 | (end-of-line)) |
| 1269 | (if (> count 0) (error "Missing block end")) | 1292 | (if (> count 0) (error "Missing block end")) |
| 1270 | ;; Check outermost block. | 1293 | ;; Check outermost block. |
| 1271 | (if num | 1294 | (when f90-smart-end |
| 1272 | (save-excursion | 1295 | (save-excursion |
| 1273 | (beginning-of-line) | 1296 | (beginning-of-line) |
| 1274 | (skip-chars-forward " \t0-9") | 1297 | (skip-chars-forward " \t0-9") |
| 1275 | (f90-match-end))))) | 1298 | (f90-match-end))))) |
| 1276 | 1299 | ||
| 1277 | (defun f90-beginning-of-block (&optional num) | 1300 | (defun f90-beginning-of-block (&optional num) |
| 1278 | "Move point backwards to the start of the current code block. | 1301 | "Move point backwards to the start of the current code block. |
| 1279 | With optional argument NUM, go backward that many balanced blocks. | 1302 | With optional argument NUM, go backward that many balanced blocks. |
| 1280 | If NUM is negative, go forward to the end of a block. | 1303 | If NUM is negative, go forward to the end of a block. |
| 1281 | Checks for consistency of block types and labels (if present). | 1304 | Checks for consistency of block types and labels (if present). |
| 1282 | Does not check the outermost block, because it may be incomplete." | 1305 | Does not check the outermost block, because it may be incomplete. |
| 1306 | Interactively, pushes mark before moving point." | ||
| 1283 | (interactive "p") | 1307 | (interactive "p") |
| 1284 | (if (and num (< num 0)) (f90-end-of-block (- num))) | 1308 | (and num (< num 0) (f90-end-of-block (- num))) |
| 1285 | (let ((case-fold-search t) | 1309 | (let ((case-fold-search t) |
| 1286 | (count (or num 1)) | 1310 | (count (or num 1)) |
| 1287 | end-list end-this end-type end-label | 1311 | end-list end-this end-type end-label |
| @@ -1320,7 +1344,8 @@ Does not check the outermost block, because it may be incomplete." | |||
| 1320 | (or (f90-equal-symbols start-label end-label) | 1344 | (or (f90-equal-symbols start-label end-label) |
| 1321 | (error "Start label `%s' does not match end label `%s'" | 1345 | (error "Start label `%s' does not match end label `%s'" |
| 1322 | start-label end-label)))))) | 1346 | start-label end-label)))))) |
| 1323 | (if (> count 0) (error "Missing block start")))) | 1347 | ;; Includes an un-named main program block. |
| 1348 | (if (> count 0) (error "Missing block start")))) | ||
| 1324 | 1349 | ||
| 1325 | (defun f90-next-block (&optional num) | 1350 | (defun f90-next-block (&optional num) |
| 1326 | "Move point forward to the next end or start of a code block. | 1351 | "Move point forward to the next end or start of a code block. |
| @@ -1439,6 +1464,8 @@ If run in the middle of a line, the line is not broken." | |||
| 1439 | (f90-indent-line 'no-update)) ; nothing to update | 1464 | (f90-indent-line 'no-update)) ; nothing to update |
| 1440 | 1465 | ||
| 1441 | 1466 | ||
| 1467 | ;; TODO not add spaces to empty lines at the start. | ||
| 1468 | ;; Why is second line getting extra indent over first? | ||
| 1442 | (defun f90-indent-region (beg-region end-region) | 1469 | (defun f90-indent-region (beg-region end-region) |
| 1443 | "Indent every line in region by forward parsing." | 1470 | "Indent every line in region by forward parsing." |
| 1444 | (interactive "*r") | 1471 | (interactive "*r") |
| @@ -1663,9 +1690,13 @@ BEG-NAME is the block start name (may be nil). | |||
| 1663 | END-BLOCK is the type of block as indicated at the end (may be nil). | 1690 | END-BLOCK is the type of block as indicated at the end (may be nil). |
| 1664 | END-NAME is the block end name (may be nil). | 1691 | END-NAME is the block end name (may be nil). |
| 1665 | Leave point at the end of line." | 1692 | Leave point at the end of line." |
| 1693 | ;; Hack to deal with the case when this is called from | ||
| 1694 | ;; f90-indent-region on a program block without an explicit PROGRAM | ||
| 1695 | ;; statement at the start. Should really be an error (?). | ||
| 1696 | (or beg-block (setq beg-block "program")) | ||
| 1666 | (search-forward "end" (line-end-position)) | 1697 | (search-forward "end" (line-end-position)) |
| 1667 | (catch 'no-match | 1698 | (catch 'no-match |
| 1668 | (if (f90-equal-symbols beg-block end-block) | 1699 | (if (and end-block (f90-equal-symbols beg-block end-block)) |
| 1669 | (search-forward end-block) | 1700 | (search-forward end-block) |
| 1670 | (if end-block | 1701 | (if end-block |
| 1671 | (progn | 1702 | (progn |
| @@ -1703,7 +1734,9 @@ Leave point at the end of line." | |||
| 1703 | end-name (car (cdr end-struct))) | 1734 | end-name (car (cdr end-struct))) |
| 1704 | (save-excursion | 1735 | (save-excursion |
| 1705 | (beginning-of-line) | 1736 | (beginning-of-line) |
| 1706 | (while (and (> count 0) (re-search-backward f90-blocks-re nil t)) | 1737 | (while (and (> count 0) |
| 1738 | (not (= (line-beginning-position) (point-min)))) | ||
| 1739 | (re-search-backward f90-blocks-re nil 'move) | ||
| 1707 | (beginning-of-line) | 1740 | (beginning-of-line) |
| 1708 | ;; GM not a line number if continued line. | 1741 | ;; GM not a line number if continued line. |
| 1709 | ;;; (skip-chars-forward " \t") | 1742 | ;;; (skip-chars-forward " \t") |
| @@ -1717,7 +1750,12 @@ Leave point at the end of line." | |||
| 1717 | (f90-looking-at-where-or-forall) | 1750 | (f90-looking-at-where-or-forall) |
| 1718 | (f90-looking-at-select-case) | 1751 | (f90-looking-at-select-case) |
| 1719 | (f90-looking-at-type-like) | 1752 | (f90-looking-at-type-like) |
| 1720 | (f90-looking-at-program-block-start))) | 1753 | (f90-looking-at-program-block-start) |
| 1754 | ;; Interpret a single END without a block | ||
| 1755 | ;; start to be the END of a program block | ||
| 1756 | ;; without an initial PROGRAM line. | ||
| 1757 | (if (= (line-beginning-position) (point-min)) | ||
| 1758 | '("program" nil)))) | ||
| 1721 | (setq count (1- count))) | 1759 | (setq count (1- count))) |
| 1722 | ((looking-at (concat "end[ \t]*" f90-blocks-re)) | 1760 | ((looking-at (concat "end[ \t]*" f90-blocks-re)) |
| 1723 | (setq count (1+ count))))) | 1761 | (setq count (1+ count))))) |
| @@ -1850,6 +1888,19 @@ CHANGE-WORD should be one of 'upcase-word, 'downcase-word, 'capitalize-word." | |||
| 1850 | (save-excursion | 1888 | (save-excursion |
| 1851 | (nth 1 (f90-beginning-of-subprogram)))) | 1889 | (nth 1 (f90-beginning-of-subprogram)))) |
| 1852 | 1890 | ||
| 1891 | |||
| 1892 | (defun f90-backslash-not-special (&optional all) | ||
| 1893 | "Make the backslash character (\\) be non-special in the current buffer. | ||
| 1894 | With optional argument ALL, change the default for all present | ||
| 1895 | and future F90 buffers. F90 mode normally treats backslash as an | ||
| 1896 | escape character." | ||
| 1897 | (or (eq major-mode 'f90-mode) | ||
| 1898 | (error "This function should only be used in F90 buffers")) | ||
| 1899 | (when (equal (char-syntax ?\\ ) ?\\ ) | ||
| 1900 | (or all (set-syntax-table (copy-syntax-table (syntax-table)))) | ||
| 1901 | (modify-syntax-entry ?\\ "."))) | ||
| 1902 | |||
| 1903 | |||
| 1853 | (provide 'f90) | 1904 | (provide 'f90) |
| 1854 | 1905 | ||
| 1855 | ;;; arch-tag: fceac97c-c147-44bd-aec0-172d4b560ef8 | 1906 | ;;; arch-tag: fceac97c-c147-44bd-aec0-172d4b560ef8 |