Conditional prompt in Git Bash (Windows), with miniconda - windows

I am using git bash on windows 10 with miniconda for my python environments, and I've been trying to modify my prompt to show the environment name. So I have my ~/.bashrc file, where I tried to write a very simple condition inspired from the git-prompt.sh. The result I want is the following:
user#laptop: working_dir (git_branch)
>
and
user#laptop: working_dir (git_branch)
(conda_env) >
when I activate an environment. My problem is that I can't find a way to show the (conda_env) properly. I've tried something like this for the 2nd line:
PS1="$PS1"'\n' # new line
if [ ! -z "$CONDA_DEFAULT_ENV" ]
then
PS1="$PS1""($CONDA_DEFAULT_ENV) "
fi
PS1="$PS1"'\[\033[32m\]' # change to green
PS1="$PS1"'> '
I also tried different test for the condition, such as:
if [[ "$CONDA_DEFAULT_ENV" != "" ]]
if [ test -n "$CONDA_DEFAULT_ENV"]
and a few others. But I always have problems, sometimes it's the parentheses who show up even when $CONDA_DEFAULT_ENV is null, sometimes the test seems to work but I still have a stray space before the final ">" (which would logically come from the "($CONDA_DEFAULT_ENV) " part, meaning the test is not correct), etc.
Does anyone knows why this happens and how I can have this simple conditional prompt working?

I had the same problem just 2 hours ago, finally, I just found a solution!
The solution is to encapsulate your if statement inside a function and calling it via the string this way it's dynamic and changes when you change environments.
Let me show you how I did it:
check_conda_env ()
{
if [ ! -z "$CONDA_DEFAULT_ENV" ]; then
printf "($CONDA_DEFAULT_ENV) "
else
printf ""
fi
}
PS1="$PS1"'\n' # new line
PS1="$PS1"'$(check_conda_env)' # calls check_conda_env everytime it is printed to the screen
PS1="$PS1"'\[\033[32m\]' # change to green
PS1="$PS1"'> '
The reason why this works is simply because your string is now "dynamic", meaning it calls the function check_conda_env every time it is printed to the screen.

Related

Possible to get bash input while user is at prompt? (Essentially an event listener)

Old stuff:
Background:
- Ultimate goal is to put a script in my .bash_profile that warns me by changing text color if I'm typing a commit message and it gets too
long (yes I'm aware vim has something like this).
Progress:
- I found the read -n option which led me to write this:
while true; do
# This hits at the 53rd character
read -rn53 input
# I have commit aliased to gc so the if is just checking if I'm writing a commit
if [ "${input:0:2}" = "gc" ]; then
printf "\nMessage getting long"
fi
done
Question:
- However, running this takes the user out of the bash prompt. I need a way to do something like this while at a normal prompt. I can't find
information on anything like this. Does that mean it's not possible?
Or am I just going about it the wrong way?
New progress:
I found the bind -x option which led me to write this:
check_commit() {
if [ "${READLINE_LINE:0:13}" == 'git commit -m' ] && [ ${#READLINE_LINE} -gt 87 ]; then
echo "Commit is $((${#READLINE_LINE} - 87)) characters too long!"
fi
READLINE_LINE="$READLINE_LINE$1"
READLINE_POINT=$(($READLINE_POINT+1))
}
bind -x '"\"": check_commit "\""'
It listens for a double quote and if I'm writing a long commit message tells me how many characters I am over the limit. Also puts the character I typed into the current line since it is eaten by the bind.
New question:
Now I just need a way to put in a regex, character list or at least a variable instead of \" so I can listen on more keys (Yes, I'm aware bind -x probably wasn't intended to be used this way. I can check performance/footprint/stability myself). I tried "$char", "${char}", "$(char)" and a few other things, but none seem to work. What is the correct approach here ?
AFAIK, not possible in a sane way if you want this to happen during your normal prompt (when PROMPT_COMMAND and PS1 are evaluated). That would involved binding a custom compiled readline function for every insert-self and alike.
If you want this to happen in a script using prompt builtin, this is crudely possible with a loop of
read -e -i $(munge_buf $buf) -n $(buf_warn_len $buf) -p $(buf_warning $buf) buf
like commands. This will allow you to create munge_buf() to alter the currently typed text if needed, buf_warn_len() to calculate a new len to warn at (which may be very large if warning was already displayed), and buf_warn_msg() to derive a warning message based upon the buffer.

Error: =: command not found (Bash Script)

I found a nifty little shell script that I wanted to use from this website here. I have followed everything step-by-step, but receive the following error when running this on my CentOS box.
./deploy: line 3: =: command not found
Line 3 only contains...
$ERRORSTRING = "Error. Please make sure you've indicated correct parameters"
I've tried toying around with a bit, but don't understand why it won't accept the "=" character. Is there something wrong with the script, or is it merely something different in the way that my server processes the script?
Thanks!
Gah, that script is full of bad scripting practices (in addition to the outright error you're running into). Here's the outright error:
$ERRORSTRING = "Error. Please make sure you've indicated correct parameters"
As devnull pointed out, this should be:
ERRORSTRING="Error. Please make sure you've indicated correct parameters"
A couple of lines down (and again near the end), we have:
echo $ERRORSTRING;
...which works, but contains two bad ideas: a variable reference without double-quotes around it (which will sometimes be parsed in unexpected ways), and a semicolon at the end of the line (which is a sign that someone is trying to write C or Java or something in a shell script). Use this instead:
echo "$ERRORSTRING"
The next line is:
elif [ $1 == "live" ]
...which might work, depending on whether the value of $1 has spaces, or is defined-but-blank, or anything like that (again, use double-quotes to prevent misparsing!). Also, the == comparison operator is nonstandard -- it'll work, because bash supports it in its [ ... ] builtin syntax, but if you're counting on having bash extensions available, why not use the much cleaner [[ ... ]] replacement? Any of these would be a better replacement for that line:
elif [ "$1" = "live" ]
elif [[ $1 == "live" ]]
elif [[ "$1" == "live" ]]
Personally, I prefer the last. The double-quotes aren't needed in this particular case, but IMO it's safest to just double-quote all variable references unless there's a specific reason not to. A bit further down, there's a elif [ $2 == "go" ] that the same comments apply to.
BTW, there's a good sanity-checking tool for shell scripts at www.shellcheck.net. It's not quite as picky as I am (e.g. it doesn't flag semicolons at the ends of lines), but it pointed out all of the actual errors in this script...
"Devnulls" answer was correct -- I had to remove the spaces around the "=" and remove the "$" from that line as well. The end result was...
ERRORSTRING="Error. Please make sure you've indicated correct parameters"
I've upvoted Devnull and gniourf_gniourf's comments.
Thank you to all whom have assisted!

Why doesn't this bit of code work? Setting variables and config file

I have recently just made this script:
if test -s $HOME/koolaid.txt ; then
Billz=$(grep / $HOME/koolaid.txt)
echo $Billz
else
Billz=$HOME/notkoolaid
echo $Billz
fi
if test -d $Billz ; then
echo "Ok"
else touch $Billz
fi
So basically, if the file $HOME/koolaid.txt file does NOT exist, then Billz will be set as $HOME/koolaid.txt. It then sucesfully creates the file.
However, if I do make the koolaid.txt then I get this
mkdir: cannot create directory : No such file or directory
Any help would be appreciated
Here is a difference between content of a variable and evaluated content...
if your variable contains a string $HOME/some - you need expand it to get /home/login/same
One dangerous method is eval.
bin=$(grep / ~/.rm.cfg)
eval rbin=${bin:-$HOME/deleted}
echo "==$rbin=="
Don't eval unless you're absolutely sure what you evaling...
Here are a couple things to fix:
Start your script with a "shebang," such as:
#!/bin/sh
This way the shell will know that you want to run this as a Bourne shell script.
Also, your conditional at the top of the script doesn't handle the case well in which .rm.cfg exists but doesn't contain a slash character anywhere in it. In that case the rbin variable never gets set.
Finally, try adding the line
ls ~
at the top so you can see how the shell is interpreting the tilde character; that might be the problem.

Trouble getting shell script to work with simple conditional statement

This is part of a bigger project but I can't get this part to work and I'm having a brain fart.
#!/bin/bash
echo -n "Do you wish to download/checkout the source code? > "
read text
if ["$text" = "Yes"]
then
do something
else
do something else
fi
It should simply be reading in what the user types and then go through a simple conditional. but I get this error
./check.sh: line 6: [Yes: command not found
I thought I had formatted the shell script correctly but I guess not.
Add spaces after brackets:
if [[ "$text" = "Yes" ]]
When performing operations on strings it's always a good idea to use double square brackets. It will make your code work properly with spaces and new lines.

How do I check if a PATH is set? And if not, set it from an argument

#!/bin/bash
if[$LD_PATH == ""]
then
export LD_PATH=$1
else
export LD_PATH=$LD_PATH
fi
#excute the program that needs the path
./someProgThatNeedsThePath
i keep getting "cannot open shared object file"
First, your bash syntax is broken due to lack of spaces. First, you would need spaces around the [ and ] closures. If you use the newer alternate double bracket syntax, you don't have to worry about quoting variables you are testing.
#!/bin/bash
if [[ $LD_PATH = "" ]]; then
export LD_PATH="$1"
else
export LD_PATH="$LD_PATH"
fi
But your real problem is not that at all. Since your code is running in a separate bash shell, the code will have no effect on anything you run in the parent shell. In order to do that you would want to build a function:
function add_to_ld_path () {
if [[ -z $LD_PATH ]]; then
export LD_PATH="$1"
fi
}
Add that code to your .profile, then run it with add_to_ld_path /my/path when you want to use it. Note that since your "else" statement wasn't actually doing anything, I removed it. I also replaced your test for a blank string by making your own with quotes with the builtin empty string test.
Next up is what you are actually trying to accomplish. If all you want to do is set the variable if it's empty, UncleAli's solution is very simple. But it might be useful to do something like this:
function add_to_ld_path () {
case ":$LD_PATH:" in
*"$1"*) :;;
*) LD_PATH=$LD_PATH:$1
esac
}
This would check the current path and add the path given if it wasn't already part of the LD_PATH variable, otherwise it would leave it alone.
if [ -z "$LD_PATH" ]
then
export LD_PATH=$1
fi
Will that do the job?

Resources