doc.tin 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. #nop vim: set filetype=tt:;
  2. /*
  3. 本文件属于 PaoTin++ 的一部分。
  4. PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
  5. 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
  6. */
  7. #nop ############################ 系统工具-帮助文档和参数类型检查 #################################;
  8. #alias {xtt.PrintHelpDoc} {
  9. #local aliasList {%1};
  10. #local funcList {%2};
  11. #local what {%3};
  12. #echo {%c%h} {light cyan};
  13. #if { "$what" == "" } {
  14. #echo {%c%s} {light yellow} {别名:};
  15. #foreach {$aliasList} {alias} {
  16. #if { "$alias" == "" } {
  17. #continue;
  18. };
  19. #var __XTinTinAPIDoc__ {};
  20. $alias 'XTinTinAPI;
  21. #if { "$__XTinTinAPIDoc__" == "" } {
  22. #echo { %c%-20s --- %s} {light cyan} {$alias} {(没有文档)};
  23. };
  24. #else {
  25. #echo { %c%-20s --- %s} {light cyan} {$alias} {$__XTinTinAPIDoc__[desc]};
  26. };
  27. };
  28. #echo {%c%s} {light yellow} {函数:};
  29. #local func {};
  30. #foreach {$funcList} {func} {
  31. #if { "$func" == "" } {
  32. #continue;
  33. };
  34. #var __XTinTinAPIDoc__ {};
  35. #local {funcCall} {#local _ {@$func{'XTinTinAPI}}};
  36. $funcCall;
  37. #if { "$__XTinTinAPIDoc__" == "" } {
  38. #echo { %c%-20s --- %s} {light cyan} {$func} {(没有文档)};
  39. };
  40. #else {
  41. #echo { %c%-20s --- %s} {light cyan} {$func} {$__XTinTinAPIDoc__[desc]};
  42. };
  43. };
  44. };
  45. #elseif { @slist.IndexOf{{$aliasList}; $what} > 0 } {
  46. #var __XTinTinAPIDoc__ {};
  47. $what 'XTinTinAPI;
  48. #if { "$__XTinTinAPIDoc__" == "" } {
  49. #echo {%c%%s} {light cyan} {没有关于 $alias 的文档。};
  50. };
  51. #else {
  52. #local _ @xtt.GenHelpDoc{{$__XTinTinAPIDoc__}};
  53. };
  54. };
  55. #elseif { @slist.IndexOf{{$funcList}; $what} > 0 } {
  56. #var __XTinTinAPIDoc__ {};
  57. #local {funcCall} {#local _ {@$what{'XTinTinAPI}}};
  58. $funcCall;
  59. #if { "$__XTinTinAPIDoc__" == "" } {
  60. #echo { %c%-20s --- %s} {light cyan} {$func} {(没有文档)};
  61. };
  62. #else {
  63. #local _ @xtt.GenHelpDoc{{$__XTinTinAPIDoc__}};
  64. };
  65. };
  66. #echo {%c%h} {light cyan};
  67. };
  68. #func {xtt.GenHelpDoc} {
  69. #local args {%1};
  70. #if { "$args[check]" == "'XTinTinAPI" } {
  71. #return {
  72. {name}{$args[name]}
  73. {type}{$args[type]}
  74. {desc}{$args[desc]}
  75. {args}{$args[args]}
  76. {check}{}
  77. };
  78. };
  79. #if { "$args[type]" == "alias" } {
  80. #echo {%c别名用法: %c%s 参数1 参数2...} {light cyan} {light yellow} {$args[name]};
  81. };
  82. #elseif { "$args[type]" == "function" } {
  83. #echo {%c函数用法: %c@%s{ {参数1}{值1} {参数2}{值2}... }} {light cyan} {light yellow} {$args[name]};
  84. };
  85. #else {
  86. #echo {%c不明类型的标识符: %c%s} {light red} {light yellow} {$args[name]};
  87. #echo {%c%h} {light cyan};
  88. #return;
  89. };
  90. #echo {%c说明:%s} {light cyan} {$args[desc]};
  91. #echo {%c参数列表(!必选,?可选):} {light cyan};
  92. #foreach *args[args][] {idx} {
  93. #local key {};
  94. #local desc {};
  95. #nop 注意别名和函数收集参数名称的方法不同;
  96. #if { "$args[type]" == "alias" } {
  97. #list tmp create $args[args][$idx];
  98. #format key {%s} {$tmp[1]};
  99. #format desc {%s} {$tmp[2]};
  100. };
  101. #else {
  102. #format key {%s} {$idx};
  103. #format desc {%s} $args[args][$idx];
  104. };
  105. #echo {%c %-16s -- %s} {light cyan} {$key} {$desc};
  106. };
  107. };
  108. /*
  109. 用法:将下面这段代码作为模版,插入到想要生成文档的别名或者函数开头,就可以了。
  110. #local ok @xtt.HelpDoc{{
  111. {type}{function}
  112. {name}{helpDoc}
  113. {desc}{为函数或别名提供代码注释,生成帮助文档,进行参数检查}
  114. {check}{%0}
  115. {args}{
  116. {!name}{函数或别名的名称}
  117. {!desc}{函数或别名的一句话说明}
  118. {!check}{需要检查的变量,别名用 %0,函数建议用 %1}
  119. {!args}{函数或别名的参数说明。}
  120. }
  121. }}
  122. #if { "$ok" != "true" } {
  123. #return "$ok"
  124. }
  125. 以上,截止到此处为止。
  126. 你可能已经注意到了,上面的代码调用了 xtt.HelpDoc 函数来检查参数并生成文档。
  127. 而 xtt.HelpDoc 本身就支持用以上语法来检查并生成文档。因此上面的代码本身也演示了如何调用函数。
  128. 注意第二个 args 有两种写法,如果是函数就用键值对,如果是别名就用列表(前面加{1}{2}{3})。
  129. 其中参数名用感叹号打头表示必选,问号打头表示可选,默认必选。
  130. */
  131. #func {xtt.HelpDoc} {
  132. #local args {%1};
  133. #if { "$args[check]" == "'XTinTinAPI" } {
  134. #return @XTinTinGenHelpDoc{{$args}};
  135. };
  136. #if { "$XTinTin[debug]" != "true" } {
  137. #return {true};
  138. };
  139. #local ok {true};
  140. #local realArgs {};
  141. #list realArgs create {$args[check]};
  142. #foreach {*args[args][]} {idx} {
  143. #nop 这个 key 必须要用 var,因为后面 regex 里面不支持 local;
  144. #var key {};
  145. #nop 注意别名和函数收集参数名称的方法不同;
  146. #if { "$args[type]" == "alias" } {
  147. #list tmp create $args[args][$idx];
  148. #format key {%s} {$tmp[1]};
  149. };
  150. #else {
  151. #format key {%s} {$idx};
  152. };
  153. #var optional {false};
  154. #regex {$key} {{!|\?}%%2} {
  155. #format key {%s} {&2};
  156. #if { "&1" == "?" } {
  157. #var optional {true};
  158. };
  159. }{};
  160. #nop 注意别名和函数收集参数值的方法不同;
  161. #local value {};
  162. #if { "$args[type]" == "alias" } {
  163. #format value {%s} {$realArgs[$idx]};
  164. };
  165. #else {
  166. #format value {%s} {$check[$key]};
  167. };
  168. #if { "$optional" == "false" && "$value" == "" } {
  169. #echo {%c函数或别名在调用时缺少必要的参数: %s} {light red} $key;
  170. #format ok {false};
  171. };
  172. };
  173. #unvar key;
  174. #if { "$ok" != "true" } {
  175. #echo {%c%h} {light cyan};
  176. #var _ @XTinTinGenHelpDoc{{$args}};
  177. #echo {%c-----\n%s} {light cyan} {实际传递的参数信息: \n$args[check]};
  178. #echo {%c%h} {light cyan};
  179. };
  180. #return $ok;
  181. };
  182. #var xtt.module-doc {};
  183. #var xtt.module-test {};
  184. #alias {HELP} {xtt.Help %0; #buffer end};
  185. #alias {xtt.Help} {
  186. #local keyword {%1};
  187. #local len {@str.Len{$keyword}};
  188. #if { $len == 0 } {
  189. warnLog 用法: HELP <关键字>;
  190. #return;
  191. };
  192. #local maybe {};
  193. #local module {};
  194. #foreach {*xtt.module-doc[]} {module} {
  195. #if { "$module" == "%*$keyword%*" } {
  196. #local likely {@math.Eval{$len * 100 / @str.Len{$module}}};
  197. #list maybe {add} {{
  198. {likely} {$likely}
  199. {module} {$module}
  200. {keyword}{__MODULE__}
  201. }};
  202. #continue;
  203. };
  204. #local key {};
  205. #foreach {*xtt.module-doc[$module][]} {key} {
  206. #if { "$key" == "__MODULE__" } {
  207. #continue;
  208. };
  209. #if { "$key" == "%*$keyword%*" } {
  210. #local likely {@math.Eval{$len * 100 / @str.Len{$key}}};
  211. #list maybe {add} {{
  212. {likely} {$likely}
  213. {module} {$module}
  214. {keyword}{$key}
  215. }};
  216. };
  217. };
  218. };
  219. #local doc {};
  220. #if { &maybe[] == 0 } {
  221. errLog 没有找到关键字「$keyword」;
  222. #return;
  223. };
  224. #local doc {$maybe[1]};
  225. #if { &maybe[] > 1 } {
  226. #list maybe {indexate} {likely};
  227. #list maybe order;
  228. #local doc {$maybe[-1]};
  229. #if { "$doc[module]/$doc[keyword]" == "%*/$keyword/" } {
  230. okLog 以下是模块 $doc[module] 的文档。;
  231. };
  232. #elseif { $doc[likely] < 100 } {
  233. warnLog 找到 &maybe[] 个关键字,我猜你想看的是 <119>$doc[keyword]<129>@$doc[module]<299>;
  234. };
  235. #else {
  236. okLog 以下是关键字 $doc[keyword] 的文档。;
  237. };
  238. };
  239. #local module {$doc[module]};
  240. #local keyword {$doc[keyword]};
  241. #local idx {};
  242. #loop 1 {&xtt.module-doc[$module][$keyword][]} {idx} {
  243. #local line {$xtt.module-doc[$module][$keyword][$idx]};
  244. #regex {$line} {{##|#@|#=} %S %*} {
  245. #if { "&1" == "##" } {
  246. #echo {<299>%s} {<B407><128> ## 别名 <138>&2 <868>&3<299>};
  247. };
  248. #elseif { "&1" == "#@" } {
  249. #echo {<299>%s} {<B04a><128> ## 函数 <138>&2 <868>&3<299>};
  250. };
  251. #elseif { "&1" == "#=" } {
  252. #echo {<299>%s} {<B00d><128> ## 文档 <138>&2 <868>&3<299>};
  253. };
  254. } {
  255. #echo {<299>%s} {$line};
  256. };
  257. };
  258. #if { &xtt.module-test[$module][$keyword][] > 0 } {
  259. #echo { 用法举例:\n};
  260. #local case {};
  261. #foreach {*xtt.module-test[$module][$keyword][]} {case} {
  262. #local {test} {test/$module/$keyword/case/$case};
  263. #if { @xtt.genTestCase{$test;$module;$keyword;$case} } {
  264. #alias $test;
  265. #unalias $test;
  266. };
  267. };
  268. };
  269. #if { &maybe[] > 1 } {
  270. warnLog 也许你还想看看:;
  271. #local idx {};
  272. #loop {&maybe[]-1} {1} {idx} {
  273. #if { "$maybe[$idx][keyword]" == "__MODULE__" } {
  274. #echo {%s} {@mslp.Exec{xtt.Help $maybe[$idx][module];<129>$maybe[$idx][module] 模块<299>}};
  275. };
  276. #else {
  277. #echo {%s} {@mslp.Exec{xtt.Help $maybe[$idx][keyword];<129>$maybe[$idx][module] 模块的 <119>$maybe[$idx][keyword]<299>}};
  278. };
  279. };
  280. };
  281. };
  282. #alias {///===} {xtt.Doc};
  283. #alias {xtt.Doc} {
  284. #local doc {%1};
  285. #replace {doc} {;} {\x3b};
  286. #replace {doc} {\x7B} {\x7b};
  287. #replace {doc} {\x7D} {\x7d};
  288. #replace {doc} {///// } {;== };
  289. #replace {doc} {/////;} {;== ;};
  290. #replace {doc} {// } {;= };
  291. #replace {doc} {//;} {;= ;};
  292. #class xtt.doc.parse open;
  293. #var xtt-doc-keyword {};
  294. #alias {xtt.doc.add.module-doc} {
  295. #local doc {%%1};
  296. #regex {$doc} {== %*} {
  297. #list {xtt.module-doc[$MODULE][__MODULE__]} add {<269>&1<299>};
  298. };
  299. };
  300. #alias {xtt.doc.add.keyword-doc} {
  301. #local doc {%%1};
  302. #regex {$doc} {={([ ]{3,})- (\d\.\s*)?(\S+?)(: |:)| }%*} {
  303. #local text {};
  304. #if { "&1" != " " } {
  305. #local text {<299>&2- <168>&3&4<278>&5&6};
  306. };
  307. #else {
  308. #local text {<299> &6};
  309. };
  310. #list {xtt.module-doc[$MODULE][__MODULE__]} add {$text};
  311. #if { "$xtt-doc-keyword" != "" } {
  312. #list {xtt.module-doc[$MODULE][$xtt-doc-keyword]} add {$text};
  313. };
  314. };
  315. };
  316. #alias {xtt.doc.found.keyword} {
  317. #local doc {%%1};
  318. #if { !@isEmpty{$xtt-doc-keyword} } {
  319. #LOCAL idx {};
  320. #loop {&xtt.module-doc[$MODULE][$xtt-doc-keyword][]} {1} {idx} {
  321. #if @isEmpty{$xtt.module-doc[$MODULE][$xtt-doc-keyword][$idx]} {
  322. #list {xtt.module-doc[$MODULE][$xtt-doc-keyword]} delete {$idx};
  323. };
  324. };
  325. };
  326. #regex {$doc} {= {##|#@|#=} %S %*} {
  327. #var xtt-doc-keyword {&2};
  328. xtt.doc.add.keyword-doc {= &1 &2 &3};
  329. };
  330. };
  331. #alias {xtt.doc.new.example} {
  332. #list xtt.module-test[$MODULE][$xtt-doc-keyword] add {{}};
  333. };
  334. #alias {xtt.doc.add.example} {
  335. #local part {%%1};
  336. #local line {%%2};
  337. #replace line {^=%s} {};
  338. #replace line {%+1..s$} {};
  339. #local idx {&xtt.module-test[$MODULE][$xtt-doc-keyword][]};
  340. #if { {$line} != {} } {
  341. #list xtt.module-test[$MODULE][$xtt-doc-keyword][$idx][$part] add {{$line}};
  342. };
  343. };
  344. #class xtt.doc.parse close;
  345. #local state {doc};
  346. #local line {};
  347. #foreach {$doc} {line} {
  348. #switch {{$state/$xtt-doc-keyword/$line}} {
  349. #case {{%*/%*/= #@ %S %*}} {
  350. #local state {doc};
  351. xtt.doc.found.keyword {$line};
  352. };
  353. #case {{%*/%*/= ## %S %*}} {
  354. #local state {doc};
  355. xtt.doc.found.keyword {$line};
  356. };
  357. #case {{%*/%*/= #= %S %*}} {
  358. #local state {doc};
  359. xtt.doc.found.keyword {$line};
  360. };
  361. #case {{%*/%*/= %sEXAMPLE:%*}} {
  362. #local state {test};
  363. #replace line {%sEXAMPLE:} {};
  364. xtt.doc.new.example;
  365. xtt.doc.add.example CODE {$line};
  366. };
  367. #case {{test/%*/= %sRESULT:%*}} {
  368. #local state {result};
  369. #replace line {%sRESULT:} {};
  370. xtt.doc.add.example RESULT {$line};
  371. };
  372. #case {{test/%*/= %sASSERT:%*}} {
  373. #local state {assert};
  374. #replace line {%sASSERT:} {};
  375. xtt.doc.add.example ASSERT {$line};
  376. };
  377. #case {{test/%*/= %sOUTPUT:%*}} {
  378. #local state {output};
  379. #replace line {%sOUTPUT:} {};
  380. xtt.doc.add.example OUTPUT {$line};
  381. };
  382. #case {{doc//}} {#0};
  383. #case {{doc/%*/= %*}} {xtt.doc.add.keyword-doc {$line}};
  384. #case {{test/%*/= %*}} {xtt.doc.add.example CODE {$line}};
  385. #case {{result/%*/= %*}} {xtt.doc.add.example RESULT {$line}};
  386. #case {{assert/%*/= %*}} {xtt.doc.add.example ASSERT {$line}};
  387. #case {{output/%*/= %*}} {xtt.doc.add.example OUTPUT {$line}};
  388. #default {xtt.doc.add.module-doc {$line}; #var xtt-doc-keyword {}};
  389. };
  390. };
  391. #class xtt.doc.parse kill;
  392. };
  393. #alias {OK} {
  394. #local module {%1};
  395. #local keyword {%2};
  396. #local case {%4};
  397. #local msg {$module $keyword test case $case};
  398. #echo {%s} {$msg @str.Repeat{@math.Eval{70 - @str.Width{$msg}};.} <129>OK<299>};
  399. };
  400. #alias {BAD} {
  401. #local module {%1};
  402. #local keyword {%2};
  403. #local case {%4};
  404. #local msg {$module $keyword test case $case};
  405. #echo {%s} {$msg @str.Repeat{@math.Eval{70 - @str.Width{$msg}};.} <119>BAD<299>};
  406. };
  407. #func {xtt.genTestCase} {
  408. #local name {%1};
  409. #local module {%2};
  410. #local keyword {%3};
  411. #local case {@defaultNum{%4;1}};
  412. #unalias {$name};
  413. #if { &xtt.module-test[$module][$keyword][] <= 0 } {
  414. #return 0;
  415. };
  416. #local call {@slist.Join{{@slist.FromList{$xtt.module-test[$module][$keyword][$case][CODE]}}}};
  417. #replace call {^%*\\x3b$} {&1};
  418. #local rslt {$xtt.module-test[$module][$keyword][$case][RESULT][1]};
  419. #local assert {$xtt.module-test[$module][$keyword][$case][ASSERT][1]};
  420. #local output {$xtt.module-test[$module][$keyword][$case][OUTPUT]};
  421. #if { {$output} !== {} } {
  422. #local width {@math.Eval{&output[] / 10 + 1}};
  423. #local lines {@slist.JoinAs{{@slist.FromList{@fp.Map{{$output};{第\@str.AlignRight{KEY;$width}行: VALUE}}}};{#nop %s\x3b}}};
  424. #line sub {var;escapes} #alias {$name} {$call; #nop 预期得到多行文本:;$lines};
  425. #unalias {$name/wrapper};
  426. #line sub {var;escapes} #alias {$name/wrapper} {
  427. #local got {};
  428. #line quiet #line capture got $name;
  429. #local got {@str.Plain{$got}};
  430. xtt.Test.Assert {$module} {$keyword} {$case} 预期得到 {$output} 实际得到 {\$got};
  431. };
  432. #return 2;
  433. };
  434. #if { {$assert} !== {} } {
  435. #local expect {};
  436. #local got {};
  437. #regex {$assert} {%* === %*} {
  438. #format got {%s} {&1};
  439. #format expect {%s} {&2};
  440. };
  441. #line sub {var;escapes} #alias {$name} {
  442. $call;
  443. xtt.Test.Assert {$module} {$keyword} {$case} 预期得到 $expect 实际得到 $got;
  444. };
  445. #return 1;
  446. };
  447. #if { {$rslt} !== {} } {
  448. #line sub {var;escapes} #alias {$name} {
  449. #local result {
  450. $call
  451. };
  452. xtt.Test.Assert {$module} {$keyword} {$case} 预期得到 $rslt 实际得到 {\$result};
  453. };
  454. #return 1;
  455. };
  456. #if { {$call} !== {} } {
  457. #line sub {var;escapes} #alias {$name} {
  458. $call
  459. };
  460. #return 3;
  461. };
  462. };
  463. #alias {xtt.Test.Assert} {
  464. #local module {%1};
  465. #local keyword {%2};
  466. #local case {%3};
  467. #local expect {%5};
  468. #local got {%7};
  469. #if { {$got} === {$expect} } {
  470. OK $module $keyword case $case;
  471. };
  472. #else {
  473. BAD $module $keyword case $case;
  474. errLog 断言失败:预期得到 {$expect} 实际得到 {$got};
  475. };
  476. };
  477. ///=== {
  478. // ## xtt.Test [<模块名称> [<关键字名称>]]
  479. // 测试指定模块中的指定关键字所对应的全部测试用例。
  480. // 如果省略关键字名称,则测试该模块中所有的关键字。
  481. // 如果省略模块名称,则测试所有的模块。
  482. // 你也可以通过 TEST 别名来使用本别名。
  483. // };
  484. #alias {TEST} {xtt.Test};
  485. #alias {xtt.Test} {
  486. #local module {%1};
  487. #local keyword {%2};
  488. #if { "$module" == "" } {
  489. #foreach {*xtt.module-test[]} {module} {
  490. xtt.Test {$module};
  491. };
  492. #return;
  493. };
  494. #if { "$keyword" == "" } {
  495. #foreach {*xtt.module-test[$module][]} {keyword} {
  496. xtt.Test {$module} {$keyword};
  497. };
  498. #return;
  499. };
  500. #local case {};
  501. #foreach {*xtt.module-test[$module][$keyword][]} {case} {
  502. #local {test} {test/$module/$keyword/case/$case};
  503. #local code {@xtt.genTestCase{$test;$module;$keyword;$case}};
  504. #switch {$code} {
  505. #case {1} {$test; #unalias $test};
  506. #case {2} {$test/wrapper; #unalias $test; #unalias $test/wrapper};
  507. };
  508. };
  509. };
  510. #alias {test/{.*}/{[^/]*}/case/%d} {xtt.Test %1 %2} {9.000};
  511. ///=== {
  512. ///// xtintin 是一个 TinTin++ 功能扩展集合,主要包含一些 MUD 无关的函数和别名,用于对 TinTin++ 的语法进行增强。
  513. ///// 类似于其它语言的标准库。
  514. /////
  515. ///// 本文档采用 xtintin 的文档化注释系统生成。
  516. ///// 有关 xtintin 的文档化注释,请查看 HELP xtt.Doc。
  517. /////
  518. // #= DataType
  519. // 打印 TinTin++ 和 xtintin 的<139>数据类型<299>说明文档。
  520. //
  521. // TinTin++ 中存在几种不同的数据类型,xtintin 基于这些数据类型扩展了一些函数,
  522. // 以增强对它们的处理能力。下面简单予以介绍:
  523. //
  524. // - 字符串: 简单变量,可以包含拉丁字母、阿拉伯数字、标点符号、UTF-8 中文、表情符号。
  525. // 理论上,所有其它类型的变量都有字符串表达形式,也都可以看作是字符串来操作。
  526. //
  527. // 字符串支持变量内插,也就是说字符串当中出现的变量和复合变量表达式都会被替换
  528. // 成相应的值,而函数调用则会被替换成调用结果。参见 #help SUBSTITUTIONS
  529. //
  530. // - 数值: TinTin++ 中并不严格区分字符串和数值,凡是内容长得像是数字一样的字符串,都
  531. // 可以直接当作数值来使用,主要是进行算术运算。大部分场合下数字都像字符串一样。
  532. // 只有少数几个场合才会被当成数值,请参考 #help math。
  533. //
  534. // - 布尔值: TinTin++ 中的 bool 值可以用来进行布尔逻辑运算,或者作为条件判断的条件。
  535. // 1 表示真,0 表示假。为了提高可读性,PaoTin++ 允许用 true 来表示真,用 false
  536. // 来表示假。
  537. //
  538. // - 正则表达式: 正则表达式是具有特殊含义的字符串。仅在正则表达式上下文中生效。
  539. // TinTin++ 中有两类正则表达式,一类是 TinTin++ 自身的语法,参见 #help regex,
  540. // 还有一类是 pcre 语法,参见 #help pcre。有关 pcre 的更多信息和高级用法,可以
  541. // 参考 man pcre 和 man pcresyntax。
  542. //
  543. // - 字符串列表: 字符串列表是由多个字符串构成的一个列表,多个字符串之间以分号隔开。
  544. // 例如 {a;b;c;d}。如前所述,字符串列表本身也可以看作是一个字符串。但由于其
  545. // 特殊的结构,可以视作是多个字符串构成的序列。
  546. //
  547. // TinTin++ 原生对字符串列表的支持不多,仅可用来遍历,或者是作为 #list 命令的
  548. // 参数。xtintin 对它进行了扩充,并基于字符串列表实现了集合运算。
  549. //
  550. // 还有另一种字符串列表,那就是用花括号代替分号分隔的字符串序列,例如
  551. // {a}{b}{c}{d},也被称为花括号列表,由于花括号列表在使用时存在一些限制,
  552. // 并且大部分情况下可以用分号分隔的字符串列表代替,所以不建议大家使用。
  553. // 即使如此,在许多要求使用字符串列表的场合,仍可接受大括号列表。本文档中将
  554. // 不再特别说明,请自行体会。
  555. //
  556. // - 表格: 表格是指由多组键值对构成的一种高级结构。类似与其它编程语言的 map(C++)、
  557. // hash(Perl)、dict(Python)、table(Lua)、Object(JSON)。例如:
  558. //
  559. // {a}{AAA}{b}{BBB}{c}{CCC}
  560. //
  561. // 习惯上一般把 a/b/c 称为 KEY(键),把 AAA/BBB/CCC 称为 VALUE(值)。键和值
  562. // 都可以是任意字符串。但习惯上 KEY 一般是一个简单字符串,而 VALUE 则可以
  563. // 包含复杂的数据结构(别忘了 TinTin++ 里任何数据结构都可以当作是字符串),
  564. // 因此表格实际上是可以嵌套的。TinTin++ 为嵌套的表格提供了专门的语法,可以
  565. // 方便地访问其中的元素。
  566. //
  567. // 请注意表格中的键值对通常被视作是没有顺序的。
  568. //
  569. // - 列表: 列表实际上是一种特殊的表格,也就是说,这个表格的所有键都是数值,
  570. // 并且是按顺序排列的、从 1 开始的。参见 #help list。
  571. //
  572. // 尽管如此,但列表在内存中的结构却和看上去并不相同。内存中的列表可以用
  573. // #list 命令高效操作,花括号在内存中实际上并不存在,只是在代码中和输出
  574. // 表达中为了区分键和值的边界而存在。
  575. //
  576. // 和表格一样,列表的值可以存储任意字符串,从而达到嵌套的目的。
  577. //
  578. // - 表格列表: 表格列表不是一种新的数据结构,只是说如果一个列表的所有值都是
  579. // 同一种格式的表格,那么这个数据结构就可以被称为表格列表。TinTin++ 和
  580. // xtintin 都为表格列表提供了更多的支持。参见 #help list。
  581. //
  582. // - 嵌套数据结构: 上面已经提到,所有的数据结构都可以被当作是字符串。而字符串
  583. // 又是 TinTin++ 中最基本的数据结构。所以这就为嵌套提供了语法基础。
  584. // 嵌套的数据结构有许多用处,最常见的比如表格列表。此外还可以模拟面向对象
  585. // 编程,或者是抽象数据类型。请自行体会。
  586. //
  587. // 你可以通过 #help lists 来了解详细说明。或者是参考小乖乖的中文手册:
  588. // https://github.com/zixijian/tt/blob/master/Wiki.md#lists
  589. //
  590. ///// 下面是 xtintin 的全部内容:
  591. // };
  592. #alias {xtt.Usage} {
  593. #local name {%1};
  594. #local message {@default{%2;用法不对}};
  595. errLog $message。正确用法如下:;
  596. xtt.Help $name;
  597. };