summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/compfix.zsh60
-rw-r--r--lib/completion.zsh7
-rw-r--r--lib/functions.zsh148
-rw-r--r--lib/git.zsh51
-rw-r--r--lib/misc.zsh13
-rw-r--r--lib/termsupport.zsh46
-rw-r--r--lib/theme-and-appearance.zsh7
7 files changed, 303 insertions, 29 deletions
diff --git a/lib/compfix.zsh b/lib/compfix.zsh
new file mode 100644
index 000000000..208aaadb1
--- /dev/null
+++ b/lib/compfix.zsh
@@ -0,0 +1,60 @@
+# Handle completions insecurities (i.e., completion-dependent directories with
+# insecure ownership or permissions) by:
+#
+# * Human-readably notifying the user of these insecurities.
+# * Moving away all existing completion caches to a temporary directory. Since
+# any of these caches may have been generated from insecure directories, they
+# are all suspect now. Failing to do so typically causes subsequent compinit()
+# calls to fail with "command not found: compdef" errors. (That's bad.)
+function handle_completion_insecurities() {
+ # List of the absolute paths of all unique insecure directories, split on
+ # newline from compaudit()'s output resembling:
+ #
+ # There are insecure directories:
+ # /usr/share/zsh/site-functions
+ # /usr/share/zsh/5.0.6/functions
+ # /usr/share/zsh
+ # /usr/share/zsh/5.0.6
+ #
+ # Since the ignorable first line is printed to stderr and thus not captured,
+ # stderr is squelched to prevent this output from leaking to the user.
+ local -aU insecure_dirs
+ insecure_dirs=( ${(f@):-"$(compaudit 2>/dev/null)"} )
+
+ # If no such directories exist, get us out of here.
+ if (( ! ${#insecure_dirs} )); then
+ print "[oh-my-zsh] No insecure completion-dependent directories detected."
+ return
+ fi
+
+ # List ownership and permissions of all insecure directories.
+ print "[oh-my-zsh] Insecure completion-dependent directories detected:"
+ ls -ld "${(@)insecure_dirs}"
+ print "[oh-my-zsh] For safety, completions will be disabled until you manually fix all"
+ print "[oh-my-zsh] insecure directory permissions and ownership and restart oh-my-zsh."
+ print "[oh-my-zsh] See the above list for directories with group or other writability.\n"
+
+ # Locally enable the "NULL_GLOB" option, thus removing unmatched filename
+ # globs from argument lists *AND* printing no warning when doing so. Failing
+ # to do so prints an unreadable warning if no completion caches exist below.
+ setopt local_options null_glob
+
+ # List of the absolute paths of all unique existing completion caches.
+ local -aU zcompdump_files
+ zcompdump_files=( "${ZSH_COMPDUMP}"(.) "${ZDOTDIR:-${HOME}}"/.zcompdump* )
+
+ # Move such caches to a temporary directory.
+ if (( ${#zcompdump_files} )); then
+ # Absolute path of the directory to which such files will be moved.
+ local ZSH_ZCOMPDUMP_BAD_DIR="${ZSH_CACHE_DIR}/zcompdump-bad"
+
+ # List such files first.
+ print "[oh-my-zsh] Insecure completion caches also detected:"
+ ls -l "${(@)zcompdump_files}"
+
+ # For safety, move rather than permanently remove such files.
+ print "[oh-my-zsh] Moving to \"${ZSH_ZCOMPDUMP_BAD_DIR}/\"...\n"
+ mkdir -p "${ZSH_ZCOMPDUMP_BAD_DIR}"
+ mv "${(@)zcompdump_files}" "${ZSH_ZCOMPDUMP_BAD_DIR}/"
+ fi
+}
diff --git a/lib/completion.zsh b/lib/completion.zsh
index 4b1bb0a62..452c0dfe7 100644
--- a/lib/completion.zsh
+++ b/lib/completion.zsh
@@ -15,7 +15,12 @@ if [ "x$CASE_SENSITIVE" = "xtrue" ]; then
zstyle ':completion:*' matcher-list 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
unset CASE_SENSITIVE
else
- zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
+ if [ "x$HYPHEN_INSENSITIVE" = "xtrue" ]; then
+ zstyle ':completion:*' matcher-list 'm:{a-zA-Z-_}={A-Za-z_-}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
+ unset HYPHEN_INSENSITIVE
+ else
+ zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
+ fi
fi
zstyle ':completion:*' list-colors ''
diff --git a/lib/functions.zsh b/lib/functions.zsh
index 17f5f9cbf..efb73a1bd 100644
--- a/lib/functions.zsh
+++ b/lib/functions.zsh
@@ -15,6 +15,22 @@ function take() {
cd $1
}
+function open_command() {
+ local open_cmd
+
+ # define the open command
+ case "$OSTYPE" in
+ darwin*) open_cmd="open" ;;
+ cygwin*) open_cmd="cygstart" ;;
+ linux*) open_cmd="xdg-open" ;;
+ *) echo "Platform $OSTYPE not supported"
+ return 1
+ ;;
+ esac
+
+ nohup $open_cmd "$@" &>/dev/null
+}
+
#
# Get the value of an alias.
#
@@ -73,3 +89,135 @@ function env_default() {
env | grep -q "^$1=" && return 0
export "$1=$2" && return 3
}
+
+
+# Required for $langinfo
+zmodload zsh/langinfo
+
+# URL-encode a string
+#
+# Encodes a string using RFC 2396 URL-encoding (%-escaped).
+# See: https://www.ietf.org/rfc/rfc2396.txt
+#
+# By default, reserved characters and unreserved "mark" characters are
+# not escaped by this function. This allows the common usage of passing
+# an entire URL in, and encoding just special characters in it, with
+# the expectation that reserved and mark characters are used appropriately.
+# The -r and -m options turn on escaping of the reserved and mark characters,
+# respectively, which allows arbitrary strings to be fully escaped for
+# embedding inside URLs, where reserved characters might be misinterpreted.
+#
+# Prints the encoded string on stdout.
+# Returns nonzero if encoding failed.
+#
+# Usage:
+# omz_urlencode [-r] [-m] <string>
+#
+# -r causes reserved characters (;/?:@&=+$,) to be escaped
+#
+# -m causes "mark" characters (_.!~*''()-) to be escaped
+#
+# -P causes spaces to be encoded as '%20' instead of '+'
+function omz_urlencode() {
+ emulate -L zsh
+ zparseopts -D -E -a opts r m P
+
+ local in_str=$1
+ local url_str=""
+ local spaces_as_plus
+ if [[ -z $opts[(r)-P] ]]; then spaces_as_plus=1; fi
+ local str="$in_str"
+
+ # URLs must use UTF-8 encoding; convert str to UTF-8 if required
+ local encoding=$langinfo[CODESET]
+ local safe_encodings
+ safe_encodings=(UTF-8 utf8 US-ASCII)
+ if [[ -z ${safe_encodings[(r)$encoding]} ]]; then
+ str=$(echo -E "$str" | iconv -f $encoding -t UTF-8)
+ if [[ $? != 0 ]]; then
+ echo "Error converting string from $encoding to UTF-8" >&2
+ return 1
+ fi
+ fi
+
+ # Use LC_CTYPE=C to process text byte-by-byte
+ local i byte ord LC_ALL=C
+ export LC_ALL
+ local reserved=';/?:@&=+$,'
+ local mark='_.!~*''()-'
+ local dont_escape="[A-Za-z0-9"
+ if [[ -z $opts[(r)-r] ]]; then
+ dont_escape+=$reserved
+ fi
+ # $mark must be last because of the "-"
+ if [[ -z $opts[(r)-m] ]]; then
+ dont_escape+=$mark
+ fi
+ dont_escape+="]"
+
+ # Implemented to use a single printf call and avoid subshells in the loop,
+ # for performance (primarily on Windows).
+ local url_str=""
+ for (( i = 1; i <= ${#str}; ++i )); do
+ byte="$str[i]"
+ if [[ "$byte" =~ "$dont_escape" ]]; then
+ url_str+="$byte"
+ else
+ if [[ "$byte" == " " && -n $spaces_as_plus ]]; then
+ url_str+="+"
+ else
+ ord=$(( [##16] #byte ))
+ url_str+="%$ord"
+ fi
+ fi
+ done
+ echo -E "$url_str"
+}
+
+# URL-decode a string
+#
+# Decodes a RFC 2396 URL-encoded (%-escaped) string.
+# This decodes the '+' and '%' escapes in the input string, and leaves
+# other characters unchanged. Does not enforce that the input is a
+# valid URL-encoded string. This is a convenience to allow callers to
+# pass in a full URL or similar strings and decode them for human
+# presentation.
+#
+# Outputs the encoded string on stdout.
+# Returns nonzero if encoding failed.
+#
+# Usage:
+# omz_urldecode <urlstring> - prints decoded string followed by a newline
+function omz_urldecode {
+ emulate -L zsh
+ local encoded_url=$1
+
+ # Work bytewise, since URLs escape UTF-8 octets
+ local caller_encoding=$langinfo[CODESET]
+ local LC_ALL=C
+ export LC_ALL
+
+ # Change + back to ' '
+ local tmp=${encoded_url:gs/+/ /}
+ # Protect other escapes to pass through the printf unchanged
+ tmp=${tmp:gs/\\/\\\\/}
+ # Handle %-escapes by turning them into `\xXX` printf escapes
+ tmp=${tmp:gs/%/\\x/}
+ local decoded
+ eval "decoded=\$'$tmp'"
+
+ # Now we have a UTF-8 encoded string in the variable. We need to re-encode
+ # it if caller is in a non-UTF-8 locale.
+ local safe_encodings
+ safe_encodings=(UTF-8 utf8 US-ASCII)
+ if [[ -z ${safe_encodings[(r)$caller_encoding]} ]]; then
+ decoded=$(echo -E "$decoded" | iconv -f UTF-8 -t $caller_encoding)
+ if [[ $? != 0 ]]; then
+ echo "Error converting string from UTF-8 to $caller_encoding" >&2
+ return 1
+ fi
+ fi
+
+ echo -E "$decoded"
+}
+
diff --git a/lib/git.zsh b/lib/git.zsh
index 118841f06..baf863717 100644
--- a/lib/git.zsh
+++ b/lib/git.zsh
@@ -36,24 +36,30 @@ git_remote_status() {
ahead=$(command git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l)
behind=$(command git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l)
- if [ $ahead -eq 0 ] && [ $behind -gt 0 ]
+ if [ $ahead -eq 0 ] && [ $behind -eq 0 ]
then
- echo "$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE"
+ echo "$ZSH_THEME_GIT_PROMPT_EQUAL_REMOTE"
elif [ $ahead -gt 0 ] && [ $behind -eq 0 ]
then
- echo "$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE"
+ git_remote_status="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE"
+ git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}"
+ elif [ $behind -gt 0 ] && [ $ahead -eq 0 ]
+ then
+ git_remote_status="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE"
+ git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}"
elif [ $ahead -gt 0 ] && [ $behind -gt 0 ]
then
- echo "$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE"
+ git_remote_status="$ZSH_THEME_GIT_PROMPT_DIVERGED_REMOTE"
+ git_remote_status_detailed="$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_AHEAD_REMOTE$((ahead))%{$reset_color%}$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE_COLOR$ZSH_THEME_GIT_PROMPT_BEHIND_REMOTE$((behind))%{$reset_color%}"
fi
- fi
-}
-# Checks if there are commits ahead from remote
-function git_prompt_ahead() {
- if $(echo "$(command git log @{upstream}..HEAD 2> /dev/null)" | grep '^commit' &> /dev/null); then
- echo "$ZSH_THEME_GIT_PROMPT_AHEAD"
- fi
+ if [ $ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_DETAILED ]
+ then
+ git_remote_status="$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_PREFIX$remote$git_remote_status_detailed$ZSH_THEME_GIT_PROMPT_REMOTE_STATUS_SUFFIX"
+ fi
+
+ echo $git_remote_status
+ fi
}
# Gets the number of commits ahead from remote
@@ -64,6 +70,29 @@ function git_commits_ahead() {
fi
}
+# Outputs if current branch is ahead of remote
+function git_prompt_ahead() {
+ if [[ -n "$(command git rev-list origin/$(current_branch)..HEAD 2> /dev/null)" ]]; then
+ echo "$ZSH_THEME_GIT_PROMPT_AHEAD"
+ fi
+}
+
+# Outputs if current branch is behind remote
+function git_prompt_behind() {
+ if [[ -n "$(command git rev-list HEAD..origin/$(current_branch) 2> /dev/null)" ]]; then
+ echo "$ZSH_THEME_GIT_PROMPT_BEHIND"
+ fi
+}
+
+# Outputs if current branch exists on remote or not
+function git_prompt_remote() {
+ if [[ -n "$(command git show-ref origin/$(current_branch) 2> /dev/null)" ]]; then
+ echo "$ZSH_THEME_GIT_PROMPT_REMOTE_EXISTS"
+ else
+ echo "$ZSH_THEME_GIT_PROMPT_REMOTE_MISSING"
+ fi
+}
+
# Formats prompt string for current git commit short SHA
function git_prompt_short_sha() {
SHA=$(command git rev-parse --short HEAD 2> /dev/null) && echo "$ZSH_THEME_GIT_PROMPT_SHA_BEFORE$SHA$ZSH_THEME_GIT_PROMPT_SHA_AFTER"
diff --git a/lib/misc.zsh b/lib/misc.zsh
index 0b7cb2696..6d1a64e8d 100644
--- a/lib/misc.zsh
+++ b/lib/misc.zsh
@@ -1,6 +1,10 @@
-## smart urls
-autoload -U url-quote-magic
-zle -N self-insert url-quote-magic
+## Load smart urls if available
+for d in $fpath; do
+ if [[ -e "$d/url-quote-magic" ]]; then
+ autoload -U url-quote-magic
+ zle -N self-insert url-quote-magic
+ fi
+done
## jobs
setopt long_list_jobs
@@ -20,3 +24,6 @@ alias afind='ack-grep -il'
if [[ -z "$LC_CTYPE" && -z "$LC_ALL" ]]; then
export LC_CTYPE=${LANG%%:*} # pick the first entry from LANG
fi
+
+# recognize comments
+setopt interactivecomments
diff --git a/lib/termsupport.zsh b/lib/termsupport.zsh
index e1c2e2f93..5f61fe8ef 100644
--- a/lib/termsupport.zsh
+++ b/lib/termsupport.zsh
@@ -7,6 +7,9 @@
# (In screen, only short_tab_title is used)
# Limited support for Apple Terminal (Terminal can't set window and tab separately)
function title {
+ emulate -L zsh
+ setopt prompt_subst
+
[[ "$EMACS" == *term* ]] && return
# if $2 is unset use $1 as default
@@ -23,9 +26,14 @@ function title {
ZSH_THEME_TERM_TAB_TITLE_IDLE="%15<..<%~%<<" #15 char left truncated PWD
ZSH_THEME_TERM_TITLE_IDLE="%n@%m: %~"
+# Avoid duplication of directory in terminals with independent dir display
+if [[ $TERM_PROGRAM == Apple_Terminal ]]; then
+ ZSH_THEME_TERM_TITLE_IDLE="%n@%m"
+fi
# Runs before showing the prompt
function omz_termsupport_precmd {
+ emulate -L zsh
if [[ $DISABLE_AUTO_TITLE == true ]]; then
return
fi
@@ -35,15 +43,15 @@ function omz_termsupport_precmd {
# Runs before executing the command
function omz_termsupport_preexec {
+ emulate -L zsh
if [[ $DISABLE_AUTO_TITLE == true ]]; then
return
fi
- emulate -L zsh
setopt extended_glob
# cmd name only, or if this is sudo or ssh, the next cmd
- local CMD=${1[(wr)^(*=*|sudo|ssh|rake|-*)]:gs/%/%%}
+ local CMD=${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%}
local LINE="${2:gs/%/%%}"
title '$CMD' '%100>...>$LINE%<<'
@@ -53,14 +61,28 @@ precmd_functions+=(omz_termsupport_precmd)
preexec_functions+=(omz_termsupport_preexec)
-# Runs before showing the prompt, to update the current directory in Terminal.app
-function omz_termsupport_cwd {
- # Notify Terminal.app of current directory using undocumented OSC sequence
- # found in OS X 10.9 and 10.10's /etc/bashrc
- if [[ $TERM_PROGRAM == Apple_Terminal ]] && [[ -z $INSIDE_EMACS ]]; then
- local PWD_URL="file://$HOSTNAME${PWD// /%20}"
- printf '\e]7;%s\a' "$PWD_URL"
- fi
-}
+# Keep Apple Terminal.app's current working directory updated
+# Based on this answer: http://superuser.com/a/315029
+# With extra fixes to handle multibyte chars and non-UTF-8 locales
+
+if [[ "$TERM_PROGRAM" == "Apple_Terminal" ]] && [[ -z "$INSIDE_EMACS" ]]; then
+
+ # Emits the control sequence to notify Terminal.app of the cwd
+ function update_terminalapp_cwd() {
+ emulate -L zsh
+ # Identify the directory using a "file:" scheme URL, including
+ # the host name to disambiguate local vs. remote paths.
+
+ # Percent-encode the pathname.
+ local URL_PATH=$(omz_urlencode -P $PWD)
+ [[ $? != 0 ]] && return 1
+ local PWD_URL="file://$HOST$URL_PATH"
+ # Undocumented Terminal.app-specific control sequence
+ printf '\e]7;%s\a' $PWD_URL
+ }
-precmd_functions+=(omz_termsupport_cwd)
+ # Use a precmd hook instead of a chpwd hook to avoid contaminating output
+ precmd_functions+=(update_terminalapp_cwd)
+ # Run once to get initial cwd set
+ update_terminalapp_cwd
+fi
diff --git a/lib/theme-and-appearance.zsh b/lib/theme-and-appearance.zsh
index 926303ca4..ebb11fb31 100644
--- a/lib/theme-and-appearance.zsh
+++ b/lib/theme-and-appearance.zsh
@@ -11,8 +11,11 @@ then
# otherwise, leave ls as is, because NetBSD's ls doesn't support -G
gls --color -d . &>/dev/null 2>&1 && alias ls='gls --color=tty'
elif [[ "$(uname -s)" == "OpenBSD" ]]; then
- # On OpenBSD, test if "colorls" is installed (this one supports colors);
- # otherwise, leave ls as is, because OpenBSD's ls doesn't support -G
+ # On OpenBSD, "gls" (ls from GNU coreutils) and "colorls" (ls from base,
+ # with color and multibyte support) are available from ports. "colorls"
+ # will be installed on purpose and can't be pulled in by installing
+ # coreutils, so prefer it to "gls".
+ gls --color -d . &>/dev/null 2>&1 && alias ls='gls --color=tty'
colorls -G -d . &>/dev/null 2>&1 && alias ls='colorls -G'
else
ls --color -d . &>/dev/null 2>&1 && alias ls='ls --color=tty' || alias ls='ls -G'