Re: formatexpr, append() and undo

2006-05-16 Thread Jiří Černý
On Mon, May 15, 2006 at 06:26:55PM -0400, Benji Fisher wrote:
 
 
 Please do post the script you use, simplified as much as possible,
 so we can test it.  I tried
 
 :call append(line($), This line brought to you by append())
 
 and then (in Normal mode)
 
 u
 
 and it worked fine.  This is with vim 7.0.
 

Here are the scripts and the test case. It is relatively complicated,
but I did not find a simpler one. It works in vim 7.0 (Included patches:
1-17)

1. First you need the script that I wrote and a small test file. They
attached to this email. Put it into files format.vim and foo

2. vim -U NONE -u NONE foo
:set nocompatible
:source format.vim
:set tw=20 this is not necessary, it only saves some typing

3. now go to the first line of , type o (open line) and
start to type something like the text below between the two lines of
=. Do not hit Enter, let the vim format the text.

lajsdf lkjfd lkasjfd
alskjdf aslkjfd
;laskdjf salkjfd    one needs first to 
l;askjdf ;alskjdf   write some normal lines
;lsajdf lsakjdf
aslkjfd
$laskjdf dfsaf$ lsdk    (*)
fasldkfj asdlkjf
asdflj
$laksjdf asfldkj    (**)

(*) this formula is important, it was started at the previous line but
was moved by the formatting mechanism to this line
(**) this formula was also started one line above 

4. Now hit ESC and 'u'. I do not get back two lines of ===. 
The last three (or two, it depends what exactly did you type) lines of
the text remain (partially with different formatting). 
Moreover, when I hit 'u' again vim says 'Already at oldest change'
It is not possible to undo to the original state.

I hope the description is good enough and the bug is reproducible. 

Regards,

Jiri



==
==
if exists(b:did_my_tex_format_pluggin)
finish
endif

let b:did_my_tex_format_pluggin = 1

setlocal formatoptions=tcqr 
setlocal formatexpr=MyTeXFormat(v:lnum,v:count)


fun! MyTeXFormat(lnum,count)
if tw  10 let the vim do the job if tw is to small
return 1
endif
if mode()==i
return SIDMyFormatInsert(a:lnum,a:count)
elseif mode()==R
return SIDMyFormatReplace(a:lnum,a:count)
else
return SIDMyFormatGQ(a:lnum,a:count)
endif
endfun

fun! s:MyFormatInsert(lnum,count)   
if a:count!=1
echoerr Assertion failed: count1
return 1
endif

if col(.)  tw
return 0
endif

let line = getline(a:lnum)
let curlineindent = indent(a:lnum)
let aftercursor = line[col(.)-1:]
let beforecursor = line[:col(.)-2]

let dolarpos = SIDFindDolar(beforecursor,0)
if dolarpos == -1 no dolars, vim do the job
return 1
endif

let evendolars = 0
let newpos = dolarpos
while newpos != -1 count dollars find the last one 
let olddolarpos = dolarpos
let dolarpos = newpos
let evendolars =  1 -  evendolars   
let newpos = SIDFindDolar(beforecursor,dolarpos + 1)
endwhile

if evendolars == 0 
if dolarpos  tw vim can do the job
return 1
elseif olddolarpos  curlineindent  
let dolarpos = olddolarpos break at the start of the 
formula
else 
call append(a:lnum,XX) 
let newline =   aftercursor
call setline(a:lnum+1,newline)
call cursor(a:lnum+1,1)
return 0
endif
endif

if beforecursor[dolarpos-1]=='$' double dollars
let dolarpos = dolarpos - 1
endif

if beforecursor[dolarpos-1] != ' ' no space before $
let dolarpos = strridx(beforecursor,' ',dolarpos-1)
let dolarpos = dolarpos + 1
endif
if dolarpos != curlineindent formula does not start at first char
call setline(a:lnum,strpart(beforecursor,0,dolarpos))
call append(a:lnum,XX)
let newline =  strpart(beforecursor,dolarpos) . aftercursor
call setline(a:lnum+1,newline)
call cursor(a:lnum+1,strlen(beforecursor)-dolarpos+1)
return 0
endif
return 0
endfun

fun! s:MyFormatReplace(lnum,count)
FIXME make something useful
I never use replace mode
return 1
endfun

fun! s:MyFormatGQ(lnum,count)
probably useles, vim does not know about ''latex type paragraphs''
return 1
endfun

fun! s:FindDolar(s, pos)
let i = match(a:s,'\%(^\|[^\\]\)\$',a:pos)
if i == -1 
return -1
endif
if a:s[i] != '$'
   

formatexpr, append() and undo

2006-05-15 Thread Jiří Černý
Hello,

I have tried to write a function for formatting TeX files using the new
'formatexpr' function. Goal is (of course) to keep matching dollars on
one line and not to use the insert mapping of space. 

I have more or less found a good solution. The only problem is that this
solution interacts quite badly with the undo mechanism of vim. The
function I wrote uses vim internal formatting algorithm when no special
treatment is necessary (returns 1) otherwise it does the formatting job
and returns 0. In the second case it uses append() function to add a new
line under the current line.

I have feeling that this append() function is not recorded for the undo.
Essentially, every use of append() for formatting during an insertion of
a long paragraph results in one line that is left in the file after
undoing this insertion. 

I can post the scripts that I use if it is necessary, but maybe the
description is sufficient to understand the problem. 

It is also maybe possible to use different means to append the line, but
I find append() to be the best one.   

This problem appears in VIM 7.0c10. I had no time to compile the final
version, so sorry if this problem has been already resolved. 

Thanks,

Jiri