-(defconst sh-escaped-line-re
- ;; Should match until the real end-of-continued-line, but if that is not
- ;; possible (because we bump into EOB or the search bound), then we should
- ;; match until the search bound.
- "\\(?:\\(?:.*[^\\\n]\\)?\\(?:\\\\\\\\\\)*\\\\\n\\)*.*")
-
-(defconst sh-here-doc-open-re
- (concat "<<-?\\s-*\\\\?\\(\\(?:['\"][^'\"]+['\"]\\|\\sw\\)+\\)"
- sh-escaped-line-re "\\(\n\\)"))
-
-(defvar sh-here-doc-markers nil)
-(make-variable-buffer-local 'sh-here-doc-markers)
-(defvar sh-here-doc-re sh-here-doc-open-re)
-(make-variable-buffer-local 'sh-here-doc-re)
-
-(defun sh-font-lock-close-heredoc (bol eof indented)
- "Determine the syntax of the \\n after an EOF.
-If non-nil INDENTED indicates that the EOF was indented."
- (let* ((eof-re (if eof (regexp-quote eof) ""))
- ;; A rough regexp that should find the opening <<EOF back.
- (sre (concat "<<\\(-?\\)\\s-*['\"\\]?"
- ;; Use \s| to cheaply check it's an open-heredoc.
- eof-re "['\"]?\\([ \t|;&)<>]"
- sh-escaped-line-re
- "\\)?\\s|"))
- ;; A regexp that will find other EOFs.
- (ere (concat "^" (if indented "[ \t]*") eof-re "\n"))
- (start (save-excursion
- (goto-char bol)
- (re-search-backward (concat sre "\\|" ere) nil t))))
- ;; If subgroup 1 matched, we found an open-heredoc, otherwise we first
- ;; found a close-heredoc which makes the current close-heredoc inoperant.
- (cond
- ((when (and start (match-end 1)
- (not (and indented (= (match-beginning 1) (match-end 1))))
- (not (sh-in-comment-or-string (match-beginning 0))))
- ;; Make sure our `<<' is not the EOF1 of a `cat <<EOF1 <<EOF2'.
- (save-excursion
- (goto-char start)
- (setq start (line-beginning-position 2))
- (while
- (progn
- (re-search-forward "<<") ; Skip ourselves.
- (and (re-search-forward sh-here-doc-open-re start 'move)
- (goto-char (match-beginning 0))
- (sh-in-comment-or-string (point)))))
- ;; No <<EOF2 found after our <<.
- (= (point) start)))
- sh-here-doc-syntax)
- ((not (or start (save-excursion (re-search-forward sre nil t))))
- ;; There's no <<EOF either before or after us,
- ;; so we should remove ourselves from font-lock's keywords.
- (setq sh-here-doc-markers (delete eof sh-here-doc-markers))
- (setq sh-here-doc-re
- (concat sh-here-doc-open-re "\\|^\\([ \t]*\\)"
- (regexp-opt sh-here-doc-markers t) "\\(\n\\)"))
- nil))))
-
-(defun sh-font-lock-open-heredoc (start string)
+(eval-and-compile
+ (defconst sh-escaped-line-re
+ ;; Should match until the real end-of-continued-line, but if that is not
+ ;; possible (because we bump into EOB or the search bound), then we should
+ ;; match until the search bound.
+ "\\(?:\\(?:.*[^\\\n]\\)?\\(?:\\\\\\\\\\)*\\\\\n\\)*.*")
+
+ (defconst sh-here-doc-open-re
+ (concat "<<-?\\s-*\\\\?\\(\\(?:['\"][^'\"]+['\"]\\|\\sw\\|[-/~._]\\)+\\)"
+ sh-escaped-line-re "\\(\n\\)")))
+
+(defun sh-font-lock-open-heredoc (start string eol)