Author: jv
License: The MIT License, Copyright (c) 2007 jv
Description: search the web from the command line; an example of using
cmdparser
Platform: Mac OS X 10.4.11
Requirements: set the character set encoding of Terminal.app to UTF-8; sudo port install libidn (after installing MacPorts)
Usage:
ws -h
ws daily quote
ws -y -p "daily news" sports football
ws -gm California
ws -p "wildlife vacation" India travel visit tiger leopard
ws -t 'Australia holiday vacation ocean desert'
ws -w http://en.wikipedia.org -p "keep it simple"
ws -wp -p "keep it simple"
ws -w en.wikipedia.org -t Africa wildlife
echo "Canada wildlife" | ws -y -w en.wikipedia.org -
Installation:
sudo mkdir -p /usr/local/bin
sudo touch /usr/local/bin/ws
sudo chmod 0755 /usr/local/bin/ws
sudo chown root:wheel /usr/local /usr/local/bin /usr/local/bin/ws
sudo nano /usr/local/bin/ws
OPATH=$PATH
export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin
OIFS=$IFS
export IFS=$' \t\n'
declare search="" sed="/usr/bin/sed" open="/usr/bin/open" grep="/usr/bin/grep"
exec 2>/dev/console # write stderr to console.log in /Library/Logs/Console/
# URL encoding
# convert special (UTF-8 encoded) input characters into hexadecimal URL-encoding form
# For further conversions see:
# http://www.w3schools.com/tags/ref_urlencode.asp (HTML URL-encoding Reference)
# http://www.blooberry.com/indexdot/html/topics/urlencoding.htm
# http://en.wikipedia.org/wiki/Percent-encoding
function url_encoding() {
echo -e "$('s/%/%25/g' -e 's/ /%20/g' -e 's/"/%22/g' -e 's/#/%23/g' \
-e 's/&/%26/g' -e 's/%3C/g' -e 's/>/%3E/g' -e 's/{/%7B/g' -e 's/}/%7D/g' -e 's/\|/%7C/g' \
-e 's/\\/%5C/g' -e 's/\^/%5E/g' -e 's/\~/%7E/g' -e 's/\[/%5B/g' -e 's/\]/%5D/g' -e 's/\`/%60/g' \
-e s/$'\342\202\254'/%80/g -e s/$'\303\274'/%FC/g -e s/$'\302\243'/%A3/g -e s/$'\303\266'/%F6/g \
-e s/$'\303\251'/%E9/g -e s/$'\303\244'/%E4/g -e s/$'\303\204'/%C4/g -e s/$'\303\226'/%D6/g \
-e s/$'\303\234'/%DC/g -e s/$'\303\237'/%DF/g -e s/$'\303\240'/%E0/g -e s/$'\303\241'/%E1/g \
-e s/$'\303\242'/%E2/g -e s/$'\303\247'/%E7/g -e s/$'\303\250'/%E8/g -e s/$'\303\252'/%EA/g \
-e s/$'\303\253'/%EB/g -e s/$'\303\254'/%EC/g -e s/$'\303\255'/%ED/g -e s/$'\303\256'/%EE/g \
-e s/$'\303\257'/%EF/g -e s/$'\303\200'/%C0/g -e s/$'\303\201'/%C1/g -e s/$'\303\202'/%C2/g \
-e s/$'\303\207'/%C7/g -e s/$'\303\210'/%C8/g -e s/$'\303\211'/%C9/g -e s/$'\303\212'/%CA/g \
-e s/$'\303\213'/%CB/g -e s/$'\303\214'/%CC/g -e s/$'\303\215'/%CD/g -e s/$'\303\216'/%CE/g \
-e s/$'\303\217'/%CF/g -e s/$'\303\277'/%BF/g -e s/$'\303\203'/%C3/g -e s/$'\303\205'/%C5/g \
-e s/$'\303\206'/%C6/g -e s/$'\303\220'/%D0/g -e s/$'\303\221'/%D1/g -e s/$'\303\245'/%E5/g \
-e s/$'\303\246'/%E6/g -e s/$'\303\261'/%F1/g -e s/$'\303\262'/%F2/g -e s/$'\303\263'/%F3/g \
-e s/$'\303\264'/%F4/g -e s/$'\303\265'/%F5/g -e s/$'\303\267'/%F7/g -e s/$'\303\270'/%F8/g \
-e s/$'\303\271'/%F9/g -e s/$'\303\272'/%FA/g -e s/$'\303\273'/%FB/g -e s/$'\303\275'/%FD/g \
-e s/$'\303\276'/%FE/g -e s/$'\303\277'/%FF/g -e s/$'\303\235'/%DD/g -e s/$'\303\236'/%DE/g \
-e s/$'\305\241'/%9A/g -e s/$'\305\223'/%9C/g -e s/$'\305\276'/%9E/g -e s/$'\305\270'/%9F/g \
-e s/$'\302\265'/%B5/g -e s/$'\305\275'/%8E/g -e s/$'\305\240'/%8C/g -e s/$'\302\241'/%A1/g \
-e s/$'\302\242'/%A2/g -e s/$'\302\245'/%A5/g -e s/$'\303\243'/%E3/g -e s/$'\303\260'/%F0/g \
-e s/$'\303\222'/%D2/g -e s/$'\303\223'/%D3/g -e s/$'\303\224'/%D4/g -e s/$'\303\225'/%D5/g \
-e s/$'\303\230'/%D8/g -e s/$'\303\223'/%D9/g -e s/$'\303\232'/%DA/g -e s/$'\303\233'/%DB/g
}
# check if character set encoding of Terminal.app is set to UTF-8
if [[ "$(/usr/bin/defaults read com.apple.Terminal StringEncoding)" != "4" ]]; then
echo "Terminal.app does not use UTF-8 character set encoding!"
exit 1
fi
# check if libidn is available (optional here; see the same libidn check below)
# http://www.gnu.org/software/libidn/
# http://en.wikipedia.org/wiki/Punycode
# http://en.wikipedia.org/wiki/Internationalized_domain_name
#if [[ ! -e "/opt/local/bin/idn" ]]; then
# echo $'You do not have libidn installed at: /opt/local/bin/idn\nPlease install it via MacPorts!\nSee: http://www.macports.org/install.php'
# exit 1
#fi
################################################# BEGINNING OF CMDPARSER
# define the names of flags as a regular expression
# flags are command line options that require arguments
# p: phrase
# t: terms
# w: website
flags="(p|t|w)"
# define the names of switches as a regular expression
# switches are command line options that do not take arguments
# make sure multi-char switches precede single-char switches in the regular expression
# note that the regular expression contains neither the special read-from-stdin switch "-" nor the special end-of-options switch "--"
# gm: Google Maps
# h: help
# wp: Wikipedia
# y: Yahoo
switches="(gm|wp|h|y)"
names_of_switches="gm h wp y"
usage="usage: $(/usr/bin/basename "$0") [-h] [-y] [-gm] [-wp] [-p \"a phrase\"] [-w website ] [-t term] [term1 term2 ...]"
declare p s t
declare -i gm=0 h=0 wp=0 y=0
declare optstr flagvar argvar argvar_escaped pipedstr piped
declare -i optid pipedvar pipedvar2
piped="piped"
pipedvar=0
pipedvar2=0
if [[ -s /dev/stdin ]]; then pipedstr="$("; else pipedstr=""; fi
if [[ $# -eq 0 ]] && [[ -z "$pipedstr" ]]; then
echo "No arguments specified!"
echo "$usage"
exit 1
fi
if [[ $# -eq 0 ]] && [[ -n "$pipedstr" ]]; then
eval $piped='"$(echo "$pipedstr")"'
pipedvar=1
pipedvar2=1
fi
if [[ $pipedvar -eq 0 ]] ; then
optstr=" "
optid=0
while [[ -n "$optstr" ]]; do
optstr="$(echo "$1" | $grep -E "^\-\-?$flags$")"
if [[ -n "$optstr" ]]; then optid=1; fi
if [[ -z "$optstr" ]]; then optid=2; optstr="$(echo "$1" | $grep -E "^\-\-?$switches$")"; fi
if [[ -z "$optstr" ]]; then optid=3; optstr="$(echo "$1" | $grep -E "^\-\-?$switches+$")"; fi
if [[ -z "$optstr" ]]; then optid=4; optstr="$(echo "$1" | $grep -E "^(\-\-?$flags\=.*|\-\-?$flags[^ ]+)$")"; fi
if [[ -z "$optstr" ]]; then
if [[ "$1" = "-" ]] && [[ "$@" = "-" ]]; then
optid=5
optstr="-"
fi
fi
if [[ -z "$optstr" ]] && ( [[ -n "$(echo "$@" | $grep -Eo "(^ *| )\-\-?$flags" )" ]] || [[ -n "$(echo "$@" | $grep -Eo "(^ *| )\-\-?$switches" )" ]] ); then
optstr="$(echo $1)"
echo "illegal option removed: $optstr"
shift
continue
#optstr=" "
#echo "$usage"
#exit 1
fi
if [[ "$1" = "--" ]]; then shift; break; fi # -- marks end of options
if [[ -z "$optstr" ]]; then break; fi
# flag followed by space (example: -f file)
if [[ $optid -eq 1 ]]; then
if [[ -z "$2" ]]; then
echo; echo "flag \"$1\" removed: no argument given!"
shift
if [[ -n "$(echo "$@")" ]]; then shift; continue; else shift; break; fi
fi
if [[ "$2" = "-" ]] || [[ "$2" = "--" ]] || [[ -n "$(echo "$2" | $grep -E "^\-\-?$flags.*$" )" ]] || [[ -n "$(echo "$2" | $grep -E "^\-\-?$switches+$" )" ]]; then
echo; echo "flag \"$1\" removed because of illegal argument: \"$2\""
shift
continue
fi
flagvar="$(/bin/expr "$1" : "^\-\{1,2\}\(.*\)$")"
argvar="$2"
eval $flagvar='"$(echo "$argvar")"'
shift 2
continue
# single switch (example: -a)
elif [[ $optid -eq 2 ]]; then
flagvar="$(/bin/expr "$1" : "^\-\{1,2\}\(.*\)$")"
eval $flagvar='"$(echo "1")"'
shift
continue
# combined switch (example: -abcc)
elif [[ $optid -eq 3 ]]; then
flagvar="$(/bin/expr "$1" : "^\-\{1,2\}\(.*\)$")"
while [[ -n "$flagvar" ]]; do
char="$(echo "$flagvar" | $sed -E "s/^$switches.*$/\1/")"
eval $char='"$(echo "1")"'
flagvar="$(echo "$flagvar" | $sed -E "s/^$switches//")"
done
shift
continue
# flag without following space (example: -ffile)
elif [[ $optid -eq 4 ]]; then
argvar="$(echo "$1" | $sed -E "s/^\-\-?$flags\=?//")"
argvar_escaped="$(echo "$argvar" | $sed -E 's/([^[:alnum:]])/\\\1/g')" # escape special regex metacharacters such as ., ?, *
#argvar_escaped="$(echo "$argvar" | $sed -E 's/([[:punct:]])/\\\1/g')"
#echo "argvar_escaped: $argvar_escaped"
flagvar="$(echo "$1" | $sed -E -e 's/^-\-?//' -e "s/\=?$argvar_escaped$//")"
eval $flagvar='"$(echo "$argvar")"'
shift
continue
# the special read-from-stdin switch "-"
elif [[ $optid -eq 5 ]]; then
pipedvar=1
eval $piped='"$(echo "$pipedstr")"'
shift
break
fi
shift
done
fi # if [[ $pipedvar -eq 0 ]] ; then ...
################################################# END OF CMDPARSER
if [[ $h -eq 1 ]]; then # help message
echo "$usage"
/bin/cat <<-EOF
Examples:
ws -h
ws daily quote
ws -y -p "daily news" sports football
ws -gm California
ws -p "wildlife vacation" India travel visit tiger leopard
ws -t 'Australia holiday vacation ocean desert'
ws -w http://en.wikipedia.org -p "keep it simple"
ws -wp -p "keep it simple"
ws -w en.wikipedia.org -t Africa wildlife
echo "Canada wildlife" | ws -y -w en.wikipedia.org -
EOF
exit 0
fi
# store the contents of $@ in $search
if [[ -n "$@" ]]; then search="$@"; fi
# if there is piped data, $search is set to $pipedstr
if [[ $pipedvar -eq 1 ]]; then search="$piped"; fi
# if there is piped data without any further flags or switches specified, we just do a Google
if [[ $pipedvar2 -eq 1 ]]; then
F="$(echo "$search" | url_encoding)"
$open "http://www.google.com/search?q=$F"
exit 0
fi
# to open the given URL directly we will store the original URL given by the -w switch in $ow for processing with libidn below
declare ow
# remove http:// and encode URL
if [[ -n "$w" ]]; then w="$(echo "$w" | $sed -E 's/^( *http:\/\/ *)(.*)$/\2/' )"; ow=$w; w="$(echo "$w" | url_encoding)"; fi
# If only the -p and/or -t flag is specified or no flags & switches are specified at all we just do a Google.
# If the remaining string stored in $search (which has been $@ above) is not empty and the -p and/or -t flags are specified,
# the remaining string will be added to the search term(s) or phrase as additional search term(s).
if [[ -z "$w" ]] && [[ $y -eq 0 ]] && [[ $gm -eq 0 ]] && [[ $wp -eq 0 ]]; then
if [[ -n "$t" ]] && [[ -n "$p" ]]; then
if [[ -n "$search" ]]; then t="$t $search"; fi # strings in $search will be added as search terms
F1="$(echo "$t" | url_encoding)" # example: ws -p "a phrase" -t "a term" term1 term2 ...
F2="$(echo "$p" | url_encoding)"
str='%22'
F2="$str$F2$str"
F="$F2%20$F1"
$open "http://www.google.com/search?q=$F"
exit 0
elif [[ -n "$p" ]]; then
if [[ -n "$search" ]]; then # strings in $search will be added as search terms
t="$search"
F1="$(echo "$t" | url_encoding)"
F2="$(echo "$p" | url_encoding)"
str='%22'
F2="$str$F2$str"
F="$F2%20$F1"
$open "http://www.google.com/search?q=$F"
exit 0
else
F="$(echo "$p" | url_encoding)"
str='%22'
F="$str$F$str"
$open "http://www.google.com/search?q=$F"
exit 0
fi
elif [[ -n "$t" ]]; then
if [[ -n "$search" ]]; then t="$t $search"; fi # strings in $search will be added as search terms
F="$(echo "$t" | url_encoding)"
$open "http://www.google.com/search?q=$F"
exit 0
else
if [[ -z "$search" ]]; then $open "http://www.google.com"; exit 0; fi # just open the given URL
F="$(echo "$search" | url_encoding)"
$open "http://www.google.com/search?q=$F"
exit 0
fi
fi
# search a website specified by the -w switch (example: ws -w www.macosxhints.com ...)
if [[ -n "$w" ]] && [[ $y -eq 0 ]]; then
if [[ -n "$t" ]] && [[ -n "$p" ]]; then
if [[ -n "$search" ]]; then t="$t $search"; fi
F1="$(echo "$t" | url_encoding)"
F2="$(echo "$p" | url_encoding)"
str='%22'
F2="$str$F2$str"
F="$F2%20$F1"
$open "http://www.google.com/search?q=site%3A$w%20$F"
exit 0
elif [[ -n "$p" ]]; then
if [[ -n "$search" ]]; then # strings in $search will be added as search terms
t="$search"
F1="$(echo "$t" | url_encoding)"
F2="$(echo "$p" | url_encoding)"
str='%22'
F2="$str$F2$str"
F="$F2%20$F1"
$open "http://www.google.com/search?q=site%3A$w%20$F"
exit 0
else
F="$(echo "$p" | url_encoding)"
str='%22'
F="$str$F$str"
$open "http://www.google.com/search?q=site%3A$w%20$F"
exit 0
fi
elif [[ -n "$t" ]]; then
if [[ -n "$search" ]]; then t="$t $search"; fi
F="$(echo "$t" | url_encoding)"
$open "http://www.google.com/search?q=site%3A$w%20$F"
exit 0
else
# if there are no search terms given at all, just open the original URL stored in $ow
if [[ -z "$search" ]]; then
# check if libidn is available
if [[ ! -e "/opt/local/bin/idn" ]]; then
echo $'You do not have libidn installed at: /opt/local/bin/idn\nPlease install it via MacPorts!\nSee: http://www.macports.org/install.php'
exit 1
fi
w="$(echo "$ow" | CHARSET=UTF-8 idn --quiet)"
$open "http://$w"
exit 0
fi
F="$(echo "$search" | url_encoding)"
$open "http://www.google.com/search?q=site%3A$w%20$F"
exit 0
fi
fi
# Wikipedia
if [[ $wp -eq 1 ]]; then
if [[ -n "$t" ]] && [[ -n "$p" ]]; then
if [[ -n "$search" ]]; then t="$t $search"; fi
F1="$(echo "$t" | url_encoding)"
F2="$(echo "$p" | url_encoding)"
str='%22'
F2="$str$F2$str"
F="$F2%20$F1"
$open "http://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=$F&=MediaWiki+search&fulltext=Search"
exit 0
elif [[ -n "$p" ]]; then
if [[ -n "$search" ]]; then
t="$search" # set $t to $search since $t is empty
F1="$(echo "$t" | url_encoding)"
F2="$(echo "$p" | url_encoding)"
str='%22'
F2="$str$F2$str"
F="$F2%20$F1"
$open "http://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=$F&=MediaWiki+search&fulltext=Search"
exit 0
else
F="$(echo "$p" | url_encoding)"
str='%22'
F="$str$F$str"
$open "http://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=$F&=MediaWiki+search&fulltext=Search"
exit 0
fi
elif [[ -n "$t" ]]; then
if [[ -n "$search" ]]; then t="$t $search"; fi
F="$(echo "$t" | url_encoding)"
$open "http://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=$F&=MediaWiki+search&fulltext=Search"
exit 0
else
if [[ -z "$search" ]]; then $open "http://en.wikipedia.org"; exit 0; fi # just open the given URL
F="$(echo "$search" | url_encoding)"
$open "http://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=$F&=MediaWiki+search&fulltext=Search"
exit 0
fi
fi
# http://www.yahoo.com
if [[ $y -eq 1 ]]; then
if [[ -n "$w" ]]; then # if a website is specified ...
str="$search"
if [[ -n "$p" ]]; then str="$str $p"; fi
if [[ -n "$t" ]]; then str="$str $t"; fi
F="$(echo "$str" | url_encoding)"
$open "http://search.yahoo.com/search?p=site%3A$w%20$F"
elif [[ -n "$t" ]] && [[ -n "$p" ]]; then
if [[ -n "$search" ]]; then t="$t $search"; fi
F1="$(echo "$t" | url_encoding)"
F2="$(echo "$p" | url_encoding)"
str='%22'
F2="$str$F2$str"
F="$F2%20$F1"
$open "http://search.yahoo.com/search?p=$F"
exit 0
elif [[ -n "$p" ]]; then
if [[ -n "$search" ]]; then
t="$search" # set $t to $search since $t is empty
F1="$(echo "$t" | url_encoding)"
F2="$(echo "$p" | url_encoding)"
str='%22'
F2="$str$F2$str"
F="$F2%20$F1"
$open "http://search.yahoo.com/search?p=$F"
exit 0
else
F="$(echo "$p" | url_encoding)"
str='%22'
F="$str$F$str"
$open "http://search.yahoo.com/search?p=$F"
exit 0
fi
elif [[ -n "$t" ]]; then
if [[ -n "$search" ]]; then t="$t $search"; fi
F="$(echo "$t" | url_encoding)"
$open "http://search.yahoo.com/search?p=$F"
exit 0
else
if [[ -z "$search" ]]; then $open "http://search.yahoo.com"; exit 0; fi # just open the given URL
F="$(echo "$search" | url_encoding)"
$open "http://search.yahoo.com/search?p=$F"
exit 0
fi
fi
# Google maps
if [[ $gm -eq 1 ]]; then
if [[ -z "$search" ]] && [[ -n "$p" ]] && [[ -n "$t" ]]; then $open "http://maps.google.com"; exit 0; fi # just open the given URL
str="$search"
if [[ -n "$p" ]]; then str="$str $p"; fi
if [[ -n "$t" ]]; then str="$str $t"; fi
F="$(echo "$str" | url_encoding)"
$open "http://maps.google.com/maps?q=$F"
exit 0
fi
export IFS=$OIFS
export PATH=$OPATH
exit 0