Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/zsh
- # vim:noet fdm=marker sw=4 ts=4
- ZIRC_VERSION="0.2"
- # ZIRC - A 100% ZSH IRC client
- #
- # Copyright (C) 2006 by Andrew Ruder <andy@aeruder.net>
- # Copyright (C) 2006 by Gergely Nagy <gergely-nagy@gmail.com>
- #
- # This IRC client is pretty ridiculous, I made it entirely as a joke, but it
- # actually works fairly decently for as little work has been put into it.
- # And of course, afaik, there are *no* external commands used in the making
- # of this program. No grep, no sed, nothing... pretty cool :)
- #
- # Guide to using it:
- # Step 1) Source this file.
- # . ./zirc or whatever
- # You can even put this into your .zshrc, it won't hurt anything
- # besides the creation of several _zirc_*/zirc_* functions.
- # Step 2) (Optional) Run zirc_aliases
- # This sets up several aliases to make it easier to use. Basically
- # it strips the zirc_ front end off of everything.
- # Step 3) (Optional) Run zirc_unquote to turn off autoquoting and
- # zirc_quote to turn it on (default on). This will quote shell
- # characters as you type on the ZIRC commands.
- # Step 4) Run zirc_connect
- # It'll explain the syntax and the fairly standardized environment
- # variables controlling its behavior.
- # Step 5) Use zirc_msg to message, zirc_pmsg to private message.
- # zirc_switch can change to another channel. (zirc_switch somechan)
- # or
- # zirc_query can change to anything
- # Step 6) zirc_last is very handy as it switches to the channel/user that
- # last said something to you.
- #
- # Prompt integration: a few environment variables can help you on your way.
- # $ZIRC_CURRENT = current focus
- # $ZIRC_NICK = current nickname
- # $ZIRC_SERVER = connected server
- #
- # This program is free software; you can redistribute it and/or modify it under
- # the terms of the GNU General Public License as published by the Free Software
- # Foundation; either version 2 of the License, or (at your option) any later
- # version.
- [[ -z "$modules[zsh/net/tcp]" ]] && zmodload zsh/net/tcp
- [[ -z "$modules[zsh/zselect]" ]] && zmodload zsh/zselect
- PS1="%m @ %~ :$ZIRC_CURRENT %% "
- ZIRC_PARAMS=( ZIRC_NICK ZIRC_USER ZIRC_NAME ZIRC_PORT ZIRC_HOST )
- if ! [[ -z "$ZIRC_FD" ]] && ! [[ -z "$functions[zirc_disconnect]" ]] ; then
- zirc_disconnect
- fi
- ZIRC_VARS=( ZIRC_LAST ZIRC_CHANNELS ZIRC_CURRENT ZIRC_LOWERCASER ZIRC_FD ZIRC_SERVER "${ZIRC_PARAMS[@]}" )
- ZIRC_UNSETSTRING="unset ${ZIRC_VARS[*]}"
- eval "$ZIRC_UNSETSTRING"
- typeset -g "$ZIRC_VARS[@]"
- typeset -A ZIRC_PARAM_DEFS
- ZIRC_PARAM_DEFS[ZIRC_NICK]="Nickname:\$IRCNICK:$USERNAME"
- ZIRC_PARAM_DEFS[ZIRC_USER]="Username:\$IRCUSER:$USERNAME"
- ZIRC_PARAM_DEFS[ZIRC_PORT]="Port:\$IRCPORT:8001"
- ZIRC_PARAM_DEFS[ZIRC_NAME]="Real name:\$IRCNAME:Ben Raber"
- ZIRC_PARAM_DEFS[ZIRC_HOST]="Host name:\$IRCHOST:localhost"
- # alias definitions {{{
- typeset -A ZIRC_ALIAS_DEFS
- ZIRC_ALIAS_DEFS[me]='zirc_action';
- ZIRC_ALIAS_DEFS[nick]='zirc_nick';
- ZIRC_ALIAS_DEFS[msg]='zirc_msg';
- ZIRC_ALIAS_DEFS[pmsg]='zirc_pmsg';
- ZIRC_ALIAS_DEFS[quit]='zirc_quit';
- ZIRC_ALIAS_DEFS[ctopic]='zirc_topic';
- ZIRC_ALIAS_DEFS[topic]='zirc_checktopic';
- ZIRC_ALIAS_DEFS[part]='zirc_part';
- ZIRC_ALIAS_DEFS[last]='zirc_last';
- ZIRC_ALIAS_DEFS[join]='zirc_join';
- ZIRC_ALIAS_DEFS[sw]='zirc_switch';
- ZIRC_ALIAS_DEFS[query]='zirc_query';
- ZIRC_ALIAS_DEFS[connect]='zirc_connect';
- ZIRC_ALIAS_DEFS[help]='zirc_help';
- ZIRC_ALIAS_DEFS[mode]='zirc_mode';
- ZIRC_ALIAS_DEFS[op]='zirc_op';
- ZIRC_ALIAS_DEFS[deop]='zirc_deop';
- ZIRC_ALIAS_DEFS[voice]='zirc_voice';
- ZIRC_ALIAS_DEFS[devoice]='zirc_devoice';
- ZIRC_ALIAS_DEFS[names]='zirc_names';
- ZIRC_ALIAS_DEFS[whois]='zirc_whois';
- ZIRC_ALIAS_DEFS[who]='zirc_who';
- ZIRC_ALIAS_DEFS[kick]='zirc_kick';
- ZIRC_ALIAS_DEFS[away]='zirc_away';
- # }}}
- # zirc_connect parameter handling {{{
- # Print out help for the environment variables using the
- # ZIRC_PARAM_DEFS and ZIRC_PARAMS variables as a reference
- function _zirc_param_help {
- local a b
- tput setaf 1
- tput bold
- echo -e "Environment variables:"
- for a in "${ZIRC_PARAMS[@]}"; do
- b=( ${(s/:/)${ZIRC_PARAM_DEFS[$a]}} )
- echo -e "\t${b[2]} - ${b[1]} (default ${b[3]})"
- done
- tput sgr0
- }
- # Fills in the variables in ZIRC_PARAMS using the correct
- # fallback values specified in ZIRC_PARAM_DEFS
- function _zirc_param_populate {
- local a b
- for a in "$ZIRC_PARAMS[@]"; do
- b=( ${(s/:/)${ZIRC_PARAM_DEFS[$a]}} )
- if [ -z "${(e)b[2]}" ]; then
- eval "${a}=\"\${b[3]}\""
- else
- eval "${a}=\"\${(e)b[2]}\""
- fi
- done
- }
- # }}}
- # Lowercasing/string comparison code {{{
- # Lowercasing according to rfc1459 strictly
- function _zirc_lowercase_strict_rfc1459 {
- local msg="${(L)1}"
- msg=${msg//\[/\{}
- msg=${msg//]/\}}
- msg=${msg//\\/\|}
- tput setaf 1
- tput bold
- echo "${msg}"
- tput sgr0
- }
- # Lowercasing according to rfc1459
- function _zirc_lowercase_rfc1459 {
- local msg="$(_zirc_lowercase_strict_rfc1459 "$1")"
- msg=${msg//\~/^}
- tput setaf 1
- tput bold
- echo "${msg}"
- tput sgr0
- }
- # Lowercasing using standard ascii rules
- function _zirc_lowercase_ascii {
- tput setaf 1
- tput bold
- echo "${(L)1}"
- tput sgr0
- }
- # Lowercasing according to the current server's specs
- function _zirc_lowercase {
- "$ZIRC_LOWERCASER" "$1"
- }
- # Case-insensitive compare according to the case-mapping= spec for the server
- function _zirc_compare {
- [[ "$("$ZIRC_LOWERCASER" "$1")" == "$("$ZIRC_LOWERCASER" "$2")" ]]
- }
- # Determine if a prefix/word is referring to you
- function _zirc_isme {
- _zirc_compare "$ZIRC_NICK" "$(_zirc_prefix_nick "$1")"
- }
- # }}}
- # data from server parsing {{{
- # Parse a line like
- # :blah!host blah3 blah4 :Message with lots of words
- # and output
- # blah!host
- # blah3
- # blah4
- # Message with lots of words
- function _zirc_parse_server_line {
- local readval args
- args=()
- readval=( "${(f)$(_zirc_parse_server_prefix "$1")}" )
- args+=( "${readval[1]}" )
- while ! [[ -z "${readval[2]}" ]] ; do
- readval=( "${(f)$(_zirc_parse_server_word "${readval[2]}")}" ) #" Bug in vim highlighting
- if ! [[ -z "${readval[1]}" ]]; then
- args+=( "${readval[1]}" )
- fi
- done
- tput setaf 1
- tput bold
- echo "${(F)args}"
- tput sgr0
- }
- # Parse a line like
- # :blah!host blah3 blah4
- # and print out
- # blah!host
- # blah3 blah4
- function _zirc_parse_server_prefix {
- setopt localoptions extendedglob
- local line prefix
- line="${1## #}"
- if [[ "${line[1]}" != ":" ]]; then
- prefix=""
- else
- prefix="${line%% *}"
- if [[ "$prefix" == "$line" ]]; then
- line=""
- else
- line="${line#* }"
- fi
- fi
- tput setaf 1
- tput bold
- echo "${prefix#:}"
- echo "$line"
- tput sgr0
- }
- # Parse out a single word from a line, so
- # blah3 blah4 :Message
- # prints out:
- # blah3
- # blah4 :Message
- # again:
- # blah4
- # :Message
- # again
- # Message
- # <empty line>
- function _zirc_parse_server_word {
- setopt localoptions extendedglob
- local line word
- line="${1## #}"
- if [[ "${line[1]}" != ":" ]]; then
- word="${line%% *}"
- if [[ "$word" == "$line" ]]; then
- line=""
- else
- line="${line#* }"
- fi
- else
- word="${line#:}"
- line=""
- fi
- tput setaf 1
- tput bold
- echo "$word"
- echo "$line"
- tput sgr0
- }
- # Split a prefix and get nick (nick!host)
- # Input: nick!host or nick
- # Output:
- # <empty-line>
- function _zirc_prefix_nick {
- local a
- a=( "${(f)$(_zirc_split_prefix "$1")}" )
- tput setaf 1
- tput bold
- echo "${a[1]}"
- tput sgr0
- }
- # Split a prefix and get host (nick!host)
- # Input: nick!host
- # Output:
- # host
- # Input: nick
- # Output:
- # <empty-line>
- function _zirc_prefix_host {
- local a
- a=( "${(f)$(_zirc_split_prefix "$1")}" )
- tput setaf 1
- tput bold
- echo "${a[2]}"
- tput sgr0
- }
- # Split a prefix
- # Input: nick!host
- # Output:
- # nick
- # host
- # Input: nick
- # Output:
- # nick
- # <empty-line>
- function _zirc_split_prefix {
- local a
- a=( ${(s:!:)1} )
- [[ ${#a} == "1" ]] && a+=( '' )
- tput setaf 1
- tput bold
- echo "${(F)a}"
- tput sgr0
- }
- # }}}
- # CTCP handling {{{
- # Print out the generic ctcp message
- # Args: prefix command where ctcp msg
- function _zirc_generic_ctcp {
- local pref="$1" comm="$2"
- local where="$3" ctcp="$4"
- local msg="$5"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_echo -n "<CTCP> <$who"
- _zirc_isme "$where" || _zirc_echo -n ":$where"
- _zirc_echo "> $ctcp $msg"
- }
- # Write out a CTCP request
- # Args: prefix command where ctcp msg
- function _zirc_ctcp_request_write {
- local msg
- if ! [[ -z "$2" ]] && ! [[ -z "$3" ]]; then
- msg="$2 $3"
- else
- msg="$2"
- fi
- tput setaf 1
- tput bold
- _zirc_write "`printf "PRIVMSG %s :\001%s\001" "$1" "$msg"`"
- tput sgr0
- }
- # Write out a CTCP reply
- # Args: where ctcp message
- function _zirc_ctcp_reply_write {
- local msg
- if ! [[ -z "$2" ]] && ! [[ -z "$3" ]]; then
- msg="$2 $3"
- else
- msg="$2"
- fi
- tput setaf 1
- tput bold
- _zirc_write "`printf "NOTICE %s :\001%s\001" "$1" "$msg"`"
- tput sgr0
- }
- # Handle a VERSION request
- function _zirc_ctcp_request_VERSION {
- _zirc_generic_ctcp "$@"
- local pref="$1"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_ctcp_reply_write "$who" "VERSION" "ZIRC $ZIRC_VERSION - 100% zsh!!"
- }
- # Handle a PING request
- function _zirc_ctcp_request_PING {
- local pref="$1" msg="$5"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_echo "Received a CTCP PING from $who"
- _zirc_ctcp_reply_write "$who" "PING" "$5"
- }
- # Handle an ACTION
- function _zirc_ctcp_reply_ACTION {
- local pref="$1" where="$3" msg="$5"
- local who="$(_zirc_prefix_nick "$pref")"
- if ( _zirc_isme "$where" ); then
- _zirc_compare "$ZIRC_CURRENT" "$who" || ZIRC_LAST="$who"
- _zirc_echo "*** * $who $msg"
- else
- _zirc_echo -n "* $who"
- _zirc_compare "$ZIRC_CURRENT" "$where" || {
- ZIRC_LAST="$where"
- _zirc_echo -n ":$where"
- }
- _zirc_echo " $msg"
- fi
- }
- # Handle ACTION requests just like replies
- function _zirc_ctcp_request_ACTION {
- _zirc_ctcp_reply_ACTION "$@"
- }
- # Handle all other CTCP requests
- function _zirc_ctcp_request_other {
- _zirc_generic_ctcp "$@"
- }
- # Handle all other CTCP replies
- function _zirc_ctcp_reply_other {
- _zirc_generic_ctcp "$@"
- }
- # Parse the CTCP stuff and call the appropriate CTCP function above
- # args: pref command where ctcp+message
- function _zirc_command_CTCP {
- local pref="$1" comm="$2"
- local who="$(_zirc_prefix_nick "$pref")"
- shift 2
- local where="$1" msg="$2"
- local ctcp func args ctype
- if [[ "$((#msg))" == "1" ]]; then
- msg="${msg#?}"
- fi
- if [[ "$((##${msg[-1]}))" == "1" ]]; then
- msg="${msg%?}"
- fi
- ctcp="${(U)msg%% *}"
- msg="${msg#* }"
- if [[ "$msg" == "$ctcp" ]]; then
- msg=""
- fi
- ctype="request"
- [[ "$comm" == "NOTICE" ]] && ctype="reply"
- func="_zirc_ctcp_${ctype}_${ctcp}"
- if [[ -z "${functions[${func}]}" ]]; then
- func="_zirc_ctcp_${ctype}_other"
- fi
- args=( "$pref" "$comm" "$where" "$ctcp" "$msg" )
- "${func}" "$args[@]"
- }
- # }}}
- # Server command handling {{{
- # An echo that should be used by anything automatically
- # called (commands). It invalidates the current prompt line first.
- function _zirc_echo {
- zle -I
- tput setaf 1
- tput bold
- echo "$@"
- tput sgr0
- }
- # Handle private messages
- function _zirc_command_PRIVMSG {
- local pref="$1" comm="$2"
- shift 2
- local who="$(_zirc_prefix_nick "$pref")"
- local where="$1" msg="$2"
- if [[ "$((#msg))" == "1" ]]; then
- _zirc_command_CTCP "$pref" "$comm" "$where" "$msg"
- return 0
- fi
- if ( _zirc_isme "$where" ); then
- _zirc_compare "$ZIRC_CURRENT" "$who" || ZIRC_LAST="$who"
- _zirc_echo "*** <$who> $msg"
- else
- _zirc_echo -n "<$who"
- _zirc_compare "$where" "$ZIRC_CURRENT" || {
- _zirc_echo -n ":$where"
- ZIRC_LAST="$where"
- }
- _zirc_echo "> $msg"
- fi
- }
- # Handle nickname changes
- function _zirc_command_NICK {
- local pref="$1" newnick="$3"
- local who="$(_zirc_prefix_nick "$pref")"
- if [[ "$who" == "$ZIRC_CURRENT" ]]; then
- ZIRC_CURRENT="${newnick}"
- fi
- _zirc_isme "$pref" && ZIRC_NICK="$newnick"
- _zirc_echo "$who is now known as $newnick"
- }
- # Handle channel joins
- function _zirc_command_JOIN {
- local pref="$1" comm="$2"
- shift 2
- local who="$(_zirc_prefix_nick "$pref")"
- local at="$(_zirc_prefix_host "$pref")"
- local where="$1"
- _zirc_echo "$who ($at) has joined $where"
- _zirc_isme "$pref" && {
- ZIRC_LAST="$ZIRC_CURRENT"
- ZIRC_CURRENT="$where"
- ZIRC_CHANNELS+=("$where")
- }
- }
- # Handle channel parts
- function _zirc_command_PART {
- local pref="$1" comm="$2" where="$3" msg="$4"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_echo "$who has left $where ($msg)"
- _zirc_isme "$pref" && {
- [[ "$ZIRC_CURRENT" == "$where" ]] && ZIRC_CURRENT="$ZIRC_LAST"
- ZIRC_CHANNELS[(r)$where]=()
- }
- }
- # Handle people quitting
- function _zirc_command_QUIT {
- local pref="$1" comm="$2" msg="$3"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_echo "$who has quit IRC ($msg)"
- }
- # Handle topic changes
- function _zirc_command_TOPIC {
- local pref="$1" comm="$2" where="$3" msg="$4"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_echo "$who has changed the topic in $where to '$msg'"
- }
- # Handle mode changes
- function _zirc_command_MODE {
- local pref="$1" comm="$2" object="$3" mode="$4"
- local who="$(_zirc_prefix_nick "$pref")"
- local rest
- rest=( "${@[4,-1]}" )
- rest=( " "${^rest} )
- rest=${(j::)rest}
- _zirc_echo "$who sets mode $mode ${object}${rest}"
- }
- # Handle invites
- function _zirc_command_INVITE {
- local pref="$1" comm="$2" where="$4"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_echo "$who has invited you to $where"
- }
- # Handle kicks
- function _zirc_command_KICK {
- local pref="$1" comm="$2" where="$3" user="$4" msg="$5"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_echo "$user was kicked from $where by $who ($msg)"
- }
- # Handle pong messages (shouldn't get these generally, but just in case)
- function _zirc_command_PONG {
- }
- # Handle notices, although we just forward this onto the privmsg code
- function _zirc_command_NOTICE {
- _zirc_command_PRIVMSG "$@"
- return
- }
- # Handle wallops
- function _zirc_command_WALLOPS {
- local pref="$1" comm="$2" msg="$3"
- local who="$(_zirc_prefix_nick "$pref")"
- _zirc_echo "Wallops from $who: $msg"
- }
- # Handle IRC Errors
- function _zirc_command_ERROR {
- local pref="$1" comm="$2"
- shift 2
- _zirc_echo "ERROR: ${(j: :)@}"
- }
- # Handle server pings
- function _zirc_command_PING {
- local pref="$1" comm="$2"
- shift 2
- _zirc_write "PONG :$1"
- }
- # RPL_WELCOME handler... this will (among other things)
- # inform us of our true nickname
- function _zirc_command_numeric_001 {
- ZIRC_NICK="$3"
- }
- # RPL_ISUPPORT this tells us how to handle casemapping
- function _zirc_command_numeric_005 {
- case "$4" in
- *casemapping=rfc1459*)
- ZIRC_LOWERCASER="_zirc_lowercase_rfc1459"
- ;;
- *casemapping=strict-rfc1459*)
- ZIRC_LOWERCASER="_zirc_lowercase_strict_rfc1459"
- ;;
- *casemapping=ascii*)
- ZIRC_LOWERCASER="_zirc_lowercase_ascii"
- ;;
- esac
- }
- # Handle numeric commands
- function _zirc_command_numeric {
- local pref="$1" comm="$2"
- _zirc_echo "-- ${(j: :)@[4,-1]}"
- if ! [[ -z "$functions[_zirc_command_numeric_${comm}]" ]]; then
- _zirc_command_numeric_"$comm" "$@"
- fi
- }
- # catchall for unhandled commands
- function _zirc_command_other {
- setopt localoptions extendedglob
- local pref="$1" comm="$2"
- shift 2
- if [[ "$comm" == [0-9]## ]]; then
- _zirc_command_numeric "$pref" "$comm" "$@"
- return 0
- fi
- }
- # }}}
- # ZLE hooks {{{
- # Parse a single line of incoming data
- function _zirc_handle_incoming_data_piece {
- local line comm func output
- line="$1"
- line=( "${(f)$(_zirc_parse_server_line "$line")}" )
- comm="${(U)line[2]}"
- func="_zirc_command_${comm}"
- if [[ -z "${functions[${func}]}" ]]; then
- func="_zirc_command_other"
- fi
- "$func" "$line[@]"
- }
- # The ZLE informs this when there is data. Grab the data, and then
- # grab any additional data available (using zselect) and passing all
- # of this back off to the _zirc_handle_incoming_data_piece function
- function _zirc_handle_incoming_data {
- local fds line
- if [[ "$1" != "$ZIRC_FD" ]]; then
- zle -I
- tput setaf 1
- tput bold
- echo "ZIRC: Handling some other file handle???"
- tput sgr0
- return 1
- fi
- while true; do
- if ! read -r line <&$ZIRC_FD; then
- zle -I
- zirc_disconnect
- return 1
- fi
- if [[ "$((##${line[-1]}))" == "13" ]]; then
- line="${line%?}"
- fi
- _zirc_handle_incoming_data_piece "$line"
- fds=()
- zselect -r -t 0 -a fds $ZIRC_FD
- if [[ "${#fds}" != "2" ]]; then
- break
- fi
- done
- }
- # }}}
- # User commands and utility functions used by them {{{
- # Write out a message to the server. It puts on the correct line ending
- # for the IRC protocol too
- function _zirc_write {
- local a
- if [[ -z "$ZIRC_FD" ]]; then
- return 1
- fi
- if [[ -z "$1" ]]; then
- return 0
- fi
- a="$@"
- tput setaf 1
- tput bold
- printf "%s\r\n" "$a" >&$ZIRC_FD
- tput sgr0
- }
- # Send the initial connection lines to the server
- function _zirc_send_connect_lines {
- _zirc_write "NICK $ZIRC_NICK"
- _zirc_write "USER $ZIRC_USER $ZIRC_HOST $ZIRC_SERVER :$ZIRC_NAME"
- }
- # Input:
- # channel name (or part of a channel name)
- # Output:
- # shortest channel that matches *<input>
- function _zirc_channel_match {
- local chan="$1"
- local chans shortest a
- chan="*${chan}"
- chans=( "${ZIRC_CHANNELS[@]}" )
- chans=( ${(e):-\${(M)chans:#$chan}} )
- if [[ "${#chans}" == "0" ]]; then
- echo ""
- return 1
- fi
- shortest=" "; shortest="${(l:1000:: :)shortest}"
- for a in "${chans[@]}"; do
- (( ${#a} < ${#shortest} )) && shortest="${a}"
- done
- tput setaf 1
- tput bold
- echo "${shortest}"
- tput sgr0
- return 0
- }
- # Switch focus. This uses _zirc_channel_match so the globbing will make it
- # easier to switch channels.
- #
- # zirc_switch step
- #
- # would change to #gnustep if you were correctly connected to that channel
- function zirc_switch {
- local chan="$1"
- local chans shortest a
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected" ; return 1; }
- if [[ -z "$chan" ]]; then
- tput setaf 1
- tput bold
- echo "Usage: $0 <channel>"
- echo "Switches current channel focus (Current: '${ZIRC_CURRENT}')"
- echo "This command is only used for channels, use zirc_query for a more"
- echo "general solution."
- tput sgr0
- return 1
- fi
- chan="$(_zirc_channel_match "$chan")"
- if [[ -z "$chan" ]]; then
- tput setaf 1
- tput bold
- echo "Could not find anything for '$1'"
- echo "Current channels: ${(j:,:)ZIRC_CHANNELS}"
- tput sgr0
- return 1
- fi
- ZIRC_LAST="$ZIRC_CURRENT"
- ZIRC_CURRENT="${chan}"
- tput setaf 1
- tput bold
- echo "Switched to $ZIRC_CURRENT"
- tput sgr0
- return 0
- }
- # Sets channel modes
- function zirc_mode {
- local modes="${(j: :)@}"
- if [[ -z "$modes" ]]; then
- tput setaf 1
- tput bold
- echo "Usage: $0 <modes>"
- echo "Set channel modes to <modes>."
- echo "Sends to the current focus (Current: '$ZIRC_CURRENT')."
- tput sgr0
- return 1
- fi
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0
- return 1 }
- _zirc_write "MODE ${ZIRC_CURRENT} ${modes}"
- }
- # Set a single mode for a list of users
- function _zirc_batch_mode {
- local mode="$1"
- shift
- local users="${(j: :)@}"
- for user in $users; do
- zirc_mode "$mode" "$user"
- done
- }
- # Give operator status to user(s)
- function zirc_op {
- if [[ -z "$@" ]]; then
- tput setaf 1
- tput bold
- echo "Usage: $0 <users>"
- echo "Give operator status to <users>."
- echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
- tput sgr0
- return 1
- fi
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1}
- _zirc_batch_mode "+o" $@
- }
- # Revoke operator status from user(s)
- function zirc_deop {
- if [[ -z "$@" ]]; then
- tput setaf 1;
- tput bold
- echo "Usage: $0 <users>"
- echo "Revoke operator status from <users>."
- echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
- tput sgr0
- return 1
- fi
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1}
- _zirc_batch_mode "-o" $@
- }
- # Give a voice flag to user(s)
- function zirc_voice {
- if [[ -z "$@" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <users>"
- echo "Give a voice flag to <users>."
- echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
- tput sgr0
- return 1
- fi
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1}
- _zirc_batch_mode "+v" $@
- }
- # Revoke the voice flag from user(s)
- function zirc_devoice {
- if [[ -z "$@" ]]; then
- tput setaf 1
- tput bold
- echo "Usage: $0 <users>"
- echo "Revoke the voice flag from <users>."
- echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
- tput sgr0
- return 1
- fi
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1}
- _zirc_batch_mode "-v" $@
- }
- # Query the names on a channel
- function zirc_names {
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1}
- _zirc_write "NAMES $ZIRC_CURRENT"
- }
- # Issue a WHOIS request
- function zirc_whois {
- if [[ -z "$1" ]]; then
- tput setaf 1
- tput bold
- echo "Usage: $0 <user>"
- echo "Get detailed information about <user>."
- tput sgr0
- return 1
- fi
- zirc_connected || { echo "Not connected" ; return 1}
- _zirc_write "WHOIS $1"
- }
- # Issue a WHO request
- function zirc_who {
- local chan="${1:-${ZIRC_CURRENT}}"
- zirc_connected || { echo "Not connected" ; return 1}
- _zirc_write "WHO $chan"
- }
- # Kick user from the current channel
- function zirc_kick {
- if [[ -z "$@" ]]; then
- tput setaf 1
- tput bold
- echo "Usage: $0 <user> [<reason>]"
- echo "Kick <users> from the current channel, due to <reason>."
- echo "Works on the current focus (Current: '$ZIRC_CURRENT')."
- tput sgr0
- return 1
- fi
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0
- return 1}
- local user=$1
- shift
- _zirc_write "KICK $ZIRC_CURRENT $user ${@:+:$@}"
- }
- # Sets/unsets the automatic away message
- function zirc_away {
- zirc_connected || {
- tput setaf 1;
- tput bold
- echo "Not connected";
- tput sgr0
- return 1}
- _zirc_write "AWAY ${@:+:$@}"
- }
- # Just switch focus to the argument. Don't check against anything else.
- function zirc_query {
- local query="$1"
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- if [[ -z "$query" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <user/channel>"
- echo "Switches current focus. (Current: '${ZIRC_CURRENT}')"
- echo "No expansion will be done on the parameter. If you are switching"
- echo "to a channel, you may try zirc_switch instead as it will expand to"
- echo "the best match without you having to deal with the escaping."
- tput sgr0
- return 1
- fi
- ZIRC_LAST="$ZIRC_CURRENT"
- ZIRC_CURRENT="${query%% *}"
- tput setaf 1
- tput bold
- echo "Switched to $ZIRC_CURRENT"
- tput sgr0
- }
- # Switch to the last focused window or wherever there was a message last
- function zirc_last {
- local a
- [[ -z "$ZIRC_LAST" ]] && return 0
- a="$ZIRC_CURRENT"
- ZIRC_CURRENT="${ZIRC_LAST}"
- ZIRC_LAST="$a"
- tput setaf 1
- tput bold
- echo "Switched to $ZIRC_CURRENT"
- tput sgr0
- }
- # Quit (with optional quit message)
- function zirc_quit {
- local msg="${(j: :)@}"
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- [[ -z "$msg" ]] && msg="ZIRC $ZIRC_VERSION - 100% zsh, woot."
- _zirc_write "QUIT :$msg"
- }
- # Print out current focus. Could be used to hook into prompts
- function zirc_focus {
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- tput setaf 1;
- tput bold;
- echo "$ZIRC_CURRENT"
- tput sgr0
- }
- # Print out zirc_* functions and alias mappings
- function zirc_help {
- local commands a
- commands=( "${(k)functions[@]}" )
- commands=( ${(M)commands:#zirc_*} )
- commands=( ${(o)commands} )
- commands=( " "${^commands} )
- tput setaf 1
- tput bold
- echo "ZIRC Commands:"
- echo "${(F)commands}"
- echo
- echo "Aliases (if using zirc_aliases):"
- for a in "${(o@)${(k)ZIRC_ALIAS_DEFS[@]}}"; do
- echo "${(l.12...)a} => ${ZIRC_ALIAS_DEFS[$a]}"
- done
- tput sgr0
- return 0
- }
- # Change nickname to argument
- function zirc_nick {
- local nick="$1"
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- if [[ -z "$nick" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <nick>"
- echo "Change nickname to <nick>."
- tput sgr0;
- return 1
- fi
- _zirc_write "NICK ${nick%% *}"
- }
- # Message the current focus
- function zirc_msg {
- local msg="${(j: :)@}"
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- if [[ -z "$msg" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <message>"
- echo "Will message the current focus <message>."
- echo "Use zirc_query/zirc_switch to change focus. (Current: '${ZIRC_CURRENT}')"
- tput sgr0
- return 1
- fi
- if [[ -z "$ZIRC_CURRENT" ]]; then
- tput setaf 1;
- tput bold;
- echo "No current focus. Use zirc_query/zirc_switch to change focus."
- tput sgr0
- return 1
- fi
- tput setaf 1;
- tput bold;
- echo "<$ZIRC_NICK:$ZIRC_CURRENT> ${msg}"
- tput sgr0;
- _zirc_write "PRIVMSG ${ZIRC_CURRENT} :${msg}"
- }
- # Message someone (temporarily changing focus then calling zirc_msg)
- function zirc_pmsg {
- local who="$1"
- shift
- local msg="${(j: :)@}"
- local temp_current temp_result
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- if [[ -z "$msg" ]] || [[ -z "$who" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <person> <message>"
- echo "Will message the <person> the message <message>."
- echo "Also see zirc_msg."
- tput sgr0
- return 1
- fi
- temp_current="$ZIRC_CURRENT"
- ZIRC_CURRENT="$who"
- zirc_msg "$msg"
- temp_result="$?"
- ZIRC_CURRENT="$temp_current"
- return "$temp_result"
- }
- # Join a channel
- function zirc_join {
- local chan="$1"
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- if [[ -z "$chan" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <channel>"
- echo "Will join the channel <channel>. If <channel> starts with a letter"
- echo "or a number, it will be prepended with a '#'"
- tput sgr0;
- return 1
- fi
- [[ "$chan" == [a-zA-Z0-9]* ]] && chan="#${chan}"
- _zirc_write "JOIN ${chan%% *}"
- }
- # Leave a channel (with optional part message)
- function zirc_part {
- local chan="$1" unchan="$1"
- shift
- local msg="${(j: :)@}"
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- if [[ -z "$chan" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <channel> [<msg>]"
- echo "Will leave the channel <channel> with optional part message <msg>."
- echo "This routine will use the same matching method as zirc_switch so"
- echo "you don't have to type the '#' or any other tricky characters"
- tput sgr0;
- return 1
- fi
- chan="$(_zirc_channel_match "$chan")"
- if [[ -z "$chan" ]]; then
- tput setaf 1;
- tput bold;
- echo "Could not find anything for '$unchan'"
- echo "Current channels: ${(j:,:)ZIRC_CHANNELS}"
- tput sgr0;
- return 1
- fi
- _zirc_write "PART ${chan%% *} :${msg}"
- }
- # Change the topic in current focus
- function zirc_topic {
- local topic="${(j: :)@}"
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- if [[ -z "$topic" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <topic>"
- echo "Change the topic in the current channel. Use zirc_switch"
- echo "to change the channel (Current: '$ZIRC_CURRENT')."
- tput sgr0
- return 1
- fi
- _zirc_write "TOPIC ${ZIRC_CURRENT} :${topic}"
- }
- # Send a CTCP action to the current focus
- function zirc_action {
- local msg="${(j: :)@}"
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- if [[ -z "$msg" ]]; then
- tput setaf 1;
- tput bold;
- echo "Usage: $0 <message>"
- echo "Send 3rd person action <message>."
- echo "Sends to the current focus (Current: '$ZIRC_CURRENT')."
- tput sgr0;
- return 1
- fi
- tput setaf 1;
- tput bold;
- echo "* $ZIRC_NICK:$ZIRC_CURRENT ${msg}"
- tput sgr0;
- _zirc_write "$(printf "PRIVMSG $ZIRC_CURRENT :\001ACTION ${msg}\001")"
- }
- # Print out current topic
- function zirc_checktopic {
- zirc_connected || {
- tput setaf 1;
- tput bold;
- echo "Not connected";
- tput sgr0;
- return 1 }
- _zirc_write "TOPIC ${ZIRC_CURRENT}"
- }
- # Returns success if currently connected
- function zirc_connected {
- ! [[ -z "$ZIRC_FD" ]]
- }
- # Connect to a server
- function zirc_connect {
- if ! [[ -z "$ZIRC_FD" ]]; then
- zirc_disconnect
- zirc_connect
- return
- fi
- if [[ -z "$1" ]]; then
- tput setaf 1;
- tput bold;
- echo -e "Usage: $0 <server>"
- tput sgr0
- _zirc_param_help
- return 1
- fi
- ZIRC_SERVER="$1"
- ZIRC_LOWERCASER="_zirc_lowercase_rfc1459"
- ZIRC_CURRENT=""
- ZIRC_CHANNELS=()
- _zirc_param_populate
- ztcp "$ZIRC_SERVER" "$ZIRC_PORT" || return 1
- ZIRC_FD="$REPLY"
- zle -F "$ZIRC_FD" _zirc_handle_incoming_data
- _zirc_send_connect_lines
- tput setaf 1;
- tput bold;
- echo "Connected to $ZIRC_SERVER on fd #$ZIRC_FD"
- tput sgr0;
- return 0
- }
- # Disconnect from a server
- function zirc_disconnect {
- if [[ -z "$ZIRC_FD" ]]; then
- return 0
- fi
- tput setaf 1;
- tput bold;
- echo "Disconnecting from $ZIRC_SERVER..."
- tput sgr0;
- zle -F "$ZIRC_FD"
- ztcp -c "$ZIRC_FD"
- eval "$ZIRC_UNSETSTRING"
- return 0
- }
- # Setup aliases
- function zirc_aliases {
- local a
- tput setaf 1;
- tput bold;
- echo "Setting up some convenience aliases:"
- tput sgr0;
- for a in "${(o@)${(k)ZIRC_ALIAS_DEFS[@]}}"; do
- eval "alias ${a}=\"\${ZIRC_ALIAS_DEFS[\$a]}\""
- tput setaf 1;
- tput bold;
- echo "${(l.12...)a} => ${ZIRC_ALIAS_DEFS[$a]}"
- tput sgr0;
- done
- }
- # Widget for autoquoting everything
- function _zirc_quote_magic {
- setopt localoptions noksharrays extendedglob
- local -A applicable
- applicable=( zirc_action 1 zirc_msg 1 zirc_pmsg 2 me 1 msg 1 pmsg 2 \
- zirc_topic 1 ctopic 1 zirc_quit 1 quit 1 zirc_part 2 part 2
- join 1 zirc_join 1 )
- local qkey="${(q)KEYS}"
- if [[ "$KEYS" != "$qkey" ]]; then
- local lbuf="$LBUFFER$qkey" arg
- local -a words
- words=("${(@Q)${(z)lbuf}}")
- arg=${applicable[${words[1]}]}
- ! [[ -z "$arg" ]] && [[ "${#words}" == "$(( arg + 1 ))" ]] && \
- LBUFFER="${LBUFFER}\\"
- fi
- zle .self-insert
- }
- # Setup quote magic
- function zirc_quote {
- zle -N self-insert _zirc_quote_magic
- }
- zirc_quote
- # Unsetup quote magic
- function zirc_unquote {
- zle -A .self-insert self-insert
- }
- # }}}3
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement