Reply to message «optwin.vim - setlocal on global options ? ...», 
sent 10:13:02 30 January 2011, Sunday
by Marc Weber:

>   fun! <SID>BinOptionL(name)
>     exe "norm! \<C-W>p"
>     exe "let val = &" . a:name
>     exe "norm! \<C-W>p"
>     call append("$", substitute(substitute(" \tset " . val . a:name . "\t"
> . \!val . a:name, "0", "no", ""), "1", "", ""))
>   endfun
> 
> Why is it important to keep it fast - is :options used that often?
> why is exe used if there is wincmd p (or even getbufvar ?)
> ... some more questions appear but its not worth writing them down.
By the way, is substitute really faster then ((val)?(""):("no"))? I guess it is 
not.

Other possible improvements:
--- /usr/share/vim/vim73/optwin.vim     2011-01-24 05:44:22.000000000 +0300
+++ optwin.vim  2011-01-30 12:43:32.000000000 +0300
@@ -26,15 +26,11 @@
 fun! <SID>CR()
 
   " If on a continued comment line, go back to the first comment line
-  let lnum = line(".")
+  let lnum = search("^[^\t]", 'bWcn')
   let line = getline(lnum)
-  while line[0] == "\t"
-    let lnum = lnum - 1
-    let line = getline(lnum)
-  endwhile
 
   " <CR> on a "set" line executes the option line
-  if match(line, "^ \tset ") >= 0
+  if line[:5] ==# " \tset "
 
     " For a local option: go to the previous window
     " If this is a help window, go to the window below it
@@ -63,7 +59,7 @@
   let line = getline(lnum)
 
   " <Space> on a "set" line refreshes the option line
-  if match(line, "^ \tset ") >= 0
+  if line[:5] ==# " \tset "
 
     " For a local option: go to the previous window
     " If this is a help window, go to the window below it
@@ -79,21 +75,21 @@
 " find the window in which the option applies
 " returns 0 for global option, 1 for local option, -1 for error
 fun! <SID>Find(lnum)
-    if getline(a:lnum - 1) =~ "(local to"
+    if stridx(getline(a:lnum-1), "(local to")!=-1
       let local = 1
       let thiswin = winnr()
-      exe "norm! \<C-W>p"
-      if exists("b:current_syntax") && b:current_syntax == "help"
-       exe "norm! \<C-W>j"
+      wincmd p
+      if getbufvar(winbufnr(0), '&buftype') ==# "help"
+       wincmd j
        if winnr() == thiswin
-         exe "norm! \<C-W>j"
+         wincmd j
        endif
       endif
     else
       let local = 0
     endif
-    if local && (winnr() == thiswin || (exists("b:current_syntax")
-       \ && b:current_syntax == "help"))
+    if local && (winnr() == thiswin
+          \ || getbufvar(winbufnr(0), '&buftype') ==# "help")
       echo "Don't know in which window"
       let local = -1
     endif
@@ -138,16 +134,13 @@
 " If the current window is a help window, try finding a non-help window.
 " Relies on syntax highlighting to be switched on.
 let s:thiswin = winnr()
-while exists("b:current_syntax") && b:current_syntax == "help"
+while s:thiswin != winnr() && getbufvar(winbufnr(0), '&buftype') ==# 'help'
   exe "norm! \<C-W>w"
-  if s:thiswin == winnr()
-    break
-  endif
 endwhile
 
 " Open the window
 new option-window
-setlocal ts=15 tw=0 noro
+setlocal ts=15 tw=0 noro buftype=nofile
 
 " Insert help and a "set" command for each option.
 call append(0, '" Each "set" line shows the current value of an option (on the 
left).')
@@ -162,31 +155,30 @@
 
 " Init a local binary option
 fun! <SID>BinOptionL(name)
-  exe "norm! \<C-W>p"
-  exe "let val = &" . a:name
-  exe "norm! \<C-W>p"
-  call append("$", substitute(substitute(" \tset " . val . a:name . "\t" .
-       \!val . a:name, "0", "no", ""), "1", "", ""))
+  wincmd p
+  let val = eval("&".a:name)
+  wincmd p
+  call append('$', " \tset " . (val?"":"no") . a:name . "\t" .
+              \ (val?"no":"") . a:name)
 endfun
 
 " Init a global binary option
 fun! <SID>BinOptionG(name, val)
-  call append("$", substitute(substitute(" \tset " . a:val . a:name . "\t" .
-       \!a:val . a:name, "0", "no", ""), "1", "", ""))
+  call append('$', " \tset " . (a:val?"":"no") . a:name . "\t" .
+              \ (a:val?"no":"") . a:name)
 endfun
 
 " Init a local string option
 fun! <SID>OptionL(name)
-  exe "norm! \<C-W>p"
-  exe "let val = substitute(&" . a:name . ', "[ \\t\\\\\"|]", "\\\\\\0", "g")'
-  exe "norm! \<C-W>p"
+  wincmd p
+  let val = escape(eval("&".a:name), " \t\\\"|")
+  wincmd p
   call append("$", " \tset " . a:name . "=" . val)
 endfun
 
 " Init a global string option
 fun! <SID>OptionG(name, val)
-  call append("$", " \tset " . a:name . "=" . substitute(a:val, '[ \t\\"|]',
-       \ '\\\0', "g"))
+  call append("$", " \tset " . a:name . "=" . escape(a:val, " \t\\\"|"))
 endfun
 
 let s:idx = 1

Original message:
> First of all: Why is setlocal aw allowed because its a global option
> only.
> 
> I'd like to tidy up optwin.vim and change its output maybe adding core
> funtions which can be used to query wether a buf local var has been set
> at all.
> 
> I'd like the output to look like this:
> 
>   === START ==
>   (g); global option
>   (b): options belonging to a buffer
>   (w): options belonging to a window
> 
>   You don't assign values to binary options. You set or unset them like
> this: set option
>   set nooption
> 
> 
>   # shiftwidth (b)    number of spaces used for each step of (auto)indent
> (local to buffer) setlocal sw=2
> 
>   # autowrite (g)     automatically write a file when leaving a modified 
buffer
>   set aw
> 
>   # ⇧shelltemp (g,b)    use a temp file for shell commands instead of using
> a pipe setlocal stmp=value1
>   set stmp="value2"     (*)
>   == END ==
> 
> 
> 
> So what's different?
> 
>   - it shows clearly whether an option is a buffer local, a window local
>     or a global option. The current behaviour is inconsistent. Some
>     options have a second line saying (local to buffer), but not all
>     (example "sts")
> 
>   - it shows both: global and buffer local vars if they are set.
>     (How to query this?)
> 
> 
> Do you know about any reason why not to change the format?
> 
> 
> It looks like several lines in the file could be improved:
> 
>   " If there already is an option window, jump to that one.
>   if bufwinnr("option-window") > 0
>     let s:thiswin = winnr()
>     while 1
>       if @% == "option-window"
>         finish
>       endif
>       exe "norm! \<C-W>w"
>       if s:thiswin == winnr()
>         break
>       endif
>     endwhile
>   endif
> 
> What the heck does it do? Let's rewrite it:
> 
>   " If there already is an option window, jump to that one.
>   if bufwinnr("option-window") > 0
>     " if buffer is shown finish even if the buffer whose options should
>     " be shouwn has different local vars. focus it
>     exec bufwinnr("option-window").' wincmd w'
>     finish
>   endif
> 
> Now that you know what this code does you'll notice some issues:
> 
> - if you hide buffer (quit with set hidden) and run options again
>   you'll have the options twice
> 
> - if you don't hide and jump to a different buffer which has buffer
>   local values set differently those local buffers won't update !
> 
> This makes me think the :options command is close to useless and should
> be fixed.
> 
> While the optwin.vim code pays much attention about whether an option is
> a local or a global one the output does not reflect this.
> 
> global autowrite output vs local shiftwidth output:
> 
>       autowrite automatically write a file when leaving a modified buffer
>               set aw noaw
>       shiftwidth number of spaces used for each step of (auto)indent
>        (local to buffer)
>         set sw=10
> 
> 
> Let's have look at the code BinOptionL:
> 
> 
>   " These functions are called often below.  Keep them fast!
> 
>   " Init a local binary option
>   fun! <SID>BinOptionL(name)
>     exe "norm! \<C-W>p"
>     exe "let val = &" . a:name
>     exe "norm! \<C-W>p"
>     call append("$", substitute(substitute(" \tset " . val . a:name . "\t"
> . \!val . a:name, "0", "no", ""), "1", "", ""))
>   endfun
> 
> Why is it important to keep it fast - is :options used that often?
> why is exe used if there is wincmd p (or even getbufvar ?)
> ... some more questions appear but its not worth writing them down.
> 
> 
> Yours
> Marc Weber

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

Raspunde prin e-mail lui