Просмотр исходного кода

refactor(xtintin): 拆分 funcs.tin,增加新函数,修复 BUG (不含文档)

dzp 2 лет назад
Родитель
Сommit
e436f71ad0

+ 9 - 3
mud/pkuxkx/plugins/quest/tang.tin

@@ -1,5 +1,11 @@
 #nop vim: set filetype=tt:;
 
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
 #var quest_tang[META] {
     {NAME}      {大唐爵位任务}
     {DESC}      {只实现了举报盗贼,满足条件后会自动提升爵位到男爵}
@@ -511,10 +517,10 @@ load-lib speedo;
 #alias {tang.案件进展} {
     #class tang.ask kill;
 
-    #local list {@list2string{{${tang.data[好人名单]}}}};
+    #local list {@list2string{${tang.data[好人名单]}}};
     #replace list {;} { };
     #echo {目前发现的好人  : <120>$list<070>};
-    #local list {@list2string{{${tang.data[嫌疑人名单]}}}};
+    #local list {@list2string{${tang.data[嫌疑人名单]}}};
     #replace list {;} { };
     #echo {目前发现的嫌疑人: <130>$list<070>};
 
@@ -553,7 +559,7 @@ load-lib speedo;
     };
         
     #local place {${tang-all-location[${tang-task-location}]}};
-    #local path {@reverseCmds{{$place[path]}}};
+    #local path {@reverseCmds{$place[path]}};
     $path;
 
     #class tang.back open;

+ 7 - 7
plugins/lib/speedo.tin

@@ -2,7 +2,7 @@
 
 /*
 本文件属于 PaoTin++ 的一部分。
-PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
 */
 
@@ -19,9 +19,9 @@ PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 
 #alias {speedo.Add} {
     #local key          {%1};
-    #local value        {@defaultInt{%2;0}};
+    #local value        {@defaultNum{%2;0}};
     #local monotone     {@default{%3;false}};
-    #local keepalive    {@defaultInt{%4;60}};
+    #local keepalive    {@defaultNum{%4;60}};
 
     #if { @isEmpty{$key} } {
         #return;
@@ -33,9 +33,9 @@ PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 
 #alias {speedo.Set} {
     #local key          {%1};
-    #local value        {@defaultInt{%2;0}};
+    #local value        {@defaultNum{%2;0}};
     #local monotone     {@default{%3;false}};
-    #local keepalive    {@defaultInt{%4;60}};
+    #local keepalive    {@defaultNum{%4;60}};
 
     #if { @isEmpty{$key} } {
         #return;
@@ -107,7 +107,7 @@ PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 
 #func {speedo.GetSpeedInfo} {
     #local key      {%1};
-    #local interval {@defaultInt{%2;1}};
+    #local interval {@defaultNum{%2;1}};
 
     #if { @isEmpty{$key} } {
         #return {};
@@ -171,7 +171,7 @@ PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 };
 
 #alias {speedo.List} {
-    #local interval {@defaultInt{%1;1}};
+    #local interval {@defaultNum{%1;1}};
     #local pattern  {@default{%2;{%*}}};
 
 	#echo {<128>     %-14s %+10s %+10s %+14s %-20s %-20s %+10s} {统计对象} {统计结果} {平均值} {测算周期(秒)} {样本开始时间} {样本截止时间} {发呆时间};

+ 10 - 2
plugins/lib/ui/prompt.tin

@@ -1,3 +1,11 @@
+#nop vim: set filetype=tt:;
+
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
 #var lib_ui_prompt[META] {
     {NAME}      {提示栏插件}
     {DESC}      {支持丰富的自定义选项,用户可用此模块定制自己的 UI。}
@@ -479,7 +487,7 @@ tt++ table 由一组选项和与之对应的选项值来组成,用来说明想
         };
 
         #format value {$color%-${width}s<070>} {$value[value]};
-        #math lineWidth {$lineWidth + @strWidth{$label} + @strWidth{$value}};
+        #math lineWidth {$lineWidth + @width{$label} + @width{$value}};
         #if { "$text" == "" } {
             #local text {$label$value};
         };
@@ -546,7 +554,7 @@ tt++ table 由一组选项和与之对应的选项值来组成,用来说明想
     #local color    {%3};
 
     #local newText {@trim{$text}};
-    #math width {$width + @strWidth{$newText} - @strWidth{$text}};
+    #math width {$width + @width{$newText} - @width{$text}};
 
     #local screenWidth {0};
     #screen get COLS screenWidth;

+ 7 - 1
plugins/lib/ui/tmux.tin

@@ -1,5 +1,11 @@
 #nop vim: set filetype=tt:;
 
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
 #var lib_ui_tmux[META] {
     {NAME}      {TMUX UI}
     {DESC}      {支持丰富的自定义选项,用户可定制自己的 tmux 边框样式。}
@@ -201,7 +207,7 @@
 #func {tmux.Width} {
     #local arg {%1};
     #replace {arg} {{#\[[^\]]*\]}} {};
-    #return {@len{{$arg}}};
+    #return {@len{$arg}};
 };
 
 #nop 默认每分钟更新一次。;

+ 7 - 3
plugins/lib/xtintin/__init__.tin

@@ -2,17 +2,21 @@
 
 /*
 本文件属于 PaoTin++ 的一部分。
-PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
 */
 
 #nop xtintin 是为了方便 TinTin++ 使用而增加的一些语法扩展。;
 
-load-file plugins/lib/xtintin/funcs.tin;
+load-file plugins/lib/xtintin/number.tin;
+load-file plugins/lib/xtintin/bool.tin;
+load-file plugins/lib/xtintin/string.tin;
+load-file plugins/lib/xtintin/list.tin;
+load-file plugins/lib/xtintin/time.tin;
+load-file plugins/lib/xtintin/path.tin;
 load-file plugins/lib/xtintin/cmds.tin;
 load-file plugins/lib/xtintin/debug.tin;
 load-file plugins/lib/xtintin/fp.tin;
-load-file plugins/lib/xtintin/answer.tin;
 load-file plugins/lib/xtintin/default.tin;
 load-file plugins/lib/xtintin/diff.tin;
 load-file plugins/lib/xtintin/mslp.tin;

+ 0 - 12
plugins/lib/xtintin/answer.tin

@@ -1,12 +0,0 @@
-#nop 回答服务器提出的问题(妥善处理不带换行符的文本。);
-
-/*
-   TinTin++ 的光标控制有点问题,问题和回答的显示有重叠,必须手动 #buffer end 才行。
-*/
-#alias {xtt.Answer} {
-    #delay 0 {
-        #echo {};
-        #buffer end;
-        #send {%1};
-    };
-};

+ 81 - 0
plugins/lib/xtintin/bool.tin

@@ -0,0 +1,81 @@
+#nop vim: set filetype=tt:;
+
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
+#func {true}    {#return 1};
+#func {false}   {#return 0};
+
+#func {isTrue} {
+    #if { "%0" == "{true|1}" } {
+        #return 1;
+    };
+    #else {
+        #return 0;
+    };
+};
+
+#func {isFalse} {
+    #if { "%0" == "{false|0}" } {
+        #return 1;
+    };
+    #else {
+        #return 0;
+    };
+};
+
+#func {allTrue} {
+    #local value {};
+    #foreach {%0} {value} {
+        #if @isFalse{$value} {
+            #return 0;
+        };
+    };
+
+    #return 1;
+};
+
+#func {allFalse} {
+    #local value {};
+    #foreach {%0} {value} {
+        #if @isTrue{$value} {
+            #return 0;
+        };
+    };
+
+    #return 1;
+};
+
+#func {anyTrue} {
+    #if @allFalse{%0} {
+        #return 0;
+    };
+    #else {
+        #return 1;
+    };
+};
+
+#func {anyFalse} {
+    #if @allTrue{%0} {
+        #return 0;
+    };
+    #else {
+        #return 1;
+    };
+};
+
+#func {if} {
+    #local cond {%1};
+    #local then {%2};
+    #local else {%3};
+
+    #if { $cond } {
+        #return {$then};
+    };
+    #else {
+        #return {$else};
+    };
+};

+ 9 - 1
plugins/lib/xtintin/cmds.tin

@@ -2,7 +2,7 @@
 
 /*
 本文件属于 PaoTin++ 的一部分。
-PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
 */
 
@@ -256,3 +256,11 @@ PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
     #local cmds {%1};
     #send {#$cmds#};
 };
+
+#alias {xtt.Answer} {
+    #delay 0 {
+        #echo {};
+        #buffer end;
+        #send {%1};
+    };
+};

+ 19 - 3
plugins/lib/xtintin/default.tin

@@ -1,3 +1,11 @@
+#nop vim: set filetype=tt:;
+
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
 #nop 字符串默认值;
 #func {default} {
     #local value    {%1};
@@ -10,8 +18,8 @@
     #return {$value};
 };
 
-#nop 数默认值;
-#func {defaultInt} {
+#nop 数默认值;
+#func {defaultNum} {
     #local value    {%1};
     #local default  {%2};
 
@@ -19,6 +27,10 @@
         #return {$default};
     };
 
+    #if { "$value" != "{-|}%+1..d{|\.\d+}" } {
+        #return {$default};
+    };
+
     #if { $value == 0 } {
         #return {$default};
     };
@@ -41,7 +53,7 @@
 
 #nop 变量展开的时候,如果变量不存在会直接展开成 $var 形式的变量名自身,;
 #nop 这种情况下也允许用 default 值代替;
-#func {defaultIntVar} {
+#func {defaultNumVar} {
     #local value    {%1};
     #local default  {%2};
 
@@ -49,6 +61,10 @@
         #return {$default};
     };
 
+    #if { "$value" != "{-|}%+1..d{|\.\d+}" } {
+        #return {$default};
+    };
+
     #if { $value == 0 } {
         #return {$default};
     };

+ 129 - 39
plugins/lib/xtintin/fp.tin

@@ -2,32 +2,34 @@
 
 /*
 本文件属于 PaoTin++ 的一部分。
-PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
 */
 
-#func {filter} {
+#nop 本文件是 xtintin 的一部分,实现了一些 FP 风格函数;
+
+#func {map} {
     #local table {%1};
-    #local cond {%2};
+    #local body {%2};
 
     #local key      {};
     #local value    {};
-    #replace {cond} {KEY} {$$key};
-    #replace {cond} {VALUE} {$$value};
+
+    #replace {body} {KEY}   {\$key};
+    #replace {body} {VALUE} {\$value};
 
     #local newTable {};
     #local key {};
     #foreach {*table[]} {key} {
         #local value {$table[$key]};
-        #line sub var #if { $cond } {
-            #cat newTable {{$key}{$value}};
-        };
+        #line sub {var;functions;escapes} #format value {%s} {$body};
+        #cat newTable {{$key}{$value}};
     };
 
-    #return {$newTable}
+    #return {$newTable};
 };
 
-#func {filterMap} {
+#func {mapIf} {
     #local table {%1};
     #local cond {%2};
     #local body {%3};
@@ -35,69 +37,157 @@ PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
     #local key      {};
     #local value    {};
 
-    #replace {cond} {KEY} {$$key};
-    #replace {cond} {VALUE} {$$value};
-    #replace {body} {KEY} {$$key};
-    #replace {body} {VALUE} {$$value};
+    #replace {cond} {KEY}   {\$key};
+    #replace {cond} {VALUE} {\$value};
+    #replace {body} {KEY}   {\$key};
+    #replace {body} {VALUE} {\$value};
 
     #local newTable {};
     #local key {};
     #foreach {*table[]} {key} {
         #local value {$table[$key]};
-        #line sub var #if { $cond } {
-            #cat newTable {{$key}{$body}};
+        #local c {};
+        #line sub {var;functions;escapes} #format c {%s} {$cond};
+        #if { $c } {
+            #line sub {var;functions;escapes} #format value {%s} {$body};
         };
+        #cat newTable {{$key}{$value}};
     };
 
-    #return {$newTable}
+    #return {$newTable};
 };
 
-#func {mapIf} {
+#func {filter} {
     #local table {%1};
-    #local cond {%2};
-    #local body {%3};
+    #local cond  {%2};
 
     #local key      {};
     #local value    {};
-
-    #replace {cond} {KEY} {$$key};
-    #replace {cond} {VALUE} {$$value};
-    #replace {body} {KEY} {$$key};
-    #replace {body} {VALUE} {$$value};
+    #replace {cond} {KEY}   {\$key};
+    #replace {cond} {VALUE} {\$value};
 
     #local newTable {};
     #local key {};
     #foreach {*table[]} {key} {
         #local value {$table[$key]};
-        #line sub var {
-            #if { $cond } {
-                #cat newTable {{$key}{$body}};
-            };
-            #else {
-                #cat newTable {{$key}{$value}};
-            };
+        #local c {};
+        #line sub {var;functions;escapes} #format c {%s} {$cond};
+        #if { $c } {
+            #cat newTable {{$key}{$value}};
         };
     };
 
-    #return {$newTable}
+    #return {$newTable};
 };
 
-#func {map} {
+#func {filterMap} {
     #local table {%1};
-    #local body {%2};
+    #local cond {%2};
+    #local body {%3};
 
     #local key      {};
     #local value    {};
 
-    #replace {body} {KEY} {$$key};
-    #replace {body} {VALUE} {$$value};
+    #replace {cond} {KEY}   {\$key};
+    #replace {cond} {VALUE} {\$value};
+    #replace {body} {KEY}   {\$key};
+    #replace {body} {VALUE} {\$value};
 
     #local newTable {};
     #local key {};
     #foreach {*table[]} {key} {
         #local value {$table[$key]};
-        #cat newTable {{$key}{$body}};
+        #local c {};
+        #line sub {var;functions;escapes} #format c {%s} {$cond};
+        #if { $c } {
+            #line sub {var;functions;escapes} #format value {%s} {$body};
+            #cat newTable {{$key}{$value}};
+        };
+    };
+
+    #return {$newTable};
+};
+
+#func {transform} {
+    #local strList {%1};
+    #local body {%2};
+
+    #local value    {};
+    #replace {body} {VALUE} {\$value};
+
+    #local newStrList {};
+    #foreach {$strList} {value} {
+        #line sub {var;functions;escapes} #format value {%s} {$body};
+        #cat newStrList {$value;};
+    };
+
+    #replace newStrList {;$} {};
+    #return {$newStrList};
+};
+
+#func {transformIf} {
+    #local strList {%1};
+    #local cond {%2};
+    #local body {%3};
+
+    #replace {cond} {VALUE} {\$value};
+    #replace {body} {VALUE} {\$value};
+
+    #local value    {};
+    #local newStrList {};
+    #foreach {$strList} {value} {
+        #local c {};
+        #line sub {var;functions;escapes} #format c {%s} {$cond};
+        #if { $c } {
+            #line sub {var;functions;escapes} #format value {%s} {$body};
+        };
+        #cat newStrList {$value;};
+    };
+
+    #replace newStrList {;$} {};
+    #return {$newStrList};
+};
+
+#func {select} {
+    #local strList {%1};
+    #local cond {%2};
+
+    #local value    {};
+    #replace {cond} {VALUE} {\$value};
+
+    #local newStrList {};
+    #local value {};
+    #foreach {$strList} {value} {
+        #local c {};
+        #line sub {var;functions;escapes} #format c {%s} {$cond};
+        #if { $c } {
+            #cat newStrList {$value;};
+        };
+    };
+
+    #replace newStrList {;$} {};
+    #return {$newStrList};
+};
+
+#func {selectTransform} {
+    #local strList {%1};
+    #local cond {%2};
+    #local body {%3};
+
+    #replace {cond} {VALUE} {\$value};
+    #replace {body} {VALUE} {\$value};
+
+    #local value    {};
+    #local newStrList {};
+    #foreach {$strList} {value} {
+        #local c {};
+        #line sub {var;functions;escapes} #format c {%s} {$cond};
+        #if { $c } {
+            #line sub {var;functions;escapes} #format value {%s} {$body};
+            #cat newStrList  {$value;};
+        };
     };
 
-    #return {$newTable}
+    #replace newStrList {;$} {};
+    #return {$newStrList};
 };

+ 0 - 237
plugins/lib/xtintin/funcs.tin

@@ -1,237 +0,0 @@
-#nop vim: set filetype=tt:;
-
-/*
-本文件属于 PaoTin++ 的一部分。
-PaoTin++ © 2020~2022 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
-你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
-*/
-
-#nop ############################ 小工具-方向处理 #################################;
-
-#func {reverseCmds} {
-    #local cmds  {%1};
-    #local newCmds {};
-    #foreach {$cmds} {item} {
-        #if { "$newCmds" == "" } {
-            #local newCmds {@reverseDir{$item}};
-        };
-        #else {
-            #format {newCmds} {%s;%s} {@reverseDir{$item}} {$newCmds};
-        };
-    };
-
-    #return {$newCmds};
-};
-
-#func {dirName}     { #return @convertDir{name; %1; %2}; };
-#func {shortDir}    { #return @convertDir{short; %1; %2}; };
-#func {longDir}     { #return @convertDir{long; %1; %2}; };
-#func {reverseDir}  {
-    #if { "%1" == "enter{| .*}" } {
-        #return {out};
-    };
-    #else {
-        #return @convertDir{reverse; %1; %2};
-    };
-};
-
-#var xtt.dir.table {
-    {east}      {{name}{正东}   {short}{e}  {long}{east}        {reverse}{west}     }
-    {west}      {{name}{正西}   {short}{w}  {long}{west}        {reverse}{east}     }
-    {south}     {{name}{正南}   {short}{s}  {long}{south}       {reverse}{north}    }
-    {north}     {{name}{正北}   {short}{n}  {long}{north}       {reverse}{south}    }
-
-    {e}         {{name}{正东}   {short}{e}  {long}{east}        {reverse}{w}        }
-    {w}         {{name}{正西}   {short}{w}  {long}{west}        {reverse}{e}        }
-    {s}         {{name}{正南}   {short}{s}  {long}{south}       {reverse}{n}        }
-    {n}         {{name}{正北}   {short}{n}  {long}{north}       {reverse}{s}        }
-
-    {northeast} {{name}{东北}   {short}{ne} {long}{northeast}   {reverse}{southwest}}
-    {southeast} {{name}{东南}   {short}{se} {long}{southeast}   {reverse}{northwest}}
-    {northwest} {{name}{西北}   {short}{nw} {long}{northwest}   {reverse}{southeast}}
-    {southwest} {{name}{西南}   {short}{sw} {long}{southwest}   {reverse}{northeast}}
-
-    {ne}        {{name}{东北}   {short}{ne} {long}{northeast}   {reverse}{sw}       }
-    {se}        {{name}{东南}   {short}{se} {long}{southeast}   {reverse}{nw}       }
-    {nw}        {{name}{西北}   {short}{nw} {long}{northwest}   {reverse}{se}       }
-    {sw}        {{name}{西南}   {short}{sw} {long}{southwest}   {reverse}{ne}       }
-
-    {up}        {{name}{正上}   {short}{u}  {long}{up}          {reverse}{down}     }
-    {down}      {{name}{正下}   {short}{d}  {long}{down}        {reverse}{up}       }
-    {u}         {{name}{正上}   {short}{u}  {long}{up}          {reverse}{d}        }
-    {d}         {{name}{正下}   {short}{d}  {long}{down}        {reverse}{u}        }
-
-    {eastup}    {{name}{东上}   {short}{eu} {long}{eastup}      {reverse}{westdown} }
-    {westup}    {{name}{西上}   {short}{wu} {long}{westup}      {reverse}{eastdown} }
-    {southup}   {{name}{南上}   {short}{su} {long}{southup}     {reverse}{northdown}}
-    {northup}   {{name}{北上}   {short}{nu} {long}{northup}     {reverse}{southdown}}
-
-    {eu}        {{name}{东上}   {short}{eu} {long}{eastup}      {reverse}{wd}       }
-    {wu}        {{name}{西上}   {short}{wu} {long}{westup}      {reverse}{ed}       }
-    {su}        {{name}{南上}   {short}{su} {long}{southup}     {reverse}{nd}       }
-    {nu}        {{name}{北上}   {short}{nu} {long}{northup}     {reverse}{sd}       }
-
-    {eastdown}  {{name}{东下}   {short}{ed} {long}{eastdown}    {reverse}{westup}   }
-    {westdown}  {{name}{西下}   {short}{wd} {long}{westdown}    {reverse}{eastup}   }
-    {southdown} {{name}{南下}   {short}{sd} {long}{southdown}   {reverse}{northup}  }
-    {northdown} {{name}{北下}   {short}{nd} {long}{northdown}   {reverse}{southup}  }
-
-    {ed}        {{name}{东下}   {short}{ed} {long}{eastdown}    {reverse}{wu}       }
-    {wd}        {{name}{西下}   {short}{wd} {long}{westdown}    {reverse}{eu}       }
-    {sd}        {{name}{南下}   {short}{sd} {long}{southdown}   {reverse}{nu}       }
-    {nd}        {{name}{北下}   {short}{nd} {long}{northdown}   {reverse}{su}       }
-
-    {out}       {{name}{出去}   {short}{out}    {long}{out}     {reverse}{enter}    }
-    {enter}     {{name}{进去}   {short}{enter}  {long}{enter}   {reverse}{out}      }
-};
-
-#func {convertDir} {
-    #local field        {%1};
-    #local dir          {%2};
-    #local restricted   {%2};
-
-    #if { "$dir" == "" } {
-        #return {};
-    };
-
-    #local entry ${xtt.dir.table[$dir]};
-
-    #if { "$restricted" == "true" && "$entry" == "" } {
-        #return {};
-    };
-    #else {
-        #return {$entry[$field]};
-    };
-};
-
-#nop ############################ 小工具-语法增强 #################################;
-
-#func {boolAnd} {
-    #if { "%1" == "true" && "%2" == "true" } {
-        #return {true};
-    };
-
-    #return {false};
-};
-
-#func {reverseList} {
-    #var l {%1};
-
-    #list {l} size len;
-    #list {result} create {};
-
-    #loop $len 1 {idx} {
-        #list {result} add $l[$idx];
-    };
-};
-
-#func {eval}            {#math result {%1}};
-#func {space}           {#var result {@repeat{%1;{ }}}};
-#func {repeat}          {#var result {}; #loop 1 %1 tmp {#var result {${result}%2}}};
-#func {string2list}     {#list result {create} {%1}};
-#func {list2string}     {#var l {%1}; #list l simplify; #return {$l}};
-#func {strListSize}     {#list l create {%1}; #list l size result};
-#func {indexOfStrList}  {#list l create {%1}; #list l find {%2} result};
-#func {indexOf}         {#var l {%1}; #list l find {%2} result};
-#func {trim}            {#format {result} {%p} {%1}};
-#func {trimAll}         {#var result {%1}; #replace {result} { } {}};
-#func {sort}            {#var l {%0}; #var result {}; #foreach {$l} {tmp} {#list result {sort} {$tmp}}; #return {@list2string{{$result}}}};
-#func {sortList}        {#var l {@list2string{{%0}}}; #var result {}; #foreach {$l} {tmp} {#list result {sort} {$tmp}}};
-#func {listSize}        {#var l {%1}; #list l size result};
-#func {listSet}         {#var l {%1}; #loc idx {%2}; #loc data {%3}; #var l @listExtend{{$l};$idx}; #list l set {$idx} {$data}; #return {$l} };
-#func {listExtend}      {#var l {%1}; #loc len {%2}; #loc size {@listSize{{$l}}}; #math len {$len - $size}; #if { $len > 0 } { #loop {1} {$len} {id} { #list l add {{}} } }; #return {$l} };
-#func {len}             {#format result {%L} {%1}};
-#func {toLower}         {#format result {%l} {%1}};
-#func {toUpper}         {#format result {%u} {%1}};
-#func {capital}         {#format result {%n} {%1}};
-#func {replace}         {#var result %1;#replace result {%2} {%3}};
-#func {inList}          {#math result { @indexOf{{%1};{%2}} > 0 }};
-#func {center}          {#format len {%L} {%1}; #math left {(%2 - $len) / 2 + $len}; #math right {%2 - $left}; #format result {%${left}s%${right}s} {%1} {}};
-
-#func {max}             {#var result {%1}; #foreach {%0} {i} {#if { $i > $result} { #var result {$i}}}};
-#func {min}             {#var result {%1}; #foreach {%0} {i} {#if { $i < $result} { #var result {$i}}}};
-
-#func {parseTime} {
-    #local {timeStr} {%1};
-
-    #nop 注意这里用了个小技巧,末尾的空格不要去掉;
-    #replace timeStr {%S小时}   {@c2d{&1}*3600+ };
-    #replace timeStr {%S分}     {@c2d{&1}*60+ };
-    #replace timeStr {%S秒}     {@c2d{&1}};
-
-    #local time {};
-    #math time {$timeStr + 0};
-
-    #return {$time};
-};
-
-#func {c2d} {
-    #local string {%1};
-
-    #local number1  {};
-    #local number2  {0};
-    #local number3  {0};
-
-    #local chr      {};
-
-    #local ch {};
-	#parse {$string} {ch} {
-        #if { "$ch" == "{1|2|3|4|5|6|7|8|9|0|\.}" } {
-            #format number1 {%s%s} {$number1} {$ch};
-            #continue;
-        };
-
-        #switch {"$ch"} {
-            #case {"零"}    { #format number1 {0}   };
-            #case {"一"}    { #format number1 {1}   };
-            #case {"二"}    { #format number1 {2}   };
-            #case {"三"}    { #format number1 {3}   };
-            #case {"四"}    { #format number1 {4}   };
-            #case {"五"}    { #format number1 {5}   };
-            #case {"六"}    { #format number1 {6}   };
-            #case {"七"}    { #format number1 {7}   };
-            #case {"八"}    { #format number1 {8}   };
-            #case {"九"}    { #format number1 {9}   };
-            #case {"十"}    {
-                #if { "$number1" == "" } {
-                    #format number1 {1};
-                };
-                #math number2 {$number2 + $number1 * 10};
-                #format number1 {};
-            };
-            #case {"百"}    {
-                #math number2 {$number2 + $number1 * 100};
-                #format number1 {};
-            };
-            #case {"千"}    {
-                #math number2 {$number2 + $number1 * 1000};
-                #format number1 {};
-            };
-            #case {"万"}    {
-                #math number3 {$number3 + ($number2 + $number1) * 10000};
-                #format number1 {};
-                #format number2 {0};
-            };
-            #case {"亿"}    {
-                #math number3 {($number2 + $number1) * 100000000};
-                #format number1 {};
-                #format number2 {0};
-            };
-        };
-    };
-
-    #if { "$number1" == "" } {
-        #format number1 {0};
-    };
-
-    #local number {};
-    #math number {$number1 + $number2 + $number3};
-    #return $number;
-};
-
-#func {strWidth} {
-    #local str {%1};
-    #replace {str} {<{[gG0-9A-Fa-f]{1,8}}>} {};
-    #replace {str} {{\e\[[0-9;]+m}} {};
-    #return {@len{$str}};
-};

+ 34 - 0
plugins/lib/xtintin/list.tin

@@ -0,0 +1,34 @@
+#nop vim: set filetype=tt:;
+
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
+#func {string2list}     {#list result {create} {%0}};
+#func {list2string}     {#var result {%0}; #list result simplify};
+
+#func {strListSize}     {#list l create {%0}; #list l size result};
+#func {indexOfStrList}  {#list l create {%1}; #list l find {%2} result};
+#func {indexOf}         {#var l {%1}; #list l find {%2} result};
+#func {inList}          {#math result { @indexOf{{%1};{%2}} > 0 }};
+
+#func {sort}            {#var l {%0}; #var l2 {}; #foreach {$l} {tmp} {#list l2 {sort} {$tmp}}; #return {@list2string{$l2}}};
+#func {sortList}        {#var l {@list2string{%0}}; #var result {}; #foreach {$l} {tmp} {#list result {sort} {$tmp}}};
+
+#func {listSet}         {#var l {%1}; #loc idx {%2}; #loc data {%3}; #var l @listExtend{{$l};$idx}; #list l set {$idx} {$data}; #return {$l} };
+#func {listExtend}      {#var l {%1}; #loc len {@eval{@defaultNum{%2;0} - &l[]}}; #if { $len > 0 } { #loop {1} {$len} {id} { #list l add {{}} } }; #return {$l} };
+
+#func {reverseList} {
+    #local list {%0};
+    #var result {};
+
+    #local len {&list[]};
+    #if { $len > 0 } {
+        #local idx {};
+        #loop {$len} {1} {idx} {
+            #list {result} add $list[$idx];
+        };
+    };
+};

+ 178 - 0
plugins/lib/xtintin/number.tin

@@ -0,0 +1,178 @@
+#nop vim: set filetype=tt:;
+
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
+#func {eval}    {#math result {%0}};
+
+#func {random} {
+    #local min {%1};
+    #local max {%2};
+    #local range {@eval{$max - $min + 1}};
+
+    #math result { ( 1 d $range ) + $min - 1 };
+};
+
+#func {int}     {#return @floor{@eval{%0 + 0.5}}};
+#func {floor}   {#format result {%d} {%0}};
+#func {ceil}    {#return @eval{@floor{%0} + 1}};
+
+#func {power}   {#return @eval{%1 ** %2}};
+#func {root}    {#return @eval{%1 // %2}};
+
+#func {abs}     {#if {%0 >= 0} {#return %0} {#math result {- %0}}};
+#func {sign}    {#if {%0 >= 0} {#return 1}  {#return -1}};
+
+#func {max} {
+    #var result {%1};
+    #local elem {};
+    #foreach {%0} {elem} {
+        #if { "$elem" == "" } {
+            #continue;
+        };
+        #if { $elem > $result } {
+            #var result {$elem};
+        };
+    };
+};
+
+#func {min} {
+    #var result {%1};
+    #local elem {};
+    #foreach {%0} {elem} {
+        #if { "$elem" == "" } {
+            #continue;
+        };
+        #if { $elem < $result } {
+            #var result {$elem};
+        };
+    };
+};
+
+#func {sum} {
+    #local sum {0};
+    #local tmp {};
+    #foreach {%0} {tmp} {
+        #math sum {$sum + $tmp};
+    };
+    #return {$sum};
+};
+
+#func {avg} {
+    #var sum {0};
+    #local tmp {};
+    #local count {0};
+    #foreach {%0} {tmp} {
+        #math sum {$sum + $tmp};
+        #math count {$count + 1};
+    };
+
+    #if { $count == 0 } {
+        #return 0;
+    };
+    #else {
+        #return @eval{$sum / $count};
+    };
+};
+
+#func {c2d} {
+    #local string {%0};
+
+    #local number1  {0};    #nop 个位(覆盖);
+    #local number2  {0};    #nop 十百千位(加法);
+    #local number3  {0};    #nop 万位(乘法);
+    #local number4  {0};    #nop 亿位(乘法);
+
+    #local ch {};
+	#parse {$string} {ch} {
+        #if { "$ch" == "{1|2|3|4|5|6|7|8|9|0|\.}" } {
+            #format number1 {%d} {$number1$ch};
+            #continue;
+        };
+
+        #switch {"$ch"} {
+            #case {"零"}    { #local number1 {0}   };
+            #case {"一"}    { #local number1 {1}   };
+            #case {"二"}    { #local number1 {2}   };
+            #case {"三"}    { #local number1 {3}   };
+            #case {"四"}    { #local number1 {4}   };
+            #case {"五"}    { #local number1 {5}   };
+            #case {"六"}    { #local number1 {6}   };
+            #case {"七"}    { #local number1 {7}   };
+            #case {"八"}    { #local number1 {8}   };
+            #case {"九"}    { #local number1 {9}   };
+            #case {"十"}    {
+                #if { $number1 == 0 } {
+                    #format number1 {1};
+                };
+                #math number2 {$number2 + $number1 * 10};
+                #format number1 {0};
+            };
+            #case {"百"}    {
+                #math number2 {$number2 + $number1 * 100};
+                #format number1 {0};
+            };
+            #case {"千"}    {
+                #math number2 {$number2 + $number1 * 1000};
+                #format number1 {0};
+            };
+            #case {"万"}    {
+                #math number3 {($number2 + $number1) * 10000};
+                #format number1 {0};
+                #format number2 {0};
+            };
+            #case {"亿"}    {
+                #math number4 {($number3 + $number2 + $number1) * 100000000};
+                #format number1 {0};
+                #format number2 {0};
+                #format number3 {0};
+            };
+        };
+    };
+
+    #local number {};
+    #math number {$number1 + $number2 + $number3 + $number4};
+    #return $number;
+};
+
+#func {grade} {
+    #local current {@defaultNum{%1;0}};
+    #local default {%2};
+
+    #local args {};
+    #local grade {};
+
+    #list args create {%0};
+    #list args delete {1} {2};
+
+    #list grade create {};
+    #local count {0};
+    #while { $count < &args[] } {
+        #local threshold    {$args[@eval{$count + 1}]};
+        #local value        {$args[@eval{$count + 2}]};
+        #list grade {add} {{
+            {threshold}{$threshold}
+            {value}{$value}
+        }};
+        #math count {$count + 2};
+    };
+
+    #list grade {indexate} {threshold};
+    #list grade {order};
+
+    #local elem {};
+    #local value {$default};
+    #foreach {$grade[%*]} {elem} {
+        #if { $current >= $elem[threshold] } {
+            #local value {$elem[value]};
+        };
+        #else {
+            #break;
+        };
+    };
+
+    #return {$value};
+};

+ 110 - 0
plugins/lib/xtintin/path.tin

@@ -0,0 +1,110 @@
+#nop vim: set filetype=tt:;
+
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
+#func {dirName}     { #return @convertDir{name; %1; %2}; };
+#func {shortDir}    { #return @convertDir{short; %1; %2}; };
+#func {longDir}     { #return @convertDir{long; %1; %2}; };
+
+#func {reverseDir}  {
+    #if { "%1" == "enter{| .*}" } {
+        #return {out};
+    };
+    #else {
+        #return @convertDir{reverse; %1; %2};
+    };
+};
+
+#func {reverseCmds} {
+    #local cmds     {%0};
+    #local newCmds  {};
+
+    #foreach {$cmds} {item} {
+        #if { "$newCmds" == "" } {
+            #local newCmds {@reverseDir{$item}};
+        };
+        #else {
+            #format {newCmds} {%s;%s} {@reverseDir{$item}} {$newCmds};
+        };
+    };
+
+    #return {$newCmds};
+};
+
+#var xtt.dir.table {
+    {east}      {{name}{正东}   {short}{e}  {long}{east}        {reverse}{west}     }
+    {west}      {{name}{正西}   {short}{w}  {long}{west}        {reverse}{east}     }
+    {south}     {{name}{正南}   {short}{s}  {long}{south}       {reverse}{north}    }
+    {north}     {{name}{正北}   {short}{n}  {long}{north}       {reverse}{south}    }
+
+    {e}         {{name}{正东}   {short}{e}  {long}{east}        {reverse}{w}        }
+    {w}         {{name}{正西}   {short}{w}  {long}{west}        {reverse}{e}        }
+    {s}         {{name}{正南}   {short}{s}  {long}{south}       {reverse}{n}        }
+    {n}         {{name}{正北}   {short}{n}  {long}{north}       {reverse}{s}        }
+
+    {northeast} {{name}{东北}   {short}{ne} {long}{northeast}   {reverse}{southwest}}
+    {southeast} {{name}{东南}   {short}{se} {long}{southeast}   {reverse}{northwest}}
+    {northwest} {{name}{西北}   {short}{nw} {long}{northwest}   {reverse}{southeast}}
+    {southwest} {{name}{西南}   {short}{sw} {long}{southwest}   {reverse}{northeast}}
+
+    {ne}        {{name}{东北}   {short}{ne} {long}{northeast}   {reverse}{sw}       }
+    {se}        {{name}{东南}   {short}{se} {long}{southeast}   {reverse}{nw}       }
+    {nw}        {{name}{西北}   {short}{nw} {long}{northwest}   {reverse}{se}       }
+    {sw}        {{name}{西南}   {short}{sw} {long}{southwest}   {reverse}{ne}       }
+
+    {up}        {{name}{正上}   {short}{u}  {long}{up}          {reverse}{down}     }
+    {down}      {{name}{正下}   {short}{d}  {long}{down}        {reverse}{up}       }
+    {u}         {{name}{正上}   {short}{u}  {long}{up}          {reverse}{d}        }
+    {d}         {{name}{正下}   {short}{d}  {long}{down}        {reverse}{u}        }
+
+    {eastup}    {{name}{东上}   {short}{eu} {long}{eastup}      {reverse}{westdown} }
+    {westup}    {{name}{西上}   {short}{wu} {long}{westup}      {reverse}{eastdown} }
+    {southup}   {{name}{南上}   {short}{su} {long}{southup}     {reverse}{northdown}}
+    {northup}   {{name}{北上}   {short}{nu} {long}{northup}     {reverse}{southdown}}
+
+    {eu}        {{name}{东上}   {short}{eu} {long}{eastup}      {reverse}{wd}       }
+    {wu}        {{name}{西上}   {short}{wu} {long}{westup}      {reverse}{ed}       }
+    {su}        {{name}{南上}   {short}{su} {long}{southup}     {reverse}{nd}       }
+    {nu}        {{name}{北上}   {short}{nu} {long}{northup}     {reverse}{sd}       }
+
+    {eastdown}  {{name}{东下}   {short}{ed} {long}{eastdown}    {reverse}{westup}   }
+    {westdown}  {{name}{西下}   {short}{wd} {long}{westdown}    {reverse}{eastup}   }
+    {southdown} {{name}{南下}   {short}{sd} {long}{southdown}   {reverse}{northup}  }
+    {northdown} {{name}{北下}   {short}{nd} {long}{northdown}   {reverse}{southup}  }
+
+    {ed}        {{name}{东下}   {short}{ed} {long}{eastdown}    {reverse}{wu}       }
+    {wd}        {{name}{西下}   {short}{wd} {long}{westdown}    {reverse}{eu}       }
+    {sd}        {{name}{南下}   {short}{sd} {long}{southdown}   {reverse}{nu}       }
+    {nd}        {{name}{北下}   {short}{nd} {long}{northdown}   {reverse}{su}       }
+
+    {out}       {{name}{出去}   {short}{out}    {long}{out}     {reverse}{enter}    }
+    {enter}     {{name}{进去}   {short}{enter}  {long}{enter}   {reverse}{out}      }
+};
+
+#func {convertDir} {
+    #local field        {%1};
+    #local dir          {%2};
+    #local restricted   {%2};
+
+    #if { "$dir" == "" } {
+        #return {};
+    };
+
+    #local entry ${xtt.dir.table[$dir]};
+
+    #if { "$entry" == "" } {
+        #if { @isTrue{$restricted} } {
+            #return {};
+        };
+        #else {
+            #return {$dir};
+        };
+    };
+    #else {
+        #return {$entry[$field]};
+    };
+};

+ 91 - 0
plugins/lib/xtintin/string.tin

@@ -0,0 +1,91 @@
+#nop vim: set filetype=tt:;
+
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
+#func {len}         {#format result {%L} {%0}};
+#func {width}       {#format result {%W} {%0}};
+
+#func {space}       {#var result {@repeat{%0;{ }}}};
+#func {repeat}      {#var result {}; #loop 1 %1 tmp {#cat result {%2}}};
+#func {reverseStr}  {#var result {}; #parse {%1} {tmp} {#var result {$tmp$result}}};
+
+#func {trim}        {#format result {%p} {%0}};
+#func {trimAll}     {#var result {%0}; #replace {result} {%+1..s} {}};
+#func {plain}       {#format result {%P} {%0}};
+
+#func {replace}     {#var result %1; #replace result {%2} {%3}};
+#func {toLower}     {#format result {%l} {%0}};
+#func {toUpper}     {#format result {%u} {%0}};
+#func {capital}     {#format result {%n} {%0}};
+
+#func {char}        {#format result {%X} {%0}; #format result {%x} {$result}};
+#func {codepoint}   {#format result {%A} {%0}};
+#func {hex2char}    {#format result {%x} {%0}};
+#func {char2hex}    {#format result {%A} {%0}; #format result {%X} {$result}};
+
+#func {format}      {#format result {%1} {%2}};
+
+#func {left}        {#local width {%2}; #if {$width<=0} {#return {}} {#format result {%.${width}s} {%1}}};
+#func {right}       {#local width {%2}; #if {$width<=0} {#return {}} {#format result {%.-${width}s} {%1}}};
+#func {substr}      {#return {@left{{@right{{%1}; @eval{@width{%1} - %2}}}; %3}}};
+
+#func {alignLeft}   {#format result {%-%2s} {%1}};
+#func {alignRight}  {#format result {%+%2s} {%1}};
+
+#func {alignCenter}  {
+    #local str  {%1};
+    #local max  {@default{%2;80}};
+
+    #local width {@width{$str}};
+
+    #local left {};
+    #local right {};
+
+    #math left {($max - $width) / 2 + $width};
+    #math right {$max - $left};
+
+    #format result {%+${left}s%${right}s} {%1} {};
+    #return {$result};
+};
+
+#func {colorBar} {
+    #local str {%1};
+
+    #local args {};
+    #list args create {%0};
+    #list args delete {1} {1};
+
+    #local parts {};
+    #list parts create {};
+    #local count {0};
+    #local sum {0};
+    #while { $count < &args[] } {
+        #local color    {$args[@eval{$count + 1}]};
+        #local weight   {@defaultNum{$args[@eval{$count + 2}];0}};
+        #list parts {add} {{
+            {color}{$color}
+            {weight}{$weight}
+        }};
+        #math count {$count + 2};
+        #math sum {$sum + $weight};
+    };
+
+    #local elem {};
+    #local len {@len{$str}};
+    #local leftLen {0};
+    #local leftWeight {0};
+    #local colorStr {};
+    #foreach {$parts[%*]} {elem} {
+        #local elemLen {@eval{($elem[weight] + $leftWeight) * $len / $sum - $leftLen}};
+        #local text {@substr{{$str};$leftLen;$elemLen}};
+        #cat colorStr {$elem[color]$text<099>};
+        #math leftLen {$leftLen + $elemLen};
+        #math leftWeight {$leftWeight + $elem[weight]};
+    };
+
+    #return {$colorStr};
+};

+ 40 - 0
plugins/lib/xtintin/time.tin

@@ -0,0 +1,40 @@
+#nop vim: set filetype=tt:;
+
+/*
+本文件属于 PaoTin++ 的一部分。
+PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
+*/
+
+#func {now} {#format result {%T}};
+
+#func {parseCDuration} {
+    #local {timeStr} {%0};
+
+    #nop 兼容不同的写法;
+    #replace {timeStr} {个} {};
+    #replace {timeStr} {星期} {周};
+    #replace {timeStr} {小时} {时};
+    #replace {timeStr} {分钟} {分};
+
+    #nop 注意这里用了个小技巧,末尾的空格不要去掉;
+    #replace timeStr {%S年}     {@c2d{&1}*31104000+ };
+    #replace timeStr {%S月}     {@c2d{&1}*2592000+ };
+    #replace timeStr {%S周}     {@c2d{&1}*604800+ };
+    #replace timeStr {%S天}     {@c2d{&1}*86400+ };
+    #replace timeStr {%S时}     {@c2d{&1}*3600+ };
+    #replace timeStr {%S分}     {@c2d{&1}*60+ };
+    #replace timeStr {%S秒}     {@c2d{&1}};
+
+    #local time {};
+    #math time {$timeStr + 0};
+
+    #return {$time};
+};
+
+#func {formatTime} {
+    #local time   {@defaultNum{%1;@now{}}};
+    #local format {@default{%2;{%Y-%m-%d %H:%M:%S}}};
+    #format result {%t} {{$format}{$time}};
+    #return {$result};
+};