diff options
| -rw-r--r-- | lisp/progmodes/sh-script.el | 284 |
1 files changed, 139 insertions, 145 deletions
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index 0255eb17ee8..877b27dbdb8 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el | |||
| @@ -921,21 +921,19 @@ a number means align to that column, e.g. 0 means fist column." | |||
| 921 | ;; (apply 'message args))) | 921 | ;; (apply 'message args))) |
| 922 | (defmacro sh-debug (&rest args)) | 922 | (defmacro sh-debug (&rest args)) |
| 923 | 923 | ||
| 924 | (setq sh-symbol-list | 924 | (defconst sh-symbol-list |
| 925 | '( | 925 | '((const :tag "+ " :value + |
| 926 | (const :tag "+ " :value + | 926 | :menu-tag "+ Indent right by sh-basic-offset") |
| 927 | :menu-tag "+ Indent right by sh-basic-offset") | 927 | (const :tag "- " :value - |
| 928 | (const :tag "- " :value - | 928 | :menu-tag "- Indent left by sh-basic-offset") |
| 929 | :menu-tag "- Indent left by sh-basic-offset") | 929 | (const :tag "++" :value ++ |
| 930 | (const :tag "++" :value ++ | 930 | :menu-tag "++ Indent right twice sh-basic-offset") |
| 931 | :menu-tag "++ Indent right twice sh-basic-offset") | 931 | (const :tag "--" :value -- |
| 932 | (const :tag "--" :value -- | 932 | :menu-tag "-- Indent left twice sh-basic-offset") |
| 933 | :menu-tag "-- Indent left twice sh-basic-offset") | 933 | (const :tag "* " :value * |
| 934 | (const :tag "* " :value * | 934 | :menu-tag "* Indent right half sh-basic-offset") |
| 935 | :menu-tag "* Indent right half sh-basic-offset") | 935 | (const :tag "/ " :value / |
| 936 | (const :tag "/ " :value / | 936 | :menu-tag "/ Indent left half sh-basic-offset"))) |
| 937 | :menu-tag "/ Indent left half sh-basic-offset") | ||
| 938 | )) | ||
| 939 | 937 | ||
| 940 | (defcustom sh-indent-for-else 0 | 938 | (defcustom sh-indent-for-else 0 |
| 941 | "*How much to indent an else relative to an if. Usually 0." | 939 | "*How much to indent an else relative to an if. Usually 0." |
| @@ -947,13 +945,11 @@ a number means align to that column, e.g. 0 means fist column." | |||
| 947 | ) | 945 | ) |
| 948 | :group 'sh-indentation) | 946 | :group 'sh-indentation) |
| 949 | 947 | ||
| 950 | (setq sh-number-or-symbol-list | 948 | (defconst sh-number-or-symbol-list |
| 951 | (append (list '( | 949 | (append (list '(integer :menu-tag "A number (positive=>indent right)" |
| 952 | integer :menu-tag "A number (positive=>indent right)" | 950 | :tag "A number") |
| 953 | :tag "A number") | 951 | '(const :tag "--")) ; separator |
| 954 | '(const :tag "--") ;; separator | 952 | sh-symbol-list)) |
| 955 | ) | ||
| 956 | sh-symbol-list)) | ||
| 957 | 953 | ||
| 958 | (defcustom sh-indent-for-fi 0 | 954 | (defcustom sh-indent-for-fi 0 |
| 959 | "*How much to indent a fi relative to an if. Usually 0." | 955 | "*How much to indent a fi relative to an if. Usually 0." |
| @@ -1104,34 +1100,32 @@ This specifically excludes an occurance of WORD followed by | |||
| 1104 | or preceded by punctuation characters like '-'." | 1100 | or preceded by punctuation characters like '-'." |
| 1105 | (concat "\\(^\\|[^-a-z0-9_]\\)" word "\\([^-a-z0-9_]\\|$\\)")) | 1101 | (concat "\\(^\\|[^-a-z0-9_]\\)" word "\\([^-a-z0-9_]\\|$\\)")) |
| 1106 | 1102 | ||
| 1107 | (setq sh-re-done (sh-mkword-regexpr "done")) | 1103 | (defconst sh-re-done (sh-mkword-regexpr "done")) |
| 1108 | 1104 | ||
| 1109 | 1105 | ||
| 1110 | (defconst sh-kws-for-done | 1106 | (defconst sh-kws-for-done |
| 1111 | '( | 1107 | '((sh . ( "while" "until" "for" ) ) |
| 1112 | (sh . ( "while" "until" "for" ) ) | ||
| 1113 | (bash . ( "while" "until" "for" "select" ) ) | 1108 | (bash . ( "while" "until" "for" "select" ) ) |
| 1114 | (ksh88 . ( "while" "until" "for" "select" ) ) | 1109 | (ksh88 . ( "while" "until" "for" "select" ) ) |
| 1115 | (zsh . ( "while" "until" "for" "repeat" "select" ) ) | 1110 | (zsh . ( "while" "until" "for" "repeat" "select" ) ) ) |
| 1116 | ) | 1111 | "Which keywords can match the word `done' in this shell.") |
| 1117 | "Which keywords can match the word `done' in this shell." | ||
| 1118 | ) | ||
| 1119 | 1112 | ||
| 1120 | 1113 | ||
| 1121 | (defconst sh-indent-supported | 1114 | (defconst sh-indent-supported |
| 1122 | '( | 1115 | '((sh . t) |
| 1123 | (sh . t) | ||
| 1124 | (csh . nil) | 1116 | (csh . nil) |
| 1125 | (rc . t) | 1117 | (rc . t)) |
| 1126 | ) | 1118 | "Shell types that shell indenting can do something with.") |
| 1127 | "Shell types that shell indenting can do something with." | 1119 | |
| 1128 | ) | 1120 | (defvar sh-indent-supported-here nil |
| 1121 | "Non-nil if we support indentation for the current buffer's shell type.") | ||
| 1129 | 1122 | ||
| 1130 | (defconst sh-electric-rparen-needed | 1123 | (defconst sh-electric-rparen-needed |
| 1131 | '( | 1124 | '((sh . t)) |
| 1132 | (sh . t)) | 1125 | "Non-nil if the shell type needs an electric handling of case alternatives.") |
| 1133 | "Non-nil if the shell type needs an electric handling of case alternatives." | 1126 | |
| 1134 | ) | 1127 | (defvar sh-electric-rparen-needed-here nil |
| 1128 | "Non-nil if the buffer needs an electric handling of case alternatives.") | ||
| 1135 | 1129 | ||
| 1136 | (defconst sh-var-list | 1130 | (defconst sh-var-list |
| 1137 | '( | 1131 | '( |
| @@ -1345,6 +1339,106 @@ This adds rules for comments and assignments." | |||
| 1345 | (sh-font-lock-keywords-1 t)) | 1339 | (sh-font-lock-keywords-1 t)) |
| 1346 | 1340 | ||
| 1347 | 1341 | ||
| 1342 | (defvar sh-regexp-for-done nil | ||
| 1343 | "A buffer-local regexp to match opening keyword for done.") | ||
| 1344 | |||
| 1345 | (defvar sh-kw-alist nil | ||
| 1346 | "A buffer-local, since it is shell-type dependent, list of keywords.") | ||
| 1347 | |||
| 1348 | ;; ( key-word first-on-this on-prev-line ) | ||
| 1349 | ;; This is used to set `sh-kw-alist' which is a list of sublists each | ||
| 1350 | ;; having 3 elements: | ||
| 1351 | ;; a keyword | ||
| 1352 | ;; a rule to check when the keyword apepars on "this" line | ||
| 1353 | ;; a rule to check when the keyword apepars on "the previous" line | ||
| 1354 | ;; The keyword is usually a string and is the first word on a line. | ||
| 1355 | ;; If this keyword appears on the line whose indenation is to be | ||
| 1356 | ;; calculated, the rule in element 2 is called. If this returns | ||
| 1357 | ;; non-zero, the resulting point (which may be changed by the rule) | ||
| 1358 | ;; is used as the default indentation. | ||
| 1359 | ;; If it returned false or the keyword was not found in the table, | ||
| 1360 | ;; then the keyword from the previous line is looked up and the rule | ||
| 1361 | ;; in element 3 is called. In this case, however, | ||
| 1362 | ;; `sh-get-indent-info' does not stop but may keepp going and test | ||
| 1363 | ;; other keywords against rules in element 3. This is because the | ||
| 1364 | ;; precending line could have, for example, an opening "if" and an | ||
| 1365 | ;; opening "while" keyword and we need to add the indentation offsets | ||
| 1366 | ;; for both. | ||
| 1367 | ;; | ||
| 1368 | (defconst sh-kw | ||
| 1369 | '( | ||
| 1370 | (sh | ||
| 1371 | ( "if" | ||
| 1372 | nil | ||
| 1373 | sh-handle-prev-if ) | ||
| 1374 | ( "elif" | ||
| 1375 | sh-handle-this-else | ||
| 1376 | sh-handle-prev-else ) | ||
| 1377 | ( "else" | ||
| 1378 | sh-handle-this-else | ||
| 1379 | sh-handle-prev-else ) | ||
| 1380 | ( "fi" | ||
| 1381 | sh-handle-this-fi | ||
| 1382 | sh-handle-prev-fi ) | ||
| 1383 | ( "then" | ||
| 1384 | sh-handle-this-then | ||
| 1385 | sh-handle-prev-then ) | ||
| 1386 | ( "(" | ||
| 1387 | nil | ||
| 1388 | sh-handle-prev-open ) | ||
| 1389 | ( "{" | ||
| 1390 | nil | ||
| 1391 | sh-handle-prev-open ) | ||
| 1392 | ( "[" | ||
| 1393 | nil | ||
| 1394 | sh-handle-prev-open ) | ||
| 1395 | ( "}" | ||
| 1396 | sh-handle-this-close | ||
| 1397 | nil ) | ||
| 1398 | ( ")" | ||
| 1399 | sh-handle-this-close | ||
| 1400 | nil ) | ||
| 1401 | ( "]" | ||
| 1402 | sh-handle-this-close | ||
| 1403 | nil ) | ||
| 1404 | ( "case" | ||
| 1405 | nil | ||
| 1406 | sh-handle-prev-case ) | ||
| 1407 | ( "esac" | ||
| 1408 | sh-handle-this-esac | ||
| 1409 | sh-handle-prev-esac ) | ||
| 1410 | ( case-label | ||
| 1411 | nil ;; ??? | ||
| 1412 | sh-handle-after-case-label ) | ||
| 1413 | ( ";;" | ||
| 1414 | nil ;; ??? | ||
| 1415 | sh-handle-prev-case-alt-end ;; ?? | ||
| 1416 | ) | ||
| 1417 | ( "done" | ||
| 1418 | sh-handle-this-done | ||
| 1419 | sh-handle-prev-done ) | ||
| 1420 | ( "do" | ||
| 1421 | sh-handle-this-do | ||
| 1422 | sh-handle-prev-do ) | ||
| 1423 | ) ;; end of sh | ||
| 1424 | |||
| 1425 | ;; Note: we don't need specific stuff for bash and zsh shells; | ||
| 1426 | ;; the regexp `sh-regexp-for-done' handles the extra keywords | ||
| 1427 | ;; these shells use. | ||
| 1428 | (rc | ||
| 1429 | ( "{" | ||
| 1430 | nil | ||
| 1431 | sh-handle-prev-open ) | ||
| 1432 | ( "}" | ||
| 1433 | sh-handle-this-close | ||
| 1434 | nil ) | ||
| 1435 | ( "case" | ||
| 1436 | sh-handle-this-rc-case | ||
| 1437 | sh-handle-prev-rc-case ) | ||
| 1438 | ) ;; end of rc | ||
| 1439 | )) | ||
| 1440 | |||
| 1441 | |||
| 1348 | (defun sh-set-shell (shell &optional no-query-flag insert-flag) | 1442 | (defun sh-set-shell (shell &optional no-query-flag insert-flag) |
| 1349 | "Set this buffer's shell to SHELL (a string). | 1443 | "Set this buffer's shell to SHELL (a string). |
| 1350 | Makes this script executable via `executable-set-magic', and sets up the | 1444 | Makes this script executable via `executable-set-magic', and sets up the |
| @@ -1637,110 +1731,10 @@ Then, if variable `sh-make-vars-local' is non-nil, make them local." | |||
| 1637 | (mapcar 'make-local-variable sh-var-list))) | 1731 | (mapcar 'make-local-variable sh-var-list))) |
| 1638 | 1732 | ||
| 1639 | 1733 | ||
| 1640 | (defvar sh-kw-alist nil | ||
| 1641 | "A buffer-local, since it is shell-type dependent, list of keywords.") | ||
| 1642 | |||
| 1643 | (defvar sh-regexp-for-done nil | ||
| 1644 | "A buffer-local regexp to match opening keyword for done.") | ||
| 1645 | |||
| 1646 | ;; Theoretically these are only needed in shell and derived modes. | 1734 | ;; Theoretically these are only needed in shell and derived modes. |
| 1647 | ;; However, the routines which use them are only called in those modes. | 1735 | ;; However, the routines which use them are only called in those modes. |
| 1648 | (defconst sh-special-keywords "then\\|do") | 1736 | (defconst sh-special-keywords "then\\|do") |
| 1649 | 1737 | ||
| 1650 | ;; ( key-word first-on-this on-prev-line ) | ||
| 1651 | ;; This is used to set `sh-kw-alist' which is a list of sublists each | ||
| 1652 | ;; having 3 elements: | ||
| 1653 | ;; a keyword | ||
| 1654 | ;; a rule to check when the keyword apepars on "this" line | ||
| 1655 | ;; a rule to check when the keyword apepars on "the previous" line | ||
| 1656 | ;; The keyword is usually a string and is the first word on a line. | ||
| 1657 | ;; If this keyword appears on the line whose indenation is to be | ||
| 1658 | ;; calculated, the rule in element 2 is called. If this returns | ||
| 1659 | ;; non-zero, the resulting point (which may be changed by the rule) | ||
| 1660 | ;; is used as the default indentation. | ||
| 1661 | ;; If it returned false or the keyword was not found in the table, | ||
| 1662 | ;; then the keyword from the previous line is looked up and the rule | ||
| 1663 | ;; in element 3 is called. In this case, however, | ||
| 1664 | ;; `sh-get-indent-info' does not stop but may keepp going and test | ||
| 1665 | ;; other keywords against rules in element 3. This is because the | ||
| 1666 | ;; precending line could have, for example, an opening "if" and an | ||
| 1667 | ;; opening "while" keyword and we need to add the indentation offsets | ||
| 1668 | ;; for both. | ||
| 1669 | ;; | ||
| 1670 | (defconst sh-kw | ||
| 1671 | '( | ||
| 1672 | (sh | ||
| 1673 | ( "if" | ||
| 1674 | nil | ||
| 1675 | sh-handle-prev-if ) | ||
| 1676 | ( "elif" | ||
| 1677 | sh-handle-this-else | ||
| 1678 | sh-handle-prev-else ) | ||
| 1679 | ( "else" | ||
| 1680 | sh-handle-this-else | ||
| 1681 | sh-handle-prev-else ) | ||
| 1682 | ( "fi" | ||
| 1683 | sh-handle-this-fi | ||
| 1684 | sh-handle-prev-fi ) | ||
| 1685 | ( "then" | ||
| 1686 | sh-handle-this-then | ||
| 1687 | sh-handle-prev-then ) | ||
| 1688 | ( "(" | ||
| 1689 | nil | ||
| 1690 | sh-handle-prev-open ) | ||
| 1691 | ( "{" | ||
| 1692 | nil | ||
| 1693 | sh-handle-prev-open ) | ||
| 1694 | ( "[" | ||
| 1695 | nil | ||
| 1696 | sh-handle-prev-open ) | ||
| 1697 | ( "}" | ||
| 1698 | sh-handle-this-close | ||
| 1699 | nil ) | ||
| 1700 | ( ")" | ||
| 1701 | sh-handle-this-close | ||
| 1702 | nil ) | ||
| 1703 | ( "]" | ||
| 1704 | sh-handle-this-close | ||
| 1705 | nil ) | ||
| 1706 | ( "case" | ||
| 1707 | nil | ||
| 1708 | sh-handle-prev-case ) | ||
| 1709 | ( "esac" | ||
| 1710 | sh-handle-this-esac | ||
| 1711 | sh-handle-prev-esac ) | ||
| 1712 | ( case-label | ||
| 1713 | nil ;; ??? | ||
| 1714 | sh-handle-after-case-label ) | ||
| 1715 | ( ";;" | ||
| 1716 | nil ;; ??? | ||
| 1717 | sh-handle-prev-case-alt-end ;; ?? | ||
| 1718 | ) | ||
| 1719 | ( "done" | ||
| 1720 | sh-handle-this-done | ||
| 1721 | sh-handle-prev-done ) | ||
| 1722 | ( "do" | ||
| 1723 | sh-handle-this-do | ||
| 1724 | sh-handle-prev-do ) | ||
| 1725 | ) ;; end of sh | ||
| 1726 | |||
| 1727 | ;; Note: we don't need specific stuff for bash and zsh shells; | ||
| 1728 | ;; the regexp `sh-regexp-for-done' handles the extra keywords | ||
| 1729 | ;; these shells use. | ||
| 1730 | (rc | ||
| 1731 | ( "{" | ||
| 1732 | nil | ||
| 1733 | sh-handle-prev-open ) | ||
| 1734 | ( "}" | ||
| 1735 | sh-handle-this-close | ||
| 1736 | nil ) | ||
| 1737 | ( "case" | ||
| 1738 | sh-handle-this-rc-case | ||
| 1739 | sh-handle-prev-rc-case ) | ||
| 1740 | ) ;; end of rc | ||
| 1741 | )) | ||
| 1742 | |||
| 1743 | |||
| 1744 | (defun sh-help-string-for-variable (var) | 1738 | (defun sh-help-string-for-variable (var) |
| 1745 | "Construct a string for `sh-read-variable' when changing variable VAR ." | 1739 | "Construct a string for `sh-read-variable' when changing variable VAR ." |
| 1746 | (let ((msg (documentation-property var 'variable-documentation)) | 1740 | (let ((msg (documentation-property var 'variable-documentation)) |
| @@ -1759,7 +1753,7 @@ which in this buffer is currently %s. | |||
| 1759 | 1753 | ||
| 1760 | \t%s." | 1754 | \t%s." |
| 1761 | sh-basic-offset | 1755 | sh-basic-offset |
| 1762 | (mapconcat '(lambda (x) | 1756 | (mapconcat (lambda (x) |
| 1763 | (nth (1- (length x)) x) ) | 1757 | (nth (1- (length x)) x) ) |
| 1764 | sh-symbol-list "\n\t") | 1758 | sh-symbol-list "\n\t") |
| 1765 | ))) | 1759 | ))) |
| @@ -3152,7 +3146,7 @@ Return values: | |||
| 3152 | (setq x (append x (list (cons i (aref totals i)))))) | 3146 | (setq x (append x (list (cons i (aref totals i)))))) |
| 3153 | (setq i (1+ i))) | 3147 | (setq i (1+ i))) |
| 3154 | 3148 | ||
| 3155 | (setq x (sort x '(lambda (a b) | 3149 | (setq x (sort x (lambda (a b) |
| 3156 | (> (cdr a)(cdr b))))) | 3150 | (> (cdr a)(cdr b))))) |
| 3157 | (setq tot (apply '+ (append totals nil))) | 3151 | (setq tot (apply '+ (append totals nil))) |
| 3158 | (sh-debug (format "vec: %s\ntotals: %s\ntot: %d" | 3152 | (sh-debug (format "vec: %s\ntotals: %s\ntot: %d" |
| @@ -3242,8 +3236,8 @@ If this parenthesis is a case alternative, set its syntax class to a word." | |||
| 3242 | )))))) | 3236 | )))))) |
| 3243 | 3237 | ||
| 3244 | (defun sh-electric-rparen () | 3238 | (defun sh-electric-rparen () |
| 3245 | "Insert a right parethese, and check if it is a case alternative. | 3239 | "Insert a right parenthesis and check if it is a case alternative. |
| 3246 | If so, its syntax class is set to word, and its text proerty | 3240 | If so, its syntax class is set to word, and its text property |
| 3247 | is set to have face `sh-st-face'." | 3241 | is set to have face `sh-st-face'." |
| 3248 | (interactive) | 3242 | (interactive) |
| 3249 | (insert ")") | 3243 | (insert ")") |
| @@ -3253,7 +3247,7 @@ is set to have face `sh-st-face'." | |||
| 3253 | (defun sh-electric-hash () | 3247 | (defun sh-electric-hash () |
| 3254 | "Insert a hash, but check it is preceded by \"$\". | 3248 | "Insert a hash, but check it is preceded by \"$\". |
| 3255 | If so, it is given a syntax type of comment. | 3249 | If so, it is given a syntax type of comment. |
| 3256 | Its text proerty has face `sh-st-face'." | 3250 | Its text property has face `sh-st-face'." |
| 3257 | (interactive) | 3251 | (interactive) |
| 3258 | (let ((pos (point))) | 3252 | (let ((pos (point))) |
| 3259 | (insert "#") | 3253 | (insert "#") |
| @@ -3315,7 +3309,7 @@ Argument ARG if non-nil disables this test." | |||
| 3315 | )) | 3309 | )) |
| 3316 | 3310 | ||
| 3317 | (defun sh-search-word (word &optional limit) | 3311 | (defun sh-search-word (word &optional limit) |
| 3318 | "Search forward for regexp WORD occuring as a word not in string nor comment. | 3312 | "Search forward for regexp WORD occurring as a word not in string nor comment. |
| 3319 | If found, returns non nil with the match available in \(match-string 2\). | 3313 | If found, returns non nil with the match available in \(match-string 2\). |
| 3320 | Yes 2, not 1, since we build a regexp to guard against false matches | 3314 | Yes 2, not 1, since we build a regexp to guard against false matches |
| 3321 | such as matching \"a-case\" when we are searching for \"case\". | 3315 | such as matching \"a-case\" when we are searching for \"case\". |