summaryrefslogtreecommitdiff
path: root/agnoster.zsh-theme
blob: 0bc1c45aa2ca1407756ed924daed4827fb6ee3ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# vim:ft=zsh ts=2 sw=2 sts=2
#
# based on agnoster's theme - https://gist.github.com/3712874

### Segment drawing
# A few utility functions to make it easy and re-usable to draw segmented prompts

CURRENT_BG='NONE'
SSH_BG=green
PRIMARY_FG=black

# Characters
SEGMENT_SEPARATOR="\ue0b0"  # 
PLUSMINUS="\u00b1"          # ±
BRANCH="\ue0a0"             # 
DETACHED="\u27a6"           # ➦
#CROSS="\u2718"              # ✘
CROSS="\u274C"              # ❌
LIGHTNING="\u26a1"          # ⚡
GEAR="\u2699"               # ⚙
ARROW="\u2197"              # ↗
STAR="\u2217"               # ∗

# Begin a segment
# Takes two arguments, background and foreground. Both can be omitted,
# rendering default background/foreground.
prompt_segment() {
  local bg fg
  [[ -n $1 ]] && bg="%K{$1}" || bg="%k"
  [[ -n $2 ]] && fg="%F{$2}" || fg="%f"
  if [[ $CURRENT_BG != 'NONE' && $1 != $CURRENT_BG ]]; then
    echo -n " %{$bg%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR%{$fg%} "
  else
    echo -n "%{$bg%}%{$fg%} "
  fi
  CURRENT_BG=$1
  [[ -n $3 ]] && echo -n $3
}

# End the prompt, closing any open segments
prompt_end() {
  if [[ -n $CURRENT_BG ]]; then
    echo -n " %{%k%F{$CURRENT_BG}%}$SEGMENT_SEPARATOR"
  else
    echo -n "%{%k%}"
  fi
  echo -n "%{%f%}"
  CURRENT_BG=''
}

### Prompt components
# Each component will draw itself, and hide itself if no information needs to be shown

# Context: user@hostname (who am I and where am I)
prompt_context() {
  local user=`whoami`

  if [[ "$user" != "$USER" || -n "$SSH_CONNECTION" ]]; then
    prompt_segment $SSH_BG $PRIMARY_FG "%(!.%{%F{yellow}%}.)$user@%m"
  fi
}

# Git: branch/detached head, dirty status
prompt_git() {
  local color ref dirty
  if $(git rev-parse --is-inside-work-tree 2> /dev/null); then
    if [[ -n $(git status -s --ignore-submodules=dirty 2> /dev/null) ]]; then
      color=yellow
    else
      color=green
    fi

    git diff --no-ext-diff --ignore-submodules --quiet --exit-code || dirty="$STAR"

    ref=$(git symbolic-ref HEAD 2> /dev/null) || ref="$DETACHED $(git show-ref --head -s --abbrev | head -n1 2> /dev/null)"

    if git rev-parse --quiet --verify HEAD >/dev/null; then
      git diff-index --cached --quiet --ignore-submodules HEAD -- || index="$PLUSMINUS"
    else
      index="#"
    fi

    if $(git status -b --porcelain | grep '\[ahead' &> /dev/null); then
      push="$ARROW"
    fi

    prompt_segment $color $PRIMARY_FG
    echo -n "${ref/refs\/heads\//}${dirty}${index}${push}"
  fi
}

# Dir: current working directory
prompt_dir() {
  prompt_segment blue $PRIMARY_FG '%~'
}

# Status:
# - was there an error
# - am I root
# - are there background jobs?
prompt_status() {
  local symbols
  symbols=()
  [[ $(jobs -l | wc -l) -gt 0 ]] && symbols+="%{%F{cyan}%}$GEAR"

  [[ -n "$symbols" ]] && prompt_segment $PRIMARY_FG default "$symbols"
}

prompt_vi_mode() {
  [[ "$KEYMAP" == "vicmd" ]] && prompt_segment cyan $PRIMARY_FG "$CROSS"
}

prompt_agnoster_setup () {
  build_prompt() {
    prompt_vi_mode
    prompt_status
    prompt_context
    prompt_dir
    prompt_git
    prompt_end
  }

  function zle-keymap-select zle-line-init zle-line-finish {
    zle reset-prompt
    zle -R
  }

  zle -N zle-line-init
  zle -N zle-line-finish
  zle -N zle-keymap-select

  PROMPT='%{%f%b%k%}$(build_prompt) '
}

prompt_agnoster_setup "$@"