]> git.rmz.io Git - dotfiles.git/commitdiff
zsh: vi-mode and new prompt
authorSamir Benmendil <samir.benmendil@gmail.com>
Mon, 15 Jun 2015 01:51:26 +0000 (02:51 +0100)
committerSamir Benmendil <samir.benmendil@gmail.com>
Mon, 15 Jun 2015 01:52:09 +0000 (02:52 +0100)
zsh/lib/00-key-bindings.zsh
zsh/lib/git.zsh [deleted file]
zsh/lib/prompt.zsh [new file with mode: 0644]
zsh/themes/ramsi.zsh-theme [deleted file]

index 803ec37cf14223f81a9e033ab363a3ac71edf8ed..7fd00e545280dd461cf3b28db7b92a3c3d51a4cf 100644 (file)
@@ -1,33 +1,59 @@
-# TODO: Explain what some of this does..
+bindkey -v
 
-bindkey -e
-bindkey -s '\el' "ls\n"
-bindkey '\ew'   kill-region
-bindkey '^r'    history-incremental-search-backward
-bindkey "^[[5~" up-line-or-history
-bindkey "^[[6~" down-line-or-history
+bindkey '^N' history-search-forward
+bindkey '^P' history-search-backward
+bindkey ' '  magic-space    # also do history expansion on space
 
-# make search up and down work, so partially type and hit up/down to find relevant stuff
-bindkey '^[[A'  up-line-or-search   # up arrow
-bindkey '^[[B'  down-line-or-search # down arrow
-
-bindkey "^[[H"  beginning-of-line
-bindkey "^[[1~" beginning-of-line
-bindkey "^[OH"  beginning-of-line
-bindkey "\e[7~" beginning-of-line
-bindkey "^[[F"  end-of-line
-bindkey "^[[4~" end-of-line
-bindkey "\e[8~" end-of-line
-bindkey "^[OF"  end-of-line
-bindkey ' '     magic-space    # also do history expansion on space
-
-bindkey "^[[1;5C" forward-word
-bindkey "^[[1;5D" backward-word
+bindkey -s '^[l' '\11ls\r' # show dir content
 
 bindkey '^[[Z' reverse-menu-complete
 
+bindkey -M vicmd 'v' edit-command-line
+
+# delay after ESC (in 0.01s)
+export KEYTIMEOUT=40
+
+# emacs bindings
+bindkey '^A'  beginning-of-line
+bindkey '^B'  backward-char
+bindkey '^E'  end-of-line
+bindkey '^F'  edit-command-line
+bindkey '^G'  list-expand
+bindkey '^O'  accept-line-and-down-history
+bindkey '^Q'  push-input
+bindkey '^?'  backward-delete-char
+bindkey '^H'  backward-delete-char
+bindkey '^W'  backward-kill-word
+bindkey '^X=' what-cursor-position
+bindkey '^[.' insert-last-word
+bindkey '^[?' which-command
+bindkey '^[A' accept-and-hold
+bindkey '^[a' accept-and-hold
+bindkey '^[C' capitalize-word
+bindkey '^[c' capitalize-word
+bindkey '^[H' run-help
+bindkey '^[h' run-help
+bindkey '^[T' transpose-words
+bindkey '^[t' transpose-words
+
+# make search up and down work, so partially type and hit up/down to find relevant stuff
+bindkey '^[[A'  up-line-or-search    # up arrow
+bindkey '^[[B'  down-line-or-search  # down arrow
+bindkey '^[[5~' up-line-or-history   # PgUp
+bindkey '^[[6~' down-line-or-history # PgDown
+
+bindkey '^[OA' up-line-or-history
+bindkey '^[OB' down-line-or-history
+bindkey '^[OC' forward-char
+bindkey '^[OD' backward-char
+bindkey '^[OF' end-of-line
+bindkey '^[OH' beginning-of-line
+
+bindkey '\e[c' forward-word
+bindkey '\e[d' backward-word
+
 # Make the delete key (or Fn + Delete on the Mac) work instead of outputting a ~
 bindkey '^?'     backward-delete-char
-bindkey "^[[3~"  delete-char
-bindkey "^[3;5~" delete-char
-bindkey "\e[3~"  delete-char
+bindkey '^[[3~'  delete-char
+bindkey '^[3;5~' delete-char
+bindkey '\e[3~'  delete-char
diff --git a/zsh/lib/git.zsh b/zsh/lib/git.zsh
deleted file mode 100644 (file)
index bffd284..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-# get the name of the branch we are on
-function git_prompt_info() {
-  ref=$(git symbolic-ref HEAD 2> /dev/null) || \
-  ref=$(git rev-parse --short HEAD 2> /dev/null) || return
-  echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$ZSH_THEME_GIT_PROMPT_SUFFIX"
-}
-
-
-# Checks if working tree is dirty
-parse_git_dirty() {
-  if [[ -n $(git status -s 2> /dev/null) ]]; then
-    echo "$ZSH_THEME_GIT_PROMPT_DIRTY"
-  else
-    echo "$ZSH_THEME_GIT_PROMPT_CLEAN"
-  fi
-}
-
-# get the difference between the local and remote branches
-git_remote_status() {
-    remote=${$(git rev-parse --verify ${hook_com[branch]}@{upstream} --symbolic-full-name 2>/dev/null)/refs\/remotes\/}
-    if [[ -n ${remote} ]] ; then
-        ahead=$(git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l)
-        behind=$(git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l)
-
-        if [ $ahead -eq 0 ] && [ $behind -gt 0 ]
-        then
-            echo "$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE"
-        elif [ $ahead -gt 0 ] && [ $behind -eq 0 ]
-        then
-            echo "$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE"
-        elif [ $ahead -gt 0 ] && [ $behind -gt 0 ]
-        then
-            echo "$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE"
-        fi
-    fi
-}
-
-# Checks if there are commits ahead from remote
-function git_prompt_ahead() {
-  if $(echo "$(git log origin/$(current_branch)..HEAD 2> /dev/null)" | grep '^commit' &> /dev/null); then
-    echo "$ZSH_THEME_GIT_PROMPT_AHEAD"
-  fi
-}
-
-# Formats prompt string for current git commit short SHA
-function git_prompt_short_sha() {
-  SHA=$(git rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER"
-}
-
-# Formats prompt string for current git commit long SHA
-function git_prompt_long_sha() {
-  SHA=$(git rev-parse HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER"
-}
-
-# Get the status of the working tree
-git_prompt_status() {
-  INDEX=$(git status --porcelain -b 2> /dev/null)
-  STATUS=""
-  if $(echo "$INDEX" | grep '^?? ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_UNTRACKED$STATUS"
-  fi
-  if $(echo "$INDEX" | grep '^A  ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS"
-  elif $(echo "$INDEX" | grep '^M  ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_ADDED$STATUS"
-  fi
-  if $(echo "$INDEX" | grep '^ M ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
-  elif $(echo "$INDEX" | grep '^AM ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
-  elif $(echo "$INDEX" | grep '^ T ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_MODIFIED$STATUS"
-  fi
-  if $(echo "$INDEX" | grep '^R  ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_RENAMED$STATUS"
-  fi
-  if $(echo "$INDEX" | grep '^ D ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
-  elif $(echo "$INDEX" | grep '^D  ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
-  elif $(echo "$INDEX" | grep '^AD ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_DELETED$STATUS"
-  fi
-  if $(git rev-parse --verify refs/stash >/dev/null 2>&1); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_STASHED$STATUS"
-  fi
-  if $(echo "$INDEX" | grep '^UU ' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_UNMERGED$STATUS"
-  fi
-  if $(echo "$INDEX" | grep '^## .*ahead' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_AHEAD$STATUS"
-  fi
-  if $(echo "$INDEX" | grep '^## .*behind' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_BEHIND$STATUS"
-  fi
-  if $(echo "$INDEX" | grep '^## .*diverged' &> /dev/null); then
-    STATUS="$ZSH_THEME_GIT_PROMPT_DIVERGED$STATUS"
-  fi
-  echo $STATUS
-}
diff --git a/zsh/lib/prompt.zsh b/zsh/lib/prompt.zsh
new file mode 100644 (file)
index 0000000..4f31348
--- /dev/null
@@ -0,0 +1,112 @@
+hostcolor=green
+[[ $(hostname) == "tardis" ]]  && hostcolor=red
+
+precmd() {
+  PROMPT='%T %n@%{$fg[$hostcolor]%}%m%{$reset_color%}%-0>..>$(git_prompt_status)%>>
+%(?..%{$fg_bold[white]%}%?%{$reset_color%})$(vi_prompt_info)%{%(!.$fg[red]❰.$fg[green]❱)%1G%} '
+  RPROMPT='%{$fg[green]%}%~%{$reset_color%}'
+}
+
+vi_prompt_info() {
+  local vicmd="$fg_bold[green]❰$reset_color%1G"
+  local viins="$fg_bold[blue]❱$reset_color%1G"
+  printf '%s' "%{${${KEYMAP/vicmd/$vicmd}/(main|viins)/$viins}%}"
+}
+
+function zle-line-init zle-line-finish zle-keymap-select {
+  zle reset-prompt
+  zle -R
+}
+
+zle -N zle-line-init
+zle -N zle-line-finish
+zle -N zle-keymap-select
+
+# reset zle on resize
+TRAPWINCH() {
+  zle && { zle reset-prompt; zle -R  }
+}
+
+# Get the status of the working tree
+git_prompt_status() {
+  local branch ahead behind 
+  local added deleted modified renamed unmerged untracked dirty
+  # Use porcelain status for easy parsing.
+  local status_cmd="git status --porcelain -b"
+
+  # Get current status.
+  while IFS=$'\n' read line; do
+    if [[ "$line" == \#\#\ * ]]; then
+      [[ "$line" =~ '## ([^.]*)\.\.\.(.*)' ]] && branch=$match[1]
+      [[ "$line" =~ 'ahead ([0-9]+)'  ]]      && ahead=$match[1]
+      [[ "$line" =~ 'behind ([0-9]+)'  ]]     && behind=$match[1]
+    else
+      # Count added, deleted, modified, renamed, unmerged, untracked, dirty.
+      # T (type change) is undocumented, see http://git.io/FnpMGw.
+      # index
+      [[ "$line" == M[\ MTD]\ * ]]      && (( updated++ ))
+      [[ "$line" == [AC][\ MTD]\ * ]]   && (( added++ ))
+      [[ "$line" == D[\ MT]\ * ]]       && (( deleted++ ))
+      [[ "$line" == R[\ MTD]\ * ]]      && (( renamed++ ))
+
+      # work tree
+      [[ "$line" == [\ MARCT]M\ * ]]    && (( modified++ ))
+      [[ "$line" == [\ MARCT]D\ * ]]    && (( deleted_wt++ ))
+      [[ "$line" == \?\?\ * ]]          && (( untracked++ ))
+
+      # morge conflicts
+      [[ "$line" == (AA|DD|U?|?U)\ * ]] && (( unmerged++ ))
+    fi
+  done < <(${(z)status_cmd} 2> /dev/null)
+
+  local git_status=" %{$fg[yellow]%}"
+
+  # Format branch
+  if [[ -n $branch ]]; then
+    git_status+="$branch"
+  else
+    git_status+="$(git rev-parse --short HEAD 2> /dev/null)"
+    [[ $? -ne 0 ]] && return
+  fi
+
+  # Format upstream
+  local upstream_str
+  (( ahead  > 0 )) && upstream_str+="%{$fg[blue]%} >$ahead"
+  (( behind > 0 )) && upstream_str+="%{$fg[blue]%} <$behind"
+  git_status+="$upstream_str"
+
+  # Format stashed
+  stashed=$(git stash list | wc -l)
+  if (( stashed > 0 )) then
+    stashed_str+="%{$fg_bold[cyan]%} ⋎$stashed%{$reset_color%}"
+  fi
+  git_status+="$stashed_str"
+
+  # Format index
+  local index_str
+  (( updated > 0 )) && index_str+="%{$fg[green]%} *$updated"
+  (( added   > 0 )) && index_str+="%{$fg[green]%} +$added"
+  (( deleted > 0 )) && index_str+="%{$fg[green]%} -$deleted"
+  (( renamed > 0 )) && index_str+="%{$fg[green]%} ≈$renamed"
+  git_status+="$index_str"
+
+  # Format working tree
+  local wt_str
+  (( modified   > 0 )) && wt_str+="%{$fg[red]%} *$modified"
+  (( deleted_wt > 0 )) && wt_str+="%{$fg[red]%} -$deleted_wt"
+  (( untracked  > 0 )) && wt_str+="%{$fg[red]%} +$untracked"
+  (( unmerged   > 0 )) && wt_str+="%{$fg[magenta]%} ♒$unmerged"
+  git_status+="$wt_str"
+
+  git_status+="%{$reset_color%}"
+
+  echo $git_status
+}
+
+function print_if_fits() {
+  local zero length
+
+  zero='%([BSUbfksu]|([FB]|){*})'
+  length=${#${(S%%)1//$~zero/}}
+  echo "%-$length(l.$1.)"
+}
diff --git a/zsh/themes/ramsi.zsh-theme b/zsh/themes/ramsi.zsh-theme
deleted file mode 100644 (file)
index 8964a07..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-[[ $(hostname) == "tardis" ]]  && hostcolor=red
-[[ $(hostname) == "shada" ]]   && hostcolor=green
-PROMPT='%(?..%{$fg_bold[white]%}[%?])%{$reset_color%}[%D{%k:%M} %n@%{$fg[$hostcolor]%}%m%{$reset_color%}$(git_prompt_info)]%# '
-RPROMPT='%{$fg[green]%}%~%{$reset_color%}'
-
-ZSH_THEME_GIT_PROMPT_PREFIX=" %{$fg[yellow]%}<"
-ZSH_THEME_GIT_PROMPT_SUFFIX=">%{$reset_color%}"
-ZSH_THEME_GIT_PROMPT_DIRTY="*"
-ZSH_THEME_GIT_PROMPT_CLEAN=""