96ff86142e9037e707f9cde8ab69e0425a0559c6

Author
Andrew Janke <andrew@apjanke.net>
Committer
Andrew Janke <andrew@apjanke.net>
Date

Message

Merge branch 'master' into installer-cygwin-support-3

Conflicts:
	tools/install.sh

Diff

This diff is truncated to protect this page.

   1diff --git a/README.markdown b/README.markdown
   2index 3805d1eb41f68cc40b400aa9b4e4c1c36c8b38d7..a29df81ab5d6aff44df86ce96e10448483474744 100644
   3--- a/README.markdown
   4+++ b/README.markdown
   5@@ -3,9 +3,9 @@
   6 
   7 Oh My Zsh is an open source, community-driven framework for managing your [zsh](http://www.zsh.org/) configuration. That sounds boring. Let's try this again.
   8 
   9diff --git a/lib/compfix.zsh b/lib/compfix.zsh
  10new file mode 100644
  11index 0000000000000000000000000000000000000000..208aaadb1ebad0e25ebdef29192da815be8136bd
  12--- /dev/null
  13+++ b/lib/compfix.zsh
  14@@ -0,0 +1,60 @@
  15+# Handle completions insecurities (i.e., completion-dependent directories with
  16+# insecure ownership or permissions) by:
  17+#
  18+# * Human-readably notifying the user of these insecurities.
  19+# * Moving away all existing completion caches to a temporary directory. Since
  20+#   any of these caches may have been generated from insecure directories, they
  21+#   are all suspect now. Failing to do so typically causes subsequent compinit()
  22+#   calls to fail with "command not found: compdef" errors. (That's bad.)
  23+function handle_completion_insecurities() {
  24+  # List of the absolute paths of all unique insecure directories, split on
  25+  # newline from compaudit()'s output resembling:
  26+  #
  27+  #     There are insecure directories:
  28+  #     /usr/share/zsh/site-functions
  29+  #     /usr/share/zsh/5.0.6/functions
  30+  #     /usr/share/zsh
  31+  #     /usr/share/zsh/5.0.6
  32+  #
  33+  # Since the ignorable first line is printed to stderr and thus not captured,
  34+  # stderr is squelched to prevent this output from leaking to the user. 
  35+  local -aU insecure_dirs
  36+  insecure_dirs=( ${(f@):-"$(compaudit 2>/dev/null)"} )
  37+
  38+  # If no such directories exist, get us out of here.
  39+  if (( ! ${#insecure_dirs} )); then
  40+      print "[oh-my-zsh] No insecure completion-dependent directories detected."
  41+      return
  42+  fi
  43+
  44+  # List ownership and permissions of all insecure directories.
  45+  print "[oh-my-zsh] Insecure completion-dependent directories detected:"
  46+  ls -ld "${(@)insecure_dirs}"
  47+  print "[oh-my-zsh] For safety, completions will be disabled until you manually fix all"
  48+  print "[oh-my-zsh] insecure directory permissions and ownership and restart oh-my-zsh."
  49+  print "[oh-my-zsh] See the above list for directories with group or other writability.\n"
  50+
  51+  # Locally enable the "NULL_GLOB" option, thus removing unmatched filename
  52+  # globs from argument lists *AND* printing no warning when doing so. Failing
  53+  # to do so prints an unreadable warning if no completion caches exist below.
  54+  setopt local_options null_glob
  55+
  56+  # List of the absolute paths of all unique existing completion caches.
  57+  local -aU zcompdump_files
  58+  zcompdump_files=( "${ZSH_COMPDUMP}"(.) "${ZDOTDIR:-${HOME}}"/.zcompdump* )
  59+
  60+  # Move such caches to a temporary directory.
  61+  if (( ${#zcompdump_files} )); then
  62+    # Absolute path of the directory to which such files will be moved.
  63+    local ZSH_ZCOMPDUMP_BAD_DIR="${ZSH_CACHE_DIR}/zcompdump-bad"
  64+
  65+    # List such files first.
  66+    print "[oh-my-zsh] Insecure completion caches also detected:"
  67+    ls -l "${(@)zcompdump_files}"
  68+
  69+    # For safety, move rather than permanently remove such files.
  70+    print "[oh-my-zsh] Moving to \"${ZSH_ZCOMPDUMP_BAD_DIR}/\"...\n"
  71+    mkdir -p "${ZSH_ZCOMPDUMP_BAD_DIR}"
  72+    mv "${(@)zcompdump_files}" "${ZSH_ZCOMPDUMP_BAD_DIR}/"
  73+  fi
  74+}
  75diff --git a/lib/completion.zsh b/lib/completion.zsh
  76index 452c0dfe765539dd6cf0a83f85037c7ac5f571a9..f5b29247127543f4aec6ffec6bdb4b29bcdd9de1 100644
  77--- a/lib/completion.zsh
  78+++ b/lib/completion.zsh
  79@@ -58,9 +58,13 @@ zstyle ':completion:*:*:*:users' ignored-patterns \
  80 # ... unless we really want to.
  81 zstyle '*' single-ignored show
  82 
  83-if [ "x$COMPLETION_WAITING_DOTS" = "xtrue" ]; then
  84+if [[ $COMPLETION_WAITING_DOTS = true ]]; then
  85   expand-or-complete-with-dots() {
  86-    echo -n "\e[31m......\e[0m"
  87+    # toggle line-wrapping off and back on again
  88+    [[ -n "$terminfo[rmam]" && -n "$terminfo[smam]" ]] && echoti rmam
  89+    print -Pn "%{%F{red}......%f%}"
  90+    [[ -n "$terminfo[rmam]" && -n "$terminfo[smam]" ]] && echoti smam
  91+
  92     zle expand-or-complete
  93     zle redisplay
  94   }
  95diff --git a/lib/diagnostics.zsh b/lib/diagnostics.zsh
  96new file mode 100644
  97index 0000000000000000000000000000000000000000..afc33829b01c0a09dc0633a21fbfee906c5d3116
  98--- /dev/null
  99+++ b/lib/diagnostics.zsh
 100@@ -0,0 +1,335 @@
 101+# diagnostics.zsh
 102+#
 103+# Diagnostic and debugging support for oh-my-zsh
 104+
 105+# omz_diagnostic_dump()
 106+#
 107+# Author: Andrew Janke <andrew@apjanke.net>
 108+#
 109+# Usage:
 110+#
 111+# omz_diagnostic_dump [-v] [-V] [file]
 112+#
 113+# NOTE: This is a work in progress. Its interface and behavior are going to change,
 114+# and probably in non-back-compatible ways.
 115+#
 116+# Outputs a bunch of information about the state and configuration of
 117+# oh-my-zsh, zsh, and the user's system. This is intended to provide a
 118+# bunch of context for diagnosing your own or a third party's problems, and to
 119+# be suitable for posting to public bug reports.
 120+#
 121+# The output is human-readable and its format may change over time. It is not
 122+# suitable for parsing. All the output is in one single file so it can be posted
 123+# as a gist or bug comment on GitHub. GitHub doesn't support attaching tarballs
 124+# or other files to bugs; otherwise, this would probably have an option to produce
 125+# tarballs that contain copies of the config and customization files instead of
 126+# catting them all in to one file.
 127+#
 128+# This is intended to be widely portable, and run anywhere that oh-my-zsh does.
 129+# Feel free to report any portability issues as bugs.
 130+#
 131+# This is written in a defensive style so it still works (and can detect) cases when
 132+# basic functionality like echo and which have been redefined. In particular, almost
 133+# everything is invoked with "builtin" or "command", to work in the face of user 
 134+# redefinitions.
 135+#
 136+# OPTIONS
 137+#
 138+# [file]   Specifies the output file. If not given, a file in the current directory
 139+#        is selected automatically.
 140+#
 141+# -v    Increase the verbosity of the dump output. May be specified multiple times.
 142+#       Verbosity levels:
 143+#        0 - Basic info, shell state, omz configuration, git state
 144+#        1 - (default) Adds key binding info and configuration file contents
 145+#        2 - Adds zcompdump file contents
 146+#
 147+# -V    Reduce the verbosity of the dump output. May be specified multiple times.
 148+#
 149+# TODO:
 150+# * Multi-file capture
 151+# * Add automatic gist uploading
 152+# * Consider whether to move default output file location to TMPDIR. More robust
 153+#     but less user friendly.
 154+#
 155+function omz_diagnostic_dump() {
 156+  emulate -L zsh
 157+
 158+  builtin echo "Generating diagnostic dump; please be patient..."
 159+  
 160+  local thisfcn=omz_diagnostic_dump
 161+  local -A opts
 162+  local opt_verbose opt_noverbose opt_outfile
 163+  local timestamp=$(date +%Y%m%d-%H%M%S)
 164+  local outfile=omz_diagdump_$timestamp.txt
 165+  builtin zparseopts -A opts -D -- "v+=opt_verbose" "V+=opt_noverbose"
 166+  local verbose n_verbose=${#opt_verbose} n_noverbose=${#opt_noverbose}
 167+  (( verbose = 1 + n_verbose - n_noverbose ))
 168+
 169+  if [[ ${#*} > 0 ]]; then
 170+    opt_outfile=$1
 171+  fi
 172+  if [[ ${#*} > 1 ]]; then
 173+    builtin echo "$thisfcn: error: too many arguments" >&2
 174+    return 1
 175+  fi
 176+  if [[ -n "$opt_outfile" ]]; then
 177+    outfile="$opt_outfile"
 178+  fi
 179+
 180+  # Always write directly to a file so terminal escape sequences are
 181+  # captured cleanly
 182+  _omz_diag_dump_one_big_text &> "$outfile"
 183+  if [[ $? != 0 ]]; then
 184+    builtin echo "$thisfcn: error while creating diagnostic dump; see $outfile for details"
 185+  fi
 186+
 187+  builtin echo
 188+  builtin echo Diagnostic dump file created at: "$outfile"
 189+  builtin echo
 190+  builtin echo To share this with OMZ developers, post it as a gist on GitHub 
 191+  builtin echo at "https://gist.github.com" and share the link to the gist.
 192+  builtin echo
 193+  builtin echo "WARNING: This dump file contains all your zsh and omz configuration files,"
 194+  builtin echo "so don't share it publicly if there's sensitive information in them."
 195+  builtin echo
 196+
 197+}
 198+
 199+function _omz_diag_dump_one_big_text() {
 200diff --git a/lib/functions.zsh b/lib/functions.zsh
 201index 17f5f9cbf246ff0e6c58abfff6dff3ea227c99d8..efb73a1bd91170f1c2622635875ceb900942ee43 100644
 202--- a/lib/functions.zsh
 203+++ b/lib/functions.zsh
 204@@ -15,6 +15,22 @@ function take() {
 205   cd $1
 206 }
 207 
 208+function open_command() {
 209+  local open_cmd
 210+
 211+  # define the open command
 212+  case "$OSTYPE" in
 213+    darwin*)  open_cmd="open" ;;
 214+    cygwin*)  open_cmd="cygstart" ;;
 215+    linux*)   open_cmd="xdg-open" ;;
 216+    *)        echo "Platform $OSTYPE not supported"
 217+              return 1
 218+              ;;
 219+  esac
 220+
 221+  nohup $open_cmd "$@" &>/dev/null
 222+}
 223+
 224 #
 225 # Get the value of an alias.
 226 #
 227@@ -73,3 +89,135 @@ function env_default() {
 228     env | grep -q "^$1=" && return 0 
 229     export "$1=$2"       && return 3
 230 }
 231+
 232+
 233+# Required for $langinfo
 234+zmodload zsh/langinfo
 235+
 236+# URL-encode a string
 237+#
 238+# Encodes a string using RFC 2396 URL-encoding (%-escaped).
 239+# See: https://www.ietf.org/rfc/rfc2396.txt
 240+#
 241+# By default, reserved characters and unreserved "mark" characters are
 242+# not escaped by this function. This allows the common usage of passing
 243+# an entire URL in, and encoding just special characters in it, with 
 244+# the expectation that reserved and mark characters are used appropriately.
 245+# The -r and -m options turn on escaping of the reserved and mark characters,
 246+# respectively, which allows arbitrary strings to be fully escaped for
 247+# embedding inside URLs, where reserved characters might be misinterpreted.
 248+#
 249+# Prints the encoded string on stdout.
 250+# Returns nonzero if encoding failed.
 251+#
 252+# Usage:
 253+#  omz_urlencode [-r] [-m] <string>
 254+#  
 255+#    -r causes reserved characters (;/?:@&=+$,) to be escaped
 256+#
 257+#    -m causes "mark" characters (_.!~*''()-) to be escaped
 258+#
 259+#    -P causes spaces to be encoded as '%20' instead of '+'
 260+function omz_urlencode() {
 261+  emulate -L zsh
 262+  zparseopts -D -E -a opts r m P
 263+
 264+  local in_str=$1
 265+  local url_str=""
 266+  local spaces_as_plus
 267+  if [[ -z $opts[(r)-P] ]]; then spaces_as_plus=1; fi
 268+  local str="$in_str"
 269+
 270+  # URLs must use UTF-8 encoding; convert str to UTF-8 if required
 271+  local encoding=$langinfo[CODESET]
 272+  local safe_encodings
 273+  safe_encodings=(UTF-8 utf8 US-ASCII)
 274+  if [[ -z ${safe_encodings[(r)$encoding]} ]]; then
 275+    str=$(echo -E "$str" | iconv -f $encoding -t UTF-8)
 276+    if [[ $? != 0 ]]; then
 277+      echo "Error converting string from $encoding to UTF-8" >&2
 278+      return 1
 279+    fi
 280+  fi
 281+
 282+  # Use LC_CTYPE=C to process text byte-by-byte
 283+  local i byte ord LC_ALL=C
 284+  export LC_ALL
 285+  local reserved=';/?:@&=+$,'
 286+  local mark='_.!~*''()-'
 287+  local dont_escape="[A-Za-z0-9"
 288+  if [[ -z $opts[(r)-r] ]]; then
 289+    dont_escape+=$reserved
 290+  fi
 291+  # $mark must be last because of the "-"
 292+  if [[ -z $opts[(r)-m] ]]; then
 293+    dont_escape+=$mark
 294+  fi
 295+  dont_escape+="]"
 296+
 297+  # Implemented to use a single printf call and avoid subshells in the loop,
 298+  # for performance (primarily on Windows).
 299+  local url_str=""
 300+  for (( i = 1; i <= ${#str}; ++i )); do
 301+    byte="$str[i]"
 302+    if [[ "$byte" =~ "$dont_escape" ]]; then
 303+      url_str+="$byte"
 304diff --git a/lib/git.zsh b/lib/git.zsh
 305index caa7e632913251f9694b3a3b7cb357e2879e02cf..baf86371724d01ae842bbfe6d4f8e39530caf208 100644
 306--- a/lib/git.zsh
 307+++ b/lib/git.zsh
 308@@ -36,7 +36,10 @@ git_remote_status() {
 309         ahead=$(command git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l)
 310         behind=$(command git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l)
 311 
 312-        if [ $ahead -gt 0 ] && [ $behind -eq 0 ]
 313+        if [ $ahead -eq 0 ] && [ $behind -eq 0 ]
 314+        then
 315+          echo "$ZSH_THEME_GIT_PROMPT_EQUAL_REMOTE"
 316+        elif [ $ahead -gt 0 ] && [ $behind -eq 0 ]
 317         then
 318             git_remote_status="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE"
 319             git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}"
 320diff --git a/lib/termsupport.zsh b/lib/termsupport.zsh
 321index e1c2e2f93a3b376a02180d21cdddf01f0bcdcb29..5f61fe8ef2d4e3cd34fe441dde04779f709f9fa7 100644
 322--- a/lib/termsupport.zsh
 323+++ b/lib/termsupport.zsh
 324@@ -7,6 +7,9 @@
 325 # (In screen, only short_tab_title is used)
 326 # Limited support for Apple Terminal (Terminal can't set window and tab separately)
 327 function title {
 328+  emulate -L zsh
 329+  setopt prompt_subst
 330+  
 331   [[ "$EMACS" == *term* ]] && return
 332 
 333   # if $2 is unset use $1 as default
 334@@ -23,9 +26,14 @@ function title {
 335 
 336 ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" #15 char left truncated PWD
 337 ZSH_THEME_TERM_TITLE_IDLE="%n@%m: %~"
 338+# Avoid duplication of directory in terminals with independent dir display
 339+if [[ $TERM_PROGRAM == Apple_Terminal ]]; then
 340+  ZSH_THEME_TERM_TITLE_IDLE="%n@%m"
 341+fi
 342 
 343 # Runs before showing the prompt
 344 function omz_termsupport_precmd {
 345+  emulate -L zsh
 346   if [[ $DISABLE_AUTO_TITLE == true ]]; then
 347     return
 348   fi
 349@@ -35,15 +43,15 @@ function omz_termsupport_precmd {
 350 
 351 # Runs before executing the command
 352 function omz_termsupport_preexec {
 353+  emulate -L zsh
 354   if [[ $DISABLE_AUTO_TITLE == true ]]; then
 355     return
 356   fi
 357 
 358-  emulate -L zsh
 359   setopt extended_glob
 360 
 361   # cmd name only, or if this is sudo or ssh, the next cmd
 362-  local CMD=${1[(wr)^(*=*|sudo|ssh|rake|-*)]:gs/%/%%}
 363+  local CMD=${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%}
 364   local LINE="${2:gs/%/%%}"
 365 
 366   title '$CMD' '%100>...>$LINE%<<'
 367@@ -53,14 +61,28 @@ precmd_functions+=(omz_termsupport_precmd)
 368 preexec_functions+=(omz_termsupport_preexec)
 369 
 370 
 371-# Runs before showing the prompt, to update the current directory in Terminal.app
 372-function omz_termsupport_cwd {
 373-  # Notify Terminal.app of current directory using undocumented OSC sequence
 374-  # found in OS X 10.9 and 10.10's /etc/bashrc
 375-  if [[ $TERM_PROGRAM == Apple_Terminal ]] && [[ -z $INSIDE_EMACS ]]; then
 376-    local PWD_URL="file://$HOSTNAME${PWD// /%20}"
 377-    printf '\e]7;%s\a' "$PWD_URL"
 378-  fi
 379-}
 380+# Keep Apple Terminal.app's current working directory updated
 381+# Based on this answer: http://superuser.com/a/315029
 382+# With extra fixes to handle multibyte chars and non-UTF-8 locales
 383+
 384+if [[ "$TERM_PROGRAM" == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]]; then
 385+
 386+  # Emits the control sequence to notify Terminal.app of the cwd
 387+  function update_terminalapp_cwd() {
 388+    emulate -L zsh
 389+    # Identify the directory using a "file:" scheme URL, including
 390+    # the host name to disambiguate local vs. remote paths.
 391+
 392+    # Percent-encode the pathname.
 393+    local URL_PATH=$(omz_urlencode -P $PWD)
 394+    [[ $? != 0 ]] && return 1
 395+    local PWD_URL="file://$HOST$URL_PATH"
 396+    # Undocumented Terminal.app-specific control sequence
 397+    printf '\e]7;%s\a' $PWD_URL
 398+  }
 399 
 400-precmd_functions+=(omz_termsupport_cwd)
 401+  # Use a precmd hook instead of a chpwd hook to avoid contaminating output
 402+  precmd_functions+=(update_terminalapp_cwd)
 403+  # Run once to get initial cwd set
 404+  update_terminalapp_cwd
 405+fi
 406diff --git a/lib/theme-and-appearance.zsh b/lib/theme-and-appearance.zsh
 407index 926303ca4509cd89bbc30187fd99879c1fbeb771..ebb11fb3185cef97ef29c8b6f11174c7669986ac 100644
 408--- a/lib/theme-and-appearance.zsh
 409+++ b/lib/theme-and-appearance.zsh
 410@@ -11,8 +11,11 @@ then
 411     # otherwise, leave ls as is, because NetBSD's ls doesn't support -G
 412     gls --color -d . &>/dev/null 2>&1 && alias ls='gls --color=tty'
 413   elif [[ "$(uname -s)" == "OpenBSD" ]]; then
 414-    # On OpenBSD, test if "colorls" is installed (this one supports colors);
 415-    # otherwise, leave ls as is, because OpenBSD's ls doesn't support -G
 416+    # On OpenBSD, "gls" (ls from GNU coreutils) and "colorls" (ls from base, 
 417+    # with color and multibyte support) are available from ports.  "colorls"  
 418+    # will be installed on purpose and can't be pulled in by installing 
 419+    # coreutils, so prefer it to "gls".
 420+    gls --color -d . &>/dev/null 2>&1 && alias ls='gls --color=tty'
 421     colorls -G -d . &>/dev/null 2>&1 && alias ls='colorls -G'
 422   else
 423     ls --color -d . &>/dev/null 2>&1 && alias ls='ls --color=tty' || alias ls='ls -G'
 424diff --git a/oh-my-zsh.sh b/oh-my-zsh.sh
 425index ec64c240f0203b64b1d32fe6da2ae657e93329f1..8e31ddd0ff62c43d187cd6f6fd2bf97a72a0bc11 100644
 426--- a/oh-my-zsh.sh
 427+++ b/oh-my-zsh.sh
 428@@ -8,6 +8,9 @@ fi
 429 # add a function path
 430 fpath=($ZSH/functions $ZSH/completions $fpath)
 431 
 432+# Load all stock functions (from $fpath files) called below.
 433+autoload -U compaudit compinit
 434+
 435 # Set ZSH_CUSTOM to the path where your custom config files
 436 # and plugins exists, or else we will use the default custom/
 437 if [[ -z "$ZSH_CUSTOM" ]]; then
 438@@ -29,11 +32,6 @@ for config_file ($ZSH/lib/*.zsh); do
 439   source $config_file
 440 done
 441 
 442-# Load all of your custom configurations from custom/
 443-for config_file ($ZSH_CUSTOM/*.zsh(N)); do
 444-  source $config_file
 445-done
 446-unset config_file
 447 
 448 is_plugin() {
 449   local base_dir=$1
 450@@ -64,9 +62,14 @@ if [ -z "$ZSH_COMPDUMP" ]; then
 451   ZSH_COMPDUMP="${ZDOTDIR:-${HOME}}/.zcompdump-${SHORT_HOST}-${ZSH_VERSION}"
 452 fi
 453 
 454-# Load and run compinit
 455-autoload -U compinit
 456-compinit -i -d "${ZSH_COMPDUMP}"
 457+# If completion insecurities exist, warn the user without enabling completions.
 458+if ! compaudit &>/dev/null; then
 459+  # This function resides in the "lib/compfix.zsh" script sourced above.
 460+  handle_completion_insecurities
 461+# Else, enable and cache completions to the desired file.
 462+else
 463+  compinit -d "${ZSH_COMPDUMP}"
 464+fi
 465 
 466 # Load all of the plugins that were defined in ~/.zshrc
 467 for plugin ($plugins); do
 468@@ -77,6 +80,12 @@ for plugin ($plugins); do
 469   fi
 470 done
 471 
 472+# Load all of your custom configurations from custom/
 473+for config_file ($ZSH_CUSTOM/*.zsh(N)); do
 474+  source $config_file
 475+done
 476+unset config_file
 477+
 478 # Load the theme
 479 if [ "$ZSH_THEME" = "random" ]; then
 480   themes=($ZSH/themes/*zsh-theme)
 481diff --git a/plugins/atom/README.md b/plugins/atom/README.md
 482index 75d77a0ac1c3732be4dbab1b4062e4f8e1d315fc..6350c647b029ef0ca2416c6dcfe976a63e1d1534 100644
 483--- a/plugins/atom/README.md
 484+++ b/plugins/atom/README.md
 485@@ -1,6 +1,8 @@
 486 ## atom
 487 
 488-Plugin for Atom, a cross platform text and code editor, available for Linux, Mac OS X, and Windows.
 489+This plugin makes "at" a useful function for invoking the Atom Editor.
 490+
 491+Originally by Github user [aforty](https://github.com/aforty) for OSX, modified to alias 'at' to 'atom' for Linux, since atom already works on the terminal for Linux, and calling 'at' in a non-OSX environment should still work.
 492 
 493 ### Requirements
 494 
 495@@ -10,8 +12,12 @@ Plugin for Atom, a cross platform text and code editor, available for Linux, Mac
 496 
 497  * If `at` command is called without an argument, launch Atom
 498 
 499- * If `at` is passed a directory, `cd` to it and open it in Atom
 500+ * If `at` is passed a directory, open it in Atom
 501 
 502  * If `at` is passed a file, open it in Atom
 503 
 504- * if `att` command is called, it is equivalent to `at .`, opening the current folder in Atom
 505+### Examples
 506+
 507+ * Open the current dir in atom: `at .`
 508+ * Open another dir in atom: `at path/to/folder`
 509+ * Open a file: `at filename.extension`
 510diff --git a/plugins/atom/atom.plugin.zsh b/plugins/atom/atom.plugin.zsh
 511index 9adb9031a0e9c61c113a0e210531f5f3fdc5f4e2..ec1a114edeb67221e0f203646fb0daf30fabbe07 100644
 512--- a/plugins/atom/atom.plugin.zsh
 513+++ b/plugins/atom/atom.plugin.zsh
 514@@ -1,14 +1,22 @@
 515-local _atom_paths > /dev/null 2>&1
 516-_atom_paths=(
 517-    "$HOME/Applications/Atom.app"
 518-    "/Applications/Atom.app"
 519-)
 520+# Gets OS Type
 521+unamestr=$(uname -s)
 522 
 523-for _atom_path in $_atom_paths; do
 524-    if [[ -a $_atom_path ]]; then
 525-        alias at="open -a '$_atom_path'"
 526-        break
 527-    fi
 528-done
 529+# If OSX
 530+if [[ "$unamestr" == 'Darwin' ]]; then
 531+    local _atom_paths > /dev/null 2>&1
 532+    _atom_paths=(
 533+        "$HOME/Applications/Atom.app"
 534+        "/Applications/Atom.app"
 535+    )
 536 
 537-alias att='at .'
 538+    for _atom_path in $_atom_paths; do
 539+        if [[ -a $_atom_path ]]; then
 540+            alias at="open -a '$_atom_path'"
 541+            break
 542+        fi
 543+    done
 544+# If Linux
 545+elif [[ "$unamestr" == 'Linux' ]]; then
 546+    # Alerts the user if 'atom' is not a found command.
 547+    type atom >/dev/null 2>&1 && alias at="atom" || { echo >&2 "You have enabled the atom oh-my-zsh plugin on Linux, but atom is not a recognized command. Please make sure you have it installed before using this plugin."; }
 548+fi
 549diff --git a/plugins/autojump/autojump.plugin.zsh b/plugins/autojump/autojump.plugin.zsh
 550index 4cf0364013b2655dac01bf250d063ff2d7b2d1b5..c05c699e106b56ec04278d4cd84d7a4176fd9c35 100644
 551--- a/plugins/autojump/autojump.plugin.zsh
 552+++ b/plugins/autojump/autojump.plugin.zsh
 553@@ -15,7 +15,7 @@ if [ $commands[autojump] ]; then # check if autojump is installed
 554     . /usr/local/share/autojump/autojump.zsh
 555   elif [ -f /opt/local/etc/profile.d/autojump.zsh ]; then # mac os x with ports
 556     . /opt/local/etc/profile.d/autojump.zsh
 557-  elif [ $commands[brew] -a -f `brew --prefix`/etc/autojump.zsh ]; then # mac os x with brew
 558-    . `brew --prefix`/etc/autojump.zsh
 559+  elif [ $commands[brew] -a -f `brew --prefix`/etc/autojump.sh ]; then # mac os x with brew
 560+    . `brew --prefix`/etc/autojump.sh
 561   fi
 562 fi
 563diff --git a/plugins/aws/aws.plugin.zsh b/plugins/aws/aws.plugin.zsh
 564index 7246db9f0e10252a2c9bee1cff624e0b76ebc6c9..d31052f8300082f0d7ed5a47e59a2cf1454288d0 100644
 565--- a/plugins/aws/aws.plugin.zsh
 566+++ b/plugins/aws/aws.plugin.zsh
 567@@ -11,11 +11,16 @@ export AWS_HOME=~/.aws
 568 function agp {
 569   echo $AWS_DEFAULT_PROFILE
 570 }
 571+
 572 function asp {
 573+  local rprompt=${RPROMPT/<aws:$(agp)>/}
 574+
 575   export AWS_DEFAULT_PROFILE=$1
 576   export AWS_PROFILE=$1
 577-  export RPROMPT="<aws:$AWS_DEFAULT_PROFILE>$RPROMPT"
 578+
 579+  export RPROMPT="<aws:$AWS_DEFAULT_PROFILE>$rprompt"
 580 }
 581+
 582 function aws_profiles {
 583   reply=($(grep profile $AWS_HOME/config|sed -e 's/.*profile \([a-zA-Z0-9_-]*\).*/\1/'))
 584 }
 585diff --git a/plugins/bgnotify/bgnotify.plugin.zsh b/plugins/bgnotify/bgnotify.plugin.zsh
 586index b70b42f984540b2d58e9a6720e57234ec5ae21d6..459f5214e62c07d62d65dbd98901ea2c4dc82bcc 100755
 587--- a/plugins/bgnotify/bgnotify.plugin.zsh
 588+++ b/plugins/bgnotify/bgnotify.plugin.zsh
 589@@ -11,31 +11,38 @@ autoload -Uz add-zsh-hook || { print "can't add zsh hook!"; return }
 590 
 591 ## definitions ##
 592 
 593-if ! (type bgnotify_formatted | grep -q 'function'); then
 594-  function bgnotify_formatted {
 595-    ## exit_status, command, elapsed_time
 596-    [ $1 -eq 0 ] && title="#win (took $3 s)" || title="#fail (took $3 s)"
 597-    bgnotify "$title" "$2"
 598+if ! (type bgnotify_formatted | grep -q 'function'); then ## allow custom function override
 599+  function bgnotify_formatted { ## args: (exit_status, command, elapsed_seconds)
 600+    elapsed="$(( $3 % 60 ))s"
 601+    (( $3 >= 60 )) && elapsed="$((( $3 % 3600) / 60 ))m $elapsed"
 602+    (( $3 >= 3600 )) && elapsed="$(( $3 / 3600 ))h $elapsed"
 603+    [ $1 -eq 0 ] && bgnotify "#win (took $elapsed)" "$2" || bgnotify "#fail (took $elapsed)" "$2"
 604   }
 605 fi
 606 
 607 currentWindowId () {
 608   if hash osascript 2>/dev/null; then #osx
 609     osascript -e 'tell application (path to frontmost application as text) to id of front window' 2&> /dev/null || echo "0"
 610-  elif hash notify-send 2>/dev/null; then #ubuntu!
 611-    xprop -root | awk '/NET_ACTIVE_WINDOW/ { print $5; exit }'
 612+  elif (hash notify-send 2>/dev/null || hash kdialog 2>/dev/null); then #ubuntu!
 613+    xprop -root 2> /dev/null | awk '/NET_ACTIVE_WINDOW/{print $5;exit} END{exit !$5}' || echo "0"
 614   else
 615     echo $EPOCHSECONDS #fallback for windows
 616   fi
 617 }
 618 
 619-bgnotify () {
 620+bgnotify () { ## args: (title, subtitle)
 621   if hash terminal-notifier 2>/dev/null; then #osx
 622-    terminal-notifier -message "$2" -title "$1"
 623+    [[ "$TERM_PROGRAM" == 'iTerm.app' ]] && term_id='com.googlecode.iterm2';
 624+    [[ "$TERM_PROGRAM" == 'Apple_Terminal' ]] && term_id='com.apple.terminal';
 625+    ## now call terminal-notifier, (hopefully with $term_id!)
 626+    [ -z "$term_id" ] && terminal-notifier -message "$2" -title "$1" >/dev/null ||
 627+    terminal-notifier -message "$2" -title "$1" -activate "$term_id" -sender "$term_id" >/dev/null
 628   elif hash growlnotify 2>/dev/null; then #osx growl
 629     growlnotify -m "$1" "$2"
 630-  elif hash notify-send 2>/dev/null; then #ubuntu!
 631+  elif hash notify-send 2>/dev/null; then #ubuntu gnome!
 632     notify-send "$1" "$2"
 633+  elif hash kdialog 2>/dev/null; then #ubuntu kde!
 634+    kdialog  -title "$1" --passivepopup  "$2" 5
 635   elif hash notifu 2>/dev/null; then #cygwyn support!
 636     notifu /m "$2" /p "$1"
 637   fi
 638@@ -46,7 +53,7 @@ bgnotify () {
 639 
 640 bgnotify_begin() {
 641   bgnotify_timestamp=$EPOCHSECONDS
 642-  bgnotify_lastcmd=$1
 643+  bgnotify_lastcmd="$1"
 644   bgnotify_windowid=$(currentWindowId)
 645 }
 646 
 647@@ -63,5 +70,8 @@ bgnotify_end() {
 648   bgnotify_timestamp=0 #reset it to 0!
 649 }
 650 
 651-add-zsh-hook preexec bgnotify_begin
 652-add-zsh-hook precmd bgnotify_end
 653+## only enable if a local (non-ssh) connection
 654+if [ -z "$SSH_CLIENT" ] && [ -z "$SSH_TTY" ]; then
 655+  add-zsh-hook preexec bgnotify_begin
 656+  add-zsh-hook precmd bgnotify_end
 657+fi
 658diff --git a/plugins/capistrano/_capistrano b/plugins/capistrano/_capistrano
 659index 3cadf3d54be8aabaacaf509d5ca75ab14eb97910..e6e71ffcc80d121d3adba7bde7f461bafcaa26b3 100644
 660--- a/plugins/capistrano/_capistrano
 661+++ b/plugins/capistrano/_capistrano
 662@@ -1,10 +1,49 @@
 663-#compdef cap
 664+#compdef shipit
 665 #autoload
 666 
 667-if [[ -f config/deploy.rb || -f Capfile ]]; then
 668-  if [[ ! -f .cap_tasks~ || config/deploy.rb -nt .cap_tasks~ ]]; then
 669-    echo "\nGenerating .cap_tasks~..." > /dev/stderr
 670-    cap -v --tasks | grep '#' | cut -d " " -f 2 > .cap_tasks~
 671+# Added `shipit` because `cap` is a reserved word. `cap` completion doesn't work.
 672+# http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fcap-Module
 673+
 674+local curcontext="$curcontext" state line ret=1
 675+local -a _configs
 676+
 677+_arguments -C \
 678+  '1: :->cmds' \
 679+  '2:: :->args' && ret=0
 680+
 681+_cap_tasks() {
 682+  if [[ -f config/deploy.rb || -f Capfile ]]; then
 683+    if [[ ! -f .cap_tasks~ ]]; then
 684+      shipit -v --tasks | sed 's/\(\[\)\(.*\)\(\]\)/\2:/' | awk '{command=$2; $1=$2=$3=""; gsub(/^[ \t\r\n]+/, "", $0); gsub(":", "\\:", command); print command"["$0"]"}' > .cap_tasks~
 685+    fi
 686+
 687+    OLD_IFS=$IFS
 688+    IFS=$'\n'
 689+    _values 'cap commands' $(< .cap_tasks~)
 690+    IFS=$OLD_IFS
 691+    # zmodload zsh/mapfile
 692+    # _values ${(f)mapfile[.cap_tasks~]}
 693   fi
 694-  compadd `cat .cap_tasks~`
 695-fi
 696+}
 697+
 698+_cap_stages() {
 699+  compadd $(find config/deploy -name \*.rb | cut -d/ -f3 | sed s:.rb::g)
 700+}
 701+
 702+case $state in
 703+  cmds)
 704+    # check if it uses multistage
 705+    if [[ -d config/deploy ]]; then
 706+      _cap_stages
 707+    else
 708+      _cap_tasks
 709+    fi
 710+    ret=0
 711+    ;;
 712+  args)
 713+    _cap_tasks
 714+    ret=0
 715+    ;;
 716+esac
 717+
 718+return ret
 719diff --git a/plugins/capistrano/capistrano.plugin.zsh b/plugins/capistrano/capistrano.plugin.zsh
 720new file mode 100644
 721index 0000000000000000000000000000000000000000..c85eb474ca8a9cd85f8f3cc4446e54ce5a5a0c85
 722--- /dev/null
 723+++ b/plugins/capistrano/capistrano.plugin.zsh
 724@@ -0,0 +1,11 @@
 725+# Added `shipit` because `cap` is a reserved word. `cap` completion doesn't work.
 726+# http://zsh.sourceforge.net/Doc/Release/Zsh-Modules.html#The-zsh_002fcap-Module
 727+
 728+func shipit() {
 729+  if [ -f Gemfile ]
 730+  then
 731+    bundle exec cap $*
 732+  else
 733+    cap $*
 734+  fi
 735+}
 736diff --git a/plugins/chruby/chruby.plugin.zsh b/plugins/chruby/chruby.plugin.zsh
 737index b461b0c9be7d5b39a27ebc7d646e93434e57e15a..5be6528b0edbcf818ca8ccd52d6cc7a619de7079 100644
 738--- a/plugins/chruby/chruby.plugin.zsh
 739+++ b/plugins/chruby/chruby.plugin.zsh
 740@@ -45,11 +45,11 @@ _source_from_omz_settings() {
 741     zstyle -s :omz:plugins:chruby path _chruby_path
 742     zstyle -s :omz:plugins:chruby auto _chruby_auto
 743 
 744-    if ${_chruby_path} && [[ -r ${_chruby_path} ]]; then
 745+    if [[ -r ${_chruby_path} ]]; then
 746         source ${_chruby_path}
 747     fi
 748 
 749-    if ${_chruby_auto} && [[ -r ${_chruby_auto} ]]; then
 750+    if [[ -r ${_chruby_auto} ]]; then
 751         source ${_chruby_auto}
 752     fi
 753 }
 754diff --git a/plugins/codeclimate/_codeclimate b/plugins/codeclimate/_codeclimate
 755new file mode 100644
 756index 0000000000000000000000000000000000000000..fd2536a340d632108c3f04bdd130052445c8d02d
 757--- /dev/null
 758+++ b/plugins/codeclimate/_codeclimate
 759@@ -0,0 +1,82 @@
 760+#compdef codeclimate
 761+
 762+_codeclimate_all_engines() {
 763+  engines_all=(`codeclimate engines:list | tail -n +2 | gawk '{ print $2 }' | gawk -F: '{ print $1 }'`)
 764+}
 765+
 766+_codeclimate_installed_engines() {
 767+  _codeclimate_all_engines
 768+
 769+  engines_installed=()
 770+
 771+  if [ -e .codeclimate.yml ]
 772+  then
 773+    for engine in $engines_all
 774+    do
 775+      if grep -q $engine ".codeclimate.yml"
 776+      then
 777+        engines_installed+=$engine
 778+      fi
 779+    done
 780+  fi
 781+}
 782+
 783+_codeclimate_not_installed_engines() {
 784+  _codeclimate_all_engines
 785+
 786+  engines_not_installed=()
 787+
 788+  if [ -e .codeclimate.yml ]
 789+  then
 790+    for engine in $engines_all
 791+    do
 792+      if ! grep -q $engine ".codeclimate.yml"
 793+      then
 794+        engines_not_installed+=$engine
 795+      fi
 796+    done
 797+  fi
 798+}
 799+
 800+local curcontext="$curcontext" state line ret=1
 801+local expl
 802+local -a engines_all engines_installed engines_not_installed
 803+
 804+_arguments \
 805+  '1: :->cmds' \
 806+  '*:: :->args' && ret=0
 807+
 808+case $state in
 809+  cmds)
 810+    _values "bundle command" \
 811+      "analyze[Analyze all relevant files in the current working directory]" \
 812+      "console[Start an interactive session providing access to the classes within the CLI]" \
 813+      "engines\:disable[Prevents the engine from being used in this project]" \
 814+      "engines\:enable[This engine will be run the next time your project is analyzed]" \
 815+      "engines\:install[Compares the list of engines in your .codeclimate.yml file to those that are currently installed, then installs any missing engines]" \
 816+      "engines\:list[Lists all available engines in the Code Climate Docker Hub]" \
 817+      "engines\:remove[Removes an engine from your .codeclimate.yml file]" \
 818+      "help[Displays a list of commands that can be passed to the Code Climate CLI]" \
 819+      "init[Generates a new .codeclimate.yml file in the current working directory]" \
 820+      "validate-config[Validates the .codeclimate.yml file in the current working directory]" \
 821+      "version[Displays the current version of the Code Climate CLI]"
 822+    ret=0
 823+    ;;
 824+  args)
 825+    case $line[1] in
 826+      engines:enable)
 827+        _codeclimate_not_installed_engines
 828+        _wanted engines_not_installed expl 'not installed engines' compadd -a engines_not_installed ;;
 829+      engines:disable|engines:remove)
 830+        _codeclimate_installed_engines
 831+        _wanted engines_installed expl 'installed engines' compadd -a engines_installed ;;
 832+      analyze)
 833+        _arguments \
 834+          '-f:Output Format:(text json)'
 835+        ret=0
 836+        ;;
 837+    esac
 838+    ;;
 839+esac
 840+
 841+return ret
 842diff --git a/plugins/coffee/coffee.plugin.zsh b/plugins/coffee/coffee.plugin.zsh
 843index 1a7bedd87fe9426f18c00e9f99bbc269a194406d..4e98e022869ea8b968ab4f3598f904bb51ff27d8 100644
 844--- a/plugins/coffee/coffee.plugin.zsh
 845+++ b/plugins/coffee/coffee.plugin.zsh
 846@@ -2,11 +2,11 @@
 847 
 848 # compile a string of coffeescript and print to output
 849 cf () {
 850-  coffee -peb $1
 851+  coffee -peb "$1"
 852 }
 853 # compile & copy to clipboard
 854 cfc () {
 855-  cf $1 | pbcopy
 856+  cf "$1" | pbcopy
 857 }
 858 
 859 # compile from pasteboard & print
 860diff --git a/plugins/dirhistory/dirhistory.plugin.zsh b/plugins/dirhistory/dirhistory.plugin.zsh
 861index d101cfcae6a435ac0d78398f23cb1aac809a0efc..0209981e31f463a30cc6d65f0b58c5d19c280c34 100644
 862--- a/plugins/dirhistory/dirhistory.plugin.zsh
 863+++ b/plugins/dirhistory/dirhistory.plugin.zsh
 864@@ -49,7 +49,8 @@ function push_future() {
 865 }
 866 
 867 # Called by zsh when directory changes
 868-function chpwd() {
 869+chpwd_functions+=(chpwd_dirhistory)
 870+function chpwd_dirhistory() {
 871   push_past $PWD
 872   # If DIRHISTORY_CD is not set...
 873   if [[ -z "${DIRHISTORY_CD+x}" ]]; then
 874diff --git a/plugins/dirpersist/dirpersist.plugin.zsh b/plugins/dirpersist/dirpersist.plugin.zsh
 875index 88d1129d4ac9a21a0a08f1a61f6531b84f320c34..616e2c3c658710d47073cfdd88aa43aea3782675 100644
 876--- a/plugins/dirpersist/dirpersist.plugin.zsh
 877+++ b/plugins/dirpersist/dirpersist.plugin.zsh
 878@@ -11,7 +11,8 @@ if [[ -f ${dirstack_file} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
 879   [[ -d $dirstack[1] ]] && cd $dirstack[1] && cd $OLDPWD
 880 fi
 881 
 882-chpwd() {
 883+chpwd_functions+=(chpwd_dirpersist)
 884+chpwd_dirpersist() {
 885   if (( $DIRSTACKSIZE <= 0 )) || [[ -z $dirstack_file ]]; then return; fi
 886   local -ax my_stack
 887   my_stack=( ${PWD} ${dirstack} )
 888diff --git a/plugins/docker-compose/README.md b/plugins/docker-compose/README.md
 889index 77b98f30df1ff85b1bebf4ed213548408f26fddb..567b821487af846fa41948fea666f7de6280954f 100644
 890--- a/plugins/docker-compose/README.md
 891+++ b/plugins/docker-compose/README.md
 892@@ -1 +1,5 @@
 893 # Docker-compose plugin for oh my zsh
 894+
 895+A copy of the completion script from the [docker-compose](1) git repo.
 896+
 897+[1]:[https://github.com/docker/compose/blob/master/contrib/completion/zsh/_docker-compose]
 898diff --git a/plugins/docker-compose/_docker-compose b/plugins/docker-compose/_docker-compose
 899new file mode 100644
 900index 0000000000000000000000000000000000000000..19c06675ad5057dd09b3398e476744ac8fdd8b10
 901--- /dev/null
 902+++ b/plugins/docker-compose/_docker-compose
 903@@ -0,0 +1,308 @@
 904+#compdef docker-compose
 905+
 906+# Description
 907+# -----------
 908+#  zsh completion for docker-compose
 909+#  https://github.com/sdurrheimer/docker-compose-zsh-completion
 910+# -------------------------------------------------------------------------
 911+# Version
 912+# -------
 913+#  0.1.0
 914+# -------------------------------------------------------------------------
 915+# Authors
 916+# -------
 917+#  * Steve Durrheimer <s.durrheimer@gmail.com>
 918+# -------------------------------------------------------------------------
 919+# Inspiration
 920+# -----------
 921+#  * @albers docker-compose bash completion script
 922+#  * @felixr docker zsh completion script : https://github.com/felixr/docker-zsh-completion
 923+# -------------------------------------------------------------------------
 924+
 925+# For compatibility reasons, Compose and therefore its completion supports several
 926+# stack compositon files as listed here, in descending priority.
 927+# Support for these filenames might be dropped in some future version.
 928+__docker-compose_compose_file() {
 929+    local file
 930+    for file in docker-compose.y{,a}ml fig.y{,a}ml ; do
 931+        [ -e $file ] && {
 932+            echo $file
 933+            return
 934+        }
 935+    done
 936+    echo docker-compose.yml
 937+}
 938+
 939+# Extracts all service names from docker-compose.yml.
 940+___docker-compose_all_services_in_compose_file() {
 941+    local already_selected
 942+    local -a services
 943+    already_selected=$(echo ${words[@]} | tr " " "|")
 944+    awk -F: '/^[a-zA-Z0-9]/{print $1}' "${compose_file:-$(__docker-compose_compose_file)}" 2>/dev/null | grep -Ev "$already_selected"
 945+}
 946+
 947+# All services, even those without an existing container
 948+__docker-compose_services_all() {
 949+    services=$(___docker-compose_all_services_in_compose_file)
 950+    _alternative "args:services:($services)"
 951+}
 952+
 953+# All services that have an entry with the given key in their docker-compose.yml section
 954+___docker-compose_services_with_key() {
 955+    local already_selected
 956+    local -a buildable
 957+    already_selected=$(echo ${words[@]} | tr " " "|")
 958+    # flatten sections to one line, then filter lines containing the key and return section name.
 959+    awk '/^[a-zA-Z0-9]/{printf "\n"};{printf $0;next;}' "${compose_file:-$(__docker-compose_compose_file)}" 2>/dev/null | awk -F: -v key=": +$1:" '$0 ~ key {print $1}' 2>/dev/null | grep -Ev "$already_selected"
 960+}
 961+
 962+# All services that are defined by a Dockerfile reference
 963+__docker-compose_services_from_build() {
 964+    buildable=$(___docker-compose_services_with_key build)
 965+    _alternative "args:buildable services:($buildable)"
 966+}
 967+
 968+# All services that are defined by an image
 969+__docker-compose_services_from_image() {
 970+    pullable=$(___docker-compose_services_with_key image)
 971+    _alternative "args:pullable services:($pullable)"
 972+}
 973+
 974+__docker-compose_get_services() {
 975+    local kind expl
 976+    declare -a running stopped lines args services
 977+
 978+    docker_status=$(docker ps > /dev/null 2>&1)
 979+    if [ $? -ne 0 ]; then
 980+        _message "Error! Docker is not running."
 981+        return 1
 982+    fi
 983+
 984+    kind=$1
 985+    shift
 986+    [[ $kind = (stopped|all) ]] && args=($args -a)
 987+
 988+    lines=(${(f)"$(_call_program commands docker ps ${args})"})
 989+    services=(${(f)"$(_call_program commands docker-compose 2>/dev/null ${compose_file:+-f $compose_file} ${compose_project:+-p $compose_project} ps -q)"})
 990+
 991+    # Parse header line to find columns
 992+    local i=1 j=1 k header=${lines[1]}
 993+    declare -A begin end
 994+    while (( $j < ${#header} - 1 )) {
 995+        i=$(( $j + ${${header[$j,-1]}[(i)[^ ]]} - 1))
 996+        j=$(( $i + ${${header[$i,-1]}[(i)  ]} - 1))
 997+        k=$(( $j + ${${header[$j,-1]}[(i)[^ ]]} - 2))
 998+        begin[${header[$i,$(($j-1))]}]=$i
 999+        end[${header[$i,$(($j-1))]}]=$k
1000+    }
1001+    lines=(${lines[2,-1]})
1002+
1003diff --git a/plugins/docker-compose/docker-compose.plugin.zsh b/plugins/docker-compose/docker-compose.plugin.zsh
1004deleted file mode 100644
1005index 08500408d7a309a116bd8064c829f8fbaea59722..0000000000000000000000000000000000000000
1006--- a/plugins/docker-compose/docker-compose.plugin.zsh
1007+++ /dev/null
1008@@ -1,14 +0,0 @@
1009-# Authors:
1010-# https://github.com/tristola
1011-#
1012-# Docker-compose related zsh aliases
1013-
1014-# Aliases ###################################################################
1015-
1016-alias dcup='docker-compose up'
1017-alias dcb='docker-compose build'
1018-alias dcrm='docker-compose rm'
1019-alias dcps='docker-compose ps'
1020-alias dcstop='docker-compose stop'
1021-alias dcrestart='docker-compose restart'
1022-
1023diff --git a/plugins/docker/_docker b/plugins/docker/_docker
1024index 25f55beca384ecdd3d4b9c970a322676e9e4599c..a82a31ad3441f78d1b79aca8220728b01fe86ff1 100644
1025--- a/plugins/docker/_docker
1026+++ b/plugins/docker/_docker
1027@@ -27,7 +27,7 @@ __docker_all_containers() {
1028 # output a selectable list of all docker images
1029 __docker_images() {
1030     declare -a img_cmd
1031-    img_cmd=($(docker images | awk 'NR>1{print $1}'))
1032+    img_cmd=($(docker images | awk 'NR>1{print $1}'| sed 's/:/\\:/g'))
1033     _describe 'images' img_cmd
1034 }
1035 
1036diff --git a/plugins/ember-cli/README.md b/plugins/ember-cli/README.md
1037index d1dedf8843786d5800d1c53f1efd5f193e47cdbb..482c347d27aa3c6af0dea4c058900362f1cdb0ef 100644
1038--- a/plugins/ember-cli/README.md
1039+++ b/plugins/ember-cli/README.md
1040@@ -1,22 +1,19 @@
1041-# Ember-cli
1042+# Ember CLI
1043 
1044-**Maintainer:** [BilalBudhani](http://www.github.com/BilalBudhani)
1045+**Maintainers:** [BilalBudhani](http://www.github.com/BilalBudhani), [eubenesa](http://www.github.com/eubenesa)
1046 
1047-Ember-cli (http://www.ember-cli.com/)
1048+Ember CLI (http://www.ember-cli.com/)
1049 
1050 ### List of Aliases
1051 
1052-alias es='ember serve'
1053-alias ea='ember addon'
1054-alias eb='ember build'
1055-alias ed='ember destroy'
1056-alias eg='ember generate'
1057-alias eh='ember help'
1058-alias ein='ember init'
1059-alias eia='ember install:addon'
1060-alias eib='ember install:bower'
1061-alias ein='ember install:npm'
1062-alias ei='ember install'
1063-alias et='ember test'
1064-alias eu='ember update'
1065-alias ev='ember version'
1066+    alias es='ember serve'
1067+    alias ea='ember addon'
1068+    alias eb='ember build'
1069+    alias ed='ember destroy'
1070+    alias eg='ember generate'
1071+    alias eh='ember help'
1072+    alias ein='ember init'
1073+    alias ei='ember install'
1074+    alias et='ember test'
1075+    alias eu='ember update'
1076+    alias ev='ember version'
1077diff --git a/plugins/ember-cli/ember-cli.plugin.zsh b/plugins/ember-cli/ember-cli.plugin.zsh
1078index 044a2c0438896a51e05d8dc4015e72db555442f0..a0f3468299e8587435bef1d63ff13ba02d33423e 100644
1079--- a/plugins/ember-cli/ember-cli.plugin.zsh
1080+++ b/plugins/ember-cli/ember-cli.plugin.zsh
1081@@ -1,5 +1,5 @@
1082-# Ember ClI 
1083-# visit http://www.ember-cli.com/ to view user guid 
1084+# Ember CLI
1085+# Visit http://www.ember-cli.com/ to view user guide
1086 
1087 alias es='ember serve'
1088 alias ea='ember addon'
1089@@ -8,9 +8,6 @@ alias ed='ember destroy'
1090 alias eg='ember generate'
1091 alias eh='ember help'
1092 alias ein='ember init'
1093-alias eia='ember install:addon'
1094-alias eib='ember install:bower'
1095-alias ein='ember install:npm'
1096 alias ei='ember install'
1097 alias et='ember test'
1098 alias eu='ember update'
1099diff --git a/plugins/emoji/README.md b/plugins/emoji/README.md
1100new file mode 100644
1101index 0000000000000000000000000000000000000000..889e567e6ce8e3689fa57a517fd74ab8bc8732e6
1102--- /dev/null
1103+++ b/plugins/emoji/README.md
1104@@ -0,0 +1,135 @@
1105+# emoji plugin
1106+
1107+Support for conveniently working with Unicode emoji in Zsh.
1108+
1109+## Features
1110+
1111diff --git a/plugins/emoji/emoji-char-definitions.zsh b/plugins/emoji/emoji-char-definitions.zsh
1112new file mode 100644
1113index 0000000000000000000000000000000000000000..04693da0593b98620161e2d52aaeba3115d953c9
1114--- /dev/null
1115+++ b/plugins/emoji/emoji-char-definitions.zsh
1116@@ -0,0 +1,1303 @@
1117+
1118+# emoji-char-definitions.zsh - Emoji character definitions for oh-my-zsh emoji plugin
1119+#
1120+# This file is auto-generated by update_emoji.pl. Do not edit it manually.
1121+#
1122+# This contains the definition for:
1123+#   $emoji         - which maps character names to Unicode characters
1124+#   $emoji_flags   - maps country names to Unicode flag characters using region indicators 
1125+
1126+# Main emoji
1127+typeset -gAH emoji
1128+# National flags
1129+typeset -gAH emoji_flags
1130+# Combining modifiers
1131+typeset -gAH emoji_mod
1132+
1133+emoji[copyright_sign]=$'\U00A9'
1134+emoji[registered_sign]=$'\U00AE'
1135+emoji[double_exclamation_mark]=$'\U203C'
1136+emoji[exclamation_question_mark]=$'\U2049'
1137+emoji[trade_mark_sign]=$'\U2122'
1138+emoji[information_source]=$'\U2139'
1139+emoji[left_right_arrow]=$'\U2194'
1140+emoji[up_down_arrow]=$'\U2195'
1141+emoji[north_west_arrow]=$'\U2196'
1142+emoji[north_east_arrow]=$'\U2197'
1143+emoji[south_east_arrow]=$'\U2198'
1144+emoji[south_west_arrow]=$'\U2199'
1145+emoji[leftwards_arrow_with_hook]=$'\U21A9'
1146+emoji[rightwards_arrow_with_hook]=$'\U21AA'
1147+emoji[watch]=$'\U231A'
1148+emoji[hourglass]=$'\U231B'
1149+emoji[keyboard]=$'\U2328'
1150+emoji[eject_symbol]=$'\U23CF'
1151+emoji[black_right_pointing_double_triangle]=$'\U23E9'
1152+emoji[black_left_pointing_double_triangle]=$'\U23EA'
1153+emoji[black_up_pointing_double_triangle]=$'\U23EB'
1154+emoji[black_down_pointing_double_triangle]=$'\U23EC'
1155+emoji[black_right_pointing_double_triangle_with_vertical_bar]=$'\U23ED'
1156+emoji[black_left_pointing_double_triangle_with_vertical_bar]=$'\U23EE'
1157+emoji[black_right_pointing_triangle_with_double_vertical_bar]=$'\U23EF'
1158+emoji[alarm_clock]=$'\U23F0'
1159+emoji[stopwatch]=$'\U23F1'
1160+emoji[timer_clock]=$'\U23F2'
1161+emoji[hourglass_with_flowing_sand]=$'\U23F3'
1162+emoji[double_vertical_bar]=$'\U23F8'
1163+emoji[black_square_for_stop]=$'\U23F9'
1164+emoji[black_circle_for_record]=$'\U23FA'
1165+emoji[circled_latin_capital_letter_m]=$'\U24C2'
1166+emoji[black_small_square]=$'\U25AA'
1167+emoji[white_small_square]=$'\U25AB'
1168+emoji[black_right_pointing_triangle]=$'\U25B6'
1169+emoji[black_left_pointing_triangle]=$'\U25C0'
1170+emoji[white_medium_square]=$'\U25FB'
1171+emoji[black_medium_square]=$'\U25FC'
1172+emoji[white_medium_small_square]=$'\U25FD'
1173+emoji[black_medium_small_square]=$'\U25FE'
1174+emoji[black_sun_with_rays]=$'\U2600'
1175+emoji[cloud]=$'\U2601'
1176+emoji[umbrella]=$'\U2602'
1177+emoji[snowman]=$'\U2603'
1178+emoji[comet]=$'\U2604'
1179+emoji[black_telephone]=$'\U260E'
1180+emoji[ballot_box_with_check]=$'\U2611'
1181+emoji[umbrella_with_rain_drops]=$'\U2614'
1182+emoji[hot_beverage]=$'\U2615'
1183+emoji[shamrock]=$'\U2618'
1184+emoji[white_up_pointing_index]=$'\U261D'
1185+emoji[skull_and_crossbones]=$'\U2620'
1186+emoji[radioactive_sign]=$'\U2622'
1187+emoji[biohazard_sign]=$'\U2623'
1188+emoji[orthodox_cross]=$'\U2626'
1189+emoji[star_and_crescent]=$'\U262A'
1190+emoji[peace_symbol]=$'\U262E'
1191+emoji[yin_yang]=$'\U262F'
1192+emoji[wheel_of_dharma]=$'\U2638'
1193+emoji[white_frowning_face]=$'\U2639'
1194+emoji[white_smiling_face]=$'\U263A'
1195+emoji[aries]=$'\U2648'
1196+emoji[taurus]=$'\U2649'
1197+emoji[gemini]=$'\U264A'
1198+emoji[cancer]=$'\U264B'
1199+emoji[leo]=$'\U264C'
1200+emoji[virgo]=$'\U264D'
1201+emoji[libra]=$'\U264E'
1202+emoji[scorpius]=$'\U264F'
1203+emoji[sagittarius]=$'\U2650'
1204+emoji[capricorn]=$'\U2651'
1205+emoji[aquarius]=$'\U2652'
1206+emoji[pisces]=$'\U2653'
1207+emoji[black_spade_suit]=$'\U2660'
1208+emoji[black_club_suit]=$'\U2663'
1209+emoji[black_heart_suit]=$'\U2665'
1210+emoji[black_diamond_suit]=$'\U2666'
1211+emoji[hot_springs]=$'\U2668'
1212+emoji[black_universal_recycling_symbol]=$'\U267B'
1213+emoji[wheelchair_symbol]=$'\U267F'
1214+emoji[hammer_and_pick]=$'\U2692'
1215+emoji[anchor]=$'\U2693'
1216diff --git a/plugins/emoji/emoji-data.txt b/plugins/emoji/emoji-data.txt
1217new file mode 100644
1218index 0000000000000000000000000000000000000000..7b4c015f7afb8ccd82f9b027da43df8c7a8e1ba7
1219--- /dev/null
1220+++ b/plugins/emoji/emoji-data.txt
1221@@ -0,0 +1,1308 @@
1222+# DRAFT emoji-data.txt
1223+# For details about the format and other information, see /../../../reports/tr51/index.html#Data_Files.
1224+#
1225+# Format: Code ; Default_Emoji_Style ; Emoji_Level ; Emoji_Modifier_Status ; Emoji_Sources # Comment
1226+#
1227+#   Field 1 — Default_Emoji_Style:
1228+#             text:      default text presentation
1229+#             emoji:     default emoji presentation
1230+#   Field 2 — Emoji_Level:
1231+#             L1:        level 1 emoji
1232+#             L2:        level 2 emoji
1233+#             NA:        not applicable
1234+#   Field 3 — Emoji_Modifier_Status:
1235+#             modifier:  an emoji modifier
1236+#             primary:   a primary emoji modifier base
1237+#             secondary: a secondary emoji modifier base
1238+#             none:      not applicable
1239+#   Field 4 — Emoji_Sources:
1240+#             one or more values from {z, a, j, w, x}
1241+#             see the key in http://www.unicode.org/draft/reports/tr51/tr51.html#Major_Sources
1242+#             NA:        not applicable
1243+#   Comment — currently contains the version where the character was first encoded,
1244+#             followed by:
1245+#             - a character name in uppercase (for a single character),
1246+#             - a keycap name,
1247+#             - an associated flag, where is associated with value unicode region code
1248+#
1249+00A9 ;	text ;	L1 ;	none ;	j	# V1.1 (©) COPYRIGHT SIGN
1250+00AE ;	text ;	L1 ;	none ;	j	# V1.1 (®) REGISTERED SIGN
1251+203C ;	text ;	L1 ;	none ;	a j	# V1.1 (‼) DOUBLE EXCLAMATION MARK
1252+2049 ;	text ;	L1 ;	none ;	a j	# V3.0 (⁉) EXCLAMATION QUESTION MARK
1253+2122 ;	text ;	L1 ;	none ;	j	# V1.1 (™) TRADE MARK SIGN
1254+2139 ;	text ;	L1 ;	none ;	j	# V3.0 (ℹ) INFORMATION SOURCE
1255+2194 ;	text ;	L1 ;	none ;	z j	# V1.1 (↔) LEFT RIGHT ARROW
1256+2195 ;	text ;	L1 ;	none ;	z j	# V1.1 (↕) UP DOWN ARROW
1257+2196 ;	text ;	L1 ;	none ;	j	# V1.1 (↖) NORTH WEST ARROW
1258+2197 ;	text ;	L1 ;	none ;	j	# V1.1 (↗) NORTH EAST ARROW
1259+2198 ;	text ;	L1 ;	none ;	j	# V1.1 (↘) SOUTH EAST ARROW
1260+2199 ;	text ;	L1 ;	none ;	j	# V1.1 (↙) SOUTH WEST ARROW
1261+21A9 ;	text ;	L1 ;	none ;	j	# V1.1 (↩) LEFTWARDS ARROW WITH HOOK
1262+21AA ;	text ;	L1 ;	none ;	j	# V1.1 (↪) RIGHTWARDS ARROW WITH HOOK
1263+231A ;	emoji ;	L1 ;	none ;	j	# V1.1 (⌚) WATCH
1264+231B ;	emoji ;	L1 ;	none ;	j	# V1.1 (⌛) HOURGLASS
1265+2328 ;	text ;	L2 ;	none ;	x	# V1.1 (⌨) KEYBOARD
1266+23CF ;	text ;	L2 ;	none ;	x	# V4.0 (⏏) EJECT SYMBOL
1267+23E9 ;	emoji ;	L1 ;	none ;	j w	# V6.0 (⏩) BLACK RIGHT-POINTING DOUBLE TRIANGLE
1268+23EA ;	emoji ;	L1 ;	none ;	j w	# V6.0 (⏪) BLACK LEFT-POINTING DOUBLE TRIANGLE
1269+23EB ;	emoji ;	L1 ;	none ;	j	# V6.0 (⏫) BLACK UP-POINTING DOUBLE TRIANGLE
1270+23EC ;	emoji ;	L1 ;	none ;	j	# V6.0 (⏬) BLACK DOWN-POINTING DOUBLE TRIANGLE
1271+23ED ;	text ;	L2 ;	none ;	w	# V6.0 (⏭) BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
1272+23EE ;	text ;	L2 ;	none ;	w	# V6.0 (⏮) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
1273+23EF ;	text ;	L2 ;	none ;	x	# V6.0 (⏯) BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
1274+23F0 ;	emoji ;	L1 ;	none ;	j	# V6.0 (⏰) ALARM CLOCK
1275+23F1 ;	text ;	L2 ;	none ;	x	# V6.0 (⏱) STOPWATCH
1276+23F2 ;	text ;	L2 ;	none ;	x	# V6.0 (⏲) TIMER CLOCK
1277+23F3 ;	emoji ;	L1 ;	none ;	j w	# V6.0 (⏳) HOURGLASS WITH FLOWING SAND
1278+23F8 ;	text ;	L2 ;	none ;	w	# V7.0 (⏸) DOUBLE VERTICAL BAR
1279+23F9 ;	text ;	L2 ;	none ;	w	# V7.0 (⏹) BLACK SQUARE FOR STOP
1280+23FA ;	text ;	L2 ;	none ;	w	# V7.0 (⏺) BLACK CIRCLE FOR RECORD
1281+24C2 ;	text ;	L1 ;	none ;	j	# V1.1 (Ⓜ) CIRCLED LATIN CAPITAL LETTER M
1282+25AA ;	text ;	L1 ;	none ;	j w	# V1.1 (▪) BLACK SMALL SQUARE
1283+25AB ;	text ;	L1 ;	none ;	j	# V1.1 (▫) WHITE SMALL SQUARE
1284+25B6 ;	text ;	L1 ;	none ;	a j w	# V1.1 (▶) BLACK RIGHT-POINTING TRIANGLE
1285+25C0 ;	text ;	L1 ;	none ;	a j w	# V1.1 (◀) BLACK LEFT-POINTING TRIANGLE
1286+25FB ;	text ;	L1 ;	none ;	j	# V3.2 (◻) WHITE MEDIUM SQUARE
1287+25FC ;	text ;	L1 ;	none ;	j w	# V3.2 (◼) BLACK MEDIUM SQUARE
1288+25FD ;	emoji ;	L1 ;	none ;	j	# V3.2 (◽) WHITE MEDIUM SMALL SQUARE
1289+25FE ;	emoji ;	L1 ;	none ;	j w	# V3.2 (◾) BLACK MEDIUM SMALL SQUARE
1290+2600 ;	text ;	L1 ;	none ;	a j	# V1.1 (☀) BLACK SUN WITH RAYS
1291+2601 ;	text ;	L1 ;	none ;	a j w	# V1.1 (☁) CLOUD
1292+2602 ;	text ;	L2 ;	none ;	a	# V1.1 (☂) UMBRELLA
1293+2603 ;	text ;	L2 ;	none ;	a	# V1.1 (☃) SNOWMAN
1294+2604 ;	text ;	L2 ;	none ;	x	# V1.1 (☄) COMET
1295+260E ;	text ;	L1 ;	none ;	z a j	# V1.1 (☎) BLACK TELEPHONE
1296+2611 ;	text ;	L1 ;	none ;	j w	# V1.1 (☑) BALLOT BOX WITH CHECK
1297+2614 ;	emoji ;	L1 ;	none ;	a j	# V4.0 (☔) UMBRELLA WITH RAIN DROPS
1298+2615 ;	emoji ;	L1 ;	none ;	j	# V4.0 (☕) HOT BEVERAGE
1299+2618 ;	text ;	L2 ;	none ;	x	# V4.1 (☘) SHAMROCK
1300+261D ;	text ;	L1 ;	secondary ;	j w	# V1.1 (☝) WHITE UP POINTING INDEX
1301+2620 ;	text ;	L2 ;	none ;	x	# V1.1 (☠) SKULL AND CROSSBONES
1302+2622 ;	text ;	L2 ;	none ;	x	# V1.1 (☢) RADIOACTIVE SIGN
1303+2623 ;	text ;	L2 ;	none ;	x	# V1.1 (☣) BIOHAZARD SIGN
1304+2626 ;	text ;	L2 ;	none ;	x	# V1.1 (☦) ORTHODOX CROSS
1305+262A ;	text ;	L2 ;	none ;	w	# V1.1 (☪) STAR AND CRESCENT
1306+262E ;	text ;	L2 ;	none ;	x	# V1.1 (☮) PEACE SYMBOL
1307+262F ;	text ;	L2 ;	none ;	w	# V1.1 (☯) YIN YANG
1308+2638 ;	text ;	L2 ;	none ;	w	# V1.1 (☸) WHEEL OF DHARMA
1309+2639 ;	text ;	L2 ;	secondary ;	w	# V1.1 (☹) WHITE FROWNING FACE
1310+263A ;	text ;	L1 ;	secondary ;	j w	# V1.1 (☺) WHITE SMILING FACE
1311+2648 ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♈) ARIES
1312+2649 ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♉) TAURUS
1313+264A ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♊) GEMINI
1314+264B ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♋) CANCER
1315+264C ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♌) LEO
1316+264D ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♍) VIRGO
1317+264E ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♎) LIBRA
1318+264F ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♏) SCORPIUS
1319+2650 ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♐) SAGITTARIUS
1320+2651 ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♑) CAPRICORN
1321diff --git a/plugins/emoji/emoji.plugin.zsh b/plugins/emoji/emoji.plugin.zsh
1322new file mode 100644
1323index 0000000000000000000000000000000000000000..7876f1c89e5580d8b57bd1fd2d3ae756bba36c80
1324--- /dev/null
1325+++ b/plugins/emoji/emoji.plugin.zsh
1326@@ -0,0 +1,288 @@
1327+# emoji plugin
1328+#
1329+# Makes emoji support available within ZSH
1330+#
1331+# See the README for documentation.
1332+
1333+_omz_emoji_plugin_dir="${0:h}"
1334+
1335+() {
1336+
1337+local LC_ALL=en_US.UTF-8
1338+
1339+typeset -gAH emoji_groups
1340+typeset -gAH emoji_con
1341+typeset -gAH emoji2
1342+typeset -gAH emoji_skintone
1343+
1344+source "$_omz_emoji_plugin_dir/emoji-char-definitions.zsh"
1345+unset _omz_emoji_plugin_dir
1346+
1347+# These additional emoji are not in the definition file, but are useful in conjunction with it
1348+
1349+# This is a combinin character that can be placed after any other character to surround
1350+# it in a "keycap" symbol.
1351+# The digits 0-9 are already in the emoji table as keycap_digit_<N>, keycap_ten, etc. 
1352+# It's unclear whether this should be in the $emoji array, because those characters are all ones
1353+# which can be displayed on their own.
1354+#emoji[combining_enclosing_keycap]="\U20E3"
1355+
1356+emoji[regional_indicator_symbol_letter_d_regional_indicator_symbol_letter_e]=$'\xF0\x9F\x87\xA9\xF0\x9F\x87\xAA'
1357+emoji[regional_indicator_symbol_letter_g_regional_indicator_symbol_letter_b]=$'\xF0\x9F\x87\xAC\xF0\x9F\x87\xA7'
1358+emoji[regional_indicator_symbol_letter_c_regional_indicator_symbol_letter_n]=$'\xF0\x9F\x87\xA8\xF0\x9F\x87\xB3'
1359+emoji[regional_indicator_symbol_letter_j_regional_indicator_symbol_letter_p]=$'\xF0\x9F\x87\xAF\xF0\x9F\x87\xB5'
1360+emoji[regional_indicator_symbol_letter_k_regional_indicator_symbol_letter_r]=$'\xF0\x9F\x87\xB0\xF0\x9F\x87\xB7'
1361+emoji[regional_indicator_symbol_letter_f_regional_indicator_symbol_letter_r]=$'\xF0\x9F\x87\xAB\xF0\x9F\x87\xB7'
1362+emoji[regional_indicator_symbol_letter_e_regional_indicator_symbol_letter_s]=$'\xF0\x9F\x87\xAA\xF0\x9F\x87\xB8'
1363+emoji[regional_indicator_symbol_letter_i_regional_indicator_symbol_letter_t]=$'\xF0\x9F\x87\xAE\xF0\x9F\x87\xB9'
1364+emoji[regional_indicator_symbol_letter_u_regional_indicator_symbol_letter_s]=$'\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8'
1365+emoji[regional_indicator_symbol_letter_r_regional_indicator_symbol_letter_u]=$'\xF0\x9F\x87\xB7\xF0\x9F\x87\xBA'
1366+
1367+# Nonstandard alias names
1368+emoji[vulcan_salute]=$'\U1F596'
1369+
1370+
1371+# Emoji combining and auxiliary characters
1372+
1373+# "Variation Selectors" for controlling text vs emoji style presentation
1374+# These apply to the immediately preceding character
1375+emoji2[text_style]=$'\UFE0E'
1376+emoji2[emoji_style]=$'\UFE0F'
1377+# Joiner that indicates a single combined-form glyph (ligature) should be used
1378+emoji2[zero_width_joiner]=$'\U200D'
1379+# Skin tone modifiers
1380+emoji2[emoji_modifier_fitzpatrick_type_1_2]=$'\U1F3FB'
1381+emoji2[emoji_modifier_fitzpatrick_type_3]=$'\U1F3FC'
1382+emoji2[emoji_modifier_fitzpatrick_type_4]=$'\U1F3FD'
1383+emoji2[emoji_modifier_fitzpatrick_type_5]=$'\U1F3FE'
1384+emoji2[emoji_modifier_fitzpatrick_type_6]=$'\U1F3FF'
1385+# Various other combining characters. (Incomplete list; I selected ones that sound useful)
1386+emoji2[combining_enclosing_circle]=$'\U20DD'
1387+emoji2[combining_enclosing_square]=$'\U20DE'
1388+emoji2[combining_enclosing_diamond]=$'\U20DF'
1389+emoji2[combining_enclosing_circle_backslash]=$'\U20E0'
1390+emoji2[combining_enclosing_screen]=$'\U20E2'
1391+emoji2[combining_enclosing_keycap]=$'\U20E3'
1392+emoji2[combining_enclosing_upward_pointing_triangle]=$'\U20E4'
1393+
1394+# Easier access to skin tone modifiers
1395+emoji_skintone[1_2]=$'\U1F3FB'
1396+emoji_skintone[3]=$'\U1F3FC'
1397+emoji_skintone[4]=$'\U1F3FD'
1398+emoji_skintone[5]=$'\U1F3FE'
1399+emoji_skintone[6]=$'\U1F3FF'
1400+
1401+# Emoji groups
1402+# These are stored in a single associative array, $emoji_groups, to avoid cluttering up the global
1403+# namespace, and to allow adding additional group definitions at run time.
1404+# The keys are the group names, and the values are whitespace-separated lists of emoji character names.
1405+
1406+emoji_groups[fruits]="
1407+  tomato
1408+  aubergine
1409+  grapes
1410+  melon
1411+  watermelon
1412+  tangerine
1413+  banana
1414+  pineapple
1415+  red_apple
1416+  green_apple
1417+  peach
1418+  cherries
1419+  strawberry
1420+  lemon
1421+  pear
1422+"
1423+
1424+emoji_groups[vehicles]="
1425+  airplane
1426diff --git a/plugins/emoji/update_emoji.pl b/plugins/emoji/update_emoji.pl
1427new file mode 100644
1428index 0000000000000000000000000000000000000000..04f3ce8e77f2e3f18ca6ded37e0a95b2b5520b04
1429--- /dev/null
1430+++ b/plugins/emoji/update_emoji.pl
1431@@ -0,0 +1,113 @@
1432+#!/usr/bin/perl -w
1433+#
1434+# update_emoji.pl
1435+#
1436+# This script generates the emoji.plugin.zsh emoji definitions from the Unicode
1437+# character data for the emoji characters.
1438+#
1439+# The data file can be found at http://unicode.org/Public/emoji/latest/emoji-data.txt
1440+# as referenced in Unicode TR51 (http://www.unicode.org/reports/tr51/index.html).
1441+#
1442+# This is known to work with the data file from version 1.0. It may not work with later
1443+# versions if the format changes. In particular, this reads line comments to get the
1444+# emoji character name and unicode version.
1445+#
1446+# Country names have punctuation and other non-letter characters removed from their name,
1447+# to avoid possible complications with having to escape the strings when using them as 
1448+# array subscripts. The definition file seems to use some combining characters like accents
1449+# that get stripped during this process.
1450+
1451+use strict;
1452+use warnings;
1453+use 5.010;
1454+use autodie;
1455+
1456+use Path::Class;
1457+use File::Copy;
1458+
1459+# Parse definitions out of the data file and convert
1460+sub process_emoji_data_file {
1461+	my ( $infile, $outfilename ) = @_;
1462+	my $file = file($infile);
1463+	my $outfile = file($outfilename);
1464+	my $outfilebase = $outfile->basename();
1465+	my $tempfilename = "$outfilename.tmp";
1466+	my $tempfile = file($tempfilename);
1467+	my $outfh = $tempfile->openw();
1468+	$outfh->print("
1469+# $outfilebase - Emoji character definitions for oh-my-zsh emoji plugin
1470+#
1471+# This file is auto-generated by update_emoji.pl. Do not edit it manually.
1472+#
1473+# This contains the definition for:
1474+#   \$emoji         - which maps character names to Unicode characters
1475+#   \$emoji_flags   - maps country names to Unicode flag characters using region indicators 
1476+
1477+# Main emoji
1478+typeset -gAH emoji
1479+# National flags
1480+typeset -gAH emoji_flags
1481+# Combining modifiers
1482+typeset -gAH emoji_mod
1483+
1484+");
1485+
1486+	my $fh = $file->openr();
1487+	my $line_num = 0;
1488+	while ( my $line = $fh->getline() ) {
1489+		$line_num++;
1490+		$_ = $line;
1491+		# Skip all-comment lines (from the header) and blank lines
1492+		# (But don't strip comments on normal lines; we need to parse those for
1493+		# the emoji names.)
1494+		next if /^\s*#/ or /^\s*$/;
1495+
1496+		if (/^(\S.*?\S)\s*;\s*(\w+)\s*;\s*(\w+)\s*;\s*(\w+)\s*;\s*(\w.*?)\s*#\s*V(\S+)\s\(.*?\)\s*(\w.*\S)\s*$/) {
1497+			my ($code, $style, $level, $modifier_status, $sources, $version, $keycap_name) 
1498+				= ($1, $2, $3, $4, $5, $6, $7);
1499+			#print "code=$code style=$style level=$level modifier_status=$modifier_status sources=$sources version=$version name=$keycap_name\n";
1500+			my @code_points = split /\s+/, $code;
1501+			my @sources = split /\s+/, $sources;
1502+
1503+			my $flag_country = "";
1504+			if ( $keycap_name =~ /^flag for (\S.*?)\s*$/) {
1505+				$flag_country = $1;
1506+			}
1507+
1508+			my $zsh_code = join '', map { "\\U$_" } @code_points;
1509+			# Convert keycap names to valid associative array names that do not require any
1510+			# quoting. Works fine for most stuff, but is clumsy for flags.
1511+			my $omz_name = lc($keycap_name);
1512+			$omz_name =~ s/[^A-Za-z0-9]/_/g;
1513+			my $zsh_flag_country = $flag_country;
1514+			$zsh_flag_country =~ s/[^\p{Letter}]/_/g;
1515+			if ($flag_country) {
1516+				$outfh->print("emoji_flags[$zsh_flag_country]=\$'$zsh_code'\n");
1517+			} else {
1518+				$outfh->print("emoji[$omz_name]=\$'$zsh_code'\n");				
1519+			}
1520+			# Modifiers are included in both the main set and their separate map,
1521+			# because they have a standalone representation as a color swatch.
1522+			if ( $modifier_status eq "modifier" ) {
1523+				$outfh->print("emoji_mod[$omz_name]=\$'$zsh_code'\n");
1524+			}
1525+		} else {
1526+			die "Failed parsing line $line_num: '$_'";
1527+		}
1528+	}
1529+	$fh->close();
1530+	$outfh->print("\n");
1531diff --git a/plugins/emotty/emotty.plugin.zsh b/plugins/emotty/emotty.plugin.zsh
1532new file mode 100644
1533index 0000000000000000000000000000000000000000..b32dd1a4c52b0a76ec21b6b7a5485db6f6a5af5a
1534--- /dev/null
1535+++ b/plugins/emotty/emotty.plugin.zsh
1536@@ -0,0 +1,43 @@
1537+# ------------------------------------------------------------------------------
1538+#          FILE: emotty.plugin.zsh
1539+#   DESCRIPTION: Return an emoji for the current $TTY number.
1540+#        AUTHOR: Alexis Hildebrandt (afh[at]surryhill.net)
1541+#       VERSION: 1.0.0
1542+#       DEPENDS: emoji plugin
1543+#       
1544+# There are different sets of emoji characters available, to choose a different
1545+# set export emotty_set to the name of the set you would like to use, e.g.:
1546+# % export emotty_set=nature
1547+# ------------------------------------------------------------------------------
1548+
1549+typeset -gAH _emotty_sets
1550+local _emotty_plugin_dir="${0:h}"
1551+source "$_emotty_plugin_dir/emotty_stellar_set.zsh"
1552+source "$_emotty_plugin_dir/emotty_floral_set.zsh"
1553+source "$_emotty_plugin_dir/emotty_zodiac_set.zsh"
1554+source "$_emotty_plugin_dir/emotty_nature_set.zsh"
1555+source "$_emotty_plugin_dir/emotty_emoji_set.zsh"
1556+source "$_emotty_plugin_dir/emotty_love_set.zsh"
1557+unset _emotty_plugin_dir
1558+
1559+emotty_default_set=emoji
1560+
1561+function emotty() {
1562+  # Use emotty set defined by user, fallback to default
1563+  local emotty=${_emotty_sets[${emotty_set:-$emotty_default_set}]}
1564+  # Parse $TTY number, normalizing it to an emotty set index
1565+  (( tty = (${TTY##/dev/ttys} % ${#${=emotty}}) + 1 ))
1566+  local character_name=${${=emotty}[tty]}
1567+  echo "${emoji[${character_name}]}${emoji2[emoji_style]}"
1568+}
1569+
1570+function display_emotty() {
1571+  local name=$1
1572+  for i in ${=_emotty_sets[$name]}; do
1573+    printf "${emoji[$i]}${emoji2[emoji_style]}  "
1574+  done
1575+  print
1576+  for i in ${=_emotty_sets[$name]}; do
1577+    print "${emoji[$i]}${emoji2[emoji_style]}  = $i"
1578+  done
1579+}
1580diff --git a/plugins/emotty/emotty_emoji_set.zsh b/plugins/emotty/emotty_emoji_set.zsh
1581new file mode 100644
1582index 0000000000000000000000000000000000000000..00e3171312aa7da12ba138f19904d2184e58b0e7
1583--- /dev/null
1584+++ b/plugins/emotty/emotty_emoji_set.zsh
1585@@ -0,0 +1,24 @@
1586+#!/usr/bin/env zsh
1587+# vim:ft=zsh ts=2 sw=2 sts=2
1588+
1589+_emotty_sets[emoji]="
1590+  crystal_ball
1591+  ghost
1592+  jack_o_lantern
1593+  see_no_evil_monkey
1594+  hear_no_evil_monkey
1595+  speak_no_evil_monkey
1596+  smiling_cat_face_with_open_mouth
1597+  extraterrestrial_alien
1598+  rocket
1599+  billiards
1600+  bomb
1601+  pill
1602+  japanese_symbol_for_beginner
1603+  direct_hit
1604+  cyclone
1605+  diamond_shape_with_a_dot_inside
1606+  sparkle
1607+  eight_spoked_asterisk
1608+  eight_pointed_black_star
1609+  "
1610diff --git a/plugins/emotty/emotty_floral_set.zsh b/plugins/emotty/emotty_floral_set.zsh
1611new file mode 100644
1612index 0000000000000000000000000000000000000000..f761feae6de186cf83e68f8398d535472dc1fd82
1613--- /dev/null
1614+++ b/plugins/emotty/emotty_floral_set.zsh
1615@@ -0,0 +1,18 @@
1616+#!/usr/bin/env zsh
1617+# vim:ft=zsh ts=2 sw=2 sts=2
1618+
1619+_emotty_sets[floral]="
1620+  hibiscus
1621+  cherry_blossom
1622+  blossom
1623+  sunflower
1624+  bouquet
1625+  tulip
1626+  rose
1627+  four_leaf_clover
1628+  seedling
1629+  herb
1630+  palm_tree
1631+  evergreen_tree
1632+  deciduous_tree
1633+  "
1634diff --git a/plugins/emotty/emotty_love_set.zsh b/plugins/emotty/emotty_love_set.zsh
1635new file mode 100644
1636index 0000000000000000000000000000000000000000..8f19e6902e2e5842eba4ed2dfb53e36ef619b391
1637--- /dev/null
1638+++ b/plugins/emotty/emotty_love_set.zsh
1639@@ -0,0 +1,34 @@
1640+#!/usr/bin/env zsh
1641+# vim:ft=zsh ts=2 sw=2 sts=2
1642+
1643+# Note: The heavy_black_heart emoji requires $emoji2[emoji_style]
1644+# to be rendered as the emoji red heart.
1645+_emotty_sets[love]="
1646+  green_heart
1647+  blue_heart
1648+  purple_heart
1649+  yellow_heart
1650+  heavy_black_heart
1651+  broken_heart
1652+  heart_with_arrow
1653+  heart_with_ribbon
1654+  sparkling_heart
1655+  two_hearts
1656+  revolving_hearts
1657+  growing_heart
1658+  beating_heart
1659+  heart_decoration
1660+  couple_with_heart
1661+  kiss
1662+  man_and_woman_holding_hands
1663+  two_women_holding_hands
1664+  two_men_holding_hands
1665+  kiss_mark
1666+  smiling_face_with_heart_shaped_eyes
1667+  kissing_face
1668+  face_throwing_a_kiss
1669+  kissing_face_with_smiling_eyes
1670+  kissing_face_with_closed_eyes
1671+  smiling_cat_face_with_heart_shaped_eyes
1672+  kissing_cat_face_with_closed_eyes
1673+  "
1674diff --git a/plugins/emotty/emotty_nature_set.zsh b/plugins/emotty/emotty_nature_set.zsh
1675new file mode 100644
1676index 0000000000000000000000000000000000000000..8dab4c1ba2eee2ad59bb8335dea79aabb007dadd
1677--- /dev/null
1678+++ b/plugins/emotty/emotty_nature_set.zsh
1679@@ -0,0 +1,58 @@
1680+#!/usr/bin/env zsh
1681+# vim:ft=zsh ts=2 sw=2 sts=2
1682+
1683+_emotty_sets[nature]="
1684+  mouse_face
1685+  hamster_face
1686+  rabbit_face
1687+  dog_face
1688+  cat_face
1689+  tiger_face
1690+  bear_face
1691+  monkey_face
1692+  koala
1693+  panda_face
1694+  chicken
1695+  baby_chick
1696+  bird
1697+  penguin
1698+  cow_face
1699+  pig_face
1700+  frog_face
1701+  boar
1702+  wolf_face
1703+  horse_face
1704+  snail
1705+  bug
1706+  ant
1707+  honeybee
1708+  lady_beetle
1709+  spouting_whale
1710+  dolphin
1711+  octopus
1712+  fish
1713+  tropical_fish
1714+  snake
1715+  turtle
1716+  lemon
1717+  tangerine
1718+  peach
1719+  mushroom
1720+  tomato
1721+  strawberry
1722+  red_apple
1723+  cherries
1724+  grapes
1725+  aubergine
1726+  watermelon
1727+  banana
1728+  pineapple
1729+  melon
1730+  pear
1731+  green_apple
1732+  ear_of_maize
1733+  sunflower
1734+  seedling
1735+  herb
1736+  four_leaf_clover
1737+  "
1738diff --git a/plugins/emotty/emotty_stellar_set.zsh b/plugins/emotty/emotty_stellar_set.zsh
1739new file mode 100644
1740index 0000000000000000000000000000000000000000..8e7e61068a523461cd1dbd4b5d0e8e023a35ce6c
1741--- /dev/null
1742+++ b/plugins/emotty/emotty_stellar_set.zsh
1743@@ -0,0 +1,25 @@
1744+#!/usr/bin/env zsh
1745+# vim:ft=zsh ts=2 sw=2 sts=2
1746+
1747+# NOTE: The following emoji show as $'character' in the title
1748+#  white_medium_star
1749+#  sparkles
1750+#  dizzy_symbol
1751+
1752+_emotty_sets[stellar]="
1753+  full_moon_symbol
1754+  waning_gibbous_moon_symbol
1755+  waning_crescent_moon_symbol
1756+  last_quarter_moon_symbol
1757+  new_moon_symbol
1758+  new_moon_with_face
1759+  waxing_crescent_moon_symbol
1760+  first_quarter_moon_symbol
1761+  waxing_gibbous_moon_symbol
1762+  full_moon_with_face
1763+  sun_with_face
1764+  glowing_star
1765+  crescent_moon
1766+  first_quarter_moon_with_face
1767+  last_quarter_moon_with_face
1768+  "
1769diff --git a/plugins/emotty/emotty_zodiac_set.zsh b/plugins/emotty/emotty_zodiac_set.zsh
1770new file mode 100644
1771index 0000000000000000000000000000000000000000..bde6e3d2e764477ce3ed0e3a0186d02a09ed6bff
1772--- /dev/null
1773+++ b/plugins/emotty/emotty_zodiac_set.zsh
1774@@ -0,0 +1,29 @@
1775+#!/usr/bin/env zsh
1776+# vim:ft=zsh ts=2 sw=2 sts=2
1777+
1778+_emotty_sets[zodiac]="
1779+  aries
1780+  taurus
1781+  gemini
1782+  cancer
1783+  leo
1784+  virgo
1785+  libra
1786+  scorpius
1787+  sagittarius
1788+  capricorn
1789+  aquarius
1790+  pisces
1791+  rat
1792+  ox
1793+  tiger
1794+  rabbit
1795+  dragon
1796+  snake
1797+  horse
1798+  goat
1799+  monkey
1800+  rooster
1801+  dog
1802+  pig
1803+  "
1804diff --git a/plugins/fancy-ctrl-z/README.md b/plugins/fancy-ctrl-z/README.md
1805new file mode 100644
1806index 0000000000000000000000000000000000000000..a7670fa2c2d9a21ea1c5aeeeb06ed07c6ece2988
1807--- /dev/null
1808+++ b/plugins/fancy-ctrl-z/README.md
1809@@ -0,0 +1,14 @@
1810+# Use Ctrl-Z to switch back to Vim
1811+
1812+I frequently need to execute random command in my shell. To achieve it I pause 
1813+Vim by pressing Ctrl-z, type command and press fg<Enter> to switch back to Vim.
1814+The fg part really hurt sme. I just wanted to hit Ctrl-z once again to get back 
1815+to Vim. I could not find a solution, so I developed one on my own that 
1816+works wonderfully with ZSH
1817+
1818+Source: http://sheerun.net/2014/03/21/how-to-boost-your-vim-productivity/
1819+
1820+Credits: 
1821+- original idea by @sheerun
1822+- added to OMZ by @mbologna
1823+
1824diff --git a/plugins/fancy-ctrl-z/fancy-ctrl-z.plugin.zsh b/plugins/fancy-ctrl-z/fancy-ctrl-z.plugin.zsh
1825new file mode 100644
1826index 0000000000000000000000000000000000000000..8ab2979133efda46a4ce1990f4d159da69d603e6
1827--- /dev/null
1828+++ b/plugins/fancy-ctrl-z/fancy-ctrl-z.plugin.zsh
1829@@ -0,0 +1,12 @@
1830+fancy-ctrl-z () {
1831+  if [[ $#BUFFER -eq 0 ]]; then
1832+    BUFFER="fg"
1833+    zle accept-line
1834+  else
1835+    zle push-input
1836+    zle clear-screen
1837+  fi
1838+}
1839+zle -N fancy-ctrl-z
1840+bindkey '^Z' fancy-ctrl-z
1841+
1842diff --git a/plugins/fasd/fasd.plugin.zsh b/plugins/fasd/fasd.plugin.zsh
1843index 472ab2b0f6b630d3c68c0de835ff4695f6306a75..b11f0b511f68ea343dcf6e090db26c9975b8fd0e 100644
1844--- a/plugins/fasd/fasd.plugin.zsh
1845+++ b/plugins/fasd/fasd.plugin.zsh
1846@@ -5,7 +5,7 @@ if [ $commands[fasd] ]; then # check if fasd is installed
1847   fi
1848   source "$fasd_cache"
1849   unset fasd_cache
1850+
1851   alias v='f -e vim'
1852-  alias o='a -e open'
1853+  alias o='a -e open_command'
1854 fi
1855-
1856diff --git a/plugins/fbterm/fbterm.plugin.zsh b/plugins/fbterm/fbterm.plugin.zsh
1857index 4f0456016f1bfa70f8a8b9efa5ea3089b5f806c2..bc253209201cca8c4a1ea4c4d30b21a621c40b07 100644
1858--- a/plugins/fbterm/fbterm.plugin.zsh
1859+++ b/plugins/fbterm/fbterm.plugin.zsh
1860@@ -1,6 +1,7 @@
1861 # start fbterm automatically in /dev/tty*
1862 
1863-if [[ $(tty|grep -o '/dev/tty') = /dev/tty ]] ; then
1864-	fbterm
1865-	exit
1866+if (( ${+commands[fbterm]} )); then
1867+	if [[ "$TTY" = /dev/tty* ]] ; then
1868+		fbterm && exit
1869+	fi
1870 fi
1871diff --git a/plugins/frontend-search/README.md b/plugins/frontend-search/README.md
1872index 801d450f300db76af79370ce96f2ac9ef65ba024..d0bc5589f742e2dd3081242f2811b69d0571bff4 100644
1873--- a/plugins/frontend-search/README.md
1874+++ b/plugins/frontend-search/README.md
1875@@ -1,74 +1,60 @@
1876-## Rationale ##
1877+## Introduction ##
1878 
1879-> Searches for your Frontend contents more easier
1880+> Searches for your frontend web development made easier
1881 
1882 
1883-## Instalation ##
1884+## Installation ##
1885 
1886+Open your `~/.zshrc` file and enable the `frontend-search` plugin:
1887 
1888-Open your `.zshrc` file and load `frontend-search` plugin
1889+```zsh
1890+
1891+plugins=( ... frontend-search)
1892 
1893-```bash
1894-...
1895-plugins=( <your-plugins-list>... frontend-search)
1896-...
1897 ```
1898 
1899 
1900-## Commands ##
1901-
1902-All command searches are accept only in format
1903-
1904-* `frontend <search-content> <search-term>`
1905-
1906-The search content are
1907-
1908-* `jquery <api.jquery.com>`
1909-* `mdn <developer.mozilla.org>`
1910-* `compass <compass-style.org>`
1911-* `html5please <html5please.com>`
1912-* `caniuse <caniuse.com>`
1913-* `aurajs <aurajs.com>`
1914-* `dartlang <api.dartlang.org/apidocs/channels/stable/dartdoc-viewer>`
1915-* `lodash <search>`
1916-* `qunit <api.qunitjs.com>`
1917-* `fontello <fontello.com>`
1918-* `bootsnipp <bootsnipp.com>`
1919-* `cssflow <cssflow.com>`
1920-* `codepen <codepen.io>`
1921-* `unheap <www.unheap.com>`
1922-* `bem <google.com/search?as_q=<search-term>&as_sitesearch=bem.info>`
1923-* `smacss <google.com/search?as_q=<search-term>&as_sitesearch=smacss.com>`
1924-* `angularjs <google.com/search?as_q=<search-term>&as_sitesearch=angularjs.org>`
1925-* `reactjs <google.com/search?as_q=<search-term>&as_sitesearch=facebook.github.io/react>`
1926-* `emberjs <emberjs.com>`
1927-* `stackoverflow <stackoverflow.com>`
1928-
1929-
1930-## Aliases ##
1931-
1932-There are a few aliases presented as well:
1933-
1934-* `jquery` A shorthand for `frontend jquery`
1935-* `mdn` A shorthand for `frontend mdn`
1936-* `compass` A shorthand for `frontend compass`
1937-* `html5please` A shorthand for `frontend html5please`
1938-* `caniuse` A shorthand for `frontend caniuse`
1939-* `aurajs` A shorthand for `frontend aurajs`
1940-* `dartlang` A shorthand for `frontend dartlang`
1941-* `lodash` A shorthand for `frontend lodash`
1942-* `qunit` A shorthand for `frontend qunit`
1943-* `fontello` A shorthand for `frontend fontello`
1944-* `bootsnipp` A shorthand for `frontend bootsnipp`
1945-* `cssflow` A shorthand for `frontend cssflow`
1946-* `codepen` A shorthand for `frontend codepen`
1947-* `unheap` A shorthand for `frontend unheap`
1948-* `bem` A shorthand for `frontend bem`
1949-* `smacss` A shorthand for `frontend smacss`
1950-* `angularjs` A shorthand for `frontend angularjs`
1951-* `reactjs` A shorthand for `frontend reactjs`
1952-* `emberjs` A shorthand for `frontend emberjs`
1953-* `stackoverflow` A shorthand for `frontend stackoverflow`
1954+## Usage ##
1955+
1956+You can use the frontend-search plugin in these two forms:
1957+
1958+* `frontend <context> <term> [more terms if you want]`
1959+* `<context> <term> [more terms if you want]`
1960+
1961+For example, these two are equivalent:
1962+
1963+```zsh
1964+$ frontend angularjs dependency injection
1965+$ angularjs dependency injection
1966+```
1967+
1968+Available search contexts are:
1969+
1970+| context       | URL                                                                      |
1971+|---------------|--------------------------------------------------------------------------|
1972+| angularjs     | `https://google.com/search?as_sitesearch=angularjs.org&as_q=`            |
1973+| aurajs        | `http://aurajs.com/api/#stq=`                                            |
1974+| bem           | `https://google.com/search?as_sitesearch=bem.info&as_q=`                 |
1975diff --git a/plugins/frontend-search/_frontend-search.sh b/plugins/frontend-search/_frontend-search.sh
1976index 252f215707240ce8c11236d919b601c51791be62..b12f829a1c58e52388c7a613b9569ec7406ce3cf 100644
1977--- a/plugins/frontend-search/_frontend-search.sh
1978+++ b/plugins/frontend-search/_frontend-search.sh
1979@@ -37,6 +37,7 @@ function _frontend() {
1980     'reactjs: Search in React website'
1981     'emberjs: Search in Ember website'
1982     'stackoverflow: Search in StackOverflow website'
1983+    'npmjs: Search in NPMJS website'
1984   )
1985 
1986   _arguments -C \
1987@@ -110,6 +111,9 @@ function _frontend() {
1988         stackoverflow)
1989           _describe -t points "Warp points" frontend_points && ret=0
1990           ;;
1991+        npmjs)
1992+          _describe -t points "Warp points" frontend_points && ret=0
1993+          ;;
1994       esac
1995       ;;
1996   esac
1997diff --git a/plugins/frontend-search/frontend-search.plugin.zsh b/plugins/frontend-search/frontend-search.plugin.zsh
1998index b9fb8634c66f15619247713d82febeeb28fbfeeb..2fd5416b3c032aaab73f1ea780aa717881ddb680 100644
1999--- a/plugins/frontend-search/frontend-search.plugin.zsh
2000+++ b/plugins/frontend-search/frontend-search.plugin.zsh
2001@@ -1,158 +1,91 @@
2002-# frontend from terminal
2003+alias angularjs='frontend angularjs'
2004+alias aurajs='frontend aurajs'
2005+alias bem='frontend bem'
2006+alias bootsnipp='frontend bootsnipp'
2007+alias caniuse='frontend caniuse'
2008+alias codepen='frontend codepen'
2009+alias compass='frontend compass'
2010+alias cssflow='frontend cssflow'
2011+alias dartlang='frontend dartlang'
2012+alias emberjs='frontend emberjs'
2013+alias fontello='frontend fontello'
2014+alias html5please='frontend html5please'
2015+alias jquery='frontend jquery'
2016+alias lodash='frontend lodash'
2017+alias mdn='frontend mdn'
2018+alias npmjs='frontend npmjs'
2019+alias qunit='frontend qunit'
2020+alias reactjs='frontend reactjs'
2021+alias smacss='frontend smacss'
2022+alias stackoverflow='frontend stackoverflow'
2023+alias unheap='frontend unheap'
2024 
2025 function frontend() {
2026-
2027-  # get the open command
2028-  local open_cmd
2029-  if [[ $(uname -s) == 'Darwin' ]]; then
2030-    open_cmd='open'
2031-  else
2032-    open_cmd='xdg-open'
2033-  fi
2034-
2035-  # no keyword provided, simply show how call methods
2036-  if [[ $# -le 1 ]]; then
2037-    echo "Please provide a search-content and a search-term for app.\nEx:\nfrontend <search-content> <search-term>\n"
2038-    return 1
2039+  emulate -L zsh
2040+
2041+  # define search context URLS
2042+  typeset -A urls
2043+  urls=(
2044+    angularjs      'https://google.com/search?as_sitesearch=angularjs.org&as_q='
2045+    aurajs         'http://aurajs.com/api/#stq='
2046+    bem            'https://google.com/search?as_sitesearch=bem.info&as_q='
2047+    bootsnipp      'http://bootsnipp.com/search?q='
2048+    caniuse        'http://caniuse.com/#search='
2049+    codepen        'http://codepen.io/search?q='
2050+    compass        'http://compass-style.org/search?q='
2051+    cssflow        'http://www.cssflow.com/search?q='
2052+    dartlang       'https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:'
2053+    emberjs        'http://emberjs.com/api/#stp=1&stq='
2054+    fontello       'http://fontello.com/#search='
2055+    html5please    'http://html5please.com/#'
2056+    jquery         'https://api.jquery.com/?s='
2057+    lodash         'https://devdocs.io/lodash/index#'
2058+    mdn            'https://developer.mozilla.org/search?q='
2059+    npmjs          'https://www.npmjs.com/search?q='
2060+    qunit          'https://api.qunitjs.com/?s='
2061+    reactjs        'https://google.com/search?as_sitesearch=facebook.github.io/react&as_q='
2062+    smacss         'https://google.com/search?as_sitesearch=smacss.com&as_q='
2063+    stackoverflow  'http://stackoverflow.com/search?q='
2064+    unheap         'http://www.unheap.com/?s='
2065+  )
2066+
2067+  # show help for command list
2068+  if [[ $# -lt 2 ]]
2069+  then
2070+      print -P "Usage: frontend %Ucontext%u %Uterm%u [...%Umore%u] (or just: %Ucontext%u %Uterm%u [...%Umore%u])"
2071+      print -P ""
2072+      print -P "%Uterm%u and what follows is what will be searched for in the %Ucontext%u website,"
2073+      print -P "and %Ucontext%u is one of the following:"
2074+      print -P ""
2075+      print -P "  angularjs, aurajs, bem, bootsnipp, caniuse, codepen, compass, cssflow,"
2076+      print -P "  dartlang, emberjs, fontello, html5please, jquery, lodash, mdn, npmjs,"
2077+      print -P "  qunit, reactjs, smacss, stackoverflow, unheap"
2078+      print -P ""
2079+      print -P "For example: frontend npmjs mocha (or just: npmjs mocha)."
2080+      print -P ""
2081+      return 1
2082   fi
2083 
2084-  # check whether the search engine is supported
2085-  if [[ ! $1 =~ '(jquery|mdn|compass|html5please|caniuse|aurajs|dartlang|qunit|fontello|bootsnipp|cssflow|codepen|unheap|bem|smacss|angularjs|reactjs|emberjs|stackoverflow)' ]];
2086+  # check whether the search context is supported
2087+  if [[ -z "$urls[$1]" ]]
2088   then
2089-    echo "Search valid search content $1 not supported."
2090-    echo "Valid contents: (formats 'frontend <search-content>' or '<search-content>')"
2091-    echo "* jquery"
2092-    echo "* mdn"
2093-    echo "* compass"
2094-    echo "* html5please"
2095-    echo "* caniuse"
2096-    echo "* aurajs"
2097-    echo "* dartlang"
2098-    echo "* lodash"
2099-    echo "* qunit"
2100-    echo "* fontello"
2101diff --git a/plugins/git-extras/git-extras.plugin.zsh b/plugins/git-extras/git-extras.plugin.zsh
2102index 8419166abc10b7f05a30fe02d39aa34d3c33cddb..d91c1af81c6391c17249449e8cd5bc554201a73a 100644
2103--- a/plugins/git-extras/git-extras.plugin.zsh
2104+++ b/plugins/git-extras/git-extras.plugin.zsh
2105@@ -3,19 +3,20 @@
2106 # Description
2107 # -----------
2108 #
2109-#  Completion script for git-extras (http://github.com/visionmedia/git-extras).
2110+#  Completion script for git-extras (http://github.com/tj/git-extras).
2111 #
2112 # ------------------------------------------------------------------------------
2113 # Authors
2114 # -------
2115 #
2116 #  * Alexis GRIMALDI (https://github.com/agrimaldi)
2117+#  * spacewander (https://github.com/spacewander)
2118 #
2119 # ------------------------------------------------------------------------------
2120 # Inspirations
2121 # -----------
2122 #
2123-#  * git-extras (http://github.com/visionmedia/git-extras)
2124+#  * git-extras (http://github.com/tj/git-extras)
2125 #  * git-flow-completion (http://github.com/bobthecow/git-flow-completion)
2126 #
2127 # ------------------------------------------------------------------------------
2128@@ -30,10 +31,21 @@ __git_command_successful () {
2129 }
2130 
2131 
2132+__git_commits() {
2133+    declare -A commits
2134+    git log --oneline -15 | sed 's/\([[:alnum:]]\{7\}\) /\1:/' | while read commit
2135+    do
2136+        hash=$(echo $commit | cut -d':' -f1)
2137+        commits[$hash]="$commit"
2138+    done
2139+    local ret=1
2140+    _describe -t commits commit commits && ret=0
2141+}
2142+
2143 __git_tag_names() {
2144     local expl
2145     declare -a tag_names
2146-    tag_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/tags 2>/dev/null)"}#refs/tags/})
2147+    tag_names=(${${(f)"$(_call_program tags git for-each-ref --format='"%(refname)"' refs/tags 2>/dev/null)"}#refs/tags/})
2148     __git_command_successful || return
2149     _wanted tag-names expl tag-name compadd $* - $tag_names
2150 }
2151@@ -47,31 +59,27 @@ __git_branch_names() {
2152     _wanted branch-names expl branch-name compadd $* - $branch_names
2153 }
2154 
2155-
2156-__git_feature_branch_names() {
2157+__git_specific_branch_names() {
2158     local expl
2159     declare -a branch_names
2160-    branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads/feature 2>/dev/null)"}#refs/heads/feature/})
2161+    branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads/"$1" 2>/dev/null)"}#refs/heads/$1/})
2162     __git_command_successful || return
2163     _wanted branch-names expl branch-name compadd $* - $branch_names
2164 }
2165 
2166 
2167+__git_feature_branch_names() {
2168+    __git_specific_branch_names 'feature'
2169+}
2170+
2171+
2172 __git_refactor_branch_names() {
2173-    local expl
2174-    declare -a branch_names
2175-    branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads/refactor 2>/dev/null)"}#refs/heads/refactor/})
2176-    __git_command_successful || return
2177-    _wanted branch-names expl branch-name compadd $* - $branch_names
2178+    __git_specific_branch_names 'refactor'
2179 }
2180 
2181 
2182 __git_bug_branch_names() {
2183-    local expl
2184-    declare -a branch_names
2185-    branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads/bug 2>/dev/null)"}#refs/heads/bug/})
2186-    __git_command_successful || return
2187-    _wanted branch-names expl branch-name compadd $* - $branch_names
2188+    __git_specific_branch_names 'bug'
2189 }
2190 
2191 
2192@@ -92,19 +100,43 @@ __git_author_names() {
2193     _wanted author-names expl author-name compadd $* - $author_names
2194 }
2195 
2196+# subcommands
2197 
2198-_git-changelog() {
2199-    _arguments \
2200-        '(-l --list)'{-l,--list}'[list commits]' \
2201+_git-bug() {
2202+    local curcontext=$curcontext state line ret=1
2203+    declare -A opt_args
2204+
2205diff --git a/plugins/git-flow/git-flow.plugin.zsh b/plugins/git-flow/git-flow.plugin.zsh
2206index 4357c08957e6f7373df0dbcd465db2d59719f6f9..444440bcb8afeff1a3f699e694d834210d793087 100644
2207--- a/plugins/git-flow/git-flow.plugin.zsh
2208+++ b/plugins/git-flow/git-flow.plugin.zsh
2209@@ -21,7 +21,7 @@
2210 #
2211 
2212 #Alias
2213-alias gf='git flow'
2214+alias gfl='git flow'
2215 alias gcd='git checkout develop'
2216 alias gch='git checkout hotfix'
2217 alias gcr='git checkout release'
2218diff --git a/plugins/git-prompt/git-prompt.plugin.zsh b/plugins/git-prompt/git-prompt.plugin.zsh
2219index d868a5fe1d1bf6b6117db674b093d1a632f5d0d7..5175bf70f91d0fafddebfd72a74eea5435131213 100644
2220--- a/plugins/git-prompt/git-prompt.plugin.zsh
2221+++ b/plugins/git-prompt/git-prompt.plugin.zsh
2222@@ -1,57 +1,92 @@
2223 # ZSH Git Prompt Plugin from:
2224 # http://github.com/olivierverdier/zsh-git-prompt
2225-#
2226-export __GIT_PROMPT_DIR=$ZSH/plugins/git-prompt
2227 
2228-# Allow for functions in the prompt.
2229-setopt PROMPT_SUBST
2230+__GIT_PROMPT_DIR="${0:A:h}"
2231 
2232-## Enable auto-execution of functions.
2233-typeset -ga preexec_functions
2234-typeset -ga precmd_functions
2235-typeset -ga chpwd_functions
2236-
2237-# Append git functions needed for prompt.
2238-preexec_functions+='preexec_update_git_vars'
2239-precmd_functions+='precmd_update_git_vars'
2240-chpwd_functions+='chpwd_update_git_vars'
2241+## Hook function definitions
2242+function chpwd_update_git_vars() {
2243+    update_current_git_vars
2244+}
2245 
2246-## Function definitions
2247 function preexec_update_git_vars() {
2248     case "$2" in
2249-        git*)
2250+        git*|hub*|gh*|stg*)
2251         __EXECUTED_GIT_COMMAND=1
2252         ;;
2253     esac
2254 }
2255 
2256 function precmd_update_git_vars() {
2257-    if [ -n "$__EXECUTED_GIT_COMMAND" ]; then
2258+    if [ -n "$__EXECUTED_GIT_COMMAND" ] || [ ! -n "$ZSH_THEME_GIT_PROMPT_CACHE" ]; then
2259         update_current_git_vars
2260         unset __EXECUTED_GIT_COMMAND
2261     fi
2262 }
2263 
2264-function chpwd_update_git_vars() {
2265-    update_current_git_vars
2266-}
2267+chpwd_functions+=(chpwd_update_git_vars)
2268+precmd_functions+=(precmd_update_git_vars)
2269+preexec_functions+=(preexec_update_git_vars)
2270+
2271 
2272+## Function definitions
2273 function update_current_git_vars() {
2274     unset __CURRENT_GIT_STATUS
2275 
2276     local gitstatus="$__GIT_PROMPT_DIR/gitstatus.py"
2277-    _GIT_STATUS=`python ${gitstatus}`
2278-    __CURRENT_GIT_STATUS=("${(f)_GIT_STATUS}")
2279+    _GIT_STATUS=$(python ${gitstatus} 2>/dev/null)
2280+     __CURRENT_GIT_STATUS=("${(@s: :)_GIT_STATUS}")
2281+    GIT_BRANCH=$__CURRENT_GIT_STATUS[1]
2282+    GIT_AHEAD=$__CURRENT_GIT_STATUS[2]
2283+    GIT_BEHIND=$__CURRENT_GIT_STATUS[3]
2284+    GIT_STAGED=$__CURRENT_GIT_STATUS[4]
2285+    GIT_CONFLICTS=$__CURRENT_GIT_STATUS[5]
2286+    GIT_CHANGED=$__CURRENT_GIT_STATUS[6]
2287+    GIT_UNTRACKED=$__CURRENT_GIT_STATUS[7]
2288 }
2289 
2290-function prompt_git_info() {
2291+git_super_status() {
2292+    precmd_update_git_vars
2293     if [ -n "$__CURRENT_GIT_STATUS" ]; then
2294-        echo "(%{${fg[red]}%}$__CURRENT_GIT_STATUS[1]%{${fg[default]}%}$__CURRENT_GIT_STATUS[2]%{${fg[magenta]}%}$__CURRENT_GIT_STATUS[3]%{${fg[default]}%})"
2295+      STATUS="$ZSH_THEME_GIT_PROMPT_PREFIX$ZSH_THEME_GIT_PROMPT_BRANCH$GIT_BRANCH%{${reset_color}%}"
2296+      if [ "$GIT_BEHIND" -ne "0" ]; then
2297+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_BEHIND$GIT_BEHIND%{${reset_color}%}"
2298+      fi
2299+      if [ "$GIT_AHEAD" -ne "0" ]; then
2300+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_AHEAD$GIT_AHEAD%{${reset_color}%}"
2301+      fi
2302+      STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_SEPARATOR"
2303+      if [ "$GIT_STAGED" -ne "0" ]; then
2304+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STAGED$GIT_STAGED%{${reset_color}%}"
2305+      fi
2306+      if [ "$GIT_CONFLICTS" -ne "0" ]; then
2307+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CONFLICTS$GIT_CONFLICTS%{${reset_color}%}"
2308+      fi
2309+      if [ "$GIT_CHANGED" -ne "0" ]; then
2310+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CHANGED$GIT_CHANGED%{${reset_color}%}"
2311+      fi
2312+      if [ "$GIT_UNTRACKED" -ne "0" ]; then
2313+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED%{${reset_color}%}"
2314+      fi
2315+      if [ "$GIT_CHANGED" -eq "0" ] && [ "$GIT_CONFLICTS" -eq "0" ] && [ "$GIT_STAGED" -eq "0" ] && [ "$GIT_UNTRACKED" -eq "0" ]; then
2316+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN"
2317+      fi
2318+      STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX"
2319+      echo "$STATUS"
2320     fi
2321 }
2322diff --git a/plugins/git-prompt/gitstatus.py b/plugins/git-prompt/gitstatus.py
2323index 2568414320a79140ab387ad4fe788d8cd78367fd..a8eb8284b7ad8ed601890d84f0ffbfe92f6c00a1 100644
2324--- a/plugins/git-prompt/gitstatus.py
2325+++ b/plugins/git-prompt/gitstatus.py
2326@@ -1,82 +1,84 @@
2327 #!/usr/bin/env python
2328-# -*- coding: UTF-8 -*-
2329-from subprocess import Popen, PIPE
2330-import re
2331+from __future__ import print_function
2332 
2333-# change those symbols to whatever you prefer
2334-symbols = {
2335-    'ahead of': '↑',
2336-    'behind': '↓',
2337-    'staged': '♦',
2338-    'changed': '‣',
2339-    'untracked': '…',
2340-    'clean': '⚡',
2341-    'unmerged': '≠',
2342-    'sha1': ':'
2343-}
2344+import sys
2345+import re
2346+import shlex
2347+from subprocess import Popen, PIPE, check_output
2348 
2349-output, error = Popen(
2350-    ['git', 'status'], stdout=PIPE, stderr=PIPE, universal_newlines=True).communicate()
2351 
2352-if error:
2353-    import sys
2354-    sys.exit(0)
2355-lines = output.splitlines()
2356+def get_tagname_or_hash():
2357+    """return tagname if exists else hash"""
2358+    cmd = 'git log -1 --format="%h%d"'
2359+    output = check_output(shlex.split(cmd)).decode('utf-8').strip()
2360+    hash_, tagname = None, None
2361+    # get hash
2362+    m = re.search('\(.*\)$', output)
2363+    if m:
2364+        hash_ = output[:m.start()-1]
2365+    # get tagname
2366+    m = re.search('tag: .*[,\)]', output)
2367+    if m:
2368+        tagname = 'tags/' + output[m.start()+len('tag: '): m.end()-1]
2369 
2370-behead_re = re.compile(
2371-    r"^# Your branch is (ahead of|behind) '(.*)' by (\d+) commit")
2372-diverge_re = re.compile(r"^# and have (\d+) and (\d+) different")
2373+    if tagname:
2374+        return tagname
2375+    elif hash_:
2376+        return hash_
2377+    return None
2378 
2379-status = ''
2380-staged = re.compile(r'^# Changes to be committed:$', re.MULTILINE)
2381-changed = re.compile(r'^# Changed but not updated:$', re.MULTILINE)
2382-untracked = re.compile(r'^# Untracked files:$', re.MULTILINE)
2383-unmerged = re.compile(r'^# Unmerged paths:$', re.MULTILINE)
2384 
2385+# `git status --porcelain --branch` can collect all information
2386+# branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind
2387+po = Popen(['git', 'status', '--porcelain', '--branch'], stdout=PIPE, stderr=PIPE)
2388+stdout, sterr = po.communicate()
2389+if po.returncode != 0:
2390+    sys.exit(0)  # Not a git repository
2391 
2392-def execute(*command):
2393-    out, err = Popen(stdout=PIPE, stderr=PIPE, *command).communicate()
2394-    if not err:
2395-        nb = len(out.splitlines())
2396+# collect git status information
2397+untracked, staged, changed, conflicts = [], [], [], []
2398+ahead, behind = 0, 0
2399+status = [(line[0], line[1], line[2:]) for line in stdout.decode('utf-8').splitlines()]
2400+for st in status:
2401+    if st[0] == '#' and st[1] == '#':
2402+        if re.search('Initial commit on', st[2]):
2403+            branch = st[2].split(' ')[-1]
2404+        elif re.search('no branch', st[2]):  # detached status
2405+            branch = get_tagname_or_hash()
2406+        elif len(st[2].strip().split('...')) == 1:
2407+            branch = st[2].strip()
2408+        else:
2409+            # current and remote branch info
2410+            branch, rest = st[2].strip().split('...')
2411+            if len(rest.split(' ')) == 1:
2412+                # remote_branch = rest.split(' ')[0]
2413+                pass
2414+            else:
2415+                # ahead or behind
2416+                divergence = ' '.join(rest.split(' ')[1:])
2417+                divergence = divergence.lstrip('[').rstrip(']')
2418+                for div in divergence.split(', '):
2419+                    if 'ahead' in div:
2420+                        ahead = int(div[len('ahead '):].strip())
2421+                    elif 'behind' in div:
2422+                        behind = int(div[len('behind '):].strip())
2423+    elif st[0] == '?' and st[1] == '?':
2424+        untracked.append(st)
2425     else: