Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim: how to :source a part of the buffer

Tags:

vim

As everyone knows, we can :source current buffer by :so % .

But sometimes I want to :source just a part of the buffer, not the whole buffer. Say, I just added something to my .vimrc, and want to source that part, but I don't want to re-source all the rest stuff.

I tried select text and :so (actually :'<,'>so ) , but it reported that range is not allowed. So, how could this be done?

Of course I can save needed part to the temp file and source it, but it is clearly annoying.

like image 882
Dmitry Frank Avatar asked Nov 28 '13 09:11

Dmitry Frank


4 Answers

Why not have the following mappings for sourcing a file (or a range):

" source the current file
nmap <leader>vs :source %<CR>
" source a visual range
vmap <leader>vs y:@"<CR>

Now, you can press ,vs (if your mapleader is ,), and the selected range will be sourced or otherwise, in normal mode, current file will be sourced.

like image 86
Stoic Avatar answered Oct 25 '22 14:10

Stoic


You can define the following command, which operates on the current line or passed range:

":[range]Execute    Execute text lines as ex commands.
"           Handles |line-continuation|.
command! -bar -range Execute silent <line1>,<line2>yank z | let @z = substitute(@z, '\n\s*\\', '', 'g') | @z
like image 28
Ingo Karkat Avatar answered Oct 25 '22 14:10

Ingo Karkat


Thanks to Ingo Karkat, I have taken his main idea and improved it. What I wanted to improve:

  • We have to use additional user-specified command :Execute instead of standard :so (ok, we can name user-specified command :So, anyway it's annoying to use new capitalized version of the command)
  • There is little side effect: register @z is corrupted after executing the command.

With my script below, we can use :so {file} command as before, and we are also able to use it with range: :'<,'>so (which actually expands to :'<,'>Source)


Here:

" This script provides :Source command, a drop-in replacement for
" built-in :source command, but this one also can take range and execute just
" a part of the buffer.
"


" Sources given range of the buffer
function! <SID>SourcePart(line1, line2)
   let tmp = @z
   silent exec a:line1.",".a:line2."yank z"
   let @z = substitute(@z, '\n\s*\\', '', 'g')
   @z
   let @z = tmp
endfunction



" if some argument is given, this command calls built-in command :source with
" given arguments; otherwise calls function <SID>SourcePart() which sources
" visually selected lines of the buffer.
command! -nargs=? -bar -range Source if empty("<args>") | call <SID>SourcePart(<line1>, <line2>) | else | exec "so <args>" | endif



" in order to achieve _real_ drop-in replacement, I like to abbreviate
" existing :so[urce] command to the new one.
"
" So, we can call :so %  just as before, and we are also call  '<,'>so

cnoreabbr so     Source
cnoreabbr sou    Source
cnoreabbr sour   Source
cnoreabbr sourc  Source
cnoreabbr source Source
like image 4
Dmitry Frank Avatar answered Oct 25 '22 14:10

Dmitry Frank


The following works if you only selected one line:

yq:p<enter>

This will also work:

y:<control-r>"<enter>
like image 2
user2987828 Avatar answered Oct 25 '22 13:10

user2987828