Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Managed with [chezmoi](https://www.chezmoi.io/), these dotfiles keep shell, edit
| Tool | Role |
| ---- | ---- |
| [chezmoi](https://www.chezmoi.io/) | Apply and template the repository contents. |
| [Antidote](https://github.com/mattmc3/antidote) | Fast Zsh plugin manager. |
| [mise](https://mise.jdx.dev/) | Install pinned runtimes via `.tool-versions`. |
| [Homebrew](https://brew.sh/) | Provision CLI tools and apps. |
| [Warp](https://www.warp.dev/) | Terminal profile stored in `dot_warp/`. |
Expand All @@ -15,6 +16,22 @@ Managed with [chezmoi](https://www.chezmoi.io/), these dotfiles keep shell, edit

Executable helpers live in `bin/`. Archived or inactive configs reside in `archive/`.

## Zsh Configuration

The Zsh configuration follows a modular structure inspired by [zdotdir](https://github.com/mattmc3/zdotdir):

- **`dot_config/zsh/`** — The `$ZDOTDIR` with modular Zsh configuration
- `.zshrc` — Interactive shell configuration
- `.zshenv` — Environment setup and XDG directories
- `.zstyles` — Zstyle settings for plugins
- `.zsh_plugins.txt` — Antidote plugin definitions
- `lib/antidote.zsh` — Antidote plugin manager loader
- `conf.d/` — Modular configuration files loaded automatically
- `functions/` — Custom Zsh functions
- `completions/` — Custom completion scripts

See [dot_config/zsh/README.md](dot_config/zsh/README.md) for details on the Zsh configuration.

## Setup

1. **Install prerequisites**
Expand Down
108 changes: 108 additions & 0 deletions dot_config/zsh/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Zsh Configuration

This directory contains the Zsh configuration (`$ZDOTDIR`) following a modular structure inspired by [zdotdir](https://github.com/mattmc3/zdotdir).

## Structure

```
~/.config/zsh/
├── .zshenv # Environment variables and XDG setup
├── .zshrc # Interactive shell configuration
├── .zstyles # Zstyle settings for plugins
├── .zsh_plugins.txt # Antidote plugin list
├── lib/
│ └── antidote.zsh # Antidote plugin manager loader
├── conf.d/
│ └── __init__.zsh # Initial configuration (runs first)
├── functions/ # Custom Zsh functions
└── completions/ # Custom completion scripts
```

## Plugin Management

This configuration uses [Antidote](https://github.com/mattmc3/antidote) for plugin management. Plugins are defined in `.zsh_plugins.txt` and are automatically loaded.

### Key Features

- **Modular Configuration**: Configuration is split into separate files in `conf.d/` for easier maintenance
- **Plugin Management**: Antidote provides fast, declarative plugin loading
- **XDG Compliance**: Respects XDG Base Directory specification
- **Performance**: Includes profiling support with `zprofrc` alias
- **Custom Functions**: Autoload custom functions from `functions/` directory
- **Completions**: Custom completions from `completions/` directory

## Adding Plugins

Edit `.zsh_plugins.txt` and add plugin entries. For example:

```
# Add a GitHub plugin
username/repo

# Add a specific path
ohmyzsh/ohmyzsh path:plugins/git

# Conditional loading (macOS only)
mattmc3/zsh_custom path:plugins/macos conditional:is-macos
```

After editing, restart your shell or run `exec zsh` to reload.

## Adding Custom Configuration

Place custom configuration files in `conf.d/`. They will be automatically loaded in alphabetical order (after `__init__.zsh` which always runs first).

Example:

```bash
# Create a new config file
echo "alias myalias='command'" > ~/.config/zsh/conf.d/aliases.zsh
```

## Adding Custom Functions

Place function files in `functions/`. Each file should contain a single function with the same name as the file.

Example:

```bash
# Create a new function
cat > ~/.config/zsh/functions/myfunc <<'EOF'
#!/bin/zsh
# Description of what this function does
myfunc() {
echo "Hello from myfunc"
}
EOF
```

## Profiling

To profile your Zsh startup time:

```bash
zprofrc
```

This will start a new Zsh session with profiling enabled and display the results.

## Integration with Chezmoi

Since this is managed by [chezmoi](https://www.chezmoi.io/), files are prefixed with `dot_` in the repository:

- `dot_config/zsh/dot_zshenv` → `~/.config/zsh/.zshenv`
- `dot_config/zsh/dot_zshrc` → `~/.config/zsh/.zshrc`
- `dot_config/zsh/dot_zstyles` → `~/.config/zsh/.zstyles`
- etc.

To edit and apply changes:

```bash
chezmoi edit --apply ~/.config/zsh/.zshrc
```

## Resources

- [Antidote GitHub](https://github.com/mattmc3/antidote) - Plugin manager documentation
- [mattmc3/zdotdir](https://github.com/mattmc3/zdotdir) - Reference implementation
- [Zsh Documentation](http://zsh.sourceforge.net/Doc/)
28 changes: 28 additions & 0 deletions dot_config/zsh/conf.d/__init__.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#
# __init__: This runs prior to any other conf.d contents.
#

# Apps
export EDITOR=${EDITOR:-nvim}
export VISUAL=${VISUAL:-code}
export PAGER=${PAGER:-less}

# Set the list of directories that cd searches.
cdpath=(
$XDG_PROJECTS_DIR(N/)
$cdpath
)

# Set the list of directories that Zsh searches for programs.
path=(
# core
$prepath
$path

# Homebrew prefix was set in .zshenv
$HOMEBREW_PREFIX/opt/curl/bin(N)
$HOMEBREW_PREFIX/share/npm/bin(N)
$HOMEBREW_PREFIX/opt/ruby/bin(N)
$HOMEBREW_PREFIX/lib/ruby/gems/*/bin(N)
$HOME/.gem/ruby/*/bin(N)
)
71 changes: 71 additions & 0 deletions dot_config/zsh/dot_zsh_plugins.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#
# .zsh_plugins.txt - antidote plugins file
#

#
# Init
#

mattmc3/zsh_custom path:lib
mattmc3/zsh_custom path:plugins/xdg
mattmc3/zsh_custom path:plugins/history
mattmc3/zsh_custom path:plugins/environment
mattmc3/zsh_custom path:plugins/homebrew conditional:is-macos

#
# Completions
#

mattmc3/ez-compinit
zsh-users/zsh-completions kind:fpath path:src

#
# Editor
#

mattmc3/zsh_custom path:plugins/editor

#
# Prompts
#

# Use starship prompt
# starship is configured via ~/.config/starship.toml

#
# Custom
#

mattmc3/zsh_custom path:plugins/color
mattmc3/zsh_custom path:plugins/common-aliases
mattmc3/zsh_custom path:plugins/common-functions
mattmc3/zsh_custom path:plugins/directory
mattmc3/zsh_custom path:plugins/dotfiles
mattmc3/zsh_custom path:plugins/git
mattmc3/zsh_custom path:plugins/utility
mattmc3/zsh_custom path:plugins/zfunctions
mattmc3/zsh_custom path:plugins/zoxide

#
# OMZ
#

ohmyzsh/ohmyzsh path:plugins/direnv
ohmyzsh/ohmyzsh path:plugins/extract

#
# macOS
#

mattmc3/zsh_custom path:plugins/macos conditional:is-macos

#
# Final
#

mattmc3/zsh_custom path:plugins/fast-syntax-highlighting
mattmc3/zsh_custom path:plugins/autosuggestions
mattmc3/zsh_custom path:plugins/history-substring-search
mattmc3/zsh_custom path:plugins/zshrcd

# vi: ft=properties
32 changes: 32 additions & 0 deletions dot_config/zsh/dot_zshenv
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/zsh
#
# .zshenv: Zsh environment file, loaded always.
#

export ZDOTDIR=${ZDOTDIR:-$HOME/.config/zsh}

# XDG
export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
export XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
export XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}
export XDG_STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state}
export XDG_RUNTIME_DIR=${XDG_RUNTIME_DIR:-$HOME/.xdg}
export XDG_PROJECTS_DIR=${XDG_PROJECTS_DIR:-$HOME/Projects}

# Fish-like dirs
: ${__zsh_config_dir:=${ZDOTDIR:-${XDG_CONFIG_HOME:-$HOME/.config}/zsh}}
: ${__zsh_user_data_dir:=${XDG_DATA_HOME:-$HOME/.local/share}/zsh}
: ${__zsh_cache_dir:=${XDG_CACHE_HOME:-$HOME/.cache}/zsh}

# Ensure Zsh directories exist.
() {
local zdir
for zdir in $@; do
[[ -d "${(P)zdir}" ]] || mkdir -p -- "${(P)zdir}"
done
} __zsh_{config,user_data,cache}_dir XDG_{CONFIG,CACHE,DATA,STATE}_HOME XDG_{RUNTIME,PROJECTS}_DIR

# Make Terminal.app behave.
if [[ "$OSTYPE" == darwin* ]]; then
export SHELL_SESSIONS_DISABLE=1
fi
27 changes: 27 additions & 0 deletions dot_config/zsh/dot_zshrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/zsh
#
# .zshrc - Zsh file loaded on interactive shell sessions.
#

# Profiling
[[ "$ZPROFRC" -ne 1 ]] || zmodload zsh/zprof
alias zprofrc="ZPROFRC=1 zsh"

# Add custom completions
fpath=(${ZDOTDIR:-$HOME/.config/zsh}/completions $fpath)

# Set any zstyles you might use for configuration.
[[ ! -f ${ZDOTDIR:-$HOME}/.zstyles ]] || source ${ZDOTDIR:-$HOME}/.zstyles

# Create an amazing Zsh config using antidote plugins.
source ${ZDOTDIR:-$HOME/.config/zsh}/lib/antidote.zsh

# Never start in the root file system.
[[ "$PWD" != "/" ]] || cd

# Finish profiling by calling zprof.
[[ "$ZPROFRC" -eq 1 ]] && zprof
[[ -v ZPROFRC ]] && unset ZPROFRC

# Always return success
true
31 changes: 31 additions & 0 deletions dot_config/zsh/dot_zstyles
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/zsh
#
# .zstyles - zstyle settings for features/plugins that need them.
#

#
# Completions
#

zstyle ':zsh_custom:plugin:*' 'use-cache' no
zstyle ':zsh_custom:plugin:completion' compstyle zshzoo

#
# Editor
#

# Set the key mapping style to 'emacs' or 'vi'.
zstyle ':zsh_custom:plugin:editor' key-bindings 'emacs'

# Enable all the editor extensions.
zstyle ':zsh_custom:plugin:editor:*' 'enabled' 'yes'

#
# ZSH_CUSTOM features
#

# zshrc.d location
zstyle ':zsh_custom:plugin:zshrcd' directory $ZDOTDIR/conf.d

# zfunctions location
zstyle ':zsh_custom:plugin:zfunctions' directory $ZDOTDIR/functions
25 changes: 25 additions & 0 deletions dot_config/zsh/lib/antidote.zsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#
# Antidote
#

: ${ANTIDOTE_HOME:=${XDG_CACHE_HOME:-~/.cache}/repos}

# Keep all 3 for different test scenarios.
ANTIDOTE_REPO=$ANTIDOTE_HOME/mattmc3/antidote
# ANTIDOTE_REPO=~/Projects/mattmc3/antidote
# ANTIDOTE_REPO=${HOMEBREW_PREFIX:-/opt/homebrew}/opt/antidote/share/antidote

zstyle ':antidote:home' path $ANTIDOTE_HOME
zstyle ':antidote:repo' path $ANTIDOTE_REPO
zstyle ':antidote:bundle' use-friendly-names 'yes'
zstyle ':antidote:plugin:*' defer-options '-p'
zstyle ':antidote:*' zcompile 'yes'

# Clone antidote if necessary.
if [[ ! -d $ANTIDOTE_REPO ]]; then
git clone https://github.com/mattmc3/antidote $ANTIDOTE_REPO
fi

# Load antidote
source $ANTIDOTE_REPO/antidote.zsh
antidote load
11 changes: 2 additions & 9 deletions dot_zshenv
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,14 @@
# NOTE: .zshenv needs to live at ~/.zshenv, not in $ZDOTDIR!
export ZDOTDIR=${ZDOTDIR:-$HOME/.config/zsh}

export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config}
export XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share}
export XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache}
export XDG_STATE_HOME=${XDG_STATE_HOME:-$HOME/.local/state}
# Source the ZDOTDIR .zshenv for additional configuration
[[ -f $ZDOTDIR/.zshenv ]] && . $ZDOTDIR/.zshenv

# Set Homebrew prefix for reuse throughout config
if command -v brew &>/dev/null; then
export HOMEBREW_PREFIX=$(brew --prefix)
fi

# Make Terminal.app behave.
if [[ "$OSTYPE" == darwin* ]]; then
export SHELL_SESSIONS_DISABLE=1
fi

# Ensure path arrays do not contain duplicates.
typeset -gU path fpath

Expand Down