📒

2024年度 わたしのdotfilesを紹介します

2024/08/16に公開

はじめに

これまで適当に管理していたdotfilesを一念発起して整理したので備忘録がてら記事にしておきます。

リポジトリは👇から。

https://github.com/ayuukumakuma/dotfiles

※dotfilesに関しては以下の記事がとても分かりやすかったので紹介しておきます。
https://qiita.com/yutkat/items/c6c7584d9795799ee164

dotfilesを使った環境構築の手順

めちゃくちゃ簡単です。

  1. ホームディレクトリ(~/, $HOME/)にdotfilesのリポジトリをcloneする。
  2. sh setup.shを実行する。
  3. 終わり!

ディレクトリ構成

dotfiles/〇〇ディレクトリ配下に各設定ファイルを置いてます。
dotfilesディレクトリ直下には環境変数であったり環境構築や環境更新に必要なシェルスクリプトを置いてます。

.
├── git
│   ├── .gitconfig
│   └── user.conf
├── homebrew
│   └── .Brewfile
├── sheldon
│   └── .sheldon.toml
├── shellchecker
│   └── .shellcheckrc
├── starship
│   └── .starship.toml
├── wezterm
│   └── .wezterm.lua
├── zsh
│   ├── sync
│   │   ├── check-and-sync-brewfile.zsh
│   │   ├── config.zsh
│   │   └── starship.zsh
│   ├── .zshrc
│   ├── alias.zsh
│   └── amazon-q.zsh
├── .env
├── .env.example
├── .gitignore
├── brew-init.sh
├── link.sh
├── replace-git.sh
├── replace-zsh.sh
├── setup.sh
└── unlink.sh

重要なスクリプトの説明

link.sh

ホームディレクトリにシンボリックリンクを作成するためのスクリプトです。
dotfiles/XXX/.YYYのような.から始まるファイルが対象になっています。

link.sh
#!/bin/bash

DOTFILES_DIR=~/dotfiles

echo "シンボリックリンクを作成します"

# dotfilesディレクトリ内の二つ下のディレクトリにあるファイルに対してループ
for file in "$DOTFILES_DIR"/*/.[^.]*; do
    # '.' と '..' はスキップ
    if [[ $file == "$DOTFILES_DIR/." || $file == "$DOTFILES_DIR/.." ]]; then
        continue
    fi

    # ホームディレクトリ直下に作成するパスを計算
    link_name=~/${file#"$DOTFILES_DIR"/*/}

    # シンボリックリンクの作成
    ln -sfn "$file" "$link_name"

    # 作成したシンボリックリンクを出力
    echo "リンクを作成: $file -> $link_name"
done

echo "シンボリックリンクがホームディレクトリ直下に作成されました"

setup.sh

環境構築時に実行するスクリプトです。
他のスクリプトもここで実行しこのファイルだけの実行で済むようにしています。

setup.sh
#!/bin/bash

echo "セットアップを開始します"

# dotfilesのシンボリックリンクを作成する
source ~/dotfiles/link.sh

# homebrewがインストールされていない場合はインストール
if ! type brew >/dev/null 2>&1; then
  echo "Homebrewをインストールします"
  /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
else
  echo "Homebrewはすでにインストールされています"
fi

# Brewfileに記載されているパッケージをインストール
source ~/dotfiles/brew-init.sh

# zshをbrewのものに置き換え
source ~/dotfiles/replace-zsh.sh

# gitをbrewのものに置き換え
source ~/dotfiles/replace-git.sh

echo "セットアップが完了しました"
echo "Next..."
echo "1. .envを追加し、環境変数を設定してください。"
echo "2. git/user.confを追加し、ユーザー情報を設定してください。"
echo "3. ターミナルを再起動してください。"

Git

これなに?

皆さん使っていると思うので省略します。

ディレクトリ構成

git
├── .gitconfig
└── user.conf

設定ファイル

.gitconfig
[include]
  path = ~/dotfiles/git/user.conf

[init]
  defaultBranch = main

[push]
  default         = current
  autoSetupRemote = true

[merge]
  ff = false

[pull]
  ff = only

[alias]
  s  = switch
  st = status
  c  = commit
  p  = pull
  ps = push
  a  = add
  r  = reset
user.conf(ignored)
[user]
  email = <メールアドレス>
  name  = <ユーザーネーム>

スクリプト

replace-git.sh
#!/bin/bash

# Brewでgitがインストールされているか確認
if ! brew list git &>/dev/null; then
    echo "gitがインストールされていないため、インストールを開始します..."
    brew install git
else
    echo "gitはすでにインストールされています。"
fi

# Brewでインストールされたgitのパスを取得
GIT_PATH=$(brew --prefix)/bin/git

# 現在のgitのパスを確認
CURRENT_GIT_PATH=$(which git)

# デフォルトのgitがすでにbrewのものかどうか確認
if [ "$CURRENT_GIT_PATH" == "$GIT_PATH" ]; then
    echo "すでにHomebrewでインストールされたgitがデフォルトになっています。"
else
    echo "Homebrewでインストールされたgitをデフォルトに設定します..."

    # パスを追加
    SHELL_PATH_FILE="$HOME/dotfiles/zsh/sync/path.zsh"
    echo "export PATH=\"$GIT_PATH:\$PATH\"" >>"$SHELL_PATH_FILE"

    # シェル設定を再読み込み
    source "$HOME"/.zshrc

    echo "Homebrewでインストールされたgitがデフォルトに設定されました。"
    echo "新しいターミナルセッションを開くと、設定が反映されます。"
fi

Point

  • .envから取得して.gitconfigに反映するのが難しそうだったので個人情報部分をuser.confに切り出してます。
  • セットアップ時にはuser.confを作成してあげる必要があります。
    • ここはシェルスクリプトでもうちょっと改善できるかも。
  • GitもHomebrewで管理したいため、デフォルトで入っているGitをHomebrewのものに置き換えるスクリプトを環境構築時に実行します。

Homebrew

これなに?

macOS or Linux用のパッケージマネージャーです。
これを使うと自分で導入するほぼ全てのGUI, CLIツールを一元管理することができます。
👇の設定ファイルを見ていただければわかると思いますが筆者は全てのCLIツールやアプリケーションをHomebrewで管理しています。
https://brew.sh/ja/

ディレクトリ構成

homebrew
└── .Brewfile

設定ファイル

.Brewfile
tap "homebrew/bundle"
brew "bat"
brew "eza"
brew "fd"
brew "fzf"
brew "git"
brew "just"
brew "mas"
brew "ripgrep"
brew "sheldon"
brew "shellcheck"
brew "shfmt"
brew "starship"
brew "tree"
brew "zsh"
cask "1password"
cask "amazon-q"
cask "arc"
cask "chatgpt"
cask "flameshot"
cask "font-monaspace-nerd-font"
cask "google-chrome@canary"
cask "hiddenbar"
cask "hot"
cask "insomnia"
cask "kap"
cask "notchnook"
cask "orbstack"
cask "raycast"
cask "spotify"
cask "steam"
cask "tableplus"
cask "visual-studio-code"
cask "wezterm"
mas "RunCat", id: 1429033973
...
# vscodeもbrewで管理していれば拡張機能もここに記載される
# 今回は数が多いので省略

スクリプト

brew-init.sh
#!/bin/bash

echo "Brewfileに記載されているパッケージをインストールします"
brew bundle --global
check-and-sync-brewfile.zsh
#!/bin/bash

function check_and_sync_brewfile() {
  # 現在インストールされているパッケージ一覧を取得
  installed_packages=$(brew leaves && brew list --cask)
  # .Brewfileに記載されているパッケージ一覧を取得
  brewfile_packages=$(grep '^(brew|cask)' ~/dotfiles/homebrew/.Brewfile | awk '{gsub(/"/, "", $2); print $2}')

  # インストールされていないパッケージをインストールし、.Brewfileに追加
  echo ".Brewfileに記載されているがインストールされていないパッケージをインストールします:"

  installed_any=false
  while read -r package; do
    if ! echo "$installed_packages" | grep -q "^$package$"; then
      echo "インストール中: $package"
      brew install "$package"
      installed_any=true
    fi
  done < <(echo "$brewfile_packages")

  if [ "$installed_any" = false ]; then
    echo "すべてのパッケージがすでにインストールされています。"
  fi

  echo

  # .Brewfileに記載されていないがインストールされているパッケージを.Brewfileに追加
  echo ".Brewfileに記載されていないがインストールされているパッケージを.Brewfileに追加します:"
  installed_any=false
  while read -r package; do
    if ! echo "$brewfile_packages" | grep -q "^$package$"; then
      installed_any=true
    fi
  done < <(echo "$installed_packages")

  if [ "$installed_any" = false ]; then
    echo "すべてのパッケージがすでに.Brewfileに記載されています。"
  else
    echo ".Brewfileの内容と実際のインストール状況が一致しません。"
    echo ".Brewfileを再生成します。"
    brew bundle dump --force --file=~/dotfiles/homebrew/.Brewfile
  fi

}

# brewコマンドが実行された時に発火する
preexec() {
  if [[ "$1" == brew* ]]; then
    check_and_sync_brewfile
  fi
}

Point

  • masを使用して、AppStoreにしか存在しないものもbrewの管轄にしています。
  • brew bundleを使用することでインストールしているものを設定ファイルとして残すことができます。
    • GitHubなどで管理することによって異なるマシンでも同一の環境を構築できます。
  • .Brewfileの更新は手動でしか行えないのでbrewコマンドを使用したときに.Brewfileの再生成や足りていないパッケージのインストールを行なうスクリプトをzshのpreexec関数でフックしています。
  • デフォルトはBrewfileという名前で生成されますが、dotfilesという名目で管理するため.Brewfileという名前で保存しています。

Sheldon(Zsh)

これなに?

シェルのプラグインや、分割された設定ファイルなどを管理するマネージャーツールです。
これを使用することでペライチの混沌(カオス)な.zshrcから解放されます...!!!

https://sheldon.cli.rs/Introduction.html

ディレクトリ構成

sheldon
└── .sheldon.toml
zsh
├── sync
│   ├── check-and-sync-brewfile.zsh
│   ├── config.zsh
│   ├── path.zsh
│   └── starship.zsh
├── .zshrc
├── alias.zsh
└── amazon-q.zsh

設定ファイル

Sheldonの設定に関しては👇の方の記事を参考にさせて頂きました🙇‍♂️
zinitが不安なのでsheldonへ移行したらzshの起動が50msと更に速くなった

sheldon/.sheldon.toml
shell = "zsh"

# デフォルトを遅延読み込みにする
apply = ["defer"]

[plugins.zsh-defer]
github = "romkatv/zsh-defer"
apply = ["source"]

# 遅延読み込みの設定 
[templates]
defer = "{% for file in files %}zsh-defer source \"{{ file }}\"\n{% endfor %}"

# シンタックスハイライト(遅延読み込み非対応)
[plugins.syntax-highlighting]
github = "zdharma/fast-syntax-highlighting"

# zsh配下のファイルは遅延読み込みする
[plugins.local-defers]
local = "~/dotfiles/zsh"
use = ["{!sync,*}.zsh"]

# zsh/sync配下のファイルは遅延読み込みしない
[plugins.local-sync]
local = "~/dotfiles/zsh"
use = ["sync/*.zsh"]
apply = ["source"]
zsh/.zshrc
#!/bin/bash

# zshの読み込み時間を表示するときはコメントアウトを外す
# zmodload zsh/zprof

export SHELDON_CONFIG_FILE=$HOME/.sheldon.toml
eval "$(sheldon source)"

# zprof
zsh/alias.zsh
#!/bin/bash

alias c='clear'
alias reload='exec $SHELL -l'
alias ls='eza -alh --icons=auto --no-user'
alias cat='bat --theme="Dracula"'
alias find='fd'
alias cdf='cd "$(dirname "$(fzf --preview="bat --color=always {}")")"'
alias grep='rg'
alias g='git'
zsh/sync/config.zsh
#!/bin/bash

# 環境変数
export LANG=ja_JP.UTF-8

# ヒストリの設定
HISTFILE=~/.zsh_history
HISTSIZE=30000
# shellcheck disable=SC2034
SAVEHIST=30000

# 他のzshと履歴を共有
setopt inc_append_history
setopt share_history

# 直前のコマンドの重複を削除
setopt hist_ignore_dups

# 同じコマンドをヒストリに残さない
setopt hist_ignore_all_dups

# パスを直接入力してもcdする
setopt auto_cd

# cd-<tab>で以前移動したディレクトリを表示
setopt auto_pushd

# 環境変数を補完
setopt auto_param_keys

# historyに保存するときに余分なスペースを削除する
setopt hist_reduce_blanks
その他
zsh/sync/check-and-sync-brewfile.zsh
#!/bin/bash

function check_and_sync_brewfile() {
  # 現在インストールされているパッケージ一覧を取得
  installed_packages=$(brew leaves && brew list --cask)
  # .Brewfileに記載されているパッケージ一覧を取得
  brewfile_packages=$(grep '^(brew|cask)' ~/dotfiles/homebrew/.Brewfile | awk '{gsub(/"/, "", $2); print $2}')

  # インストールされていないパッケージをインストールし、.Brewfileに追加
  echo ".Brewfileに記載されているがインストールされていないパッケージをインストールします:"

  installed_any=false
  while read -r package; do
    if ! echo "$installed_packages" | grep -q "^$package$"; then
      echo "インストール中: $package"
      brew install "$package"
      installed_any=true
    fi
  done < <(echo "$brewfile_packages")

  if [ "$installed_any" = false ]; then
    echo "すべてのパッケージがすでにインストールされています。"
  fi

  echo

  # .Brewfileに記載されていないがインストールされているパッケージを.Brewfileに追加
  echo ".Brewfileに記載されていないがインストールされているパッケージを.Brewfileに追加します:"
  installed_any=false
  while read -r package; do
    if ! echo "$brewfile_packages" | grep -q "^$package$"; then
      installed_any=true
    fi
  done < <(echo "$installed_packages")

  if [ "$installed_any" = false ]; then
    echo "すべてのパッケージがすでに.Brewfileに記載されています。"
  else
    echo ".Brewfileの内容と実際のインストール状況が一致しません。"
    echo ".Brewfileを再生成します。"
    brew bundle dump --force --file=~/dotfiles/homebrew/.Brewfile
  fi

}

# brewコマンドが実行された時に発火する
preexec() {
  if [[ "$1" == brew* ]]; then
    check_and_sync_brewfile
  fi
}
zsh/sync/path.zsh
#!/bin/bash
export PATH="/opt/homebrew/bin/git:$PATH"
zsh/sync/starship.zsh
#!/bin/bash

export STARSHIP_CONFIG=$HOME/.starship.toml
eval "$(starship init zsh)"
zsh/amazon-q.zsh
#!/bin/bash
# Amazon Q pre block. Keep at the top of this file.
[[ -f "${HOME}/Library/Application Support/amazon-q/shell/zshrc.pre.zsh" ]] && builtin source "${HOME}/Library/Application Support/amazon-q/shell/zshrc.pre.zsh"

# Amazon Q post block. Keep at the bottom of this file.
[[ -f "${HOME}/Library/Application Support/amazon-q/shell/zshrc.post.zsh" ]] && builtin source "${HOME}/Library/Application Support/amazon-q/shell/zshrc.post.zsh"

スクリプト

replace-zsh.sh
#!/bin/bash

# Brewでzshがインストールされているか確認
if ! brew list zsh &>/dev/null; then
    echo "zshがインストールされていないため、インストールを開始します..."
    brew install zsh
else
    echo "zshはすでにインストールされています。"
fi

# インストールしたzshのパスを取得
ZSH_PATH=$(brew --prefix)/bin/zsh

# インストールされたzshがシェルとして許可されているか確認し、追加
if ! grep -Fxq "$ZSH_PATH" /etc/shells; then
    echo "$ZSH_PATH" | sudo tee -a /etc/shells
fi

# デフォルトシェルをインストールしたzshに変更
chsh -s "$ZSH_PATH"

# 設定の反映を促すメッセージ
echo "brewでインストールしたzshをデフォルトシェルに設定しました。ターミナルを再起動してください。"

Point

  • ezabatripgrepなど、既存コマンドの代替ツールを使用することで効率や視認性を向上させています。
  • aliasやconfigなど設定もファイルとして分割し、.zshrcをシンプルにすることで管理しやすくしています。
  • 設定やプラグインを遅延読み込みさせることでzshの立ち上げを高速化しています。
  • 補完系はAmazon Q(旧Fig)に一任することで面倒な設定を省いています。
    • Amazon Qはめちゃ便利なのでぜひ試したことのない方には一度導入してもらいたいです。
  • Gitと同様にZshもHomebrewで管理したいためデフォルトで入っているZshをHomebrewのものに置き換えるスクリプトを環境構築時に実行します。

WezTerm

これなに?

Rust製の軽量で高速なターミナルです。
設定は全てLua Languageで記述し、設定できる項目が非常に沢山あります!
ちなみに自分はこんな感じにしてます。(モチベが上がりますね \ΦwΦ/ )
my wezterm
https://wezfurlong.org/wezterm/

ディレクトリ構成

wezterm
└── .wezterm.lua

設定ファイル

.wezterm.lua
local wezterm = require 'wezterm'

-- .envから環境変数を読み込む
local load_env = function(file)
  local env = {}

  for line in io.lines(file) do
    -- 行が空行やコメント行(#で始まる)でない場合
    if line:match("^%s*#") == nil and line:match("^%s*$") == nil then
      -- KEY=VALUEの形式を解析
      local key, value = line:match("^%s*([^=]+)%s*=%s*(.*)%s*$")

      if key and value then
        -- 環境変数として設定
        env[key] = value
      end
    end
  end

  return env
end

local dirName = os.getenv("HOME")
local env = load_env(string.format("%s/dotfiles/.env", dirName))

local config = wezterm.config_builder()

-- Color scheme
config.color_scheme = 'Andromeda'

-- Background
config.background = {
  {
    source = {
      File = env.BACKGROUND_IMAGE_PATH
    },
    attachment = { Parallax = 0.05 },
    hsb = {
      brightness = 0.05,
    }
  }

}

-- Cursor
config.default_cursor_style = "BlinkingBlock"

-- TabBar
config.hide_tab_bar_if_only_one_tab = true -- タブが1つだけの場合はタブバーを非表示にする
config.show_tab_index_in_tab_bar    = false -- タブバーにインデックスを表示しない

-- Font
config.line_height                              = 1.1
config.treat_east_asian_ambiguous_width_as_wide = true -- 日本語を2文字分の幅で表示する
config.font                                     = wezterm.font "MonaspiceAr Nerd Font Mono"

-- Window
config.window_decorations        = "RESIZE" -- タイトルバーを非表示にする
config.window_close_confirmation = "NeverPrompt" -- ウィンドウを閉じる際の確認を行わない
config.initial_rows              = 50 -- 初期の行数
config.initial_cols              = 150 -- 初期の列数

return config
.env.example
BACKGROUND_IMAGE_PATH= # weztermの背景画像のパス

Point

  • 環境変数を読み込めるようにして、好きな背景画像を設定できるようにしました。
    • モチベが上がります!!
    • 背景透過+ぼかしもできます。

Starship

これなに?

先ほどちらっとお見せしましたがプロンプトの見た目を整えてくれるこれまたRust製のツールです。
カスタマイズ製が非常に高く自分だけのプロンプトを作成できちゃいます。(自分はデフォルトで用意されているテーマを使用していますが...)
https://starship.rs/

ディレクトリ構成

starship
└── .starship.toml

設定ファイル

公式のpresetsを貼り付けているだけなので省略します。

一応残しておく
.starship.toml
[aws]
symbol = "  "

[buf]
symbol = " "

[c]
symbol = " "

[conda]
symbol = " "

[crystal]
symbol = " "

[dart]
symbol = " "

[directory]
read_only = " 󰌾"

[docker_context]
symbol = " "

[elixir]
symbol = " "

[elm]
symbol = " "

[fennel]
symbol = " "

[fossil_branch]
symbol = " "

[git_branch]
symbol = " "

[golang]
symbol = " "

[guix_shell]
symbol = " "

[haskell]
symbol = " "

[haxe]
symbol = " "

[hg_branch]
symbol = " "

[hostname]
ssh_symbol = " "

[java]
symbol = " "

[julia]
symbol = " "

[kotlin]
symbol = " "

[lua]
symbol = " "

[memory_usage]
symbol = "󰍛 "

[meson]
symbol = "󰔷 "

[nim]
symbol = "󰆥 "

[nix_shell]
symbol = " "

[nodejs]
symbol = " "

[ocaml]
symbol = " "

[os.symbols]
Alpaquita = " "
Alpine = " "
AlmaLinux = " "
Amazon = " "
Android = " "
Arch = " "
Artix = " "
CentOS = " "
Debian = " "
DragonFly = " "
Emscripten = " "
EndeavourOS = " "
Fedora = " "
FreeBSD = " "
Garuda = "󰛓 "
Gentoo = " "
HardenedBSD = "󰞌 "
Illumos = "󰈸 "
Kali = " "
Linux = " "
Mabox = " "
Macos = " "
Manjaro = " "
Mariner = " "
MidnightBSD = " "
Mint = " "
NetBSD = " "
NixOS = " "
OpenBSD = "󰈺 "
openSUSE = " "
OracleLinux = "󰌷 "
Pop = " "
Raspbian = " "
Redhat = " "
RedHatEnterprise = " "
RockyLinux = " "
Redox = "󰀘 "
Solus = "󰠳 "
SUSE = " "
Ubuntu = " "
Unknown = " "
Void = " "
Windows = "󰍲 "

[package]
symbol = "󰏗 "

[perl]
symbol = " "

[php]
symbol = " "

[pijul_channel]
symbol = " "

[python]
symbol = " "

[rlang]
symbol = "󰟔 "

[ruby]
symbol = " "

[rust]
symbol = "󱘗 "

[scala]
symbol = " "

[swift]
symbol = " "

[zig]
symbol = " "

スクリプト

zsh/sync/starship.zsh
#!/bin/bash

export STARSHIP_CONFIG=$HOME/.starship.toml
eval "$(starship init zsh)"

Point

特にないです!

おわりに

本当はRaycast(Spotlightのようなランチャーアプリ)の設定やMac本体の設定(defaultコマンドによる設定)もdotfilesに追加しておきたかったのですが時間が足らず断念しました...
時間があれば追記しておこうと思いますmm

今回はツールの細かい説明まではしませんでしたが「こんなんがあるのね〜」程度に把握しておいてもらえたら嬉しいです。

GitHubで編集を提案
SMARTCAMP Engineer Blog

Discussion