📄 tabkey.ce
字号:
## OK, here's the plan:## Tabkey cuts the input line up into edible chunks, and selects a function# to do the actual completion. The function will receive a single word as# its argument, and return a list of potential matches. The word is whatever# is under the cursor, up to the insertion point at the current time. The# word may be empty or contain spaces and the function should be able to# cope with this.## The exact function chosen works like this:# * If the current _word_ is a command (first word, begins with $cmdchars),# call command_completion by way of parsekey (don't call any aliases).# * Or, if the current line is a command, it gets handed to $tabkey.cmd().# * Otherwise, call tabkey.default, which is a stub that can be changed# to suit your preferences. The default tabkey.default calls# tabkey.nickchan which matches against all channels you're currently on# and either the nicks in your current channel, or failing that, the# nicks in all channels.# * tabkey.default is also called if tabkey.cmd() returns nothing. If# necessary, the function can prevent this behaviour by returning a single# space, but this is discouraged.# * tabkey.default is also called by $tabkey.cmd() if it cannot find an# appropriate command handler.# * $tabkey.cmd() will search for an appropriate function by joining the# command and all its arguments together with dots and progressively# removing those arguments until a function is found.## tabkey "exports" a number of local variables that the functions may use# or alter after using "bless":# * $curword is what tabkey believes the current word is. The function# may make use of this for context sensitivity. I say believes because# this may be open to different interpretations.# * $wordind is the character index of the _beginning_ of the word that is# being completed. If it is equal to $curpos(), then the first argument# will be empty and the user has hit tab at the beginning of the word or# in between words and the function should return all possible matches.# The reason you may need to use it is if the function is designed to# complete something that is not a single word. It, and the current# cursor position may be altered to cause tabkey to replace the chosen# part of the string instead of just the word.## The organisation of the supporting functions goes like this:# * "Context sensitive" functions are to be named with "tabkey.cmd." as a# prefix followed by the name of the command that they are used to# complete. This is where tabkey.cmd will look for them.# * Generally, completion "methods" should be placed under tabkey.method# Context sensitive functions should be as simple as possible and the bulk# of the work should be done by the methods.## NOTE: The "first argument" description above is no longer true. The# functions argument list is to be treated as a single argument.## Remaining known issues:# Doesn't work (very well) with commands with dots in them.package tabkey.cebind ^i parse_command tabkey.mainalias tabkey.default tabkey.method.nickchanalias tabkey.main { @ :oxd = xdebug(extractw) xdebug extractw @ :curpos = curpos() @ :curword = indextoword($curpos $L ) @ :wordind = wordtoindex($curword $L) @ :cmdind = 0 if (32 >= (127 & ascii($mid(${curpos-1} 1 $L )))) { @ curword++ @ wordind = curpos } @ :word = mid($wordind ${curpos-wordind} $L) if (word=~["*"]) { @ :word = shift(word) } elsif (word=~["*]) { @ :word#=["] @ :word = shift(word) } if (!index($cmdchars $L)) { wait for @ :matches = tabkey.cmd($word) } else { wait for @ :matches = tabkey.default($word) } @ :prefix = prefix($matches) if (1 < numwords($matches) && word == prefix) { echo Completions for \"$word\": $matches } elsif (#matches && strlen($word) <= strlen($prefix)) { @ :prefix = 0 > index("$chr($jot(32 1))" $prefix) ? prefix : ["$prefix"] @ :line = mid(0 $wordind $L) parsekey erase_to_beg_of_line xtype -l $line$prefix${1<#matches?[]:[ ]} } xdebug $oxd}alias tabkey.cmd { bless @ :ret = :cmd = [] @ :pass = chr($jot($ascii(AZ))) @ :pass#= chr($jot($ascii(az))) @ :pass#= chr($jot($ascii(09))) @ :args = wordtoindex($cmdind $L) @ :args = mid($args $curpos $L) @ :args = unsplit(. $args) @ :args = pass(._$pass $args) if (!curword) { @ ret = tabkey.method.commands($args) repeat $#ret {push ret /$shift(ret)} return $ret } while (args) { @ :matches = aliasctl(alias pmatch tabkey.cmd.$args*) @ :matches = prefix($matches) if (curword == count(. $args)) { } elsif (matches != [tabkey.cmd.$args]) { } elsif (aliasctl(alias exists $matches)) { @ args = matches break } @ args = before(-1 . $args) } if (args) { wait for @ ret = ${args}($*) } unless (strlen($ret)) { wait for @ ret = tabkey.default($*) } return $ret}# Used for things like /eval and /repeat where what you are completing# is another command. depth is the arg number where the command begins.# This is not well cpu optimised. See examples below.alias tabkey.recurse (depth,...) { bless @ :curpos += wordtoindex($cmdind $L ) @ :curpos -= wordtoindex(${cmdind+depth} $L ) @ :cmdind += depth @ :curword -= depth @ function_return = 0 > curword ? [] : tabkey.cmd($*) @ :curword += depth @ :cmdind -= depth @ :curpos += wordtoindex(${cmdind+depth} $L ) @ :curpos -= wordtoindex($cmdind $L )}# Context sensitive completion goes here.alias tabkey.cmd.eval tabkey.recurse 1alias tabkey.cmd.repeat tabkey.recurse 2alias tabkey.cmd.dcc (args) { bless switch ($curword) { (1) {return $pattern("$args*" CHAT CLOSE CLOSEALL GET LIST RAW RENAME RESUME SEND)} }}alias tabkey.cmd.dcc.resume tabkey.cmd.dcc.sendalias tabkey.cmd.dcc.send { bless switch ($curword) { (0) (1) {echo This should never happen.;call;local} (2) {return $tabkey.method.nick($*)} (*) {return $tabkey.method.filei($*)} }}alias tabkey.cmd.help { bless @ :matches = [] @ :path = restw(1 $left($curpos $L)) if (wordind == curpos) {@ push(path *)} repeat $#path @ push(path $shift(path)*) @ matches = globi($unsplit(/ $getset(HELP_PATH) $path)) repeat $#matches @ push(matches $rightw(1 $remws(/ $split(/ $shift(matches))))) return $matches}# Methods.alias tabkey.method.commands { @ :ret = sort($uniq($getcommands($**) $aliasctl(alias match $*) $aliasctl(alias match $**))) return $ret}alias tabkey.method.chan (args) { return $pattern("$args*" $mychannels()); }alias tabkey.method.notify (args) { return $pattern("$args*" $notify(on)); }stack push alias alias.fooalias alias.foo alias $*;alias $sar(g/globi/glob/$sar(g/filei/file/$*))alias.foo tabkey.method.filei (f0) { @ :f0 = sar(gr/\\/\\\\/f0) @ :f0 = sar(gr/*/\\*/f0) @ :f0 = sar(gr/?/\\?/f0) @ :f0 = sar(gr/[/\\[/f0) @ :f0 = sar(gr/]/\\]/f0) @ :f0 = :f1 = globi("" $f0*) while (numwords($f0) == 1 && f0 =~ [*/]) { @ f0 = globi("" $f0*) } return ${f0 ? f0 : f1}}stack pop alias alias.fooalias tabkey.method.nick (args) { if (match("$args*" $chanusers())) { return $pattern("$args*" $chanusers()); } else { @ :chanusers = mychannels() repeat $#chanusers @ push(chanusers $chanusers($shift(chanusers))) return $pattern("$args*" $sort($uniq($chanusers))); }}alias tabkey.method.nickchan { return $remws(/ $tabkey.method.chan($*) $tabkey.method.nick($*))}alias tabkey.method.nickchannotify { return $remws(/ $tabkey.method.chan($*) $sort($uniq($tabkey.method.nick($*) $tabkey.method.notify($*))))}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -