diff options
| author | Eli Zaretskii | 2006-06-03 08:38:43 +0000 |
|---|---|---|
| committer | Eli Zaretskii | 2006-06-03 08:38:43 +0000 |
| commit | 6d39902f3583e94a67281f0ca15b6f715ade4484 (patch) | |
| tree | c2432ad5cd29f978b0dbfb0771eddabada411d0f | |
| parent | e7818a4a1fffbb56db506881771f37d6c92cb59e (diff) | |
| download | emacs-6d39902f3583e94a67281f0ca15b6f715ade4484.tar.gz emacs-6d39902f3583e94a67281f0ca15b6f715ade4484.zip | |
(sh-quoted-exec): New face for quoted exec constructs like `foo bar`.
(sh-quoted-subshell): New helper function to search for a possibly nested
subshell (like `` or $()) within a "" quoted string.
(sh-font-lock-keywords-var): Add sh-quoted-exec for Bash.
(sh-apply-quoted-subshell): Flag quote characters inside a subshell, which is
itself already in a quoted region, as punctuation, since this is the closest
to what they actually are.
(sh-font-lock-syntactic-keywords): Add sh-quoted-subshell and
sh-apply-quoted-subshell.
(sh-font-lock-syntactic-face-function): Apply the new face for text inside ``
instead of the old font-lock-string-face.
| -rw-r--r-- | lisp/ChangeLog | 15 | ||||
| -rw-r--r-- | lisp/progmodes/sh-script.el | 82 |
2 files changed, 91 insertions, 6 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 9d4a6d0de47..8f29118a10e 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | 2006-05-20 Vivek Dasmohapatra <vivek@etla.org> | ||
| 2 | |||
| 3 | * progmodes/sh-script.el (sh-quoted-exec): New face for quoted | ||
| 4 | exec constructs like `foo bar`. | ||
| 5 | (sh-quoted-subshell): New helper function to search for a possibly | ||
| 6 | nested subshell (like `` or $()) within a "" quoted string. | ||
| 7 | (sh-font-lock-keywords-var): Add sh-quoted-exec for Bash. | ||
| 8 | (sh-apply-quoted-subshell): Flag quote characters inside a | ||
| 9 | subshell, which is itself already in a quoted region, as | ||
| 10 | punctuation, since this is the closest to what they actually are. | ||
| 11 | (sh-font-lock-syntactic-keywords): Add sh-quoted-subshell and | ||
| 12 | sh-apply-quoted-subshell. | ||
| 13 | (sh-font-lock-syntactic-face-function): Apply the new face for | ||
| 14 | text inside `` instead of the old font-lock-string-face. | ||
| 15 | |||
| 1 | 2006-06-03 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> | 16 | 2006-06-03 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> |
| 2 | 17 | ||
| 3 | * term/mac-win.el (mac-ts-active-input-overlay): Add defvar. | 18 | * term/mac-win.el (mac-ts-active-input-overlay): Add defvar. |
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el index ab3da050456..ef80d28c578 100644 --- a/lisp/progmodes/sh-script.el +++ b/lisp/progmodes/sh-script.el | |||
| @@ -814,6 +814,18 @@ See `sh-feature'.") | |||
| 814 | (:weight bold))) | 814 | (:weight bold))) |
| 815 | "Face to show a here-document" | 815 | "Face to show a here-document" |
| 816 | :group 'sh-indentation) | 816 | :group 'sh-indentation) |
| 817 | |||
| 818 | ;; These colours are probably icky. It's just a placeholder though. | ||
| 819 | (defface sh-quoted-exec | ||
| 820 | '((((class color) (background dark)) | ||
| 821 | (:foreground "salmon")) | ||
| 822 | (((class color) (background light)) | ||
| 823 | (:foreground "magenta")) | ||
| 824 | (t | ||
| 825 | (:weight bold))) | ||
| 826 | "Face to show quoted execs like ``" | ||
| 827 | :group 'sh-indentation) | ||
| 828 | |||
| 817 | ;; backward-compatibility alias | 829 | ;; backward-compatibility alias |
| 818 | (put 'sh-heredoc-face 'face-alias 'sh-heredoc) | 830 | (put 'sh-heredoc-face 'face-alias 'sh-heredoc) |
| 819 | (defvar sh-heredoc-face 'sh-heredoc) | 831 | (defvar sh-heredoc-face 'sh-heredoc) |
| @@ -833,7 +845,7 @@ See `sh-feature'.") | |||
| 833 | font-lock-variable-name-face)) | 845 | font-lock-variable-name-face)) |
| 834 | 846 | ||
| 835 | (rc sh-append es) | 847 | (rc sh-append es) |
| 836 | 848 | (bash sh-append shell ("\\$(\\(\\sw+\\)" (1 'sh-quoted-exec t) )) | |
| 837 | (sh sh-append shell | 849 | (sh sh-append shell |
| 838 | ;; Variable names. | 850 | ;; Variable names. |
| 839 | ("\\$\\({#?\\)?\\([A-Za-z_][A-Za-z0-9_]*\\|[-#?@!]\\)" 2 | 851 | ("\\$\\({#?\\)?\\([A-Za-z_][A-Za-z0-9_]*\\|[-#?@!]\\)" 2 |
| @@ -967,6 +979,49 @@ Point is at the beginning of the next line." | |||
| 967 | ;; This looks silly, but it's because `sh-here-doc-re' keeps changing. | 979 | ;; This looks silly, but it's because `sh-here-doc-re' keeps changing. |
| 968 | (re-search-forward sh-here-doc-re limit t)) | 980 | (re-search-forward sh-here-doc-re limit t)) |
| 969 | 981 | ||
| 982 | (defun sh-quoted-subshell (limit) | ||
| 983 | "Search for a subshell embedded in a string. Find all the unescaped | ||
| 984 | \" characters within said subshell, remembering that subshells can nest." | ||
| 985 | (if (re-search-forward "\"\\(?:.\\|\n\\)*?\\(\\$(\\|`\\)" limit t) | ||
| 986 | ;; bingo we have a $( or a ` inside a "" | ||
| 987 | (let ((char (char-after (point))) | ||
| 988 | (continue t) | ||
| 989 | (pos (point)) | ||
| 990 | (data nil) ;; value to put into match-data (and return) | ||
| 991 | (last nil) ;; last char seen | ||
| 992 | (bq (equal (match-string 1) "`")) ;; ` state flip-flop | ||
| 993 | (seen nil) ;; list of important positions | ||
| 994 | (nest 1)) ;; subshell nesting level | ||
| 995 | (while (and continue char (<= pos limit)) | ||
| 996 | ;; unescaped " inside a $( ... ) construct. | ||
| 997 | ;; state machine time... | ||
| 998 | ;; \ => ignore next char; | ||
| 999 | ;; ` => increase or decrease nesting level based on bq flag | ||
| 1000 | ;; ) [where nesting > 0] => decrease nesting | ||
| 1001 | ;; ( [where nesting > 0] => increase nesting | ||
| 1002 | ;; ( [preceeded by $ ] => increase nesting | ||
| 1003 | ;; " [nesting <= 0 ] => terminate, we're done. | ||
| 1004 | ;; " [nesting > 0 ] => remember this, it's not a proper " | ||
| 1005 | (if (eq ?\\ last) nil | ||
| 1006 | (if (eq ?\` char) (setq nest (+ nest (if bq -1 1)) bq (not bq)) | ||
| 1007 | (if (and (> nest 0) (eq ?\) char)) (setq nest (1- nest)) | ||
| 1008 | (if (and (eq ?$ last) (eq ?\( char)) (setq nest (1+ nest)) | ||
| 1009 | (if (and (> nest 0) (eq ?\( char)) (setq nest (1+ nest)) | ||
| 1010 | (if (eq char ?\") | ||
| 1011 | (if (>= 0 nest) (setq continue nil) | ||
| 1012 | (setq seen (cons pos seen)) ) )))))) | ||
| 1013 | ;;(message "POS: %d [%d]" pos nest) | ||
| 1014 | (setq last char | ||
| 1015 | pos (1+ pos) | ||
| 1016 | char (char-after pos)) ) | ||
| 1017 | (when seen | ||
| 1018 | ;;(message "SEEN: %S" seen) | ||
| 1019 | (setq data (list (current-buffer))) | ||
| 1020 | (mapc (lambda (P) | ||
| 1021 | (setq data (cons P (cons (1+ P) data)) ) ) seen) | ||
| 1022 | (store-match-data data)) | ||
| 1023 | data) )) | ||
| 1024 | |||
| 970 | (defun sh-is-quoted-p (pos) | 1025 | (defun sh-is-quoted-p (pos) |
| 971 | (and (eq (char-before pos) ?\\) | 1026 | (and (eq (char-before pos) ?\\) |
| 972 | (not (sh-is-quoted-p (1- pos))))) | 1027 | (not (sh-is-quoted-p (1- pos))))) |
| @@ -997,6 +1052,17 @@ Point is at the beginning of the next line." | |||
| 997 | (when (save-excursion (backward-char 2) (looking-at ";;\\|in")) | 1052 | (when (save-excursion (backward-char 2) (looking-at ";;\\|in")) |
| 998 | sh-st-punc))) | 1053 | sh-st-punc))) |
| 999 | 1054 | ||
| 1055 | (defun sh-apply-quoted-subshell () | ||
| 1056 | "Apply the `sh-st-punc' syntax to all the matches in `match-data'. | ||
| 1057 | This is used to flag quote characters in subshell constructs inside strings | ||
| 1058 | \(which should therefore not be treated as normal quote characters\)" | ||
| 1059 | (let ((m (match-data)) a b) | ||
| 1060 | (while m | ||
| 1061 | (setq a (car m) | ||
| 1062 | b (cadr m) | ||
| 1063 | m (cddr m)) | ||
| 1064 | (put-text-property a b 'syntax-table sh-st-punc))) sh-st-punc) | ||
| 1065 | |||
| 1000 | (defconst sh-font-lock-syntactic-keywords | 1066 | (defconst sh-font-lock-syntactic-keywords |
| 1001 | ;; A `#' begins a comment when it is unquoted and at the beginning of a | 1067 | ;; A `#' begins a comment when it is unquoted and at the beginning of a |
| 1002 | ;; word. In the shell, words are separated by metacharacters. | 1068 | ;; word. In the shell, words are separated by metacharacters. |
| @@ -1007,6 +1073,9 @@ Point is at the beginning of the next line." | |||
| 1007 | ("\\(\\\\\\)'" 1 ,sh-st-punc) | 1073 | ("\\(\\\\\\)'" 1 ,sh-st-punc) |
| 1008 | ;; Make sure $@ and @? are correctly recognized as sexps. | 1074 | ;; Make sure $@ and @? are correctly recognized as sexps. |
| 1009 | ("\\$\\([?@]\\)" 1 ,sh-st-symbol) | 1075 | ("\\$\\([?@]\\)" 1 ,sh-st-symbol) |
| 1076 | ;; highlight (possibly nested) subshells inside "" quoted regions correctly. | ||
| 1077 | (sh-quoted-subshell | ||
| 1078 | (1 (sh-apply-quoted-subshell) t t)) | ||
| 1010 | ;; Find HEREDOC starters and add a corresponding rule for the ender. | 1079 | ;; Find HEREDOC starters and add a corresponding rule for the ender. |
| 1011 | (sh-font-lock-here-doc | 1080 | (sh-font-lock-here-doc |
| 1012 | (2 (sh-font-lock-open-heredoc | 1081 | (2 (sh-font-lock-open-heredoc |
| @@ -1019,11 +1088,12 @@ Point is at the beginning of the next line." | |||
| 1019 | (")" 0 (sh-font-lock-paren (match-beginning 0))))) | 1088 | (")" 0 (sh-font-lock-paren (match-beginning 0))))) |
| 1020 | 1089 | ||
| 1021 | (defun sh-font-lock-syntactic-face-function (state) | 1090 | (defun sh-font-lock-syntactic-face-function (state) |
| 1022 | (if (nth 3 state) | 1091 | (let ((q (nth 3 state))) |
| 1023 | (if (char-valid-p (nth 3 state)) | 1092 | (if q |
| 1024 | font-lock-string-face | 1093 | (if (char-valid-p q) |
| 1025 | sh-heredoc-face) | 1094 | (if (eq q ?\`) 'sh-quoted-exec font-lock-string-face) |
| 1026 | font-lock-comment-face)) | 1095 | sh-heredoc-face) |
| 1096 | font-lock-comment-face))) | ||
| 1027 | 1097 | ||
| 1028 | (defgroup sh-indentation nil | 1098 | (defgroup sh-indentation nil |
| 1029 | "Variables controlling indentation in shell scripts. | 1099 | "Variables controlling indentation in shell scripts. |