8

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.

Dmitry Frank
  • 10,417
  • 10
  • 64
  • 114

5 Answers5

13

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.

Stoic
  • 10,536
  • 6
  • 41
  • 60
  • 1
    It's why I love macro(register) so much! Just a single ":@" does all the trick! ♪ No bothering a mapping or a function. Rare users know macro in command mode is as useful as in normal mode. – Charles Jie Dec 22 '18 at 08:53
8

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
Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
4

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
Dmitry Frank
  • 10,417
  • 10
  • 64
  • 114
  • 2
    You need to be careful when using `cnoreabbr`'s. They expand in unexpected places e.g. searching. See this post for more http://stackoverflow.com/questions/7513380/vim-change-x-function-to-delete-buffer-instead-of-save-quit – Peter Rincker Nov 28 '13 at 13:20
  • @PeterRincker, thank you for your note, will examine. – Dmitry Frank Nov 28 '13 at 13:21
2

The following works if you only selected one line:

yq:p<enter>

This will also work:

y:<control-r>"<enter>
user2987828
  • 1,116
  • 1
  • 10
  • 33
0

Starting with Vim 9, you can source a range of lines in a buffer using the :<range>source command without specifying any arguments. If you don't specify any range, this command sources the current buffer. Refer to :help source-range for more details.