When I input this command in zsh:
which conda
It returns
conda () {
\local cmd="${1-__missing__}"
case "$cmd" in
(activate | deactivate) __conda_activate "$#" ;;
(install | update | upgrade | remove | uninstall) __conda_exe "$#" || \return
__conda_reactivate ;;
(*) __conda_exe "$#" ;;
esac
}
But I hope it returns the absolute path as it behaves in bash.
When I input:
type conda
It returns
conda is a shell function from /Users/qxchen/.zshrc
Actually, there is no function in .zshrc named by conda
I delete the script in .zshrc which is made by "conda init zsh", and then I add the absolute path of miniconda/bin to PATH.
But in bash, "which conda" returns the absolute path of "conda".
/Users/ABC/miniforge3/condabin/conda
And the result of "type conda":
conda is a function
conda ()
{
\local cmd="${1-__missing__}";
case "$cmd" in
activate | deactivate)
__conda_activate "$#"
;;
install | update | upgrade | remove | uninstall)
__conda_exe "$#" || \return;
__conda_reactivate
;;
*)
__conda_exe "$#"
;;
esac
}
I want zsh to behave like bash at this point, aka "which conda" should return the path of conda, and "type conda" should return its real type.
What should I do?
Thanks for your help in advance.
Related
One helpful feature of R is being able to use "?<function>" to quickly look up functions, without having to type out "help("<function>")".
Is it possible to implement a similar behavior in shell (e.g. bash or zsh), using a non-reserved character?
That is, somecommand (no space) triggering "man somecommand"
Perhaps, for bash
command_not_found_handle() {
if [[ $1 != Z* ]]; then
echo "$1: command not found" >&2
return 127
fi
local cmd=${1#Z}
case "$(type -t "$cmd")" in
builtin|keyword) help "$cmd" ;;
file) man "$cmd" ;;
alias) alias "$cmd" ;;
function) type "$cmd" ;;
*) echo "$cmd: command not found" >&2; return 127 ;;
esac
}
I'm following this blog to setup a zsh function to switch aws cli profiles
: https://mads-hartmann.com/2017/04/27/multiple-aws-profiles.html
This is the zsh function in the blog:
function aws-switch() {
case ${1} in
"")
clear)
export AWS_PROFILE=""
;;
*)
export AWS_PROFILE="${1}"
;;
esac
}
#compdef aws-switch
#description Switch the AWS profile
_aws-switch() {
local -a aws_profiles
aws_profiles=$( \
grep '\[profile' ~/.aws/config \
| awk '{sub(/]/, "", $2); print $2}' \
| while read -r profile; do echo -n "$profile "; done \
)
_arguments \
':Aws profile:($(echo ${aws_profiles}) clear)'
}
_aws-switch "$#"
I added these lines to my ~/.zshrc, when I run source ~/.zshrc
It gives /.zshrc:4: parse error near `)'
I read the zsh function doc but still not very good at understanding the syntax and how could I fix this.
Have a look at the zsh man page (man zshmisc):
case word in [ [(] pattern [ | pattern ] ... ) list (;;|;&|;|) ] ... esac
As you see, you have to separate multiple pattern by |:
case $1 in
|clear)
....
I'm trying to add a completion to a custom vs function which basically open the first filename matching the argument.
OPTIONAL (If you want more information about this function you can find my medium post here => https://medium.com/#victor.boissiere/how-to-quickly-open-files-with-your-editor-1a51b3fe21bf)
In my current folder I have the following:
./example.sh
./custom/directory.sh
./custom/example.sh
Behavior
vs direct<TAB> => completes to custom/directory.sh SUCCESS
vs example<TAB> => vs
Why does it removes the argument and does not let me choose between example.sh and custom/example.sh ?
Code
_vs() {
local curcontext="$curcontext" state line expl
_arguments -C \
'*:: :->open_files'
case "$state" in
open_files)
local file=${words[CURRENT]}
compadd -U - `find . -type f -ipath "*$file*" | sed "s|^\./||"`
;;
esac
return 0
}
compdef _vs vs
I just found the solution thanks to this post => https://superuser.com/questions/1264778/changing-to-a-directory-found-somewhere-in-the-tree-hierarchy/1278919#1278919
I just needed to add compstate[insert]=menu # no expand
Solution
_vs() {
local curcontext="$curcontext" state line expl
_arguments -C \
'*:: :->open_files'
case "$state" in
open_files)
local file=${words[CURRENT]}
compadd -U - `find . -type f -ipath "*$file*" | sed "s|^\./||"`
compstate[insert]=menu # add this
;;
esac
return 0
}
compdef _vs vs
I want to create a zsh completion for a tool with a virtual file tree.
e.g. my file tree looks like the following:
/
|- foo/
| |- bar
| |- baz/
| |- qux
|- foobar
My tool mycmd has a subcommand for listing the current directory:
$ mycmd ls
foo/
foobar
$ mycmd ls foo/
bar
baz/
My actual zsh completion looks like this:
_mycmd_ls() {
if [ ! -z "$words[-1]" ]; then
dir=$(dirname /$words[-1])
lastpart=$(basename $words[-1])
items=$(mycmd ls $dir | grep "^$lastpart")
else
items=$(mycmd ls)
fi
_values -s ' ' 'items' ${(uozf)items}
}
_mycmd() {
local -a commands
commands=(
'ls:list items in directory'
)
_arguments -C -s -S -n \
'(- 1 *)'{-v,--version}"[Show program\'s version number and exit]: :->full" \
'(- 1 *)'{-h,--help}'[Show help message and exit]: :->full' \
'1:cmd:->cmds' \
'*:: :->args' \
case "$state" in
(cmds)
_describe -t commands 'commands' commands
;;
(args)
_mycmd_ls
;;
(*)
;;
esac
}
_mycmd
IMHO is _values the wrong utility function. The actual behaviour is:
$ mycmd ls<TAB>
foo/ foobar
$ mycmd ls foo/<TAB> ## <- it inserts automatically a space before <TAB> and so $words[-1] = ""
foo/ foobar
I can't use the utility function _files or _path_files because the file tree is only virtual.
I would suggest to make use of compadd rather _values to get in control of the suffix character appended. Then looking at the available choices, set an empty suffix character in case a virtual directory is part of the result:
_mycmd_ls() {
if [ ! -z "$words[-1]" ]; then
dir=$(dirname /$words[-1])
lastpart=$(basename $words[-1])
items=$(mycmd ls $dir | grep "^$lastpart")
else
items=$(mycmd ls)
fi
local suffix=' ';
# do not append space to word completed if it is a directory (ends with /)
for val in $items; do
if [ "${val: -1:1}" = '/' ]; then
suffix=''
break
fi
done
compadd -S "$suffix" -a items
}
I'm trying to create a Capistrano mutilstage completion for ZSH:
$ cap |
production staging
$ cap production |
deploy -- Deploy a new release
deploy:bundle -- Bundle
...
Completion code:
#compdef cap
#autoload
# /Users/pablo/.oh-my-zsh/custom/plugins/capistrano_custom/_capistrano_custom
local curcontext="$curcontext" state line ret=1
local -a _configs
_arguments -C \
'1: :->cmds' \
'2:: :->args' && ret=0
_cap_tasks() {
if [[ ! -f .cap_tasks~ ]]; then
echo "\nGenerating .cap_tasks~..." > /dev/stderr
cap -v --tasks | grep '#' | cut -d " " -f 2 > .cap_tasks~
fi
cat .cap_tasks~
}
_cap_stages() {
find config/deploy -name \*.rb | cut -d/ -f3 | sed s:.rb::g
}
case $state in
cmds)
if [[ -d config/deploy ]]; then
compadd `_cap_stages`
else
compadd `_cap_tasks`
fi
ret=0
;;
args)
compadd `_cap_tasks`
ret=0
;;
esac
return ret
The problem:
#compdef cap doesn't work. If I type cap and [TAB] it doesn't execute the completion, but with other words (i.e. shipit) works fine.
Any ideas?
Solution:
cap is really a reserved word and it seems that we can't use it with #compdef cap.
I'm wondering how cap and capistrano completions worked before (maybe an old version of ZSH).
Solution dotfiles code: capistrano_custom
Solution oh-my-zsh/PR: #2471
Both solutions use shipit instead of cap.
$ shipit |
production staging
$ shipit production |
deploy -- Deploy a new release
deploy:bundle -- Bundle
...
Yes, cap is a ZSH builtin. Quoting from zsh docs:
The zsh/cap module is used for manipulating POSIX.1e (POSIX.6)
capability sets. [...]. The builtins in this module are:
cap [ capabilities ] Change the shell’s process capability sets to the
specified capabilities, otherwise display the shell’s current
capabilities.