help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: nXML mode indentation


From: N. Raghavendra
Subject: Re: nXML mode indentation
Date: Wed, 09 May 2018 08:52:36 +0530
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

At 2018-05-08T21:00:14+05:30, N. Raghavendra wrote:

> Now, the next thing I see is that if, after this indentation, I do
> `fill-paragraph', it goes back to the old indentation.  Anyway, I'll
> deal with that later.  For now, I'll make do with these changes, which
> at least give me the indentation I want.

I've found a fix for this also.

I've seen references to difficulties with nXML mode indentation, so I am
enclosing the changes in case someone else is bugged by the problem.
Using the advice mechanism seems a kludge, but it will do for me at
present.

Thanks,
Raghu.

----------
;; Fix indentation, so that it conforms to the guidelines of the
;; FreeBSD Documentation Project.
;; 
https://www.freebsd.org/doc/en_US.ISO8859-1/books/fdp-primer/writing-style-guide.html#writing-style-indentation

(defun my-nxml-compute-indent-from-matching-start-tag ()
  "Compute the indent for an end tag line using its start tag.
This function is meant to be an overriding advice for
`nxml-compute-indent-from-matching-start-tag'.  Adds a
local variable ONLY-END-TAG to distinguish between end
tags that are alone on a line, from end tags that are
accompanied by text on a line."
  (save-excursion
    (back-to-indentation)
    (let ((bol (point))
          (only-end-tag nil))
      (let ((inhibit-field-text-motion t))
        (end-of-line))
      (skip-chars-backward " \t")
      (and (= (nxml-token-before) (point))
           (memq xmltok-type '(end-tag partial-end-tag))
           ;; start of line must not be inside a token
           (or (and (= xmltok-start bol)
                    (setq only-end-tag t))
               (save-excursion
                 (goto-char bol)
                 (nxml-token-after)
                 (= xmltok-start bol))
               (eq xmltok-type 'data))
           (condition-case nil
               (nxml-scan-element-backward
                (point)
                nil
                (- (point)
                   nxml-end-tag-indent-scan-distance))
             (nxml-scan-error nil))
           (< xmltok-start bol)
           (progn
             (goto-char xmltok-start)
             (skip-chars-backward " \t")
             (bolp))
           (if only-end-tag
               (current-indentation)
             (+ (current-indentation) nxml-child-indent))))))

(advice-add 'nxml-compute-indent-from-matching-start-tag :override
            #'my-nxml-compute-indent-from-matching-start-tag)

(defun my-nxml-compute-indent-from-previous-line ()
  "Compute the indent for a line using the previous line.
This function is meant to be an overriding advice for
`nxml-compute-indent-from-previous-line'.  Considers
extra cases depending on the context of the line."
  (save-excursion
    (end-of-line)
    (let ((eol (point))
          bol prev-bol ref
          before-context after-context)
      (back-to-indentation)
      (setq bol (point))
      (catch 'indent
        ;; Move backwards until the start of a non-blank line that is
        ;; not inside a token.
        (while (progn
                 (when (= (forward-line -1) -1)
                   (throw 'indent 0))
                 (back-to-indentation)
                 (if (looking-at "[ \t]*$")
                     t
                   (or prev-bol
                       (setq prev-bol (point)))
                   (nxml-token-after)
                   (not (or (= xmltok-start (point))
                            (eq xmltok-type 'data))))))
        (setq ref (point))
        ;; Now scan over tokens until the end of the line to be indented.
        ;; Determine the context before and after the beginning of the
        ;; line.
        (while (< (point) eol)
          (nxml-tokenize-forward)
          (cond ((<= bol xmltok-start)
                 (setq after-context
                       (nxml-merge-indent-context-type after-context)))
                ((and (<= (point) bol)
                      (not (and (eq xmltok-type 'partial-start-tag)
                                (= (point) bol))))
                 (setq before-context
                       (nxml-merge-indent-context-type before-context)))
                ((eq xmltok-type 'data)
                 (setq before-context
                       (nxml-merge-indent-context-type before-context))
                 (setq after-context
                       (nxml-merge-indent-context-type after-context)))
                ;; If in the middle of a token that looks inline,
                ;; then indent relative to the previous non-blank line
                ((eq (nxml-merge-indent-context-type before-context)
                     'mixed)
                 (goto-char prev-bol)
                 (throw 'indent (current-column)))
                (t
                 (throw 'indent
                        (nxml-compute-indent-in-token bol))))
          (skip-chars-forward " \t\r\n"))
        (goto-char ref)
        (cond ((and (eq before-context 'mixed)
                    (eq after-context 'markup))
               (+ (current-column) nxml-child-indent))
              ((and (eq before-context 'markup)
                    (eq after-context 'markup))
               (current-column))
              (t (+ (current-column)
                    (* nxml-child-indent
                       (+ (if (eq before-context 'start-tag) 1 0)
                          (if (eq after-context 'end-tag) -1 0))))))))))

(advice-add 'nxml-compute-indent-from-previous-line :override
            #'my-nxml-compute-indent-from-previous-line)

(defun my-nxml-do-fill-paragraph (arg)
  "Fill paragraph in `nxml-mode'.
This function is meant to be an overriding advice for
`nxml-do-fill-paragraph'.  Adds some space to `fill-prefix'."
  (let (fill-paragraph-function
        fill-prefix
        start end)
    (save-excursion
      (nxml-forward-paragraph)
      (setq end (point))
      (nxml-backward-paragraph)
      (skip-chars-forward " \t\r\n")
      (setq start (point))
      (beginning-of-line)
      (setq fill-prefix
            (concat
             (buffer-substring-no-properties (point) start)
             (make-string nxml-child-indent ?\s)))
      (when (and (not (nxml-get-inside (point)))
                 (looking-at "[ \t]*<!--"))
        (setq fill-prefix (concat fill-prefix "     ")))
      (fill-region-as-paragraph start end arg))
    (skip-line-prefix fill-prefix)
    fill-prefix))

(advice-add 'nxml-do-fill-paragraph :override
            #'my-nxml-do-fill-paragraph))
----------

--
N. Raghavendra <raghu@hri.res.in>, http://www.retrotexts.net/
Harish-Chandra Research Institute, http://www.hri.res.in/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]