diff --git a/.gitmodules b/.gitmodules index 239b94e..5fc8049 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,18 @@ [submodule "vim/pack/normal/start/vim-elixir"] path = vim/pack/normal/start/vim-elixir url = https://github.com/elixir-editors/vim-elixir +[submodule "zsh/bullet-train.zsh"] + path = zsh/bullet-train.zsh + url = https://github.com/caiogondim/bullet-train.zsh +[submodule "zsh/zsh-syntax-highlighting"] + path = zsh/zsh-syntax-highlighting + url = https://github.com/zsh-users/zsh-syntax-highlighting +[submodule "zsh/zsh-autosuggestions"] + path = zsh/zsh-autosuggestions + url = https://github.com/zsh-users/zsh-autosuggestions +[submodule "zsh/zsh-completions"] + path = zsh/zsh-completions + url = https://github.com/zsh-users/zsh-completions +[submodule "zsh/zsh-history-substring-search"] + path = zsh/zsh-history-substring-search + url = https://github.com/zsh-users/zsh-history-substring-search diff --git a/zsh/bullet-train.zsh b/zsh/bullet-train.zsh new file mode 160000 index 0000000..d60f62c --- /dev/null +++ b/zsh/bullet-train.zsh @@ -0,0 +1 @@ +Subproject commit d60f62c34b3d9253292eb8be81fb46fa65d8f048 diff --git a/zsh/theme.zsh b/zsh/theme.zsh new file mode 100644 index 0000000..fd1124d --- /dev/null +++ b/zsh/theme.zsh @@ -0,0 +1,230 @@ +# Taken from https://raw.githubusercontent.com/zplug/zplug/6985646ad3f5dbc9b1f215aed747c6fac85d28b3/base/utils/theme.zsh +# TODO: potentially update? + + +# Import oh-my-zsh/lib/git.zsh +# + +# Outputs current branch info in prompt format +git_prompt_info() +{ + local ref hide_status + hide_status="$(git config --get oh-my-zsh.hide-status 2>/dev/null)" + if [[ $hide_status != 1 ]]; then + ref="$(git symbolic-ref HEAD 2>/dev/null)" || ref="$(git rev-parse --short HEAD 2>/dev/null)" || return 0 + echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$ZSH_THEME_GIT_PROMPT_SUFFIX" + fi +} + +# Checks if working tree is dirty +parse_git_dirty() +{ + local _status hide_dirty + local -a flags + + flags=('--porcelain') + hide_dirty="$(git config --get oh-my-zsh.hide-dirty)" + + if [[ $hide_dirty != "1" ]]; then + if [[ $DISABLE_UNTRACKED_FILES_DIRTY == true ]]; then + flags+=('--untracked-files=no') + fi + _status="$(git status "$flags[@]" | tail -n 1)" + fi + + if [[ -n $_status ]]; then + echo "$ZSH_THEME_GIT_PROMPT_DIRTY" + else + echo "$ZSH_THEME_GIT_PROMPT_CLEAN" + fi +} + +# Gets the difference between the local and remote branches +git_remote_status() +{ + local remote ahead behind git_remote_status git_remote_status_detailed + 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 == 0 ]] && [[ $behind == 0 ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_EQUAL_REMOTE" + + elif [[ $ahead == 0 ]] && [[ $behind == 0 ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE" + git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}" + + elif [[ $behind -gt 0 ]] && [[ $ahead == 0 ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE" + git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}" + + elif [[ $ahead -gt 0 ]] && [[ $behind -gt 0 ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE" + git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}" + fi + + if [[ -n $ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_DETAILED ]]; then + git_remote_status="$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_PREFIX$remote$git_remote_status_detailed$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_SUFFIX" + fi + + echo "$git_remote_status" + fi +} + +# Outputs the name of the current branch +# Usage example: git pull origin $(git_current_branch) +# Using '--quiet' with 'symbolic-ref' will not cause a fatal error (128) if +# it's not a symbolic ref, but in a Git repo. +git_current_branch() +{ + local ref + + ref="$(git symbolic-ref --quiet HEAD 2>/dev/null)" + local ret=$? + + if [[ $ret != 0 ]]; then + [[ $ret == 128 ]] && return 0 # no git repo + ref=$(git rev-parse --short HEAD 2>/dev/null) || return 0 + fi + echo "${ref#refs/heads/}" +} + +# Gets the number of commits ahead from remote +git_commits_ahead() +{ + if git rev-parse --git-dir &>/dev/null; then + local commits="$(git rev-list --count @{upstream}..HEAD)" + if [[ $commits != 0 ]]; then + echo "$ZSH_THEME_GIT_COMMITS_AHEAD_PREFIX$commits$ZSH_THEME_GIT_COMMITS_AHEAD_SUFFIX" + fi + fi +} + +# Gets the number of commits behind remote +git_commits_behind() +{ + if git rev-parse --git-dir &>/dev/null; then + local commits="$(git rev-list --count HEAD..@{upstream})" + if [[ $commits != 0 ]]; then + echo "$ZSH_THEME_GIT_COMMITS_BEHIND_PREFIX$commits$ZSH_THEME_GIT_COMMITS_BEHIND_SUFFIX" + fi + fi +} + +# Outputs if current branch is ahead of remote +git_prompt_ahead() +{ + if [[ -n "$(git rev-list origin/$(git_current_branch)..HEAD 2>/dev/null)" ]]; then + echo "$ZSH_THEME_GIT_PROMPT_AHEAD" + fi +} + +# Outputs if current branch is behind remote +git_prompt_behind() +{ + if [[ -n "$(git rev-list HEAD..origin/$(git_current_branch) 2>/dev/null)" ]]; then + echo "$ZSH_THEME_GIT_PROMPT_BEHIND" + fi +} + +# Outputs if current branch exists on remote or not +git_prompt_remote() +{ + if [[ -n "$(git show-ref origin/$(git_current_branch) 2>/dev/null)" ]]; then + echo "$ZSH_THEME_GIT_PROMPT_REMOTE_EXISTS" + else + echo "$ZSH_THEME_GIT_PROMPT_REMOTE_MISSING" + fi +} + +# Formats prompt string for current git commit short sha +git_prompt_short_sha() +{ + local 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 +git_prompt_long_sha() +{ + local 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() +{ + local INDEX _status + INDEX="$(git status --porcelain -b 2>/dev/null)" + _status="" + + if echo "$INDEX" | grep -E '^\?\? ' &>/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; 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" +} + +# Outputs the name of the current user +# Usage example: $(git_current_user_name) +git_current_user_name() +{ + git config user.name +} + +# Outputs the email of the current user +# Usage example: $(git_current_user_email) +git_current_user_email() +{ + git config user.email +} diff --git a/zsh/zsh-autosuggestions b/zsh/zsh-autosuggestions new file mode 160000 index 0000000..ae315de --- /dev/null +++ b/zsh/zsh-autosuggestions @@ -0,0 +1 @@ +Subproject commit ae315ded4dba10685dbbafbfa2ff3c1aefeb490d diff --git a/zsh/zsh-completions b/zsh/zsh-completions new file mode 160000 index 0000000..ed4ff53 --- /dev/null +++ b/zsh/zsh-completions @@ -0,0 +1 @@ +Subproject commit ed4ff5384b03aa775a57d4c9588c88850026b0b3 diff --git a/zsh/zsh-history-substring-search b/zsh/zsh-history-substring-search new file mode 160000 index 0000000..0f80b8e --- /dev/null +++ b/zsh/zsh-history-substring-search @@ -0,0 +1 @@ +Subproject commit 0f80b8eb3368b46e5e573c1d91ae69eb095db3fb diff --git a/zsh/zsh-syntax-highlighting b/zsh/zsh-syntax-highlighting new file mode 160000 index 0000000..870bccf --- /dev/null +++ b/zsh/zsh-syntax-highlighting @@ -0,0 +1 @@ +Subproject commit 870bccf8ffdcce7e01319438f96475a6329c9363 diff --git a/zshrc b/zshrc index e6802d9..1c423af 100644 --- a/zshrc +++ b/zshrc @@ -1,17 +1,12 @@ -######### -# zplug configuraton -######### -export ZPLUG_HOME=$HOME/.zplug -source $ZPLUG_HOME/init.zsh +function load_plugin() { + source ~/.zsh/$1/$1.plugin.zsh +} -zplug "felixr/docker-zsh-completion" - -# Stuff that modifies -zplug "zsh-users/zsh-syntax-highlighting" -zplug "zsh-users/zsh-autosuggestions" -zplug "zsh-users/zsh-completions" -zplug "zsh-users/zsh-history-substring-search" -zplug 'mfaerevaag/wd', as:command, use:"wd.sh", hook-load:"wd() { . $ZPLUG_REPOS/mfaerevaag/wd/wd.sh }" +# Things that modify +load_plugin "zsh-syntax-highlighting" +load_plugin "zsh-autosuggestions" +load_plugin "zsh-completions" +load_plugin "zsh-history-substring-search" bindkey "^[[A" history-beginning-search-backward bindkey "^[[B" history-beginning-search-forward @@ -30,7 +25,9 @@ setopt share_history # goodbye, out-of-sync cross-shell passwords setopt auto_list # magic and things involving listing of items setopt auto_menu # Use a menu because I'm _that_ type of person -zplug "caiogondim/bullet-train.zsh", use:bullet-train.zsh-theme, defer:3 +# Theme requires oh-my-zsh's git functions. +source ~/.zsh/theme.zsh +source ~/.zsh/bullet-train.zsh/bullet-train.zsh-theme # Configure prompt to my liking. BULLETTRAIN_PROMPT_ORDER=( @@ -46,17 +43,6 @@ BULLETTRAIN_PROMPT_ORDER=( BULLETTRAIN_PROMPT_CHAR=">" BULLETTRAIN_DIR_BG="black" -# Install plugins if there are plugins that have not been installed -if ! zplug check --verbose; then - printf "Install? [y/N]: " - if read -q; then - echo; zplug install - fi -fi - -# Let's do this. -zplug load - ######### # the env _essentials_ ######### @@ -74,7 +60,6 @@ fi # Google Cloud tools if [ -d ${HOME}/bin/google-cloud-sdk ]; then - source ${HOME}/bin/google-cloud-sdk/completion.zsh.inc source ${HOME}/bin/google-cloud-sdk/path.zsh.inc fi @@ -108,6 +93,8 @@ fi if [[ $OSTYPE == darwin* ]]; then # Fix Homebrew pathing. export PATH="/usr/local/bin:/usr/local/sbin:${PATH}" + # Fix ZSH site-functions pathing due to Homebrew. + FPATH=$(brew --prefix)/share/zsh/site-functions:$FPATH fi # Personal preferences @@ -134,3 +121,12 @@ if [ -d $HOME/.rvm ]; then PATH=${PATH}:$HOME/.rvm/bin [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" ]] fi + +autoload -Uz compinit +compinit + +# Google Cloud tries to prematurely call compinit for completion. +# I don't want >1 second load times. +if [ -d ${HOME}/bin/google-cloud-sdk ]; then + source ${HOME}/bin/google-cloud-sdk/completion.zsh.inc +fi \ No newline at end of file