Commit 3fb819e5 authored by Stefan Monnier's avatar Stefan Monnier

(sgml-lexical-context): Return (text . START)

instead of nil when point is outside of any tag.
(sgml-beginning-of-tag): Adjust to the change.
(sgml-calculate-indent): Use the new info returned by
sgml-lexical-context.  Try to handle unclosed tags.
parent 4c0414fe
...@@ -846,8 +846,7 @@ and move to the line in the SGML document that caused it." ...@@ -846,8 +846,7 @@ and move to the line in the SGML document that caused it."
(defun sgml-lexical-context (&optional limit) (defun sgml-lexical-context (&optional limit)
"Return the lexical context at point as (TYPE . START). "Return the lexical context at point as (TYPE . START).
START is the location of the start of the lexical element. START is the location of the start of the lexical element.
TYPE is one of `string', `comment', `tag', `cdata', .... TYPE is one of `string', `comment', `tag', or `text'.
Return nil if we are inside text (i.e. outside of any kind of tag).
If non-nil LIMIT is a nearby position before point outside of any tag." If non-nil LIMIT is a nearby position before point outside of any tag."
;; As usual, it's difficult to get a reliable answer without parsing the ;; As usual, it's difficult to get a reliable answer without parsing the
...@@ -855,23 +854,26 @@ If non-nil LIMIT is a nearby position before point outside of any tag." ...@@ -855,23 +854,26 @@ If non-nil LIMIT is a nearby position before point outside of any tag."
;; any string or tag or comment or ... ;; any string or tag or comment or ...
(save-excursion (save-excursion
(let ((pos (point)) (let ((pos (point))
(state nil)) (state nil)
textstart)
(if limit (goto-char limit) (if limit (goto-char limit)
;; Hopefully this regexp will match something that's not inside ;; Hopefully this regexp will match something that's not inside
;; a tag and also hopefully the match is nearby. ;; a tag and also hopefully the match is nearby.
(re-search-backward "^[ \t]*<[_:[:alpha:]/%!?#]" nil 'move)) (re-search-backward "^[ \t]*<[_:[:alpha:]/%!?#]" nil 'move))
(setq textstart (point))
(with-syntax-table sgml-tag-syntax-table (with-syntax-table sgml-tag-syntax-table
(while (< (point) pos) (while (< (point) pos)
;; When entering this loop we're inside text. ;; When entering this loop we're inside text.
(setq textstart (point))
(skip-chars-forward "^<" pos) (skip-chars-forward "^<" pos)
;; We skipped text and reached a tag. Parse it. ;; We skipped text and reached a tag. Parse it.
;; FIXME: this does not handle CDATA and funny stuff yet. ;; FIXME: Handle net-enabling start-tags and <![CDATA[ ...]]>.
(setq state (parse-partial-sexp (point) pos 0))) (setq state (parse-partial-sexp (point) pos 0)))
(cond (cond
((nth 3 state) (cons 'string (nth 8 state))) ((nth 3 state) (cons 'string (nth 8 state)))
((nth 4 state) (cons 'comment (nth 8 state))) ((nth 4 state) (cons 'comment (nth 8 state)))
((and state (> (nth 0 state) 0)) (cons 'tag (nth 1 state))) ((and state (> (nth 0 state) 0)) (cons 'tag (nth 1 state)))
(t nil)))))) (t (cons 'text textstart)))))))
(defun sgml-beginning-of-tag (&optional top-level) (defun sgml-beginning-of-tag (&optional top-level)
"Skip to beginning of tag and return its name. "Skip to beginning of tag and return its name.
...@@ -883,7 +885,7 @@ If this can't be done, return nil." ...@@ -883,7 +885,7 @@ If this can't be done, return nil."
(when (looking-at sgml-tag-name-re) (when (looking-at sgml-tag-name-re)
(match-string-no-properties 1))) (match-string-no-properties 1)))
(if top-level nil (if top-level nil
(when context (when (not (eq (car context) 'text))
(goto-char (cdr context)) (goto-char (cdr context))
(sgml-beginning-of-tag t)))))) (sgml-beginning-of-tag t))))))
...@@ -968,22 +970,43 @@ With prefix argument, unquote the region." ...@@ -968,22 +970,43 @@ With prefix argument, unquote the region."
(goto-char (1+ (cdr lcon))) (goto-char (1+ (cdr lcon)))
(+ (current-column) sgml-basic-offset))) (+ (current-column) sgml-basic-offset)))
(t (t ;; text
(while (looking-at "</") (while (looking-at "</")
(forward-sexp 1) (forward-sexp 1)
(skip-chars-forward " \t")) (skip-chars-forward " \t"))
(let ((context (xml-lite-get-context))) (let* ((here (point))
(cond (unclosed (and ;; (not sgml-xml-mode)
((null context) 0) ; no context (looking-at sgml-tag-name-re)
(t (member-ignore-case (match-string 1)
(let ((here (point))) sgml-unclosed-tags)
(goto-char (xml-lite-tag-end (car context))) (match-string 1)))
(skip-chars-forward " \t\n") (context
(if (and (< (point) here) (xml-lite-at-indentation-p)) ;; If possible, align on the previous non-empty text line.
(current-column) ;; Otherwise, do a more serious parsing to find the
(goto-char (xml-lite-tag-start (car context))) ;; tag(s) relative to which we should be indenting.
(+ (current-column) (if (and (not unclosed) (skip-chars-backward " \t")
(* sgml-basic-offset (length context)))))))))))) (< (skip-chars-backward " \t\n") 0)
(back-to-indentation)
(> (point) (cdr lcon)))
nil
(goto-char here)
(nreverse (xml-lite-get-context (if unclosed nil 'empty)))))
(there (point)))
;; Ignore previous unclosed start-tag in context.
(while (and context unclosed
(eq t (compare-strings
(xml-lite-tag-name (car context)) nil nil
unclosed nil nil t)))
(setq context (cdr context)))
;; Indent to reflect nesting.
(if (and context
(goto-char (xml-lite-tag-end (car context)))
(skip-chars-forward " \t\n")
(< (point) here) (xml-lite-at-indentation-p))
(current-column)
(goto-char there)
(+ (current-column)
(* sgml-basic-offset (length context)))))))))
(defun sgml-indent-line () (defun sgml-indent-line ()
"Indent the current line as SGML." "Indent the current line as SGML."
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment