compadd failure during optparse-applicative zsh completion script - zsh

So I'm not exactly sure whether this is something wrong with optparse-applicative's script or if I'm using it wrong.
In the optparse-applicative readme, it states that programs are made available with automatic completion scripts, with options for zsh. For my program setup:
$> setup --zsh-completion-script `which setup`
Outputs:
#compdef setup
local request
local completions
local word
local index=$((CURRENT - 1))
request=(--bash-completion-enriched --bash-completion-index $index)
for arg in ${words[#]}; do
request=(${request[#]} --bash-completion-word $arg)
done
IFS=$'\n' completions=($( /Users/anrothan/.local/bin/setup "${request[#]}" ))
for word in $completions; do
local -a parts
# Split the line at a tab if there is one.
IFS=$'\t' parts=($( echo $word ))
if [[ -n $parts[2] ]]; then
if [[ $word[1] == "-" ]]; then
local desc=("$parts[1] ($parts[2])")
compadd -d desc -- $parts[1]
else
local desc=($(print -f "%-019s -- %s" $parts[1] $parts[2]))
compadd -l -d desc -- $parts[1]
fi
else
compadd -f -- $word
fi
done
I'm running the following in my zshrc (I use oh-my-zsh, but I removed it and this still happens in a bare-minimum config with only a small PATH addition to get the setup script).
autoload -U +X compinit && compinit
autoload -U +X bashcompinit && bashcompinit
source <(setup --zsh-completion-script `which setup`)
I get the following error several times:
/dev/fd/11:compadd:24: can only be called from completion function
I've run compinit, and the completion script seems to look right to me, and I've looked around but I can't seem to figure out why this error is happening...

You don't need to source zsh-completion scripts, they just need to be added to your fpath parameter.
So just place the output of setup --zsh-completion-script $(which setup) in a file call _setup in $HOME/.config/zsh/completions.
fpath=($HOME/.config/zsh/completions $fpath)
autoload -U compinit && compinit

Related

How do I reset and put the zshrc file back to default?

/Users/ello/.zshrc:source:3: no such file or directory:
/Users/ello/Projects/config/env.sh
Ello-MacBook-Pro% /Users/ello/.zshrc:source
zsh: no such file or directory: /Users/ello/.zshrc:source
Ello-MacBook-Pro% /Users/ello/.zshrc
zsh: permission denied: /Users/ello/.zshrc
Ello-MacBook-Pro%
This has been happening, after I foolishly edited the .zshrc file. All that remains in the file now, after attempting to reset the shell, is this:
# Created by newuser for 5.3.1
# Add env.sh
How do I undo everything, reinstall zsh, or remake the .zshrc file?
This is on macOS Sierra.
Edit: I reinstalled oh-my-zsh, leading to this message:
ain() {
# Use colors, but only if connected to a terminal, and that terminal
# supports them.
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
BOLD=""
NORMAL=""
fi
# Only enable exit-on-error after the non-critical colorization
stuff,
# which may fail on systems lacking tput or terminfo
set -e
CHECK_ZSH_INSTALLED=$(grep /zsh$ /etc/shells | wc -l)
if [ ! $CHECK_ZSH_INSTALLED -ge 1 ]; then
printf "${YELLOW}Zsh is not installed!${NORMAL} Please install zsh
first!\n"
exit
fi
unset CHECK_ZSH_INSTALLED
if [ ! -n "$ZSH" ]; then
ZSH=~/.oh-my-zsh
fi
if [ -d "$ZSH" ]; then
printf "${YELLOW}You already have Oh My Zsh installed.${NORMAL}\n"
printf "You'll need to remove $ZSH if you want to re-install.\n"
exit
fi
# Prevent the cloned repository from having insecure permissions.
Failing to do
# so causes compinit() calls to fail with "command not found:
compdef" errors
# for users with insecure umasks (e.g., "002", allowing group
writability). Note
# that this will be ignored under Cygwin by default, as Windows ACLs
take
# precedence over umasks except for filesystems mounted with option
"noacl".
umask g-w,o-w
printf "${BLUE}Cloning Oh My Zsh...${NORMAL}\n"
hash git >/dev/null 2>&1 || {
echo "Error: git is not installed"
exit 1
}
# The Windows (MSYS) Git is not compatible with normal use on cygwin
if [ "$OSTYPE" = cygwin ]; then
if git --version | grep msysgit > /dev/null; then
echo "Error: Windows/MSYS Git is not supported on Cygwin"
echo "Error: Make sure the Cygwin git package is installed and is
first on the path"
exit 1
fi
fi
env git clone --depth=1 https://github.com/robbyrussell/oh-my-zsh.git
$ZSH || {
printf "Error: git clone of oh-my-zsh repo failed\n"
exit 1
}
printf "${BLUE}Looking for an existing zsh config...${NORMAL}\n"
if [ -f ~/.zshrc ] || [ -h ~/.zshrc ]; then
printf "${YELLOW}Found ~/.zshrc.${NORMAL} ${GREEN}Backing up to
~/.zshrc.pre-oh-my-zsh${NORMAL}\n";
mv ~/.zshrc ~/.zshrc.pre-oh-my-zsh;
fi
zsh itself does not have a default user configuration. So the default ~/.zshrc is actually no ~/.zshrc.
But as you tagged the question with oh-my-zsh I would assume that you want to restore the default oh-my-zsh configuration. For this it should be sufficient to copy templates/zshrc.zsh-template from your oh-my-zsh installation path, usually ~/.oh-my-zsh:
cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc
You may want to backup your current ~/.zshrc beforehand. Although it may have some problems now, you still might want to look up some settings once you reverted to default.
There is no such thing as "default". The best you can do, is check if your system has /etc/skel/.zshrc. If yes copy that into your home.
When you log in first time, your home is populated with everything from /etc/skel.
My dumass decided to just put a crash command into the zsh file. Now when I open the terminal, it just kernel panics. so I just deleted the config file using rm -f ~/.zshrc* and by default, it just got replaced with another copy. So good luck.
You can copy .zshrc template from
https://github.com/ohmyzsh/ohmyzsh/blob/master/templates/zshrc.zsh-template
And copy and paste all content in to ~/.zshrc
[MS Windows Friendly Solution - If terminal(using vim editor) steps are confusing]
Actually, there is no default .zshrc file, but if you need to edit is as a simple notepad, do these:
Goto /Users/ Folder via Finder App.
Click Shift + Command + . (Dot) to view hidden system files.
Look on .zshrc file, double click to open, then it will open in a notepad(TextEdit.app) in default.
Clear whichever lines to be removed.
Retype/Edit the file as per the Paths to be added.
Hit Command + s to save and exit.
Make it your default shell using this command:
chsh -s $(which zsh)

.zshrc unrecognized condition on $-

I'm attempting to port over some functionality from my old .bashrc into my .zshrc and I'm having trouble with a condition that worked in bash.
Whenever I remote log in to my computer, I had bash check the $- variable to see if it was interactive. If it was, I would start up an emacs server if one wasn't already running and change to my code directory. Otherwise (if I was getting a file with scp, for example), I wouldn't do anything.
Here's the bit of code:
if [[ $- -regex-match "i" ]]; then
ps -u myusername | grep emacs > /dev/null
if [ $? -eq 0 ]; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
And here's the error zsh gives me: .zshrc:125: unrecognized condition:$-'`
Does anyone know how to get around this error when using $- ? I've tried quoting it, wrapping it in $(echo $-) but none have worked. Thanks in advance.
Edit: If I switch my code to:
if [[ $- =~ "i" ]]; then
ps -u myusername | grep emacs > /dev/null
if [ $? -eq 0 ]; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
I now get: .zshrc:125: condition expected: =~ I'm not sure exactly what zsh is interpreting incorrectly here as I'm not very familiar with the semantics of zsh's shell scripts. Could someone point me in the right direction on how to express this condition in zsh?
In zsh, you don't need to bother with $-, which is--I think--intended primarily for POSIX compatibility.
if [[ -o INTERACTIVE ]]; then
if ps -u myusername | grep -q emacs; then
echo "emacs server already running"
else
emacsserver
fi
aliastocdtomydirectory
fi
-regex-match is only available if tho module zsh/regex (man 1 zshmodules) is loaded. (The error message depends on the version: I get zsh: unknown condition: -regex-match if it is not loaded on 4.3.17, but zsh:1: unknown condition: -$- on 4.3.10).
You can try [[ $- =~ "i" ]] which is not dependend on additional modules.

sh script: no output when run in mounted filesystem

Need some help to understand what's wrong.
In short: I've written a bourne shell script, which creates links to contents of source directory in the target directory.
It worked fine on the host system but when targeted on directories on mounted fs (both from chroot and native system) it doesn't work and provides no output at all.
Details:
mounted fs: ext3, rw
host system: 3.2.0-48-generic #74-Ubuntu SMP GNU/Linux
To narrow the question, "/usr" was taken as an example.
permissions for "/usr" in the host system: drwxr-xr-x
permissions for "/usr" on mounted partition: drwxr-xr-x
Tried to use both bash and dash from host system. Same result - works for native file systems, does not work for the mounted.
script (cord.sh; run from root in my cases):
# !/bin/sh
SRCFOLDER=$2 # folder with package installation
DESTFOLDER=$3 # destination folder to install symlinks to ('/' - for base sys; '/usr' - userland)
TARGETS=$(ls $SRCFOLDER) # targets to handle
SRCFOLDER=${SRCFOLDER%/} # stripping slashes from the end, if they are present
DESTFOLDER=${DESTFOLDER%/} #
##
## LINKING
##
if [ "$1" = "-c" ];
then printf %s "$TARGETS" | while IFS= read -r line
do
current_target=$(file $SRCFOLDER/$line) # had an issue with different output in different systems
if [ "${current_target% }" = "$SRCFOLDER/$line: directory" ]; # stripping space helped
then
mkdir -v $DESTFOLDER/$line # if other package created it - it'll fail
/usr/local/bin/cord.sh -c $SRCFOLDER/$line $DESTFOLDER/$line # RECURSION
else
ln -sv $SRCFOLDER/$line $DESTFOLDER/$line # will fail, if exists
fi;
done
##
## REMOVING LINKS
##
elif [ "$1" = "-d" ];
then printf %s "$TARGETS" | while IFS= read -r line
do
current_target=$(file $SRCFOLDER/$line)
if [ "${current_target% }" = "$SRCFOLDER/$line: directory" ];
then
/usr/local/bin/cord.sh -d $SRCFOLDER/$line $DESTFOLDER/$line # RECURSION
else
rm -v $DESTFOLDER/$line
fi;
done
elif [ "$1" = "-h" ];
then
echo "Usage:"
echo "cord -c /path/to/pkgdir /path/to/linkdir - create simlinks for package contents"
echo "cord -d /path/to/pkgdir /path/to/linkdir - delete links for package"
echo "cord -h - displays this help note"
else
echo "Usage:"
echo "cord -c /path/to/pkgdir /path/to/linkdir - create simlinks for package contents"
echo "cord -d /path/to/pkgdir /path/to/linkdir - delete links for package"
echo "cord -h - displays this help note"
fi;
The most obvious thing to suggest, was some issue with permissions. Yet everything looks sane. Maybe I've missed something?
I don't know what your main problem might be (permissions or something else - you should include an example of how you run the script and how you prepare for it with the mounts and everything). But this script can be cleaned up.
First, if you want to test whether something is a directory, use
if [ -d "$something ]
That'll get rid of the clumsy file usage.
Second, don't go through the redundant steps of converting your $TARGETS array to a series of lines and then reading the lines with a loop. Just loop over the array directly.
for line in $TARGETS
Also, instead of using ls to populate an array of filenames, I'd use a glob. But instead of either of those, I'd use find so it can take care of recursion and eliminate the tree of processes you're creating by recursing with a call to the same script. And instead of writing a symlink-tree-maker script I'd use something like lndir which already exists for that purpose...

check if directory exists and delete in one command unix

Is it possible to check if a directory exists and delete if it does,in Unix using a single command? I have situation where I use ANT 'sshexec' task where I can run only a single command in the remote machine. And I need to check if directory exists and delete it...
Why not just use rm -rf /some/dir? That will remove the directory if it's present, otherwise do nothing. Unlike rm -r /some/dir this flavor of the command won't crash if the folder doesn't exist.
Assuming $WORKING_DIR is set to the directory... this one-liner should do it:
if [ -d "$WORKING_DIR" ]; then rm -Rf $WORKING_DIR; fi
(otherwise just replace with your directory)
Try:
bash -c '[ -d my_mystery_dirname ] && run_this_command'
This will work if you can run bash on the remote machine....
In bash, [ -d something ] checks if there is directory called 'something', returning a success code if it exists and is a directory. Chaining commands with && runs the second command only if the first one succeeded. So [ -d somedir ] && command runs the command only if the directory exists.
Here is another one liner:
[[ -d /tmp/test ]] && rm -r /tmp/test
&& means execute the statement which follows only if the preceding
statement executed successfully (returned exit code zero)
I recommend opening documentation of rm command.
If open then you will see that there is a
-f flag does what you want. Example: rm -f -R ./my_folder

line doesn't execute in .bash_profile and .bashrc on my Mac OSX Snow Leopard

I just installed Ruby Version Manager (RVM) which is working fine but it asked me to put the following line in my /.bash_profile and ~/.bashrc files:
if [[ -s /Users/tammam56/.rvm/scripts/rvm ]] ; then source /Users/tammam56/.rvm/scripts/rvm ; fi
looking at the content I see the following:
tammam56$ cat /.bash_profile
export PATH="/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:$PATH"
if [[ -s /Users/tammam56/.rvm/scripts/rvm ]] ; then source /Users/tammam56/.rvm/scripts/rvm ; fi
tammam56$ cat ~/.bashrc
export PATH=/usr/local/bin:$PATH
export MANPATH=/usr/local/man:$MANPATH
if [[ -s /Users/tammam56/.rvm/scripts/rvm ]] ; then source /Users/tammam56/.rvm/scripts/rvm ; fi
However when I start new Terminal window it doesn't execute the command I know this as I set my default Ruby verion to 1.9 and if I execute the line manually I get to the correct version:
tammam56$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]
Macintosh-37:~ tammam56$ if [[ -s /Users/tammam56/.rvm/scripts/rvm ]] ; then source /Users/tammam56/.rvm/scripts/rvm ; fi
Macintosh-37:~ tammam56$ ruby -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin10.2.0]
Any ideas how I can fix that?
Thanks,
Tam
If you have a ~/.profile try adding the following line to it.
if [[ -s /Users/tammam56/.rvm/scripts/rvm ]] ; then source /Users/tammam56/.rvm/scripts/rvm ; fi
Have you confirmed that other commands in .bashrc and/or .bash_profile get updated properly?
Next you should confirm whether Terminal is starting the shell as a login shell or not (see under Preferences -> Startup).
From the bash man page:
When bash is invoked as an interactive login shell, or as a non-inter-
active shell with the --login option, it first reads and executes com-
mands from the file /etc/profile, if that file exists. After reading
that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile,
in that order, and reads and executes commands from the first one that
exists and is readable. The --noprofile option may be used when the
shell is started to inhibit this behavior.
When an interactive shell that is not a login shell is started, bash
reads and executes commands from ~/.bashrc, if that file exists. This
may be inhibited by using the --norc option. The --rcfile file option
will force bash to read and execute commands from file instead of
~/.bashrc.
I found that the easiest solution to this issue was to move all of the contents from my ~/.bashrc file (so my ~/.bashrc is now empty) to a new ~/.bash_profile file. Now all Terminal.app tabs automatically run all lines included in ~/.bash_profile. This also applies to iTerm.

Resources