functions.zsh 7.5 KB

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