mirror of
https://github.com/logos-co/logos-workspace.git
synced 2026-08-27 10:41:16 +00:00
411 lines
17 KiB
Nix
411 lines
17 KiB
Nix
# Dev shell configuration for the Logos workspace.
|
|
# Provides a modern, batteries-included shell environment.
|
|
#
|
|
# Used by: flake.nix devShells.default
|
|
{ pkgs, wsScript }:
|
|
|
|
let
|
|
# Starship prompt config
|
|
starshipConfig = pkgs.writeText "starship.toml" ''
|
|
format = """$directory$git_branch$git_status$nix_shell$character"""
|
|
|
|
[character]
|
|
success_symbol = "[λ](bold green)"
|
|
error_symbol = "[λ](bold red)"
|
|
|
|
[directory]
|
|
truncation_length = 3
|
|
truncate_to_repo = true
|
|
style = "bold cyan"
|
|
|
|
[git_branch]
|
|
format = " [$branch]($style)"
|
|
style = "bold purple"
|
|
|
|
[git_status]
|
|
format = "[$all_status$ahead_behind]($style) "
|
|
style = "bold yellow"
|
|
|
|
[nix_shell]
|
|
format = "[$symbol]($style)"
|
|
symbol = " ❄"
|
|
style = "bold blue"
|
|
'';
|
|
|
|
# Delta (git pager) config
|
|
deltaConfig = pkgs.writeText "delta-gitconfig" ''
|
|
[core]
|
|
pager = delta
|
|
[interactive]
|
|
diffFilter = delta --color-only
|
|
[delta]
|
|
navigate = true
|
|
side-by-side = true
|
|
line-numbers = true
|
|
hyperlinks = true
|
|
[merge]
|
|
conflictstyle = diff3
|
|
'';
|
|
|
|
# Tmux config
|
|
tmuxConfig = pkgs.writeText "tmux.conf" ''
|
|
# ── General ──────────────────────────────────────────────────────
|
|
set -g default-shell "${pkgs.zsh}/bin/zsh"
|
|
set -g default-command "${pkgs.zsh}/bin/zsh"
|
|
set -g default-terminal "tmux-256color"
|
|
set -ag terminal-overrides ",xterm-256color:RGB"
|
|
set -g mouse on
|
|
set -g history-limit 50000
|
|
set -g base-index 1
|
|
setw -g pane-base-index 1
|
|
set -g renumber-windows on
|
|
set -g set-clipboard on
|
|
set -sg escape-time 0
|
|
set -g focus-events on
|
|
|
|
# ── Prefix ───────────────────────────────────────────────────────
|
|
unbind C-b
|
|
set -g prefix C-a
|
|
bind C-a send-prefix
|
|
|
|
# ── Splits ───────────────────────────────────────────────────────
|
|
bind | split-window -h -c "#{pane_current_path}"
|
|
bind - split-window -v -c "#{pane_current_path}"
|
|
bind c new-window -c "#{pane_current_path}"
|
|
unbind '"'
|
|
unbind %
|
|
|
|
# ── Navigation (vim-style) ───────────────────────────────────────
|
|
bind h select-pane -L
|
|
bind j select-pane -D
|
|
bind k select-pane -U
|
|
bind l select-pane -R
|
|
|
|
# ── Resize (hold prefix + arrow) ─────────────────────────────────
|
|
bind -r H resize-pane -L 5
|
|
bind -r J resize-pane -D 5
|
|
bind -r K resize-pane -U 5
|
|
bind -r L resize-pane -R 5
|
|
|
|
# ── Copy mode (vi-style) ─────────────────────────────────────────
|
|
setw -g mode-keys vi
|
|
bind v copy-mode
|
|
bind -T copy-mode-vi v send -X begin-selection
|
|
bind -T copy-mode-vi y send -X copy-selection-and-cancel
|
|
|
|
# ── Status bar ───────────────────────────────────────────────────
|
|
set -g status-position top
|
|
set -g status-style "bg=default,fg=white"
|
|
set -g status-left-length 40
|
|
set -g status-right-length 80
|
|
|
|
set -g status-left "#[fg=blue,bold] #S #[fg=brightblack]│ "
|
|
set -g status-right "#[fg=brightblack]│ #[fg=cyan] %H:%M"
|
|
|
|
# Window tabs
|
|
set -g window-status-format "#[fg=brightblack] #I:#W "
|
|
set -g window-status-current-format "#[fg=cyan,bold] #I:#W "
|
|
set -g window-status-separator ""
|
|
|
|
# Pane borders
|
|
set -g pane-border-style "fg=brightblack"
|
|
set -g pane-active-border-style "fg=cyan"
|
|
|
|
# ── Quick reload ─────────────────────────────────────────────────
|
|
bind r source-file ~/.tmux.conf \; display "Config reloaded"
|
|
'';
|
|
|
|
# Zsh config
|
|
zshrc = pkgs.writeText "logos-zshrc" ''
|
|
# ── Zsh options ────────────────────────────────────────────────────
|
|
setopt AUTO_CD
|
|
setopt HIST_IGNORE_DUPS
|
|
setopt HIST_IGNORE_SPACE
|
|
setopt SHARE_HISTORY
|
|
setopt EXTENDED_HISTORY
|
|
setopt INC_APPEND_HISTORY
|
|
HISTFILE=''${HOME}/.zsh_history
|
|
HISTSIZE=50000
|
|
SAVEHIST=50000
|
|
|
|
# ── Completion ─────────────────────────────────────────────────────
|
|
autoload -Uz compinit && compinit
|
|
zstyle ':completion:*' menu select
|
|
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
|
|
zstyle ':completion:*' list-colors "''${(s.:.)LS_COLORS}"
|
|
zstyle ':completion:*:descriptions' format '%F{cyan}-- %d --%f'
|
|
zstyle ':completion:*' group-name '''
|
|
|
|
# ── ws tab completion ─────────────────────────────────────────────
|
|
_ws() {
|
|
local -a commands
|
|
commands=(
|
|
'init:Clone all submodules'
|
|
'list:List all repos and their status'
|
|
'build:Build a repo via nix'
|
|
'run:Build and run a repo'
|
|
'develop:Enter a nix devShell'
|
|
'test:Run checks/tests'
|
|
'status:Git status across all repos'
|
|
'dirty:Show dirty repos and what they affect'
|
|
'graph:Show dependency graph'
|
|
'override-inputs:Show nix override flags'
|
|
'update:Update flake.lock inputs'
|
|
'loc:Count lines of code'
|
|
'watch:Auto-run commands on file changes'
|
|
'foreach:Run a command in every repo'
|
|
'worktree:Manage worktrees'
|
|
'sync-graph:Regenerate dep-graph.nix'
|
|
'help:Show help'
|
|
)
|
|
local -a repos
|
|
repos=($(ls "$LOGOS_WORKSPACE_ROOT/repos/" 2>/dev/null))
|
|
|
|
if (( CURRENT == 2 )); then
|
|
_describe 'command' commands
|
|
elif (( CURRENT == 3 )); then
|
|
case "''${words[2]}" in
|
|
build|run|develop|test|graph|update|override-inputs|loc)
|
|
_describe 'repo' repos
|
|
;;
|
|
watch)
|
|
local -a watch_cmds
|
|
watch_cmds=('test:Re-run tests on change' 'build:Re-build on change' 'run:Run command on change')
|
|
_describe 'subcommand' watch_cmds
|
|
;;
|
|
worktree)
|
|
local -a wt_cmds
|
|
wt_cmds=('add:Create a worktree' 'list:List worktrees' 'remove:Remove a worktree')
|
|
_describe 'subcommand' wt_cmds
|
|
;;
|
|
esac
|
|
elif (( CURRENT >= 4 )); then
|
|
case "''${words[2]}" in
|
|
build|run|develop|override-inputs)
|
|
local -a opts
|
|
opts=('--auto-local' '--local' '--fresh')
|
|
_describe 'option' opts
|
|
;;
|
|
test)
|
|
local -a opts
|
|
opts=('--all' '--type')
|
|
_describe 'option' opts
|
|
;;
|
|
loc)
|
|
local -a opts
|
|
opts=('--all' '--no-nix' '--code-only')
|
|
_describe 'option' opts
|
|
;;
|
|
watch)
|
|
_describe 'repo' repos
|
|
;;
|
|
esac
|
|
fi
|
|
}
|
|
compdef _ws ws
|
|
|
|
# ── Plugins ────────────────────────────────────────────────────────
|
|
source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh
|
|
source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
|
|
source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh
|
|
|
|
# History substring search keybindings (up/down arrows)
|
|
bindkey '^[[A' history-substring-search-up
|
|
bindkey '^[[B' history-substring-search-down
|
|
|
|
# Autosuggestions — accept with right arrow or end key
|
|
ZSH_AUTOSUGGEST_STRATEGY=(history completion)
|
|
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=244"
|
|
|
|
# ── Aliases ────────────────────────────────────────────────────────
|
|
# ls wrapper — translates common ls flags to eza equivalents
|
|
ls() {
|
|
local args=()
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
-ltra|-lart|-latr) args+=(--long --all --sort=modified --reverse) ;;
|
|
-ltr|-lrt) args+=(--long --sort=modified --reverse) ;;
|
|
-la|-al) args+=(--long --all) ;;
|
|
-lt|-tl) args+=(--long --sort=modified) ;;
|
|
*) args+=("$arg") ;;
|
|
esac
|
|
done
|
|
eza --icons=auto --group-directories-first "''${args[@]}"
|
|
}
|
|
alias ll='eza --icons=auto --group-directories-first -la'
|
|
alias lt='eza --icons=auto --tree --level=3'
|
|
alias la='eza --icons=auto --group-directories-first -a'
|
|
alias cat='bat --paging=never --style=plain'
|
|
alias less='bat --paging=always'
|
|
alias vim='nvim'
|
|
alias vi='nvim'
|
|
alias cd='z'
|
|
|
|
# ws shortcuts
|
|
alias wss='ws status'
|
|
alias wsb='ws build'
|
|
alias wst='ws test'
|
|
alias wsd='ws dirty'
|
|
alias wsg='ws graph'
|
|
|
|
# git shortcuts
|
|
alias gst='git status'
|
|
alias gs='git status -s'
|
|
alias ga='git add'
|
|
alias gc='git commit'
|
|
alias gcm='git commit -m'
|
|
alias gd='git diff'
|
|
alias gds='git diff --staged'
|
|
alias gl='git log --oneline --graph --decorate -20'
|
|
alias glog='git log --graph --decorate --oneline --all'
|
|
alias gp='git pull'
|
|
alias gps='git push'
|
|
alias gco='git checkout'
|
|
alias gb='git branch'
|
|
alias gcp='git cherry-pick'
|
|
alias grb='git rebase'
|
|
alias lg='lazygit'
|
|
|
|
# ── Environment ────────────────────────────────────────────────────
|
|
export EDITOR=nvim
|
|
export VISUAL=nvim
|
|
export PAGER='less -R'
|
|
export MANPAGER="sh -c 'col -bx | bat -l man -p'"
|
|
|
|
# Git — use delta as pager via env vars only (no global config changes)
|
|
export GIT_PAGER='delta --paging=always'
|
|
export DELTA_PAGER='less -R'
|
|
export GIT_CONFIG_COUNT=4
|
|
export GIT_CONFIG_KEY_0="delta.navigate"
|
|
export GIT_CONFIG_VALUE_0="true"
|
|
export GIT_CONFIG_KEY_1="delta.side-by-side"
|
|
export GIT_CONFIG_VALUE_1="true"
|
|
export GIT_CONFIG_KEY_2="delta.line-numbers"
|
|
export GIT_CONFIG_VALUE_2="true"
|
|
export GIT_CONFIG_KEY_3="diff.submodule"
|
|
export GIT_CONFIG_VALUE_3="diff"
|
|
|
|
# Starship prompt
|
|
export STARSHIP_CONFIG="${starshipConfig}"
|
|
eval "$(starship init zsh)"
|
|
|
|
# fzf — fuzzy finder + keybindings (Ctrl-T, Ctrl-R, Alt-C)
|
|
source <(fzf --zsh)
|
|
export FZF_DEFAULT_OPTS='--height=40% --layout=reverse --border --margin=0,1'
|
|
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
|
|
export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND"
|
|
export FZF_ALT_C_COMMAND='fd --type d --hidden --follow --exclude .git'
|
|
|
|
# zoxide
|
|
eval "$(zoxide init zsh)"
|
|
|
|
|
|
# ── Workspace ──────────────────────────────────────────────────────
|
|
export LOGOS_WORKSPACE_ROOT="''${LOGOS_WORKSPACE_ROOT:-$(pwd)}"
|
|
export PATH="$LOGOS_WORKSPACE_ROOT/scripts:$PATH"
|
|
|
|
# ── Welcome ────────────────────────────────────────────────────────
|
|
if [[ -z "$LOGOS_WELCOMED" ]]; then
|
|
export LOGOS_WELCOMED=1
|
|
echo ""
|
|
echo -e "\033[1;36m Logos Workspace\033[0m"
|
|
echo -e "\033[0;90m ─────────────────────────────────────────────────────\033[0m"
|
|
echo -e " \033[1mws help\033[0m Commands \033[0;90m│\033[0m \033[1mCtrl-A |\033[0m Split horizontal"
|
|
echo -e " \033[1mws status\033[0m Repo status \033[0;90m│\033[0m \033[1mCtrl-A -\033[0m Split vertical"
|
|
echo -e " \033[1mws dirty\033[0m Impact \033[0;90m│\033[0m \033[1mCtrl-A c\033[0m New tab"
|
|
echo -e " \033[1mws graph\033[0m Dep graph \033[0;90m│\033[0m \033[1mCtrl-A d\033[0m Detach"
|
|
echo -e "\033[0;90m ─────────────────────────────────────────────────────\033[0m"
|
|
echo -e " \033[0;90mCtrl-R: history search Ctrl-T: file search Tab: complete\033[0m"
|
|
echo ""
|
|
fi
|
|
'';
|
|
|
|
# Wrapper script that launches zsh inside tmux
|
|
enterShell = pkgs.writeShellScriptBin "logos-shell" ''
|
|
export ZDOTDIR=$(mktemp -d)
|
|
cp ${zshrc} "$ZDOTDIR/.zshrc"
|
|
# Suppress macOS /etc/zshrc "locale: command not found" error
|
|
echo 'locale() { :; }' > "$ZDOTDIR/.zshenv"
|
|
|
|
# Derive a unique tmux session name from the workspace root directory
|
|
# so each worktree/fork gets its own session
|
|
_ws_root="''${LOGOS_WORKSPACE_ROOT:-$(pwd)}"
|
|
_session_name="logos-$(echo "$_ws_root" | md5sum | cut -c1-8)"
|
|
|
|
# Launch tmux with zsh, or attach if session exists
|
|
if command -v tmux &>/dev/null; then
|
|
if tmux has-session -t "$_session_name" 2>/dev/null; then
|
|
exec tmux attach -t "$_session_name"
|
|
else
|
|
tmux -f ${tmuxConfig} new-session -d -s "$_session_name" -n workspace
|
|
tmux set-environment -t "$_session_name" ZDOTDIR "$ZDOTDIR"
|
|
tmux set-environment -t "$_session_name" STARSHIP_CONFIG "${starshipConfig}"
|
|
tmux set-environment -t "$_session_name" GIT_PAGER "delta --paging=always"
|
|
tmux set-environment -t "$_session_name" DELTA_PAGER "less -R"
|
|
tmux set-environment -t "$_session_name" LOGOS_WORKSPACE_ROOT "$_ws_root"
|
|
tmux set-environment -t "$_session_name" PATH "$PATH"
|
|
exec tmux attach -t "$_session_name"
|
|
fi
|
|
else
|
|
exec ${pkgs.zsh}/bin/zsh
|
|
fi
|
|
'';
|
|
|
|
in pkgs.mkShell {
|
|
name = "logos-workspace";
|
|
|
|
packages = with pkgs; [
|
|
# ── Core ──────────────────────────────────────────────────────────
|
|
git
|
|
openssh
|
|
jq
|
|
nix
|
|
wsScript
|
|
|
|
# ── Shell ─────────────────────────────────────────────────────────
|
|
zsh
|
|
zsh-autosuggestions
|
|
zsh-syntax-highlighting
|
|
zsh-history-substring-search
|
|
starship # cross-shell prompt
|
|
tmux # terminal multiplexer
|
|
|
|
# ── Fuzzy & Navigation ────────────────────────────────────────────
|
|
fzf # fuzzy finder (Ctrl-R, Ctrl-T)
|
|
fd # fast find (used by fzf)
|
|
zoxide # smart cd
|
|
|
|
# ── Modern CLI replacements ───────────────────────────────────────
|
|
eza # modern ls
|
|
bat # modern cat
|
|
ripgrep # modern grep
|
|
delta # modern diff / git pager
|
|
htop # modern top
|
|
dust # modern du
|
|
duf # modern df
|
|
procs # modern ps
|
|
|
|
# ── Git ───────────────────────────────────────────────────────────
|
|
lazygit # interactive git TUI
|
|
|
|
# ── Code analysis & docs ─────────────────────────────────────────
|
|
tokei # lines of code counter
|
|
glow # markdown renderer
|
|
|
|
# ── File watching ────────────────────────────────────────────────
|
|
watchexec # run commands on file changes
|
|
|
|
# ── Editor ────────────────────────────────────────────────────────
|
|
neovim
|
|
|
|
# ── Build tools ───────────────────────────────────────────────────
|
|
cmake
|
|
ninja
|
|
pkg-config
|
|
];
|
|
|
|
shellHook = ''
|
|
exec ${enterShell}/bin/logos-shell
|
|
'';
|
|
}
|