Sorry, I did not see the neovim tag before I wrote and posted. This is for Vim and I have to figure out what to do with it. Delete / move / …. My bad. No idea if this would work in neovim.
One could use the :h clientserver.
Tried this first but had some issues where it did not switch window before opening resulting it opening in the terminal window. Tested again after comment by Mr. Krämer and not able to reproduce, so likely a very rare glitch.
Example:
vim --servername "$VIM_SERVERNAME" --remote-send '<C-w><C-w>' --remote a*
Simply add it as an alias or the like:
alias svim="vim --servername \"\$VIM_SERVERNAME\" \
--remote-send '<C-w><C-w>' --remote"
svim foo b*
It requires the Vim session to be run as server. If not one can become by
:call remote_startserver('foo')
Another option that is easier to get smooth is the :h terminal-api. (Considering edit above, perhaps not :)
It gives the possibility to send commands back to Vim.
Besides the already supported drop one can also call functions. The function name has to start with Tapi_ and the terminal started with ++api=Tapi_function_name.
On the shell / terminal side one can then print a special sequence to send data to the Vim instance that opened it.
<Esc>]51; + data + <07>
The data is JSON and for terminal API calls using call it has the format:
["call", "Tapi_function_name", DATA] where DATA can be anything from a number, string, to an JSON array or object.
Modified another script I used to test for this.
Basics
Send a reply in the format:
{
"split": 0,
"stay" : 1,
"files": ["file_A", "file_B", "file_C"]
}
split: always split (0 = false, 1 = true)
stay : stay in terminal (0 = false, 1 = true)
On the Vim side:
fun! Tapi_File_open(term_bufnr, args)
" Escape the file-names and create a string "
" we can use with for example :next"
let files = join(map(a:args['files'], 'fnameescape(v:val)'), ' ')
" Window ID's "
let win_term = win_getid(winnr())
let win_use = win_getid(winnr('#'))
if win_use == 0 || win_term == win_use || a:args['split']
split
else
call win_gotoid(win_use)
endif
exe ":next " . files
if a:args['stay']
call win_gotoid(win_term)
endif
endfun
" Custom command to open a terminal with the API enabled."
command! FileTerm :terminal ++api=Tapi_File_open
On the Terminal side
One could use Vim in Ex mode to generate the data. Something like:
let TAPI_FUNCTION = 'Tapi_Files_open'
let f = map(argv(), '"\"".fnameescape(fnamemodify(v:val, ":p"))."\""')
let reply = [
\ "call",
\ TAPI_FUNCTION,
\ #{
\ files: f,
\ split: 0,
\ goto: 0
\}
\ ]
exe "set t_ts=\<Esc>]51; t_fs=\x07"
let &titlestring = json_encode(reply)
redraw
qa
Instead of using titlestring it would likely be better to use a temporary file that one sourced after. That way one can use -s as well.
And call it by some alias or small script that in turn sources it:
vim -E -c "source argv2json_cmd.vim" -- file1 file2 file3 ...
Using bash
This is a crudebash script. The help section should be explanatory.
./svim --vvv -g *.txt
NB! NB!
=============
StackExchange destroys tabs in code. In bash script below there are required TAB's in the print_help() section. To copy the script click edit on this answer and copy the text from the raw text.
#! /bin/bash -
stay=1
split=0
eopt=0
verbose=0
v_files=()
print_help() {
cat<<-EOH >&2
USAGE: $0 [OPTIONS] <FILES>
Open file(s) from terminal in Vim where
terminal has been started with:
++api=Tapi_File_open
OPTIONS
-h --help This help
-n --stay Stay in terminal window
-g --goto Goto opened document(s)
-s --split Split
--vv Print information in terminal
--vvv Print information + JSON arg
-- End of options
EOH
}
for arg in "$@"; do
# Options section
if [ $eopt -eq 0 ] && [ "${arg:0:1}" = "-" ]; then
case "$arg" in
-h|--help) print_help; exit ;;
-n|--stay) stay=1 ;;
-g|--goto) stay=0 ;;
-s|--split) split=1 ;;
--vv) verbose=1 ;;
--vvv) verbose=2 ;;
--) eopt=1 ;;
esac
else
# Escape backslash then double quote
v_files+=( "$(printf %s "$(realpath -- "$arg")" |
sed 's/\/\\/g;s/"/\"/g')" )
fi
done
Join file-names into string
files=$(printf '"%s",' "${v_files[@]}")
Verbose
if [ $verbose -gt 0 ]; then
printf '\033[1;34mOpen files in vim (stay: %d, split: %d)\033[0m\n'
"$stay" "$split" >&2
fi
Extra verbose: print JSON data
if [ $verbose -gt 1 ]; then
printf '\n\033[0;36m{"stay": %d, "split": %d, "files": [%s]}\033[0m\n\n'
"$stay" "$split" "$files" >&2
fi
Call Vim by printing special sequence
printf '\033]51;['
'"call", "Tapi_File_open",'
'{"stay": %d, "split": %d, "files": [%s]}'
']\007'
"$stay" "$split" "$files"
neovim. Not sure if this would work there. I might have to delete it / move it somewhere more suited. – Moba Jun 29 '22 at 12:05+clientserverfeature is always enabled. There in a terminal inside Vim the environment variable VIM_SERVERNAME is defined, so withvim --servername %VIM_SERVERNAME% --remote myfile.txtI was able to open myfile.txt in the original Vim instance (both console and GUI). – Jürgen Krämer Jun 30 '22 at 06:12