Mercurial > emacs
comparison lisp/progmodes/sh-script.el @ 72044:3dc0557bba5f
(sh-quoted-subshell): Further fix last change.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Thu, 20 Jul 2006 21:23:48 +0000 |
parents | 93069e336ae9 |
children | cedc7e7f2199 858cb33ae39d |
comparison
equal
deleted
inserted
replaced
72043:dce50dd248c3 | 72044:3dc0557bba5f |
---|---|
978 "Search for a heredoc marker." | 978 "Search for a heredoc marker." |
979 ;; 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. |
980 (re-search-forward sh-here-doc-re limit t)) | 980 (re-search-forward sh-here-doc-re limit t)) |
981 | 981 |
982 (defun sh-quoted-subshell (limit) | 982 (defun sh-quoted-subshell (limit) |
983 "Search for a subshell embedded in a string. Find all the unescaped | 983 "Search for a subshell embedded in a string. |
984 \" characters within said subshell, remembering that subshells can nest." | 984 Find all the unescaped \" characters within said subshell, remembering that |
985 subshells can nest." | |
985 ;; FIXME: This can (and often does) match multiple lines, yet it makes no | 986 ;; FIXME: This can (and often does) match multiple lines, yet it makes no |
986 ;; effort to handle multiline cases correctly, so it ends up being | 987 ;; effort to handle multiline cases correctly, so it ends up being |
987 ;; rather flakey. | 988 ;; rather flakey. |
988 (if (re-search-forward "\"\\(?:\\(?:.\\|\n\\)*?[^\\]\\(\\\\\\\\\\)*\\)??\\(\\$(\\|`\\)" limit t) | 989 (when (re-search-forward "\"\\(?:\\(?:.\\|\n\\)*?[^\\]\\(?:\\\\\\\\\\)*\\)??\\(\\$(\\|`\\)" limit t) |
989 ;; bingo we have a $( or a ` inside a "" | 990 ;; bingo we have a $( or a ` inside a "" |
990 (let ((char (char-after (point))) | 991 (let ((char (char-after (point))) |
991 (continue t) | 992 (continue t) |
992 (pos (point)) | 993 (pos (point)) |
993 (data nil) ;; value to put into match-data (and return) | 994 (data nil) ;; value to put into match-data (and return) |
994 (last nil) ;; last char seen | 995 (last nil) ;; last char seen |
995 (bq (equal (match-string 1) "`")) ;; ` state flip-flop | 996 (bq (equal (match-string 1) "`")) ;; ` state flip-flop |
996 (seen nil) ;; list of important positions | 997 (seen nil) ;; list of important positions |
997 (nest 1)) ;; subshell nesting level | 998 (nest 1)) ;; subshell nesting level |
998 (while (and continue char (<= pos limit)) | 999 (while (and continue char (<= pos limit)) |
999 ;; unescaped " inside a $( ... ) construct. | 1000 ;; unescaped " inside a $( ... ) construct. |
1000 ;; state machine time... | 1001 ;; state machine time... |
1001 ;; \ => ignore next char; | 1002 ;; \ => ignore next char; |
1002 ;; ` => increase or decrease nesting level based on bq flag | 1003 ;; ` => increase or decrease nesting level based on bq flag |
1003 ;; ) [where nesting > 0] => decrease nesting | 1004 ;; ) [where nesting > 0] => decrease nesting |
1004 ;; ( [where nesting > 0] => increase nesting | 1005 ;; ( [where nesting > 0] => increase nesting |
1005 ;; ( [preceeded by $ ] => increase nesting | 1006 ;; ( [preceeded by $ ] => increase nesting |
1006 ;; " [nesting <= 0 ] => terminate, we're done. | 1007 ;; " [nesting <= 0 ] => terminate, we're done. |
1007 ;; " [nesting > 0 ] => remember this, it's not a proper " | 1008 ;; " [nesting > 0 ] => remember this, it's not a proper " |
1008 ;; FIXME: don't count parens that appear within quotes. | 1009 ;; FIXME: don't count parens that appear within quotes. |
1009 (cond | 1010 (cond |
1010 ((eq ?\\ last) nil) | 1011 ((eq ?\\ last) nil) |
1011 ((eq ?\` char) (setq nest (+ nest (if bq -1 1)) bq (not bq))) | 1012 ((eq ?\` char) (setq nest (+ nest (if bq -1 1)) bq (not bq))) |
1012 ((and (> nest 0) (eq ?\) char)) (setq nest (1- nest))) | 1013 ((and (> nest 0) (eq ?\) char)) (setq nest (1- nest))) |
1013 ((and (eq ?$ last) (eq ?\( char)) (setq nest (1+ nest))) | 1014 ((and (eq ?$ last) (eq ?\( char)) (setq nest (1+ nest))) |
1014 ((and (> nest 0) (eq ?\( char)) (setq nest (1+ nest))) | 1015 ((and (> nest 0) (eq ?\( char)) (setq nest (1+ nest))) |
1015 ((eq char ?\") | 1016 ((eq char ?\") |
1016 (if (>= 0 nest) (setq continue nil) (push pos seen)))) | 1017 (if (>= 0 nest) (setq continue nil) (push pos seen)))) |
1017 ;;(message "POS: %d [%d]" pos nest) | 1018 ;;(message "POS: %d [%d]" pos nest) |
1018 (setq last char | 1019 (setq last char |
1019 pos (1+ pos) | 1020 pos (1+ pos) |
1020 char (char-after pos)) ) | 1021 char (char-after pos)) ) |
1021 ;; FIXME: why construct a costly match data to pass to | 1022 ;; FIXME: why construct a costly match data to pass to |
1022 ;; sh-apply-quoted-subshell rather than apply the highlight | 1023 ;; sh-apply-quoted-subshell rather than apply the highlight |
1023 ;; directly here? -- Stef | 1024 ;; directly here? -- Stef |
1024 (when seen | 1025 (when seen |
1025 ;;(message "SEEN: %S" seen) | 1026 ;;(message "SEEN: %S" seen) |
1026 (setq data (list (current-buffer))) | 1027 (setq data (list (current-buffer))) |
1027 (dolist(P seen) | 1028 (dolist(P seen) |
1028 (setq data (cons P (cons (1+ P) data)))) | 1029 (setq data (cons P (cons (1+ P) data)))) |
1029 (store-match-data data)) | 1030 (store-match-data data)) |
1030 data) )) | 1031 data) )) |
1031 | 1032 |
1032 (defun sh-is-quoted-p (pos) | 1033 (defun sh-is-quoted-p (pos) |
1033 (and (eq (char-before pos) ?\\) | 1034 (and (eq (char-before pos) ?\\) |
1034 (not (sh-is-quoted-p (1- pos))))) | 1035 (not (sh-is-quoted-p (1- pos))))) |
1035 | 1036 |