# Complete - by Ian Frechette (Daemon)
# inspired by the tcsh shell 'complete' command
# version .8 (alpha) Do NOT distribute
# Tue Jul 13 13:16:01 MDT 1993
@ RCS.complete = [$$Header: /home/cvs/ircii/script/complete,v 1.2 2001/08/12 15:44:17 mrg Exp $$]
#
# Commands:
#   compl.add [-null] [-nomatch] <command pattern> <command parser name>
#  or
#   compl.add <[-nulll] [-nomatch]> <command parser name>
#  to add patterns and assciated parsers or just parsers to null and nomatch
#  condition.  (See notes below for me info)
#
#   compl.list      Just list everything out..

# don't clobber existing lists when reloading complete
if (!compl.list) {@ compl.list = []}
if (!compl.parse) {@ compl.parse = []}
if (!compl.null) {@ compl.null = []}
if (!compl.null) {@ compl.nomatch = []}

# Bind TAB to call compl.parse with the contents of the input line
bind ^I parse_command compl.parse $L

# alias compl.add 
# Usage: compl.add [-null] [-nomatch] <command pattern> <command parser>
# Usage: compl.add <[-null] [-nomatch]> <command parser>
# e.g.  compl.add /msg message_parser      will call the message_parser 
#                                         when TAB is pressed and /msg
#                                         is the current command on the
#                                         input line
# -null specifies that the given <command parser> should be used when
#       TAB is pressed and the input line is blank
# -nomatch  specifies that the given <command parser> should be used
#       when the current command at the head of the input line is not
#       found in the list of <command pattern>s
# can use just compl.add -null message_parser
# or           compl.add -null -nomatch message_parser
#      
# 
alias compl.add {
    if ([$1])
    {
        @ compl.add.last = [$*]
        @ compl.add.last = #compl.add.last
        @ compl.tmp = 0
        @ compl.flag.null = 0
        @ compl.flag.nm = 0
        if (compl.flag.null = rmatch(-null $*)) {@ compl.tmp = compl.tmp +1}
        if (compl.flag.nm = rmatch(-nomatch $*)) {@ compl.tmp = compl.tmp +1 }

        # Need to make sure there is at least one morpe argument beyond
        # the -null or -nomatch which we'll take as the parser name
        if (compl.add.last > compl.tmp)
        {
            if (compl.flag.null) 
            {
                if (compl.null) {echo *** compl.add: null call replaced.}
                @ compl.null = [$(${compl.add.last -1 })] 
                echo *** compl.add: null calls $compl.null
            }
            if (compl.flag.nm) 
            {
                if (compl.nomatch) {echo *** compl.add: nomatch call replaced.}
                @ compl.nomatch = [$(${compl.add.last -1})]
                echo *** compl.add: nomatch calls $compl.nomatch
            }
            # Need both the pattern and parser for this part.
            if ((compl.add.last - 2) == compl.tmp)
            {
                # At this point compl.tmp should be 0 1 or 2
                # basically 1 past the last -null or -nomatch found
                push compl.list $($compl.tmp)
                push compl.parse $(${compl.tmp+1})
                echo *** compl.add: $($compl.tmp) $(${compl.tmp +1}) added
            }
        }
        {   echo *** compl.add: Not enough arguments to do anything (1)}
    }
    {   echo *** compl.add: Not enough arguments to do anything (2)}
    ^assign -compl.tmp
    ^assign -compl.flag.null
    ^assign -compl.flag.nm
}

# alias compl.list   No arguments.
# just list the various completion lists.
alias compl.list {
    # if there are items in the list
    @compl.list.cnt = 0
    @compl.list.flag = 0
    echo *** $format(4 num): $lformat(17 Command Pattern) $lformat(15 Action taken)
    if (compl.list)
    {
        @ compl.list.flag = 1
        @ compl.tmp = #compl.list
        while (compl.list.cnt < compl.tmp)
        {
            echo *** $format(4 ${compl.list.cnt +1}): $lformat(17 $word($compl.list.cnt $compl.list)) $lformat(15 $word($compl.list.cnt $compl.parse))
            @ compl.list.cnt = compl.list.cnt + 1
        }
    }
    if (compl.null)
    {
        @compl.list.cnt = compl.list.cnt + 1
        @compl.list.flag = 1
        echo *** $format(4 $compl.list.cnt): $lformat(17 <NULL PATTERN>) $lformat(15 $compl.null)
    }
    if (compl.nomatch)
    {
        @compl.list.cnt = compl.list.cnt + 1
        @compl.list.flag = 1
        echo *** $format(4 $compl.list.cnt): $lformat(17 <NO MATCH>) $lformat(15 $compl.nomatch)
    }
    if (!compl.list.flag) { echo *** compl.list: no completions set }

    ^assign -compl.tmp
    ^assign -compl.list.flag
    ^assign -compl.list.cnt
}


# alias compl.del   Delete an entry from the list of completions
# Do a 'compl.list' first to get a list with numbers.
# then issue a compl.del <item number> and walla.. gone poof.
alias compl.del {
    if (index(0123456789 $0) > -1)
    {
        @ c.d.len = #compl.list
        if (([$0] > 0) && ([$0] <= c.d.len))
        {
            # notword() does boundary checking
            @ compl.list = notword($0 $compl.list)
            @ compl.parse = notword($0 $compl.parse)
            if (#comp.list == c.d.len)
                { echo *** compl.del: Failed to remove item $0 from compl.list}
                { echo *** compl.del: removed item $0 from list of completions}
        }
        {if ([$0] == (c.d.len + 1))
        {
            if (compl.null)
            {
                echo *** compl.del: Removed default null action
                @ compl.null = []
            }
            {
                echo *** compl.del: Removed default nomatch action
                @ compl.nomatch = []
            }
        }
        {if (([$0] == (c.d.len + 2)) && (compl.null != []) && (compl.nomatch != []))
        {
            echo *** compl.del: Removed default nomatch action
            @ compl.nomatch = []
        }
        {
            echo *** compl.del: Selection not in range.  /coml.list for list
        }}}
    }
    {
        echo *** compl.del: Not a valid number. /compl.del <number to delete>
        echo *** compl.del: /compl.list for a list of current completions
    }
    ^assign -c.d.len
}
            


# alias compl.parse
# This is the real guts of the whole script.  Don't let all the other
# fool you. This is what is called when you press TAB.
# It simply tries to find a match for the command word
# ($0 of the input line) and if it finds one it calls the corresponding
# parser with the entire input line as an argument.
# There are two additional states
# null == the command in the compl.null var is called when the input line
#         is empty and compl.parse is called
# nomatch == the command in the compl.nomatch var is called when the input
#         line command word ($0) is not found in the list of commands
#         compl.list
alias compl.parse {
    if ([$0])
    {
        if (compl.ptr = rmatch($0 $compl.list))
        {
            $word(${compl.ptr -1} $compl.parse) $*
        }
        {
            if (compl.nomatch) {$compl.nomatch $*}
        }
    }
    {
        $compl.null
    }
    ^assign -compl.ptr
}

# push an item onto the head of a list
# this only takes the name of the list instead of the variable itself. 
# examples.
# /push list Item
# or     if (push(list Item)) { echo push sucessful } { echo push failed }
# echo $list returns 'Item'
alias push {
	if (![$1])
	{ @function_return = 0 }
	{ eval @ $0 = [$1- $($0)];@function_return = 1}
}

alias debug if (ddebug) {echo *D* $*}

