3

I am beginning to learn to use the shell via macOS's Terminal running Zsh, and I'm finding it difficult to process all of the very tightly packed information in the commands and results.

What are the most common ways to maximize intelligibility in the shell/Terminal?

Two specific customizations I know I'd like to try:

  1. How would I set up the shell to always include an extra line or a horizontal rule after each command has finished, to visually separate each command from the previous?

    • From this answer, I ran PS0="\n", which did nothing.
    • From this answer, which took me here, I ran vi .bash_profile from the home directory, which caused my Terminal to freak out with a bunch of lines of just ~ over and over again, so I aborted that.
  2. Is there a way to customize the way paths are displayed? e.g. Instead of path/name/example, perhaps path > name > example? For very long paths with spaces in directory names, this would increase legibility to include space between each level.

1
  • Apple switched to zsh from bash as the default shell fairly recently, so a lot of what you'll find is out of date and assumes bash. With zsh, use ~/.zprofile instead of ~/.bash_profile and ~/.zshrc instead of ~/.bashrc. And there are plenty of other differences... BTW, I'd recommend nano instead of vi as an editor; it's way less confusing. Sep 14 at 6:59
2

Note that zsh is different from bash. Their scripting languages are similar (but they do have a few important differences), but the way most interaction features are configured (initialization files, prompt, command history, key bindings, etc.) is very different. Generally speaking, if you're using zsh, ignore configuration advice about bash (and vice versa).

The main configuration file for zsh is .zshrc in your home directory. Zsh reads it when it starts (only when it's running interactively in a terminal, not when it's running a script). This is the place to configure prompts, completion, aliases, key bindings, etc.

I ran vi .bash_profile

vi is a text editor which is absolutely not newbie-friendly. Whenever you see instructions to use vi, take it as “edit this text file”, and feel free to use any text editor you like.


How would I set up the shell to always include an extra line or a horizontal rule after each command has finished, to visually separate each command from the previous?

The text that the shell displays before the command that you type is called the prompt. The basic way to configure the prompt is through the variable PS1. The content can be very complex, taking advantage of prompt escape sequences and more. There are whole frameworks that make it easier to customize the prompt, including a built-in prompt theme facility as well as many third-party frameworks.

For something simple like displaying a blank line before each prompt, it's easy to do manually. Put this line in your .zshrc:

PS1=$'\n'$PS1

What this means:

  • PS1=… is an assignment. It changes the value of the variable PS1 to what's on the right of the equal sign.
  • $'…' is one of several forms of quoting. Inside $'…', the backslash character allows you to specify non-printing characters, like with echo. \n stands for a newline character.
  • $PS1 takes the current value of the variable PS1.

Note that this adds a blank line each time you run the command, so if you run it twice, you'll get two blank lines.

Is there a way to customize the way paths are displayed?

If you mean changing the way the current directory is typeset in the prompt, then yes, because you can run arbitrary code to choose what goes into the prompt. I wouldn't recommend it, however, because you can't customize the way paths are presented in other places, and you can't type paths in another way. Note also that anything you do there is likely to interfere with other prompt customizations.

I'm going to assume that you've customized your prompt manually, by setting PS1, and that you use the %~ prompt escape sequence to have the current directory in the prompt with ~ standing for your home directory.

Enable the prompt_subst option. This lets you use variables inside the prompt specification. For example, the following snippet in .zshrc causes the prompt to display the current directory and % (or # for the root user), similar to PS1='%~ %# ':

setopt prompt_subst
PS1='${(D)PWD//\%/%%} %# '
  • We assign to the prompt with PS1='…'. Everything inside single quotes is interpreted literally: no expansion takes place, so the value of PS1 is the 13-character string ${PWD//\%/%%}. We do this so that ${PWD//\%/%%} is evaluated each time the prompt is displayed (in contrast, PS1=${PWD//\%/%%} would set PS1 once and for all based on the current directory at the time of the assignment).
  • The PWD variable contains the full path to the current directory. Zsh updates it automatically whenever the current directory changes. $PWD or ${PWD} is the value of the PWD variable.
  • ${(D)PWD} applies the parameter expansion flag D to the value of PWD. The effect of this flag is that if the path starts with your home directory, it's replaced by ~. This is similar to what %~ does.
  • ${VARIABLE//…/…} is a form of parameter expansion that replaces one string by another in the value. Specifically, we use ${(D)PWD//\%/%%} which replaces every % by %%. The backslash before the left-hand % is necessary because a bare % in this position would have a special meaning. We do this because with prompt_subst enabled, the values of variables used in the prompt are themselves subject to prompt expansion, i.e. if they contain a % character, it starts a prompt escape sequence. So PS1='$PWD' would do strange things if the path to the current directory happens to contain %.

Now we can build on this to change how the path is displayed. The following snippet uses the %B and %b prompt expansion flags to cause slashes in the path to appear in bold. We use another ${…//…/…} replacement, this time to replace / by %B/%b (start bold, /, stop bold).

setopt prompt_subst
PS1='${${(D)PWD//\%/%%}//\//%B/%b} %# '
6
  • Thank you so much for this god-like answer. I'm slowly working my way through all the info people have given, and am currently hitting these snags:
    – etudes
    Sep 19 at 7:31
  • 1) some people mention to use .zlogin and some .zshrc. Can you configure the prompt in either, and why choose one or the other?
    – etudes
    Sep 19 at 7:31
  • 2) Neither .zshrc (nor .zlogin) exist in ~, not even as hidden files. Is that correct, and I need to create them myself? In which case, would your method of choice be nano for that?
    – etudes
    Sep 19 at 7:32
  • @etudes Putting interactive settings such as the prompt in .zshrc always works, because zsh reads .zshrc when it runs interactively. Zsh reads .zlogin when it's a login shell, which is the case when it's started by a macOS terminal, but is not the case in other circumstances such as running on Linux, or running zsh inside another shell, etc. Putting prompt settings in .zlogin has no advantage. It's normal for .zsh* files not to exist initially, just create them when you have to put something in it. Sep 19 at 20:22
  • Got it, thank you. Next snag: why is $PS1 in your example PS1=$'\n'$PS1 not causing a feedback loop, seeing as I'm setting the value of the PS1 prompt and referring to itself within that value?
    – etudes
    Sep 19 at 21:37
1

First off, prefer nano or your favourite GUI text editor instead of vi. nano ~/.zprofile or open ~/.zprofile -a TextEdit. Sublime Text and VSCode have command line tools which you can add to your PATH and subl ~/.zshrc becomes less scary.

https://stackoverflow.com/questions/11828270/how-do-i-exit-the-vim-editor

From this answer, I ran PS0="\n", which did nothing.

With ohmyzsh, I kept changing themes (in ~/.zshrc) until I found the right one: ZSH_THEME="garyblessington". Then got the current PROMPT: echo ${PROMPT}. And modified it to suit my liking and added it to ~/.zshrc:

export PROMPT='%{$fg[cyan]%}%c%{$fg_bold[blue]%}$(git_prompt_info)%{$fg_bold[blue]%}% %{$reset_color%} $'

There are some online PROMPT editors too that can help you visualize it or tell you which pattern to use to get, say current time.

For readability, try changing colors, font size and contrast in the Terminal Preferences.

1
  • If you are begging shell programming stay away from oh-my-fish it hides things away for good reasons and ease of use but not ease of understanding - you have to start looking at its code and there is probably too much to take in at once.
    – mmmmmm
    Sep 14 at 10:18
1

As noted this are many things to follow.

For the default shell in recent macOS, zsh, the authors supply good documentation.

See https://zsh.sourceforge.io/ for all of it.

Start with the User guide https://zsh.sourceforge.io/Guide/zshguide.html

Note however for $PATH Apple have not read the documents and have made a change so that you need to edit $PATH in .zshrc not .zshenv as stated in the zsh manual and user guide (path_helper is called in /etc/zshrc after .zshenv is called)

1

This is really in addition to the other answers, which have great info, and not a perfect answer in itself.

Try Starship - https://starship.rs/

It's a new prompt tool that the shell calls, and has some great options, including good defaults.

One of the first config examples they give is adding new lines - FYI. The following entroies are the the configuration file for starship - usually ~/.config/starship.toml You will first need to edit your zsh startup files as noted in the installation instructions.

# Inserts a blank line between shell prompts
add_newline = true

And, the direction option allows for automatic truncation: https://starship.rs/config/#directory

[directory]
truncation_length = 8
truncation_symbol = "…/"

You'll also want to follow some other advice and do things like get some nice powerline fonts, get a nice color scheme (personally I like Solarized), and maybe try iTerm as well.

1

There are some great general answers, but here's a specific suggestion: use reverse video for the prompt.

For zsh, add something like this in your .zlogin file:

export PS1="%S%~>%s "

PS1 is the shell variable used to generate the prompt.  %S and %s set and clear reverse video.  (They should work for all terminal types.)  The part between shows the current directory, followed by >; tweak that if you want the hostname, name of the shell, and/or anything else; see some of the other answers and their links.  (The format is specific to zsh; there are equivalents for other shells.)

That makes prompt lines stand out very clearly to me — without taking any more screen space, or adding too much visual ‘noise’.  (And it's easy to tweak — for example, you can change the colour as a visual reminder when you're root or on a production server.)

I've used this sort of prompt on many different machines for decades — I can't see why it's not standard :-)

1
  • This is so brilliant, thank you. Looked into it, and I guess Zsh calls it "standout mode".
    – etudes
    Sep 21 at 6:52
0

You can customize the shell prompts in almost arbitrary ways, add newlines, format the path in different ways, print additional informations like the Git status, etc. pp.

But it's a vast topic that can fill a book.

Since you mentioned zsh, a popular package for that shell is oh my zsh which provides a lot of plugins for different tasks. And there are a lot of themes with screenshots available, some of them do format the path in a different way by default, similar to what you have in mind. Be aware that some of these themes require to have a Powerline font installed and selected in your terminal to render correctly.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .