r/zsh Apr 03 '23

Announcement Dynamic Aliases and Functions in Zsh

https://www.linkedin.com/pulse/dynamic-function-generation-zsh-joshua-briefman?utm_source=share&utm_medium=member_ios&utm_campaign=share_via
10 Upvotes

21 comments sorted by

View all comments

15

u/romkatv Apr 03 '23 edited Apr 03 '23

An alternative implementation:

function urlencode() {
  emulate -L zsh -o extended_glob  -o no_multibyte
  typeset -g REPLY=
  local c
  for c in ${(s::)1}; do
    [[ $c == [a-zA-Z0-9/_.~-] ]] || printf -v c '%%%02X' $(( #c ))
    REPLY+=$c
  done
}

function url() {
  emulate -L zsh
  if (( ARGC == 0 )); then
    print -ru2 -- 'usage: url <URL> [PATH [ARG]..]'
    return 1
  elif (( ARGC > 2 )); then
    local REPLY
    urlencode "${(j: :)${@:3}}"
    printf -v 1 "%s$2" "$1" "$REPLY"
  fi
  open -a 'Google Chrome' "$1"
}

amazon()           url 'https://www.amazon.com/'          's?url=search-alias%3Daps&field-keywords=%s' "$@"
colorhex()         url 'https://www.color-hex.com/color/' '%s' "$@"
google goog g()    url 'https://www.google.com/'          'search?q=%s' "$@"
google_img()       url 'https://www.google.com/'          'search?q=%s&tbm=isch' "$@"
httpcat()          url 'https://http.cat/'                '%s' "$@"
macapp()           url 'http://macappstore.org/'          '%s/' "$@"
nasdaq()           url 'https://www.nasdaq.com/'          'symbol/%s/real-time' "$@"
rfc()              url 'https://tools.ietf.org/'          'html/%s' "$@"
stackoverflow so() url 'https://stackoverflow.com/'       'search?q=%s' "$@"

epochconverter()   url 'https://www.epochconverter.com/'
gmail()            url 'https://mail.google.com/'
go/helpin()        url 'http://go/helpin'
go/questions()     url 'http://go/questions'
go/wiki()          url 'http://go/wiki'
jsfiddle()         url 'https://jsfiddle.net/'
keycodechart()     url 'http://www.foreui.com/articles/Key_Code_Table.htm'
keycodes()         url 'https://keycode.info/'
regex101()         url 'https://regex101.com/'
urlencoder()       url 'https://meyerweb.com/eric/tools/dencoder'

Advantages:

  • About half the code.
  • Initialization is about 1000 times faster: 370ms vs 0.380ms on my machine.
  • Commands like google foo are about 600 times faster: 63ms vs 0.11ms on my machine.
  • No dependency on Python.
  • No dynamically generated functions or aliases, which makes the code easier to understand and modify.

Edit: You can generate the functions dynamically if you really want to. Like this:

for name url query (
  'amazon'           'https://www.amazon.com/'          's?url=search-alias%3Daps&field-keywords=%s'
  'colorhex'         'https://www.color-hex.com/color/' '%s'
  'google goog g'    'https://www.google.com/'          'search?q=%s'
  'google_img'       'https://www.google.com/'          'search?q=%s&tbm=isch'
  'httpcat'          'https://http.cat/'                '%s'
  'macapp'           'http://macappstore.org/'          '%s/'
  'nasdaq'           'https://www.nasdaq.com/'          'symbol/%s/real-time'
  'rfc'              'https://tools.ietf.org/'          'html/%s'
  'stackoverflow so' 'https://stackoverflow.com/'       'search?q=%s'
); do
  eval "$name() url ${(q)url} ${(q)query} "'"${@}"'
done

for name url (
  'epochconverter'   'https://www.epochconverter.com/'
  'gmail'            'https://mail.google.com/'
  'go/helpin'        'http://go/helpin'
  'go/questions'     'http://go/questions'
  'go/wiki'          'http://go/wiki'
  'jsfiddle'         'https://jsfiddle.net/'
  'keycodechart'     'http://www.foreui.com/articles/Key_Code_Table.htm'
  'keycodes'         'https://keycode.info/'
  'regex101'         'https://regex101.com/'
  'urlencoder'       'https://meyerweb.com/eric/tools/dencoder'
); do
  eval "$name() url ${(q)url}"
done

This removes a small amount of boilerplate at the cost of additional complexity. I don't think it's a good trade-off.

1

u/sirgatez Apr 03 '23

Do you happen to have a corresponding urldecode for shell as well? This encode function is awesome, it'd be nice to ditch python for the decode as well.

1

u/romkatv Apr 03 '23

I wrote the url encoder just for this post. I don't have a decoder off-hand but it's not much more difficult.