3

I would like to fold

<type>
  <xsl:attribute name="multiplicity">
    <xsl:choose>
      <xsl:when test="collection = true">*</xsl:when>
      <xsl:otherwise>1</xsl:otherwise>
    </xsl:choose>
  </xsl:attribute>
  <xsl:value-of select="field_type"/>
</type>

into

<type>
  <xsl:attribute name="multiplicity">
    <xsl:choose>...</xsl:choose>
  </xsl:attribute>
  <xsl:value-of select="field_type"/>
</type>

or

<type>
  <xsl:attribute name="multiplicity">...</xsl:attribute>
  <xsl:value-of select="field_type"/>
</type>

nxml-mode can outline certain elements already. How can I set up nxml-mode to be willing to outline any element?

  • The outline feature requires a definitive beginning regexp and a definitive ending regexp. If no one offers a solution in the near future, then I'll take a stab at it. In the meantime, please assemble a list of all beginning and rending regexp of the region(s) you wish to fold -- that will be needed to create a custom fold function (if such a function does not already exist) for your nxml-mode project. You may also wish to take a look at the hide-show library: emacswiki.org/emacs/HideShow and gnu.org/software/emacs/manual/html_node/emacs/Hideshow.html – lawlist Jul 23 '14 at 4:33
  • @lawlist The problem with that—near as I can figure with classical regular expressions—is that regular expressions cannot really handle nested things. That said, xsl:.* should cover everything I would like nested, although the ability to define a list of such tags to fold would be ideal. – Sean Allred Jul 23 '14 at 4:42
  • It looks like the beginning regexp can be used to derive the ending regexp, similar to a prior example I drafted for LaTeX: tex.stackexchange.com/a/161196/26911 I'll check back in the next day or so to see if someone has a built-in solution or for hideshow or another method. If not, I'll likely put something together based on the draft in the link I've mentioned. That prior example of mine looks pretty close to what you want -- you might want to take a stab at it yourself in the meantime. – lawlist Jul 23 '14 at 6:04
3

Initial Draft (July 23, 2014):  First rough draft.

EDIT (July 23, 2014):  Second rough draft. Added a counter and while-loop in an attempt to deal with nested situations containing the same regexp.

(defvar beg-xsl-regexp
  "\\(\<xsl:\\)\\([^ >]*\\)\\([^>]*\\)\\(\>\\)"
"Regexp matching the beginning of the folded region.")

(defun toggle-xsl-block ()
"When FLAG is non-nil, hide the region.  Otherwise make it visible.  For this
function to work, the cursor must be on the same line as the beginning regexp."
(interactive)
  (require 'outline)
  (cond
    ((or
        (looking-at beg-xsl-regexp)
        (let ((line-begin (save-excursion (beginning-of-line 1) (point))))
          (save-excursion
            (re-search-backward "\<" line-begin t)
            (looking-at beg-xsl-regexp)))
        (let ((line-begin (save-excursion (beginning-of-line 1) (point))))
          (save-excursion
            (re-search-backward "\<xsl:" line-begin t)
            (looking-at beg-xsl-regexp)))
        (let ((line-end (save-excursion (end-of-line 1) (point))))
          (save-excursion
            (re-search-forward "\<xsl:" line-end t)
            (backward-char 5)
            (looking-at beg-xsl-regexp))))
      (let* (
          congratulations
          (i 0)
          (beg-1 (match-beginning 0))
          (flag (not (get-char-property (match-end 0) 'invisible)))
          (begin-fold (match-end 0))
          end-fold
          (base-flag-match (regexp-quote
            (buffer-substring-no-properties (match-beginning 2) (match-end 2))))
          (beg-flag-match (concat "\<xsl:" base-flag-match))
          (end-flag-match (concat "\</xsl:" base-flag-match "\>"))
          (go-fish (concat "\</xsl:" base-flag-match "\>"))  )
        (save-excursion
          (when (save-excursion (re-search-forward end-flag-match nil t))
            (catch 'done
              (while t 
                (re-search-forward end-flag-match nil t)
                (when
                  (>
                    (save-excursion (re-search-backward beg-flag-match beg-1 t i) (point))
                    beg-1)
                  (setq i (1+ i)))
                (when
                  (=
                    (save-excursion (re-search-backward beg-flag-match beg-1 t i) (point))
                    beg-1)
                  (setq congratulations t)
                  (throw 'done nil)))))
          (if congratulations
            (progn
              (setq end-fold (point))
              (outline-flag-region begin-fold end-fold flag)
              (cond
                (flag
                  (overlay-put (make-overlay begin-fold end-fold) 'display "\u25be"))
                (t
                  (mapc 'delete-overlay (overlays-in begin-fold end-fold)))))
            (user-error "Error locating an ending match for:  %s." go-fish)))
        (if (> (point) begin-fold)
          (goto-char begin-fold)) ))
    (t
      (message "You are not on a line containing the beginning regexp."))))
  • Try it out with transform.xsl --- particularly the xsl:for-each on line 11 (but interestingly not the xsl:for-each on line 43). – Sean Allred Jul 23 '14 at 17:47
  • 1
    Thank you for the transform.xsl test code. I'll need to think about how we might handle nested situations containing the same regexp. At least we have a semi-working first draft to get us started. – lawlist Jul 23 '14 at 17:56
  • @Sean Allred -- I added a while-loop and counter to try and deal with the nested situations containing the same regexp -- whenever you have some free time, you can go ahead and give it a try if you'd like. – lawlist Jul 23 '14 at 21:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.