1

Some time ago, I've made this question where I asked how to execute a file on the terminal with NeoVim... The solution I found was the following :terminal bash % . Knowing that, I made the following configuration on my init.vim file:

function! ExecuteOnTerminal(type) range
    if (&ft=='javascript')
        if a:type == "V"
            :vert botright '<,'> terminal node %
        else
            :vert botright terminal node %
        endif
    elseif (&ft=='sh')
        if a:type == "V"
            :vert botright '<,'> terminal bash %
        else
            :vert botright terminal bash %
        endif
    elseif (&ft=='python')
        if a:type == "V"
            :vert botright '<,'> terminal python3 %
        else
            :vert botright terminal python3 %
        endif
    endif
endfunction

vnoremap <silent> <F6> :call ExecuteOnTerminal("V")<CR>
nnoremap <silent> <F6> :call ExecuteOnTerminal("I")<CR>

The above configuration works perfectly fine, it allows me to execute a file with bash, node.js and python when I press F6... And if I select some lines and press F6 it`ll execute only the selected lines.

The problem is that in my context, I need to execute files that are not stored on the disk. Let's say I have the following file.sh:

echo "Hello World"

I need to open this file with cat file.sh | nvim - (not nvim file.sh)... When I do that, if I try using the command :vert botright terminal bash % I receive the error:

E499: Empty file name for '%' or '#', only works with ":p:h"

I tried using set ft=sh but it didn't work as well. Is there any workaround for this problem? In a way that I don't need to save this file on the disk to execute it with nvim?


Observation: With vim, I have a similar configuration in my vimrc file, the only difference is that I use the commands :vert botright '<,'> %terminal bash and vert botright %terminal bash instead. With vim it works perfectly fine to execute files opened from pipe. Like in cat file.sh | vi -. This issue only exists on NeoVim.

2
  • 2
    Depending on what you’re running, you can use term_start and a command with the text to execute or an in_buf if the command accepts stdin
    – D. Ben Knoble
    Mar 22, 2022 at 13:48
  • 1
    You might want to check out the vim-slime plug-in.
    – filbranden
    Mar 22, 2022 at 14:28

1 Answer 1

0

I managed to solve this problem by creating the following vimscript:

function! ExecuteOnTerminal(type) range
    if (&ft=='javascript')
        if a:type == "V"
            '<,'>w! /tmp/file.js
        else
            :w! /tmp/file.js
        endif
        :vert sp | terminal node /tmp/file.js  
        call system('xdotool key "Control_L+w" ; xdotool type r')
    elseif (&ft=='bash' || &ft=='sh')
        if a:type == "V"
            '<,'>w! /tmp/file.bash
        else
            :w! /tmp/file.bash
        endif
        :vert sp | terminal bash /tmp/file.bash
        call system('xdotool key "Control_L+w" ; xdotool type r')
    elseif (&ft=='python')
        if a:type == "V"
            '<,'>w! /tmp/file.py
        else
            :w! /tmp/file.py
        endif
        :vert sp | terminal python3 /tmp/file.py
        call system('xdotool key "Control_L+w" ; xdotool type r')
    endif
endfunction

vnoremap <silent> <F6> :call ExecuteOnTerminal("V")<CR>
nnoremap <silent> <F6> :call ExecuteOnTerminal("I")<CR>

In this solution, a temporary file with the content of the file was created.

I wanted to make NeoVim behavior exactly the same as Vim, so I've also used xdotool from the system to press Ctrl+w and r to switch sides of the terminal window. The logic here is writing a temporary file with its extension in /tmp and then executing it with terminal language /tmp/file.extension. The result on NeoVim after pressing F6 is:

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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