From 7b9e48992fa82a72587e451018926e2607172e95 Mon Sep 17 00:00:00 2001 From: Evgeny Golubev Date: Fri, 17 Jan 2014 12:59:14 +0300 Subject: [PATCH 1/9] Add Laravel4 plugin --- plugins/laravel4/laravel4.plugin.zsh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 plugins/laravel4/laravel4.plugin.zsh diff --git a/plugins/laravel4/laravel4.plugin.zsh b/plugins/laravel4/laravel4.plugin.zsh new file mode 100644 index 000000000..4b1022b66 --- /dev/null +++ b/plugins/laravel4/laravel4.plugin.zsh @@ -0,0 +1,20 @@ +# Laravel4 basic command completion +_laravel4_get_command_list () { + php artisan --no-ansi | sed "1,/Available commands/d" | awk '/^ [a-z]+/ { print $1 }' +} + +_laravel4 () { + if [ -f artisan ]; then + compadd `_laravel4_get_command_list` + fi +} + +compdef _laravel4 artisan +compdef _laravel4 la4 + +#Alias +alias la4='php artisan' + +alias la4dump='php artisan dump-autoload' +alias la4cache='php artisan cache:clear' +alias la4routes='php artisan routes' From ed19ffee5ecc0db6617c1ae753e515d60cb486c6 Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Sat, 8 Feb 2014 19:49:54 -0500 Subject: [PATCH 2/9] Add scd plugin for smart change of directory. Synced with the scd-tracker branch pavoljuhas/oh-my-zsh@9d04d8ca78030d4c9af4bf0f58b49532a6ef1b35 --- plugins/scd/README.md | 123 +++++++++++++ plugins/scd/scd | 350 +++++++++++++++++++++++++++++++++++++ plugins/scd/scd.plugin.zsh | 19 ++ 3 files changed, 492 insertions(+) create mode 100644 plugins/scd/README.md create mode 100755 plugins/scd/scd create mode 100644 plugins/scd/scd.plugin.zsh diff --git a/plugins/scd/README.md b/plugins/scd/README.md new file mode 100644 index 000000000..ea7c72464 --- /dev/null +++ b/plugins/scd/README.md @@ -0,0 +1,123 @@ +# scd - smart change of directory + +Define `scd` shell function for changing to any directory with +a few keystrokes. + +`scd` keeps history of the visited directories, which serves as an index of +the known paths. The directory index is updated after every `cd` command in +the shell and can be also filled manually by running `scd -a`. To switch to +some directory, `scd` needs few fragments of the desired path to match with +the index. A selection menu is displayed in case of several matches, with a +preference given to recently visited paths. `scd` can create permanent +directory aliases, which appear as named directories in zsh session. + +## INSTALLATION + +For oh-my-zsh, add `scd` to the `plugins` array in the ~/.zshrc file as in the +[template file](../../templates/zshrc.zsh-template#L45). + +Besides zsh, `scd` can be used with *bash*, *dash* or *tcsh* +shells and is also available as [Vim](http://www.vim.org/) plugin and +[IPython](http://ipython.org/) extension. For installation details, see +https://github.com/pavoljuhas/smart-change-directory. + +## SYNOPSIS + +```sh +scd [options] [pattern1 pattern2 ...] +``` + +## OPTIONS + +
+-a, --add
+ add specified directories to the directory index.
+ +--unindex
+ remove specified directories from the index.
+ +-r, --recursive
+ apply options --add or --unindex recursively.
+ +--alias=ALIAS
+ create alias for the current or specified directory and save it to + ~/.scdalias.zsh.
+ +--unalias
+ remove ALIAS definition for the current or specified directory from + ~/.scdalias.zsh.
+ +--list
+ show matching directories and exit.
+ +-v, --verbose
+ display directory rank in the selection menu.
+ +-h, --help
+ display this options summary and exit.
+
+ +## Examples + +```sh +# Index recursively some paths for the very first run +scd -ar ~/Documents/ + +# Change to a directory path matching "doc" +scd doc + +# Change to a path matching all of "a", "b" and "c" +scd a b c + +# Change to a directory path that ends with "ts" +scd "ts(#e)" + +# Show selection menu and ranking of 20 most likely directories +scd -v + +# Alias current directory as "xray" +scd --alias=xray + +# Jump to a previously defined aliased directory +scd xray +``` + +# FILES + +
+~/.scdhistory
+ time-stamped index of visited directories.
+ +~/.scdalias.zsh
+ scd-generated definitions of directory aliases.
+
+ +# ENVIRONMENT + +
+SCD_HISTFILE
+ path to the scd index file (by default ~/.scdhistory).
+ +SCD_HISTSIZE
+ maximum number of entries in the index (5000). Index is trimmed when it + exceeds SCD_HISTSIZE by more than 20%.
+ +SCD_MENUSIZE
+ maximum number of items for directory selection menu (20).
+ +SCD_MEANLIFE
+ mean lifetime in seconds for exponential decay of directory + likelihood (86400).
+ +SCD_THRESHOLD
+ threshold for cumulative directory likelihood. Directories with + lower likelihood are excluded unless they are the only match to + scd patterns. +
+ +SCD_SCRIPT
+ command script file where scd writes the final cd + command. This variable must be defined when scd runs in its own + process rather than as a shell function. It is up to the + scd caller to use the output in SCD_SCRIPT.
+
diff --git a/plugins/scd/scd b/plugins/scd/scd new file mode 100755 index 000000000..9e055eadd --- /dev/null +++ b/plugins/scd/scd @@ -0,0 +1,350 @@ +#!/bin/zsh -f + +emulate -L zsh +if [[ $(whence -w $0) == *:' 'command ]]; then + emulate -R zsh + alias return=exit + local RUNNING_AS_COMMAND=1 +fi + +local DOC='scd -- smart change to a recently used directory +usage: scd [options] [pattern1 pattern2 ...] +Go to a directory path that contains all fixed string patterns. Prefer +recently visited directories and directories with patterns in their tail +component. Display a selection menu in case of multiple matches. + +Options: + -a, --add add specified directories to the directory index + --unindex remove specified directories from the index + -r, --recursive apply options --add or --unindex recursively + --alias=ALIAS create alias for the current or specified directory and + store it in ~/.scdalias.zsh + --unalias remove ALIAS definition for the current or specified + directory from ~/.scdalias.zsh + --list show matching directories and exit + -v, --verbose display directory rank in the selection menu + -h, --help display this message and exit +' + +local SCD_HISTFILE=${SCD_HISTFILE:-${HOME}/.scdhistory} +local SCD_HISTSIZE=${SCD_HISTSIZE:-5000} +local SCD_MENUSIZE=${SCD_MENUSIZE:-20} +local SCD_MEANLIFE=${SCD_MEANLIFE:-86400} +local SCD_THRESHOLD=${SCD_THRESHOLD:-0.005} +local SCD_SCRIPT=${RUNNING_AS_COMMAND:+$SCD_SCRIPT} +local SCD_ALIAS=~/.scdalias.zsh + +local ICASE a d m p i tdir maxrank threshold +local opt_help opt_add opt_unindex opt_recursive opt_verbose +local opt_alias opt_unalias opt_list +local -A drank dalias dkey +local dmatching + +setopt extendedhistory extendedglob noautonamedirs brace_ccl + +# If SCD_SCRIPT is defined make sure the file exists and is empty. +# This removes any previous old commands. +[[ -n "$SCD_SCRIPT" ]] && [[ -s $SCD_SCRIPT || ! -f $SCD_SCRIPT ]] && ( + umask 077 + : >| $SCD_SCRIPT +) + +# process command line options +zmodload -i zsh/zutil +zmodload -i zsh/datetime +zparseopts -D -- a=opt_add -add=opt_add -unindex=opt_unindex \ + r=opt_recursive -recursive=opt_recursive \ + -alias:=opt_alias -unalias=opt_unalias -list=opt_list \ + v=opt_verbose -verbose=opt_verbose h=opt_help -help=opt_help \ + || return $? + +if [[ -n $opt_help ]]; then + print $DOC + return +fi + +# load directory aliases if they exist +[[ -r $SCD_ALIAS ]] && source $SCD_ALIAS + +# works faster than the (:a) modifier and is compatible with zsh 4.2.6 +_scd_Y19oug_abspath() { + set -A $1 ${(ps:\0:)"$( + unfunction -m "*"; shift + for d; do + cd $d && print -Nr -- $PWD && cd $OLDPWD + done + )"} +} + +# define directory alias +if [[ -n $opt_alias ]]; then + if [[ -n $1 && ! -d $1 ]]; then + print -u2 "'$1' is not a directory" + return 1 + fi + a=${opt_alias[-1]#=} + _scd_Y19oug_abspath d ${1:-$PWD} + # alias in the current shell, update alias file if successful + hash -d -- $a=$d && + ( + umask 077 + hash -dr + [[ -r $SCD_ALIAS ]] && source $SCD_ALIAS + hash -d -- $a=$d + hash -dL >| $SCD_ALIAS + ) + return $? +fi + +# undefine directory alias +if [[ -n $opt_unalias ]]; then + if [[ -n $1 && ! -d $1 ]]; then + print -u2 "'$1' is not a directory" + return 1 + fi + _scd_Y19oug_abspath a ${1:-$PWD} + a=$(print -rD ${a}) + if [[ $a != [~][^/]## ]]; then + return + fi + a=${a#[~]} + # unalias in the current shell, update alias file if successful + if unhash -d -- $a 2>/dev/null && [[ -r $SCD_ALIAS ]]; then + ( + umask 077 + hash -dr + source $SCD_ALIAS + unhash -d -- $a 2>/dev/null && + hash -dL >| $SCD_ALIAS + ) + fi + return $? +fi + +# Rewrite the history file if it is at least 20% oversized +if [[ -s $SCD_HISTFILE ]] && \ +(( $(wc -l <$SCD_HISTFILE) > 1.2 * $SCD_HISTSIZE )); then + m=( ${(f)"$(<$SCD_HISTFILE)"} ) + print -lr -- ${m[-$SCD_HISTSIZE,-1]} >| ${SCD_HISTFILE} +fi + +# Internal functions are prefixed with "_scd_Y19oug_". +# The "record" function adds a non-repeating directory to the history +# and turns on history writing. +_scd_Y19oug_record() { + while [[ -n $1 && $1 == ${history[$HISTCMD]} ]]; do + shift + done + if [[ $# != 0 ]]; then + ( umask 077; : >>| $SCD_HISTFILE ) + p=": ${EPOCHSECONDS}:0;" + print -lr -- ${p}${^*} >> $SCD_HISTFILE + fi +} + +if [[ -n $opt_add ]]; then + for a; do + if [[ ! -d $a ]]; then + print -u 2 "Directory $a does not exist" + return 2 + fi + done + _scd_Y19oug_abspath m ${*:-$PWD} + _scd_Y19oug_record $m + if [[ -n $opt_recursive ]]; then + for d in $m; do + print -n "scanning ${d} ... " + _scd_Y19oug_record ${d}/**/*(-/N) + print "[done]" + done + fi + return +fi + +# take care of removing entries from the directory index +if [[ -n $opt_unindex ]]; then + if [[ ! -s $SCD_HISTFILE ]]; then + return + fi + # expand existing directories in the argument list + for i in {1..$#}; do + if [[ -d ${argv[i]} ]]; then + _scd_Y19oug_abspath d ${argv[i]} + argv[i]=${d} + fi + done + m="$(awk -v recursive=${opt_recursive} ' + BEGIN { + for (i = 2; i < ARGC; ++i) { + argset[ARGV[i]] = 1; + delete ARGV[i]; + } + } + 1 { + d = $0; sub(/^[^;]*;/, "", d); + if (d in argset) next; + } + recursive { + for (a in argset) { + if (substr(d, 1, length(a) + 1) == a"/") next; + } + } + { print $0 } + ' $SCD_HISTFILE ${*:-$PWD} )" || return $? + : >| ${SCD_HISTFILE} + [[ ${#m} == 0 ]] || print -r -- $m >> ${SCD_HISTFILE} + return +fi + +# The "action" function is called when there is just one target directory. +_scd_Y19oug_action() { + if [[ -n $opt_list ]]; then + for d; do + a=${(k)dalias[(r)${d}]} + print -r -- "# $a" + print -r -- $d + done + elif [[ $# == 1 ]]; then + if [[ -z $SCD_SCRIPT && -n $RUNNING_AS_COMMAND ]]; then + print -u2 "Warning: running as command with SCD_SCRIPT undefined." + fi + [[ -n $SCD_SCRIPT ]] && (umask 077; + print -r "cd ${(q)1}" >| $SCD_SCRIPT) + [[ -N $SCD_HISTFILE ]] && touch -a $SCD_HISTFILE + cd $1 + # record the new directory unless already done in some chpwd hook + [[ -N $SCD_HISTFILE ]] || _scd_Y19oug_record $PWD + fi +} + +# handle different argument scenarios ---------------------------------------- + +## single argument that is an existing directory +if [[ $# == 1 && -d $1 && -x $1 ]]; then + _scd_Y19oug_action $1 + return $? +## single argument that is an alias +elif [[ $# == 1 && -d ${d::=${nameddirs[$1]}} ]]; then + _scd_Y19oug_action $d + return $? +fi + +# ignore case unless there is an argument with an uppercase letter +[[ "$*" == *[[:upper:]]* ]] || ICASE='(#i)' + +# calculate rank of all directories in the SCD_HISTFILE and keep it as drank +# include a dummy entry for splitting of an empty string is buggy +[[ -s $SCD_HISTFILE ]] && drank=( ${(f)"$( + print -l /dev/null -10 + <$SCD_HISTFILE \ + awk -v epochseconds=$EPOCHSECONDS -v meanlife=$SCD_MEANLIFE ' + BEGIN { FS = "[:;]"; } + length($0) < 4096 && $2 > 0 { + tau = 1.0 * ($2 - epochseconds) / meanlife; + if (tau < -4.61) tau = -4.61; + prec = exp(tau); + sub(/^[^;]*;/, ""); + if (NF) ptot[$0] += prec; + } + END { for (di in ptot) { print di; print ptot[di]; } }' + )"} +) +unset "drank[/dev/null]" + +# filter drank to the entries that match all arguments +for a; do + p=${ICASE}"*${a}*" + drank=( ${(kv)drank[(I)${~p}]} ) +done + +# build a list of matching directories reverse-sorted by their probabilities +dmatching=( ${(f)"$( + for d p in ${(kv)drank}; do + print -r -- "$p $d"; + done | sort -grk1 | cut -d ' ' -f 2- + )"} +) + +# if some directory paths match all patterns in order, discard all others +p=${ICASE}"*${(j:*:)argv}*" +m=( ${(M)dmatching:#${~p}} ) +[[ -d ${m[1]} ]] && dmatching=( $m ) +# if some directory names match last pattern, discard all others +p=${ICASE}"*${(j:*:)argv}[^/]#" +m=( ${(M)dmatching:#${~p}} ) +[[ -d ${m[1]} ]] && dmatching=( $m ) +# if some directory names match all patterns, discard all others +m=( $dmatching ) +for a; do + p=${ICASE}"*/[^/]#${a}[^/]#" + m=( ${(M)m:#${~p}} ) +done +[[ -d ${m[1]} ]] && dmatching=( $m ) +# if some directory names match all patterns in order, discard all others +p=${ICASE}"/*${(j:[^/]#:)argv}[^/]#" +m=( ${(M)dmatching:#${~p}} ) +[[ -d ${m[1]} ]] && dmatching=( $m ) + +# do not match $HOME or $PWD when run without arguments +if [[ $# == 0 ]]; then + dmatching=( ${dmatching:#(${HOME}|${PWD})} ) +fi + +# keep at most SCD_MENUSIZE of matching and valid directories +m=( ) +for d in $dmatching; do + [[ ${#m} == $SCD_MENUSIZE ]] && break + [[ -d $d && -x $d ]] && m+=$d +done +dmatching=( $m ) + +# find the maximum rank +maxrank=0.0 +for d in $dmatching; do + [[ ${drank[$d]} -lt maxrank ]] || maxrank=${drank[$d]} +done + +# discard all directories below the rank threshold +threshold=$(( maxrank * SCD_THRESHOLD )) +dmatching=( ${^dmatching}(Ne:'(( ${drank[$REPLY]} >= threshold ))':) ) + +## process whatever directories that remained +case ${#dmatching} in +(0) + print -u2 "no matching directory" + return 1 + ;; +(1) + _scd_Y19oug_action $dmatching + return $? + ;; +(*) + # build a list of strings to be displayed in the selection menu + m=( ${(f)"$(print -lD ${dmatching})"} ) + if [[ -n $opt_verbose ]]; then + for i in {1..${#dmatching}}; do + d=${dmatching[i]} + m[i]=$(printf "%.3g %s" ${drank[$d]} $d) + done + fi + # build a map of string names to actual directory paths + for i in {1..${#m}}; dalias[${m[i]}]=${dmatching[i]} + # opt_list - output matching directories and exit + if [[ -n $opt_list ]]; then + _scd_Y19oug_action ${dmatching} + return + fi + # finally use the selection menu to get the answer + a=( {a-z} {A-Z} ) + p=( ) + for i in {1..${#m}}; do + [[ -n ${a[i]} ]] || break + dkey[${a[i]}]=${dalias[$m[i]]} + p+="${a[i]}) ${m[i]}" + done + print -c -r -- $p + if read -s -k 1 d && [[ -n ${dkey[$d]} ]]; then + _scd_Y19oug_action ${dkey[$d]} + fi + return $? +esac diff --git a/plugins/scd/scd.plugin.zsh b/plugins/scd/scd.plugin.zsh new file mode 100644 index 000000000..0197c53a1 --- /dev/null +++ b/plugins/scd/scd.plugin.zsh @@ -0,0 +1,19 @@ +## The scd script should autoload as a shell function. +autoload scd + + +## If the scd function exists, define a change-directory-hook function +## to record visited directories in the scd index. +if [[ ${+functions[scd]} == 1 ]]; then + scd_chpwd_hook() { scd --add $PWD } + autoload add-zsh-hook + add-zsh-hook chpwd scd_chpwd_hook +fi + + +## Allow scd usage with unquoted wildcard characters such as "*" or "?". +alias scd='noglob scd' + + +## Load the directory aliases created by scd if any. +if [[ -s ~/.scdalias.zsh ]]; then source ~/.scdalias.zsh; fi From 1a029f293541d37e545f4706791ca41ce129600b Mon Sep 17 00:00:00 2001 From: Kevin Bongart Date: Thu, 13 Feb 2014 12:27:00 -0500 Subject: [PATCH 3/9] Add rake-fast plugin for fast rake autocompletion --- plugins/rake-fast/rake-fast.plugin.zsh | 56 ++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 plugins/rake-fast/rake-fast.plugin.zsh diff --git a/plugins/rake-fast/rake-fast.plugin.zsh b/plugins/rake-fast/rake-fast.plugin.zsh new file mode 100644 index 000000000..0c268355e --- /dev/null +++ b/plugins/rake-fast/rake-fast.plugin.zsh @@ -0,0 +1,56 @@ +# rake-fast +# Fast rake autocompletion plugin for oh-my-zsh + +# This script caches the output for later usage and significantly speeds it up. +# It generates a .rake_tasks file in parallel to the Rakefile. + +# You'll want to add `.rake_tasks` to your global .git_ignore file: +# https://help.github.com/articles/ignoring-files#global-gitignore + +# You can force .rake_tasks to refresh with: +# $ rake_refresh + +# This is entirely based on Ullrich Schäfer's work +# (https://github.com/robb/.dotfiles/pull/10/), +# which is inspired by this Ruby on Rails trick from 2006: +# http://weblog.rubyonrails.org/2006/3/9/fast-rake-task-completion-for-zsh/ + +# Author: Kevin Bongart +# contact@kevinbongart.net +# http://kevinbongart.net +# https://github.com/KevinBongart + +_rake_refresh () { + if [ -f .rake_tasks ]; then + rm .rake_tasks + fi + echo "Generating .rake_tasks..." > /dev/stderr + _rake_generate + cat .rake_tasks +} + +_rake_does_task_list_need_generating () { + if [ ! -f .rake_tasks ]; then return 0; + else + accurate=$(stat -f%m .rake_tasks) + changed=$(stat -f%m Rakefile) + return $(expr $accurate '>=' $changed) + fi +} + +_rake_generate () { + rake --silent --tasks | cut -d " " -f 2 > .rake_tasks +} + +_rake () { + if [ -f Rakefile ]; then + if _rake_does_task_list_need_generating; then + echo "\nGenerating .rake_tasks..." > /dev/stderr + _rake_generate + fi + compadd `cat .rake_tasks` + fi +} + +compdef _rake rake +alias rake_refresh='_rake_refresh' From baeac5bec9cc9b2da5ac69054d91ae3838fde402 Mon Sep 17 00:00:00 2001 From: Kevin Bongart Date: Sun, 16 Mar 2014 16:52:37 -0400 Subject: [PATCH 4/9] Remove copyright information, as per #2588 --- plugins/rake-fast/rake-fast.plugin.zsh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/rake-fast/rake-fast.plugin.zsh b/plugins/rake-fast/rake-fast.plugin.zsh index 0c268355e..320855233 100644 --- a/plugins/rake-fast/rake-fast.plugin.zsh +++ b/plugins/rake-fast/rake-fast.plugin.zsh @@ -15,11 +15,6 @@ # which is inspired by this Ruby on Rails trick from 2006: # http://weblog.rubyonrails.org/2006/3/9/fast-rake-task-completion-for-zsh/ -# Author: Kevin Bongart -# contact@kevinbongart.net -# http://kevinbongart.net -# https://github.com/KevinBongart - _rake_refresh () { if [ -f .rake_tasks ]; then rm .rake_tasks From c1c107cfb9669beeda258efed9a17cc4bddf7aa7 Mon Sep 17 00:00:00 2001 From: Pavol Juhas Date: Mon, 17 Mar 2014 19:49:12 -0400 Subject: [PATCH 5/9] Add scd plugin for smart change of directory. Synced with the scd-tracker branch pavoljuhas/oh-my-zsh@2f78243cad3509058d142aa4b70a604e75ec741e. --- plugins/scd/README.md | 3 +- plugins/scd/scd | 343 +++++++++++++++++++++--------------------- 2 files changed, 174 insertions(+), 172 deletions(-) diff --git a/plugins/scd/README.md b/plugins/scd/README.md index ea7c72464..197cea50a 100644 --- a/plugins/scd/README.md +++ b/plugins/scd/README.md @@ -111,8 +111,7 @@ SCD_MEANLIFE
SCD_THRESHOLD
threshold for cumulative directory likelihood. Directories with - lower likelihood are excluded unless they are the only match to - scd patterns. + a lower likelihood compared to the best match are excluded (0.005).
SCD_SCRIPT
diff --git a/plugins/scd/scd b/plugins/scd/scd index 9e055eadd..1567d2736 100755 --- a/plugins/scd/scd +++ b/plugins/scd/scd @@ -1,10 +1,11 @@ #!/bin/zsh -f emulate -L zsh +local EXIT=return if [[ $(whence -w $0) == *:' 'command ]]; then emulate -R zsh - alias return=exit local RUNNING_AS_COMMAND=1 + EXIT=exit fi local DOC='scd -- smart change to a recently used directory @@ -37,8 +38,9 @@ local SCD_ALIAS=~/.scdalias.zsh local ICASE a d m p i tdir maxrank threshold local opt_help opt_add opt_unindex opt_recursive opt_verbose local opt_alias opt_unalias opt_list -local -A drank dalias dkey +local -A drank dalias local dmatching +local last_directory setopt extendedhistory extendedglob noautonamedirs brace_ccl @@ -56,11 +58,11 @@ zparseopts -D -- a=opt_add -add=opt_add -unindex=opt_unindex \ r=opt_recursive -recursive=opt_recursive \ -alias:=opt_alias -unalias=opt_unalias -list=opt_list \ v=opt_verbose -verbose=opt_verbose h=opt_help -help=opt_help \ - || return $? + || $EXIT $? if [[ -n $opt_help ]]; then print $DOC - return + $EXIT fi # load directory aliases if they exist @@ -79,8 +81,8 @@ _scd_Y19oug_abspath() { # define directory alias if [[ -n $opt_alias ]]; then if [[ -n $1 && ! -d $1 ]]; then - print -u2 "'$1' is not a directory" - return 1 + print -u2 "'$1' is not a directory." + $EXIT 1 fi a=${opt_alias[-1]#=} _scd_Y19oug_abspath d ${1:-$PWD} @@ -93,19 +95,19 @@ if [[ -n $opt_alias ]]; then hash -d -- $a=$d hash -dL >| $SCD_ALIAS ) - return $? + $EXIT $? fi # undefine directory alias if [[ -n $opt_unalias ]]; then if [[ -n $1 && ! -d $1 ]]; then - print -u2 "'$1' is not a directory" - return 1 + print -u2 "'$1' is not a directory." + $EXIT 1 fi _scd_Y19oug_abspath a ${1:-$PWD} a=$(print -rD ${a}) if [[ $a != [~][^/]## ]]; then - return + $EXIT fi a=${a#[~]} # unalias in the current shell, update alias file if successful @@ -118,35 +120,39 @@ if [[ -n $opt_unalias ]]; then hash -dL >| $SCD_ALIAS ) fi - return $? + $EXIT $? fi -# Rewrite the history file if it is at least 20% oversized +# Rewrite directory index if it is at least 20% oversized if [[ -s $SCD_HISTFILE ]] && \ (( $(wc -l <$SCD_HISTFILE) > 1.2 * $SCD_HISTSIZE )); then m=( ${(f)"$(<$SCD_HISTFILE)"} ) print -lr -- ${m[-$SCD_HISTSIZE,-1]} >| ${SCD_HISTFILE} fi +# Determine the last recorded directory +if [[ -s ${SCD_HISTFILE} ]]; then + last_directory=${"$(tail -1 ${SCD_HISTFILE})"#*;} +fi + # Internal functions are prefixed with "_scd_Y19oug_". -# The "record" function adds a non-repeating directory to the history -# and turns on history writing. +# The "record" function adds its arguments to the directory index. _scd_Y19oug_record() { - while [[ -n $1 && $1 == ${history[$HISTCMD]} ]]; do + while [[ -n $last_directory && $1 == $last_directory ]]; do shift done - if [[ $# != 0 ]]; then - ( umask 077; : >>| $SCD_HISTFILE ) - p=": ${EPOCHSECONDS}:0;" - print -lr -- ${p}${^*} >> $SCD_HISTFILE + if [[ $# -gt 0 ]]; then + ( umask 077 + p=": ${EPOCHSECONDS}:0;" + print -lr -- ${p}${^*} >>| $SCD_HISTFILE ) fi } if [[ -n $opt_add ]]; then - for a; do - if [[ ! -d $a ]]; then - print -u 2 "Directory $a does not exist" - return 2 + for d; do + if [[ ! -d $d ]]; then + print -u2 "Directory '$d' does not exist." + $EXIT 2 fi done _scd_Y19oug_abspath m ${*:-$PWD} @@ -158,13 +164,13 @@ if [[ -n $opt_add ]]; then print "[done]" done fi - return + $EXIT fi # take care of removing entries from the directory index if [[ -n $opt_unindex ]]; then if [[ ! -s $SCD_HISTFILE ]]; then - return + $EXIT fi # expand existing directories in the argument list for i in {1..$#}; do @@ -190,161 +196,158 @@ if [[ -n $opt_unindex ]]; then } } { print $0 } - ' $SCD_HISTFILE ${*:-$PWD} )" || return $? + ' $SCD_HISTFILE ${*:-$PWD} )" || $EXIT $? : >| ${SCD_HISTFILE} [[ ${#m} == 0 ]] || print -r -- $m >> ${SCD_HISTFILE} - return + $EXIT fi # The "action" function is called when there is just one target directory. _scd_Y19oug_action() { - if [[ -n $opt_list ]]; then - for d; do - a=${(k)dalias[(r)${d}]} - print -r -- "# $a" - print -r -- $d - done - elif [[ $# == 1 ]]; then - if [[ -z $SCD_SCRIPT && -n $RUNNING_AS_COMMAND ]]; then - print -u2 "Warning: running as command with SCD_SCRIPT undefined." - fi - [[ -n $SCD_SCRIPT ]] && (umask 077; - print -r "cd ${(q)1}" >| $SCD_SCRIPT) - [[ -N $SCD_HISTFILE ]] && touch -a $SCD_HISTFILE - cd $1 - # record the new directory unless already done in some chpwd hook - [[ -N $SCD_HISTFILE ]] || _scd_Y19oug_record $PWD + cd $1 || return $? + if [[ -z $SCD_SCRIPT && -n $RUNNING_AS_COMMAND ]]; then + print -u2 "Warning: running as command with SCD_SCRIPT undefined." + fi + if [[ -n $SCD_SCRIPT ]]; then + print -r "cd ${(q)1}" >| $SCD_SCRIPT fi } -# handle different argument scenarios ---------------------------------------- - -## single argument that is an existing directory -if [[ $# == 1 && -d $1 && -x $1 ]]; then - _scd_Y19oug_action $1 - return $? -## single argument that is an alias -elif [[ $# == 1 && -d ${d::=${nameddirs[$1]}} ]]; then - _scd_Y19oug_action $d - return $? -fi - -# ignore case unless there is an argument with an uppercase letter -[[ "$*" == *[[:upper:]]* ]] || ICASE='(#i)' - -# calculate rank of all directories in the SCD_HISTFILE and keep it as drank -# include a dummy entry for splitting of an empty string is buggy -[[ -s $SCD_HISTFILE ]] && drank=( ${(f)"$( - print -l /dev/null -10 - <$SCD_HISTFILE \ - awk -v epochseconds=$EPOCHSECONDS -v meanlife=$SCD_MEANLIFE ' - BEGIN { FS = "[:;]"; } - length($0) < 4096 && $2 > 0 { - tau = 1.0 * ($2 - epochseconds) / meanlife; - if (tau < -4.61) tau = -4.61; - prec = exp(tau); - sub(/^[^;]*;/, ""); - if (NF) ptot[$0] += prec; - } - END { for (di in ptot) { print di; print ptot[di]; } }' - )"} -) -unset "drank[/dev/null]" - -# filter drank to the entries that match all arguments -for a; do - p=${ICASE}"*${a}*" - drank=( ${(kv)drank[(I)${~p}]} ) -done - -# build a list of matching directories reverse-sorted by their probabilities -dmatching=( ${(f)"$( - for d p in ${(kv)drank}; do - print -r -- "$p $d"; - done | sort -grk1 | cut -d ' ' -f 2- - )"} -) - -# if some directory paths match all patterns in order, discard all others -p=${ICASE}"*${(j:*:)argv}*" -m=( ${(M)dmatching:#${~p}} ) -[[ -d ${m[1]} ]] && dmatching=( $m ) -# if some directory names match last pattern, discard all others -p=${ICASE}"*${(j:*:)argv}[^/]#" -m=( ${(M)dmatching:#${~p}} ) -[[ -d ${m[1]} ]] && dmatching=( $m ) -# if some directory names match all patterns, discard all others -m=( $dmatching ) -for a; do - p=${ICASE}"*/[^/]#${a}[^/]#" - m=( ${(M)m:#${~p}} ) -done -[[ -d ${m[1]} ]] && dmatching=( $m ) -# if some directory names match all patterns in order, discard all others -p=${ICASE}"/*${(j:[^/]#:)argv}[^/]#" -m=( ${(M)dmatching:#${~p}} ) -[[ -d ${m[1]} ]] && dmatching=( $m ) - -# do not match $HOME or $PWD when run without arguments -if [[ $# == 0 ]]; then - dmatching=( ${dmatching:#(${HOME}|${PWD})} ) -fi - -# keep at most SCD_MENUSIZE of matching and valid directories -m=( ) -for d in $dmatching; do - [[ ${#m} == $SCD_MENUSIZE ]] && break - [[ -d $d && -x $d ]] && m+=$d -done -dmatching=( $m ) - -# find the maximum rank -maxrank=0.0 -for d in $dmatching; do - [[ ${drank[$d]} -lt maxrank ]] || maxrank=${drank[$d]} -done - -# discard all directories below the rank threshold -threshold=$(( maxrank * SCD_THRESHOLD )) -dmatching=( ${^dmatching}(Ne:'(( ${drank[$REPLY]} >= threshold ))':) ) - -## process whatever directories that remained -case ${#dmatching} in -(0) - print -u2 "no matching directory" - return 1 - ;; -(1) - _scd_Y19oug_action $dmatching - return $? - ;; -(*) - # build a list of strings to be displayed in the selection menu - m=( ${(f)"$(print -lD ${dmatching})"} ) - if [[ -n $opt_verbose ]]; then - for i in {1..${#dmatching}}; do - d=${dmatching[i]} - m[i]=$(printf "%.3g %s" ${drank[$d]} $d) - done - fi - # build a map of string names to actual directory paths - for i in {1..${#m}}; dalias[${m[i]}]=${dmatching[i]} - # opt_list - output matching directories and exit - if [[ -n $opt_list ]]; then - _scd_Y19oug_action ${dmatching} +# Match and rank patterns to the index file +# set global arrays dmatching and drank +_scd_Y19oug_match() { + ## single argument that is an existing directory or directory alias + if [[ $# == 1 ]] && \ + [[ -d ${d::=$1} || -d ${d::=${nameddirs[$1]}} ]] && [[ -x $d ]]; + then + _scd_Y19oug_abspath dmatching $d + drank[${dmatching[1]}]=1 return fi - # finally use the selection menu to get the answer - a=( {a-z} {A-Z} ) - p=( ) - for i in {1..${#m}}; do - [[ -n ${a[i]} ]] || break - dkey[${a[i]}]=${dalias[$m[i]]} - p+="${a[i]}) ${m[i]}" + + # ignore case unless there is an argument with an uppercase letter + [[ "$*" == *[[:upper:]]* ]] || ICASE='(#i)' + + # calculate rank of all directories in the SCD_HISTFILE and keep it as drank + # include a dummy entry for splitting of an empty string is buggy + [[ -s $SCD_HISTFILE ]] && drank=( ${(f)"$( + print -l /dev/null -10 + <$SCD_HISTFILE \ + awk -v epochseconds=$EPOCHSECONDS -v meanlife=$SCD_MEANLIFE ' + BEGIN { FS = "[:;]"; } + length($0) < 4096 && $2 > 0 { + tau = 1.0 * ($2 - epochseconds) / meanlife; + if (tau < -4.61) tau = -4.61; + prec = exp(tau); + sub(/^[^;]*;/, ""); + if (NF) ptot[$0] += prec; + } + END { for (di in ptot) { print di; print ptot[di]; } }' + )"} + ) + unset "drank[/dev/null]" + + # filter drank to the entries that match all arguments + for a; do + p=${ICASE}"*${a}*" + drank=( ${(kv)drank[(I)${~p}]} ) done - print -c -r -- $p - if read -s -k 1 d && [[ -n ${dkey[$d]} ]]; then - _scd_Y19oug_action ${dkey[$d]} + + # build a list of matching directories reverse-sorted by their probabilities + dmatching=( ${(f)"$( + for d p in ${(kv)drank}; do + print -r -- "$p $d"; + done | sort -grk1 | cut -d ' ' -f 2- + )"} + ) + + # if some directory paths match all patterns in order, discard all others + p=${ICASE}"*${(j:*:)argv}*" + m=( ${(M)dmatching:#${~p}} ) + [[ -d ${m[1]} ]] && dmatching=( $m ) + # if some directory names match last pattern, discard all others + p=${ICASE}"*${(j:*:)argv}[^/]#" + m=( ${(M)dmatching:#${~p}} ) + [[ -d ${m[1]} ]] && dmatching=( $m ) + # if some directory names match all patterns, discard all others + m=( $dmatching ) + for a; do + p=${ICASE}"*/[^/]#${a}[^/]#" + m=( ${(M)m:#${~p}} ) + done + [[ -d ${m[1]} ]] && dmatching=( $m ) + # if some directory names match all patterns in order, discard all others + p=${ICASE}"/*${(j:[^/]#:)argv}[^/]#" + m=( ${(M)dmatching:#${~p}} ) + [[ -d ${m[1]} ]] && dmatching=( $m ) + + # do not match $HOME or $PWD when run without arguments + if [[ $# == 0 ]]; then + dmatching=( ${dmatching:#(${HOME}|${PWD})} ) fi - return $? -esac + + # keep at most SCD_MENUSIZE of matching and valid directories + m=( ) + for d in $dmatching; do + [[ ${#m} == $SCD_MENUSIZE ]] && break + [[ -d $d && -x $d ]] && m+=$d + done + dmatching=( $m ) + + # find the maximum rank + maxrank=0.0 + for d in $dmatching; do + [[ ${drank[$d]} -lt maxrank ]] || maxrank=${drank[$d]} + done + + # discard all directories below the rank threshold + threshold=$(( maxrank * SCD_THRESHOLD )) + dmatching=( ${^dmatching}(Ne:'(( ${drank[$REPLY]} >= threshold ))':) ) +} + +_scd_Y19oug_match $* + +## process whatever directories that remained +if [[ ${#dmatching} == 0 ]]; then + print -u2 "No matching directory." + $EXIT 1 +fi + +## build formatted directory aliases for selection menu or list display +for d in $dmatching; do + if [[ -n ${opt_verbose} ]]; then + dalias[$d]=$(printf "%.3g %s" ${drank[$d]} $d) + else + dalias[$d]=$(print -Dr -- $d) + fi +done + +## process the --list option +if [[ -n $opt_list ]]; then + for d in $dmatching; do + print -r -- "# ${dalias[$d]}" + print -r -- $d + done + $EXIT +fi + +## process single directory match +if [[ ${#dmatching} == 1 ]]; then + _scd_Y19oug_action $dmatching + $EXIT $? +fi + +## here we have multiple matches - display selection menu +a=( {a-z} {A-Z} ) +p=( ) +for i in {1..${#dmatching}}; do + [[ -n ${a[i]} ]] || break + p+="${a[i]}) ${dalias[${dmatching[i]}]}" +done + +print -c -r -- $p + +if read -s -k 1 d && [[ ${i::=${a[(I)$d]}} -gt 0 ]]; then + _scd_Y19oug_action ${dmatching[i]} + $EXIT $? +fi From 645fceb38b091e1dd5c9804a444730a9837bae07 Mon Sep 17 00:00:00 2001 From: Johan Svensson Date: Tue, 18 Mar 2014 10:52:25 +0100 Subject: [PATCH 6/9] Add chef-vault knife cmd support --- plugins/knife/_knife | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/knife/_knife b/plugins/knife/_knife index b44283f78..163149267 100644 --- a/plugins/knife/_knife +++ b/plugins/knife/_knife @@ -31,7 +31,7 @@ _knife() { case $state in knifecmd) - compadd -Q "$@" bootstrap client configure cookbook "cookbook site" "data bag" diff exec environment index node recipe role search ssh status upload windows $cloudproviders + compadd -Q "$@" bootstrap client configure cookbook "cookbook site" "data bag" diff exec environment index node recipe role search ssh status upload vault windows $cloudproviders ;; knifesubcmd) case $words[2] in @@ -65,6 +65,9 @@ _knife() { upload) _arguments '*:file or directory:_files -g "*"' ;; + vault) + compadd -Q "$@" create decrypt delete edit remove "rotate all keys" "rotate keys" show update + ;; windows) compadd "$@" bootstrap ;; From ef343eef307cf8d329240dcdf5e973f1d18d410e Mon Sep 17 00:00:00 2001 From: Antoine Dechaume Date: Thu, 20 Mar 2014 10:43:33 +0100 Subject: [PATCH 7/9] Fix dirpersist plugin This plugin did not work, I just found the same functionnality in grml, this one works. --- plugins/dirpersist/dirpersist.plugin.zsh | 52 ++++++++---------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/plugins/dirpersist/dirpersist.plugin.zsh b/plugins/dirpersist/dirpersist.plugin.zsh index 0f6d9f435..88d1129d4 100644 --- a/plugins/dirpersist/dirpersist.plugin.zsh +++ b/plugins/dirpersist/dirpersist.plugin.zsh @@ -1,39 +1,19 @@ -#!/bin/zsh -# -# Make the dirstack more persistant -# -# Add dirpersist to $plugins in ~/.zshrc to load -# +# Save dirstack history to .zdirs +# adapted from: +# github.com/grml/grml-etc-core/blob/master/etc/zsh/zshrc#L1547 -# $zdirstore is the file used to persist the stack -zdirstore=~/.zdirstore +DIRSTACKSIZE=${DIRSTACKSIZE:-20} +dirstack_file=${dirstack_file:-${HOME}/.zdirs} -dirpersistinstall () { - if grep 'dirpersiststore' ~/.zlogout > /dev/null; then - else - if read -q \?"Would you like to set up your .zlogout file for use with dirspersist? (y/n) "; then - echo "# Store dirs stack\n# See $ZSH/plugins/dirspersist.plugin.zsh\ndirpersiststore" >> ~/.zlogout - else - echo "If you don't want this message to appear, remove dirspersist from \$plugins" - fi - fi +if [[ -f ${dirstack_file} ]] && [[ ${#dirstack[*]} -eq 0 ]] ; then + dirstack=( ${(f)"$(< $dirstack_file)"} ) + # "cd -" won't work after login by just setting $OLDPWD, so + [[ -d $dirstack[1] ]] && cd $dirstack[1] && cd $OLDPWD +fi + +chpwd() { + if (( $DIRSTACKSIZE <= 0 )) || [[ -z $dirstack_file ]]; then return; fi + local -ax my_stack + my_stack=( ${PWD} ${dirstack} ) + builtin print -l ${(u)my_stack} >! ${dirstack_file} } - -dirpersiststore () { - dirs -p | perl -e 'foreach (reverse ) {chomp;s/([& ])/\\$1/g ;print "if [ -d $_ ]; then pushd -q $_; fi\n"}' > $zdirstore -} - -dirpersistrestore () { - if [ -f $zdirstore ]; then - source $zdirstore - fi -} - -DIRSTACKSIZE=10 -setopt autopushd pushdminus pushdsilent pushdtohome pushdignoredups - -dirpersistinstall -dirpersistrestore - -# Make popd changes permanent without having to wait for logout -alias popd="popd;dirpersiststore" From 5f31190ab9fd41fd1ffe2b0878674adc02933f9b Mon Sep 17 00:00:00 2001 From: Arno Fortelny Date: Fri, 21 Mar 2014 11:49:52 -0400 Subject: [PATCH 8/9] atom plugin --- plugins/atom/atom.plugin.zsh | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/plugins/atom/atom.plugin.zsh b/plugins/atom/atom.plugin.zsh index 048fd7521..9adb9031a 100644 --- a/plugins/atom/atom.plugin.zsh +++ b/plugins/atom/atom.plugin.zsh @@ -1,4 +1,14 @@ -# -# Your guess is as good as mine. Let's just assume that we will need this... -# - For more info visit... http://atom.io/ -# \ No newline at end of file +local _atom_paths > /dev/null 2>&1 +_atom_paths=( + "$HOME/Applications/Atom.app" + "/Applications/Atom.app" +) + +for _atom_path in $_atom_paths; do + if [[ -a $_atom_path ]]; then + alias at="open -a '$_atom_path'" + break + fi +done + +alias att='at .' From 1509ac9a0414801dbbe45060eae19ae6e6e9841c Mon Sep 17 00:00:00 2001 From: jieryn Date: Sat, 22 Mar 2014 08:51:26 -0400 Subject: [PATCH 9/9] add common video formats FLV and WEBM --- plugins/common-aliases/common-aliases.plugin.zsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/common-aliases/common-aliases.plugin.zsh b/plugins/common-aliases/common-aliases.plugin.zsh index 75899ca2c..b19650fee 100644 --- a/plugins/common-aliases/common-aliases.plugin.zsh +++ b/plugins/common-aliases/common-aliases.plugin.zsh @@ -71,7 +71,7 @@ if [ ${ZSH_VERSION//\./} -ge 420 ]; then _image_fts=(jpg jpeg png gif mng tiff tif xpm) for ft in $_image_fts ; do alias -s $ft=$XIVIEWER; done - _media_fts=(avi mpg mpeg ogm mp3 wav ogg ape rm mov mkv) + _media_fts=(ape avi flv mkv mov mp3 mpeg mpg ogg ogm rm wav webm) for ft in $_media_fts ; do alias -s $ft=mplayer ; done #read documents