summaryrefslogtreecommitdiff
path: root/lisp/progmodes/sh-script.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes/sh-script.el')
-rw-r--r--lisp/progmodes/sh-script.el76
1 files changed, 41 insertions, 35 deletions
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 035dd50771e..aad38b94d76 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -345,7 +345,7 @@ naming the shell."
:group 'sh-script)
(defcustom sh-imenu-generic-expression
- `((sh
+ '((sh
. ((nil
;; function FOO
;; function FOO()
@@ -578,6 +578,7 @@ This is buffer-local in every such buffer.")
:group 'sh-script)
(defcustom sh-assignment-regexp
+ ;; The "\\[.+\\]" matches the "[index]" in "arrayvar[index]=value".
`((csh . "\\<\\([[:alnum:]_]+\\)\\(\\[.+\\]\\)?[ \t]*[-+*/%^]?=")
;; actually spaces are only supported in let/(( ... ))
(ksh88 . ,(concat "\\<\\([[:alnum:]_]+\\)\\(\\[.+\\]\\)?"
@@ -959,8 +960,8 @@ See `sh-feature'.")
;; ((...)) or $((...)) or $[...] or ${...}. Nested
;; parenthesis can occur inside the first of these forms, so
;; parse backward recursively.
- (`?\( (eq ?\( (char-before)))
- ((or `?\{ `?\[) (eq ?\$ (char-before))))
+ (?\( (eq ?\( (char-before)))
+ ((or ?\{ ?\[) (eq ?\$ (char-before))))
(sh--inside-noncommand-expression (1- (point))))))))
(defun sh-font-lock-open-heredoc (start string eol)
@@ -1022,7 +1023,7 @@ subshells can nest."
;; unescape " inside a $( ... ) construct.
(pcase (char-after)
(?\' (pcase state
- (`double-quote nil)
+ ('double-quote nil)
(_ (forward-char 1)
;; FIXME: mark skipped double quotes as punctuation syntax.
(let ((spos (point)))
@@ -1035,12 +1036,12 @@ subshells can nest."
'syntax-table '(1)))))))))
(?\\ (forward-char 1))
(?\" (pcase state
- (`double-quote (setq state (pop states)))
+ ('double-quote (setq state (pop states)))
(_ (push state states) (setq state 'double-quote)))
(if state (put-text-property (point) (1+ (point))
'syntax-table '(1))))
(?\` (pcase state
- (`backquote (setq state (pop states)))
+ ('backquote (setq state (pop states)))
(_ (push state states) (setq state 'backquote))))
(?\$ (if (not (eq (char-after (1+ (point))) ?\())
nil
@@ -1048,10 +1049,10 @@ subshells can nest."
(pcase state
(_ (push state states) (setq state 'code)))))
(?\( (pcase state
- (`double-quote nil)
+ ('double-quote nil)
(_ (push state states) (setq state 'code))))
(?\) (pcase state
- (`double-quote nil)
+ ('double-quote nil)
(_ (setq state (pop states)))))
(_ (error "Internal error in sh-font-lock-quoted-subshell")))
(forward-char 1))
@@ -1141,7 +1142,13 @@ subshells can nest."
;; metacharacters. The list of special chars is taken from
;; the single-unix spec of the shell command language (under
;; `quoting') but with `$' removed.
- ("\\(?:[^|&;<>()`\\\"' \t\n]\\|\\${\\)\\(#+\\)" (1 "_"))
+ ("\\(?:[^|&;<>(`\\\"' \t\n]\\|\\${\\)\\(#+\\)" (1 "_"))
+ ;; In addition, `#' at the beginning of closed parentheses
+ ;; does not start a comment if the parentheses are not isolated
+ ;; by metacharacters, excluding [()].
+ ;; (e.g. `foo(#q/)' and `(#b)foo' in zsh)
+ ("[^|&;<>(`\\\"' \t\n](\\(#+\\)" (1 "_"))
+ ("(\\(#\\)[^)]+?)[^|&;<>)`\\\"' \t\n]" (1 "_"))
;; In a '...' the backslash is not escaping.
("\\(\\\\\\)'" (1 (sh-font-lock-backslash-quote)))
;; Make sure $@ and $? are correctly recognized as sexps.
@@ -1601,7 +1608,7 @@ with your script for an edit-interpret-debug cycle."
(setq-local comint-prompt-regexp "^[ \t]*")
(setq-local imenu-case-fold-search nil)
(setq font-lock-defaults
- `((sh-font-lock-keywords
+ '((sh-font-lock-keywords
sh-font-lock-keywords-1 sh-font-lock-keywords-2)
nil nil
((?/ . "w") (?~ . "w") (?. . "w") (?- . "w") (?_ . "w")) nil
@@ -1619,9 +1626,9 @@ with your script for an edit-interpret-debug cycle."
(setq-local defun-prompt-regexp
(concat
"^\\("
- "\\(function[ \t]\\)?[ \t]*[[:alnum:]]+[ \t]*([ \t]*)"
+ "\\(function[ \t]\\)?[ \t]*[[:alnum:]_]+[ \t]*([ \t]*)"
"\\|"
- "function[ \t]+[[:alnum:]]+[ \t]*\\(([ \t]*)\\)?"
+ "function[ \t]+[[:alnum:]_]+[ \t]*\\(([ \t]*)\\)?"
"\\)[ \t]*"))
(setq-local add-log-current-defun-function #'sh-current-defun-name)
(add-hook 'completion-at-point-functions
@@ -2035,10 +2042,10 @@ May return nil if the line should not be treated as continued."
(defun sh-smie-sh-rules (kind token)
(pcase (cons kind token)
- (`(:elem . basic) sh-basic-offset)
- (`(:after . "case-)") (- (sh-var-value 'sh-indent-for-case-alt)
+ ('(:elem . basic) sh-basic-offset)
+ ('(:after . "case-)") (- (sh-var-value 'sh-indent-for-case-alt)
(sh-var-value 'sh-indent-for-case-label)))
- (`(:before . ,(or `"(" `"{" `"[" "while" "if" "for" "case"))
+ (`(:before . ,(or "(" "{" "[" "while" "if" "for" "case"))
(if (not (smie-rule-prev-p "&&" "||" "|"))
(when (smie-rule-hanging-p)
(smie-rule-parent))
@@ -2047,11 +2054,11 @@ May return nil if the line should not be treated as continued."
`(column . ,(smie-indent-virtual)))))
;; FIXME: Maybe this handling of ;; should be made into
;; a smie-rule-terminator function that takes the substitute ";" as arg.
- (`(:before . ,(or `";;" `";&" `";;&"))
+ (`(:before . ,(or ";;" ";&" ";;&"))
(if (and (smie-rule-bolp) (looking-at ";;?&?[ \t]*\\(#\\|$\\)"))
(cons 'column (smie-indent-keyword ";"))
(smie-rule-separator kind)))
- (`(:after . ,(or `";;" `";&" `";;&"))
+ (`(:after . ,(or ";;" ";&" ";;&"))
(with-demoted-errors
(smie-backward-sexp token)
(cons 'column
@@ -2062,26 +2069,26 @@ May return nil if the line should not be treated as continued."
(smie-rule-bolp))))
(current-column)
(smie-indent-calculate)))))
- (`(:before . ,(or `"|" `"&&" `"||"))
+ (`(:before . ,(or "|" "&&" "||"))
(unless (smie-rule-parent-p token)
(smie-backward-sexp token)
`(column . ,(+ (funcall smie-rules-function :elem 'basic)
(smie-indent-virtual)))))
;; Attempt at backward compatibility with the old config variables.
- (`(:before . "fi") (sh-var-value 'sh-indent-for-fi))
- (`(:before . "done") (sh-var-value 'sh-indent-for-done))
- (`(:after . "else") (sh-var-value 'sh-indent-after-else))
- (`(:after . "if") (sh-var-value 'sh-indent-after-if))
- (`(:before . "then") (sh-var-value 'sh-indent-for-then))
- (`(:before . "do") (sh-var-value 'sh-indent-for-do))
- (`(:after . "do")
+ ('(:before . "fi") (sh-var-value 'sh-indent-for-fi))
+ ('(:before . "done") (sh-var-value 'sh-indent-for-done))
+ ('(:after . "else") (sh-var-value 'sh-indent-after-else))
+ ('(:after . "if") (sh-var-value 'sh-indent-after-if))
+ ('(:before . "then") (sh-var-value 'sh-indent-for-then))
+ ('(:before . "do") (sh-var-value 'sh-indent-for-do))
+ ('(:after . "do")
(sh-var-value (if (smie-rule-hanging-p)
'sh-indent-after-loop-construct 'sh-indent-after-do)))
;; sh-indent-after-done: aligned completely differently.
- (`(:after . "in") (sh-var-value 'sh-indent-for-case-label))
+ ('(:after . "in") (sh-var-value 'sh-indent-for-case-label))
;; sh-indent-for-continuation: Line continuations are handled differently.
- (`(:after . ,(or `"(" `"{" `"["))
+ (`(:after . ,(or "(" "{" "["))
(if (not (looking-at ".[ \t]*[^\n \t#]"))
(sh-var-value 'sh-indent-after-open)
(goto-char (1- (match-end 0)))
@@ -2244,16 +2251,16 @@ Point should be before the newline."
(defun sh-smie-rc-rules (kind token)
(pcase (cons kind token)
- (`(:elem . basic) sh-basic-offset)
+ ('(:elem . basic) sh-basic-offset)
;; (`(:after . "case") (or sh-basic-offset smie-indent-basic))
- (`(:after . ";")
+ ('(:after . ";")
(if (smie-rule-parent-p "case")
(smie-rule-parent (sh-var-value 'sh-indent-after-case))))
- (`(:before . "{")
+ ('(:before . "{")
(save-excursion
(when (sh-smie--rc-after-special-arg-p)
`(column . ,(current-column)))))
- (`(:before . ,(or `"(" `"{" `"["))
+ (`(:before . ,(or "(" "{" "["))
(if (smie-rule-hanging-p) (smie-rule-parent)))
;; FIXME: SMIE parses "if (exp) cmd" as "(if ((exp) cmd))" so "cmd" is
;; treated as an arg to (exp) by default, which indents it all wrong.
@@ -2262,7 +2269,7 @@ Point should be before the newline."
;; rule we have is the :list-intro hack, which we use here to align "cmd"
;; with "(exp)", which is rarely the right thing to do, but is better
;; than nothing.
- (`(:list-intro . ,(or `"for" `"if" `"while")) t)
+ (`(:list-intro . ,(or "for" "if" "while")) t)
;; sh-indent-after-switch: handled implicitly by the default { rule.
))
@@ -2392,7 +2399,6 @@ whose value is the shell name (don't quote it)."
(funcall mksym "rules")
:forward-token (funcall mksym "forward-token")
:backward-token (funcall mksym "backward-token")))
- (setq-local parse-sexp-lookup-properties t)
(unless sh-use-smie
(setq-local sh-kw-alist (sh-feature sh-kw))
(let ((regexp (sh-feature sh-kws-for-done)))
@@ -2906,8 +2912,7 @@ STRING This is ignored for the purposes of calculating
(setq align-point (point))))
(or (bobp)
(forward-char -1))
- ;; FIXME: This charset looks too much like a regexp. --Stef
- (skip-chars-forward "[a-z0-9]*?")
+ (skip-chars-forward "*0-9?[]a-z")
)
((string-match "[])}]" x)
(setq x (sh-safe-forward-sexp -1))
@@ -4336,6 +4341,7 @@ option followed by a colon `:' if the option accepts an argument."
t)
(match-string 1))))))
+(put 'sh-assignment 'delete-selection t)
(defun sh-maybe-here-document (arg)
"Insert self. Without prefix, following unquoted `<' inserts here document.