Weird Color Stuff In The Terminal
Tags: terminal, cli, color
Published: 2024-01-01 20:14:00

---
title: Weird Color Stuff In The Terminal
published: true
description: Some strangeness encountered doing some stuff with color in the terminal.
tags: terminal,cli,color
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uwgviuz4b294mlxvii50.png
published_at: 2024-01-01 20:14 +0000
---

I recently got a new mac mini (not the latest and greatest, but plenty for my needs) and my intention is to use it for dev. Something I like to do is setup the terminal so that when  I start a new session I get a little quote from [Oblique Strategies.](https://en.wikipedia.org/wiki/Oblique_Strategies)

There's lots of implementations for this existing in the wild, from the very old unix command [fortune](https://linux.die.net/man/6/fortune), to sundry [web](http://obliquestrategies.ca/) [apps](http://stoney.sb.org/eno/oblique.html), to [stuff written in modern languages](https://github.com/nessieSnippets/oblique-strategies). But, I wanted to diy the solution.

I had just gone through [a fun tutorial](https://www.youtube.com/watch?v=wNQpDWLs4To) for setting up [oh-my-zsh](https://ohmyz.sh) with a nice color scheme from [iterm2colorschemes.com](https://iterm2colorschemes.com) and [a decent prompt](https://github.com/romkatv/powerlevel10k) and I was wondering: can I make my oblique strategy look nice? how can you actually use the colors from your scheme in the output in your cli?

##Terminal Color Basics.

The first clue for how to make your cli text output more colorful comes from the image defining the color scheme that you get from [iterm2colorschemes.com.](https://iterm2colorschemes.com) Here's the one for the scheme   Peppermint.

![Peppermint iterm2 color scheme](https://raw.githubusercontent.com/mbadolato/iTerm2-Color-Schemes/master/screenshots/Peppermint.png)

Something you might notice is that there are things like `4dm` along the top, and like `(1;)?3dm` off to the left of the table. And that's what this image is, its a table of all the possible text and background color pairs and how they look. But how do you use them?

The answer is an escape sequence. Try something like
```zsh
echo '\e[1;35;47m walrus'
```
in your terminal. You should have the word 'walrus' with a preceeding space written in some fancy colors. Play around with different digits where the `5` and `7` are. Delete or include the `1;`. Neat!

Of course, the colors will be from your color scheme, either the default, or from whatever scheme you've installed (that tutorial I linked above is super clear about how to do this).

If you're like me and you take your code looking like line noise as a code smell, you might want to try something a little more readable.
```zsh
tput setaf 13; tput setab 7; echo ' walrus'
```
That should look the same as what you got from my earlier echo command. `;` runs the command but doesn't append a new line to the output. `setaf` is 'set as foreground' and `setab` is 'set as background'. The 13 is 8+5: the 5 selects the base color, adding 8 brightens it (like using `1;` did in the escape sequence). Like the table shows, there's 18 permissible foregrounds, and 10 permissible backgrounds. I'll let you work out how to get them all.

##Strange state

So, I learnt this after some googling and stack overflow and looking at man pages for `tput` and `terminfo` and was feeling pretty good, but I wanted the background color to stretch to the end of the line, and for there to be colored lines above and below my one line quote. I reasoned some newlines would do the trick and ended up with something like
```zsh
tput setaf 11; tput setab 4; echo "\n\n\t"walrus"\n"
```
and it worked! So I put it at the top of my `.zshrc` (because other stuff complained if I put it at the bottom) and when I `source .zshrc`'d it worked! And when I opened a new tab it didn't work!

What the hell? I went backwards and forwards with it a few times, and had a tab where sourcing the file worked, with the background color extending all the way to the ends of my empty lines and the line with text, and another where the color only covered the tab and the word 'walrus'.

This felt pretty crazy at the time. Somehow, the other stuff I was doing in the terminal, like editing files and resizing windows, was occasionally creating persistent state that was telling the terminal to use the background on the full line. And I wasn't alone in seeing [this weird behaviour.](https://stackoverflow.com/questions/19915208/extending-terminal-colors-to-the-end-of-line)

The accepted answer at that link talking about using an escape sequence to clear to end of line was good. I just defined `\x1B[K` as a variable and liberally sprinkled it in my output, and was finally seeing what I wanted. But I didn't like using `tput` for some escapes and the raw sequence for others. `tput el` was my friend (found on the man page for 
`terminfo` after searching for the word 'clear').

##Getting a random line from a file

Long story short on this one, the code ended up looking like
```zsh
CLREOL=$(tput el)

oblique_line_no=$(( RANDOM%$(wc -l oblique.txt | awk '{print $1}') + 1 ))
oblique_line=$(sed -n ${oblique_line_no}p oblique.txt)

tput bold; tput setaf 11; tput setab 4; echo "\n${CLREOL}\n${CLREOL}\t"$oblique_line"${CLREOL}\n${CLREOL}"
echo
```
To decompose that a bit:
* `RANDOM` makes a random number
* `$((...))` evaluates arithmetic, with `%` doing mod
* `wc` will count lines of a file, but you need to trim the output a bit (the pipe into `awk`)
* `sed` has a one liner to print just one line of a file.

##Takeaways

Firstly, if you're going to dev, you'll spend some time on your command line, maybe even a lot. Make it something you like. I really love the off kilter suggestions from oblique strategies, you might love some ascii art, or a really stripped down experience. Whatever you want, make the terminal your own.

Secondly, test your code. I would never have seen that weird behaviour if I wasn't testing my code to see what it would do in a variety of circumstances, or rather, I would have stepped away thinking the problem solved, only for it to rear its head when I next opened a terminal.

Finally, don't give up! If there's an effect you want to achieve, the tools are almost certainly out there waiting for you to learn about them.

PS `touch .hushlogin` to remove the 'last login' stuff from your osx terminal. [Concise articles are great!](https://medium.com/macoclock/how-to-remove-the-last-login-prompt-from-iterm-terminal-on-macos-8d70dea0f2e)