/usr/share/ircII/script/compl.mods is in ircii 20060725-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 | # $eterna: compl.mods,v 1.3 2003/12/08 05:05:59 mrg Exp $
#
# Complete Modules by Ian Frechette
# Last updated 2-2-94
# example modules
# Don't let the size scare you. This is a whole collection of
# examples and comments about the design of modules
# meat of all this are the interface functions to 'complete'
# compl.add, and compl.list (soon to be compl.del)
# the function that does the work is compl.parse which is very small
# and whatever parsing routine it calls.
# These should actually all be in their individual modules
# but this is just an example file..
# Note.. compl.list is internal to complete.. shoulnd't normally be used
if (compl.list == [])
{
# Note here.. Currently, if you compl.add /blah blahparse
# followed by compl.add /blah otherparse only the latter will
# called. No conflict message is shown unless you replace the
# default 'null' and 'nomatch' parsers.
compl.add -null -nomatch /m messparse
compl.add /msg messparse
compl.add /connect connparse
compl.add /tr connparse
compl.add /load loadparse
compl.add /test testparse
compl.add /con expand.con
compl.add /conbunch expand.con
}
# message parser module.. Compatible with included tabscript
# currently calls the tabkey script under 3 conditions
# the input line has more than 2 argments on it.. '/msg bob thud<TAB>'
# the input line has nothing on it '<TAB>'
# the input line has only one argument and the character before the
# cursor is a space '/msg bob <TAB>'
# plus it now does nickname completion
# /m D<TAB> expands to /m Daemon and so on
alias messparse {
if (([$1] != []) && ([$2] == []))
{
if (right(1 $*) != [ ])
{
# this is the simple match.. just match first occurance
# and expand
if (mp.cnt = match($(1)* $tk.msglist))
{
parsekey delete_previous_word
# in case one does /m =ni<TAB> it must delete the =
if (index(#=% $1) >= 0) {parsekey backspace}
type $word(${mp.cnt - 1} $tk.msglist)
type ${[ ]}
}
}
{
^tk.getmsg 1 $tk.msglist
}
}
{
^tk.getmsg 1 $tk.msglist
}
}
# connect module for opers.. easily changeable to kicks, bans.. etc..
# simply use /connect <TAB> for list or /connect <uniqid tag><TAB>
# eg. /connect pen<TAB> expands to /connect penfold.ece.uiuc.edu
# It always expands first matching string. Look at testparse for
# a more intelligent way to do it.
@ connlist = [irc.uiuc.edu goren1.u.washington.edu ircserver.iastate.edu w6yx.stanford.edu hamblin.math.byu.edu freedom.nmsu.edu dreamtime.unm.edu ircserver.santafe.edu irc.netsys.com irc-2.mit.edu cs-mail.bu.edu]
alias connparse {
if ([$1] != [])
{
@ cp.line = [$*]
if ((right(1 $*) == [ ]) && ([$2] == [])&& ([$0] == [/connect]))
{
type 6667;type ${[ ]}
# note.. if converted to use smartparse.. the port number must
# be removed here.. the above logic conflicts with SP
}
{
# expand only the first match found (See 'testparse' for better way
if (cp.cnt = match($(${#cp.line -1})* $connlist))
{
delword
type $word(${cp.cnt - 1} $connlist)
type ${[ ]}
}
{
echo *** connlist $connlist
}
}
}
{
echo *** connlist $connlist
}
}
# Load module
# /load net<TAB> expand to /load netsplit and so on.
# Note the problem right now is that it only finds and expands the first
# name in the list I think we can get around this.
@ loadlist = [netsplit ircgrep cut-paste compl.mods]
alias loadparse {
if ([$1] != []) {
if (lp.cnt = match($(1)* $loadlist))
{
parsekey delete_previous_word
type $word(${lp.cnt - 1} $loadlist)
}
}
{
echo *** loadlist = $loadlist
}
^assign -lp.cnt
}
# ############ stuff related to SMARTPARSE ###################
# The new testparse rewritten to use the
# extremely awsome smartparse routine.
if (!match(/test $compl.list)) {compl.add /test testparse}
# just a quick alias for making LINKS lists.. /makelist testlist *.edu
# will make a list of all *.edu servers.. Note that just * is
# generally too big a list for ircII
alias makelist {
if ([$1])
{
^on ^364 * push $0 $$1
links $1-
wait -cmd eval ^on 364 -\;echo *** makelist finished
}
}
@ testlist = [aone atwo athree bone btwo bthree ircserver.iastate.edu ircserver.santafe.edu]
# testparse <cmd> <stuff....pat>
# this is called by the complete routines.
@ tp.tmp = [0 :]
# [0 :] represents a count of 0.. and a null pattern :<pat>
alias testparse {
# ignore this first line..
@ tp.cnt = [$*]
@ tp.cnt = #tp.cnt
^assign -tp.pat
# all the cnt stuff is in case you do /command word1 word2 pattern<tab>
if (tp.cnt > 1)
{
@ tp.pat = [$(${tp.cnt - 1})]
# '/command pattern ' leaves <pat> null
# '/command pattern' sets <pat> to a new pattern
# important because smartparse may leave a space
if (right(1 $L) != [ ]) {@ tp.tmp = [0 :$tp.pat]}
# Uncomment the following line to see how it works from here.. debugging
# echo smartparse\($tp.tmp testlist $tp.pat\)
# call testparse with current cnt :<pat> <listname> <newpat>
@ tp.tmp = smartparse($tp.tmp testlist $tp.pat)
# note tp.tmp accounts for two arguments.. and is modified and saved
if (left(1 $word(1 $tp.tmp)) == [,])
{echo *** no match for pattern [$tp.pat] found in list}
{if (left(1 $word(1 $tp.tmp)) == [.])
{echo *** testlist: $testlist}}
}
{
echo *** testlist : $testlist
}
}
alias test echo *** TEST: You've matched: $*
# test module
# Trying to make some sort of intelligent handling of the tab lists.
@ sp.cnt = 0
# call it with smartparse <cnt> :<pat> <listname> <newpat>
# $0 $1 $2 $3
# returns <counter> [:,.]<pattern>
# : == successful match , == no match . == null
#
# Look at how testparse uses it.. you shouldn't have to touch any
# smartparse vars.. It's all handled through the interface.. basically
# you're telling it where to start looking in the list and how
# long the list is.. Each time smartparse is called it returns a counter
# value indicating where it left off last time. You can save it
# or not.. testparse saves it.. and passes it back as the new
# starting position <cnt>
#
# Assuming the counter, pattern, and list are maintained through each call
# it'll assume you're searching forward in the list from some place
# after the last word matched in the list..
#
# If you feed it a <newpat> for which <pat> is not a subset, it'll reassign
# <pat> to <newpat> and restart the process..
# It defaults to expansion.. so.. <pat> = blah
# will match blahone, blahtwo etc. Works with wildcards.. *a* matches a lot
# Try it.
^assign -sp.tmp
alias smartparse {
# int sp.tmp - index of last match found
# int sp.cnt - position in list
# int sp.max - max number of elements in list
# string sp.pat - match pattern
if ([$3] != [])
{
# Extract <pat> from :<pat> Note.. It may be null
@ sp.pat = mid(1 50 $1)
@ sp.max = [$(#$2)]
@ sp.cnt = [$0]
# set pattern. Determine if we've changed the base pattern or not
if (sp.pat == [])
{@ sp.pat = [$3]}
{ if (!match($(sp.pat)* $3)) {@sp.pat = [$3]} }
@ sp.run = 1
while (((sp.list = words($sp.cnt $sp.max $($2))) != []) && (!sp.tmp) && sp.run)
{
# look for match in list
if (sp.tmp = match($(sp.pat)* $sp.list))
{
# sp.cnt is absolute position in list. Jump over found item.
# to set up for the next call to smartparse
@ sp.cnt = sp.cnt + sp.tmp
# parsekey delete_previous_word
delword
type $word(${sp.tmp - 1} $sp.list)
type ${[ ]}
}
{
# nothing found.. drop out of loop
# for this condidtion to occur we must be at the beginning
# of the loop... either first pass.. or just looped back
if (!sp.cnt && !sp.tmp)
{
# notfound condition set for return value later
@ sp.notfound = [$sp.cnt ,$sp.pat]
@ sp.run = 0
# echo *** smartparse: no matching pattern
}
# loop back
@ sp.cnt = 0
}
}
^assign -sp.tmp
if (!sp.list) {@sp.cnt = 0}
^assign -sp.list
if (sp.notfound == [])
{@ function_return = [$sp.cnt :$sp.pat]}
{@ function_return = sp.notfound;^assign -sp.notfound}
}
{
# echo *** sp NULL
# echo *** $2: $($2)
@ function_return = [$sp.cnt .$sp.pat]
}
^assign -sp.run
}
# alias words.. usage $word(<begin> <end> <words>)
# words(0 2 zero one two three ... ) == 'zero one two' and so on
alias words {
@ function_return = [$(${[$0]+2}-${[$1] +2})]
}
# This is like DELETE_PREVIOUS_WORD except that it delets to the
# previous space which is much more useful than the current
# behavior of deleting to the previos non- [a-zA-Z0-9] char. :-?
alias delword {
parsekey erase_to_end_of_line
if ((dw.char = right(1 $L)) != [ ]) {@ dw.nw = 0} {@dw.nw = 1}
while (((dw.char != [ ]) || dw.nw) && (dw.char != []))
{
parsekey backspace
if ((dw.char = right(1 $L)) != [ ]) {@ dw.nw = 0}
}
^assign -dw.char;^assign -dw.nw
}
# it is of course possible to do command completion with something like
alias expand.con parsekey erase_to_beg_of_line;type /connect $()
# /con<tab> expands to /connect
# Be careful though.. note the $() at the end of the line.
# Without this 'complete' sends expand.con /con and the above
# alias will add the '/con' back onto the end of the line resulting
# in /connect /con on the input line when you're done
# # # # # # # # # # MODULE WRITING PHILOSOPHY # # # # # # # # # #
# Some thoughts about using complete and designing complete modules.
#
# Basically for any given time you hit TAB there are three states
# normal, null, and nomatch
# normal - there is something on the command line to process
# and the command is in the command list maintained by 'complete'
# The associated command parser is called with the contents of the
# input line in its entirety as the arguments.
# null - there is nothing at all on the command line and some
# default action must be taken. No parser need be called at all as well.
# nomatch - the command at the head of the input line is not
# found in the list of commands maintained by 'complete'.
# A default 'nomatch' parser may or may not be called but if it is called
# it's passed the entire contents of the input line.
#
# This is not the end of the story however.
# If you're writing a completion module of some sort there are the same
# 3 states plus 1 more. Let's say you want to write something to
# find a match for a given keyword prefix out of a list when you hit
# TAB. e.g. /eat ap<TAB> looks for matching words that start with ap
# The 4 actions are
# normal - There is a single match for ap and it expands /eat apple
# multiple matches - There is more than one match for ap and thus
# a choice must be made. Possible choices include
# 1. do nothing
# 2. list possible matches (like ^D) or set showmatch in tcsh shell
# *** matches for prefix 'ap': apple apricot apendage
# 3. match only the first occurance Currently what the /connect module
# does /eat apple
# 4. cycle through the possible matches for the keyword 'ap'.
# The 'testparse' modules uses this scheme and it's my favorite
# albiet a tad more expensive in terms of CPU cycles and responce
# time. (I'm sure someone could see the diff.. I can't ;)
# /eat ap<TAB> -> /eat apple<TAB> -> /eat apricot<TAB> etc..
# 5. display worthless error message
# *** non-unique matches found
# nomatch - as as before, nomatching keywords are found, the choices are
# limited to things like displaying the whole list or just cycling through
# to the next item in the list like the 'tabkey' script's 'messparse' does.
# null - This one is more likely to happen only if 'complete' saw the
# input line as null, but then the null action is ussually special anyway.
# Otherwise this may occur when you say just /eat<TAB> and the obvious
# thing to do here is just to display the list of items to choose from
# in an appropriate format.
# Just remember.. the parsing routine can really do anything it wants..
# it could simply 'sendline' the line on to the server and push a
# button to start WWIII when you hit tab.. It doesn't have to mess with the
# command line but it's more useful that way. Although.. you could write
# a tab completion module that when tab was hit.. it spell checked
# the line.. anything is possible..
|