Improving the terminal experience on Windows

DEVELOPMENT -️ June 15, 2022

My take on The Windows Terminal experience

Some of you might wonder what is wrong with the Windows Terminal experience. Let me tell you a story.

Let's go back in time to where I was a wee junior developer. I was learning how to use git using the command line. I found myself spamming git status trying to understand what I was doing and felt it was quite bothersome to do so.

Fast forward in time. Junior me trying to do basically anything on a unix based server and figuring out it's a whole different world out there in scary 'nix land.

Imagine there being solutions that let help you using git whilst also helping embrace that scary but sweet 'nix experience.

Different options

Windows Command Prompt

Windows Command Prompt, also known as CMD.

It is the defacto shell solution on Windows. It works well if you need to do simple routine operations, it will however disappoint you for your average day-to-day development tasks due to:

  • no visual git support*
  • being forced to use lackluster implementation of listing files called dir
  • limited options to use custom scripts at startup
  • no simple way to customize the colors without making your eyes bleed 😓
  • having to script using batch files*

PowerShell

PowerShell was supposed to fix some of the CMD shortcomings. In some ways it does, in others it does not. There is not doubt in my mind that PowerShell allows you to handle more complex operations and actions, but it seems like this introduced a hidden cost. With this added ability to execute these operations, the syntax complexity and verbosity absolutely skyrocketed. The commands you use in PowerShell to me look more like a programming language (a mix of a functional and object oriented one actually) than a scripting language, which is something I am personally not looking for. It feels even worse that I cannot even use these commands I spent time on learning in a unix environment.

I understand there are a lot of people that like and use PowerShell, and it's probably a great tool if you like the syntax and the problems it solves. It does however fall short for me due to the very nature of the tools provided by it as I was looking for a more 'unix-like terminal experience'.

If you like PowerShell and would like to spice up your experience, go take a look at Scott Hanselman's blog on how he set up PowerShell

Cmder

Cmder is a lightweight third party solution for console emulation on Windows. It comes packed with a plethora of configuration options for theming, shell choice, shortcuts, tab support, startup tasks and more.

Cmder has built-in visual git support and comes paired with a set of common auto-completion tools which will help you with your everyday development tasks.

Windows Terminal

The newest terminal emulation addition developed by Microsoft which also comes distributed with Windows 11 by default. Regardless of what you think of the Windows Terminal advertisement Microsoft placed on Youtube (seriously how did they expect this would attract developers?), Windows Terminal is a solid contender if you are looking for a certain amount of customization. It may not have as many configuration options as Cmder does, but it will probably fill most people's needs regarding shell management (switching between different shells), tab management, shortcut management, and theming. Some people might see this as Windows Terminal having a more focused and less option bloated approach.

My personal terminal setup

I am currently using Windows Terminal as my 'daily terminal emulation driver'.

As I was looking for a more 'unix-like terminal experience' my main usage resides in Git Bash. My setup current looks like this:

Current setup

Shell selection

Bonus raccoon ascii art

Several configuration options were customized:

  • I only have Command Prompt, PowerShell and Git Bash as shell options as I do not need anything else.
  • Git Bash is set as the default shell when opening the terminal or opening a new tab.
  • I have set a specific starting directory as I often need to access a git repository in this specific location.
  • I have set a custom color scheme named 'Tango Dark'.

    • If you want to find a color scheme that suits your needs I recommend looking at TerminalSplash
  • I'm using a Powerline-patched font called Jetbrains Mono NL.

    • You will need a Powerline-patched font if you want actually want to be able to read 👀 the git hints that a Powerline theme provides.
  • I'm using a Powerline theme which is referenced in my .bashrc.

    • The Powerline theme is what provides the addition git support hints.
  • I use lsd which is basically 'ls' on steroids.

    • You will probably need scoop to install lsd.
    • If you encounter problems with version 0.22 of lsd, try downloading the latest nightly from their GitHub workflow artifacts
  • I use bat 🦇 instead of cat 🐱 to view file contents quickly.

    • If you are looking for cat with better highlighting and scrolling features, you might as well give bat a go.
  • I use several completion scripts for tools I frequently use such as: bash, docker, docker-compose, kubectl, Azure CLI.

    • Do make sure to only use completion scripts you actually need. Adding these scripts penalize the startup time of your shell.
  • I load up some nice ascii art of a raccoon 🦝 when opening a new terminal tab.
  • I have some magic functions (__fastgit_ps1)🌈 to speed up Git usage done by the Powerline theme.
  • I have some aliases you probably do not want to copy 🐵, unless you fancy them.

Windows Terminal config 📝

You can edit the config file by going into the Windows Terminal settings (CTRL + ,) and pressing the 'Open JSON file' button.

{
  "$help": "https://aka.ms/terminal-documentation",
  "$schema": "https://aka.ms/terminal-profiles-schema",
  "actions": [
    {
      "command": {
        "action": "copy",
        "singleLine": false
      },
      "keys": "ctrl+c"
    },
    {
      "command": "paste",
      "keys": "ctrl+v"
    },
    {
      "command": "unbound",
      "keys": "ctrl+shift+t"
    },
    {
      "command": "find",
      "keys": "ctrl+shift+f"
    },
    {
      "command": {
        "action": "newTab"
      },
      "keys": "ctrl+t"
    },
    {
      "command": {
        "action": "splitPane",
        "split": "auto",
        "splitMode": "duplicate"
      },
      "keys": "alt+shift+d"
    }
  ],
  "copyFormatting": "none",
  "copyOnSelect": false,
  "defaultProfile": "{c3c26583-b525-43b5-a830-cab55baba518}",
  "profiles": {
    "defaults": {},
    "list": [
      {
        "guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
        "hidden": false,
        "name": "Command Prompt"
      },
      {
        "guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
        "hidden": false,
        "name": "Windows PowerShell"
      },
      {
        "colorScheme": "Tango Dark",
        "commandline": "\"%PROGRAMFILES%\\Git\\usr\\bin\\bash.exe\"  -i -l",
        "elevate": true,
        "experimental.retroTerminalEffect": false,
        "font": {
          "face": "JetBrainsMonoNL Nerd Font"
        },
        "guid": "{c3c26583-b525-43b5-a830-cab55baba518}",
        "icon": "C:\\Program Files\\Git\\mingw64\\share\\git\\git-for-windows.ico",
        "name": "Git Bash",
        "opacity": 90,
        "startingDirectory": "C:\\repositories",
        "useAcrylic": true
      }
    ]
  },
  "schemes": [
    {
      "background": "#002B36",
      "black": "#000000",
      "blue": "#424242",
      "brightBlack": "#555753",
      "brightBlue": "#E82D72",
      "brightCyan": "#E82D72",
      "brightGreen": "#2FEBC4",
      "brightPurple": "#AD7FA8",
      "brightRed": "#EF2929",
      "brightWhite": "#EEEEEC",
      "brightYellow": "#FCE94F",
      "cursorColor": "#FFFFFF",
      "cyan": "#37FFB5",
      "foreground": "#FAFFF6",
      "green": "#B0D700",
      "name": "Tango Dark",
      "purple": "#75507B",
      "red": "#FF5C5C",
      "selectionBackground": "#FFFFFF",
      "white": "#D3D7CF",
      "yellow": "#C4A000"
    }
  ]
}

The .bashrc magic 🎆

# Theme
THEME=$HOME/.bash/themes/git_bash_windows_powerline/theme.bash
if [ -f $THEME ]; then
   . $THEME
fi
unset THEME


# Simple PS1 without colors using format arg. Feel free to use PROMPT_COMMAND
export PS1="\u@\h \w \$(__fastgit_ps1 '[%s] ')$ "

# 100% pure Bash (no forking) function to determine the name of the current git branch
function __fastgit_ps1 () {
    local headfile head branch
    local dir="$PWD"

    while [ -n "$dir" ]; do
        if [ -e "$dir/.git/HEAD" ]; then
            headfile="$dir/.git/HEAD"
            break
        fi
        dir="${dir%/*}"
    done

    if [ -e "$headfile" ]; then
        read -r head < "$headfile" || return
        case "$head" in
            ref:*) branch="${head##*/}" ;;
            "") branch="" ;;
            *) branch="${head:0:7}" ;;  #Detached head. You can change the format for this too.
        esac
    fi

    if [ -z "$branch" ]; then
        return 0
    fi

    if [ -z "$1" ]; then
        # Default format
        printf "(%s) " "$branch"
    else
        # Use passed format string
        printf "$1" "$branch"
    fi
}

alias ls="TERM=dumb lsd"
source ~/bash_completion.d/bash_completion
source ~/bash_completion.d/docker-compose
alias python='winpty python.exe'
source ~/bash_completion.d/git
source ~/bash_completion.d/kubectl
alias az='az.cmd'
alias jq=~/jq-win64.exe
alias bat=~/bat/bat.exe

cat ~/raccoon

Greater things to come?

As always in development, there's some new stuff on the horizon. Things I will be looking at in the near future:

  • starship is a Rust-based cross-shell prompt.
  • Fig has crazy looking auto complete features, but is not ready for Windows yet.
  • Alacritty is a cross-platform OpenGL terminal emulator that looks like a real contender.

Do you know an upcoming tool or piece of tech I should be looking at? Let me know below!

Initializing...