| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- #nop vim: set filetype=tt:;
- /*
- 本文件属于 PaoTin++ 的一部分。
- PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
- 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
- */
- #nop ############################ 系统工具-帮助文档和参数类型检查 #################################;
- #alias {xtt.PrintHelpDoc} {
- #local aliasList {%1};
- #local funcList {%2};
- #local what {%3};
- #echo {%c%h} {light cyan};
- #if { "$what" == "" } {
- #echo {%c%s} {light yellow} {别名:};
- #foreach {$aliasList} {alias} {
- #if { "$alias" == "" } {
- #continue;
- };
- #var __XTinTinAPIDoc__ {};
- $alias 'XTinTinAPI;
- #if { "$__XTinTinAPIDoc__" == "" } {
- #echo { %c%-20s --- %s} {light cyan} {$alias} {(没有文档)};
- };
- #else {
- #echo { %c%-20s --- %s} {light cyan} {$alias} {$__XTinTinAPIDoc__[desc]};
- };
- };
- #echo {%c%s} {light yellow} {函数:};
- #local func {};
- #foreach {$funcList} {func} {
- #if { "$func" == "" } {
- #continue;
- };
- #var __XTinTinAPIDoc__ {};
- #local {funcCall} {#local _ {@$func{'XTinTinAPI}}};
- $funcCall;
- #if { "$__XTinTinAPIDoc__" == "" } {
- #echo { %c%-20s --- %s} {light cyan} {$func} {(没有文档)};
- };
- #else {
- #echo { %c%-20s --- %s} {light cyan} {$func} {$__XTinTinAPIDoc__[desc]};
- };
- };
- };
- #elseif { @slist.IndexOf{{$aliasList}; $what} > 0 } {
- #var __XTinTinAPIDoc__ {};
- $what 'XTinTinAPI;
- #if { "$__XTinTinAPIDoc__" == "" } {
- #echo {%c%%s} {light cyan} {没有关于 $alias 的文档。};
- };
- #else {
- #local _ @xtt.GenHelpDoc{{$__XTinTinAPIDoc__}};
- };
- };
- #elseif { @slist.IndexOf{{$funcList}; $what} > 0 } {
- #var __XTinTinAPIDoc__ {};
- #local {funcCall} {#local _ {@$what{'XTinTinAPI}}};
- $funcCall;
- #if { "$__XTinTinAPIDoc__" == "" } {
- #echo { %c%-20s --- %s} {light cyan} {$func} {(没有文档)};
- };
- #else {
- #local _ @xtt.GenHelpDoc{{$__XTinTinAPIDoc__}};
- };
- };
- #echo {%c%h} {light cyan};
- };
- #func {xtt.GenHelpDoc} {
- #local args {%1};
- #if { "$args[check]" == "'XTinTinAPI" } {
- #return {
- {name}{$args[name]}
- {type}{$args[type]}
- {desc}{$args[desc]}
- {args}{$args[args]}
- {check}{}
- };
- };
- #if { "$args[type]" == "alias" } {
- #echo {%c别名用法: %c%s 参数1 参数2...} {light cyan} {light yellow} {$args[name]};
- };
- #elseif { "$args[type]" == "function" } {
- #echo {%c函数用法: %c@%s{ {参数1}{值1} {参数2}{值2}... }} {light cyan} {light yellow} {$args[name]};
- };
- #else {
- #echo {%c不明类型的标识符: %c%s} {light red} {light yellow} {$args[name]};
- #echo {%c%h} {light cyan};
- #return;
- };
- #echo {%c说明:%s} {light cyan} {$args[desc]};
- #echo {%c参数列表(!必选,?可选):} {light cyan};
- #foreach *args[args][] {idx} {
- #local key {};
- #local desc {};
- #nop 注意别名和函数收集参数名称的方法不同;
- #if { "$args[type]" == "alias" } {
- #list tmp create $args[args][$idx];
- #format key {%s} {$tmp[1]};
- #format desc {%s} {$tmp[2]};
- };
- #else {
- #format key {%s} {$idx};
- #format desc {%s} $args[args][$idx];
- };
- #echo {%c %-16s -- %s} {light cyan} {$key} {$desc};
- };
- };
- /*
- 用法:将下面这段代码作为模版,插入到想要生成文档的别名或者函数开头,就可以了。
- #local ok @xtt.HelpDoc{{
- {type}{function}
- {name}{helpDoc}
- {desc}{为函数或别名提供代码注释,生成帮助文档,进行参数检查}
- {check}{%0}
- {args}{
- {!name}{函数或别名的名称}
- {!desc}{函数或别名的一句话说明}
- {!check}{需要检查的变量,别名用 %0,函数建议用 %1}
- {!args}{函数或别名的参数说明。}
- }
- }}
- #if { "$ok" != "true" } {
- #return "$ok"
- }
- 以上,截止到此处为止。
- 你可能已经注意到了,上面的代码调用了 xtt.HelpDoc 函数来检查参数并生成文档。
- 而 xtt.HelpDoc 本身就支持用以上语法来检查并生成文档。因此上面的代码本身也演示了如何调用函数。
- 注意第二个 args 有两种写法,如果是函数就用键值对,如果是别名就用列表(前面加{1}{2}{3})。
- 其中参数名用感叹号打头表示必选,问号打头表示可选,默认必选。
- */
- #func {xtt.HelpDoc} {
- #local args {%1};
- #if { "$args[check]" == "'XTinTinAPI" } {
- #return @XTinTinGenHelpDoc{{$args}};
- };
- #if { "$XTinTin[debug]" != "true" } {
- #return {true};
- };
- #local ok {true};
- #local realArgs {};
- #list realArgs create {$args[check]};
- #foreach {*args[args][]} {idx} {
- #nop 这个 key 必须要用 var,因为后面 regex 里面不支持 local;
- #var key {};
- #nop 注意别名和函数收集参数名称的方法不同;
- #if { "$args[type]" == "alias" } {
- #list tmp create $args[args][$idx];
- #format key {%s} {$tmp[1]};
- };
- #else {
- #format key {%s} {$idx};
- };
- #var optional {false};
- #regex {$key} {{!|\?}%%2} {
- #format key {%s} {&2};
- #if { "&1" == "?" } {
- #var optional {true};
- };
- }{};
- #nop 注意别名和函数收集参数值的方法不同;
- #local value {};
- #if { "$args[type]" == "alias" } {
- #format value {%s} {$realArgs[$idx]};
- };
- #else {
- #format value {%s} {$check[$key]};
- };
- #if { "$optional" == "false" && "$value" == "" } {
- #echo {%c函数或别名在调用时缺少必要的参数: %s} {light red} $key;
- #format ok {false};
- };
- };
- #unvar key;
- #if { "$ok" != "true" } {
- #echo {%c%h} {light cyan};
- #var _ @XTinTinGenHelpDoc{{$args}};
- #echo {%c-----\n%s} {light cyan} {实际传递的参数信息: \n$args[check]};
- #echo {%c%h} {light cyan};
- };
- #return $ok;
- };
- #var xtt.module-doc {};
- #alias {HELP} {xtt.Help %0; #buffer end};
- #alias {xtt.Help} {
- #local keyword {%1};
- #local len {@str.Len{$keyword}};
- #if { $len == 0 } {
- warnLog 用法: HELP <关键字>;
- #return;
- };
- #local maybe {};
- #local module {};
- #foreach {*xtt.module-doc[]} {module} {
- #if { "$module" == "%*$keyword%*" } {
- #local likely {@math.Eval{$len * 100 / @str.Len{$module}}};
- #list maybe {add} {{
- {likely} {$likely}
- {module} {$module}
- {keyword}{__MODULE__}
- }};
- #continue;
- };
- #local key {};
- #foreach {*xtt.module-doc[$module][]} {key} {
- #if { "$key" == "__MODULE__" } {
- #continue;
- };
- #if { "$key" == "%*$keyword%*" } {
- #local likely {@math.Eval{$len * 100 / @str.Len{$key}}};
- #list maybe {add} {{
- {likely} {$likely}
- {module} {$module}
- {keyword}{$key}
- }};
- };
- };
- };
- #local doc {};
- #if { &maybe[] == 0 } {
- errLog 没有找到关键字「$keyword」;
- #return;
- };
- #local doc {$maybe[1]};
- #if { &maybe[] > 1 } {
- #list maybe {indexate} {likely};
- #list maybe order;
- #local doc {$maybe[-1]};
- #if { "$doc[module]/$doc[keyword]" == "%*/$keyword/" } {
- okLog 以下是模块 $doc[module] 的文档。;
- };
- #elseif { $doc[likely] < 100 } {
- warnLog 找到 &maybe[] 个关键字,我猜你想看的是 <119>$doc[keyword]<129>@$doc[module]<299>;
- };
- #else {
- okLog 以下是关键字 $doc[keyword] 的文档。;
- };
- };
- #local module {$doc[module]};
- #local keyword {$doc[keyword]};
- #local idx {};
- #loop 1 {&xtt.module-doc[$module][$keyword][]} {idx} {
- #local line {$xtt.module-doc[$module][$keyword][$idx]};
- #regex {$line} {{##|#@} %S %*} {
- #if { "&1" == "##" } {
- #echo {<299>%s} {<B407><128> ## 别名 <138>&2 <868>&3<299>};
- };
- #else {
- #echo {<299>%s} {<B04a><128> ## 函数 <138>&2 <868>&3<299>};
- };
- } {
- #echo {<299>%s} {$line};
- };
- };
- #if { &maybe[] > 1 } {
- warnLog 也许你还想看看:;
- #local idx {};
- #loop {&maybe[]-1} {1} {idx} {
- #if { "$maybe[$idx][keyword]" == "__MODULE__" } {
- #echo {%s} {@mslp.Exec{xtt.Help $maybe[$idx][module];<129>$maybe[$idx][module] 模块<299>}};
- };
- #else {
- #echo {%s} {@mslp.Exec{xtt.Help $maybe[$idx][keyword];<129>$maybe[$idx][module] 模块的 <119>$maybe[$idx][keyword]<299>}};
- };
- };
- };
- };
- #alias {///===} {xtt.Doc};
- #alias {xtt.Doc} {
- #local doc {%1};
- #replace {doc} {;} {\x3b};
- #replace {doc} {\x7B} {\x7b};
- #replace {doc} {\x7D} {\x7d};
- #replace {doc} {///// } {;== };
- #replace {doc} {/////;} {;== ;};
- #replace {doc} {// } {;= };
- #replace {doc} {//;} {;= ;};
- #class xtt.doc.parse open;
- #var xtt-doc-keyword {};
- #alias {xtt.doc.add.module-doc} {
- #local doc {%%1};
- #regex {$doc} {== %*} {
- #list {xtt.module-doc[$MODULE][__MODULE__]} add {<269>&1<299>};
- };
- };
- #alias {xtt.doc.add.keyword-doc} {
- #local doc {%%1};
- #regex {$doc} {={([ ]{3,})- (\d\.\s*)?(\S+?)(: |:)| }%*} {
- #local text {};
- #if { "&1" != " " } {
- #local text {<299>&2- <168>&3&4<278>&5&6};
- };
- #else {
- #local text {<299> &6};
- };
- #list {xtt.module-doc[$MODULE][__MODULE__]} add {$text};
- #if { "$xtt-doc-keyword" != "" } {
- #list {xtt.module-doc[$MODULE][$xtt-doc-keyword]} add {$text};
- };
- };
- };
- #alias {xtt.doc.found.keyword} {
- #local doc {%%1};
- #if { !@isEmpty{$xtt-doc-keyword} } {
- #LOCAL idx {};
- #loop {&xtt.module-doc[$MODULE][$xtt-doc-keyword][]} {1} {idx} {
- #if @isEmpty{$xtt.module-doc[$MODULE][$xtt-doc-keyword][$idx]} {
- #list {xtt.module-doc[$MODULE][$xtt-doc-keyword]} delete {$idx};
- };
- };
- };
- #regex {$doc} {= {##|#@} %S %*} {
- #var xtt-doc-keyword {&2};
- xtt.doc.add.keyword-doc {= &1 &2 &3};
- };
- };
- #class xtt.doc.parse close;
- #local line {};
- #foreach {$doc} {line} {
- #switch {{$xtt-doc-keyword/$line}} {
- #case {{/}} {#0};
- #case {{%*/= #@ %S %*}} {xtt.doc.found.keyword {$line}};
- #case {{%*/= ## %S %*}} {xtt.doc.found.keyword {$line}};
- #case {{%*/= %*}} {xtt.doc.add.keyword-doc {$line}};
- #default {xtt.doc.add.module-doc {$line}; #var xtt-doc-keyword {}};
- };
- };
- #class xtt.doc.parse kill;
- };
- ///=== {
- ///// xtintin 是一个 TinTin++ 功能扩展集合,主要包含一些 MUD 无关的函数和别名,用于对 TinTin++ 的语法进行增强。
- ///// 类似于其它语言的标准库。
- /////
- ///// 本文档采用 xtintin 的文档化注释系统生成。
- ///// 有关 xtintin 的文档化注释,请查看 HELP xtt.Doc。
- /////
- // ## DataType
- // 打印 TinTin++ 和 xtintin 的<139>数据类型<299>说明文档。
- //
- // TinTin++ 中存在几种不同的数据类型,xtintin 基于这些数据类型扩展了一些函数,
- // 以增强对它们的处理能力。下面简单予以介绍:
- //
- // - 字符串: 简单变量,可以包含拉丁字母、阿拉伯数字、标点符号、UTF-8 中文、表情符号。
- // 理论上,所有其它类型的变量都有字符串表达形式,也都可以看作是字符串来操作。
- //
- // 字符串支持变量内插,也就是说字符串当中出现的变量和复合变量表达式都会被替换
- // 成相应的值,而函数调用则会被替换成调用结果。参见 #help SUBSTITUTIONS
- //
- // - 数值: TinTin++ 中并不严格区分字符串和数值,凡是内容长得像是数字一样的字符串,都
- // 可以直接当作数值来使用,主要是进行算术运算。大部分场合下数字都像字符串一样。
- // 只有少数几个场合才会被当成数值,请参考 #help math。
- //
- // - 布尔值: TinTin++ 中的 bool 值可以用来进行布尔逻辑运算,或者作为条件判断的条件。
- // 1 表示真,0 表示假。为了提高可读性,PaoTin++ 允许用 true 来表示真,用 false
- // 来表示假。
- //
- // - 正则表达式: 正则表达式是具有特殊含义的字符串。仅在正则表达式上下文中生效。
- // TinTin++ 中有两类正则表达式,一类是 TinTin++ 自身的语法,参见 #help regex,
- // 还有一类是 pcre 语法,参见 #help pcre。有关 pcre 的更多信息和高级用法,可以
- // 参考 man pcre 和 man pcresyntax。
- //
- // - 字符串列表: 字符串列表是由多个字符串构成的一个列表,多个字符串之间以分号隔开。
- // 例如 {a;b;c;d}。如前所述,字符串列表本身也可以看作是一个字符串。但由于其
- // 特殊的结构,可以视作是多个字符串构成的序列。
- //
- // TinTin++ 原生对字符串列表的支持不多,仅可用来遍历,或者是作为 #list 命令的
- // 参数。xtintin 对它进行了扩充,并基于字符串列表实现了集合运算。
- //
- // 还有另一种字符串列表,那就是用花括号代替分号分隔的字符串序列,例如
- // {a}{b}{c}{d},也被称为花括号列表,由于花括号列表在使用时存在一些限制,
- // 并且大部分情况下可以用分号分隔的字符串列表代替,所以不建议大家使用。
- // 即使如此,在许多要求使用字符串列表的场合,仍可接受大括号列表。本文档中将
- // 不再特别说明,请自行体会。
- //
- // - 表格: 表格是指由多组键值对构成的一种高级结构。类似与其它编程语言的 map(C++)、
- // hash(Perl)、dict(Python)、table(Lua)、Object(JSON)。例如:
- //
- // {a}{AAA}{b}{BBB}{c}{CCC}
- //
- // 习惯上一般把 a/b/c 称为 KEY(键),把 AAA/BBB/CCC 称为 VALUE(值)。键和值
- // 都可以是任意字符串。但习惯上 KEY 一般是一个简单字符串,而 VALUE 则可以
- // 包含复杂的数据结构(别忘了 TinTin++ 里任何数据结构都可以当作是字符串),
- // 因此表格实际上是可以嵌套的。TinTin++ 为嵌套的表格提供了专门的语法,可以
- // 方便地访问其中的元素。
- //
- // 请注意表格中的键值对通常被视作是没有顺序的。
- //
- // - 列表: 列表实际上是一种特殊的表格,也就是说,这个表格的所有键都是数值,
- // 并且是按顺序排列的、从 1 开始的。参见 #help list。
- //
- // 尽管如此,但列表在内存中的结构却和看上去并不相同。内存中的列表可以用
- // #list 命令高效操作,花括号在内存中实际上并不存在,只是在代码中和输出
- // 表达中为了区分键和值的边界而存在。
- //
- // 和表格一样,列表的值可以存储任意字符串,从而达到嵌套的目的。
- //
- // - 表格列表: 表格列表不是一种新的数据结构,只是说如果一个列表的所有值都是
- // 同一种格式的表格,那么这个数据结构就可以被称为表格列表。TinTin++ 和
- // xtintin 都为表格列表提供了更多的支持。参见 #help list。
- //
- // - 嵌套数据结构: 上面已经提到,所有的数据结构都可以被当作是字符串。而字符串
- // 又是 TinTin++ 中最基本的数据结构。所以这就为嵌套提供了语法基础。
- // 嵌套的数据结构有许多用处,最常见的比如表格列表。此外还可以模拟面向对象
- // 编程,或者是抽象数据类型。请自行体会。
- //
- // 你可以通过 #help lists 来了解详细说明。或者是参考小乖乖的中文手册:
- // https://github.com/zixijian/tt/blob/master/Wiki.md#lists
- //
- ///// 下面是 xtintin 的全部内容:
- // };
- #alias {xtt.Usage} {
- #local name {%1};
- #local message {@default{%2;用法不对}};
- errLog $message。正确用法如下:;
- xtt.Help $name;
- };
- #alias {DataType} {HELP DataType};
|