Advertisement
Braber01

zirc mod 2

Sep 3rd, 2011
413
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 30.67 KB | None | 0 0
  1. #!/bin/zsh
  2. # vim:noet fdm=marker sw=4 ts=4
  3.  
  4. ZIRC_VERSION="0.2"
  5.  
  6. # ZIRC - A 100% ZSH IRC client
  7. #
  8. # Copyright (C) 2006 by Andrew Ruder <andy@aeruder.net>
  9. # Copyright (C) 2006 by Gergely Nagy <gergely-nagy@gmail.com>
  10. #
  11. # This IRC client is pretty ridiculous, I made it entirely as a joke, but it
  12. # actually works fairly decently for as little work has been put into it.
  13. # And of course, afaik, there are *no* external commands used in the making
  14. # of this program.  No grep, no sed, nothing... pretty cool :)
  15. #
  16. # Guide to using it:
  17. #   Step 1) Source this file.
  18. #           . ./zirc or whatever
  19. #           You can even put this into your .zshrc, it won't hurt anything
  20. #           besides the creation of several _zirc_*/zirc_* functions.
  21. #   Step 2) (Optional) Run zirc_aliases
  22. #           This sets up several aliases to make it easier to use.  Basically
  23. #           it strips the zirc_ front end off of everything.
  24. #   Step 3) (Optional) Run zirc_unquote to turn off autoquoting and
  25. #           zirc_quote to turn it on (default on).  This will quote shell
  26. #           characters as you type on the ZIRC commands.
  27. #   Step 4) Run zirc_connect
  28. #           It'll explain the syntax and the fairly standardized environment
  29. #           variables controlling its behavior.
  30. #   Step 5) Use zirc_msg to message, zirc_pmsg to private message.
  31. #           zirc_switch can change to another channel. (zirc_switch somechan)
  32. #           or
  33. #           zirc_query can change to anything
  34. #   Step 6) zirc_last is very handy as it switches to the channel/user that
  35. #           last said something to you.
  36. #
  37. #   Prompt integration: a few environment variables can help you on your way.
  38. #     $ZIRC_CURRENT = current focus
  39. #     $ZIRC_NICK    = current nickname
  40. #     $ZIRC_SERVER  = connected server
  41. #
  42. # This program is free software; you can redistribute it and/or modify it under
  43. # the terms of the GNU General Public License as published by the Free Software
  44. # Foundation; either version 2 of the License, or (at your option) any later
  45. # version.
  46.  
  47. [[ -z "$modules[zsh/net/tcp]" ]] && zmodload zsh/net/tcp
  48. [[ -z "$modules[zsh/zselect]" ]] && zmodload zsh/zselect
  49.  
  50. PS1="%m @ %~ :$ZIRC_CURRENT %% "
  51.  
  52. ZIRC_PARAMS=( ZIRC_NICK ZIRC_USER ZIRC_NAME ZIRC_PORT ZIRC_HOST )
  53.  
  54. if ! [[ -z "$ZIRC_FD" ]] && ! [[ -z "$functions[zirc_disconnect]" ]] ; then
  55.     zirc_disconnect
  56. fi
  57.  
  58. ZIRC_VARS=( ZIRC_LAST ZIRC_CHANNELS ZIRC_CURRENT ZIRC_LOWERCASER ZIRC_FD ZIRC_SERVER "${ZIRC_PARAMS[@]}" )
  59. ZIRC_UNSETSTRING="unset ${ZIRC_VARS[*]}"
  60. eval "$ZIRC_UNSETSTRING"
  61.  
  62. typeset -g "$ZIRC_VARS[@]"
  63.  
  64. typeset -A ZIRC_PARAM_DEFS
  65. ZIRC_PARAM_DEFS[ZIRC_NICK]="Nickname:\$IRCNICK:$USERNAME"
  66. ZIRC_PARAM_DEFS[ZIRC_USER]="Username:\$IRCUSER:$USERNAME"
  67. ZIRC_PARAM_DEFS[ZIRC_PORT]="Port:\$IRCPORT:8001"
  68. ZIRC_PARAM_DEFS[ZIRC_NAME]="Real name:\$IRCNAME:Ben Raber"
  69. ZIRC_PARAM_DEFS[ZIRC_HOST]="Host name:\$IRCHOST:localhost"
  70.  
  71.  
  72. # alias definitions {{{
  73. typeset -A ZIRC_ALIAS_DEFS
  74. ZIRC_ALIAS_DEFS[me]='zirc_action';
  75. ZIRC_ALIAS_DEFS[nick]='zirc_nick';
  76. ZIRC_ALIAS_DEFS[msg]='zirc_msg';
  77. ZIRC_ALIAS_DEFS[pmsg]='zirc_pmsg';
  78. ZIRC_ALIAS_DEFS[quit]='zirc_quit';
  79. ZIRC_ALIAS_DEFS[ctopic]='zirc_topic';
  80. ZIRC_ALIAS_DEFS[topic]='zirc_checktopic';
  81. ZIRC_ALIAS_DEFS[part]='zirc_part';
  82. ZIRC_ALIAS_DEFS[last]='zirc_last';
  83. ZIRC_ALIAS_DEFS[join]='zirc_join';
  84. ZIRC_ALIAS_DEFS[sw]='zirc_switch';
  85. ZIRC_ALIAS_DEFS[query]='zirc_query';
  86. ZIRC_ALIAS_DEFS[connect]='zirc_connect';
  87. ZIRC_ALIAS_DEFS[help]='zirc_help';
  88. ZIRC_ALIAS_DEFS[mode]='zirc_mode';
  89. ZIRC_ALIAS_DEFS[op]='zirc_op';
  90. ZIRC_ALIAS_DEFS[deop]='zirc_deop';
  91. ZIRC_ALIAS_DEFS[voice]='zirc_voice';
  92. ZIRC_ALIAS_DEFS[devoice]='zirc_devoice';
  93. ZIRC_ALIAS_DEFS[names]='zirc_names';
  94. ZIRC_ALIAS_DEFS[whois]='zirc_whois';
  95. ZIRC_ALIAS_DEFS[who]='zirc_who';
  96. ZIRC_ALIAS_DEFS[kick]='zirc_kick';
  97. ZIRC_ALIAS_DEFS[away]='zirc_away';
  98. # }}}
  99.  
  100.  
  101. # zirc_connect parameter handling {{{
  102.  
  103. # Print out help for the environment variables using the
  104. # ZIRC_PARAM_DEFS and ZIRC_PARAMS variables as a reference
  105. function _zirc_param_help {
  106.     local a b
  107.     tput setaf 1
  108.     tput bold
  109.     echo -e "Environment variables:"
  110.     for a in "${ZIRC_PARAMS[@]}"; do
  111.         b=( ${(s/:/)${ZIRC_PARAM_DEFS[$a]}} )
  112.         echo -e "\t${b[2]} - ${b[1]} (default ${b[3]})"
  113.     done
  114.     tput sgr0
  115. }
  116.  
  117. # Fills in the variables in ZIRC_PARAMS using the correct
  118. # fallback values specified in ZIRC_PARAM_DEFS
  119. function _zirc_param_populate {
  120.     local a b
  121.     for a in "$ZIRC_PARAMS[@]"; do
  122.         b=( ${(s/:/)${ZIRC_PARAM_DEFS[$a]}} )
  123.         if [ -z "${(e)b[2]}" ]; then
  124.             eval "${a}=\"\${b[3]}\""
  125.         else
  126.             eval "${a}=\"\${(e)b[2]}\""
  127.         fi
  128.     done
  129. }
  130.  
  131. # }}}
  132.  
  133.  
  134. # Lowercasing/string comparison code {{{
  135.  
  136. # Lowercasing according to rfc1459 strictly
  137. function _zirc_lowercase_strict_rfc1459 {
  138.     local msg="${(L)1}"
  139.     msg=${msg//\[/\{}
  140.     msg=${msg//]/\}}
  141.     msg=${msg//\\/\|}
  142.     tput setaf 1
  143.     tput bold
  144.     echo "${msg}"
  145.     tput sgr0
  146. }
  147.  
  148. # Lowercasing according to rfc1459
  149. function _zirc_lowercase_rfc1459 {
  150.     local msg="$(_zirc_lowercase_strict_rfc1459 "$1")"
  151.     msg=${msg//\~/^}
  152.     tput setaf 1
  153.     tput bold
  154.     echo "${msg}"
  155.     tput sgr0
  156. }
  157.  
  158. # Lowercasing using standard ascii rules
  159. function _zirc_lowercase_ascii {
  160.     tput setaf 1
  161.     tput bold
  162.     echo "${(L)1}"
  163.     tput sgr0
  164. }
  165.  
  166. # Lowercasing according to the current server's specs
  167. function _zirc_lowercase {
  168.     "$ZIRC_LOWERCASER" "$1"
  169. }
  170.  
  171. # Case-insensitive compare according to the case-mapping= spec for the server
  172. function _zirc_compare {
  173.     [[ "$("$ZIRC_LOWERCASER" "$1")" == "$("$ZIRC_LOWERCASER" "$2")" ]]
  174. }
  175.  
  176. # Determine if a prefix/word is referring to you
  177. function _zirc_isme {
  178.     _zirc_compare "$ZIRC_NICK" "$(_zirc_prefix_nick "$1")"
  179. }
  180.  
  181. # }}}
  182.  
  183.  
  184. # data from server parsing {{{
  185.  
  186. # Parse a line like
  187. #   :blah!host blah3 blah4 :Message with lots of words
  188. # and output
  189. #   blah!host
  190. #   blah3
  191. #   blah4
  192. #   Message with lots of words
  193. function _zirc_parse_server_line {
  194.     local readval args
  195.     args=()
  196.     readval=( "${(f)$(_zirc_parse_server_prefix "$1")}" )
  197.     args+=( "${readval[1]}" )
  198.     while ! [[ -z "${readval[2]}" ]] ; do
  199.         readval=( "${(f)$(_zirc_parse_server_word "${readval[2]}")}" ) #" Bug in vim highlighting
  200.         if ! [[ -z "${readval[1]}" ]]; then
  201.             args+=( "${readval[1]}" )
  202.         fi
  203.     done
  204.     tput setaf 1
  205.     tput bold
  206.     echo "${(F)args}"
  207.     tput sgr0
  208. }
  209.  
  210. # Parse a line like
  211. #   :blah!host blah3 blah4
  212. # and print out
  213. #   blah!host
  214. #   blah3 blah4
  215. function _zirc_parse_server_prefix {
  216.     setopt localoptions extendedglob
  217.     local line prefix
  218.     line="${1## #}"
  219.     if [[ "${line[1]}" != ":" ]]; then
  220.         prefix=""
  221.     else
  222.         prefix="${line%% *}"
  223.         if [[ "$prefix" == "$line" ]]; then
  224.             line=""
  225.         else
  226.             line="${line#* }"
  227.         fi
  228.     fi
  229.     tput setaf 1
  230.     tput bold
  231.     echo "${prefix#:}"
  232.     echo "$line"
  233.     tput sgr0
  234. }
  235.  
  236. # Parse out a single word from a line, so
  237. #   blah3 blah4 :Message
  238. # prints out:
  239. #   blah3
  240. #   blah4 :Message
  241. # again:
  242. #   blah4
  243. #   :Message
  244. # again
  245. #   Message
  246. #   <empty line>
  247. function _zirc_parse_server_word {
  248.     setopt localoptions extendedglob
  249.     local line word
  250.     line="${1## #}"
  251.     if [[ "${line[1]}" != ":" ]]; then
  252.         word="${line%% *}"
  253.         if [[ "$word" == "$line" ]]; then
  254.             line=""
  255.         else
  256.             line="${line#* }"
  257.         fi
  258.     else
  259.         word="${line#:}"
  260.         line=""
  261.     fi
  262.     tput setaf 1
  263.     tput bold
  264.     echo "$word"
  265.     echo "$line"
  266.     tput sgr0
  267. }
  268.  
  269. # Split a prefix and get nick (nick!host)
  270. #   Input: nick!host or nick
  271. #   Output:
  272. #     <empty-line>
  273. function _zirc_prefix_nick {
  274.     local a
  275.     a=( "${(f)$(_zirc_split_prefix "$1")}" )
  276.     tput setaf 1
  277.     tput bold
  278.     echo "${a[1]}"
  279.     tput sgr0
  280. }
  281.  
  282. # Split a prefix and get host (nick!host)
  283. #  Input: nick!host
  284. #  Output:
  285. #    host
  286. #  Input: nick
  287. #  Output:
  288. #    <empty-line>
  289. function _zirc_prefix_host {
  290.     local a
  291.     a=( "${(f)$(_zirc_split_prefix "$1")}" )
  292.     tput setaf 1
  293.     tput bold
  294.     echo "${a[2]}"
  295.     tput sgr0
  296. }
  297.  
  298. # Split a prefix
  299. # Input: nick!host
  300. # Output:
  301. #   nick
  302. #   host
  303. # Input: nick
  304. # Output:
  305. #   nick
  306. #   <empty-line>
  307. function _zirc_split_prefix {
  308.     local a
  309.     a=( ${(s:!:)1} )
  310.     [[ ${#a} == "1" ]] && a+=( '' )
  311.     tput setaf 1
  312.     tput bold
  313.     echo "${(F)a}"
  314.     tput sgr0
  315. }
  316.  
  317. # }}}
  318.  
  319.  
  320. # CTCP handling {{{
  321.  
  322. # Print out the generic ctcp message
  323. # Args: prefix command where ctcp msg
  324. function _zirc_generic_ctcp {
  325.     local pref="$1" comm="$2"
  326.     local where="$3" ctcp="$4"
  327.     local msg="$5"
  328.     local who="$(_zirc_prefix_nick "$pref")"
  329.  
  330.     _zirc_echo -n "<CTCP> <$who"
  331.     _zirc_isme "$where" || _zirc_echo -n ":$where"
  332.     _zirc_echo "> $ctcp $msg"
  333. }
  334.  
  335. # Write out a CTCP request
  336. # Args: prefix command where ctcp msg
  337. function _zirc_ctcp_request_write {
  338.     local msg
  339.     if ! [[ -z "$2" ]] && ! [[ -z "$3" ]]; then
  340.         msg="$2 $3"
  341.     else
  342.         msg="$2"
  343.     fi
  344.  
  345. tput setaf 1
  346. tput bold
  347.     _zirc_write "`printf "PRIVMSG %s :\001%s\001" "$1" "$msg"`"
  348. tput sgr0
  349. }
  350.  
  351. # Write out a CTCP reply
  352. # Args: where ctcp message
  353. function _zirc_ctcp_reply_write {
  354.     local msg
  355.     if ! [[ -z "$2" ]] && ! [[ -z "$3" ]]; then
  356.         msg="$2 $3"
  357.     else
  358.         msg="$2"
  359.     fi
  360.     tput setaf 1
  361.     tput bold
  362.     _zirc_write "`printf "NOTICE %s :\001%s\001" "$1" "$msg"`"
  363.     tput sgr0
  364. }
  365.  
  366. # Handle a VERSION request
  367. function _zirc_ctcp_request_VERSION {
  368.     _zirc_generic_ctcp "$@"
  369.     local pref="$1"
  370.     local who="$(_zirc_prefix_nick "$pref")"
  371.  
  372.     _zirc_ctcp_reply_write "$who" "VERSION" "ZIRC $ZIRC_VERSION - 100% zsh!!"
  373. }
  374.  
  375. # Handle a PING request
  376. function _zirc_ctcp_request_PING {
  377.     local pref="$1" msg="$5"
  378.     local who="$(_zirc_prefix_nick "$pref")"
  379.     _zirc_echo "Received a CTCP PING from $who"
  380.  
  381.     _zirc_ctcp_reply_write "$who" "PING" "$5"
  382. }
  383.  
  384. # Handle an ACTION
  385. function _zirc_ctcp_reply_ACTION {
  386.     local pref="$1" where="$3" msg="$5"
  387.     local who="$(_zirc_prefix_nick "$pref")"
  388.  
  389.     if ( _zirc_isme "$where" ); then
  390.         _zirc_compare "$ZIRC_CURRENT" "$who" || ZIRC_LAST="$who"
  391.         _zirc_echo "*** * $who $msg"
  392.     else
  393.         _zirc_echo -n "* $who"
  394.         _zirc_compare "$ZIRC_CURRENT" "$where" || {
  395.             ZIRC_LAST="$where"
  396.             _zirc_echo -n ":$where"
  397.         }
  398.         _zirc_echo " $msg"
  399.     fi
  400. }
  401.  
  402. # Handle ACTION requests just like replies
  403. function _zirc_ctcp_request_ACTION {
  404.     _zirc_ctcp_reply_ACTION "$@"
  405. }
  406.  
  407. # Handle all other CTCP requests
  408. function _zirc_ctcp_request_other {
  409.     _zirc_generic_ctcp "$@"
  410. }
  411.  
  412. # Handle all other CTCP replies
  413. function _zirc_ctcp_reply_other {
  414.     _zirc_generic_ctcp "$@"
  415. }
  416.  
  417. # Parse the CTCP stuff and call the appropriate CTCP function above
  418. # args: pref command where ctcp+message
  419. function _zirc_command_CTCP {
  420.     local pref="$1" comm="$2"
  421.     local who="$(_zirc_prefix_nick "$pref")"
  422.     shift 2
  423.     local where="$1" msg="$2"
  424.     local ctcp func args ctype
  425.    
  426.     if [[ "$((#msg))" == "1" ]]; then
  427.         msg="${msg#?}"
  428.     fi
  429.  
  430.     if [[ "$((##${msg[-1]}))" == "1" ]]; then
  431.         msg="${msg%?}"
  432.     fi
  433.    
  434.     ctcp="${(U)msg%% *}"
  435.     msg="${msg#* }"
  436.     if [[ "$msg" == "$ctcp" ]]; then
  437.         msg=""
  438.     fi
  439.     ctype="request"
  440.     [[ "$comm" == "NOTICE" ]] && ctype="reply"
  441.  
  442.     func="_zirc_ctcp_${ctype}_${ctcp}"
  443.  
  444.     if [[ -z "${functions[${func}]}" ]]; then
  445.         func="_zirc_ctcp_${ctype}_other"
  446.     fi
  447.  
  448.     args=( "$pref" "$comm" "$where" "$ctcp" "$msg" )
  449.  
  450.     "${func}" "$args[@]"
  451. }
  452.  
  453. # }}}
  454.  
  455.  
  456. # Server command handling {{{
  457.  
  458. # An echo that should be used by anything automatically
  459. # called (commands).  It invalidates the current prompt line first.
  460. function _zirc_echo {
  461.     zle -I
  462.     tput setaf 1
  463.     tput bold
  464.     echo "$@"
  465.     tput sgr0
  466. }
  467.  
  468. # Handle private messages
  469. function _zirc_command_PRIVMSG {
  470.     local pref="$1" comm="$2"
  471.     shift 2
  472.     local who="$(_zirc_prefix_nick "$pref")"
  473.     local where="$1" msg="$2"
  474.     if [[ "$((#msg))" == "1" ]]; then
  475.         _zirc_command_CTCP "$pref" "$comm" "$where" "$msg"
  476.         return 0
  477.     fi
  478.  
  479.     if ( _zirc_isme "$where" ); then
  480.         _zirc_compare "$ZIRC_CURRENT" "$who" || ZIRC_LAST="$who"
  481.         _zirc_echo "*** <$who> $msg"
  482.     else
  483.         _zirc_echo -n "<$who"
  484.         _zirc_compare "$where" "$ZIRC_CURRENT" || {
  485.             _zirc_echo -n ":$where"
  486.             ZIRC_LAST="$where"
  487.         }
  488.         _zirc_echo "> $msg"
  489.     fi
  490. }
  491.  
  492. # Handle nickname changes
  493. function _zirc_command_NICK {
  494.     local pref="$1" newnick="$3"
  495.     local who="$(_zirc_prefix_nick "$pref")"
  496.  
  497.     if [[ "$who" == "$ZIRC_CURRENT" ]]; then
  498.         ZIRC_CURRENT="${newnick}"
  499.     fi
  500.  
  501.     _zirc_isme "$pref" && ZIRC_NICK="$newnick"
  502.  
  503.     _zirc_echo "$who is now known as $newnick"
  504. }
  505.  
  506. # Handle channel joins
  507. function _zirc_command_JOIN {
  508.     local pref="$1" comm="$2"
  509.     shift 2
  510.     local who="$(_zirc_prefix_nick "$pref")"
  511.     local at="$(_zirc_prefix_host "$pref")"
  512.     local where="$1"
  513.  
  514.     _zirc_echo "$who ($at) has joined $where"
  515.     _zirc_isme "$pref" && {
  516.         ZIRC_LAST="$ZIRC_CURRENT"
  517.         ZIRC_CURRENT="$where"
  518.         ZIRC_CHANNELS+=("$where")
  519.     }
  520. }
  521.  
  522. # Handle channel parts
  523. function _zirc_command_PART {
  524.     local pref="$1" comm="$2" where="$3" msg="$4"
  525.     local who="$(_zirc_prefix_nick "$pref")"
  526.  
  527.     _zirc_echo "$who has left $where ($msg)"
  528.     _zirc_isme "$pref" && {
  529.         [[ "$ZIRC_CURRENT" == "$where" ]] && ZIRC_CURRENT="$ZIRC_LAST"
  530.         ZIRC_CHANNELS[(r)$where]=()
  531.     }
  532. }
  533.  
  534. # Handle people quitting
  535. function _zirc_command_QUIT {
  536.     local pref="$1" comm="$2" msg="$3"
  537.     local who="$(_zirc_prefix_nick "$pref")"
  538.  
  539.     _zirc_echo "$who has quit IRC ($msg)"
  540. }
  541.  
  542. # Handle topic changes
  543. function _zirc_command_TOPIC {
  544.     local pref="$1" comm="$2" where="$3" msg="$4"
  545.     local who="$(_zirc_prefix_nick "$pref")"
  546.  
  547.     _zirc_echo "$who has changed the topic in $where to '$msg'"
  548. }
  549.  
  550. # Handle mode changes
  551. function _zirc_command_MODE {
  552.     local pref="$1" comm="$2" object="$3" mode="$4"
  553.     local who="$(_zirc_prefix_nick "$pref")"
  554.     local rest
  555.     rest=( "${@[4,-1]}" )
  556.     rest=( " "${^rest} )
  557.     rest=${(j::)rest}
  558.  
  559.     _zirc_echo "$who sets mode $mode ${object}${rest}"
  560. }
  561.  
  562. # Handle invites
  563. function _zirc_command_INVITE {
  564.     local pref="$1" comm="$2" where="$4"
  565.     local who="$(_zirc_prefix_nick "$pref")"
  566.  
  567.     _zirc_echo "$who has invited you to $where"
  568. }
  569.  
  570. # Handle kicks
  571. function _zirc_command_KICK {
  572.     local pref="$1" comm="$2" where="$3" user="$4" msg="$5"
  573.     local who="$(_zirc_prefix_nick "$pref")"
  574.  
  575.     _zirc_echo "$user was kicked from $where by $who ($msg)"
  576. }
  577.  
  578. # Handle pong messages (shouldn't get these generally, but just in case)
  579. function _zirc_command_PONG {
  580. }
  581.  
  582. # Handle notices, although we just forward this onto the privmsg code
  583. function _zirc_command_NOTICE {
  584.     _zirc_command_PRIVMSG "$@"
  585.     return
  586. }
  587.  
  588. # Handle wallops
  589. function _zirc_command_WALLOPS {
  590.     local pref="$1" comm="$2" msg="$3"
  591.     local who="$(_zirc_prefix_nick "$pref")"
  592.     _zirc_echo "Wallops from $who: $msg"
  593. }
  594.  
  595. # Handle IRC Errors
  596. function _zirc_command_ERROR {
  597.     local pref="$1" comm="$2"
  598.     shift 2
  599.     _zirc_echo "ERROR: ${(j: :)@}"
  600. }
  601.  
  602. # Handle server pings
  603. function _zirc_command_PING {
  604.     local pref="$1" comm="$2"
  605.     shift 2
  606.     _zirc_write "PONG :$1"
  607. }
  608.  
  609. # RPL_WELCOME handler... this will (among other things)
  610. # inform us of our true nickname
  611. function _zirc_command_numeric_001 {
  612.     ZIRC_NICK="$3"
  613. }
  614.  
  615. # RPL_ISUPPORT this tells us how to handle casemapping
  616. function _zirc_command_numeric_005 {
  617.     case "$4" in
  618.         *casemapping=rfc1459*)
  619.             ZIRC_LOWERCASER="_zirc_lowercase_rfc1459"
  620.             ;;
  621.         *casemapping=strict-rfc1459*)
  622.             ZIRC_LOWERCASER="_zirc_lowercase_strict_rfc1459"
  623.             ;;
  624.         *casemapping=ascii*)
  625.             ZIRC_LOWERCASER="_zirc_lowercase_ascii"
  626.             ;;
  627.     esac
  628. }
  629.  
  630. # Handle numeric commands
  631. function _zirc_command_numeric {
  632.     local pref="$1" comm="$2"
  633.     _zirc_echo "-- ${(j: :)@[4,-1]}"
  634.     if ! [[ -z "$functions[_zirc_command_numeric_${comm}]" ]]; then
  635.         _zirc_command_numeric_"$comm" "$@"
  636.     fi
  637. }
  638.  
  639. # catchall for unhandled commands
  640. function _zirc_command_other {
  641.     setopt localoptions extendedglob
  642.     local pref="$1" comm="$2"
  643.     shift 2
  644.     if [[ "$comm" == [0-9]## ]]; then
  645.         _zirc_command_numeric "$pref" "$comm" "$@"
  646.         return 0
  647.     fi
  648. }
  649.  
  650. # }}}
  651.  
  652.  
  653. # ZLE hooks {{{
  654.  
  655. # Parse a single line of incoming data
  656. function _zirc_handle_incoming_data_piece {
  657.     local line comm func output
  658.     line="$1"
  659.  
  660.     line=( "${(f)$(_zirc_parse_server_line "$line")}" )
  661.  
  662.     comm="${(U)line[2]}"
  663.     func="_zirc_command_${comm}"
  664.  
  665.     if [[ -z "${functions[${func}]}" ]]; then
  666.         func="_zirc_command_other"
  667.     fi
  668.  
  669.     "$func" "$line[@]"
  670. }
  671.  
  672. # The ZLE informs this when there is data.  Grab the data, and then
  673. # grab any additional data available (using zselect) and passing all
  674. # of this back off to the _zirc_handle_incoming_data_piece function
  675. function _zirc_handle_incoming_data {
  676.     local fds line
  677.  
  678.     if [[ "$1" != "$ZIRC_FD" ]]; then
  679.         zle -I
  680.         tput setaf 1
  681.         tput bold
  682.         echo "ZIRC: Handling some other file handle???"
  683.         tput sgr0
  684.         return 1
  685.     fi
  686.  
  687.     while true; do
  688.         if ! read -r line <&$ZIRC_FD; then
  689.             zle -I
  690.             zirc_disconnect
  691.             return 1
  692.         fi
  693.         if [[ "$((##${line[-1]}))" == "13" ]]; then
  694.             line="${line%?}"
  695.         fi
  696.  
  697.         _zirc_handle_incoming_data_piece "$line"
  698.  
  699.         fds=()
  700.         zselect -r -t 0 -a fds $ZIRC_FD
  701.         if [[ "${#fds}" != "2" ]]; then
  702.             break
  703.         fi
  704.     done
  705. }
  706.  
  707. # }}}
  708.  
  709.  
  710. # User commands and utility functions used by them {{{
  711.  
  712. # Write out a message to the server.  It puts on the correct line ending
  713. # for the IRC protocol too
  714. function _zirc_write {
  715.     local a
  716.  
  717.     if [[ -z "$ZIRC_FD" ]]; then
  718.         return 1
  719.     fi
  720.  
  721.     if [[ -z "$1" ]]; then
  722.         return 0
  723.     fi
  724.  
  725.     a="$@"
  726.     tput setaf 1
  727.     tput bold
  728.     printf "%s\r\n" "$a" >&$ZIRC_FD
  729.     tput sgr0
  730. }
  731.  
  732. # Send the initial connection lines to the server
  733. function _zirc_send_connect_lines {
  734.     _zirc_write "NICK $ZIRC_NICK"
  735.     _zirc_write "USER $ZIRC_USER $ZIRC_HOST $ZIRC_SERVER :$ZIRC_NAME"
  736. }
  737.  
  738. # Input:
  739. #   channel name (or part of a channel name)
  740. # Output:
  741. #   shortest channel that matches *<input>
  742. function _zirc_channel_match {
  743.     local chan="$1"
  744.     local chans shortest a
  745.  
  746.     chan="*${chan}"
  747.     chans=( "${ZIRC_CHANNELS[@]}" )
  748.     chans=( ${(e):-\${(M)chans:#$chan}} )
  749.  
  750.     if [[ "${#chans}" == "0" ]]; then
  751.         echo ""
  752.         return 1
  753.     fi
  754.  
  755.     shortest=" "; shortest="${(l:1000:: :)shortest}"
  756.  
  757.     for a in "${chans[@]}"; do
  758.         (( ${#a} < ${#shortest} )) && shortest="${a}"
  759.     done
  760.    
  761.     tput setaf 1
  762.     tput bold
  763.     echo "${shortest}"
  764.     tput sgr0
  765.     return 0
  766. }
  767.  
  768. # Switch focus.  This uses _zirc_channel_match so the globbing will make it
  769. # easier to switch channels.
  770. #
  771. #   zirc_switch step
  772. #
  773. # would change to #gnustep if you were correctly connected to that channel
  774. function zirc_switch {
  775.     local chan="$1"
  776.     local chans shortest a
  777.     zirc_connected || {
  778.     tput setaf 1;
  779.     tput bold;
  780.     echo "Not connected" ; return 1; }
  781.     if [[ -z "$chan" ]]; then
  782.         tput setaf 1
  783.         tput bold
  784.         echo "Usage: $0 <channel>"
  785.         echo "Switches current channel focus (Current: '${ZIRC_CURRENT}')"
  786.         echo "This command is only used for channels, use zirc_query for a more"
  787.         echo "general solution."
  788.         tput sgr0
  789.         return 1
  790.     fi
  791.  
  792.     chan="$(_zirc_channel_match "$chan")"
  793.  
  794.     if [[ -z "$chan" ]]; then
  795.         tput setaf 1
  796.         tput bold
  797.         echo "Could not find anything for '$1'"
  798.         echo "Current channels: ${(j:,:)ZIRC_CHANNELS}"
  799.         tput sgr0
  800.         return 1
  801.     fi
  802.  
  803.     ZIRC_LAST="$ZIRC_CURRENT"
  804.     ZIRC_CURRENT="${chan}"
  805.     tput setaf 1
  806.     tput bold
  807.     echo "Switched to $ZIRC_CURRENT"
  808.     tput sgr0
  809.     return 0
  810. }
  811.  
  812. # Sets channel modes
  813. function zirc_mode {
  814.     local modes="${(j: :)@}"
  815.  
  816.     if [[ -z "$modes" ]]; then
  817.         tput setaf 1
  818.         tput bold
  819.         echo "Usage: $0 <modes>"
  820.         echo "Set channel modes to <modes>."
  821.         echo "Sends to the current focus (Current: '$ZIRC_CURRENT')."
  822.         tput sgr0
  823.         return 1
  824.     fi
  825.  
  826.     zirc_connected || {
  827.     tput setaf 1;
  828.     tput bold;
  829.     echo "Not connected";
  830.     tput sgr0
  831.     return 1 }
  832.     _zirc_write "MODE ${ZIRC_CURRENT} ${modes}"
  833. }
  834.  
  835. # Set a single mode for a list of users
  836. function _zirc_batch_mode {
  837.     local mode="$1"
  838.     shift
  839.     local users="${(j: :)@}"
  840.  
  841.     for user in $users; do
  842.         zirc_mode "$mode" "$user"
  843.     done
  844. }
  845.  
  846. # Give operator status to user(s)
  847. function zirc_op {
  848.     if [[ -z "$@" ]]; then
  849.         tput setaf 1
  850.         tput bold
  851.         echo "Usage: $0 <users>"
  852.         echo "Give operator status to <users>."
  853.         echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
  854.         tput sgr0
  855.         return 1
  856.     fi
  857.  
  858.     zirc_connected || {
  859.     tput setaf 1;
  860.     tput bold;
  861.     echo "Not connected";
  862.     tput sgr0;
  863.     return 1}
  864.  
  865.     _zirc_batch_mode "+o" $@
  866. }
  867.  
  868. # Revoke operator status from user(s)
  869. function zirc_deop {
  870.     if [[ -z "$@" ]]; then
  871.         tput setaf 1;
  872.         tput bold
  873.         echo "Usage: $0 <users>"
  874.         echo "Revoke operator status from <users>."
  875.         echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
  876.         tput sgr0
  877.         return 1
  878.     fi
  879.  
  880.     zirc_connected || {
  881.     tput setaf 1;
  882.     tput bold;
  883.     echo "Not connected";
  884.     tput sgr0;
  885.     return 1}
  886.  
  887.     _zirc_batch_mode "-o" $@
  888. }
  889.  
  890. # Give a voice flag to user(s)
  891. function zirc_voice {
  892.     if [[ -z "$@" ]]; then
  893.         tput setaf 1;
  894.         tput bold;
  895.         echo "Usage: $0 <users>"
  896.         echo "Give a voice flag to <users>."
  897.         echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
  898.         tput sgr0
  899.         return 1
  900.     fi
  901.  
  902.     zirc_connected || {
  903.     tput setaf 1;
  904.     tput bold;
  905.     echo "Not connected";
  906.     tput sgr0;
  907.     return 1}
  908.  
  909.     _zirc_batch_mode "+v" $@
  910. }
  911.  
  912. # Revoke the voice flag from user(s)
  913. function zirc_devoice {
  914.     if [[ -z "$@" ]]; then
  915.         tput setaf 1
  916.         tput bold
  917.         echo "Usage: $0 <users>"
  918.         echo "Revoke the voice flag from <users>."
  919.         echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
  920.         tput sgr0
  921.         return 1
  922.     fi
  923.  
  924.     zirc_connected || {
  925.     tput setaf 1;
  926.     tput bold;
  927.     echo "Not connected";
  928.     tput sgr0;
  929.     return 1}
  930.  
  931.     _zirc_batch_mode "-v" $@
  932. }
  933.  
  934. # Query the names on a channel
  935. function zirc_names {
  936.     zirc_connected || {
  937.     tput setaf 1;
  938.     tput bold;
  939.     echo "Not connected";
  940.     tput sgr0;
  941.     return 1}
  942.  
  943.     _zirc_write "NAMES $ZIRC_CURRENT"
  944. }
  945.  
  946. # Issue a WHOIS request
  947. function zirc_whois {
  948.     if [[ -z "$1" ]]; then
  949.         tput setaf 1
  950.         tput bold
  951.         echo "Usage: $0 <user>"
  952.         echo "Get detailed information about <user>."
  953.         tput sgr0
  954.         return 1
  955.     fi
  956.  
  957.     zirc_connected || { echo "Not connected" ; return 1}
  958.  
  959.     _zirc_write "WHOIS $1"
  960. }
  961.  
  962. # Issue a WHO request
  963. function zirc_who {
  964.     local chan="${1:-${ZIRC_CURRENT}}"
  965.  
  966.     zirc_connected || { echo "Not connected" ; return 1}
  967.  
  968.     _zirc_write "WHO $chan"
  969. }
  970.  
  971. # Kick user from the current channel
  972. function zirc_kick {
  973.     if [[ -z "$@" ]]; then
  974.         tput setaf 1
  975.         tput bold
  976.         echo "Usage: $0 <user> [<reason>]"
  977.         echo "Kick <users> from the current channel, due to <reason>."
  978.         echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
  979.         tput sgr0
  980.         return 1
  981.     fi
  982.  
  983.     zirc_connected || {
  984.     tput setaf 1;
  985.     tput bold;
  986.     echo "Not connected";
  987.     tput sgr0
  988.     return 1}
  989.  
  990.     local user=$1
  991.     shift
  992.  
  993.     _zirc_write "KICK $ZIRC_CURRENT $user ${@:+:$@}"
  994. }
  995.  
  996. # Sets/unsets the automatic away message
  997. function zirc_away {
  998.     zirc_connected || {
  999.     tput setaf 1;
  1000.     tput bold
  1001.     echo "Not connected";
  1002.     tput sgr0
  1003.     return 1}
  1004.  
  1005.     _zirc_write "AWAY ${@:+:$@}"
  1006. }
  1007.  
  1008. # Just switch focus to the argument.  Don't check against anything else.
  1009. function zirc_query {
  1010.     local query="$1"
  1011.     zirc_connected || {
  1012.     tput setaf 1;
  1013.     tput bold;
  1014.     echo "Not connected";
  1015.     tput sgr0;
  1016.     return 1 }
  1017.     if [[ -z "$query" ]]; then
  1018.         tput setaf 1;
  1019.         tput bold;
  1020.         echo "Usage: $0 <user/channel>"
  1021.         echo "Switches current focus. (Current: '${ZIRC_CURRENT}')"
  1022.         echo "No expansion will be done on the parameter.  If you are switching"
  1023.         echo "to a channel, you may try zirc_switch instead as it will expand to"
  1024.         echo "the best match without you having to deal with the escaping."
  1025.         tput sgr0
  1026.         return 1
  1027.     fi
  1028.     ZIRC_LAST="$ZIRC_CURRENT"
  1029.     ZIRC_CURRENT="${query%% *}"
  1030.     tput setaf 1
  1031.     tput bold
  1032.     echo "Switched to $ZIRC_CURRENT"
  1033.     tput sgr0
  1034. }
  1035.  
  1036. # Switch to the last focused window or wherever there was a message last
  1037. function zirc_last {
  1038.     local a
  1039.     [[ -z "$ZIRC_LAST" ]] && return 0
  1040.     a="$ZIRC_CURRENT"
  1041.     ZIRC_CURRENT="${ZIRC_LAST}"
  1042.     ZIRC_LAST="$a"
  1043.     tput setaf 1
  1044.     tput bold
  1045.     echo "Switched to $ZIRC_CURRENT"
  1046.     tput sgr0
  1047. }
  1048.  
  1049. # Quit (with optional quit message)
  1050. function zirc_quit {
  1051.     local msg="${(j: :)@}"
  1052.     zirc_connected || {
  1053.     tput setaf 1;
  1054.     tput bold;
  1055.     echo "Not connected";
  1056.     tput sgr0;
  1057.     return 1 }
  1058.  
  1059.     [[ -z "$msg" ]] && msg="ZIRC $ZIRC_VERSION - 100% zsh, woot."
  1060.  
  1061.     _zirc_write "QUIT :$msg"
  1062. }
  1063.  
  1064. # Print out current focus.  Could be used to hook into prompts
  1065. function zirc_focus {
  1066.     zirc_connected || {
  1067.     tput setaf 1;
  1068.     tput bold;
  1069.     echo "Not connected";
  1070.     tput sgr0;
  1071.     return 1 }
  1072.     tput setaf 1;
  1073.     tput bold;
  1074.     echo "$ZIRC_CURRENT"
  1075.     tput sgr0
  1076. }
  1077.  
  1078. # Print out zirc_* functions and alias mappings
  1079. function zirc_help {
  1080.     local commands a
  1081.     commands=( "${(k)functions[@]}" )
  1082.     commands=( ${(M)commands:#zirc_*} )
  1083.     commands=( ${(o)commands} )
  1084.     commands=( "        "${^commands} )
  1085.     tput setaf 1
  1086.     tput bold
  1087.     echo "ZIRC Commands:"
  1088.     echo "${(F)commands}"
  1089.  
  1090.     echo
  1091.     echo "Aliases (if using zirc_aliases):"
  1092.     for a in "${(o@)${(k)ZIRC_ALIAS_DEFS[@]}}"; do
  1093.         echo "${(l.12...)a} => ${ZIRC_ALIAS_DEFS[$a]}"
  1094.     done
  1095.     tput sgr0
  1096.  
  1097.     return 0
  1098.  
  1099. }
  1100.  
  1101. # Change nickname to argument
  1102. function zirc_nick {
  1103.     local nick="$1"
  1104.     zirc_connected || {
  1105.     tput setaf 1;
  1106.     tput bold;
  1107.     echo "Not connected";
  1108.     tput sgr0;
  1109.     return 1 }
  1110.  
  1111.     if [[ -z "$nick" ]]; then
  1112.         tput setaf 1;
  1113.         tput bold;
  1114.         echo "Usage: $0 <nick>"
  1115.         echo "Change nickname to <nick>."
  1116.         tput sgr0;
  1117.         return 1
  1118.     fi
  1119.  
  1120.     _zirc_write "NICK ${nick%% *}"
  1121. }
  1122.  
  1123. # Message the current focus
  1124. function zirc_msg {
  1125.     local msg="${(j: :)@}"
  1126.     zirc_connected || {
  1127.     tput setaf 1;
  1128.     tput bold;
  1129.     echo "Not connected";
  1130.     tput sgr0;
  1131.     return 1 }
  1132.     if [[ -z "$msg" ]]; then
  1133.         tput setaf 1;
  1134.         tput bold;
  1135.         echo "Usage: $0 <message>"
  1136.         echo "Will message the current focus <message>."
  1137.         echo "Use zirc_query/zirc_switch to change focus. (Current: '${ZIRC_CURRENT}')"
  1138.         tput sgr0
  1139.         return 1
  1140.     fi
  1141.     if [[ -z "$ZIRC_CURRENT" ]]; then
  1142.         tput setaf 1;
  1143.         tput bold;
  1144.         echo "No current focus.  Use zirc_query/zirc_switch to change focus."
  1145.         tput sgr0
  1146.         return 1
  1147.     fi
  1148.    
  1149.     tput setaf 1;
  1150.     tput bold;
  1151.     echo "<$ZIRC_NICK:$ZIRC_CURRENT> ${msg}"
  1152.     tput sgr0;
  1153.     _zirc_write "PRIVMSG ${ZIRC_CURRENT} :${msg}"
  1154. }
  1155.  
  1156. # Message someone (temporarily changing focus then calling zirc_msg)
  1157. function zirc_pmsg {
  1158.     local who="$1"
  1159.     shift
  1160.     local msg="${(j: :)@}"
  1161.     local temp_current temp_result
  1162.  
  1163.     zirc_connected || {
  1164.     tput setaf 1;
  1165.     tput bold;
  1166.     echo "Not connected";
  1167.     tput sgr0;
  1168.     return 1 }
  1169.     if [[ -z "$msg" ]] || [[ -z "$who" ]]; then
  1170.         tput setaf 1;
  1171.         tput bold;
  1172.         echo "Usage: $0 <person> <message>"
  1173.         echo "Will message the <person> the message <message>."
  1174.         echo "Also see zirc_msg."
  1175.         tput sgr0
  1176.         return 1
  1177.     fi
  1178.     temp_current="$ZIRC_CURRENT"
  1179.     ZIRC_CURRENT="$who"
  1180.     zirc_msg "$msg"
  1181.     temp_result="$?"
  1182.     ZIRC_CURRENT="$temp_current"
  1183.     return "$temp_result"
  1184. }
  1185.  
  1186. # Join a channel
  1187. function zirc_join {
  1188.     local chan="$1"
  1189.     zirc_connected || {
  1190.     tput setaf 1;
  1191.     tput bold;
  1192.     echo "Not connected";
  1193.     tput sgr0;
  1194.     return 1 }
  1195.     if [[ -z "$chan" ]]; then
  1196.         tput setaf 1;
  1197.         tput bold;
  1198.         echo "Usage: $0 <channel>"
  1199.         echo "Will join the channel <channel>.  If <channel> starts with a letter"
  1200.         echo "or a number, it will be prepended with a '#'"
  1201.         tput sgr0;
  1202.         return 1
  1203.     fi
  1204.     [[ "$chan" == [a-zA-Z0-9]* ]] && chan="#${chan}"
  1205.  
  1206.     _zirc_write "JOIN ${chan%% *}"
  1207. }
  1208.  
  1209. # Leave a channel (with optional part message)
  1210. function zirc_part {
  1211.     local chan="$1" unchan="$1"
  1212.     shift
  1213.     local msg="${(j: :)@}"
  1214.     zirc_connected || {
  1215.     tput setaf 1;
  1216.     tput bold;
  1217.     echo "Not connected";
  1218.     tput sgr0;
  1219.     return 1 }
  1220.     if [[ -z "$chan" ]]; then
  1221.         tput setaf 1;
  1222.         tput bold;
  1223.         echo "Usage: $0 <channel> [<msg>]"
  1224.         echo "Will leave the channel <channel> with optional part message <msg>."
  1225.         echo "This routine will use the same matching method as zirc_switch so"
  1226.         echo "you don't have to type the '#' or any other tricky characters"
  1227.         tput sgr0;
  1228.         return 1
  1229.     fi
  1230.     chan="$(_zirc_channel_match "$chan")"
  1231.  
  1232.     if [[ -z "$chan" ]]; then
  1233.         tput setaf 1;
  1234.         tput bold;
  1235.         echo "Could not find anything for '$unchan'"
  1236.         echo "Current channels: ${(j:,:)ZIRC_CHANNELS}"
  1237.         tput sgr0;
  1238.         return 1
  1239.     fi
  1240.  
  1241.     _zirc_write "PART ${chan%% *} :${msg}"
  1242. }
  1243.  
  1244. # Change the topic in current focus
  1245. function zirc_topic {
  1246.     local topic="${(j: :)@}"
  1247.     zirc_connected || {
  1248.     tput setaf 1;
  1249.     tput bold;
  1250.     echo "Not connected";
  1251.     tput sgr0;
  1252.     return 1 }
  1253.     if [[ -z "$topic" ]]; then
  1254.         tput setaf 1;
  1255.         tput bold;
  1256.         echo "Usage: $0 <topic>"
  1257.         echo "Change the topic in the current channel.  Use zirc_switch"
  1258.         echo "to change the channel (Current: '$ZIRC_CURRENT')."
  1259.         tput sgr0
  1260.         return 1
  1261.     fi
  1262.  
  1263.     _zirc_write "TOPIC ${ZIRC_CURRENT} :${topic}"
  1264. }
  1265.  
  1266. # Send a CTCP action to the current focus
  1267. function zirc_action {
  1268.     local msg="${(j: :)@}"
  1269.     zirc_connected || {
  1270.     tput setaf 1;
  1271.     tput bold;
  1272.     echo "Not connected";
  1273.     tput sgr0;
  1274.     return 1 }
  1275.     if [[ -z "$msg" ]]; then
  1276.         tput setaf 1;
  1277.         tput bold;
  1278.         echo "Usage: $0 <message>"
  1279.         echo "Send 3rd person action <message>."
  1280.         echo "Sends to the current focus (Current: '$ZIRC_CURRENT')."
  1281.         tput sgr0;
  1282.         return 1
  1283.     fi
  1284.  
  1285.     tput setaf 1;
  1286.     tput bold;
  1287.     echo "* $ZIRC_NICK:$ZIRC_CURRENT ${msg}"
  1288.     tput sgr0;
  1289.     _zirc_write "$(printf "PRIVMSG $ZIRC_CURRENT :\001ACTION ${msg}\001")"
  1290. }
  1291.  
  1292. # Print out current topic
  1293. function zirc_checktopic {
  1294.     zirc_connected || {
  1295.     tput setaf 1;
  1296.     tput bold;
  1297.     echo "Not connected";
  1298.     tput sgr0;
  1299.     return 1 }
  1300.     _zirc_write "TOPIC ${ZIRC_CURRENT}"
  1301. }
  1302.  
  1303. # Returns success if currently connected
  1304. function zirc_connected {
  1305.     ! [[ -z "$ZIRC_FD" ]]
  1306. }
  1307.  
  1308. # Connect to a server
  1309. function zirc_connect {
  1310.     if ! [[ -z "$ZIRC_FD" ]]; then
  1311.         zirc_disconnect
  1312.         zirc_connect
  1313.         return
  1314.     fi
  1315.  
  1316.     if [[ -z "$1" ]]; then
  1317.         tput setaf 1;
  1318.         tput bold;
  1319.         echo -e "Usage: $0 <server>"
  1320.         tput sgr0
  1321.         _zirc_param_help
  1322.         return 1
  1323.     fi
  1324.  
  1325.     ZIRC_SERVER="$1"
  1326.     ZIRC_LOWERCASER="_zirc_lowercase_rfc1459"
  1327.     ZIRC_CURRENT=""
  1328.     ZIRC_CHANNELS=()
  1329.  
  1330.     _zirc_param_populate
  1331.  
  1332.     ztcp "$ZIRC_SERVER" "$ZIRC_PORT" || return 1
  1333.     ZIRC_FD="$REPLY"
  1334.     zle -F "$ZIRC_FD" _zirc_handle_incoming_data
  1335.  
  1336.     _zirc_send_connect_lines
  1337.  
  1338.     tput setaf 1;
  1339.     tput bold;
  1340.     echo "Connected to $ZIRC_SERVER on fd #$ZIRC_FD"
  1341.     tput sgr0;
  1342.     return 0
  1343. }
  1344.  
  1345. # Disconnect from a server
  1346. function zirc_disconnect {
  1347.     if [[ -z "$ZIRC_FD" ]]; then
  1348.         return 0
  1349.     fi
  1350.     tput setaf 1;
  1351.     tput bold;
  1352.     echo "Disconnecting from $ZIRC_SERVER..."
  1353.     tput sgr0;
  1354.     zle -F "$ZIRC_FD"
  1355.     ztcp -c "$ZIRC_FD"
  1356.     eval "$ZIRC_UNSETSTRING"
  1357.     return 0
  1358. }
  1359.  
  1360. # Setup aliases
  1361. function zirc_aliases {
  1362.     local a
  1363.     tput setaf 1;
  1364.     tput bold;
  1365.     echo "Setting up some convenience aliases:"
  1366.     tput sgr0;
  1367.     for a in "${(o@)${(k)ZIRC_ALIAS_DEFS[@]}}"; do
  1368.         eval "alias ${a}=\"\${ZIRC_ALIAS_DEFS[\$a]}\""
  1369.         tput setaf 1;
  1370.         tput bold;
  1371.         echo "${(l.12...)a} => ${ZIRC_ALIAS_DEFS[$a]}"
  1372.         tput sgr0;
  1373.     done
  1374. }
  1375.  
  1376. # Widget for autoquoting everything
  1377. function _zirc_quote_magic {
  1378.     setopt localoptions noksharrays extendedglob
  1379.  
  1380.     local -A applicable
  1381.     applicable=( zirc_action 1 zirc_msg 1 zirc_pmsg 2 me 1 msg 1 pmsg 2 \
  1382.                  zirc_topic 1 ctopic 1 zirc_quit 1 quit 1 zirc_part 2 part 2
  1383.                  join 1 zirc_join 1 )
  1384.  
  1385.     local qkey="${(q)KEYS}"
  1386.    
  1387.     if [[ "$KEYS" != "$qkey" ]]; then
  1388.         local lbuf="$LBUFFER$qkey" arg
  1389.         local -a words
  1390.         words=("${(@Q)${(z)lbuf}}")
  1391.  
  1392.         arg=${applicable[${words[1]}]}
  1393.         ! [[ -z "$arg" ]] && [[ "${#words}" == "$(( arg + 1 ))" ]] && \
  1394.             LBUFFER="${LBUFFER}\\"
  1395.     fi
  1396.     zle .self-insert
  1397. }
  1398.  
  1399. # Setup quote magic
  1400. function zirc_quote {
  1401.     zle -N self-insert _zirc_quote_magic
  1402. }
  1403. zirc_quote
  1404.  
  1405. # Unsetup quote magic
  1406. function zirc_unquote {
  1407.     zle -A .self-insert self-insert
  1408. }
  1409.  
  1410. # }}}3
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement