How to get absolute path on a zsh prompt? - zsh

I'm switching from bash to zsh.
I want to update my new zsh prompt and looked around to find a way, but I have only found "solutions" via oh-my-zsh.
The goal:
Location: ~/dir_1/dir_1_1/dir_1_1_1
What I have:
Location: dir_1_1_1
The code (source):
PS1='${SSH_CONNECTION+"%{$fg_bold[green]%}%n#%m:"}%{$fg_bold[green]%}Location: %c%{$reset_color%}$(git_prompt_info) '

To preserve original prompt format (colors, git info and potentially other customisations before this one) except related to path info, you could append following to the end of ~/.zshrc:
PROMPT=${PROMPT/\%c/\%~}
As pointed out by #caleb-adams and #fend25 the key is replacing %c (just folder name) with %~ to include full path (or absolute from $HOME when under ~). See http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html for more info

As Horacio Chavez mentioned in the comment above, you want to look here: http://zsh.sourceforge.net/Doc/Release/Prompt-Expansion.html for the details on how to change your displayed path in zsh.
In this case if you are looking for a path that is relative to your home folder, include a %~ in your zsh-theme file. Your prompt would now look like this:
PS1='${SSH_CONNECTION+"%{$fg_bold[green]%}%n#%m:"}%{$fg_bold[green]%}Location: %~%{$reset_color%}$(git_prompt_info) '
note, I only changed one character in your prompt. the %c was swapped for the %~. %c will only give your current directory (see the document link above, or here)
For a full path you could use %/

Simplest way to add bash-style dir path to the prompt. Just add this to ~/.zshrc:
setopt PROMPT_SUBST
PROMPT='%n#%m: ${(%):-%~} '
The part with the path is ${(%):-%~}. Colouring could be added according with your lifestyle:)

Related

Trying to set a prompt to display a specific portion of PWD in ZSH

I am currently using this in ZSH
export PS1='${USER}:${PWD}: '
I could use this:
export PS1='${USER}:${PWD##*/} \$ '
But I want to see a folder further up in the folder hierarchy, so I would like to use something like this,
export PS1='${USER}:${PWD | cut -d '/' -f6}:${PWD##*/} '
But this doesn't work it just shows this:
${USER}:${PWD | cut -d / -f6}:${PWD##*/}
I want it to show a specific folder (at positision f6) and then the current directory.
Any thoughts on how I can do this?
Does this work?:
setopt prompt_subst
export PROMPT='${USER}:${${(s:/:)PWD}[5]}:${PWD:t} '
Some of the pieces:
setopt prompt_subst - allows ${...} in prompts to be expanded. You probably have this in your ~/.zshrc already.
PROMPT - same effect as PS1.
${(s:/:)PWD} - splits the working directory value in PWD on /s.
${...[5]} - selects the fifth element of that split (which correlates to the sixth field from cut).
${PWD:t} - selects the 'tail' (last) element from the path.
The s parameter expansion flag is documented in the zshexpn man page, along with the t modifier. You may also want to look at the prompt escapes described in the zshmisc man page, and the precmd hook in zshcontrib.

How can I change PATH variable in zsh?

I want to change my PATH variable in zsh.
Problem: I don't understand where in the .zshrc file I have to make modifications.
Normally, I would look for the assignment to the PATH variable and set the values from scratch how I would like them to be (leaving all the systems binaries directories untouched).
The first lines in my .zshrc file are as follows:
# If you come from bash you might have to change your $PATH.
# export PATH=$HOME/bin:/usr/local/bin:$PATH
# Path to your oh-my-zsh installation.
export ZSH="/Users/Sam/oh-my-zsh"
export PATH=$PATH:/Applications/Postgres.app/Contents/Versions/13/bin
etc.
My actual PATH variable is:
/Library/Frameworks/Python.framework/Versions/3.9/bin:/Library/Frameworks/Python.framework/Versions/3.8/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/Postgres.app/Contents/Versions/13/bin
I want to delete the directory where python3.8 is in, it's redundant.
My questions:
Do I have to change line 2 or line 7 in my .zshrc file?
Line 2 is commented out...is it executed anyway at the start of the terminal?
I have tried to comment out line 7. But the postgres directory still remained in my PATH variable which I don't understand.
The .zshrc is located in the home dir. The dot at the beginning keeps it hidden. Type ls -a from ~ directory to see it. To edit just run vim, nvim, etc as usual.
nvim ~/.zshrc
This is the command for Neovim. For your editor, sub nvim for the proper command.
Once you get in, you need only add the same export command that you would add from the command line.
export PATH=$PATH:/whatever/you/are/adding
EDIT
To remove a path variable:
First, run the command:
echo $PATH
from the command line.
Next, Copy the output to clipboard.
Finally, at the very end of the .zshrc file, add the following:
export PATH=<paste-what-you-copied-here>
Because you didn't reference $PATH after the =, this will set the path to EXACTLY what you pasted, no more, no less. Adding $PATH: as in the first example will just add whatever to the end of what is already there.
Since this gives you access to every item in the path array, deleting is just a matter of a literal highlight/select and of whatever you want deleted.
Finally, be sure that there is only one place in the file where you are editing PATH. If there are more than one, the result can be confusing to say the least.
That said, I believe the script runs top-to-bottom, so only the last mention should persist. You can take advantage of this in some situations, but for this purpose, one will suffice. XD
Be careful when you decide to fiddle with the PATH in .zshrc: Since the file is processed by every interactive subshell, the PATH would get longer and longer for each subshell, with the same directory occuring in it several times. This can become a nightmare if you later try to hunt down PATH-related errors.
Since you are using zsh, you can take advantage that the scalar variable PATH is mirrored in the array variable path, and that you can ask zsh to keep entries in arrays unique.
Hence, the first thing I would do is put a
typeset -aU path
in your .zshrc; this (due to mirroring) also keeps the entries in PATH unique. You can put this statement anywhere, but I have it for easier maintenance before my first assignment to PATH or path.
It is up to you to decide where exactly you add a new entry to PATH or path. The entries are searched in that order which is listed in the variable. You have to ask yourself two questions:
Are some directories located on a network share, where you can sometimes expect access delays (due to bad network conditions)? Those directories should better show up near the end of the path.
Do you have commands which occur in more than one directoryin your path? In this case, a path search will always find the first occurance only.
Finally, don't forget that your changes will be seen after zsh processes the file. Therefore, you could create a new subshell after having edited the file, or source .zshrc manually.

How get zsh prompt of form: [working-directory] # under macOS

In macOS Catalina (10.15.6), I want to use zsh for Terminal sessions. Formerly I had been using the default bash. For bash, I had a .profile containing the line
export PS1="[\u#\h:\w]$ "
which gave a prompt of the form:
[me#myhost:current-dir]$
I want something similar for zsh, but without the user-name#host-name prefix and with # instead of $ for the actual prompt.
In a zsh Terminal session, the command
PROMPT='[%/]%% '
gives the expected prompt, with the current directory enclosed in square brackets.
Of course I don't want to enter that manually each time. Instead, I want to set this in .zprofile. So in .zprofile I included the line
export PROMPT='[%/]%% '
However, that does not work as expected -- the prompt now has the form:
me#myhost current-dir %
Question: How can I get the zsh prompt to have the desired form as follows?
[current-dir] %
Just add the following export to ~/.zshrc, otherwise it won't work.
export PROMPT='[%1~] %%'
That will give you the following, my directory name is test-workflow-branch-only
[test-workflow-branch-only] %
NOTE: This will give you [~] % when in ~/ directory so don't be alarmed when you see that
UPDATE - per comment questions
We add it to ~/.zshrc as this file gets sourced in all interactive shell configurations. The file ~/.zprofile are for commands that we want to execute when we log in, therefore a non-login shell won't source this file.
Thanks for info from Edward Romero. My critique of answer is that it contains four wasted characters, '[',']',' ','%'. Using instead PROMPT='%d>' yields the nice clear absolute path, something like this:
/Users/myuser/test-workflow-branch-only>
In any case, nice to get this headache behind me, and begin reaping the wonderful benefits of using zsh, whatever they may be.

ZSH: Hide computer name in terminal

How would I hide the computer name in the prompt while using the terminal?
At the moment it shows both username and computer name like so:
It would save some space by removing anwarchoukah#anwars-mbp, seeing as I actually know who I am:)
Try to add export DEFAULT_USER=$USER to your .zshrc file
On MacOS 10.15 Catalina:
Open the file /private/etc/zshrc in a text editor
Locate the comment: # Default prompt
Modify the line that looks like this: PS1="%n#%m~ %& # "
Save the file. You will be prompted to enter a password to save it.
Load a new Terminal window.
For example, you can:
Remove "%n#%m" to get rid of both the username and computer name
Remove "%n" to get rid of the user name
Remove "%m" to get rid of the machine name
step 1. one your .zshrc file by vim .zshrc
step 2. go to end of your file.
Paste this code:
careful indent again your code
prompt_context() {
if [[ "$USER" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then
prompt_segment black default "%(!.%{%F{yellow}%}.)$USER"
fi
}
EDIT - explaining what this does
This will remove the machine#user name from the prompt IF:
- you are not logged in as the default user
- you are not in an ssh client shell
For most people, not needed, but if you regularly ssh to other machines and have multiple terminals open (eg remote sys admin type work) then this is extremely useful so when you look at your terminal you know which machine and user you are logged in as inside that terminal.
If you don't need/manage that type of complexity then use one of the other answers to just modify your export PROMPT/PS1 value.
* WARNING *
If you are using a custom shell or theme, this might not work and although the prompt will no longer show your computer and username it will keep throwing the error:
prompt_context:2: command not found: prompt_segment
For example, you can see with this (very popular) powerlevel9k it does not work. This is because the Powerlevel9k theme uses it's own magic and you simply add commands to your ~/.zshrc file to get the same result, eg:
POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(context)
More info on that here.
Open up .zshrc, find the line reading export PS1 or maybe export PROMPT.
Remove the variable that is used for the hostname, could be %m or %M.
Zsh on Archlinux wiki
You can use colors and also have a prompt (or some information) on the right side.
I like this approach (on my mac)
put in .zshrc
PS1="%n$ "
The terminal will look like
username$
Just add prompt_context() {} to .zshrc
Unfortunately none of the .zshrc changes worked for me.
Machine : Mac M1, Big Sur 11.4
So this is what worked.
I Navigated to where the ZSH themes were installed, opened my theme, agnoster in TextEdit, and modified the configuration where it chooses what do display, which by default is $username#%m.
Note : %m here is the machine name.
Here is a screenshot of delta. Yellow is what I did, Green is the default setting from github version of agnoster theme.
Voila this worked. Now to me it just displays the machine name, as I intended.
Hope that helps. Many links and SOF posts only made me click that solution.
Set DEFAULT_USER in ~/.zshrc file to your regular username. You can get your exact username value by executing whoami in the terminal.
Something like this:
export DEFAULT_USER=username
If you are using PowerLevel9k theme, there is a variable POWERLEVEL9K_CONTEXT_TEMPLATE that can change the view of your hostname and computer name.
The default option is %n#%m,
%n -> username
%m -> machine name
to hide hostname:
Open the .zshrc file using sudo nano ~/.zshrc
Add the line
POWERLEVEL9K_CONTEXT_TEMPLATE="%n" at the end of .zshrc file
Save the file.
Maybe this will help you [ Open Profile => Shell ]
PS1="~ $: ";clear;
Just add this to your ~/.zshrc file:
export DEFAULT_USER=\`whoami`
Install Oh My Zsh is the easiest solution for me:
https://ohmyz.sh/
One liner install:
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
Result:
If you're using Powerlevel10k, then you can run p10k configure and configure the output a bit.
My username and computer-name was gone after having gone through it. It feel less hacky, than the other solutions here.
I don't know why I can't find a simplified solution.
So here is the simplified one.
Just jump into the themes directory,
# ~/.oh-my-zsh/themes
Select the theme, as I have been using
# vim agnoster.zsh-theme
Just remove %m to remove and also you can remove the username too.
Once done,
Just run
#zsh
To reflect the changes, Enjoy :)
Thanks to Wes Bos' amazing video series Command Line Power User , I managed to find the answer.. It's pretty simple. Stuff like that is set in the ZSH theme.
Open up .zshrc, change the theme from ZSH_THEME="agnoster" (which is what I was using) to something else.
Wes Bos has made a lovely theme called Cobalt2 which does exactly what I was looking for :)
I've now changed it to ZSH_THEME="cobalt2"

Setting path in bash_profile

Why does setting a PATH require the :${PATH} at the end?
PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}"
When I append a path to this I would do
PATH=$PATH:...
How do I append a PATH without going to a new line. That is, how would I append a PATH to the original PATH statement.
If I wanted to put the following all in the first line, for instance. How does this interact with the :${PATH} part?
PATH=$PATH:/usr/local/mysql/bin
There's a difference between appending an existing path to the front or the end of the $PATH environment variable. The way bash resolves execution paths is by starting from the front of the list. That means if you have these two directories in your path:
PATH="/dir1/bin:/dir2/bin"
And they both have the executable test.sh in it, then when you run test.sh, it'll execute the one in /dir1/bin/test.sh since that directory appears first in the path.
Additionally, ${PATH} is the same as $PATH.
PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}"
is simply adding /Library/Frameworks/Python.framework/Versions/2.7/bin to the front of the path and
PATH=$PATH:/usr/local/mysql/bin
is simply adding /usr/local/mysql/bin to the end of the path.
So how do you do both in one line? Something like this:
PATH="/Library/Frameworks/Python.framework/Versions/2.7/bin:${PATH}:/usr/local/mysql/bin"

Resources