This commit is contained in:
2025-06-11 07:45:20 +09:00
parent eb436e9b3a
commit 359cabaf59

244
airline.zsh Normal file
View File

@ -0,0 +1,244 @@
#!/usr/bin/env zsh
# ================================
# airline.zsh - Modern ZSH Prompt
# ================================
# Clean, fast powerline-style prompt with ai.moji support
# Author: syui
# License: MIT
# ================================
# Core Configuration
# ================================
# Theme colors (256-color palette)
typeset -gA AIRLINE_THEME
AIRLINE_THEME=(
dir_bg 33 # Blue
dir_fg 15 # White
git_bg 2 # Green
git_fg 0 # Black
os_bg 5 # Magenta
os_fg 15 # White
mode_normal 1 # Red
mode_insert 6 # Cyan
mode_emacs 3 # Yellow
)
# Powerline separators
if [[ "$OSTYPE" == "darwin"* ]]; then
readonly AIRLINE_SEP=""
readonly AIRLINE_RSEP=""
else
readonly AIRLINE_SEP=""
readonly AIRLINE_RSEP=""
fi
# ================================
# Icon System
# ================================
function _airline_setup_icons() {
typeset -gA AIRLINE_ICONS
# Check for ai.moji font
# git clone https://git.syui.ai/ai/moji
if [[ -f ~/.local/share/fonts/aimoji.ttf ]] || [[ -f ~/.fonts/aimoji.ttf ]]; then
# ai.moji icons (placeholder - update when font is ready)
AIRLINE_ICONS=(
dir ""
branch ""
staged ""
unstaged ""
untrack ""
clean ""
os_mac ""
os_arch ""
os_linux ""
)
else
# Unicode fallback
AIRLINE_ICONS=(
dir "📁"
branch "🌿"
staged "+"
unstaged "~"
untrack "?"
clean "✓"
os_mac "🍎"
os_arch "🏔️"
os_linux "🐧"
)
fi
# OS-specific icon
case "$OSTYPE" in
darwin*)
AIRLINE_ICONS[os]="${AIRLINE_ICONS[os_mac]}"
;;
linux*)
if [[ -f /etc/arch-release ]]; then
AIRLINE_ICONS[os]="${AIRLINE_ICONS[os_arch]}"
else
AIRLINE_ICONS[os]="${AIRLINE_ICONS[os_linux]}"
fi
;;
*)
AIRLINE_ICONS[os]="💻"
;;
esac
}
# ================================
# Color Functions
# ================================
function _airline_color() {
echo "%{\e[38;5;${1}m%}"
}
function _airline_bg() {
echo "%{\e[48;5;${1}m%}"
}
function _airline_reset() {
echo "%{\e[0m%}"
}
# ================================
# Segment Builder
# ================================
function _airline_segment() {
local bg="$1" fg="$2" content="$3" next_bg="${4:-reset}"
local out=""
out+="$(_airline_bg $bg)$(_airline_color $fg) $content "
if [[ "$next_bg" != "reset" ]]; then
out+="$(_airline_bg $next_bg)$(_airline_color $bg)$AIRLINE_SEP"
else
out+="$(_airline_reset)$(_airline_color $bg)$AIRLINE_SEP$(_airline_reset)"
fi
echo "$out"
}
# ================================
# Information Providers
# ================================
function _airline_dir() {
local content="${AIRLINE_ICONS[dir]} %~"
echo "$(_airline_segment ${AIRLINE_THEME[dir_bg]} ${AIRLINE_THEME[dir_fg]} "$content" ${AIRLINE_THEME[git_bg]})"
}
function _airline_git() {
# Early return if not in git repo
git rev-parse --git-dir >/dev/null 2>&1 || return
local branch_name content git_status=""
branch_name=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null)
# Get status counts
local staged unstaged untracked
staged=$(git diff --cached --name-only 2>/dev/null | wc -l | tr -d ' ')
unstaged=$(git diff --name-only 2>/dev/null | wc -l | tr -d ' ')
untracked=$(git ls-files --other --exclude-standard 2>/dev/null | wc -l | tr -d ' ')
# Build status indicator
if [[ $staged -gt 0 || $unstaged -gt 0 || $untracked -gt 0 ]]; then
[[ $staged -gt 0 ]] && git_status+=" $(_airline_color 15)${AIRLINE_ICONS[staged]}$staged"
[[ $unstaged -gt 0 ]] && git_status+=" $(_airline_color 9)${AIRLINE_ICONS[unstaged]}$unstaged"
[[ $untracked -gt 0 ]] && git_status+=" $(_airline_color 11)${AIRLINE_ICONS[untrack]}$untracked"
git_status+="$(_airline_color ${AIRLINE_THEME[git_fg]})"
else
git_status=" $(_airline_color 10)${AIRLINE_ICONS[clean]}$(_airline_color ${AIRLINE_THEME[git_fg]})"
fi
content="${AIRLINE_ICONS[branch]} $branch_name$git_status"
echo "$(_airline_segment ${AIRLINE_THEME[git_bg]} ${AIRLINE_THEME[git_fg]} "$content" ${AIRLINE_THEME[os_bg]})"
}
function _airline_os() {
local content="${AIRLINE_ICONS[os]}"
echo "$(_airline_segment ${AIRLINE_THEME[os_bg]} ${AIRLINE_THEME[os_fg]} "$content")"
}
# ================================
# Vi Mode Indicator
# ================================
function _airline_mode() {
local mode_bg mode_fg mode_text
case "${KEYMAP:-main}" in
vicmd)
mode_bg="${AIRLINE_THEME[mode_normal]}"
mode_fg="15"
mode_text="NORMAL"
;;
main|viins)
mode_bg="${AIRLINE_THEME[mode_insert]}"
mode_fg="0"
mode_text="INSERT"
;;
*)
mode_bg="${AIRLINE_THEME[mode_emacs]}"
mode_fg="0"
mode_text="EMACS"
;;
esac
echo "$(_airline_bg $mode_bg)$(_airline_color $mode_fg) $mode_text $(_airline_reset)"
}
# ================================
# Main Prompt Functions
# ================================
function airline_prompt() {
local segments=""
segments+="$(_airline_dir)"
segments+="$(_airline_git)"
segments+="$(_airline_os)"
echo "$segments "
}
function airline_rprompt() {
echo "$(_airline_mode)"
}
# ================================
# Setup and Initialization
# ================================
function airline_setup() {
# Initialize icons
_airline_setup_icons
# Vi mode setup
function zle-keymap-select() {
zle reset-prompt
}
zle -N zle-keymap-select
# Key bindings
bindkey '^E' emacs
bindkey '^V' vi-cmd-mode
# Enable prompt substitution
setopt PROMPT_SUBST
# Set prompts
PROMPT='$(airline_prompt)'
RPROMPT='$(airline_rprompt)'
}
# ================================
# Auto-initialize
# ================================
# Only setup if being sourced (not in subshell)
if [[ "${(%):-%N}" == *airline.zsh ]]; then
airline_setup
fi