Mercurial > emacs
comparison lisp/textmodes/sgml-mode.el @ 80876:f46158b1c8bc
(sgml-lexical-context): Add handling of XML style Processing Instructions.
(sgml-parse-tag-backward): Handle XML-style PIs. Also ensure progress.
(sgml-calculate-indent): Handle `pi' context.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Tue, 08 May 2007 06:57:38 +0000 |
parents | 33363c78b671 |
children | 8938fa90afdb |
comparison
equal
deleted
inserted
replaced
80875:51b85ee9ab0f | 80876:f46158b1c8bc |
---|---|
935 (bolp))) | 935 (bolp))) |
936 | 936 |
937 (defun sgml-lexical-context (&optional limit) | 937 (defun sgml-lexical-context (&optional limit) |
938 "Return the lexical context at point as (TYPE . START). | 938 "Return the lexical context at point as (TYPE . START). |
939 START is the location of the start of the lexical element. | 939 START is the location of the start of the lexical element. |
940 TYPE is one of `string', `comment', `tag', `cdata', or `text'. | 940 TYPE is one of `string', `comment', `tag', `cdata', `pi', or `text'. |
941 | 941 |
942 Optional argument LIMIT is the position to start parsing from. | 942 Optional argument LIMIT is the position to start parsing from. |
943 If nil, start from a preceding tag at indentation." | 943 If nil, start from a preceding tag at indentation." |
944 (save-excursion | 944 (save-excursion |
945 (let ((pos (point)) | 945 (let ((pos (point)) |
962 ((looking-at "<!\\[[A-Z]+\\[") | 962 ((looking-at "<!\\[[A-Z]+\\[") |
963 ;; We've found a CDATA section or similar. | 963 ;; We've found a CDATA section or similar. |
964 (let ((cdata-start (point))) | 964 (let ((cdata-start (point))) |
965 (unless (search-forward "]]>" pos 'move) | 965 (unless (search-forward "]]>" pos 'move) |
966 (list 0 nil nil 'cdata nil nil nil nil cdata-start)))) | 966 (list 0 nil nil 'cdata nil nil nil nil cdata-start)))) |
967 ((and sgml-xml-mode (looking-at "<\\?")) | |
968 ;; Processing Instructions. | |
969 ;; In SGML, it's basically a normal tag of the form | |
970 ;; <?NAME ...> but in XML, it takes the form <? ... ?>. | |
971 (let ((pi-start (point))) | |
972 (unless (search-forward "?>" pos 'move) | |
973 (list 0 nil nil 'pi nil nil nil nil pi-start)))) | |
967 (t | 974 (t |
968 ;; We've reached a tag. Parse it. | 975 ;; We've reached a tag. Parse it. |
969 ;; FIXME: Handle net-enabling start-tags | 976 ;; FIXME: Handle net-enabling start-tags |
970 (parse-partial-sexp (point) pos 0)))))) | 977 (parse-partial-sexp (point) pos 0)))))) |
971 (cond | 978 (cond |
972 ((eq (nth 3 state) 'cdata) (cons 'cdata (nth 8 state))) | 979 ((memq (nth 3 state) '(cdata pi)) (cons (nth 3 state) (nth 8 state))) |
973 ((nth 3 state) (cons 'string (nth 8 state))) | 980 ((nth 3 state) (cons 'string (nth 8 state))) |
974 ((nth 4 state) (cons 'comment (nth 8 state))) | 981 ((nth 4 state) (cons 'comment (nth 8 state))) |
975 ((and state (> (nth 0 state) 0)) (cons 'tag (nth 1 state))) | 982 ((and state (> (nth 0 state) 0)) (cons 'tag (nth 1 state))) |
976 (t (cons 'text text-start)))))) | 983 (t (cons 'text text-start)))))) |
977 | 984 |
1091 (or (re-search-backward "[<>]" limit 'move) | 1098 (or (re-search-backward "[<>]" limit 'move) |
1092 (error "No tag found")) | 1099 (error "No tag found")) |
1093 (when (eq (char-after) ?<) | 1100 (when (eq (char-after) ?<) |
1094 ;; Oops!! Looks like we were not in a textual context after all!. | 1101 ;; Oops!! Looks like we were not in a textual context after all!. |
1095 ;; Let's try to recover. | 1102 ;; Let's try to recover. |
1103 ;; Remember the tag-start so we don't need to look for it later. | |
1104 ;; This is not just an optimization but also makes sure we don't get | |
1105 ;; stuck in infloops in cases where "looking back for <" would not go | |
1106 ;; back far enough. | |
1107 (setq tag-start (point)) | |
1096 (with-syntax-table sgml-tag-syntax-table | 1108 (with-syntax-table sgml-tag-syntax-table |
1097 (let ((pos (point))) | 1109 (let ((pos (point))) |
1098 (condition-case nil | 1110 (condition-case nil |
1111 ;; FIXME: This does not correctly skip over PI an CDATA tags. | |
1099 (forward-sexp) | 1112 (forward-sexp) |
1100 (scan-error | 1113 (scan-error |
1101 ;; This < seems to be just a spurious one, let's ignore it. | 1114 ;; This < seems to be just a spurious one, let's ignore it. |
1102 (goto-char pos) | 1115 (goto-char pos) |
1103 (throw 'found (sgml-parse-tag-backward limit)))) | 1116 (throw 'found (sgml-parse-tag-backward limit)))) |
1108 (forward-char -1)))) | 1121 (forward-char -1)))) |
1109 (setq tag-end (1+ (point))) | 1122 (setq tag-end (1+ (point))) |
1110 (cond | 1123 (cond |
1111 ((sgml-looking-back-at "--") ; comment | 1124 ((sgml-looking-back-at "--") ; comment |
1112 (setq tag-type 'comment | 1125 (setq tag-type 'comment |
1113 tag-start (search-backward "<!--" nil t))) | 1126 tag-start (or tag-start (search-backward "<!--" nil t)))) |
1114 ((sgml-looking-back-at "]]") ; cdata | 1127 ((sgml-looking-back-at "]]") ; cdata |
1115 (setq tag-type 'cdata | 1128 (setq tag-type 'cdata |
1116 tag-start (re-search-backward "<!\\[[A-Z]+\\[" nil t))) | 1129 tag-start (or tag-start |
1130 (re-search-backward "<!\\[[A-Z]+\\[" nil t)))) | |
1131 ((sgml-looking-back-at "?") ; XML processing-instruction | |
1132 (setq tag-type 'pi | |
1133 ;; IIUC: SGML processing instructions take the form <?foo ...> | |
1134 ;; i.e. a "normal" tag, handled below. In XML this is changed | |
1135 ;; to <?foo ... ?> where "..." can contain < and > and even <? | |
1136 ;; but not ?>. This means that when parsing backward, there's | |
1137 ;; no easy way to make sure that we find the real beginning of | |
1138 ;; the PI. | |
1139 tag-start (or tag-start (search-backward "<?" nil t)))) | |
1117 (t | 1140 (t |
1118 (setq tag-start | 1141 (unless tag-start |
1119 (with-syntax-table sgml-tag-syntax-table | 1142 (setq tag-start |
1120 (goto-char tag-end) | 1143 (with-syntax-table sgml-tag-syntax-table |
1121 (condition-case nil | 1144 (goto-char tag-end) |
1122 (backward-sexp) | 1145 (condition-case nil |
1123 (scan-error | 1146 (backward-sexp) |
1124 ;; This > isn't really the end of a tag. Skip it. | 1147 (scan-error |
1125 (goto-char (1- tag-end)) | 1148 ;; This > isn't really the end of a tag. Skip it. |
1126 (throw 'found (sgml-parse-tag-backward limit)))) | 1149 (goto-char (1- tag-end)) |
1127 (point))) | 1150 (throw 'found (sgml-parse-tag-backward limit)))) |
1151 (point)))) | |
1128 (goto-char (1+ tag-start)) | 1152 (goto-char (1+ tag-start)) |
1129 (case (char-after) | 1153 (case (char-after) |
1130 (?! ; declaration | 1154 (?! (setq tag-type 'decl)) ; declaration |
1131 (setq tag-type 'decl)) | 1155 (?? (setq tag-type 'pi)) ; processing-instruction |
1132 (?? ; processing-instruction | 1156 (?% (setq tag-type 'jsp)) ; JSP tags |
1133 (setq tag-type 'pi)) | |
1134 (?/ ; close-tag | 1157 (?/ ; close-tag |
1135 (forward-char 1) | 1158 (forward-char 1) |
1136 (setq tag-type 'close | 1159 (setq tag-type 'close |
1137 name (sgml-parse-tag-name))) | 1160 name (sgml-parse-tag-name))) |
1138 (?% ; JSP tags | |
1139 (setq tag-type 'jsp)) | |
1140 (t ; open or empty tag | 1161 (t ; open or empty tag |
1141 (setq tag-type 'open | 1162 (setq tag-type 'open |
1142 name (sgml-parse-tag-name)) | 1163 name (sgml-parse-tag-name)) |
1143 (if (or (eq ?/ (char-before (- tag-end 1))) | 1164 (if (or (eq ?/ (char-before (- tag-end 1))) |
1144 (sgml-empty-tag-p name)) | 1165 (sgml-empty-tag-p name)) |
1329 (forward-char 2) (skip-chars-forward " \t")) | 1350 (forward-char 2) (skip-chars-forward " \t")) |
1330 (current-column))) | 1351 (current-column))) |
1331 | 1352 |
1332 ;; We don't know how to indent it. Let's be honest about it. | 1353 ;; We don't know how to indent it. Let's be honest about it. |
1333 (cdata nil) | 1354 (cdata nil) |
1355 ;; We don't know how to indent it. Let's be honest about it. | |
1356 (pi nil) | |
1334 | 1357 |
1335 (tag | 1358 (tag |
1336 (goto-char (1+ (cdr lcon))) | 1359 (goto-char (1+ (cdr lcon))) |
1337 (skip-chars-forward "^ \t\n") ;Skip tag name. | 1360 (skip-chars-forward "^ \t\n") ;Skip tag name. |
1338 (skip-chars-forward " \t") | 1361 (skip-chars-forward " \t") |