3

I am relatively new to vim and have started using the vim-slime plugin. One thing I use it for is to run python scripts, for example

:SlimeSend1 python ~/myPythonFile.py

I now would like to automate the command above. More specifically, I would like to map the command above to a keystroke, but for whatever python file I happen to be working with. Using F5 as my example keystroke, I am looking for something like

:map <F5> SlimeSend1 python expand('%:p')<CR>

The command above doesn't work because it sends the literal string "python expand('%:p')". As a note, I have gone through vim-slime's documentation, but still can't figure this out.

1

As a general rule of thumb, you can always get around this kind of problem by using :execute and building the command you want to run as a string:

:nnoremap <F5> :execute 'SlimeSend1 python' expand('%:p')<CR>

See :help :execute for more details.

  • Note the first suggestion in the answer from @Mass would also work. The command would be :nnoremap <F5> :SlimeSend1 python <c-r>%<CR> – wxyz Mar 6 '18 at 22:44
0

As you found out, :SlimeSend1 sends its arguments literally, as a single string. You could type CTRL+R to insert the % register, which is the current filename:

:SlimeSend1 python <c-r>%

You could use SlimeSend0 instead which accepts an expression.

:SlimeSend0 'python '.expand('%:p')

This command is a bit unwieldy. You can use a wrapper command;

let s:flags = '<\=\%(:[p8~.htre]\|:g\=s\(.\).\{-\}\1.\{-\}\1\)*'
let s:expandable = '\\*\%(<\w\+>\|%\|#\d*\)' . s:flags
function! s:expand(string) abort
  let slashes = len(matchstr(a:string, '^\%(\\\\\)*'))
  sandbox let v = repeat('\', slashes/2) . expand(a:string[slashes : -1])
  return v
endfunction
function! TExpand(string) abort
  return substitute(a:string, s:expandable,
          \ '\=s:expand(submatch(0))', 'g')
endfunction

command! -complete=shellcmd -bang -nargs=+ Send
      \ SlimeSend0 TExpand(<q-args>)

I stole the TExpand function from Dispatch. If you have Dispatch installed you can simply use:

command! -complete=shellcmd -bang -nargs=+ Send
      \ SlimeSend0 dispatch#expand(<q-args>)

Then :Send python % will work as you expect.

  • Did you mean to write s:expand instead of dispatch#expand? – Karl Yngve Lervåg Mar 6 '18 at 7:10
  • @Mass My original question may not have been clear enough, so I updated it. Your first suggestion would work. Your next suggestion (:SlimeSend0) will send but not evaluate the command (unlike :SlimeSend1 which will both send and evaluate the command). Your last suggestion also seems to send but not evaluate the command. – wxyz Mar 6 '18 at 7:32
  • @KarlYngveLervåg no actually, TExpand is the same as dispatch#expand (I just copy and pasted it). s:expand() expands a single "%" while dispatch#expand expands an entire string e.g. "python %", emulating the expansion of the :! command. – Mass Mar 6 '18 at 16:01
  • @user447986 Ah, yes my second suggestion will not work within a mapping (see @Rich's answer), only interactively. But my last suggestion would work I think; nnoremap <f5> :Send python %<cr> . – Mass Mar 6 '18 at 16:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.