How to write formatexpr script?

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

How to write formatexpr script?

Edward L. Fox
Hi VIMmers,

Mr. Moolenaar had implemented a very nice interface for formatting text in the
newest Vim 7 snapshot. See ":help formatexpr" for more details.

As Mr. Moolenaar said, now it is possible to write our own formatting script
to deal with more complicated languages, for example, the Asian languages such
as Chinese, Japanese and Korean. But I'm still puzzled of how to write this
kind of scripts. Any one can offer me a script that can emulate the current
behavior of the built-in formatting function? Including:

1. Detect the information from the current settings, such as "textwidth",
"linebreak", "formatoptions", etc.

2. Preserve the indent and prefix of each line.

3. Some other stuff, if exists.

Thanks very much for your help!


Regards,


Edward L. Fox
Reply | Threaded
Open this post in threaded view
|

Re: How to write formatexpr script?

Benji Fisher
On Wed, Feb 22, 2006 at 04:44:58PM +0800, Edward L. Fox wrote:

> Hi VIMmers,
>
> Mr. Moolenaar had implemented a very nice interface for formatting text in the
> newest Vim 7 snapshot. See ":help formatexpr" for more details.
>
> As Mr. Moolenaar said, now it is possible to write our own formatting script
> to deal with more complicated languages, for example, the Asian languages such
> as Chinese, Japanese and Korean. But I'm still puzzled of how to write this
> kind of scripts. Any one can offer me a script that can emulate the current
> behavior of the built-in formatting function? Including:
>
> 1. Detect the information from the current settings, such as "textwidth",
> "linebreak", "formatoptions", etc.
>
> 2. Preserve the indent and prefix of each line.
>
> 3. Some other stuff, if exists.

     That is a big job, but (I think) a useful one.  Doing this well is
probably too complicated for including in the docs, but if someone can
do a decent job, it could be included somewhere in the standard
distribution, with a reference to it in the docs.

     So here is a start.  It uses getline() and setline() to generate
and insert a List of lines.  Writing a real format script will be more
complicated, since the number of lines is likely to change.  It uses
map() to change the lines; since the second argument of map() is an
expression that can be pretty nasty, I use it to call a script-local
function.  Finally, I illustrate how to change the behavior based on the
'textwidth' option (just an example, not very realistic).

     If anyone wants to continue working on this, I can offer advice,
but I am not planning to write a comprehensive version myself.

:help expr-option
:help getline()
:help setline()
:help map()


fun! MyFormat()
  let lines = getline(v:lnum, v:lnum + v:count - 1)
  if &tw > 0 && max(map(copy(lines), 'strlen(v:val)')) > &tw
    let indent = ""
  else
    let indent = matchstr(lines[0], '\s*')
  endif
  call map(lines, 's:MyLineFormat(v:val, "' . escape(indent, '\') . '")')
  call setline(v:lnum, lines)
endfun

fun! s:MyLineFormat(val, ...)
  let prefix = (a:0 > 0) ? a:1 : ""
  let postfix = (a:0 > 1) ? a:2 : ""
  return prefix . matchstr(a:val, '\S.*') . postfix
endfun

HTH --Benji Fisher