Starship cross-shell prompt is not working on Mac zsh - zsh

I'm using a Mac and followed the instructions to install with homebrew and added eval "$(starship init zsh)" to ~/.zshrc.
However, when I restarted my terminal it still shows the default one.
Here's the content of my .zshrc (added the line at the bottom)
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/opt/anaconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
eval "$__conda_setup"
else
if [ -f "/opt/anaconda3/etc/profile.d/conda.sh" ]; then
. "/opt/anaconda3/etc/profile.d/conda.sh"
else
export PATH="/opt/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<<
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
export GOPATH=$HOME/go
export PATH=$GOPATH/bin:$PATH
export GOBIN=$GOPATH/bin
eval "$(starship init zsh)"

Related

Conditionally set global variables in a bash script [duplicate]

This question already has answers here:
Can a shell script set environment variables of the calling shell? [duplicate]
(20 answers)
Closed last month.
I am trying to write a bash script that will take a single argument("prod" or "staging"), and use that to conditionally set global environment variables, specifically to switch between my staging and prod AWS keys. However, even though my logs in the script show what I expect, running echo $AWS_ACCESS_KEY in my terminal after running the script, does not show it was updated. I have tried adding source ~/.zshrc but I don't think that is needed. What can I change to update the $AWS_ACCESS_KEY globally?
#!/bin/bash
tmpAccess="access"
tmpSecret="secret"
if [ $1 == "prod" ];
then
echo "Setting the AWS KEYS to $1 keys"
tmpAccess=$PROD_ACCESS_KEY
tmpSecret=$PROD_SECRET_KEY
elif [ $1 == "staging" ];
then
echo "Setting the AWS KEYS to $1 keys"
tmpAccess=$STAGING_ACCESS_KEY
tmpSecret=$STAGING_SECRET_KEY
else
echo "Unknown env passed in: $1"
fi
export AWS_ACCESS_KEY=$tmpAccess
export AWS_SECRETS_KEY=$tmpSecret
echo "Updated AWS_ACCESS_KEY: $AWS_ACCESS_KEY"
echo "Current tmpAccess: $tmpAccess"
echo "AWS_ACCESS_KEY has been updated to $AWS_ACCESS_KEY for env $1"
echo "AWS_SECRETS_KEY has been updated to $AWS_SECRETS_KEY for env $1"
source ~/.zshrc
My zshrc file looks similar to:
export STAGING_ACCESS_KEY=1234
export STAGING_SECRETS_KEY=abcd
export PROD_ACCESS_KEY=5678
export PROD_SECRETS_KEY=efgh
Clearly, it's not possible to put in a script a program to modify a variable in the current terminal except if you accept to source it (see Setting environment variable in shell script does not make it visible to the shell).
There is another solution. Put your script content in a function:
myfunctionName () {
tmpAccess="access"
tmpSecret="secret"
if [ $1 == "prod" ];
then
echo "Setting the AWS KEYS to $1 keys"
tmpAccess=$PROD_ACCESS_KEY
tmpSecret=$PROD_SECRET_KEY
elif [ $1 == "staging" ];
then
echo "Setting the AWS KEYS to $1 keys"
tmpAccess=$STAGING_ACCESS_KEY
tmpSecret=$STAGING_SECRET_KEY
else
echo "Unknown env passed in: $1"
fi
export AWS_ACCESS_KEY=$tmpAccess
export AWS_SECRETS_KEY=$tmpSecret
echo "Updated AWS_ACCESS_KEY: $AWS_ACCESS_KEY"
echo "Current tmpAccess: $tmpAccess"
echo "AWS_ACCESS_KEY has been updated to $AWS_ACCESS_KEY for env $1"
echo "AWS_SECRETS_KEY has been updated to $AWS_SECRETS_KEY for env $1"
}
and put this function in your .zshrc file.
After that, launch a new terminal and call your myfunctionName function like the script filename.

parse erorr near '\n' in .zshrc file

When I open my MacOS terminal, it shows
Last login: Sun Jan 2 15:50:48 on ttys000
/Users/rajeshrao/.zshrc:18: parse error near `\n'
(base) rajeshrao#Rajeshs-MacBook-Air ~ %
I tried opening that .zshrc file which had this code in there ---->
export PATH="/usr/local/sbin:$PATH"
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/Users/rajeshrao/opt/anaconda3/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
eval "$__conda_setup"
else
if [ -f "/Users/rajeshrao/opt/anaconda3/etc/profile.d/conda.sh" ]; then
. "/Users/rajeshrao/opt/anaconda3/etc/profile.d/conda.sh"
else
export PATH="/Users/rajeshrao/opt/anaconda3/bin:$PATH"
fi
fi
unset __conda_setup
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.0.1.jdk/Contents/Home
<<<conda initialize<<<
here is the image of code
I don't know much about how shell works and am just a beginner. I didn't interfere with anything before using the terminal.
The last line has lost the initial '#' (ie. is not a comment).
Edit the file to end with this line:
# <<<conda initialize<<<

Changing path to current working directory in zsh prompt

I'm trying to modify an existing zsh prompt to work with zsh 5.0 and 4.3 because those the versions the systems that I use. How would I make a zsh-script be aware of the current working directory instead of the directory that the file is in?
For context,
This is a function in the script that checks if we're currently in a git directory and adds to the prompt if we are:
# Git status.
# Collect indicators, git branch and pring string.
spaceship_git_status() {
[[ $SPACESHIP_GIT_SHOW == false ]] && return
# Check if the current directory is in a Git repository.
command git rev-parse --is-inside-work-tree &>/dev/null || return
# Check if the current directory is in .git before running git checks.
if [[ "$(git rev-parse --is-inside-git-dir 2> /dev/null)" == 'false' ]]; then
# Ensure the index is up to date.
git update-index --really-refresh -q &>/dev/null
# String of indicators
local indicators=''
indicators+="$(spaceship_git_uncomitted)"
indicators+="$(spaceship_git_unstaged)"
indicators+="$(spaceship_git_untracked)"
indicators+="$(spaceship_git_stashed)"
indicators+="$(spaceship_git_unpushed_unpulled)"
[ -n "${indicators}" ] && indicators=" [${indicators}]";
echo -n " %Bon%b "
echo -n "%{$fg_bold[magenta]%}"
echo -n "$(git_current_branch)"
echo -n "%{$reset_color%}"
echo -n "%{$fg_bold[red]%}"
echo -n "$indicators"
echo -n "%{$reset_color%}"
fi
}
However, based on my debugging, it appears that the function always believes that it is in the directory from which the script was sourced. In other words, as I change directory, the script continues to reference the directory where the script is located.
The spaceship_git_status function is called here:
# Build prompt line
spaceship_build_prompt() {
spaceship_host
spaceship_current_dir
spaceship_git_status
spaceship_nvm_status
spaceship_ruby_version
spaceship_venv_status
}
And this is the PROMPT environment variable is:
# Compose PROMPT
PROMPT=''
[[ $SPACESHIP_PROMPT_ADD_NEWLINE == true ]] && PROMPT="$PROMPT$NEWLINE"
PROMPT="$PROMPT $(spaceship_build_prompt) "
[[ $SPACESHIP_PROMPT_SEPARATE_LINE == true ]] && PROMPT="$PROMPT$NEWLINE"
PROMPT="$PROMPT $(spaceship_return_status) "
I think this is an issue with zsh versions < 5.2 because the prompt renders fine on my other computer with 5.2.
Full code: https://github.com/denysdovhan/spaceship-zsh-theme/blob/master/spaceship.zsh

zsh / zle Editing long commands, specifically trying to insert characters, garbles the command string

tmux, zsh, vi mode, oh-my-zsh, TERM set to screen-256color
I scroll through command history with Esc K, on each command i can move left and right, and i can erase characters, but as soon as I try to insert the command string gets garbled. Also,this only happens when the command is longer then the terminal width.
zshrc:
export ZSH=${HOME}/.oh-my-zsh
ZSH_THEME="robbyrussell-ay"
CASE_SENSITIVE="true"
plugins=(git)
if [ -f $HOME/.aliases ]; then
source $HOME/.aliases
fi
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
if [ -f $ZSH/oh-my-zsh.sh ]; then
source $ZSH/oh-my-zsh.sh
fi
export LANG=en_US.UTF-8
export KEYTIMEOUT=1
setopt nosharehistory
bindkey -v
PATH=$PATH:${HOME}/bin
export PATH="$HOME/.plenv/bin:$PATH"
eval "$(plenv init - zsh)"`
prompt is set in "robbyrussell-ay":
local ret_status="%(?:%{$fg_bold[green]%}➜ :%{$fg_bold[red]%}➜ )"
PROMPT=$'[%D{%Y-%m-%d %H:%M:%S}]$fg[cyan][%n#%m]$reset_color $fg[yellow]%~ $fg[green]$(git_prompt_info)\n${ret_status}${reset_color} '
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[blue]%}git:(%{$fg[red]%}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[blue]%}) %{$fg[yellow]%}✗"
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[blue]%})"
As it turns out, i had an error in my prompt -
PROMPT=$'[%D{%Y-%m-%d %H:%M:%S}]$fg[cyan][%n#%m]$reset_color $fg[yellow]%~ $fg[green]$(git_prompt_info)\n${ret_status}${reset_color} '
had a section that should have been wrapped in %{...%}
$fg[cyan][%n#%m]
should be
%{fg[cyan]%}[%n#%m]
I ended up changing my prompt slightly, it now looks like this:
PROMPT='%{$fg[yellow]%}[%*|%D]%}${ret_status}%{$fg[cyan]%}[%n#%m]$reset_color%{$fg[cyan]%}%~%{$reset_color%}$(git_prompt_info)
$ '

Find out if a command exists on POSIX system

I want to be able to tell if a command exists on any POSIX system from a shell script.
On Linux, I can do the following:
if which <command>; then
...snip...
fi
However, Solaris and MacOS which do not give an exit failure code when the command does not exist, they just print an error message to STDOUT.
Also, I recently discovered that the which command itself is not POSIX (see http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html)
Any ideas?
command -v is a POSIX specified command that does what which does.
It is defined to to return >0 when the command is not found or an error occurs.
You could read the stdout/stderr of "which" into a variable or an array (using backticks) rather than checking for an exit code.
If the system does not have a "which" or "where" command, you could also grab the contents of the $PATH variable, then loop over all the directories and search for the given executable. That's essentially what which does (although it might use some caching/optimization of $PATH results).
One which utility is available as shell script in the Git repository of debianutils package of Debian Linux. The script seems to be POSIX compatible and you could use it, if you take into account copyright and license. Note that there have been some controversy whether or not and how the which utility should be deprecated; (at time of writing) current version in Git shows deprecation message whereas an earlier version added later removed -s option to enable silent operation.
command -v as such is problematic as it may output a shell function name, an alias definition, a keyword, a builtin or a non-executable file path. On the other hand some path(s) output by which would not be executed by shell if you run the respective argument as such or as an argument for command. As an alternative for using the which script, a POSIX shell function using command -v could be something like
#!/bin/sh
# Argument $1 should be the basename of the command to be searched for.
# Outputs the absolute path of the command with that name found first in
# a directory listed in PATH environment variable, if the name is not
# shadowed by a special built-in utility, a regular built-in utility not
# associated with a PATH search, or a shell reserved word; otherwise
# outputs nothing and returns 1. If this function prints something for
# an argument, it is the path of the same executable as what 'command'
# would execute for the same argument.
executable() {
if cmd=$(unset -f -- "$1"; command -v -- "$1") \
&& [ -z "${cmd##/*}" ] && [ -x "$cmd" ]; then
printf '%s\n' "$cmd"
else
return 1
fi
}
Disclaimer: Note that the script using command -v above does not find an executable whose name equals a name of a special built-in utility, a regular built-in utility not associated with a PATH search, or a shell reserved word. It might not find an executable either in case if there is non-executable file and executable file available in PATH search.
A function_command_exists for checking if a command exists:
#!/bin/sh
set -eu
function_command_exists() {
local command="$1"
local IFS=":" # paths are delimited with a colon in $PATH
# iterate over dir paths having executables
for search_dir in $PATH
do
# seek only in dir (excluding subdirs) for a file with an exact (case sensitive) name
found_path="$(find "$search_dir" -maxdepth 1 -name "$command" -type f 2>/dev/null)"
# (positive) if a path to a command was found and it was executable
test -n "$found_path" && \
test -x "$found_path" && \
return 0
done
# (negative) if a path to an executable of a command was not found
return 1
}
# example usage
echo "example 1";
command="ls"
if function_command_exists "$command"; then
echo "Command: "\'$command\'" exists"
else
echo "Command: "\'$command\'" does not exist"
fi
command="notpresent"
if function_command_exists "$command"; then
echo "Command: "\'$command\'" exists"
else
echo "Command: "\'$command\'" does not exist"
fi
echo "example 2";
command="ls"
function_command_exists "$command" && echo "Command: "\'$command\'" exists"
command="notpresent"
function_command_exists "$command" && echo "Command: "\'$command\'" does not exist"
echo "End of the script"
output:
example 1
Command: 'ls' exists
Command: 'notpresent' does not exist
example 2
Command: 'ls' exists
End of the script
Note that even the set -eu that turns -e option for the script was used the script was executed to the last line "End of the script"
There is no Command: 'notpresent' does not exist in the example 2 because of the && operator so the execution of echo "Command: "\'$command\'" does not exist" is skipped but the execution of the script continues till the end.
Note that the function_command_exists does not check if you have a right to execute the command. This needs to be done separately.
Solution with command -v <command-to-check>
#!/bin/sh
set -eu;
# check if a command exists (Yes)
command -v echo > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 1>"
fi
# check if a command exists (No)
command -v command-that-does-not-exists > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 2>"
fi
produces:
<handle not found 2>
because echo was found at the first example.
Solution with running a command and handling errors including command not found.
#!/bin/sh
set -eu;
# check if a command exists (No)
command -v command-that-does-not-exist > /dev/null && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 2>"
fi
# run command and handle errors (no problem expected, echo exist)
echo "three" && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 3>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 3>"
fi
# run command and handle errors (<handle not found 4> expected)
command-that-does-not-exist && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 4>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 4>"
fi
# run command and handle errors (command exists but <handle other error 5> expected)
ls non-existing-path && status="$?" || status="$?"
if [ "${status}" = 127 ]; then
echo "<handle not found 5>"
elif [ "${status}" -ne 0 ]; then
echo "<handle other error 5>"
fi
produces:
<handle not found 2>
three
./function_command_exists.sh: 34: ./function_command_exists.sh: command-that-does-not-exist: not found
<handle not found 4>
ls: cannot access 'non-existing-path': No such file or directory
<handle other error 5>
The following works in both bash and zsh and avoids both functions and aliases.
It returns 1 if the binary is not found.
bin_path () {
if [[ -n ${ZSH_VERSION:-} ]]; then
builtin whence -cp "$1" 2> /dev/null
else
builtin type -P "$1"
fi
}

Resources