Re: foldmethod=expr very slow
On 7/26/06, Thore B. Karlsen [EMAIL PROTECTED] wrote: set foldexpr=GetFoldLevel() function! GetFoldLevel() let line_text = getline(v:lnum) let left_idx = (stridx(line_text, '{') = 0) let right_idx = (stridx(line_text, '}') = 0) if left_idx if ! right_idx return 'a1' endif elseif right_idx return 's1' endif return '=' endfunction I spoke too soon. I tested it on another file that is 2500 lines long, and it is still unbearably slow. It gets worse towards the end of the file, where it can still take seconds for characters to show up when I type them. I think I'll have to fire up vim in a profiler to see what is causing this slowness, because if this system can compress dozens of channels of video in realtime without breaking a sweat it seems strange that inserting a character in a smallish text file would be a problem. Use of return values like 'a1', 's1' and '=' in a fold expression will cause significant slowdown. This is because vim has to recursively evaluate the fold expression for many lines every time the folding is recalculated. Since your expression returns nothing other than these particular values, it probably has to run the expression on *every* line in your file. I tried experimenting with folding expressions for c# a while back. I found that I had to return real number values for as many lines as possible. (Even when it wasn't necessary for correctness). This gave absolute fold levels for many lines and limited the recursive evaluation that vim had to use in situations where I had to return an 'a1', 's1' or '='. This was the only way I could get acceptable performance.
Re: foldmethod=expr very slow
On Wed, 26 Jul 2006 11:16:31 -0400, Cory Echols [EMAIL PROTECTED] wrote: set foldexpr=GetFoldLevel() function! GetFoldLevel() let line_text = getline(v:lnum) let left_idx = (stridx(line_text, '{') = 0) let right_idx = (stridx(line_text, '}') = 0) if left_idx if ! right_idx return 'a1' endif elseif right_idx return 's1' endif return '=' endfunction I spoke too soon. I tested it on another file that is 2500 lines long, and it is still unbearably slow. It gets worse towards the end of the file, where it can still take seconds for characters to show up when I type them. I think I'll have to fire up vim in a profiler to see what is causing this slowness, because if this system can compress dozens of channels of video in realtime without breaking a sweat it seems strange that inserting a character in a smallish text file would be a problem. Use of return values like 'a1', 's1' and '=' in a fold expression will cause significant slowdown. This is because vim has to recursively evaluate the fold expression for many lines every time the folding is recalculated. Since your expression returns nothing other than these particular values, it probably has to run the expression on *every* line in your file. Yes, I understand that. However, when I'm editing a line I would expect vim to have cached the fold levels of the surrounding lines, but it seems to reevaluate all the lines above it for every keypress. One would think everything should stay the same until something entered on the current line caused a change in the fold level. In other words, I would expect vim to continuously evaluate the foldexpr on the current line for every character I typed, and not do anything else until the fold level changed. When I open the file, it opens instantly. I can navigate around the file just fine, and open/close folds. It seems to me that there is something strange about the way the foldexpr seems to be constantly reevaluated when I'm typing. I tried experimenting with folding expressions for c# a while back. I found that I had to return real number values for as many lines as possible. (Even when it wasn't necessary for correctness). This gave absolute fold levels for many lines and limited the recursive evaluation that vim had to use in situations where I had to return an 'a1', 's1' or '='. This was the only way I could get acceptable performance. How do you do your folding? I'm not sure how I could do that the way I like to do my folding. :( Maybe I'll resort to just modifying the vim source to change the way foldmethod=marker works. -- Be seeing you.
Re: foldmethod=expr very slow
On 7/26/06, Thore B. Karlsen [EMAIL PROTECTED] wrote: On Wed, 26 Jul 2006 11:16:31 -0400, Cory Echols [EMAIL PROTECTED] wrote: Use of return values like 'a1', 's1' and '=' in a fold expression will cause significant slowdown. This is because vim has to recursively evaluate the fold expression for many lines every time the folding is recalculated. Since your expression returns nothing other than these particular values, it probably has to run the expression on *every* line in your file. Yes, I understand that. However, when I'm editing a line I would expect vim to have cached the fold levels of the surrounding lines, but it seems to reevaluate all the lines above it for every keypress. One would think everything should stay the same until something entered on the current line caused a change in the fold level. In other words, I would expect vim to continuously evaluate the foldexpr on the current line for every character I typed, and not do anything else until the fold level changed. I once wrote a foldexpression that kept track of the number of times it was evaluated. I don't remember the exact numbers, but I was astounded by the number of times it was executed for each keystroke. When I open the file, it opens instantly. I can navigate around the file just fine, and open/close folds. It seems to me that there is something strange about the way the foldexpr seems to be constantly reevaluated when I'm typing. I'm suprised the file opens so quickly. Opening the file was where my expressions were still unacceptably slow. Even so, I'll bet we're more tolerant of delays while opening that we are of delays between insert-mode keystrokes. I tried experimenting with folding expressions for c# a while back. I found that I had to return real number values for as many lines as possible. (Even when it wasn't necessary for correctness). This gave absolute fold levels for many lines and limited the recursive evaluation that vim had to use in situations where I had to return an 'a1', 's1' or '='. This was the only way I could get acceptable performance. How do you do your folding? I'm not sure how I could do that the way I like to do my folding. :( Maybe I'll resort to just modifying the vim source to change the way foldmethod=marker works. I pretty much gave up on the idea of nested folds. I decided that I would only fold method bodies at level 1. This gave me lots of shortcuts for keywords that only appeared inside method bodies (so my expression could return '1' for those lines). I might post my code, but it's verbose and very much overkill because it contains many functions that I hoped would be useful for more general c# editing.
Re: foldmethod=expr very slow
On Wed, 26 Jul 2006 14:05:45 -0400, Cory Echols [EMAIL PROTECTED] wrote: In other words, I would expect vim to continuously evaluate the foldexpr on the current line for every character I typed, and not do anything else until the fold level changed. I once wrote a foldexpression that kept track of the number of times it was evaluated. I don't remember the exact numbers, but I was astounded by the number of times it was executed for each keystroke. I just tried that, and my suspicions were confirmed. When in insert mode, any keystroke will cause foldexpr to be evaluated for every line above the current line. When I open the file, it opens instantly. I can navigate around the file just fine, and open/close folds. It seems to me that there is something strange about the way the foldexpr seems to be constantly reevaluated when I'm typing. I'm suprised the file opens so quickly. Opening the file was where my expressions were still unacceptably slow. Even so, I'll bet we're more tolerant of delays while opening that we are of delays between insert-mode keystrokes. That must be it. I can wait a second or two while the file is being opened, but waiting a second or two between each keystroke when I'm writing is too much. [...] I pretty much gave up on the idea of nested folds. I decided that I would only fold method bodies at level 1. This gave me lots of shortcuts for keywords that only appeared inside method bodies (so my expression could return '1' for those lines). I might post my code, but it's verbose and very much overkill because it contains many functions that I hoped would be useful for more general c# editing. Well, I think I've found a solution that works for me. It turns out that what was causing my problems was where vim interpreted a number following a marker as a fold level. A line like this would mess up my folds: int array[16] = {0}; In those cases it's easy enough to insert a space before the 0, but there are cases where it's not that easy, or not desireable. What I ended up doing was changing fold.c to not look for a fold level after a marker, and recompiling. Now everything seems to work great, and I don't notice any slowdown. Perhaps there should be an option for not interpreting numbers after a fold marker as a fold level, but I don't know if this is causing enough people grief that it would be included. I'm happy with my quick fix for now. -- Be seeing you.
Re: foldmethod=expr very slow
On Wed, Jul 26, 2006 at 03:33:55PM -0500, Thore B. Karlsen wrote: Well, I think I've found a solution that works for me. It turns out that what was causing my problems was where vim interpreted a number following a marker as a fold level. A line like this would mess up my folds: int array[16] = {0}; In those cases it's easy enough to insert a space before the 0, but there are cases where it's not that easy, or not desireable. What I ended up doing was changing fold.c to not look for a fold level after a marker, and recompiling. Now everything seems to work great, and I don't notice any slowdown. Perhaps there should be an option for not interpreting numbers after a fold marker as a fold level, but I don't know if this is causing enough people grief that it would be included. I'm happy with my quick fix for now. I am surprised that {0} is recognized as a fold marker. Do you have 'foldmarker' set to the default value of {{{,}}} or something else? In my limited tests (try zc in Normal mode and see whether vim throws an error message) {0} is not recognized as a fold marker but {{{0}}} is. HTH --Benji Fisher
Re: foldmethod=expr very slow
On Wed, 26 Jul 2006 17:19:42 -0400, Benji Fisher [EMAIL PROTECTED] wrote: Well, I think I've found a solution that works for me. It turns out that what was causing my problems was where vim interpreted a number following a marker as a fold level. A line like this would mess up my folds: int array[16] = {0}; In those cases it's easy enough to insert a space before the 0, but there are cases where it's not that easy, or not desireable. What I ended up doing was changing fold.c to not look for a fold level after a marker, and recompiling. Now everything seems to work great, and I don't notice any slowdown. Perhaps there should be an option for not interpreting numbers after a fold marker as a fold level, but I don't know if this is causing enough people grief that it would be included. I'm happy with my quick fix for now. I am surprised that {0} is recognized as a fold marker. Do you have 'foldmarker' set to the default value of {{{,}}} or something else? In my limited tests (try zc in Normal mode and see whether vim throws an error message) {0} is not recognized as a fold marker but {{{0}}} is. I have foldmarker set to {,} to make folds automatically in languages like C, C++, Java, C#, PHP, Perl, etc. -- Be seeing you.
Re: foldmethod=expr very slow
Hi Thore, You can probably get away with foldmethod=expr in large files by de-activating it in Insert mode. I.e., add this to your after/ftplugin/php.vim: augroup FastFold autocmd! autocmd InsertEnter * if ft == 'php' | setlocal foldmethod=manual | endif autocmd Insertleave * if ft == 'php' | setlocal foldmethod=expr | endif augroup end I tried it out and it actually seems to work. Folds are re-evaluated when you are finished inserting. HTH, Peter --- Thore B. Karlsen [EMAIL PROTECTED] wrote: On Mon, 24 Jul 2006 23:48:12 -0500, Thore B. Karlsen [EMAIL PROTECTED] wrote: Hi Thore, I've never tried folding like this before, and unfortunately I don't have time to try out this 'optimized' version, but it may work faster for you (I've just replaced the regex matches with stridx and rearranged the code flow): set foldexpr=GetFoldLevel() function! GetFoldLevel() let line_text = getline(v:lnum) let left_idx = (stridx(line_text, '{') = 0) let right_idx = (stridx(line_text, '}') = 0) if left_idx if ! right_idx return 'a1' endif elseif right_idx return 's1' endif return '=' endfunction Thanks! I did a quick test, and that does appear to speed it up. One of the files that was giving me problems before is now fast enough to work in. There's still a slight latency when I type, but it's much better. I'll do some more testing to see how it works in other files, but this looks promising! I spoke too soon. I tested it on another file that is 2500 lines long, and it is still unbearably slow. It gets worse towards the end of the file, where it can still take seconds for characters to show up when I type them. I think I'll have to fire up vim in a profiler to see what is causing this slowness, because if this system can compress dozens of channels of video in realtime without breaking a sweat it seems strange that inserting a character in a smallish text file would be a problem. -- Be seeing you. Send instant messages to your online friends http://au.messenger.yahoo.com
Re: foldmethod=expr very slow
On Mon, Jul 24, 2006 at 12:30:07PM -0500, Thore B. Karlsen wrote: I use foldmethod=expr with the following foldexpr: set foldexpr=GetFoldLevel(v:lnum) function! GetFoldLevel(line) let line_text = getline(a:line) if (line_text =~ '\%({.*}\)\|\%(}.*{\)') return '=' elseif (line_text =~ '{') return a1 elseif (line_text =~ '}') return s1 endif return '=' endfunction I haven't read the above too carefully: But if all you want to do is fold your code based on {...} blocks, then use Vim 7 and set fdm=syntax (for C / C++ files). Incidentally, fdm=syntax is also slow (though much much faster than fdm=expr). I could (grudgingly) live with a short delay when first loading the file. The thing that bothers me is that when I switch between buffers, Vim takes it's own sweet time to get the syntax based folding right. So I only enable syntax folding for files that have less than 3000 lines. Once my clever spies steal Benji Fisher's computer, I'm going to up this limit to 18000. GI -- You're not drunk if you can lie on the floor without holding on.
Re: foldmethod=expr very slow
On Mon, 24 Jul 2006 13:06:47 -0500, Gautam Iyer [EMAIL PROTECTED] wrote: I use foldmethod=expr with the following foldexpr: set foldexpr=GetFoldLevel(v:lnum) function! GetFoldLevel(line) let line_text = getline(a:line) if (line_text =~ '\%({.*}\)\|\%(}.*{\)') return '=' elseif (line_text =~ '{') return a1 elseif (line_text =~ '}') return s1 endif return '=' endfunction I haven't read the above too carefully: But if all you want to do is fold your code based on {...} blocks, then use Vim 7 and set fdm=syntax (for C / C++ files). Unfortunately, that doesn't work for the way I do my folding. I also insert braces manually in comments where I want folds, e.g.: //@{ Private data. private int blah; //@} Incidentally, fdm=syntax is also slow (though much much faster than fdm=expr). I could (grudgingly) live with a short delay when first loading the file. The thing that bothers me is that when I switch between buffers, Vim takes it's own sweet time to get the syntax based folding right. I wonder why, because you'd think it would be about the same work as just figuring out the syntax highlighting? So I only enable syntax folding for files that have less than 3000 lines. Once my clever spies steal Benji Fisher's computer, I'm going to up this limit to 18000. I have a quad qore Opteron machine, perhaps if vim could take advantage of all the CPUs it would be tolerable. :) -- Be seeing you.
Re: foldmethod=expr very slow
Hi Thore, I've never tried folding like this before, and unfortunately I don't have time to try out this 'optimized' version, but it may work faster for you (I've just replaced the regex matches with stridx and rearranged the code flow): set foldexpr=GetFoldLevel() function! GetFoldLevel() let line_text = getline(v:lnum) let left_idx = (stridx(line_text, '{') = 0) let right_idx = (stridx(line_text, '}') = 0) if left_idx if ! right_idx return 'a1' endif elseif right_idx return 's1' endif return '=' endfunction HTH, Peter --- Thore B. Karlsen [EMAIL PROTECTED] wrote: I use foldmethod=expr with the following foldexpr: set foldexpr=GetFoldLevel(v:lnum) function! GetFoldLevel(line) let line_text = getline(a:line) if (line_text =~ '\%({.*}\)\|\%(}.*{\)') return '=' elseif (line_text =~ '{') return a1 elseif (line_text =~ '}') return s1 endif return '=' endfunction What I want to do is similar to foldmethod=marker with foldmarker={,}, but if I use foldmethod=marker vim gets confused by lines that contain both { and } like these: string s = String.Format({0}, v); string[] sa = new string[] { a, b }; GetFoldLevel() above fixes that, in that it keeps the same fold level if both { and } are found on the same line, but it is horribly slow. Even in pretty small files (1k lines long), it can take several seconds for characters to appear when I'm typing in insert mode. Is there a way to optimize the above, or an alternative way of doing this? It is very frustrating to have my folds get out of whack with foldmethod=marker, but the slowness of this foldexpr is unbearable. -- Be seeing you. Send instant messages to your online friends http://au.messenger.yahoo.com