Parent directory

functions.zsh

7789 bytes
  1function zsh_stats() {
  2  fc -l 1 \
  3    | awk '{ CMD[$2]++; count++; } END { for (a in CMD) print CMD[a] " " CMD[a]*100/count "% " a }' \
  4    | grep -v "./" | sort -nr | head -n 20 | column -c3 -s " " -t | nl
  5}
  6
  7function uninstall_oh_my_zsh() {
  8  command env ZSH="$ZSH" sh "$ZSH/tools/uninstall.sh"
  9}
 10
 11function upgrade_oh_my_zsh() {
 12  echo >&2 "${fg[yellow]}Note: \`$0\` is deprecated. Use \`omz update\` instead.$reset_color"
 13  omz update
 14}
 15
 16function open_command() {
 17  local open_cmd
 18
 19  # define the open command
 20  case "$OSTYPE" in
 21    darwin*)  open_cmd='open' ;;
 22    cygwin*)  open_cmd='cygstart' ;;
 23    linux*)   [[ "$(uname -r)" != *icrosoft* ]] && open_cmd='nohup xdg-open' || {
 24                open_cmd='cmd.exe /c start ""'
 25                [[ -e "$1" ]] && { 1="$(wslpath -w "${1:a}")" || return 1 }
 26                [[ "$1" = (http|https)://* ]] && {
 27                  1="$(echo "$1" | sed -E 's/([&|()<>^])/^\1/g')" || return 1
 28                }
 29              } ;;
 30    msys*)    open_cmd='start ""' ;;
 31    *)        echo "Platform $OSTYPE not supported"
 32              return 1
 33              ;;
 34  esac
 35
 36  # If a URL is passed, $BROWSER might be set to a local browser within SSH.
 37  # See https://github.com/ohmyzsh/ohmyzsh/issues/11098
 38  if [[ -n "$BROWSER" && "$1" = (http|https)://* ]]; then
 39    "$BROWSER" "$@"
 40    return
 41  fi
 42
 43  ${=open_cmd} "$@" &>/dev/null
 44}
 45
 46# take functions
 47
 48# mkcd is equivalent to takedir
 49function mkcd takedir() {
 50  mkdir -p $@ && cd ${@:$#}
 51}
 52
 53function takeurl() {
 54  local data thedir
 55  data="$(mktemp)"
 56  curl -L "$1" > "$data"
 57  tar xf "$data"
 58  thedir="$(tar tf "$data" | head -n 1)"
 59  rm "$data"
 60  cd "$thedir"
 61}
 62
 63function takezip() {
 64  local data thedir
 65  data="$(mktemp)"
 66  curl -L "$1" > "$data"
 67  unzip "$data" -d "./"
 68  thedir="$(unzip -l "$data" | awk 'NR==4 {print $4}' | sed 's/\/.*//')"
 69  rm "$data"
 70  cd "$thedir"
 71}
 72
 73function takegit() {
 74  git clone "$1"
 75  cd "$(basename ${1%%.git})"
 76}
 77
 78function take() {
 79  if [[ $1 =~ ^(https?|ftp).*\.(tar\.(gz|bz2|xz)|tgz)$ ]]; then
 80    takeurl "$1"
 81  elif [[ $1 =~ ^(https?|ftp).*\.(zip)$ ]]; then
 82    takezip "$1"
 83  elif [[ $1 =~ ^([A-Za-z0-9]\+@|https?|git|ssh|ftps?|rsync).*\.git/?$ ]]; then
 84    takegit "$1"
 85  else
 86    takedir "$@"
 87  fi
 88}
 89
 90#
 91# Get the value of an alias.
 92#
 93# Arguments:
 94#    1. alias - The alias to get its value from
 95# STDOUT:
 96#    The value of alias $1 (if it has one).
 97# Return value:
 98#    0 if the alias was found,
 99#    1 if it does not exist
100#
101function alias_value() {
102    (( $+aliases[$1] )) && echo $aliases[$1]
103}
104
105#
106# Try to get the value of an alias,
107# otherwise return the input.
108#
109# Arguments:
110#    1. alias - The alias to get its value from
111# STDOUT:
112#    The value of alias $1, or $1 if there is no alias $1.
113# Return value:
114#    Always 0
115#
116function try_alias_value() {
117    alias_value "$1" || echo "$1"
118}
119
120#
121# Set variable "$1" to default value "$2" if "$1" is not yet defined.
122#
123# Arguments:
124#    1. name - The variable to set
125#    2. val  - The default value
126# Return value:
127#    0 if the variable exists, 3 if it was set
128#
129function default() {
130    (( $+parameters[$1] )) && return 0
131    typeset -g "$1"="$2"   && return 3
132}
133
134#
135# Set environment variable "$1" to default value "$2" if "$1" is not yet defined.
136#
137# Arguments:
138#    1. name - The env variable to set
139#    2. val  - The default value
140# Return value:
141#    0 if the env variable exists, 3 if it was set
142#
143function env_default() {
144    [[ ${parameters[$1]} = *-export* ]] && return 0
145    export "$1=$2" && return 3
146}
147
148
149# Required for $langinfo
150zmodload zsh/langinfo
151
152# URL-encode a string
153#
154# Encodes a string using RFC 2396 URL-encoding (%-escaped).
155# See: https://www.ietf.org/rfc/rfc2396.txt
156#
157# By default, reserved characters and unreserved "mark" characters are
158# not escaped by this function. This allows the common usage of passing
159# an entire URL in, and encoding just special characters in it, with
160# the expectation that reserved and mark characters are used appropriately.
161# The -r and -m options turn on escaping of the reserved and mark characters,
162# respectively, which allows arbitrary strings to be fully escaped for
163# embedding inside URLs, where reserved characters might be misinterpreted.
164#
165# Prints the encoded string on stdout.
166# Returns nonzero if encoding failed.
167#
168# Usage:
169#  omz_urlencode [-r] [-m] [-P] <string> [<string> ...]
170#
171#    -r causes reserved characters (;/?:@&=+$,) to be escaped
172#
173#    -m causes "mark" characters (_.!~*''()-) to be escaped
174#
175#    -P causes spaces to be encoded as '%20' instead of '+'
176function omz_urlencode() {
177  emulate -L zsh
178  setopt norematchpcre
179
180  local -a opts
181  zparseopts -D -E -a opts r m P
182
183  local in_str="$@"
184  local url_str=""
185  local spaces_as_plus
186  if [[ -z $opts[(r)-P] ]]; then spaces_as_plus=1; fi
187  local str="$in_str"
188
189  # URLs must use UTF-8 encoding; convert str to UTF-8 if required
190  local encoding=$langinfo[CODESET]
191  local safe_encodings
192  safe_encodings=(UTF-8 utf8 US-ASCII)
193  if [[ -z ${safe_encodings[(r)$encoding]} ]]; then
194    str=$(echo -E "$str" | iconv -f $encoding -t UTF-8)
195    if [[ $? != 0 ]]; then
196      echo "Error converting string from $encoding to UTF-8" >&2
197      return 1
198    fi
199  fi
200
201  # Use LC_CTYPE=C to process text byte-by-byte
202  # Note that this doesn't work in Termux, as it only has UTF-8 locale.
203  # Characters will be processed as UTF-8, which is fine for URLs.
204  local i byte ord LC_ALL=C
205  export LC_ALL
206  local reserved=';/?:@&=+$,'
207  local mark='_.!~*''()-'
208  local dont_escape="[A-Za-z0-9"
209  if [[ -z $opts[(r)-r] ]]; then
210    dont_escape+=$reserved
211  fi
212  # $mark must be last because of the "-"
213  if [[ -z $opts[(r)-m] ]]; then
214    dont_escape+=$mark
215  fi
216  dont_escape+="]"
217
218  # Implemented to use a single printf call and avoid subshells in the loop,
219  # for performance (primarily on Windows).
220  local url_str=""
221  for (( i = 1; i <= ${#str}; ++i )); do
222    byte="$str[i]"
223    if [[ "$byte" =~ "$dont_escape" ]]; then
224      url_str+="$byte"
225    else
226      if [[ "$byte" == " " && -n $spaces_as_plus ]]; then
227        url_str+="+"
228      elif [[ "$PREFIX" = *com.termux* ]]; then
229        # Termux does not have non-UTF8 locales, so just send the UTF-8 character directly
230        url_str+="$byte"
231      else
232        ord=$(( [##16] #byte ))
233        url_str+="%$ord"
234      fi
235    fi
236  done
237  echo -E "$url_str"
238}
239
240# URL-decode a string
241#
242# Decodes a RFC 2396 URL-encoded (%-escaped) string.
243# This decodes the '+' and '%' escapes in the input string, and leaves
244# other characters unchanged. Does not enforce that the input is a
245# valid URL-encoded string. This is a convenience to allow callers to
246# pass in a full URL or similar strings and decode them for human
247# presentation.
248#
249# Outputs the encoded string on stdout.
250# Returns nonzero if encoding failed.
251#
252# Usage:
253#   omz_urldecode <urlstring>  - prints decoded string followed by a newline
254function omz_urldecode {
255  emulate -L zsh
256  local encoded_url=$1
257
258  # Work bytewise, since URLs escape UTF-8 octets
259  local caller_encoding=$langinfo[CODESET]
260  local LC_ALL=C
261  export LC_ALL
262
263  # Change + back to ' '
264  local tmp=${encoded_url:gs/+/ /}
265  # Protect other escapes to pass through the printf unchanged
266  tmp=${tmp:gs/\\/\\\\/}
267  # Handle %-escapes by turning them into `\xXX` printf escapes
268  tmp=${tmp:gs/%/\\x/}
269  local decoded="$(printf -- "$tmp")"
270
271  # Now we have a UTF-8 encoded string in the variable. We need to re-encode
272  # it if caller is in a non-UTF-8 locale.
273  local -a safe_encodings
274  safe_encodings=(UTF-8 utf8 US-ASCII)
275  if [[ -z ${safe_encodings[(r)$caller_encoding]} ]]; then
276    decoded=$(echo -E "$decoded" | iconv -f UTF-8 -t $caller_encoding)
277    if [[ $? != 0 ]]; then
278      echo "Error converting string from UTF-8 to $caller_encoding" >&2
279      return 1
280    fi
281  fi
282
283  echo -E "$decoded"
284}