82c76f6b5c2718622a532fb759231e8d24171413

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

Message

Merge changes from #4241 into installer-portable-colors

Conflicts:
	tools/install.sh
	tools/upgrade.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/functions.zsh b/lib/functions.zsh
  10index 17f5f9cbf246ff0e6c58abfff6dff3ea227c99d8..0d632a2686693f5d624ebd17694d9c4e18bc3d3e 100644
  11--- a/lib/functions.zsh
  12+++ b/lib/functions.zsh
  13@@ -15,6 +15,22 @@ function take() {
  14   cd $1
  15 }
  16 
  17+function open_command() {
  18+  local open_cmd
  19+
  20+  # define the open command
  21+  case "$OSTYPE" in
  22+    darwin*)  open_cmd="open" ;;
  23+    cygwin*)  open_cmd="cygstart" ;;
  24+    linux*)   open_cmd="xdg-open" ;;
  25+    *)        echo "Platform $OSTYPE not supported"
  26+              return 1
  27+              ;;
  28+  esac
  29+
  30+  nohup $open_cmd "$@" &>/dev/null
  31+}
  32+
  33 #
  34 # Get the value of an alias.
  35 #
  36diff --git a/lib/termsupport.zsh b/lib/termsupport.zsh
  37index e1c2e2f93a3b376a02180d21cdddf01f0bcdcb29..babbaa95789afb3233e8b4eb74216ceed44ce716 100644
  38--- a/lib/termsupport.zsh
  39+++ b/lib/termsupport.zsh
  40@@ -7,6 +7,9 @@
  41 # (In screen, only short_tab_title is used)
  42 # Limited support for Apple Terminal (Terminal can't set window and tab separately)
  43 function title {
  44+  emulate -L zsh
  45+  setopt prompt_subst
  46+  
  47   [[ "$EMACS" == *term* ]] && return
  48 
  49   # if $2 is unset use $1 as default
  50@@ -23,6 +26,10 @@ function title {
  51 
  52 ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" #15 char left truncated PWD
  53 ZSH_THEME_TERM_TITLE_IDLE="%n@%m: %~"
  54+# Avoid duplication of directory in terminals with independent dir display
  55+if [[ $TERM_PROGRAM == Apple_Terminal ]]; then
  56+  ZSH_THEME_TERM_TITLE_IDLE="%n@%m"
  57+fi
  58 
  59 # Runs before showing the prompt
  60 function omz_termsupport_precmd {
  61@@ -43,7 +50,7 @@ function omz_termsupport_preexec {
  62   setopt extended_glob
  63 
  64   # cmd name only, or if this is sudo or ssh, the next cmd
  65-  local CMD=${1[(wr)^(*=*|sudo|ssh|rake|-*)]:gs/%/%%}
  66+  local CMD=${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%}
  67   local LINE="${2:gs/%/%%}"
  68 
  69   title '$CMD' '%100>...>$LINE%<<'
  70diff --git a/oh-my-zsh.sh b/oh-my-zsh.sh
  71index ec64c240f0203b64b1d32fe6da2ae657e93329f1..4e5f77990dd567ca1495ed2af948473609ed1bfe 100644
  72--- a/oh-my-zsh.sh
  73+++ b/oh-my-zsh.sh
  74@@ -29,11 +29,6 @@ for config_file ($ZSH/lib/*.zsh); do
  75   source $config_file
  76 done
  77 
  78-# Load all of your custom configurations from custom/
  79-for config_file ($ZSH_CUSTOM/*.zsh(N)); do
  80-  source $config_file
  81-done
  82-unset config_file
  83 
  84 is_plugin() {
  85   local base_dir=$1
  86@@ -77,6 +72,12 @@ for plugin ($plugins); do
  87   fi
  88 done
  89 
  90+# Load all of your custom configurations from custom/
  91+for config_file ($ZSH_CUSTOM/*.zsh(N)); do
  92+  source $config_file
  93+done
  94+unset config_file
  95+
  96 # Load the theme
  97 if [ "$ZSH_THEME" = "random" ]; then
  98   themes=($ZSH/themes/*zsh-theme)
  99diff --git a/plugins/autojump/autojump.plugin.zsh b/plugins/autojump/autojump.plugin.zsh
 100index 4cf0364013b2655dac01bf250d063ff2d7b2d1b5..c05c699e106b56ec04278d4cd84d7a4176fd9c35 100644
 101--- a/plugins/autojump/autojump.plugin.zsh
 102+++ b/plugins/autojump/autojump.plugin.zsh
 103@@ -15,7 +15,7 @@ if [ $commands[autojump] ]; then # check if autojump is installed
 104     . /usr/local/share/autojump/autojump.zsh
 105   elif [ -f /opt/local/etc/profile.d/autojump.zsh ]; then # mac os x with ports
 106     . /opt/local/etc/profile.d/autojump.zsh
 107-  elif [ $commands[brew] -a -f `brew --prefix`/etc/autojump.zsh ]; then # mac os x with brew
 108-    . `brew --prefix`/etc/autojump.zsh
 109+  elif [ $commands[brew] -a -f `brew --prefix`/etc/autojump.sh ]; then # mac os x with brew
 110+    . `brew --prefix`/etc/autojump.sh
 111   fi
 112 fi
 113diff --git a/plugins/dirhistory/dirhistory.plugin.zsh b/plugins/dirhistory/dirhistory.plugin.zsh
 114index d101cfcae6a435ac0d78398f23cb1aac809a0efc..0209981e31f463a30cc6d65f0b58c5d19c280c34 100644
 115--- a/plugins/dirhistory/dirhistory.plugin.zsh
 116+++ b/plugins/dirhistory/dirhistory.plugin.zsh
 117@@ -49,7 +49,8 @@ function push_future() {
 118 }
 119 
 120 # Called by zsh when directory changes
 121-function chpwd() {
 122+chpwd_functions+=(chpwd_dirhistory)
 123+function chpwd_dirhistory() {
 124   push_past $PWD
 125   # If DIRHISTORY_CD is not set...
 126   if [[ -z "${DIRHISTORY_CD+x}" ]]; then
 127diff --git a/plugins/dirpersist/dirpersist.plugin.zsh b/plugins/dirpersist/dirpersist.plugin.zsh
 128index 88d1129d4ac9a21a0a08f1a61f6531b84f320c34..616e2c3c658710d47073cfdd88aa43aea3782675 100644
 129--- a/plugins/dirpersist/dirpersist.plugin.zsh
 130+++ b/plugins/dirpersist/dirpersist.plugin.zsh
 131@@ -11,7 +11,8 @@ if [[ -f ${dirstack_file} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then
 132   [[ -d $dirstack[1] ]] && cd $dirstack[1] && cd $OLDPWD
 133 fi
 134 
 135-chpwd() {
 136+chpwd_functions+=(chpwd_dirpersist)
 137+chpwd_dirpersist() {
 138   if (( $DIRSTACKSIZE <= 0 )) || [[ -z $dirstack_file ]]; then return; fi
 139   local -ax my_stack
 140   my_stack=( ${PWD} ${dirstack} )
 141diff --git a/plugins/docker-compose/README.md b/plugins/docker-compose/README.md
 142index 77b98f30df1ff85b1bebf4ed213548408f26fddb..567b821487af846fa41948fea666f7de6280954f 100644
 143--- a/plugins/docker-compose/README.md
 144+++ b/plugins/docker-compose/README.md
 145@@ -1 +1,5 @@
 146 # Docker-compose plugin for oh my zsh
 147+
 148+A copy of the completion script from the [docker-compose](1) git repo.
 149+
 150+[1]:[https://github.com/docker/compose/blob/master/contrib/completion/zsh/_docker-compose]
 151diff --git a/plugins/docker-compose/_docker-compose b/plugins/docker-compose/_docker-compose
 152new file mode 100644
 153index 0000000000000000000000000000000000000000..19c06675ad5057dd09b3398e476744ac8fdd8b10
 154--- /dev/null
 155+++ b/plugins/docker-compose/_docker-compose
 156@@ -0,0 +1,308 @@
 157+#compdef docker-compose
 158+
 159+# Description
 160+# -----------
 161+#  zsh completion for docker-compose
 162+#  https://github.com/sdurrheimer/docker-compose-zsh-completion
 163+# -------------------------------------------------------------------------
 164+# Version
 165+# -------
 166+#  0.1.0
 167+# -------------------------------------------------------------------------
 168+# Authors
 169+# -------
 170+#  * Steve Durrheimer <s.durrheimer@gmail.com>
 171+# -------------------------------------------------------------------------
 172+# Inspiration
 173+# -----------
 174+#  * @albers docker-compose bash completion script
 175+#  * @felixr docker zsh completion script : https://github.com/felixr/docker-zsh-completion
 176+# -------------------------------------------------------------------------
 177+
 178+# For compatibility reasons, Compose and therefore its completion supports several
 179+# stack compositon files as listed here, in descending priority.
 180+# Support for these filenames might be dropped in some future version.
 181+__docker-compose_compose_file() {
 182+    local file
 183+    for file in docker-compose.y{,a}ml fig.y{,a}ml ; do
 184+        [ -e $file ] && {
 185+            echo $file
 186+            return
 187+        }
 188+    done
 189+    echo docker-compose.yml
 190+}
 191+
 192+# Extracts all service names from docker-compose.yml.
 193+___docker-compose_all_services_in_compose_file() {
 194+    local already_selected
 195+    local -a services
 196+    already_selected=$(echo ${words[@]} | tr " " "|")
 197+    awk -F: '/^[a-zA-Z0-9]/{print $1}' "${compose_file:-$(__docker-compose_compose_file)}" 2>/dev/null | grep -Ev "$already_selected"
 198+}
 199+
 200+# All services, even those without an existing container
 201+__docker-compose_services_all() {
 202+    services=$(___docker-compose_all_services_in_compose_file)
 203+    _alternative "args:services:($services)"
 204+}
 205+
 206+# All services that have an entry with the given key in their docker-compose.yml section
 207+___docker-compose_services_with_key() {
 208+    local already_selected
 209+    local -a buildable
 210+    already_selected=$(echo ${words[@]} | tr " " "|")
 211+    # flatten sections to one line, then filter lines containing the key and return section name.
 212+    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"
 213+}
 214+
 215+# All services that are defined by a Dockerfile reference
 216+__docker-compose_services_from_build() {
 217+    buildable=$(___docker-compose_services_with_key build)
 218+    _alternative "args:buildable services:($buildable)"
 219+}
 220+
 221+# All services that are defined by an image
 222+__docker-compose_services_from_image() {
 223+    pullable=$(___docker-compose_services_with_key image)
 224+    _alternative "args:pullable services:($pullable)"
 225+}
 226+
 227+__docker-compose_get_services() {
 228+    local kind expl
 229+    declare -a running stopped lines args services
 230+
 231+    docker_status=$(docker ps > /dev/null 2>&1)
 232+    if [ $? -ne 0 ]; then
 233+        _message "Error! Docker is not running."
 234+        return 1
 235+    fi
 236+
 237+    kind=$1
 238+    shift
 239+    [[ $kind = (stopped|all) ]] && args=($args -a)
 240+
 241+    lines=(${(f)"$(_call_program commands docker ps ${args})"})
 242+    services=(${(f)"$(_call_program commands docker-compose 2>/dev/null ${compose_file:+-f $compose_file} ${compose_project:+-p $compose_project} ps -q)"})
 243+
 244+    # Parse header line to find columns
 245+    local i=1 j=1 k header=${lines[1]}
 246+    declare -A begin end
 247+    while (( $j < ${#header} - 1 )) {
 248+        i=$(( $j + ${${header[$j,-1]}[(i)[^ ]]} - 1))
 249+        j=$(( $i + ${${header[$i,-1]}[(i)  ]} - 1))
 250+        k=$(( $j + ${${header[$j,-1]}[(i)[^ ]]} - 2))
 251+        begin[${header[$i,$(($j-1))]}]=$i
 252+        end[${header[$i,$(($j-1))]}]=$k
 253+    }
 254+    lines=(${lines[2,-1]})
 255+
 256diff --git a/plugins/docker-compose/docker-compose.plugin.zsh b/plugins/docker-compose/docker-compose.plugin.zsh
 257deleted file mode 100644
 258index 08500408d7a309a116bd8064c829f8fbaea59722..0000000000000000000000000000000000000000
 259--- a/plugins/docker-compose/docker-compose.plugin.zsh
 260+++ /dev/null
 261@@ -1,14 +0,0 @@
 262-# Authors:
 263-# https://github.com/tristola
 264-#
 265-# Docker-compose related zsh aliases
 266-
 267-# Aliases ###################################################################
 268-
 269-alias dcup='docker-compose up'
 270-alias dcb='docker-compose build'
 271-alias dcrm='docker-compose rm'
 272-alias dcps='docker-compose ps'
 273-alias dcstop='docker-compose stop'
 274-alias dcrestart='docker-compose restart'
 275-
 276diff --git a/plugins/docker/_docker b/plugins/docker/_docker
 277index 25f55beca384ecdd3d4b9c970a322676e9e4599c..a82a31ad3441f78d1b79aca8220728b01fe86ff1 100644
 278--- a/plugins/docker/_docker
 279+++ b/plugins/docker/_docker
 280@@ -27,7 +27,7 @@ __docker_all_containers() {
 281 # output a selectable list of all docker images
 282 __docker_images() {
 283     declare -a img_cmd
 284-    img_cmd=($(docker images | awk 'NR>1{print $1}'))
 285+    img_cmd=($(docker images | awk 'NR>1{print $1}'| sed 's/:/\\:/g'))
 286     _describe 'images' img_cmd
 287 }
 288 
 289diff --git a/plugins/ember-cli/README.md b/plugins/ember-cli/README.md
 290index d1dedf8843786d5800d1c53f1efd5f193e47cdbb..482c347d27aa3c6af0dea4c058900362f1cdb0ef 100644
 291--- a/plugins/ember-cli/README.md
 292+++ b/plugins/ember-cli/README.md
 293@@ -1,22 +1,19 @@
 294-# Ember-cli
 295+# Ember CLI
 296 
 297-**Maintainer:** [BilalBudhani](http://www.github.com/BilalBudhani)
 298+**Maintainers:** [BilalBudhani](http://www.github.com/BilalBudhani), [eubenesa](http://www.github.com/eubenesa)
 299 
 300-Ember-cli (http://www.ember-cli.com/)
 301+Ember CLI (http://www.ember-cli.com/)
 302 
 303 ### List of Aliases
 304 
 305-alias es='ember serve'
 306-alias ea='ember addon'
 307-alias eb='ember build'
 308-alias ed='ember destroy'
 309-alias eg='ember generate'
 310-alias eh='ember help'
 311-alias ein='ember init'
 312-alias eia='ember install:addon'
 313-alias eib='ember install:bower'
 314-alias ein='ember install:npm'
 315-alias ei='ember install'
 316-alias et='ember test'
 317-alias eu='ember update'
 318-alias ev='ember version'
 319+    alias es='ember serve'
 320+    alias ea='ember addon'
 321+    alias eb='ember build'
 322+    alias ed='ember destroy'
 323+    alias eg='ember generate'
 324+    alias eh='ember help'
 325+    alias ein='ember init'
 326+    alias ei='ember install'
 327+    alias et='ember test'
 328+    alias eu='ember update'
 329+    alias ev='ember version'
 330diff --git a/plugins/ember-cli/ember-cli.plugin.zsh b/plugins/ember-cli/ember-cli.plugin.zsh
 331index 044a2c0438896a51e05d8dc4015e72db555442f0..a0f3468299e8587435bef1d63ff13ba02d33423e 100644
 332--- a/plugins/ember-cli/ember-cli.plugin.zsh
 333+++ b/plugins/ember-cli/ember-cli.plugin.zsh
 334@@ -1,5 +1,5 @@
 335-# Ember ClI 
 336-# visit http://www.ember-cli.com/ to view user guid 
 337+# Ember CLI
 338+# Visit http://www.ember-cli.com/ to view user guide
 339 
 340 alias es='ember serve'
 341 alias ea='ember addon'
 342@@ -8,9 +8,6 @@ alias ed='ember destroy'
 343 alias eg='ember generate'
 344 alias eh='ember help'
 345 alias ein='ember init'
 346-alias eia='ember install:addon'
 347-alias eib='ember install:bower'
 348-alias ein='ember install:npm'
 349 alias ei='ember install'
 350 alias et='ember test'
 351 alias eu='ember update'
 352diff --git a/plugins/emoji/README.md b/plugins/emoji/README.md
 353new file mode 100644
 354index 0000000000000000000000000000000000000000..889e567e6ce8e3689fa57a517fd74ab8bc8732e6
 355--- /dev/null
 356+++ b/plugins/emoji/README.md
 357@@ -0,0 +1,135 @@
 358+# emoji plugin
 359+
 360+Support for conveniently working with Unicode emoji in Zsh.
 361+
 362+## Features
 363+
 364diff --git a/plugins/emoji/emoji-char-definitions.zsh b/plugins/emoji/emoji-char-definitions.zsh
 365new file mode 100644
 366index 0000000000000000000000000000000000000000..04693da0593b98620161e2d52aaeba3115d953c9
 367--- /dev/null
 368+++ b/plugins/emoji/emoji-char-definitions.zsh
 369@@ -0,0 +1,1303 @@
 370+
 371+# emoji-char-definitions.zsh - Emoji character definitions for oh-my-zsh emoji plugin
 372+#
 373+# This file is auto-generated by update_emoji.pl. Do not edit it manually.
 374+#
 375+# This contains the definition for:
 376+#   $emoji         - which maps character names to Unicode characters
 377+#   $emoji_flags   - maps country names to Unicode flag characters using region indicators 
 378+
 379+# Main emoji
 380+typeset -gAH emoji
 381+# National flags
 382+typeset -gAH emoji_flags
 383+# Combining modifiers
 384+typeset -gAH emoji_mod
 385+
 386+emoji[copyright_sign]=$'\U00A9'
 387+emoji[registered_sign]=$'\U00AE'
 388+emoji[double_exclamation_mark]=$'\U203C'
 389+emoji[exclamation_question_mark]=$'\U2049'
 390+emoji[trade_mark_sign]=$'\U2122'
 391+emoji[information_source]=$'\U2139'
 392+emoji[left_right_arrow]=$'\U2194'
 393+emoji[up_down_arrow]=$'\U2195'
 394+emoji[north_west_arrow]=$'\U2196'
 395+emoji[north_east_arrow]=$'\U2197'
 396+emoji[south_east_arrow]=$'\U2198'
 397+emoji[south_west_arrow]=$'\U2199'
 398+emoji[leftwards_arrow_with_hook]=$'\U21A9'
 399+emoji[rightwards_arrow_with_hook]=$'\U21AA'
 400+emoji[watch]=$'\U231A'
 401+emoji[hourglass]=$'\U231B'
 402+emoji[keyboard]=$'\U2328'
 403+emoji[eject_symbol]=$'\U23CF'
 404+emoji[black_right_pointing_double_triangle]=$'\U23E9'
 405+emoji[black_left_pointing_double_triangle]=$'\U23EA'
 406+emoji[black_up_pointing_double_triangle]=$'\U23EB'
 407+emoji[black_down_pointing_double_triangle]=$'\U23EC'
 408+emoji[black_right_pointing_double_triangle_with_vertical_bar]=$'\U23ED'
 409+emoji[black_left_pointing_double_triangle_with_vertical_bar]=$'\U23EE'
 410+emoji[black_right_pointing_triangle_with_double_vertical_bar]=$'\U23EF'
 411+emoji[alarm_clock]=$'\U23F0'
 412+emoji[stopwatch]=$'\U23F1'
 413+emoji[timer_clock]=$'\U23F2'
 414+emoji[hourglass_with_flowing_sand]=$'\U23F3'
 415+emoji[double_vertical_bar]=$'\U23F8'
 416+emoji[black_square_for_stop]=$'\U23F9'
 417+emoji[black_circle_for_record]=$'\U23FA'
 418+emoji[circled_latin_capital_letter_m]=$'\U24C2'
 419+emoji[black_small_square]=$'\U25AA'
 420+emoji[white_small_square]=$'\U25AB'
 421+emoji[black_right_pointing_triangle]=$'\U25B6'
 422+emoji[black_left_pointing_triangle]=$'\U25C0'
 423+emoji[white_medium_square]=$'\U25FB'
 424+emoji[black_medium_square]=$'\U25FC'
 425+emoji[white_medium_small_square]=$'\U25FD'
 426+emoji[black_medium_small_square]=$'\U25FE'
 427+emoji[black_sun_with_rays]=$'\U2600'
 428+emoji[cloud]=$'\U2601'
 429+emoji[umbrella]=$'\U2602'
 430+emoji[snowman]=$'\U2603'
 431+emoji[comet]=$'\U2604'
 432+emoji[black_telephone]=$'\U260E'
 433+emoji[ballot_box_with_check]=$'\U2611'
 434+emoji[umbrella_with_rain_drops]=$'\U2614'
 435+emoji[hot_beverage]=$'\U2615'
 436+emoji[shamrock]=$'\U2618'
 437+emoji[white_up_pointing_index]=$'\U261D'
 438+emoji[skull_and_crossbones]=$'\U2620'
 439+emoji[radioactive_sign]=$'\U2622'
 440+emoji[biohazard_sign]=$'\U2623'
 441+emoji[orthodox_cross]=$'\U2626'
 442+emoji[star_and_crescent]=$'\U262A'
 443+emoji[peace_symbol]=$'\U262E'
 444+emoji[yin_yang]=$'\U262F'
 445+emoji[wheel_of_dharma]=$'\U2638'
 446+emoji[white_frowning_face]=$'\U2639'
 447+emoji[white_smiling_face]=$'\U263A'
 448+emoji[aries]=$'\U2648'
 449+emoji[taurus]=$'\U2649'
 450+emoji[gemini]=$'\U264A'
 451+emoji[cancer]=$'\U264B'
 452+emoji[leo]=$'\U264C'
 453+emoji[virgo]=$'\U264D'
 454+emoji[libra]=$'\U264E'
 455+emoji[scorpius]=$'\U264F'
 456+emoji[sagittarius]=$'\U2650'
 457+emoji[capricorn]=$'\U2651'
 458+emoji[aquarius]=$'\U2652'
 459+emoji[pisces]=$'\U2653'
 460+emoji[black_spade_suit]=$'\U2660'
 461+emoji[black_club_suit]=$'\U2663'
 462+emoji[black_heart_suit]=$'\U2665'
 463+emoji[black_diamond_suit]=$'\U2666'
 464+emoji[hot_springs]=$'\U2668'
 465+emoji[black_universal_recycling_symbol]=$'\U267B'
 466+emoji[wheelchair_symbol]=$'\U267F'
 467+emoji[hammer_and_pick]=$'\U2692'
 468+emoji[anchor]=$'\U2693'
 469diff --git a/plugins/emoji/emoji-data.txt b/plugins/emoji/emoji-data.txt
 470new file mode 100644
 471index 0000000000000000000000000000000000000000..7b4c015f7afb8ccd82f9b027da43df8c7a8e1ba7
 472--- /dev/null
 473+++ b/plugins/emoji/emoji-data.txt
 474@@ -0,0 +1,1308 @@
 475+# DRAFT emoji-data.txt
 476+# For details about the format and other information, see /../../../reports/tr51/index.html#Data_Files.
 477+#
 478+# Format: Code ; Default_Emoji_Style ; Emoji_Level ; Emoji_Modifier_Status ; Emoji_Sources # Comment
 479+#
 480+#   Field 1 — Default_Emoji_Style:
 481+#             text:      default text presentation
 482+#             emoji:     default emoji presentation
 483+#   Field 2 — Emoji_Level:
 484+#             L1:        level 1 emoji
 485+#             L2:        level 2 emoji
 486+#             NA:        not applicable
 487+#   Field 3 — Emoji_Modifier_Status:
 488+#             modifier:  an emoji modifier
 489+#             primary:   a primary emoji modifier base
 490+#             secondary: a secondary emoji modifier base
 491+#             none:      not applicable
 492+#   Field 4 — Emoji_Sources:
 493+#             one or more values from {z, a, j, w, x}
 494+#             see the key in http://www.unicode.org/draft/reports/tr51/tr51.html#Major_Sources
 495+#             NA:        not applicable
 496+#   Comment — currently contains the version where the character was first encoded,
 497+#             followed by:
 498+#             - a character name in uppercase (for a single character),
 499+#             - a keycap name,
 500+#             - an associated flag, where is associated with value unicode region code
 501+#
 502+00A9 ;	text ;	L1 ;	none ;	j	# V1.1 (©) COPYRIGHT SIGN
 503+00AE ;	text ;	L1 ;	none ;	j	# V1.1 (®) REGISTERED SIGN
 504+203C ;	text ;	L1 ;	none ;	a j	# V1.1 (‼) DOUBLE EXCLAMATION MARK
 505+2049 ;	text ;	L1 ;	none ;	a j	# V3.0 (⁉) EXCLAMATION QUESTION MARK
 506+2122 ;	text ;	L1 ;	none ;	j	# V1.1 (™) TRADE MARK SIGN
 507+2139 ;	text ;	L1 ;	none ;	j	# V3.0 (ℹ) INFORMATION SOURCE
 508+2194 ;	text ;	L1 ;	none ;	z j	# V1.1 (↔) LEFT RIGHT ARROW
 509+2195 ;	text ;	L1 ;	none ;	z j	# V1.1 (↕) UP DOWN ARROW
 510+2196 ;	text ;	L1 ;	none ;	j	# V1.1 (↖) NORTH WEST ARROW
 511+2197 ;	text ;	L1 ;	none ;	j	# V1.1 (↗) NORTH EAST ARROW
 512+2198 ;	text ;	L1 ;	none ;	j	# V1.1 (↘) SOUTH EAST ARROW
 513+2199 ;	text ;	L1 ;	none ;	j	# V1.1 (↙) SOUTH WEST ARROW
 514+21A9 ;	text ;	L1 ;	none ;	j	# V1.1 (↩) LEFTWARDS ARROW WITH HOOK
 515+21AA ;	text ;	L1 ;	none ;	j	# V1.1 (↪) RIGHTWARDS ARROW WITH HOOK
 516+231A ;	emoji ;	L1 ;	none ;	j	# V1.1 (⌚) WATCH
 517+231B ;	emoji ;	L1 ;	none ;	j	# V1.1 (⌛) HOURGLASS
 518+2328 ;	text ;	L2 ;	none ;	x	# V1.1 (⌨) KEYBOARD
 519+23CF ;	text ;	L2 ;	none ;	x	# V4.0 (⏏) EJECT SYMBOL
 520+23E9 ;	emoji ;	L1 ;	none ;	j w	# V6.0 (⏩) BLACK RIGHT-POINTING DOUBLE TRIANGLE
 521+23EA ;	emoji ;	L1 ;	none ;	j w	# V6.0 (⏪) BLACK LEFT-POINTING DOUBLE TRIANGLE
 522+23EB ;	emoji ;	L1 ;	none ;	j	# V6.0 (⏫) BLACK UP-POINTING DOUBLE TRIANGLE
 523+23EC ;	emoji ;	L1 ;	none ;	j	# V6.0 (⏬) BLACK DOWN-POINTING DOUBLE TRIANGLE
 524+23ED ;	text ;	L2 ;	none ;	w	# V6.0 (⏭) BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
 525+23EE ;	text ;	L2 ;	none ;	w	# V6.0 (⏮) BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR
 526+23EF ;	text ;	L2 ;	none ;	x	# V6.0 (⏯) BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
 527+23F0 ;	emoji ;	L1 ;	none ;	j	# V6.0 (⏰) ALARM CLOCK
 528+23F1 ;	text ;	L2 ;	none ;	x	# V6.0 (⏱) STOPWATCH
 529+23F2 ;	text ;	L2 ;	none ;	x	# V6.0 (⏲) TIMER CLOCK
 530+23F3 ;	emoji ;	L1 ;	none ;	j w	# V6.0 (⏳) HOURGLASS WITH FLOWING SAND
 531+23F8 ;	text ;	L2 ;	none ;	w	# V7.0 (⏸) DOUBLE VERTICAL BAR
 532+23F9 ;	text ;	L2 ;	none ;	w	# V7.0 (⏹) BLACK SQUARE FOR STOP
 533+23FA ;	text ;	L2 ;	none ;	w	# V7.0 (⏺) BLACK CIRCLE FOR RECORD
 534+24C2 ;	text ;	L1 ;	none ;	j	# V1.1 (Ⓜ) CIRCLED LATIN CAPITAL LETTER M
 535+25AA ;	text ;	L1 ;	none ;	j w	# V1.1 (▪) BLACK SMALL SQUARE
 536+25AB ;	text ;	L1 ;	none ;	j	# V1.1 (▫) WHITE SMALL SQUARE
 537+25B6 ;	text ;	L1 ;	none ;	a j w	# V1.1 (▶) BLACK RIGHT-POINTING TRIANGLE
 538+25C0 ;	text ;	L1 ;	none ;	a j w	# V1.1 (◀) BLACK LEFT-POINTING TRIANGLE
 539+25FB ;	text ;	L1 ;	none ;	j	# V3.2 (◻) WHITE MEDIUM SQUARE
 540+25FC ;	text ;	L1 ;	none ;	j w	# V3.2 (◼) BLACK MEDIUM SQUARE
 541+25FD ;	emoji ;	L1 ;	none ;	j	# V3.2 (◽) WHITE MEDIUM SMALL SQUARE
 542+25FE ;	emoji ;	L1 ;	none ;	j w	# V3.2 (◾) BLACK MEDIUM SMALL SQUARE
 543+2600 ;	text ;	L1 ;	none ;	a j	# V1.1 (☀) BLACK SUN WITH RAYS
 544+2601 ;	text ;	L1 ;	none ;	a j w	# V1.1 (☁) CLOUD
 545+2602 ;	text ;	L2 ;	none ;	a	# V1.1 (☂) UMBRELLA
 546+2603 ;	text ;	L2 ;	none ;	a	# V1.1 (☃) SNOWMAN
 547+2604 ;	text ;	L2 ;	none ;	x	# V1.1 (☄) COMET
 548+260E ;	text ;	L1 ;	none ;	z a j	# V1.1 (☎) BLACK TELEPHONE
 549+2611 ;	text ;	L1 ;	none ;	j w	# V1.1 (☑) BALLOT BOX WITH CHECK
 550+2614 ;	emoji ;	L1 ;	none ;	a j	# V4.0 (☔) UMBRELLA WITH RAIN DROPS
 551+2615 ;	emoji ;	L1 ;	none ;	j	# V4.0 (☕) HOT BEVERAGE
 552+2618 ;	text ;	L2 ;	none ;	x	# V4.1 (☘) SHAMROCK
 553+261D ;	text ;	L1 ;	secondary ;	j w	# V1.1 (☝) WHITE UP POINTING INDEX
 554+2620 ;	text ;	L2 ;	none ;	x	# V1.1 (☠) SKULL AND CROSSBONES
 555+2622 ;	text ;	L2 ;	none ;	x	# V1.1 (☢) RADIOACTIVE SIGN
 556+2623 ;	text ;	L2 ;	none ;	x	# V1.1 (☣) BIOHAZARD SIGN
 557+2626 ;	text ;	L2 ;	none ;	x	# V1.1 (☦) ORTHODOX CROSS
 558+262A ;	text ;	L2 ;	none ;	w	# V1.1 (☪) STAR AND CRESCENT
 559+262E ;	text ;	L2 ;	none ;	x	# V1.1 (☮) PEACE SYMBOL
 560+262F ;	text ;	L2 ;	none ;	w	# V1.1 (☯) YIN YANG
 561+2638 ;	text ;	L2 ;	none ;	w	# V1.1 (☸) WHEEL OF DHARMA
 562+2639 ;	text ;	L2 ;	secondary ;	w	# V1.1 (☹) WHITE FROWNING FACE
 563+263A ;	text ;	L1 ;	secondary ;	j w	# V1.1 (☺) WHITE SMILING FACE
 564+2648 ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♈) ARIES
 565+2649 ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♉) TAURUS
 566+264A ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♊) GEMINI
 567+264B ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♋) CANCER
 568+264C ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♌) LEO
 569+264D ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♍) VIRGO
 570+264E ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♎) LIBRA
 571+264F ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♏) SCORPIUS
 572+2650 ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♐) SAGITTARIUS
 573+2651 ;	emoji ;	L1 ;	none ;	j w	# V1.1 (♑) CAPRICORN
 574diff --git a/plugins/emoji/emoji.plugin.zsh b/plugins/emoji/emoji.plugin.zsh
 575new file mode 100644
 576index 0000000000000000000000000000000000000000..7876f1c89e5580d8b57bd1fd2d3ae756bba36c80
 577--- /dev/null
 578+++ b/plugins/emoji/emoji.plugin.zsh
 579@@ -0,0 +1,288 @@
 580+# emoji plugin
 581+#
 582+# Makes emoji support available within ZSH
 583+#
 584+# See the README for documentation.
 585+
 586+_omz_emoji_plugin_dir="${0:h}"
 587+
 588+() {
 589+
 590+local LC_ALL=en_US.UTF-8
 591+
 592+typeset -gAH emoji_groups
 593+typeset -gAH emoji_con
 594+typeset -gAH emoji2
 595+typeset -gAH emoji_skintone
 596+
 597+source "$_omz_emoji_plugin_dir/emoji-char-definitions.zsh"
 598+unset _omz_emoji_plugin_dir
 599+
 600+# These additional emoji are not in the definition file, but are useful in conjunction with it
 601+
 602+# This is a combinin character that can be placed after any other character to surround
 603+# it in a "keycap" symbol.
 604+# The digits 0-9 are already in the emoji table as keycap_digit_<N>, keycap_ten, etc. 
 605+# It's unclear whether this should be in the $emoji array, because those characters are all ones
 606+# which can be displayed on their own.
 607+#emoji[combining_enclosing_keycap]="\U20E3"
 608+
 609+emoji[regional_indicator_symbol_letter_d_regional_indicator_symbol_letter_e]=$'\xF0\x9F\x87\xA9\xF0\x9F\x87\xAA'
 610+emoji[regional_indicator_symbol_letter_g_regional_indicator_symbol_letter_b]=$'\xF0\x9F\x87\xAC\xF0\x9F\x87\xA7'
 611+emoji[regional_indicator_symbol_letter_c_regional_indicator_symbol_letter_n]=$'\xF0\x9F\x87\xA8\xF0\x9F\x87\xB3'
 612+emoji[regional_indicator_symbol_letter_j_regional_indicator_symbol_letter_p]=$'\xF0\x9F\x87\xAF\xF0\x9F\x87\xB5'
 613+emoji[regional_indicator_symbol_letter_k_regional_indicator_symbol_letter_r]=$'\xF0\x9F\x87\xB0\xF0\x9F\x87\xB7'
 614+emoji[regional_indicator_symbol_letter_f_regional_indicator_symbol_letter_r]=$'\xF0\x9F\x87\xAB\xF0\x9F\x87\xB7'
 615+emoji[regional_indicator_symbol_letter_e_regional_indicator_symbol_letter_s]=$'\xF0\x9F\x87\xAA\xF0\x9F\x87\xB8'
 616+emoji[regional_indicator_symbol_letter_i_regional_indicator_symbol_letter_t]=$'\xF0\x9F\x87\xAE\xF0\x9F\x87\xB9'
 617+emoji[regional_indicator_symbol_letter_u_regional_indicator_symbol_letter_s]=$'\xF0\x9F\x87\xBA\xF0\x9F\x87\xB8'
 618+emoji[regional_indicator_symbol_letter_r_regional_indicator_symbol_letter_u]=$'\xF0\x9F\x87\xB7\xF0\x9F\x87\xBA'
 619+
 620+# Nonstandard alias names
 621+emoji[vulcan_salute]=$'\U1F596'
 622+
 623+
 624+# Emoji combining and auxiliary characters
 625+
 626+# "Variation Selectors" for controlling text vs emoji style presentation
 627+# These apply to the immediately preceding character
 628+emoji2[text_style]=$'\UFE0E'
 629+emoji2[emoji_style]=$'\UFE0F'
 630+# Joiner that indicates a single combined-form glyph (ligature) should be used
 631+emoji2[zero_width_joiner]=$'\U200D'
 632+# Skin tone modifiers
 633+emoji2[emoji_modifier_fitzpatrick_type_1_2]=$'\U1F3FB'
 634+emoji2[emoji_modifier_fitzpatrick_type_3]=$'\U1F3FC'
 635+emoji2[emoji_modifier_fitzpatrick_type_4]=$'\U1F3FD'
 636+emoji2[emoji_modifier_fitzpatrick_type_5]=$'\U1F3FE'
 637+emoji2[emoji_modifier_fitzpatrick_type_6]=$'\U1F3FF'
 638+# Various other combining characters. (Incomplete list; I selected ones that sound useful)
 639+emoji2[combining_enclosing_circle]=$'\U20DD'
 640+emoji2[combining_enclosing_square]=$'\U20DE'
 641+emoji2[combining_enclosing_diamond]=$'\U20DF'
 642+emoji2[combining_enclosing_circle_backslash]=$'\U20E0'
 643+emoji2[combining_enclosing_screen]=$'\U20E2'
 644+emoji2[combining_enclosing_keycap]=$'\U20E3'
 645+emoji2[combining_enclosing_upward_pointing_triangle]=$'\U20E4'
 646+
 647+# Easier access to skin tone modifiers
 648+emoji_skintone[1_2]=$'\U1F3FB'
 649+emoji_skintone[3]=$'\U1F3FC'
 650+emoji_skintone[4]=$'\U1F3FD'
 651+emoji_skintone[5]=$'\U1F3FE'
 652+emoji_skintone[6]=$'\U1F3FF'
 653+
 654+# Emoji groups
 655+# These are stored in a single associative array, $emoji_groups, to avoid cluttering up the global
 656+# namespace, and to allow adding additional group definitions at run time.
 657+# The keys are the group names, and the values are whitespace-separated lists of emoji character names.
 658+
 659+emoji_groups[fruits]="
 660+  tomato
 661+  aubergine
 662+  grapes
 663+  melon
 664+  watermelon
 665+  tangerine
 666+  banana
 667+  pineapple
 668+  red_apple
 669+  green_apple
 670+  peach
 671+  cherries
 672+  strawberry
 673+  lemon
 674+  pear
 675+"
 676+
 677+emoji_groups[vehicles]="
 678+  airplane
 679diff --git a/plugins/emoji/update_emoji.pl b/plugins/emoji/update_emoji.pl
 680new file mode 100644
 681index 0000000000000000000000000000000000000000..04f3ce8e77f2e3f18ca6ded37e0a95b2b5520b04
 682--- /dev/null
 683+++ b/plugins/emoji/update_emoji.pl
 684@@ -0,0 +1,113 @@
 685+#!/usr/bin/perl -w
 686+#
 687+# update_emoji.pl
 688+#
 689+# This script generates the emoji.plugin.zsh emoji definitions from the Unicode
 690+# character data for the emoji characters.
 691+#
 692+# The data file can be found at http://unicode.org/Public/emoji/latest/emoji-data.txt
 693+# as referenced in Unicode TR51 (http://www.unicode.org/reports/tr51/index.html).
 694+#
 695+# This is known to work with the data file from version 1.0. It may not work with later
 696+# versions if the format changes. In particular, this reads line comments to get the
 697+# emoji character name and unicode version.
 698+#
 699+# Country names have punctuation and other non-letter characters removed from their name,
 700+# to avoid possible complications with having to escape the strings when using them as 
 701+# array subscripts. The definition file seems to use some combining characters like accents
 702+# that get stripped during this process.
 703+
 704+use strict;
 705+use warnings;
 706+use 5.010;
 707+use autodie;
 708+
 709+use Path::Class;
 710+use File::Copy;
 711+
 712+# Parse definitions out of the data file and convert
 713+sub process_emoji_data_file {
 714+	my ( $infile, $outfilename ) = @_;
 715+	my $file = file($infile);
 716+	my $outfile = file($outfilename);
 717+	my $outfilebase = $outfile->basename();
 718+	my $tempfilename = "$outfilename.tmp";
 719+	my $tempfile = file($tempfilename);
 720+	my $outfh = $tempfile->openw();
 721+	$outfh->print("
 722+# $outfilebase - Emoji character definitions for oh-my-zsh emoji plugin
 723+#
 724+# This file is auto-generated by update_emoji.pl. Do not edit it manually.
 725+#
 726+# This contains the definition for:
 727+#   \$emoji         - which maps character names to Unicode characters
 728+#   \$emoji_flags   - maps country names to Unicode flag characters using region indicators 
 729+
 730+# Main emoji
 731+typeset -gAH emoji
 732+# National flags
 733+typeset -gAH emoji_flags
 734+# Combining modifiers
 735+typeset -gAH emoji_mod
 736+
 737+");
 738+
 739+	my $fh = $file->openr();
 740+	my $line_num = 0;
 741+	while ( my $line = $fh->getline() ) {
 742+		$line_num++;
 743+		$_ = $line;
 744+		# Skip all-comment lines (from the header) and blank lines
 745+		# (But don't strip comments on normal lines; we need to parse those for
 746+		# the emoji names.)
 747+		next if /^\s*#/ or /^\s*$/;
 748+
 749+		if (/^(\S.*?\S)\s*;\s*(\w+)\s*;\s*(\w+)\s*;\s*(\w+)\s*;\s*(\w.*?)\s*#\s*V(\S+)\s\(.*?\)\s*(\w.*\S)\s*$/) {
 750+			my ($code, $style, $level, $modifier_status, $sources, $version, $keycap_name) 
 751+				= ($1, $2, $3, $4, $5, $6, $7);
 752+			#print "code=$code style=$style level=$level modifier_status=$modifier_status sources=$sources version=$version name=$keycap_name\n";
 753+			my @code_points = split /\s+/, $code;
 754+			my @sources = split /\s+/, $sources;
 755+
 756+			my $flag_country = "";
 757+			if ( $keycap_name =~ /^flag for (\S.*?)\s*$/) {
 758+				$flag_country = $1;
 759+			}
 760+
 761+			my $zsh_code = join '', map { "\\U$_" } @code_points;
 762+			# Convert keycap names to valid associative array names that do not require any
 763+			# quoting. Works fine for most stuff, but is clumsy for flags.
 764+			my $omz_name = lc($keycap_name);
 765+			$omz_name =~ s/[^A-Za-z0-9]/_/g;
 766+			my $zsh_flag_country = $flag_country;
 767+			$zsh_flag_country =~ s/[^\p{Letter}]/_/g;
 768+			if ($flag_country) {
 769+				$outfh->print("emoji_flags[$zsh_flag_country]=\$'$zsh_code'\n");
 770+			} else {
 771+				$outfh->print("emoji[$omz_name]=\$'$zsh_code'\n");				
 772+			}
 773+			# Modifiers are included in both the main set and their separate map,
 774+			# because they have a standalone representation as a color swatch.
 775+			if ( $modifier_status eq "modifier" ) {
 776+				$outfh->print("emoji_mod[$omz_name]=\$'$zsh_code'\n");
 777+			}
 778+		} else {
 779+			die "Failed parsing line $line_num: '$_'";
 780+		}
 781+	}
 782+	$fh->close();
 783+	$outfh->print("\n");
 784diff --git a/plugins/fasd/fasd.plugin.zsh b/plugins/fasd/fasd.plugin.zsh
 785index 472ab2b0f6b630d3c68c0de835ff4695f6306a75..b11f0b511f68ea343dcf6e090db26c9975b8fd0e 100644
 786--- a/plugins/fasd/fasd.plugin.zsh
 787+++ b/plugins/fasd/fasd.plugin.zsh
 788@@ -5,7 +5,7 @@ if [ $commands[fasd] ]; then # check if fasd is installed
 789   fi
 790   source "$fasd_cache"
 791   unset fasd_cache
 792+
 793   alias v='f -e vim'
 794-  alias o='a -e open'
 795+  alias o='a -e open_command'
 796 fi
 797-
 798diff --git a/plugins/fbterm/fbterm.plugin.zsh b/plugins/fbterm/fbterm.plugin.zsh
 799index 4f0456016f1bfa70f8a8b9efa5ea3089b5f806c2..bc253209201cca8c4a1ea4c4d30b21a621c40b07 100644
 800--- a/plugins/fbterm/fbterm.plugin.zsh
 801+++ b/plugins/fbterm/fbterm.plugin.zsh
 802@@ -1,6 +1,7 @@
 803 # start fbterm automatically in /dev/tty*
 804 
 805-if [[ $(tty|grep -o '/dev/tty') = /dev/tty ]] ; then
 806-	fbterm
 807-	exit
 808+if (( ${+commands[fbterm]} )); then
 809+	if [[ "$TTY" = /dev/tty* ]] ; then
 810+		fbterm && exit
 811+	fi
 812 fi
 813diff --git a/plugins/frontend-search/README.md b/plugins/frontend-search/README.md
 814index 801d450f300db76af79370ce96f2ac9ef65ba024..b8e96ea4a36770a7731b4c20e30221a43594bc7a 100644
 815--- a/plugins/frontend-search/README.md
 816+++ b/plugins/frontend-search/README.md
 817@@ -43,6 +43,7 @@ The search content are
 818 * `reactjs <google.com/search?as_q=<search-term>&as_sitesearch=facebook.github.io/react>`
 819 * `emberjs <emberjs.com>`
 820 * `stackoverflow <stackoverflow.com>`
 821+* `npmjs <npmjs.com>`
 822 
 823 
 824 ## Aliases ##
 825@@ -69,6 +70,7 @@ There are a few aliases presented as well:
 826 * `reactjs` A shorthand for `frontend reactjs`
 827 * `emberjs` A shorthand for `frontend emberjs`
 828 * `stackoverflow` A shorthand for `frontend stackoverflow`
 829+* `npmjs` A shorthand for `frontend npmjs`
 830 
 831 
 832 ## Author
 833diff --git a/plugins/frontend-search/_frontend-search.sh b/plugins/frontend-search/_frontend-search.sh
 834index 252f215707240ce8c11236d919b601c51791be62..b12f829a1c58e52388c7a613b9569ec7406ce3cf 100644
 835--- a/plugins/frontend-search/_frontend-search.sh
 836+++ b/plugins/frontend-search/_frontend-search.sh
 837@@ -37,6 +37,7 @@ function _frontend() {
 838     'reactjs: Search in React website'
 839     'emberjs: Search in Ember website'
 840     'stackoverflow: Search in StackOverflow website'
 841+    'npmjs: Search in NPMJS website'
 842   )
 843 
 844   _arguments -C \
 845@@ -110,6 +111,9 @@ function _frontend() {
 846         stackoverflow)
 847           _describe -t points "Warp points" frontend_points && ret=0
 848           ;;
 849+        npmjs)
 850+          _describe -t points "Warp points" frontend_points && ret=0
 851+          ;;
 852       esac
 853       ;;
 854   esac
 855diff --git a/plugins/frontend-search/frontend-search.plugin.zsh b/plugins/frontend-search/frontend-search.plugin.zsh
 856index b9fb8634c66f15619247713d82febeeb28fbfeeb..e47735a60fe7fc2ea455f4e95ee236df8f4f24de 100644
 857--- a/plugins/frontend-search/frontend-search.plugin.zsh
 858+++ b/plugins/frontend-search/frontend-search.plugin.zsh
 859@@ -2,14 +2,6 @@
 860 
 861 function frontend() {
 862 
 863-  # get the open command
 864-  local open_cmd
 865-  if [[ $(uname -s) == 'Darwin' ]]; then
 866-    open_cmd='open'
 867-  else
 868-    open_cmd='xdg-open'
 869-  fi
 870-
 871   # no keyword provided, simply show how call methods
 872   if [[ $# -le 1 ]]; then
 873     echo "Please provide a search-content and a search-term for app.\nEx:\nfrontend <search-content> <search-term>\n"
 874@@ -17,7 +9,7 @@ function frontend() {
 875   fi
 876 
 877   # check whether the search engine is supported
 878-  if [[ ! $1 =~ '(jquery|mdn|compass|html5please|caniuse|aurajs|dartlang|qunit|fontello|bootsnipp|cssflow|codepen|unheap|bem|smacss|angularjs|reactjs|emberjs|stackoverflow)' ]];
 879+  if [[ ! $1 =~ '(jquery|mdn|compass|html5please|caniuse|aurajs|dartlang|qunit|fontello|bootsnipp|cssflow|codepen|unheap|bem|smacss|angularjs|reactjs|emberjs|stackoverflow|npmjs)' ]];
 880   then
 881     echo "Search valid search content $1 not supported."
 882     echo "Valid contents: (formats 'frontend <search-content>' or '<search-content>')"
 883@@ -41,6 +33,7 @@ function frontend() {
 884     echo "* reactjs"
 885     echo "* emberjs"
 886     echo "* stackoverflow"
 887+    echo "* npmjs"
 888     echo ""
 889 
 890     return 1
 891@@ -107,13 +100,16 @@ function frontend() {
 892     "stackoverflow")
 893       url="${url}stackoverflow.com"
 894       url="${url}/search?q=$2" ;;
 895+    "npmjs")
 896+      url="${url}www.npmjs.com"
 897+      url="${url}/search?q=$2" ;;
 898     *) echo "INVALID PARAM!"
 899        return ;;
 900   esac
 901 
 902   echo "$url"
 903 
 904-  $open_cmd "$url"
 905+  open_command "$url"
 906 
 907 }
 908 
 909@@ -156,3 +152,4 @@ alias emberjs='frontend emberjs'
 910 
 911 # search websites
 912 alias stackoverflow='frontend stackoverflow'
 913+alias npmjs='frontend npmjs'
 914diff --git a/plugins/git-flow/git-flow.plugin.zsh b/plugins/git-flow/git-flow.plugin.zsh
 915index 4357c08957e6f7373df0dbcd465db2d59719f6f9..444440bcb8afeff1a3f699e694d834210d793087 100644
 916--- a/plugins/git-flow/git-flow.plugin.zsh
 917+++ b/plugins/git-flow/git-flow.plugin.zsh
 918@@ -21,7 +21,7 @@
 919 #
 920 
 921 #Alias
 922-alias gf='git flow'
 923+alias gfl='git flow'
 924 alias gcd='git checkout develop'
 925 alias gch='git checkout hotfix'
 926 alias gcr='git checkout release'
 927diff --git a/plugins/git-prompt/git-prompt.plugin.zsh b/plugins/git-prompt/git-prompt.plugin.zsh
 928index d868a5fe1d1bf6b6117db674b093d1a632f5d0d7..5175bf70f91d0fafddebfd72a74eea5435131213 100644
 929--- a/plugins/git-prompt/git-prompt.plugin.zsh
 930+++ b/plugins/git-prompt/git-prompt.plugin.zsh
 931@@ -1,57 +1,92 @@
 932 # ZSH Git Prompt Plugin from:
 933 # http://github.com/olivierverdier/zsh-git-prompt
 934-#
 935-export __GIT_PROMPT_DIR=$ZSH/plugins/git-prompt
 936 
 937-# Allow for functions in the prompt.
 938-setopt PROMPT_SUBST
 939+__GIT_PROMPT_DIR="${0:A:h}"
 940 
 941-## Enable auto-execution of functions.
 942-typeset -ga preexec_functions
 943-typeset -ga precmd_functions
 944-typeset -ga chpwd_functions
 945-
 946-# Append git functions needed for prompt.
 947-preexec_functions+='preexec_update_git_vars'
 948-precmd_functions+='precmd_update_git_vars'
 949-chpwd_functions+='chpwd_update_git_vars'
 950+## Hook function definitions
 951+function chpwd_update_git_vars() {
 952+    update_current_git_vars
 953+}
 954 
 955-## Function definitions
 956 function preexec_update_git_vars() {
 957     case "$2" in
 958-        git*)
 959+        git*|hub*|gh*|stg*)
 960         __EXECUTED_GIT_COMMAND=1
 961         ;;
 962     esac
 963 }
 964 
 965 function precmd_update_git_vars() {
 966-    if [ -n "$__EXECUTED_GIT_COMMAND" ]; then
 967+    if [ -n "$__EXECUTED_GIT_COMMAND" ] || [ ! -n "$ZSH_THEME_GIT_PROMPT_CACHE" ]; then
 968         update_current_git_vars
 969         unset __EXECUTED_GIT_COMMAND
 970     fi
 971 }
 972 
 973-function chpwd_update_git_vars() {
 974-    update_current_git_vars
 975-}
 976+chpwd_functions+=(chpwd_update_git_vars)
 977+precmd_functions+=(precmd_update_git_vars)
 978+preexec_functions+=(preexec_update_git_vars)
 979+
 980 
 981+## Function definitions
 982 function update_current_git_vars() {
 983     unset __CURRENT_GIT_STATUS
 984 
 985     local gitstatus="$__GIT_PROMPT_DIR/gitstatus.py"
 986-    _GIT_STATUS=`python ${gitstatus}`
 987-    __CURRENT_GIT_STATUS=("${(f)_GIT_STATUS}")
 988+    _GIT_STATUS=$(python ${gitstatus} 2>/dev/null)
 989+     __CURRENT_GIT_STATUS=("${(@s: :)_GIT_STATUS}")
 990+    GIT_BRANCH=$__CURRENT_GIT_STATUS[1]
 991+    GIT_AHEAD=$__CURRENT_GIT_STATUS[2]
 992+    GIT_BEHIND=$__CURRENT_GIT_STATUS[3]
 993+    GIT_STAGED=$__CURRENT_GIT_STATUS[4]
 994+    GIT_CONFLICTS=$__CURRENT_GIT_STATUS[5]
 995+    GIT_CHANGED=$__CURRENT_GIT_STATUS[6]
 996+    GIT_UNTRACKED=$__CURRENT_GIT_STATUS[7]
 997 }
 998 
 999-function prompt_git_info() {
1000+git_super_status() {
1001+    precmd_update_git_vars
1002     if [ -n "$__CURRENT_GIT_STATUS" ]; then
1003-        echo "(%{${fg[red]}%}$__CURRENT_GIT_STATUS[1]%{${fg[default]}%}$__CURRENT_GIT_STATUS[2]%{${fg[magenta]}%}$__CURRENT_GIT_STATUS[3]%{${fg[default]}%})"
1004+      STATUS="$ZSH_THEME_GIT_PROMPT_PREFIX$ZSH_THEME_GIT_PROMPT_BRANCH$GIT_BRANCH%{${reset_color}%}"
1005+      if [ "$GIT_BEHIND" -ne "0" ]; then
1006+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_BEHIND$GIT_BEHIND%{${reset_color}%}"
1007+      fi
1008+      if [ "$GIT_AHEAD" -ne "0" ]; then
1009+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_AHEAD$GIT_AHEAD%{${reset_color}%}"
1010+      fi
1011+      STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_SEPARATOR"
1012+      if [ "$GIT_STAGED" -ne "0" ]; then
1013+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_STAGED$GIT_STAGED%{${reset_color}%}"
1014+      fi
1015+      if [ "$GIT_CONFLICTS" -ne "0" ]; then
1016+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CONFLICTS$GIT_CONFLICTS%{${reset_color}%}"
1017+      fi
1018+      if [ "$GIT_CHANGED" -ne "0" ]; then
1019+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CHANGED$GIT_CHANGED%{${reset_color}%}"
1020+      fi
1021+      if [ "$GIT_UNTRACKED" -ne "0" ]; then
1022+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED%{${reset_color}%}"
1023+      fi
1024+      if [ "$GIT_CHANGED" -eq "0" ] && [ "$GIT_CONFLICTS" -eq "0" ] && [ "$GIT_STAGED" -eq "0" ] && [ "$GIT_UNTRACKED" -eq "0" ]; then
1025+          STATUS="$STATUS$ZSH_THEME_GIT_PROMPT_CLEAN"
1026+      fi
1027+      STATUS="$STATUS%{${reset_color}%}$ZSH_THEME_GIT_PROMPT_SUFFIX"
1028+      echo "$STATUS"
1029     fi
1030 }
1031diff --git a/plugins/git-prompt/gitstatus.py b/plugins/git-prompt/gitstatus.py
1032index 2568414320a79140ab387ad4fe788d8cd78367fd..a8eb8284b7ad8ed601890d84f0ffbfe92f6c00a1 100644
1033--- a/plugins/git-prompt/gitstatus.py
1034+++ b/plugins/git-prompt/gitstatus.py
1035@@ -1,82 +1,84 @@
1036 #!/usr/bin/env python
1037-# -*- coding: UTF-8 -*-
1038-from subprocess import Popen, PIPE
1039-import re
1040+from __future__ import print_function
1041 
1042-# change those symbols to whatever you prefer
1043-symbols = {
1044-    'ahead of': '↑',
1045-    'behind': '↓',
1046-    'staged': '♦',
1047-    'changed': '‣',
1048-    'untracked': '…',
1049-    'clean': '⚡',
1050-    'unmerged': '≠',
1051-    'sha1': ':'
1052-}
1053+import sys
1054+import re
1055+import shlex
1056+from subprocess import Popen, PIPE, check_output
1057 
1058-output, error = Popen(
1059-    ['git', 'status'], stdout=PIPE, stderr=PIPE, universal_newlines=True).communicate()
1060 
1061-if error:
1062-    import sys
1063-    sys.exit(0)
1064-lines = output.splitlines()
1065+def get_tagname_or_hash():
1066+    """return tagname if exists else hash"""
1067+    cmd = 'git log -1 --format="%h%d"'
1068+    output = check_output(shlex.split(cmd)).decode('utf-8').strip()
1069+    hash_, tagname = None, None
1070+    # get hash
1071+    m = re.search('\(.*\)$', output)
1072+    if m:
1073+        hash_ = output[:m.start()-1]
1074+    # get tagname
1075+    m = re.search('tag: .*[,\)]', output)
1076+    if m:
1077+        tagname = 'tags/' + output[m.start()+len('tag: '): m.end()-1]
1078 
1079-behead_re = re.compile(
1080-    r"^# Your branch is (ahead of|behind) '(.*)' by (\d+) commit")
1081-diverge_re = re.compile(r"^# and have (\d+) and (\d+) different")
1082+    if tagname:
1083+        return tagname
1084+    elif hash_:
1085+        return hash_
1086+    return None
1087 
1088-status = ''
1089-staged = re.compile(r'^# Changes to be committed:$', re.MULTILINE)
1090-changed = re.compile(r'^# Changed but not updated:$', re.MULTILINE)
1091-untracked = re.compile(r'^# Untracked files:$', re.MULTILINE)
1092-unmerged = re.compile(r'^# Unmerged paths:$', re.MULTILINE)
1093 
1094+# `git status --porcelain --branch` can collect all information
1095+# branch, remote_branch, untracked, staged, changed, conflicts, ahead, behind
1096+po = Popen(['git', 'status', '--porcelain', '--branch'], stdout=PIPE, stderr=PIPE)
1097+stdout, sterr = po.communicate()
1098+if po.returncode != 0:
1099+    sys.exit(0)  # Not a git repository
1100 
1101-def execute(*command):
1102-    out, err = Popen(stdout=PIPE, stderr=PIPE, *command).communicate()
1103-    if not err:
1104-        nb = len(out.splitlines())
1105+# collect git status information
1106+untracked, staged, changed, conflicts = [], [], [], []
1107+ahead, behind = 0, 0
1108+status = [(line[0], line[1], line[2:]) for line in stdout.decode('utf-8').splitlines()]
1109+for st in status:
1110+    if st[0] == '#' and st[1] == '#':
1111+        if re.search('Initial commit on', st[2]):
1112+            branch = st[2].split(' ')[-1]
1113+        elif re.search('no branch', st[2]):  # detached status
1114+            branch = get_tagname_or_hash()
1115+        elif len(st[2].strip().split('...')) == 1:
1116+            branch = st[2].strip()
1117+        else:
1118+            # current and remote branch info
1119+            branch, rest = st[2].strip().split('...')
1120+            if len(rest.split(' ')) == 1:
1121+                # remote_branch = rest.split(' ')[0]
1122+                pass
1123+            else:
1124+                # ahead or behind
1125+                divergence = ' '.join(rest.split(' ')[1:])
1126+                divergence = divergence.lstrip('[').rstrip(']')
1127+                for div in divergence.split(', '):
1128+                    if 'ahead' in div:
1129+                        ahead = int(div[len('ahead '):].strip())
1130+                    elif 'behind' in div:
1131+                        behind = int(div[len('behind '):].strip())
1132+    elif st[0] == '?' and st[1] == '?':
1133+        untracked.append(st)
1134     else:
1135diff --git a/plugins/git/git.plugin.zsh b/plugins/git/git.plugin.zsh
1136index cc6eb1031b1063be5639af3312713ca95fe79513..bbee13ab825fb6d8a729375efbc7612b83176b69 100644
1137--- a/plugins/git/git.plugin.zsh
1138+++ b/plugins/git/git.plugin.zsh
1139@@ -68,10 +68,12 @@ alias gc!='git commit -v --amend'
1140 alias gca='git commit -v -a'
1141 alias gca!='git commit -v -a --amend'
1142 alias gcan!='git commit -v -a -s --no-edit --amend'
1143+alias gcam='git commit -a -m'
1144 alias gcb='git checkout -b'
1145 alias gcf='git config --list'
1146 alias gcl='git clone --recursive'
1147-alias gclean='git reset --hard && git clean -dfx'
1148+alias gclean='git clean -fd'
1149+alias gpristine='git reset --hard && git clean -dfx'
1150 alias gcm='git checkout master'
1151 alias gcmsg='git commit -m'
1152 alias gco='git checkout'
1153diff --git a/plugins/heroku/_heroku b/plugins/heroku/_heroku
1154index bb2f7403f697f6b24bbd80f8a343fcd423a94cbe..fd72e530e80be98bfda0af8b3090c16852d58da2 100644
1155--- a/plugins/heroku/_heroku
1156+++ b/plugins/heroku/_heroku
1157@@ -143,5 +143,6 @@ _arguments \
1158   $_command_args \
1159   '(--app)--app[the app name]' \
1160   '(--remote)--remote[the remote name]' \
1161+  '(--help)--help[help about the current command]' \
1162   &&  return 0
1163 
1164diff --git a/plugins/jira/_jira b/plugins/jira/_jira
1165new file mode 100644
1166index 0000000000000000000000000000000000000000..b0ea658e2f3ac23079fb19166509667407741ae2
1167--- /dev/null
1168+++ b/plugins/jira/_jira
1169@@ -0,0 +1,21 @@
1170+#compdef jira
1171+#autoload
1172+
1173+local -a _1st_arguments
1174+_1st_arguments=(
1175+  'new:create a new issue'
1176+  'dashboard:open the dashboard'
1177+  'reported:search for issues reported by a user'
1178+  'assigned:search for issues assigned to a user'
1179+)
1180+
1181+_arguments -C \
1182+  ':command:->command' \
1183+  '*::options:->options'
1184+
1185+case $state in
1186+  (command)
1187+    _describe -t commands "jira subcommand" _1st_arguments
1188+    return
1189+   ;;
1190+esac
1191diff --git a/plugins/jira/jira.plugin.zsh b/plugins/jira/jira.plugin.zsh
1192index ca540c84c1229cbea6d0bb0ae721499e2ce41364..89559767f86b684ea0e47a69ea363e94acf11d12 100644
1193--- a/plugins/jira/jira.plugin.zsh
1194+++ b/plugins/jira/jira.plugin.zsh
1195@@ -1,97 +1,118 @@
1196-# To use: add a .jira-url file in the base of your project
1197-#         You can also set JIRA_URL in your .zshrc or put .jira-url in your home directory
1198-#         .jira-url in the current directory takes precedence
1199+# CLI support for JIRA interaction
1200 #
1201-# If you use Rapid Board, set:
1202-#JIRA_RAPID_BOARD="true"
1203-# in you .zshrc
1204+# Setup: 
1205+#   Add a .jira-url file in the base of your project
1206+#   You can also set $JIRA_URL in your .zshrc or put .jira-url in your home directory
1207+#   A .jira-url in the current directory takes precedence. 
1208+#   The same goes with .jira-prefix and $JIRA_PREFIX.
1209 #
1210-# Setup: cd to/my/project
1211-#        echo "https://name.jira.com" >> .jira-url
1212-# Usage: jira           # opens a new issue
1213-#        jira ABC-123   # Opens an existing issue
1214-open_jira_issue () {
1215-  local open_cmd
1216-  if [[ "$OSTYPE" = darwin* ]]; then
1217-    open_cmd='open'
1218-  else
1219-    open_cmd='xdg-open'
1220-  fi
1221+#   For example:
1222+#     cd to/my/project
1223+#     echo "https://name.jira.com" >> .jira-url
1224+#
1225+# Variables:
1226+#  $JIRA_RAPID_BOARD     - set to "true" if you use Rapid Board
1227+#  $JIRA_DEFAULT_ACTION  - action to do when `jira` is called witn no args
1228+#                          defaults to "new"
1229+#  $JIRA_NAME            - Your JIRA username. Used as default for assigned/reported
1230+#  $JIRA_PREFIX          - Prefix added to issue ID arguments
1231+#
1232+#
1233+# Usage: 
1234+#   jira            # Performs the default action
1235+#   jira new        # opens a new issue
1236+#   jira reported [username]
1237+#   jira assigned [username]
1238+#   jira dashboard
1239+#   jira ABC-123    # Opens an existing issue
1240+#   jira ABC-123 m  # Opens an existing issue for adding a comment
1241+
1242+: ${JIRA_DEFAULT_ACTION:=new}
1243 
1244-  if [ -f .jira-url ]; then
1245+function jira() {
1246+  local action=${1:=$JIRA_DEFAULT_ACTION}
1247+
1248+  local jira_url jira_prefix
1249+  if [[ -f .jira-url ]]; then
1250     jira_url=$(cat .jira-url)
1251-  elif [ -f ~/.jira-url ]; then
1252+  elif [[ -f ~/.jira-url ]]; then
1253     jira_url=$(cat ~/.jira-url)
1254-  elif [[ "x$JIRA_URL" != "x" ]]; then
1255-    jira_url=$JIRA_URL
1256+  elif [[ -n "${JIRA_URL}" ]]; then
1257+    jira_url=${JIRA_URL}
1258   else
1259-    echo "JIRA url is not specified anywhere."
1260+    _jira_url_help
1261     return 1
1262   fi
1263 
1264-  if [ -f .jira-prefix ]; then
1265+  if [[ -f .jira-prefix ]]; then
1266     jira_prefix=$(cat .jira-prefix)
1267-  elif [ -f ~/.jira-prefix ]; then
1268+  elif [[ -f ~/.jira-prefix ]]; then
1269     jira_prefix=$(cat ~/.jira-prefix)
1270+  elif [[ -n "${JIRA_PREFIX}" ]]; then
1271+    jira_prefix=${JIRA_PREFIX}
1272   else
1273     jira_prefix=""
1274   fi
1275 
1276-  if [ -z "$1" ]; then
1277+
1278+  if [[ $action == "new" ]]; then
1279     echo "Opening new issue"
1280-    $open_cmd "${jira_url}/secure/CreateIssue!default.jspa"
1281-  elif [[ "$1" = "assigned" || "$1" = "reported" ]]; then
1282-    jira_query $@
1283-  else 
1284-    local addcomment=''
1285+    open_command "${jira_url}/secure/CreateIssue!default.jspa"
1286+  elif [[ "$action" == "assigned" || "$action" == "reported" ]]; then
1287+    _jira_query $@
1288+  elif [[ "$action" == "dashboard" ]]; then
1289+    echo "Opening dashboard"
1290+    open_command "${jira_url}/secure/Dashboard.jspa"
1291+  else
1292+    # Anything that doesn't match a special action is considered an issue name
1293+    local issue_arg=$action
1294+    local issue="${jira_prefix}${issue_arg}"
1295diff --git a/plugins/last-working-dir/last-working-dir.plugin.zsh b/plugins/last-working-dir/last-working-dir.plugin.zsh
1296index 75041f08ef63874a9ecba86180ea912bb9d43e2c..c458464ce32a7e3734bf2738f42a41e7e717ceab 100644
1297--- a/plugins/last-working-dir/last-working-dir.plugin.zsh
1298+++ b/plugins/last-working-dir/last-working-dir.plugin.zsh
1299@@ -8,7 +8,8 @@ mkdir -p $ZSH_CACHE_DIR
1300 cache_file="$ZSH_CACHE_DIR/last-working-dir"
1301 
1302 # Updates the last directory once directory is changed.
1303-function chpwd() {
1304+chpwd_functions+=(chpwd_last_working_dir)
1305+function chpwd_last_working_dir() {
1306   # Use >| in case noclobber is set to avoid "file exists" error
1307 	pwd >| "$cache_file"
1308 }
1309diff --git a/plugins/lighthouse/lighthouse.plugin.zsh b/plugins/lighthouse/lighthouse.plugin.zsh
1310index 7661c6add6124a30a9544c47fdd4521657e3d69f..48cddbccc7e015257a7928f82e765b4a8acf7eb7 100644
1311--- a/plugins/lighthouse/lighthouse.plugin.zsh
1312+++ b/plugins/lighthouse/lighthouse.plugin.zsh
1313@@ -9,7 +9,7 @@ open_lighthouse_ticket () {
1314   else
1315     lighthouse_url=$(cat .lighthouse-url);
1316     echo "Opening ticket #$1";
1317-    `open $lighthouse_url/tickets/$1`;
1318+    open_command "$lighthouse_url/tickets/$1";
1319   fi
1320 }
1321 
1322diff --git a/plugins/man/man.zsh b/plugins/man/man.zsh
1323new file mode 100644
1324index 0000000000000000000000000000000000000000..3490b0b61b85ed7c0d6363728f7d4014fb85920d
1325--- /dev/null
1326+++ b/plugins/man/man.zsh
1327@@ -0,0 +1,27 @@
1328+# ------------------------------------------------------------------------------
1329+# Author
1330+# ------
1331+#
1332+# * Jerry Ling<jerryling315@gmail.com>
1333+#
1334+# ------------------------------------------------------------------------------
1335+# Usgae
1336+# -----
1337+#
1338+# man will be inserted before the command
1339+#
1340+# ------------------------------------------------------------------------------
1341+
1342+man-command-line() {
1343+    [[ -z $BUFFER ]] && zle up-history
1344+    [[ $BUFFER != man\ * ]] && LBUFFER="man $LBUFFER"
1345+}
1346+zle -N man-command-line
1347+# Defined shortcut keys: [Esc]man
1348+bindkey "\e"man man-command-line
1349+
1350+
1351+# ------------------------------------------------------------------------------
1352+# Also, you might want to use man-preview included in 'osx' plugin
1353+# just substitute "man" in the function with "man-preview" after you included OS X in
1354+# the .zshrc
1355diff --git a/plugins/n98-magerun/n98-magerun.plugin.zsh b/plugins/n98-magerun/n98-magerun.plugin.zsh
1356new file mode 100755
1357index 0000000000000000000000000000000000000000..bfcf27b984ada059662eb28f559671b72863e3fe
1358--- /dev/null
1359+++ b/plugins/n98-magerun/n98-magerun.plugin.zsh
1360@@ -0,0 +1,34 @@
1361+# ------------------------------------------------------------------------------
1362+# FILE: n98-magerun.plugin.zsh
1363+# DESCRIPTION: oh-my-zsh n98-magerun plugin file. Adapted from composer plugin 
1364+# AUTHOR: Andrew Dwyer (andrewrdwyer at gmail dot com)
1365+# VERSION: 1.0.0
1366+# ------------------------------------------------------------------------------
1367+
1368+# n98-magerun basic command completion
1369+_n98_magerun_get_command_list () {
1370+  $_comp_command1 --no-ansi | sed "1,/Available commands/d" | awk '/^ +[a-z\-:]+/ { print $1 }'
1371+}
1372+
1373+
1374+_n98_magerun () {
1375+  _arguments '1: :->command' '*:optional arg:_files'
1376+
1377+  case $state in
1378+    command)
1379+      compadd $(_n98_magerun_get_command_list)
1380+      ;;
1381+    *)
1382+  esac
1383+}
1384+
1385+compdef _n98_magerun n98-magerun.phar
1386+compdef _n98_magerun n98-magerun
1387+
1388+# Aliases
1389+alias n98='n98-magerun.phar'
1390+alias mage='n98-magerun.phar'
1391+alias magefl='n98-magerun.phar cache:flush'
1392+
1393+# Install n98-magerun into the current directory
1394+alias mage-get='wget https://raw.github.com/netz98/n98-magerun/master/n98-magerun.phar'
1395diff --git a/plugins/node/node.plugin.zsh b/plugins/node/node.plugin.zsh
1396index 39d8b10d99324b60c6b01155ac8b9401b4b57aa0..2463815aca572c54cb08dda1bc4a69335225aacd 100644
1397--- a/plugins/node/node.plugin.zsh
1398+++ b/plugins/node/node.plugin.zsh
1399@@ -1,13 +1,5 @@
1400 # Open the node api for your current version to the optional section.
1401 # TODO: Make the section part easier to use.
1402 function node-docs {
1403-  # get the open command
1404-  local open_cmd
1405-  if [[ "$OSTYPE" = darwin* ]]; then
1406-    open_cmd='open'
1407-  else
1408-    open_cmd='xdg-open'
1409-  fi
1410-
1411-  $open_cmd "http://nodejs.org/docs/$(node --version)/api/all.html#all_$1"
1412+  open_command "http://nodejs.org/docs/$(node --version)/api/all.html#all_$1"
1413 }
1414diff --git a/plugins/osx/osx.plugin.zsh b/plugins/osx/osx.plugin.zsh
1415index a6e3a83e6a738a7e4931afc5ffa62bc28d27d9ff..390960fdcc162c6701fe0c066772f32d75460bb8 100644
1416--- a/plugins/osx/osx.plugin.zsh
1417+++ b/plugins/osx/osx.plugin.zsh
1418@@ -6,7 +6,7 @@
1419 # ------------------------------------------------------------------------------
1420 
1421 function tab() {
1422-  local command="cd \\\"$PWD\\\"; clear; "
1423+  local command="cd \\\"$PWD\\\"; clear"
1424   (( $# > 0 )) && command="${command}; $*"
1425 
1426   the_app=$(
1427diff --git a/plugins/rand-quote/rand-quote.plugin.zsh b/plugins/rand-quote/rand-quote.plugin.zsh
1428index c3bf6234ec61157034f1080d3bed8c1257a2f551..8f345d9aa1e04626c45195f07253ec2cccc5aba4 100644
1429--- a/plugins/rand-quote/rand-quote.plugin.zsh
1430+++ b/plugins/rand-quote/rand-quote.plugin.zsh
1431@@ -18,8 +18,6 @@ if [[ -x `which curl` ]]; then
1432         W=$(echo "$Q" | sed -e 's/.*\/quotes\///g' -e 's/<.*//g' -e 's/.*">//g')
1433         if [ "$W" -a "$TXT" ]; then
1434           echo "${WHO_COLOR}${W}${COLON_COLOR}: ${TEXT_COLOR}“${TXT}”${END_COLOR}"
1435-        else
1436-          quote
1437         fi
1438     }
1439     #quote
1440diff --git a/plugins/rbenv/rbenv.plugin.zsh b/plugins/rbenv/rbenv.plugin.zsh
1441index 213e1beb0b4986db4d95fbe38432edbfd0b38612..ef5106f2d61ad7aa6dbdd13f47eb5141f3eec21b 100644
1442--- a/plugins/rbenv/rbenv.plugin.zsh
1443+++ b/plugins/rbenv/rbenv.plugin.zsh
1444@@ -2,14 +2,11 @@ _homebrew-installed() {
1445   type brew &> /dev/null
1446 }
1447 
1448-_rbenv-from-homebrew-installed() {
1449-  brew --prefix rbenv &> /dev/null
1450-}
1451-
1452 FOUND_RBENV=0
1453 rbenvdirs=("$HOME/.rbenv" "/usr/local/rbenv" "/opt/rbenv" "/usr/local/opt/rbenv")
1454-if _homebrew-installed && _rbenv-from-homebrew-installed ; then
1455-    rbenvdirs=($(brew --prefix rbenv) "${rbenvdirs[@]}")
1456+if _homebrew-installed && rbenv_homebrew_path=$(brew --prefix rbenv 2>/dev/null); then
1457+    rbenvdirs=($rbenv_homebrew_path "${rbenvdirs[@]}")
1458+    unset rbenv_homebrew_path
1459 fi
1460 
1461 for rbenvdir in "${rbenvdirs[@]}" ; do
1462diff --git a/plugins/rvm/rvm.plugin.zsh b/plugins/rvm/rvm.plugin.zsh
1463index 234ac164201c004b5d1717593a52ca6f21b2a877..53e809aaf77d219540de1d3f8616723c43b29d32 100644
1464--- a/plugins/rvm/rvm.plugin.zsh
1465+++ b/plugins/rvm/rvm.plugin.zsh
1466@@ -61,11 +61,11 @@ function gems {
1467 	local current_ruby=`rvm-prompt i v p`
1468 	local current_gemset=`rvm-prompt g`
1469 
1470-	gem list $@ | sed \
1471-		-Ee "s/\([0-9, \.]+( .+)?\)/$fg[blue]&$reset_color/g" \
1472-		-Ee "s|$(echo $rvm_path)|$fg[magenta]\$rvm_path$reset_color|g" \
1473-		-Ee "s/$current_ruby@global/$fg[yellow]&$reset_color/g" \
1474-		-Ee "s/$current_ruby$current_gemset$/$fg[green]&$reset_color/g"
1475+	gem list $@ | sed -E \
1476+		-e "s/\([0-9, \.]+( .+)?\)/$fg[blue]&$reset_color/g" \
1477+		-e "s|$(echo $rvm_path)|$fg[magenta]\$rvm_path$reset_color|g" \
1478+		-e "s/$current_ruby@global/$fg[yellow]&$reset_color/g" \
1479+		-e "s/$current_ruby$current_gemset$/$fg[green]&$reset_color/g"
1480 }
1481 
1482 function _rvm_completion {
1483diff --git a/plugins/spring/README.md b/plugins/spring/README.md
1484new file mode 100644
1485index 0000000000000000000000000000000000000000..62bfd8013e40eab1fea3aee86c7da58c4fde139f
1486--- /dev/null
1487+++ b/plugins/spring/README.md
1488@@ -0,0 +1,25 @@
1489+# Spring Boot oh-my-zsh plugin
1490+oh-my-zsh Spring Boot plugin
1491+
1492+## Spring Boot autocomplete plugin
1493+
1494+- Adds autocomplete options for all spring boot commands.
1495+
1496+## Manual Install
1497+
1498+     $ cd ~/.oh-my-zsh/plugins
1499+     $ git clone git@github.com:linux-china/oh-my-zsh-spring-boot-plugin.git spring
1500+
1501+Adjust your .zshrc file and add spring to plugins=(...)  
1502+ 
1503+## Tips 
1504+
1505+* Install Spring Cloud plugin: spring install org.springframework.cloud:spring-cloud-cli:1.0.2.RELEASE
1506+
1507+## Reference
1508+
1509+* Spring Boot: http://projects.spring.io/spring-boot/
1510+* Spring Boot CLI: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#cli
1511+
1512+Maintainer : linux_china ([@linux_china](https://twitter.com/linux_china))
1513+
1514diff --git a/plugins/spring/_spring b/plugins/spring/_spring
1515new file mode 100644
1516index 0000000000000000000000000000000000000000..93f19517d51344e88637ea665f3c4d324b9ee67f
1517--- /dev/null
1518+++ b/plugins/spring/_spring
1519@@ -0,0 +1,29 @@
1520+#compdef spring 'spring'
1521+#autoload
1522+
1523+_spring() {
1524+
1525+        local cword
1526+        let cword=CURRENT-1
1527+
1528+        local hints
1529+        hints=()
1530+
1531+        local reply
1532+        while read -r line; do
1533+                reply=`echo "$line" | awk '{printf $1 ":"; for (i=2; i<NF; i++) printf $i " "; print $NF}'`
1534+                hints+=("$reply")
1535+        done < <(spring hint ${cword} ${words[*]})
1536+
1537+        if ((cword == 1)) {
1538+                _describe -t commands 'commands' hints
1539+                return 0
1540+        }
1541+
1542+        _describe -t options 'options' hints
1543+        _files
1544+
1545+        return 0
1546+}
1547+
1548+_spring "$@"
1549diff --git a/plugins/symfony2/symfony2.plugin.zsh b/plugins/symfony2/symfony2.plugin.zsh
1550index e94280ed075c7b0a4a55ee8b21b8e267bf4cac34..98a2321db13102527727a97277536e4709912690 100644
1551--- a/plugins/symfony2/symfony2.plugin.zsh
1552+++ b/plugins/symfony2/symfony2.plugin.zsh
1553@@ -5,7 +5,7 @@ _symfony_console () {
1554 }
1555 
1556 _symfony2_get_command_list () {
1557-   `_symfony_console` --no-ansi | sed "1,/Available commands/d" | awk '/^  ?[a-z]+/ { print $1 }'
1558+   `_symfony_console` --no-ansi | sed "1,/Available commands/d" | awk '/^  ?[^ ]+ / { print $1 }'
1559 }
1560 
1561 _symfony2 () {
1562diff --git a/plugins/systemd/systemd.plugin.zsh b/plugins/systemd/systemd.plugin.zsh
1563index 7d3db0f8e3bac444e6a31f24295e32f7fb317b0a..07eb595a6debc9f5d938230f63bbd2b9ee3b467a 100644
1564--- a/plugins/systemd/systemd.plugin.zsh
1565+++ b/plugins/systemd/systemd.plugin.zsh
1566@@ -1,11 +1,12 @@
1567 user_commands=(
1568   list-units is-active status show help list-unit-files
1569-  is-enabled list-jobs show-environment)
1570+  is-enabled list-jobs show-environment cat)
1571 
1572 sudo_commands=(
1573   start stop reload restart try-restart isolate kill
1574   reset-failed enable disable reenable preset mask unmask
1575-  link load cancel set-environment unset-environment)
1576+  link load cancel set-environment unset-environment
1577+  edit)
1578 
1579 for c in $user_commands; do; alias sc-$c="systemctl $c"; done
1580 for c in $sudo_commands; do; alias sc-$c="sudo systemctl $c"; done
1581diff --git a/plugins/terraform/README.md b/plugins/terraform/README.md
1582new file mode 100644
1583index 0000000000000000000000000000000000000000..44e38a1c0b2761bbbad77bf4aa3a28ee0e9b0be6
1584--- /dev/null
1585+++ b/plugins/terraform/README.md
1586@@ -0,0 +1,11 @@
1587+## atom
1588+
1589+Plugin for Terraform, a tool from Hashicorp for managing infrastructure safely and efficiently.
1590+
1591+### Requirements
1592+
1593+ * [Terraform](https://terraform.io/)
1594+
1595+### Usage
1596+
1597+ * Type `terraform` into your prompt and hit `TAB` to see available completion options
1598diff --git a/plugins/terraform/_terraform b/plugins/terraform/_terraform
1599new file mode 100644
1600index 0000000000000000000000000000000000000000..11740dc4819cbda50cfb63dfda7ca14e16831f1d
1601--- /dev/null
1602+++ b/plugins/terraform/_terraform
1603@@ -0,0 +1,177 @@
1604+#compdef terraform
1605+
1606+local -a _terraform_cmds
1607+_terraform_cmds=(
1608+    'apply:Builds or changes infrastructure'
1609+    'destroy:Destroy Terraform-managed infrastructure'
1610+    'get:Download and install modules for the configuration'
1611+    'graph:Create a visual graph of Terraform resources'
1612+    'init:Initializes Terraform configuration from a module'
1613+    'output:Read an output from a state file'
1614+    'plan:Generate and show an execution plan'
1615+    'pull:Refreshes the local state copy from the remote server'
1616+    'push:Uploads the local state to the remote server'
1617+    'refresh:Update local state file against real resources'
1618+    'remote:Configures remote state management'
1619+    'show:Inspect Terraform state or plan'
1620+    'taint:Manually forcing a destroy and recreate on the next plan/apply'
1621+    'version:Prints the Terraform version'
1622+)
1623+
1624+__apply() {
1625+    _arguments \
1626+        '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]' \
1627+        '-input=[(true) Ask for input for variables if not directly set.]' \
1628+        '-no-color[If specified, output will not contain any color.]' \
1629+        '-refresh=[(true) Update state prior to checking for differences. This has no effect if a plan file is given to apply.]' \
1630+        '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]' \
1631+        '-state-out=[(path) Path to write state to that is different than "-state". This can be used to preserve the old state.]' \
1632+        '-target=[(resource) A Resource Address to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]' \
1633+        '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \
1634+        '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]'
1635+}
1636+
1637+__destroy() {
1638+    _arguments \
1639+        '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with ".backup" extension. Set to "-" to disable backup.]' \
1640+        '-force[If set, then the destroy confirmation will not be shown.]' \
1641+        '-input=[(true) Ask for input for variables if not directly set.]' \
1642+        '-no-color[If specified, output will not contain any color.]' \
1643+        '-refresh=[(true) Update state prior to checking for differences. This has no effect if a plan file is given to apply.]' \
1644+        '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]' \
1645+        '-state-out=[(path) Path to write state to that is different than "-state". This can be used to preserve the old state.]' \
1646+        '-target=[(resource) Instead of affecting "dependencies" will instead also destroy any resources that depend on the target(s) specified.]' \
1647+        '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \
1648+        '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]'
1649+}
1650+
1651+__get() {
1652+    _arguments \
1653+        '-update=[(false) If true, modules already downloaded will be checked for updates and updated if necessary.]'
1654+}
1655+
1656+__graph() {
1657+    _arguments \
1658+        '-draw-cycles[Highlight any cycles in the graph with colored edges. This helps when diagnosing cycle errors.]' \
1659+        '-module-depth=[(n) The maximum depth to expand modules. By default this is zero, which will not expand modules at all.]' \
1660+        '-verbose[Generate a verbose, "worst-case" graph, with all nodes for potential operations in place.]'
1661+}
1662+
1663+__init() {
1664+    _arguments \
1665+        '-address=[(url) URL of the remote storage server. Required for HTTP backend, optional for Atlas and Consul.]' \
1666+        '-access-token=[(token) Authentication token for state storage server. Required for Atlas backend, optional for Consul.]' \
1667+        '-backend=[(atlas) Specifies the type of remote backend. Must be one of Atlas, Consul, or HTTP. Defaults to atlas.]' \
1668+        '-name=[(name) Name of the state file in the state storage server. Required for Atlas backend.]' \
1669+        '-path=[(path) Path of the remote state in Consul. Required for the Consul backend.]'
1670+}
1671+
1672+__output() {
1673+    _arguments \
1674+        '-state=[(path) Path to the state file to read. Defaults to "terraform.tfstate".]' \
1675+        '-module=[(module_name) The module path which has needed output. By default this is the root path. Other modules can be specified by a period-separated list.]'
1676+}
1677+
1678+__plan() {
1679+    _arguments \
1680+        '-backup=[(path) Path to backup the existing state file before modifying. Defaults to the "-state-out" path with" .backup" extension. Set to "-" to disable backup.]' \
1681+        '-destroy[If set, a plan will be generated to destroy all resources managed by the given configuration and state.]' \
1682+        '-detailed-exitcode[Return a detailed exit code when the command exits. When provided, this argument changes the exit codes and their meanings to provide more granular information about what the resulting plan contains]' \
1683+        '-input=[(true) Ask for input for variables if not directly set.]' \
1684+        '-module-depth=[(n) Specifies the depth of modules to show in the output. This does not affect the plan itself, only the output shown. By default, this is zero. -1 will expand all.]' \
1685+        '-no-color[If specified, output will not contain any color.]' \
1686+        '-out=[(path) Write a plan file to the given path. This can be used as input to the "apply" command.]' \
1687+        '-refresh=[(true) Update state prior to checking for differences.]' \
1688+        '-state=[(statefile) Path to a Terraform state file to use to look up Terraform-managed resources. By default it will use the state "terraform.tfstate" if it exists.]' \
1689+        '-target=[(resource) A Resource Address to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]' \
1690+        '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \
1691+        '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]'
1692+}
1693+
1694+__push() {
1695+    _arguments \
1696+        '-atlas-address=[(url) An alternate address to an Atlas instance. Defaults to https://atlas.hashicorp.com.]' \
1697+        '-upload-modules=[(true) If true (default), then the modules being used are all locked at their current checkout and uploaded completely to Atlas. This prevents Atlas from running terraform get for you.]' \
1698diff --git a/plugins/thefuck/README.md b/plugins/thefuck/README.md
1699new file mode 100644
1700index 0000000000000000000000000000000000000000..a9b7550d7f3e88dfc6ac2b6acb2b2febb21a9350
1701--- /dev/null
1702+++ b/plugins/thefuck/README.md
1703@@ -0,0 +1,9 @@
1704+# The Fuck
1705+
1706+[The Fuck](https://github.com/nvbn/thefuck) plugin — magnificent app which corrects your previous console command.
1707+
1708+## Usage
1709+Press `ESC` twice to correct previous console command.
1710+
1711+## Notes
1712+`Esc`-`Esc` key binding conflicts with [sudo](https://github.com/robbyrussell/oh-my-zsh/tree/master/plugins/sudo) plugin.
1713diff --git a/plugins/thefuck/thefuck.plugin.zsh b/plugins/thefuck/thefuck.plugin.zsh
1714new file mode 100644
1715index 0000000000000000000000000000000000000000..8b1746e85494bea866b21aca4dd12539e8e23e23
1716--- /dev/null
1717+++ b/plugins/thefuck/thefuck.plugin.zsh
1718@@ -0,0 +1,17 @@
1719+if [[ -z $commands[thefuck] ]]; then
1720+    echo 'thefuck is not installed, you should "pip install thefuck" first'
1721+    return -1
1722+fi
1723+
1724+# Register alias
1725+eval "$(thefuck-alias)"
1726+
1727+fuck-command-line() {
1728+    local FUCK="$(THEFUCK_REQUIRE_CONFIRMATION=0 thefuck $(fc -ln -1 | tail -n 1) 2> /dev/null)"
1729+    [[ -z $FUCK ]] && echo -n -e "\a" && return
1730+    BUFFER=$FUCK
1731+    zle end-of-line
1732+}
1733+zle -N fuck-command-line
1734+# Defined shortcut keys: [Esc] [Esc]
1735+bindkey "\e\e" fuck-command-line
1736diff --git a/plugins/ubuntu/ubuntu.plugin.zsh b/plugins/ubuntu/ubuntu.plugin.zsh
1737index 0211d33742577092cf8902b4e83cb0761d9d7433..f08853643b514df132496a90777a033cf1924d6b 100644
1738--- a/plugins/ubuntu/ubuntu.plugin.zsh
1739+++ b/plugins/ubuntu/ubuntu.plugin.zsh
1740@@ -3,6 +3,7 @@
1741 # https://github.com/dbb
1742 # https://github.com/Mappleconfusers
1743 # Nicolas Jonas nextgenthemes.com
1744+# https://github.com/loctauxphilippe
1745 #
1746 # Debian, Ubuntu and friends related zsh aliases and functions for zsh
1747 
1748@@ -28,6 +29,7 @@ compdef _ppap ppap='sudo ppa-purge'
1749 
1750 alias ag='sudo apt-get'            # age - but without sudo
1751 alias aga='sudo apt-get autoclean' # aac
1752+alias agar='sudo apt-get autoremove'
1753 alias agb='sudo apt-get build-dep' # abd
1754 alias agc='sudo apt-get clean'     # adc
1755 alias agd='sudo apt-get dselect-upgrade' # ads
1756@@ -38,9 +40,11 @@ alias agu='sudo apt-get update'   # ad
1757 alias agud='sudo apt-get update && sudo apt-get dist-upgrade' #adu
1758 alias agug='sudo apt-get upgrade' # ag
1759 alias aguu='sudo apt-get update && sudo apt-get upgrade'      #adg
1760+alias agar='sudo apt-get autoremove'
1761 
1762 compdef _ag ag='sudo apt-get'
1763 compdef _aga aga='sudo apt-get autoclean'
1764+compdef _agar agar='sudo apt-get autoremove'
1765 compdef _agb agb='sudo apt-get build-dep'
1766 compdef _agc agc='sudo apt-get clean'
1767 compdef _agd agd='sudo apt-get dselect-upgrade'
1768@@ -51,6 +55,7 @@ compdef _agu agu='sudo apt-get update'
1769 compdef _agud agud='sudo apt-get update && sudo apt-get dist-upgrade'
1770 compdef _agug agug='sudo apt-get upgrade'
1771 compdef _aguu aguu='sudo apt-get update && sudo apt-get upgrade'
1772+compdef _agar agar='sudo apt-get autoremove'
1773 
1774 # Remove ALL kernel images and headers EXCEPT the one in use
1775 alias kclean='sudo aptitude remove -P ?and(~i~nlinux-(ima|hea) \
1776@@ -65,7 +70,7 @@ alias mydeb='time dpkg-buildpackage -rfakeroot -us -uc'
1777 
1778 # apt-add-repository with automatic install/upgrade of the desired package
1779 # Usage: aar ppa:xxxxxx/xxxxxx [packagename]
1780-# If packagename is not given as 2nd arument the function will ask for it and guess the defaupt by taking
1781+# If packagename is not given as 2nd argument the function will ask for it and guess the default by taking
1782 # the part after the / from the ppa name wich is sometimes the right name for the package you want to install
1783 aar() {
1784 	if [ -n "$2" ]; then
1785diff --git a/plugins/virtualenvwrapper/virtualenvwrapper.plugin.zsh b/plugins/virtualenvwrapper/virtualenvwrapper.plugin.zsh
1786index f5f37ff6f573a2f8303ac7498d9b96d46a2b6b80..6cd30732e7be10398f7c747b478e098713785084 100644
1787--- a/plugins/virtualenvwrapper/virtualenvwrapper.plugin.zsh
1788+++ b/plugins/virtualenvwrapper/virtualenvwrapper.plugin.zsh
1789@@ -14,32 +14,38 @@ elif [[ -f "/etc/bash_completion.d/virtualenvwrapper" ]]; then
1790     source "/etc/bash_completion.d/virtualenvwrapper"
1791   }
1792 else
1793-  print "zsh virtualenvwrapper plugin: Cannot find ${virtualenvwrapper}.\n"\
1794+  print "[oh-my-zsh] virtualenvwrapper plugin: Cannot find ${virtualenvwrapper}.\n"\
1795         "Please install with \`pip install virtualenvwrapper\`" >&2
1796   return
1797 fi
1798 if ! type workon &>/dev/null; then
1799-  print "zsh virtualenvwrapper plugin: shell function 'workon' not defined.\n"\
1800+  print "[oh-my-zsh] virtualenvwrapper plugin: shell function 'workon' not defined.\n"\
1801         "Please check ${virtualenvwrapper}" >&2
1802   return
1803 fi
1804 
1805 if [[ "$WORKON_HOME" == "" ]]; then
1806-  print "\$WORKON_HOME is not defined so ZSH plugin virtualenvwrapper will not work" >&2
1807+  print "[oh-my-zsh] \$WORKON_HOME is not defined so plugin virtualenvwrapper will not work" >&2
1808   return
1809 fi
1810 
1811 if [[ ! $DISABLE_VENV_CD -eq 1 ]]; then
1812-  # Automatically activate Git projects' virtual environments based on the
1813+  # Automatically activate Git projects or other customized virtualenvwrapper projects based on the
1814   # directory name of the project. Virtual environment name can be overridden
1815-  # by placing a .venv file in the project root with a virtualenv name in it
1816+  # by placing a .venv file in the project root with a virtualenv name in it.
1817   function workon_cwd {
1818-    if [ ! $WORKON_CWD ]; then
1819-      WORKON_CWD=1
1820+    if [[ -z "$WORKON_CWD" ]]; then
1821+      local WORKON_CWD=1
1822       # Check if this is a Git repo
1823+      local GIT_REPO_ROOT=""
1824+      local GIT_TOPLEVEL="$(git rev-parse --show-toplevel 2> /dev/null)"
1825+      if [[ $? == 0 ]]; then
1826+        GIT_REPO_ROOT="$GIT_TOPLEVEL"
1827+      fi
1828       # Get absolute path, resolving symlinks
1829-      PROJECT_ROOT="${PWD:A}"
1830-      while [[ "$PROJECT_ROOT" != "/" && ! -e "$PROJECT_ROOT/.venv" ]]; do
1831+      local PROJECT_ROOT="${PWD:A}"
1832+      while [[ "$PROJECT_ROOT" != "/" && ! -e "$PROJECT_ROOT/.venv" \
1833+               && ! -d "$PROJECT_ROOT/.git"  && "$PROJECT_ROOT" != "$GIT_REPO_ROOT" ]]; do
1834         PROJECT_ROOT="${PROJECT_ROOT:h}"
1835       done
1836       if [[ "$PROJECT_ROOT" == "/" ]]; then
1837@@ -47,7 +53,7 @@ if [[ ! $DISABLE_VENV_CD -eq 1 ]]; then
1838       fi
1839       # Check for virtualenv name override
1840       if [[ -f "$PROJECT_ROOT/.venv" ]]; then
1841-        ENV_NAME=`cat "$PROJECT_ROOT/.venv"`
1842+        ENV_NAME="$(cat "$PROJECT_ROOT/.venv")"
1843       elif [[ -f "$PROJECT_ROOT/.venv/bin/activate" ]];then
1844         ENV_NAME="$PROJECT_ROOT/.venv"
1845       elif [[ "$PROJECT_ROOT" != "." ]]; then
1846@@ -69,8 +75,6 @@ if [[ ! $DISABLE_VENV_CD -eq 1 ]]; then
1847         # Note: this only happens if the virtualenv was activated automatically
1848         deactivate && unset CD_VIRTUAL_ENV
1849       fi
1850-      unset PROJECT_ROOT
1851-      unset WORKON_CWD
1852     fi
1853   }
1854 
1855diff --git a/plugins/vundle/vundle.plugin.zsh b/plugins/vundle/vundle.plugin.zsh
1856index b5f1c0bbf43eca29d9c6193836c06ab153e50e6c..fa1911477b14cc0a65f8765b8ac6c23460fba0b4 100644
1857--- a/plugins/vundle/vundle.plugin.zsh
1858+++ b/plugins/vundle/vundle.plugin.zsh
1859@@ -13,15 +13,15 @@ function vundle-init () {
1860 
1861 function vundle () {
1862   vundle-init
1863-  vim -c "execute \"PluginInstall\" | q | q"
1864+  vim -c "execute \"PluginInstall\" | qa"
1865 }
1866 
1867 function vundle-update () {
1868   vundle-init
1869-  vim -c "execute \"PluginInstall!\" | q | q"
1870+  vim -c "execute \"PluginInstall!\" | qa"
1871 }
1872 
1873 function vundle-clean () {
1874   vundle-init
1875-  vim -c "execute \"PluginClean!\" | q | q"
1876+  vim -c "execute \"PluginClean!\" | qa"
1877 }