vim-xml-ftplugin vs. formatoptions

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

vim-xml-ftplugin vs. formatoptions

Rob Foehl
I've noticed that formatoptions+=c and a suitable textwidth value has no
effect with xml/xslt filetypes, and found this in
$VIMRUNTIME/autoload/xmlformat.vim:

func! xmlformat#Format()
   " only allow reformatting through the gq command
   " (e.g. Vim is in normal mode)
   if mode() != 'n'
     " do not fall back to internal formatting
     return 0
   endif
[...]

This is as shipped with 8.1.998, although the upstream version appears to
be identical at the moment.  Kind of surprised at that -- is there some
underlying reason to disable auto formatting for XML filetypes?

Removing that mode() test definitely causes problems, figured I'd ask here
before digging any further...

-Rob

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: vim-xml-ftplugin vs. formatoptions

Christian Brabandt

On Di, 26 Mär 2019, Rob Foehl wrote:

> I've noticed that formatoptions+=c and a suitable textwidth value has no
> effect with xml/xslt filetypes, and found this in
> $VIMRUNTIME/autoload/xmlformat.vim:
>
> func! xmlformat#Format()
>   " only allow reformatting through the gq command
>   " (e.g. Vim is in normal mode)
>   if mode() != 'n'
>     " do not fall back to internal formatting
>     return 0
>   endif
> [...]
>
> This is as shipped with 8.1.998, although the upstream version appears to be
> identical at the moment.  Kind of surprised at that -- is there some
> underlying reason to disable auto formatting for XML filetypes?
>
> Removing that mode() test definitely causes problems, figured I'd ask here
> before digging any further...

Maintainer here: Yes, there were some serious problems with the way
formatexpressions are evaluated, therefore I explicitly disabled it.

This is from a mail to Bram about the topic (sorry for disclosure):

Also, it looks like the doc patch has never been included, so I keep it
here for reference. (CC'ing Bram, who might want to include the doc
patch):

On Sa, 12 Mai 2018, Bram Moolenaar wrote:

> Christian wrote:
> > However when playing around a bit with formatexpession in insert mode, I
> > had all kind of strange effects (non-undoable insertions below the
> > current line, kind of a recursive call of the function, etc) so I would
> > actually go so far to discourage calling the function in insert mode (or
> > at least mention that in insert mode the function should fall back to
> > Vims internal formatter by returning non-zero).
> >
> > And in general it feels too limited to be called in insert mode for each
> > character inserted (since you have to be really careful not to overwrite
> > anything unwanted and it is a bit tricky to simply add a line break)
> >
> > Also I think it is hardly possible to make an educated guess what the
> > user actually wants from the single character to be inserted.
> >
[...]
>
> Oh, I didn't mean to include an example of a function, but just when to
> set 'formatexpr' to an existing function.  And where to do that.  I
> would assume in most cases it would be done in the ftplugin file:
>
> :set formatexpr=xmlformat#Format()
>
> With an explanation of how Vim finds the file that contains the function
> in the autoload directory.

Okay, how about this then:
diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt
index ab820b066..95479fae8 100644
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -1445,7 +1445,52 @@ to the name of an external program for Vim to use for text formatting.  The
 'textwidth' and other options have no effect on formatting by an external
 program.

-                                                       *right-justify*
+                                                        *format-formatexpr*
+The 'formatexpr' option can be set to a Vim Script function that performs
+reformatting of the buffer.  This should usually happen in a |ftplugin|, since
+formatting is highly dependent on the actually used language.  It makes sense
+to use an |autoload| script, so the corresponding script is only loaded when
+actually needed and the script should be called <filetype>format.vim.
+
+For example, the xml filetype plugin distributed with Vim in the $VIMRUNTIME
+directory, sets the 'formatexpr' option to: >
+
+   setlocal formatexpr=xmlformat#Format()
+
+That means, you will find the corresponding script in the directory
+`$VIMRUNTIME/autoload/xmlformat.vim`
+
+Here is an example script that removes trailing whitespace from the selected text: >
+
+  func! format#Format()
+    " only reformat on explicit gq command
+    if mode() != 'n'
+      " fall back to Vims internal reformatting
+      return 1
+    endif
+    let lines = getline(v:lnum, v:lnum + v:count - 1)
+    call map(lines, {key, val -> substitute(val, '\s\+$', '', 'g')})
+    call setline('.', lines)
+
+    " do not run internal formatter!
+    return 0
+  endfunc
+  setl formatexpr=format#Format()
+>
+Note: this function explicitly returns non-zero when called from insert mode
+(which basically means, text is inserted beyond the 'textwidth' limit).  This
+causes Vim to fall back to reformat the text by using the internal formatter.
+
+However, if the |gq| command is used to reformat the text, the function
+will receive the selected lines, trim trailing whitespace from those lines and
+put them back in place.  If you are going to split single lines into multiple
+lines, be careful not to overwrite anything.
+
+If you want to allow reformatting of text from insert or replace mode, one has
+to be very careful, because the function might be called recursively.  For
+debugging it helps to set the 'debug' option.
+
+                                                                *right-justify*
 There is no command in Vim to right justify text.  You can do it with
 an external command, like "par" (e.g.: "!}par" to format until the end of the
 paragraph) or set 'formatprg' to "par".


> Fixing the problems in Insert mode is a different issue.

Another inconsistency: The script will be called for every (normal)
typed character that is typed in insert mode (when beyond the textwidth
limit) but not when pressing enter. I am just mentioning it. It seems so
seldomly used, that I think it might be enough to document that there
might still be bugs and discourage using it.

Best,
Christian

--
--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

---
You received this message because you are subscribed to the Google Groups "vim_use" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.