I work mostly in gvim and many terminals. Originally, I preferred to open all my files in a single vim instance. To that end I used an alias to open files from my terminals in the current 'vim server'.
alias rv="gvim --remote-silent"
But having many files from multiple projects open in a single vim instance impacts my productivity, so I'm upgrading my alias to a function.
# main function
rv() {
local args options server
options=$(getopt -o hils:t: -l "help,info,list,set:,target:" -- "$@")
if [[ $? -ne 0 ]]; then
echo "Failed to parse options."
return 1
fi
# a little magic, necessary when using getopt
eval set -- "$options"
# go through the options with a case and use shift to analyze one option at a time.
while true; do
case "1ドル" in
-h|--help)
echo "Usage: 0ドル [-hil] [--help] [--info] [--list]";
echo " 0ドル {-s | --set} <name> [<file1 file2...>]";
echo " 0ドル {-t | --target} <name>] <file1 file2...>";
return 0;;
-i|--info)
gvim_show_info;
return 0;;
-l|--list)
gvim_list_servers;
return 0;;
-s|--set)
gvim_set_server_name ${2:u};
shift 2;;
-t|--target)
server="2ドル";
shift 2;;
--)
shift;
break;;
esac
done
if [[ "$#" -eq 0 ]]; then
# if no files specified...
if [[ -n "$server" ]]; then
# throw error if --target option was specified.
echo "Error! --target requires one or more filenames."
return 1;
fi
else
# if files were specified...
if [[ -n "$server" ]]; then
# if --target was specified
gvim_run_remote $server "$@"
else
gvim_run_remote $(gvim_get_default_server) "$@"
fi
fi
return 0;
}
Now this new rv
has it's own options. I can use it to:
- list available vim servers (-l --list)
- set the default vim server for the current shell (-s --set)
- show the default vim server (-i --info)
- open files in a specific vim server (-t --target)
- open files in default vim server:
rv files...
However, since I'm using a function for rv
instead of an alias, I lose the zsh completion I previously enjoyed. I've read up on creating a completion function, _rv
, that will show rv
's options, but I want to combine my completion options with the existing vim completion options. I know there may be some conflicts with rv
's -s
and vim
's -s
, but I figure I can handle that elegantly with the --
separator.
TLDR; So, how do I create a completion script that combines the _arguments
options for both _rv
and _vim
? I prefer to reuse _vim
if possible instead of copy-pasting it's arguments list into _rv
.
Here's my _rv
. Updated 2014年6月10日 16:10
#compdef rv
_rv() {
typeset -A opt_args
local alternatives
alternatives=(
'args:rv options:_rv_options'
'files:file:_vim_files'
)
_alternative $alternatives && return 0
return 1
}
_rv_options() {
local arguments
arguments=(
'(-i -l -s -t --info --list --set --target)'{-h,--help}'[Print usage info.]'
'(-h -l -s -t --help --list --set --target)'{-i,--info}'[Print default vim server. As stored in $GVIM_SERVER.]'
'(-i -h -s -t --info --help --set --target)'{-l,--list}'[Print list of existing vim servers.]'
'(-i -h -l -t --info --help --list --target)'{-s,--set}'[Set default vim server for the current shell.]:vim servers:_rv_vim_servers'
'(-i -h -l -s --info --help --list --set)'{-t,--target}'[Open files in a particular vim server.]:vim servers:_rv_vim_servers'
)
_arguments -s -C $arguments && return 0
return 1
}
_rv_vim_servers() {
local -a servers
servers=( ${(f)"$(_call_program servers vim --serverlist 2>/dev/null)"} )
_wanted servers expl server compadd -M 'm:{a-z}={A-Z}' -a servers && return
}
# invoke the completion command during autoload
_rv "$@"
Current Behavior
Currently _rv
completion will is usable, but not ideal.
- When I type
rv <TAB>
, I do not see the vim options. Only rv options and file paths are displayed._vim
is completing file paths for me, so hooray to that! - When I type
rv -s <TAB>
, I see the list of vim servers, but also the file paths are displayed. A file is not permitted at this point in the command, and should not appear in the autocomplete.
Expected Behavior
- When I type
rv <TAB>
, I expect to see: 1) rv options, 2) vim options, 3) file path list - When I type
rv -s <TAB>
, I expect to see: 1) vim server names (as provided by_rv_vim_servers
. - When I type
rv /valid/file/path/<TAB>
, I expect to only see a file path list. Since_vim
already has this capability, I would prefer to rely on it.
2 Answers 2
You can monkey-patch the _arguments
function to extend the _vim
completer:
#compdef rv
_rv_vim_servers() {
local expl
_wanted servers expl server \
compadd -- ${(f)"$( _call_program servers vim --serverlist 2>/dev/null )"}
}
_rv() {
autoload +X -Uz _arguments # Load the function body.
functions -c _arguments _rv_arguments # Make a copy.
# Replace the original function.
_arguments() {
# Call the original function with additional completions.
_rv_arguments "$@" \
'(-i -l -s -t --info --list --set --target)'{-h,--help}'[print usage info]' \
'(-h -l -s -t --help --list --set --target)'{-i,--info}'[print default vim server as stored in $GVIM_SERVER]' \
'(-i -h -s -t --info --help --set --target)'{-l,--list}'[print list of existing vim servers]' \
'(-i -h -l -t --info --help --list --target)'{-s,--set}'[set default vim server for the current shell]:vim servers:_rv_vim_servers' \
'(-i -h -l -s --info --help --list --set)'{-t,--target}'[open files in a particular vim server]:vim servers:_rv_vim_servers'
}
{
_vim "$@"
} always {
functions -c _rv_arguments _arguments # Restore the original.
unfunction _rv_arguments # Discard our copy.
}
}
_rv "$@"
I found /usr/share/zsh/functions/Completion/Unix/_git which had some tips for aliases like this and ended up defining these functions for the aliases:
_git-ls () {
# Just return the _git-ls-files autocomplete function
_git-ls-files
}
Then, do a straight compdef g=git. The autocomplete system will see that you are running, for example, g ls and use the _git-ls autocomplete function.
As found Here
-
2thanks, but not quite. your solution assumes I only want the auto-complete from
_git-ls-files
. This question has agit-ls
(to stick with your convention) with its own options, and some of those options overlap withgit-ls-files
. Instead of writing autocomplete for all options ofgit-ls
, how do I write an autocomplete that takes the autocomplete from_git-ls-files
(which covers say 90%), and combines them with the autocomplete of the remaining (say 10%) options?Justin C– Justin C2017年01月17日 00:27:28 +00:00Commented Jan 17, 2017 at 0:27
compdef
has a-n
option which says it "prevents any completions already defined for the command or context from being overwritten". So, have you triedcompdef _vim rv
followed bycompdev -n _rv rv
?_vim
file, but before doing so overwrite the_arguments
function with a custom local function? By doing so you would get the arguments from_vim
. Maybe with a separate zsh process.