Ответ на сообщение «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
 

Attachment: signature.asc
Description: This is a digitally signed message part.

Raspunde prin e-mail lui