Skip to content

Instantly share code, notes, and snippets.

@AndrewRadev
Created April 16, 2012 11:44
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndrewRadev/2398003 to your computer and use it in GitHub Desktop.
Save AndrewRadev/2398003 to your computer and use it in GitHub Desktop.
"with" command for vimscript
let s:undo_stack = []
command! -nargs=1 With call s:With(<f-args>)
function! s:With(expression)
if a:expression[0] == '*'
return s:WithFunction(a:expression)
else
return s:WithVariable(a:expression)
endif
endfunction
function! s:WithFunction(expression)
let function = a:expression[1:]
let old_value = call(function, [-1, "get"])
call add(s:undo_stack, ['call '.function.'("'.string(old_value).'", "set")'])
endfunction
function! s:WithVariable(expression)
let [variable, body] = split(a:expression, '\s*=\s*')
if !exists(variable)
" then we just need to unset it after we're done
let undo_operations = ['unlet '.variable]
else
" then we need to store its old value
let variable_index = 1
let old_variable = variable.'_'.variable_index
while exists(old_variable)
let variable_index += 1
let old_variable = variable.'_'.variable_index
endwhile
exe 'let '.old_variable.' = '.variable
let undo_operations = [
\ 'let '.variable.' = '.old_variable,
\ 'unlet '.old_variable
\ ]
endif
call add(s:undo_stack, undo_operations)
exe 'let '.variable.' = '.body
endfunction
command! Endwith call s:Endwith()
function! s:Endwith()
for operation in remove(s:undo_stack, -1)
exe operation
endfor
endfunction
" ==========================================================
" Examples
" ==========================================================
" Save the cursor
function! s:SaveCursor(value, action)
if a:action == 'get'
return getpos('.')
elseif a:action == 'set'
call setpos('.', eval(a:value))
endif
endfunction
With *s:SaveCursor
normal! gg
sleep 1
Endwith
" Save the value of a variable
let g:foo = 2
echo g:foo
With g:foo = 1
echo g:foo
Endwith
echo g:foo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment