Ответ на сообщение «Re: Progress indicator for :TOhtml command», присланное в 13:03:23 06 июня 2010, Воскресенье, отправитель ZyX:
Yes, buffer switching is the problem: attached patch uses my technique (save everything in a list, not in a buffer) and here are the results: My script: 1:05,09 w/o progress 1:08,40 ShowProgress=1 1:20,59 ShowProgress=2 Your 2html: 1:19,67 w/o progress 1:44,74 with progress Patched 2html: 1:03,51 w/o progress 1:05,08 with progress Apply patch to your 2html, not to previously patched version. Текст сообщения: > Ответ на сообщение «Re: Progress indicator for :TOhtml command», > присланное в 10:59:42 06 июня 2010, Воскресенье, > отправитель Benjamin Fritz: > > It is odd: the only problem in your script is redrawstatus which is called > only 100 times (without styles, 109 with) (>21 seconds), while in my > script redrawstatus called 328 times takes less than a second. > > Second problem with the whole 2html is buffer switching, I think you should > consider instead of doing constant switches, save every line in a List and > only after everything is finished create a new buffer and call setline(1, > s:list). Note that new versions of my script are faster (but not much) > then your 2html because I use this technique. > > And, why do you calculate length of the title at each progressbarupdate? > Attached patch fixes this and the case when there is no space for progress > bar. > > Текст сообщения: > > On Jun 5, 8:10 pm, ZyX <[email protected]> wrote: > > > It occures that the problem is not floating-point math: the attached > > > patch removes this math but does not add any perfomance. > > > > Yes, I did not expect any performance gains from removing the little > > bit of remaining floating point, since it is just up to 100 > > calculations done once at the start and thereafter only when the > > window changes size. It is a good idea to remove, because as you point > > out, that amount of precision is probably unnecessary, and it would > > just introduce another dependency. > > > > > It also removes recalculating > > > progress bar width (you just used used some generic progress bar?) and > > > needs_redraw. > > > > Yes, we did use a generic progress bar as the starting point for this. > > However, I think it IS necessary to recalculate the progress bar > > width. This is done so that if the user changes window sizes, the > > progress bar will be updated accordingly. We don't want a progress bar > > that is too big to fit in the window, or smaller than needed for > > decent viewing. With your patch, if you start with the gvim window > > maximized, then restore the window to a smaller size, Vim goes blank > > until the next progress bar update, and then the progress bar is too > > large to fit on the screen and is truncated. This is not desirable, > > but perhaps it would acceptable if the performance gains are great > > enough. This does not seem to be the case, because I added back in the > > size recalculation with no noticeable performance hit. > > > > The needs_redraw was done in order to allow us to call redrawstatus on > > the correct window. :help redrawstatus says that it redraws the status > > line for the *current window* only unless you use redrawstatus! which > > redraws all windows. In practice, however, it does not seem to matter > > which window we use it in. Why is this? > > > > > Also, why you forbid profiling progress bar functions? It is also > > > fixed. > > > > Good catch, that's certainly something to include going forward. > > > > There is a slight speed gain from your patch, however there is a > > mistaken assumption in the way you update the progress bar. Your code > > assumes that the progress bar will only ever update by one tick at a > > time. Updating the progress bar without your patch calculates the > > entire string every time, using repeat(). Your update simply adds one > > to the colored string of spaces, and subtracts one from the uncolored. > > This does not work if the user folds away some text and does not use > > dynamic folding, it does not work when there are fewer than 100 lines > > in the text to convert, and it does not work for the second use of the > > progress bar, where there are usually fewer that 100 highlight groups > > to process. > > > > I corrected this problem and initially, the performance still seemed > > to be improved over the previous version. However, I noticed afterward > > that part of the patch removes the "sleep 100m" from the "processing > > classes" step. I took this line out of the original script for a fair > > comparison, and got the following timings, converting > > autoload/netrw.vim (7764 lines) with dynamic folding enabled: > > > > Before patch: 50 seconds > > Patch from ZyX: 49 seconds > > Fixed patch: 51 seconds > > > > So, it looks like the patch is actually no faster, and potentially > > slightly slower than the precalculated version. > > > > I have therefore attached an updated version of my last submission, > > which removes floating point from the calculate_ticks function, and > > incorporates some of the other improvements from ZyX. > > > > This version takes 50 seconds to convert netrw, if I comment out the > > sleep 100 line. Do we want this line in the code? Without it, if there > > are not very many highlight groups to process, the "processing > > classes" bar flashes by without being seen. This happens anyway for > > very small selections. I don't know how I feel about deliberately > > slowing down the execution. I have left it commented out for now. > > > > I am very curious about this: > > > > " Note that you must use len(split) instead of len() if you want to use > > " unicode in title > > let self.pb_len = max_len-len(split(self.title, '\zs'))-3-4-2 > > > > Can someone explain the problem described in the comment a little > > better? And why does the split on '\zs' work to fix the problem? >
--- oldnew2html.vim 2010-06-06 12:24:39.000000000 +0400
+++ 2html.vim 2010-06-06 13:58:01.000000000 +0400
@@ -321,9 +321,11 @@
set magic
+let s:lines=[]
+
if exists("use_xhtml")
if s:html_encoding != ""
- exe "normal! a<?xml version=\"1.0\" encoding=\"" . s:html_encoding . "\"?>\n\e"
+ call add(s:lines, "<?xml version=\"1.0\" encoding=\"" . s:html_encoding . "\"?>")
else
- exe "normal! a<?xml version=\"1.0\"?>\n\e"
+ call add(s:lines, "<?xml version=\"1.0\"?>")
endif
let s:tag_close = ' />'
@@ -353,9 +355,12 @@
" HTML header, with the title and generator ;-). Left free space for the CSS,
" to be filled at the end.
-exe "normal! a<html>\n\e"
-exe "normal! a<head>\n<title>" . expand("%:p:~") . "</title>\n\e"
-exe "normal! a<meta name=\"Generator\" content=\"Vim/" . v:version/100 . "." . v:version %100 . '"' . s:tag_close . "\n\e"
+call extend(s:lines, [
+ \"<html>",
+ \"<head>",
+ \("<title>".expand("%:p:~")."</title>"),
+ \("<meta name=\"Generator\" content=\"Vim/".v:version/100.".".v:version%100.'"'.s:tag_close),
+ \])
if s:html_encoding != ""
- exe "normal! a<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:html_encoding . '"' . s:tag_close . "\n\e"
+ call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" . s:html_encoding . '"' . s:tag_close)
endif
@@ -364,55 +369,65 @@
if exists("s:html_hover_unfold")
" if we are doing hover_unfold, use css 2 with css 1 fallback for IE6
- exe "normal! a".
- \ "<style type=\"text/css\">\n<!--\n".
- \ ".FoldColumn { text-decoration: none; white-space: pre; }\n\n".
- \ "body * { margin: 0; padding: 0; }\n".
- \ "\n".
- \ ".open-fold > .Folded { display: none; }\n".
- \ ".open-fold > .fulltext { display: inline; }\n".
- \ ".closed-fold > .fulltext { display: none; }\n".
- \ ".closed-fold > .Folded { display: inline; }\n".
- \ "\n".
- \ ".open-fold > .toggle-open { display: none; }\n".
- \ ".open-fold > .toggle-closed { display: inline; }\n".
- \ ".closed-fold > .toggle-open { display: inline; }\n".
- \ ".closed-fold > .toggle-closed { display: none; }\n"
- exe "normal! a\n/* opening a fold while hovering won't be supported by IE6 and other\n".
- \ "similar browsers, but it should fail gracefully. */\n".
- \ ".closed-fold:hover > .fulltext { display: inline; }\n".
- \ ".closed-fold:hover > .toggle-filler { display: none; }\n".
- \ ".closed-fold:hover > .Folded { display: none; }\n"
- exe "normal! a-->\n</style>\n"
- exe "normal! a<!--[if lt IE 7]>".
- \ "<style type=\"text/css\">\n".
- \ ".open-fold .Folded { display: none; }\n".
- \ ".open-fold .fulltext { display: inline; }\n".
- \ ".open-fold .toggle-open { display: none; }\n".
- \ ".closed-fold .toggle-closed { display: inline; }\n".
- \ "\n".
- \ ".closed-fold .fulltext { display: none; }\n".
- \ ".closed-fold .Folded { display: inline; }\n".
- \ ".closed-fold .toggle-open { display: inline; }\n".
- \ ".closed-fold .toggle-closed { display: none; }\n".
- \ "</style>\n".
- \ "<![endif]-->\n"
+ call extend(s:lines, [
+ \ "<style type=\"text/css\">",
+ \ "<!--",
+ \ ".FoldColumn { text-decoration: none; white-space: pre; }",
+ \ "",
+ \ "body * { margin: 0; padding: 0; }", "",
+ \ ".open-fold > .Folded { display: none; }",
+ \ ".open-fold > .fulltext { display: inline; }",
+ \ ".closed-fold > .fulltext { display: none; }",
+ \ ".closed-fold > .Folded { display: inline; }",
+ \ "",
+ \ ".open-fold > .toggle-open { display: none; }",
+ \ ".open-fold > .toggle-closed { display: inline; }",
+ \ ".closed-fold > .toggle-open { display: inline; }",
+ \ ".closed-fold > .toggle-closed { display: none; }",
+ \ "", "",
+ \ '/* opening a fold while hovering won''t be supported by IE6 and other',
+ \ "similar browsers, but it should fail gracefully. */",
+ \ ".closed-fold:hover > .fulltext { display: inline; }",
+ \ ".closed-fold:hover > .toggle-filler { display: none; }",
+ \ ".closed-fold:hover > .Folded { display: none; }",
+ \ '-->',
+ \ '<style>',
+ \ "<!--[if lt IE 7]><style type=\"text/css\">",
+ \ ".open-fold .Folded { display: none; }",
+ \ ".open-fold .fulltext { display: inline; }",
+ \ ".open-fold .toggle-open { display: none; }",
+ \ ".closed-fold .toggle-closed { display: inline; }",
+ \ "",
+ \ ".closed-fold .fulltext { display: none; }",
+ \ ".closed-fold .Folded { display: inline; }",
+ \ ".closed-fold .toggle-open { display: inline; }",
+ \ ".closed-fold .toggle-closed { display: none; }",
+ \ "</style>",
+ \ "<![endif]-->",
+ \])
else
" if we aren't doing hover_unfold, use CSS 1 only
- exe "normal! a<style type=\"text/css\">\n<!--\n".
- \ ".FoldColumn { text-decoration: none; white-space: pre; }\n\n".
- \ ".open-fold .Folded { display: none; }\n".
- \ ".open-fold .fulltext { display: inline; }\n".
- \ ".open-fold .toggle-open { display: none; }\n".
- \ ".closed-fold .toggle-closed { display: inline; }\n".
- \ "\n".
- \ ".closed-fold .fulltext { display: none; }\n".
- \ ".closed-fold .Folded { display: inline; }\n".
- \ ".closed-fold .toggle-open { display: inline; }\n".
- \ ".closed-fold .toggle-closed { display: none; }\n".
- \ "-->\n</style>\n"
+ call extend(s:lines, [
+ \ "<style type=\"text/css\">\n<!--",
+ \ ".FoldColumn { text-decoration: none; white-space: pre; }\n",
+ \ ".open-fold .Folded { display: none; }",
+ \ ".open-fold .fulltext { display: inline; }",
+ \ ".open-fold .toggle-open { display: none; }",
+ \ ".closed-fold .toggle-closed { display: inline; }",
+ \ "",
+ \ ".closed-fold .fulltext { display: none; }",
+ \ ".closed-fold .Folded { display: inline; }",
+ \ ".closed-fold .toggle-open { display: inline; }",
+ \ ".closed-fold .toggle-closed { display: none; }",
+ \ '-->\n</style>'
+ \])
endif
else
" if we aren't doing any dynamic folding, no need for any special rules
- exe "normal! a<style type=\"text/css\">\n<!--\n-->\n</style>\n\e"
+ call extend(s:lines, [
+ \ "<style type=\"text/css\">",
+ \ "<!--",
+ \ '-->',
+ \ "</style>",
+ \])
endif
endif
@@ -420,28 +435,30 @@
" insert javascript to toggle folds open and closed
if exists("s:html_dynamic_folds")
- exe "normal! a\n".
- \ "<script type='text/javascript'>\n".
- \ "<!--\n".
- \ "function toggleFold(objID)\n".
- \ "{\n".
- \ " var fold;\n".
- \ " fold = document.getElementById(objID);\n".
- \ " if(fold.className == 'closed-fold')\n".
- \ " {\n".
- \ " fold.className = 'open-fold';\n".
- \ " }\n".
- \ " else if (fold.className == 'open-fold')\n".
- \ " {\n".
- \ " fold.className = 'closed-fold';\n".
- \ " }\n".
- \ "}\n".
- \ "-->\n".
- \ "</script>\n\e"
+ call extend(s:lines, [
+ \ "",
+ \ "<script type='text/javascript'>",
+ \ "<!--",
+ \ "function toggleFold(objID)",
+ \ "{",
+ \ " var fold;",
+ \ " fold = document.getElementById(objID);",
+ \ " if(fold.className == 'closed-fold')",
+ \ " {",
+ \ " fold.className = 'open-fold';",
+ \ " }",
+ \ " else if (fold.className == 'open-fold')",
+ \ " {",
+ \ " fold.className = 'closed-fold';",
+ \ " }",
+ \ "}",
+ \ '-->',
+ \ "</script>"
+ \])
endif
if exists("html_no_pre")
- exe "normal! a</head>\n<body>\n\e"
+ call extend(s:lines, ["</head>", "<body>"])
else
- exe "normal! a</head>\n<body>\n<pre>\n\e"
+ call extend(s:lines, ["</head>", "<body>", "<pre>"])
endif
@@ -561,4 +578,11 @@
let pgb.last_value = 0
let pgb.needs_redraw = 0
+ " Note that you must use len(split) instead of len() if you want to use
+ " unicode in title.
+ "
+ " Subtract 3 for spacing around the title.
+ " Subtract 4 for the percentage display.
+ " Subtract 2 for spacing before this.
+ let pgb.substractedlen=len(split(pgb.title, '\zs'))+3+4+2
let pgb.max_len = 0
set laststatus=2
@@ -568,5 +592,10 @@
" Function: progressbar.calculate_ticks() {{{1
func! s:progressbar.calculate_ticks(pb_len)
- let self.progress_ticks = map(range(a:pb_len+1), "v:val * self.max_value / a:pb_len")
+ if a:pb_len<=0
+ let pb_len = 100
+ else
+ let pb_len = a:pb_len
+ endif
+ let self.progress_ticks = map(range(pb_len+1), "v:val * self.max_value / pb_len")
endfun
@@ -581,11 +610,5 @@
" Progressbar length
- " Note that you must use len(split) instead of len() if you want to use
- " unicode in title.
- "
- " Subtract 3 for spacing around the title.
- " Subtract 4 for the percentage display.
- " Subtract 2 for spacing before this.
- let pb_len = max_len-len(split(self.title, '\zs'))-3-4-2
+ let pb_len = max_len - self.substractedlen
let pb_len = pb_len > 100 ? 100 : pb_len
@@ -601,6 +624,8 @@
endif
+ let cur_val_max = pb_len > 0 ? pb_len : 100
+
" find the current progress bar position based on precalculated thresholds
- while cur_value < pb_len && self.cur_value > self.progress_ticks[cur_value]
+ while cur_value < cur_val_max && self.cur_value > self.progress_ticks[cur_value]
let cur_value += 1
endwhile
@@ -617,7 +642,9 @@
let stl = "%#".t_color."#%-( ".self.title." %)".
- \"%#".b_color."#|".
- \"%#".b_fcolor."#%-(".repeat(" ",cur_value)."%)".
- \"%#".b_color."#".repeat(" ",pb_len-cur_value)."|".
+ \"%#".b_color."#".
+ \(pb_len>0 ?
+ \ ('|%#'.b_fcolor."#%-(".repeat(" ",cur_value)."%)".
+ \ '%#'.b_color."#".repeat(" ",pb_len-cur_value)."|"):
+ \ ('')).
\"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)"
call setwinvar(self.winnr, '&stl', stl)
@@ -634,5 +661,5 @@
endfun
" }}}
- let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:newwin)
+ let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:orgwin)
else
let s:html_no_progress=1
@@ -687,7 +714,5 @@
let s:new = repeat(s:LeadingSpace, s:margin) . s:new
endif
- exe s:newwin . "wincmd w"
- exe "normal! a" . s:new . s:HtmlEndline . "\n\e"
- exe s:orgwin . "wincmd w"
+ call add(s:lines, s:new.s:HtmlEndline)
let s:n = s:n - 1
@@ -879,6 +904,5 @@
endif
- exe s:newwin . "wincmd w"
- exe "normal! a" . s:new . s:HtmlEndline . "\n\e"
+ call extend(s:lines, split(s:new.s:HtmlEndline, '\n'))
if !s:html_no_progress && s:pgb.needs_redraw
redrawstatus
@@ -893,11 +917,8 @@
endwhile
-" Finish with the last line
-exe s:newwin . "wincmd w"
-
if exists("s:html_dynamic_folds")
" finish off any open folds
while !empty(s:foldstack)
- exe "normal! a</span></span>"
+ let s:lines[-1].="</span></span>"
call remove(s:foldstack, 0)
endwhile
@@ -912,14 +933,17 @@
" Close off the font tag that encapsulates the whole <body>
if !exists("s:html_use_css")
- exe "normal! a</font>\e"
+ let s:lines[-1].="</font>"
endif
if exists("html_no_pre")
- exe "normal! a</body>\n</html>\e"
+ call extend(s:lines, ["</body>", "</html>"])
else
- exe "normal! a</pre>\n</body>\n</html>\e"
+ call extend(s:lines, ["</pre>", "</body>", "</html>"])
endif
+exe s:newwin . "wincmd w"
+call setline(1, s:lines)
+unlet s:lines
" Now, when we finally know which, we define the colors and styles
if exists("s:html_use_css")
@@ -967,5 +991,5 @@
let s:idlist = split(s:idlist_str, ',')
if !s:html_no_progress && !empty(s:idlist)
- let s:pgb = s:ProgressBar("Processing classes:", len(s:idlist),s:newwin)
+ let s:pgb = s:ProgressBar("Processing classes:", len(s:idlist),s:orgwin)
endif
while !empty(s:idlist)
@@ -1043,5 +1067,5 @@
endif
-call setwinvar(s:newwin,'&stl', s:stl)
+call setwinvar(s:orgwin,'&stl', s:stl)
let &ls=s:ls
signature.asc
Description: This is a digitally signed message part.
