How do I make the Terminal easier to read and mentally process?

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.


Solution 1:

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} %# '

Solution 2:

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.

Solution 3:

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)

Solution 4:

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.