On Fri, 16 Mar 2012, Dotan Cohen wrote:

Hi all, I am having a real hard time with an indeterminate bug in a
VIM function. First, here is the function:

[...]
set statusline+=%{WhatFunctionAreWeIn()}

fun WhatFunctionAreWeIn()
[...]


This function displays the current PHP function name in the status bar. It is derived from this gem:
http://vim.wikia.com/wiki/VimTip1296

Both the original function from the VIM wiki and my derived version suffer an indeterminate bug. Sometimes when scrolling down with J the cursor will "jump" to the wrong location. When this happens one can simply `z to bring the cursor back to where it should be. I would say that about one line in every 100 lines of PHP that I have triggers the bug.

There are at least two things going on:

1. items in an 'stl' %{} group are expanded. So, if you ever return a line that contains a '%', you'll have trouble. I worked around this by renaming your function from WhatFunctionAreWeIn to RawWhatFunctionAreWeIn, then creating:

fun! WhatFunctionAreWeIn()
   let stl=RawWhatFunctionAreWeIn()
   let stl=substitute(stl, '\t', ' ', 'g')  " tabs don't show up right
   let stl=substitute(stl, '%', '%%', 'g')  " need to escape %'s
   return stl
endfun

2. The :help for 'stl' states that you shouldn't change text or jump to another window. (See :help textlock).

But, even more strongly, you *probably* shouldn't move the cursor in a function called from 'stl'. When your function calls [{ to find the prior block, it moves the displayed text. That's what causes the jump. The problem is that the sequence of events for updating the displayed text seems to vary for different types of movement. I was unable to trigger the bug with <C-d> and <C-u> movement, for example. But, I could pretty consistently trigger it (when viewing Vim help files) by rapidly using 'k' to move up a single line.



Here's a much simpler function for what you're trying to do (also more naïve, but it's a trade-off):

" still used in the same way:
" e.g.: set statusline+=%{WhatFunctionAreWeIn()}

fun! StatusLineSafe(txt)
   let stl = a:txt
   let stl = substitute(stl, '\t', ' ', 'g') " tabs don't show up right
   let stl = substitute(stl, '%', '%%', 'g') " need to escape %'s
   return stl
endfun

fun! WhatFunctionAreWeIn()
   let strList = ['function', 'class']
   let lnum = line('.') - 1
   while lnum > 0
      let line = getline(lnum)
      let lnum -= 1
      if line =~ '^\s*#'     " simple improvement to skip comments
         continue
      endif
      for item in strList
         let position = match(line, '\<'.item.'\>')
         if position >= 0
             break
         endif
      endfor
      if position >= 0
         return StatusLineSafe("[line ".(lnum+1)."] ".line)
      endif
   endwhile
   return ''  " return empty string if it's unknown
endfun

--
Best,
Ben

--
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

Reply via email to