2017-12-16 16:37 GMT+03:00 Bram Moolenaar <[email protected]>:
>
> Nikolay Pavlov wrote:
>
>> 2017-12-15 22:09 GMT+03:00 Bram Moolenaar <[email protected]>:
>> >
>> > Many plugins set options to a different value. To be able to restore
>> > the original value very often the old value needs to be saved.
>> >
>> > Not only is this a bit of a hassle, especially for local options, it is
>> > also incomplete, since the location where the option was originally set
>> > can't be restored.
>> >
>> > I have been thinking of adding two functions to make this work better:
>> >
>> > option_save({list}) *option_save()*
>> > Saves the options named in {list}. The returned value can
>> > be
>> > passed to option_restore(). Example: >
>> > let s:saved_options = option_save([
>> > \ 'ignorecase',
>> > \ 'iskeyword',
>> > \ ])
>> > au <buffer> BufLeave *
>> > \ call option_restore(s:saved_options)
>> > < The advantage over using `:let` is that global and local
>> > values are handled and the script ID is restored, so that
>> > `:verbose set` will show where the option was originally
>> > set,
>> > not where it was restored.
>> >
>> >
>> > option_restore({list}) *option_restore()*
>> > Restore options previously saved by option_save().
>> > When buffer-local options have been saved, this function
>> > must
>> > be called when the same buffer is the current buffer.
>> > When window-local options have been saved, this function
>> > must
>> > be called when the same window is the current window.
>> > When in the wrong buffer and/or window an error is given
>> > and
>> > the local options won't be restored.
>> >
>> > Does that sound useful?
>>
>> AFAIK it was discussed before. Functions are too easy to forget to
>> call, especially given existence of excetpions and I don’t think that
>> “must be called when the same buffer … the same window …” is a good
>> idea either. Using context managers is a better option for the first
>> problem: you can forget ending `:with` block no more then you can
>> forget ending `:try`: i.e. forgetting will spawn an error at the point
>> where VimL does end the block even if `:endtry` was forgotten. Second
>> is nothing more then an annoing unnecessary nuisance, both buffers and
>> windows do have a unique identifiers and I do not see anything which
>> may prevent code from using them to find buffer/window to restore
>> option in, it is only needed to agree on behaviour in case that
>> buffer/window no longer exists.
>>
>> Context managers are also not limited to just options, they are
>> frequently used in Python for user code as well because this syntax is
>> in many cases more pleasant then `try … finally`.
>>
>> Also something like `:with setlocal iskeyword&vim|…|endwith` is much
>> nicer syntax then anything you can come up with based on VimL
>> expressions, with your proposal that would be
>>
>> let saved_options = option_save(['iskeyword'])
>> try
>> setlocal iskeyword&vim
>> …
>> finally
>> " Restore buffer/window here if needed.
>> " Do not forget to check if it is.
>> " Do not forget :try/finally if `…` is anything which may
>> throw an exception.
>> " Do not forget :try/finally if `…` may throw an error as well
>> and user may have
>> " a reason to call your function inside a `:try` block.
>> Basically do not forget it ever,
>> " you may never know whether last statement is true.
>> call option_restore(saved_options)
>> endtry
>>
>> Putting my comments aside this is +2 lines for try/finally (endtry is
>> endwith, `let` line is `with` line), +1 line for `setlocal` (may be
>> good idea to devise different syntax, AFAIR I had something better
>> then `with setlocal iskeyword&vim`, i.e. more suitable for setting to
>> a value of an expression) and +1 line for `option_restore`, totalling
>> +4 lines.
>>
>> The only downside (from the user POV) I see is that you can’t split
>> calls up: i.e. have option_save() in one function and option_restore()
>> in another. From the developer POV I understand that context managers
>> are significantly harder to implement.
>
> You are talking about something else, a script that sets options, does
> its thing and then restores. Without the user doing anything.
>
> What I was aiming at is a plugin, like netrw, which sets global options
> and restores them when switching to another window or when editing
> another buffer in the current window. In the last case local options
> also need to be restored.
Temporary setting global option to be restored afterwards with
option_save()/option_restore() looks like a workaround for the case
“that option ought to be local, but it is not”. But it is a valid
concern, just I would suggest to solve it differently. Basically
Python’s :with context managers are syntax sugar for something like
# original code: `with manager as w: …`
v = manager.__enter__()
try:
…
finally:
manager.__exit__({exception data})
. If you won’t special-case saving/restoring options the syntax may look like
with option_save('iskeyword', ['ignorecase', v:false], …)
…
endwith
which is
let saved_options = option_save('iskeyword', ['ignorecase', v:false], …)
try
…
finally
call saved_options.exit()
endtry
where option_save returns basically the same thing, but wrapped in a dictionary
{
'options': [
{
'name': 'iskeyword',
'buffer': bufnr('%'),
'value': '@,48-57,_,192-255',
'snr': 1,
},
{
'name': 'ignorecase',
'value': v:true,
" 'snr': omitted if setter not known
},
],
'exit': function('option_restore'),
}
if some plugin actually needs to set the option temporary and reset
when gone to another buffer it will just desugarate :with and move
what it needed into another call. In my experience temporary setting
option for the duration of one function is far more common, though I
recognize the use-case.
>
> It should also work for an editing mode. E.g., editing Vim script
> example in a help text file. Then you would change 'shiftwidth' and
> some other settings, do some editing and restore when exiting the mode.
>
> We should probably also add a simple way to save and restore registers.
> getreg() and getregtype() almost do it, but you can't restore
> everything.
Restoring clipboard register is outright impossible as it is just a
pointer to another app and there are lots of ways to unintentionally
write to @". It is worth to have something like :keepregisters
(better, context manager with same meaning) which in addition to
saving and restoring internal registers will basically disable any
writes to system clipboard, regardless of what &clipboard setting is.
So one would be able to do `normal! gvy`, get @" register contents for
its purposes and still not make that spoil system clipboard.
>
> --
> hundred-and-one symptoms of being an internet addict:
> 103. When you find yourself in the "Computer" section of Barnes & Noble
> enjoying yourself.
>
> /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
> /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
> \\\ an exciting new programming language -- http://www.Zimbu.org ///
> \\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" 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
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.