/macos-dotfiles

:round_pushpin: My dotfiles for macOS using Neovim, Zsh or Fish, and Kitty or iTerm+Tmux

Primary LanguageShellMIT LicenseMIT

My Dotfiles for macOS

dotfiles screenshot

🤩 Highlights

🗂️ Table of Contents

⚡️ Quick Setup

Make sure macOS is up to date and you have installed the required software.

Clone this repo.

git clone https://github.com/joshukraine/dotfiles.git ~/dotfiles

Read the setup script.

less ~/dotfiles/setup.sh

Run the setup script.

bash ~/dotfiles/setup.sh

✅ Prerequisites

The dotfiles assume you are running macOS with (at minimum) the following software pre-installed:

All of the above and more are installed with my fork of Laptop.

🌟 New Mac Bootstrap

This is what I would do if I bought a new Mac computer today. The steps below assume you have already completed the basics:

💻 1. Run my fork of thoughtbot’s Laptop

github.com/joshukraine/laptop

Download the mac script:

curl --remote-name https://raw.githubusercontent.com/joshukraine/laptop/main/mac

Download .local.laptop for additional customizations:

curl --remote-name https://raw.githubusercontent.com/joshukraine/dotfiles/master/laptop/.laptop.local

Review both scripts before proceeding:

less mac
less .laptop.local

Execute the mac script:

sh mac 2>&1 | tee ~/laptop.log

I’ve made the following changes to my fork of Laptop:

  • Install asdf via git instead of Homebrew
  • Comment out Heroku-related code
  • Comment out unused Homebrew taps and formulae

It is worth noting that the Laptop script (mac) is idempotent and can be safely run multiple times to ensure a consistent baseline configuration.

⚠️ 2. Check for Stow conflicts

The dotfiles setup.sh script uses GNU Stow to symlink all the config files to your $HOME directory. If you already have an identically-named file/directory in $HOME (e.g. ~/.zshrc leftover from installing Laptop), this will cause a conflict, and Stow will (rightly) abort with an error.

The setup script will try to detect and backup these files ahead of Stow, but it’s still a good idea to check your $HOME directory as well as $HOME/.config and $HOME/.local/bin.

📍 3. Clone and setup the dotfiles

Clone

git clone https://github.com/joshukraine/dotfiles.git ~/dotfiles

Read

less ~/dotfiles/setup.sh

Setup

bash ~/dotfiles/setup.sh

If you do encounter Stow conflicts, resolve these and run setup again. The script is idempotent, so you can run it multiple times safely.

⚡️ 4. Install Zap

Zap describes itself as a “minimal zsh plugin manager that does what you expect.”

zapzsh.com

Important

After copying/pasting the install command for Zap, be sure to add the --keep flag to prevent Zap from replacing you existing .zshrc file.

🍺 5. Install remaining Homebrew packages

Review the included Brewfile and make desired adjustments.

less ~/Brewfile

Install the bundle.

brew bundle install

🛠️ 6. Complete post-install tasks

  • Launch LazyVim (nvim) and run :checkhealth. Resolve errors and warnings. Plugins should install automatically on first launch.
  • Add personal data as needed to *.local files such as ~/.gitconfig.local, ~/.laptop.local, ~/dotfiles/local/config.fish.local.
  • Set up 1Password CLI for managing secrets.
  • Set up 1Password SSH key management.
  • If using Fish, customize your setup by running the fish_config command.
  • If using Zsh, edit .zshrc and plugins.zsh to select either Starship or Powerlevel10K as your prompt.
  • If using Tmux, install Tmux plugins with <prefix> + I (https://github.com/tmux-plugins/tpm)

Zsh or Fish?

Having used both Zsh and Fish for several years, I’ve decided to keep my configs for both. One thing I particularly love about Fish is the concept of abbreviations over aliases. Happily, there is now zsh-abbr which brings this functionality to Zsh.

Fish abbr docs

My Zsh and Fish configs mostly have functional parity:

  • Same prompt (Starship)
  • Same essential abbreviations and functions
Zsh Setup Instructions Zsh is now the default shell on macOS. However, it’s helpful to add an entry enabling the Homebrew version of Zsh (`$HOMEBREW_PREFIX/bin/zsh`) instead of the default (`/bin/zsh`) version.

Ensure that you have Zsh from Homebrew. (which zsh) If not:

brew install zsh

Add Zsh (Homebrew version) to /etc/shells:

echo $HOMEBREW_PREFIX/bin/zsh | sudo tee -a /etc/shells

Set it as your default shell:

chsh -s $(which zsh)

Install Zap. (Required for functional parity with Fish)

Restart your terminal.

Fish Setup Instructions Install Fish from Homebrew:
 brew install fish

Add Fish to /etc/shells:

echo $HOMEBREW_PREFIX/bin/fish | sudo tee -a /etc/shells

Set it as your default shell:

chsh -s $(which fish)

Restart your terminal. This will create the ~/.config and ~/.local directories if they don’t already exist.

About Neovim Distributions

TL;DR: Just install LazyVim💤

📺 Zero to IDE with LazyVim

Back in the day if you wanted to use Vim (and later Neovim) you had to code a ton of configuration on your own. With Vim we got Vimscript 🤢, but then came Neovim which brought us Lua 🤩. I went from ye olde crunchy .vimrc to the more adventurous init.vim to the blessed path of init.lua. 😇

Meanwhile, there were the VS Code boys across the fence, bragging about their fancy icons, shiny tabs, and the oh-so-cool LSP. I confess, I even tried VS Code for a bit. That didn't last long. 😬

But Neovim has caught up. And wow have they. caught. up. Not only do we have native LSP support in Neovim (have had for a while now — v0.5), but we are solidly in the era of pre-baked Neovim distributions that are really challenging the notion of Vim/Neovim as austere, command-line editors. (I will say that I think we owe a lot to VS Code for raising the bar here. But I'm still glad I'm with Neovim. 😉)

If you want a quick primer on Neovim distros, check out the YouTube video below. I started with LunarVim (my first entry into distro-land) and now I'm with LazyVim and the Folke gang. Bottom line: you can still config Neovim from scratch if you want to, but you can get a HUGE head-start by just grabbing a distro and tweaking it to your needs.

📺 I tried Neovim Distributions so you don't have to

Boy, when I reminisce about the days of writing PHP for Internet Explorer in BBEdit...

🫣 Good-bye, Tmux?

I have nothing but warm fuzzy feelings towards Tmux. ... Ok, mostly warm and fuzzy. Tmux is amazing, and once I learned how to use it, it forever changed the way I came to see my terminal. I now expect the ability to spawn as many splits/panes/windows as needed, at any time, in any arrangement I choose, easily accessible through keyboard shortcuts.

But as anyone who has used Tmux can tell you, it's not without its trade-offs: copy/paste issues, color problems, font irregularities, etc. Yes, it was worth it, and somehow I always found workarounds. Still, at the end of the day, I don't consider myself a “Tmux power user”. That is, I don't usually need multiple sessions (tabs will do) or even persistence. I'm mostly here for the layouts. And for that, I found kitty...

😸 Hello, kitty!

The argument can be made that kitty vs. Tmux is an apples-to-oranges comparison. kitty is a terminal emulator whereas Tmux is a terminal multiplexer. But if you don't need all the features of Tmux (and you don't want to hassle with the Tmux overhead) I think kitty is a fine, much lighter replacement. As one Reddit user put it:

“...basic multiplexer = Kitty; advanced multiplexer = TMUX”.1

In addition to native split-pane support (think Tmux Lite), kitty brings a host of other cool features to the party including speed (GPU-based), excellent font support, extensible with “kittens”, and highly configurable via kitty.conf. In essence, kitty has allowed me to greatly simplify my development environment by going from Vim+iTerm2+Tmux to simply Vim+kitty.

I'm glad Tmux exists, I'm grateful for what it's taught me, and I'll probably use it again from time to time. Meanwhile, kitty is awesome...and I can finally change my colorscheme without having to reconcile THREE colorschemes! 🤪

Note

Be sure to get yourself a cool icon for kitty! HINT: Get this one. 😻

Still not convinced?

Fear not: if you're using these dotfiles and you'd rather stay with iTerm2 and Tmux, I've kept all of the Tmux-related configs, functions, aliases and abbreviations I had before. I'm not installing Tmux by default anymore, but you need only uncomment the appropriate lines in .laptop.local and Brewfile, and you're back in business.

My Favorite Programming Fonts

Over the years, I’ve branched out to explore a variety of mono-spaced fonts, both free and premium. Here is a list of my favorites.

Free Fonts

Included in my Brewfile and installed by default via Homebrew Cask Fonts

Premium Fonts

You have to give people money if you want these. 🤑

Ligatures

I first discovered ligatures through Fira Code, which IMHO is probably the king of programming fonts. After using Fira Code, it’s hard to go back to a sans-ligature typeface. Therefore all the fonts I’ve included in my fave’s list do include ligatures, although some have more than others.

Note

Operator Mono does not include ligatures but can be easily patched to add them.

Nerd Fonts and Icons

Back in the day, I started using the VimDevicons plugin so I could have fancy file-type icons in Vim. (Remember NERDTree?) In order for this to work, one had to install patched “Nerd-font” versions of whatever programming font one wanted to use. For example:

# Original font
$ brew install --cask font-fira-code

# Patched variant
$ brew install --cask font-fira-code-nerd-font

Patching fonts with icons still works fine of course, and is, I think, pretty widely used. However, during my exploration of kitty, I discovered that there is a different (better?) approach to icon fonts. It turns out, you don't need a patched version of your chosen mono-spaced font. You can get most if not all the icons you need and use them alongside any font by just installing the Symbols Nerd Font Mono font.

Leveraging this approach depends on your terminal. In iTerm2, for example, you need to check “Use a different font for non-ASCII text” in the Preferences panel. Then select Symbols Nerd Font Mono font under “Non-ASCII font”. (see screenshot below)

iterm2-font-settings

kitty does things a little differently. If you install a patched font, it will mostly work. Mostly. But the “kitty way” can be broken down in three steps:

  1. Install a normal, un-patched mono-spaced font, such as Cascadia Code
  2. Install a dedicated icon font, such as Symbols Nerd Font Mono
  3. Create a set of Unicode symbol maps2 to tell kitty which font to use for which icons (symbols)

More work up front, maybe, but less guesswork in the long-term once you understand what's going on. And if you're using my dotfiles, you have it easy. All the fonts you need are installed in Brewfile, and I have a set of Unicode symbol maps ready to go. 😎

Note

To learn more about Nerd fonts in terminals, as well as Unicode symbol maps and all the rest, be sure to check out Effective Nerd Fonts in Multiple Terminals by Elijah Manor

🧪 Nerd Font Smoke Test

If you want to check whether icons and ligatures are working properly, try running the included nerd-font-smoke-test.sh script from the root of the dotfiles folder like so:

bash nerd-font-smoke-test.sh

If your terminal is configured correctly, the output of the test should look like this:

smoke-test-output

Again, thank you, Elijah Manor!

Useful Font Links

A Note about Vim performance and Ruby files

Once upon a time, I almost left Vim due to some crippling performance issues. These issues were particularly painful when editing Ruby files. I documented what I learned here:

What I’ve learned about slow performance in Vim

Identifying Sources of Slow Startup Times (Zsh)

The .zshrc script can be profiled by touching the file ~/.zshrc.profiler and starting a new login shell. To see the top 20 lines that are taking the most time use the zshrc_profiler_view. zshrc_profiler parameters are number of lines to show (20) and path to profiler log file ($TMPDIR/zshrc_profiler.${PID}log).

Awesome Neovim Dotfiles, Distros, and Starters

Some of my favorite dotfile repos

Helpful web resources on dotfiles, et al.

License

Copyright © 2014–2023 Joshua Steele. MIT License

Footnotes

  1. https://www.reddit.com/r/KittyTerminal/comments/zxileg/comment/j21m4i4/

  2. https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.symbol_map