YAT*SH - yet another terminal *sh setup
Tags: zsh, terminal, productivity, mac
Published: 2020-05-02 15:40:04

Terminal setup is a really first thing that gives you real dev powers.
> Once you get it right and comfortable for your workflow, you'll love what you do even more.

I remember on my first setups I've tried a lot of different things, I've tried to make my terminal perfect. It took so much of my time, I can't even imagine. Spotting yourself?

After all, it was a great investment in my dev machine setup and in my opinion - most impactful. I'm trying to use new things once they come (sure you do that as well). And here I'd like to share my setup I'm happy with - didn't change for a while now - so you could play with all that on your machine as well!

> So if you are looking for some quick setup or just for some toolset - you are in right place.
> By the end of this article we will have complete setup with lots of fine tools and ready to smash it terminal.

P.S. Important note, that working on mac, made the most meaningful impact on me. So all the next notes are applying mostly to that OS, though with the latest terminal improvements on windows/ubuntu/whatever you should be able to set up something similar.

**Outline - What's inside**

* Terminal
* Shell
* Pure Prompt Theme
* Font
* Autojump
* Completion
* Syntax Highlighting
* Search back in history
* Howdoi
* Lazydocker
* Dive
* Alias
* Useful commands

A lot of things to cover, so let's get started.


# Terminal

![Hyper](https://dev-to-uploads.s3.amazonaws.com/i/rc30yer9cpk3zmm7b8j2.png)

## Hyper / ITerm2

[Hyper](https://hyper.is/) is a rockstar here for me. One of the Zeit(Vercel) team products. No pressure on iterm2 users, it's handy and stable.

Hyper was the first app I saw built with the electron. That was so powerful mindset changer so I've started using it. Style changes made with simple CSS changes 🤯. Plugins installed with similar to npm package manager - hpm. It's so easy to use I've stopped worrying about anything related to the terminal app itself.

In any case, you prefer hyper or iterm2 - don't use default mac terminal, save your time.

---

## IDE Terminal

Also on my experience a lot of people are using the IDE terminal for running scripts, it is also fine if you like that way. Having code and runners in 1 place is handy.

I've stopped using any terminal in IDE as I like to separate concerns even if it makes me go to another window.

> So as a small summary to this section - do terminal things wherever it suits you. 99% of configuration comes from Shell and available in any up to date terminal.

# Shell

For the shell, I'm fan of [zsh](https://ohmyz.sh/). 'Oh my zsh' to be specific as the framework for managing configuration. Now it comes as default for mac so you don't need to waste your 5 minutes on this. Plenty of plugins, customizability is what you expect from the brilliant shell - zsh.


# Plugins

The true power that doesn't need a lot of responsibility from you.

It is quite easy to install plugins for zsh usually, you just put the name of the plugin in _plugins_ section inside of your configuration file. Some plugins are not that easy to install but Readme usually covering all cases how can you make that work.

## Appearance

Making terminal beautiful was really my first think of that ugly app that I had to use. It was a long way before I started to like the setup.

### Configuration

![zshrc example](https://dev-to-uploads.s3.amazonaws.com/i/3jmlf4na8j4zbk9kz25m.png)
As all of the configurations placed in `~/.zshrc` it is important you make it accessible for yourself.
I'm splitting it into different sections divided by lines for easier determination for the next change. Usually, I'm adding all new things there manually so for me it is a good practice to keep that clean.

### Theme

![pure](https://dev-to-uploads.s3.amazonaws.com/i/rktpqslsl13k4z790chf.png)
There are themes that you can install already prebuilt in zsh. I didn't find "my theme" there until I met... `pure prompt` 🌟 Definitely my winner here, minimal, with all needed information.

Prompt gives lot of brilliant stuff of the box like:

- shows git branch and status ✅
- shows if your last command successful or not ✅
- shows the command execution time ✅
- shows current path ✅

All needed docs in their [github repo](https://github.com/sindresorhus/pure).

---

Even untouched it is gorgeous. Though as they are saying, it _makes an excellent starting point for your own custom prompt._

I've added to it 2 tweaks:

- Current time at the start of the line
  - The time when a command started. Sometimes it is nice to have timestamp when the last command started.

- Random emoji
  - Never know what is waiting for you in the next tab.

And now it looks like this:
![Updated pure](https://dev-to-uploads.s3.amazonaws.com/i/jmoxq9j4mq33ga68nro4.png)

Here is the configuration I've used:


```sh
# locale fixes
export LANG=en_US.UTF-8
export LC_CTYPE=en_US.UTF-8

ZSH_THEME=""

autoload -U promptinit; promptinit

# optionally define some options
PURE_CMD_MAX_EXEC_TIME=10

prompt pure
# customisation
# icons
OUTLINED_TRIANGLE_PROMPT='â–³'
FILLED_TRIANGLE_PROMPT='â–²'
SMALL_ARROW_PROMPT=$'\U203A' # small
BIG_ARROW_PROMPT=$'\U276F' # big
# time + emoji + triangle
PROMPT='%F{white}%* $(random_emoji)  %(?.%F{magenta}$BIG_ARROW_PROMPT.%F{red}$BIG_ARROW_PROMPT)%f '
```

There are a bit more icons than my current setup uses, previously I've used _Outlined/Filled_ triangles combo. But now I'm switched to a standard arrow with emoji.

To make it work - check you've added [emoji plugin](https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/emoji) so `random_emoji` function works. As an alternative, you could use single emoji with syntax like `$emoji[mouse_face]`.

---

As Michael suggested in the comment there is an outstanding prompt - [starship](https://starship.rs/).

It comes with a lot of defaults and really worth considering for your setup. It definitely wins on pure as there is an inbuilt way to configure displays around what's inside a directory.

---

Just one more great theme - [powerlevel10k](https://github.com/romkatv/powerlevel10k).

Super configurable, you even can create `pure` from it!

### Font

![font](https://dev-to-uploads.s3.amazonaws.com/i/70wfu661qo9yi998pvt4.jpg)

It is important to have good looking font on any app you are using. More to this it should also support last features like ligatures. Hyper is supporting them through the plugin [hyper-font-ligatures](https://github.com/tolbertam/hyper-font-ligatures) but the list of fonts they support isn't a long one.

That solution works with a few workarounds (like WebGL disable on hyper v3) to a font like [Fira Code](https://github.com/tonsky/FiraCode). I've used it for a while but recently switched to more elegant in my opinion - [Operator Mono Lig](https://github.com/kiliman/operator-mono-lig). It is a standard operator mono but with the addition of ligatures.

So for now my list of fonts looks as next array:

```js
fontFamily: "'Operator Mono Lig', 'Fira Code', 'Fira Code iScript', Menlo, Monaco, 'Courier New', monospace",
```

### Tab layout

Usually, my workflow needs 3 or 4 terminal screens simultaneously. To keep them tidy I'm splitting a window into squares with `CMD-D` and `CMD-SHIFT-D` commands. For one tab. Once you need another one you are going with a new tab and arranging it again.

![Usual tab layout](https://dev-to-uploads.s3.amazonaws.com/i/at5n3updsp2kjfd1skfb.png)

With iterm2 I've used layout presets, but that didn't give me that much of help. With Hyper you can use something like `hyperlayout` if you want to start your layout in 1 command.

## Productivity

### j - [autojump](https://github.com/wting/autojump)

**THE MOST PRODUCTIVE PLUGIN YOU NEED.**
![autojump](https://github.com/icrosil/YAT-SH/raw/master/clips/autojump.gif)

You visit folders, `j` will recognize it and keep track where have you been. Once you put `j fold` it will fuzzy-find the most relevant folder and instantly change your location.
No more `../../../../`.

It also adds extra commands:

- `jc` - Jump into Child directory from current
- `jo` - Jump and Opens in finder instead of going there.

### right-arrow completion

![right-arrow](https://github.com/icrosil/YAT-SH/raw/master/clips/right-arrow.gif)

Ever had a command that you run 1 time per month?
Remember that it starts with `ssh...`?
Alright, this one is for you. [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions)

It will add the last command that starts with your input to a command, with the right arrow you could expand it.

### autocompletion

A handful for some commands. I cannot say it helps a lot, but I do like yarn completion, docker.

I'm using plugins `zsh-completions`, `yarn-completion`, `git flow completion`. To install them it is usually enough to add it to the plugin section.

Hit tab on the start of a needed command, that's it.

### same directory

![same-directory](https://github.com/icrosil/YAT-SH/raw/master/clips/same-directory.gif)

[hypercwd](https://github.com/hharnisc/hypercwd)
The first plugin I've felt in love is the same directory on the new tab or split.
In combination with `j`, it's just so fast.
There are plugins for zsh by itself but I'm happy with hyper plugin `hypercwd`.

### syntax highlight

![highlight](https://dev-to-uploads.s3.amazonaws.com/i/mufeh8s3xfrcsx0063st.png)

Scientifically proven eyes identifying elements much faster if they have different colors. This principle used to help you categorize code as well. A good theme for your IDE or Editor would increase your efficiency significantly. Same works for a terminal even if you don't code inside of it. Let your eyes help you identify what is important on your screen.

I'm using plugin `zsh-syntax-highlighting`. And some defined I've grabbed from `hyper-snazzy` colors to meet better contrast:
```js
const foregroundColor = 'white';
const backgroundColor = 'black';
const red = '#ff5c57';
const green = '#1CB88B';
const yellow = '#FDB92C';
const blue = '#57c7ff';
const magenta = '#ff6ac1';
const cyan = '#9aedfe';

module.exports = {
  config: {
    backgroundColor,
    foregroundColor,
    borderColor: '#222430',
    cursorColor: magenta,
    cursorAccentColor: backgroundColor,
    selectionColor: 'rgba(151, 151, 155, 0.2)',
    colors: {
      black: backgroundColor,
      red,
      green,
      yellow,
      blue,
      magenta,
      cyan,
      white: 'white',
      lightBlack: '#686868',
      lightRed: red,
      lightGreen: green,
      lightYellow: yellow,
      lightBlue: blue,
      lightMagenta: magenta,
      lightCyan: cyan,
      lightWhite: foregroundColor
    },
  },
};
```

### corrections

![corrections](https://github.com/icrosil/YAT-SH/raw/master/clips/corrections.gif)

I'm making typos every day with my terminal, it's usual for me to type `ayrn` or `got`. Got bless corrections.

Fortunately, we have in build command to save our fingers
`setopt correct_all # autocorrect commands`

**Bam 💥**

This option is working with 90% but if you want to express yourself more... natural. - `f*ck` is your choice.

Run a typo command -> run `fuck` -> it will rerun your previous command with the fix.

### search back in history

Ever had a command that you run only once, 2 years ago, pasted from the internet? Don't remember what was the command but starts with `ssh...`?

Wait. We already have `right-arrow` completion why we need something different?

`right-arrow` works great if you start typing and want it to finish command for you, but what if you remember only the middle part of a command, or last?

In `CTRL-R` should you trust. There is a built-in bash reverse-i-search which allows you to filter and find your previous command by inputting your search and `CTRL-R` to show the previous match.

One handy addition to that is the next bind
`bindkey '^[[A' history-substring-search-up`
It allows you to do the same with typing part of a command and clicking up to show the previous match.
A M A Z I N G.
`bindkey '^[[B' history-substring-search-down`
for search down.

### Howdoi

![howdoi](https://github.com/icrosil/YAT-SH/raw/master/clips/howdoi.gif)

Do you remember the feature of google `I'm feeling lucky` that gave you first found result, that should be more relevant?

[This is exactly it but for code](https://github.com/gleitz/howdoi). It usually gives pretty correct answers to frequently asked questions. One caveat - you have to ask your questions as simpler as possible. On my experience, it is working much better if specifying language or a tool.

- howdoi stop all containers docker
- howdoi uppercase python
- howdoi copy directory bash

### Lazydocker

![lazydocker](https://github.com/icrosil/YAT-SH/raw/master/clips/lazydocker.gif)

Getting to know each docker command is great if you are DevOps. Though for front devs especially that might be nontrivial. I've used to google major commands I needed for docker or docker-compose before I remembered a significant part of them.

But then a friend gave me [this link to a docker tool](https://github.com/jesseduffield/lazydocker). And that changed a lot of how I started to work with docker. Small inline docker tool is good for day to day things. To me, it is much smoother than VScode docker plugin or kitematic.

### Dive

![dive](https://github.com/icrosil/YAT-SH/raw/master/clips/dive.gif)

[Another tool for docker](https://github.com/wagoodman/dive), but more specifically to see what's inside and how layers built. Way back when I was investigating why my image with nodejs API was too big that tool helped me see that I've installed node modules twice, in my folder and yarn global cache.

### Alias

Aliases are just shortcuts for long commands.
A brilliant idea of a shortcut born in your head? That's the time you need to put it in alias and start saving your 5 sec times in the future.

As a tip for aliases, once you are tired to type a few words for git/docker/npm/bash - it's time to make an alias. Be lazy. Be smart.

Adding aliases is that easy:

- open sh file configuration with your text editor like `code ~/.zshrc`
- find a place for new alias within your alias section
- name it - `alias NAME="COMMAND"`
- reload your terminal with `source ~/.zshrc` or opening new tab

Here is my list:

```sh
# git-flow
alias git_cbr='git symbolic-ref --short -q HEAD | cut -f2 -d"/"'
alias gffp='gfl feature publish $(git_cbr); ghpr'
alias gffs='gfl feature start'
# git
# I'm using safari by default but you can change this to chrome
# This alias is usefully opens new PR in browser on publishing
alias ghpr='/usr/bin/open -a Safari "https://github.com/icrosil/$(pwd | xargs basename)/compare/feature/$(git_cbr)?expand=1"'
alias gbruu="git branch --unset-upstream"
alias gdfsh="git diff --shortstat develop HEAD"
alias gcp="git cherry-pick"
# docker
alias dkc="docker-compose"
# yarn
alias y="yarn"
alias yi="yarn install"
alias ya="yarn add"
alias yad="yarn add --dev"
alias yga="yarn global add"
alias yr="yarn run"
alias yre="yarn run example"
alias ys="yarn start"
alias yis="yarn install && yarn start"
alias yt="yarn test"
alias yit="yarn install && yarn test"
alias yl="yarn link"
alias yu="yarn unlink"
# chrome
alias purge-idb="rm -rf ${HOME}/Library/Application\ Support/Google/Chrome/Default/IndexedDB/*"
# functions
function take() {
  mkdir $1 && cd $_;
}
```

Most useful from the list:

- `gffp` - publish feature and open in browser
- `yr` - run npm script in a directory. Yes you can run script with just yarn command, but with this shortcut I'm actually getting autocomplete for available commands in repo!
- `dkc` - just can't do docker compose without it
- `take` - mkdir and cd into
- `...` - go up 2 level, `....` - 3 levels and so on
- `cd +2` - go up 2 dirs 

### Extra useful commands

- `lsof -i :port` - check if port occupied. Handy to kill some process blocking your app.
- `cat index.js` - log a file to a console. Especially helpful for small files that `should have one line of code you need`.
- `some_command | grep text` - will show lines where text found. When dealing with a lot of logs neat command.
- `code ~/.zshrc` - open file in vs code editor. To enable this thing you need to follow [these steps](https://code.visualstudio.com/docs/setup/mac)
- `rm -rf ./node_modules` - when nothing else helps.
- `kill process_id` - kill hang process
- `kill -9 process_id` - terminator mode
- `kill -9 $(ps aux | grep 'text' | awk '{print $2}')` - finding process and kills it, worth to put in alias though
- `touch file.txt` - creates file in a command line
- `mkdir dir_name` - creates a directory