Parcourir la source

feat(xtintin): 增加三个新 API: str.SimpleColor/color.Trim/color.Clean

// #@ str.SimpleColor <字符串>
//    仅保留字符串中的颜色代码,去掉其余成分,方便比较颜色。
//    本函数与 str.Color 的区别在于,本函数会简化颜色。
//    所谓简化是指对颜色代码串进行了 color.Trim 和 color.Clean 操作。
//
// #@ color.Trim <颜色代码串>
//    去掉颜色代码串两头的复位代码。
//
// #@ color.Clean <颜色代码串>
//    压缩颜色代码串,只保留经过运算后的效果。
//    NOTE: 注意某些情况下你可能需要先进行 color.Trim 操作。
dzp il y a 1 mois
Parent
commit
10bcf31c55
1 fichiers modifiés avec 133 ajouts et 25 suppressions
  1. 133 25
      plugins/lib/xtintin/raw.tin

+ 133 - 25
plugins/lib/xtintin/raw.tin

@@ -2,7 +2,7 @@
 
 /*
 本文件属于 PaoTin++ 的一部分。
-PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
+PaoTin++ © 2020~2026 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
 */
 
@@ -16,12 +16,25 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 //
 // #@ str.Color <字符串>
 //    仅保留字符串中的颜色代码,去掉其余成分,方便比较颜色。
+//    本函数与 str.SimpleColor 的区别在于,本函数不会简化颜色。
+//
+// #@ str.SimpleColor <字符串>
+//    仅保留字符串中的颜色代码,去掉其余成分,方便比较颜色。
+//    本函数与 str.Color 的区别在于,本函数会简化颜色。
+//    所谓简化是指对颜色代码串进行了 color.Trim 和 color.Clean 操作。
+//
+// #@ color.Trim <颜色代码串>
+//    去掉颜色代码串两头的复位代码。
+//
+// #@ color.Clean <颜色代码串>
+//    压缩颜色代码串,只保留经过运算后的效果。
+//    NOTE: 注意某些情况下你可能需要先进行 color.Trim 操作。
 // };
 
 #func {str.Plain}   {#format result {%P} {%0}};
 
 #func {str.Color} {
-    #local str      {};
+    #local color    {};
     #local state    {START};
     #local ch       {};
 
@@ -31,15 +44,69 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
             #case {"START/%*"}  {#0};
             #case {"ESCAPE/["}  {#local state {INNER}};
             #case {"ESCAPE/%*"} {#local state {OUTER}};
-            #case {"INNER/m"}   {#cat str {;}; #local state {OUTER}};
-            #case {"INNER/%*"}  {#cat str {$ch}};
+            #case {"INNER/m"}   {#cat color {;}; #local state {OUTER}};
+            #case {"INNER/%*"}  {#cat color {$ch}};
             #case {"OUTER/\e"}  {#local state {ESCAPE}};
         };
     };
 
-    #replace {str} {;$} {};
+    #replace {color} {;$} {};
+
+    #return {$color};
+};
+
+#func {str.SimpleColor} {
+    #local color {@str.Color{%0}};
+    #local color {@color.Trim{$color}};
+    #local color {@color.Clean{$color}};
+    #return {$color};
+};
+
+#func {color.Trim} {
+    #local color {%0};
+    #replace color {^{(2;37;0(;|))+}} {};
+    #replace color {^{(0(;|))+}} {};
+    #replace color {{((;|)2;37;0)+}$} {};
+    #replace color {{(0(;|))+}$} {};
+
+    #return {$color};
+};
+
+#func {color.Clean} {
+    #local color {%0};
+
+    #local str {};
+    #line sub escapes #format str {%s} {@raw.ParseFragments{{\e[${color}m}}};
+    #if { &str[color][] == 0 } {
+        #return {};
+    };
+
+    #local color {$str[color]};
+    #local attr {};
+    #local output {};
+
+    #foreach {$color[attrs]} {attr} {
+        #switch {"$attr"} {
+            #case {"bold"}      {#cat output {;1}};
+            #case {"dim"}       {#cat output {;2}};
+            #case {"italic"}    {#cat output {;3}};
+            #case {"underline"} {#cat output {;4}};
+            #case {"blink"}     {#cat output {;5}};
+            #case {"reverse"}   {#cat output {;7}};
+            #case {"f16"}       {#cat output {;$color[fg]}};
+            #case {"b16"}       {#cat output {;$color[bg]}};
+            #case {"F16"}       {#cat output {;$color[fg]}};
+            #case {"B16"}       {#cat output {;$color[bg]}};
+            #case {"f256"}      {#cat output {;38;5;$color[fg]}};
+            #case {"b256"}      {#cat output {;48;5;$color[bg]}};
+            #case {"ftrue"}     {#cat output {;38;2;$color[fg]}};
+            #case {"btrue"}     {#cat output {;48;2;$color[bg]}};
+        };
+    };
+
+    #replace output {^;} {};
 
-    #return {$str};
+    #return {$output};
 };
 
 ///=== {
@@ -118,15 +185,20 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 //          - bg: 背景色,同上
 //          - attrs: 文本样式属性,是一个字符串集合(sset),包含以下可能的值:
 //              - bold
+//              - dim
 //              - italic
 //              - underline
 //              - blink
 //              - reverse
-//              - dim
+//              - f16       表示前景色是 16 色系统
+//              - b16       表示背景色是 16 色系统
+//              - F16       表示前景色是 AIXterm 16 色系统
+//              - B16       表示背景色是 AIXterm 16 色系统
 //              - f256      表示前景色是 256 色系统
 //              - b256      表示背景色是 256 色系统
 //              - ftrue     表示前景色是真彩色
 //              - btrue     表示背景色是真彩色
+//            注意以上属性承诺按照以上顺序出现,但如果未设置该属性则不出现。
 // };
 #func {raw.ParseFragments} {
     #local str      {%1};
@@ -146,7 +218,7 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
 
             #if { "$str[text]" !== "" } {
                 #local fragment[text] {$str[text]};
-                #local fragment[color] {$color};
+                #local fragment[color] {@raw.ParseFragments.buildColor{$color}};
                 #list fragments add {{$fragment}};
                 #local fragment {};
             };
@@ -167,34 +239,36 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
         #list tokens delete 1;
 
         #switch {"$mode/$token"} {
-            #case {"SGR/0"}             {#local color[fg] {0}; #local color[bg] {0}; #local color[attrs] {}};
-            #case {"SGR/1"}             {#local color[attrs] {@sset.Add{{$color[attrs]};bold}}};
-            #case {"SGR/2"}             {#local color[attrs] {@sset.Add{{$color[attrs]};dim}}};
-            #case {"SGR/3"}             {#local color[attrs] {@sset.Add{{$color[attrs]};italic}}};
-            #case {"SGR/4"}             {#local color[attrs] {@sset.Add{{$color[attrs]};underline}}};
-            #case {"SGR/5"}             {#local color[attrs] {@sset.Add{{$color[attrs]};blink}}};
-            #case {"SGR/7"}             {#local color[attrs] {@sset.Add{{$color[attrs]};reverse}}};
-            #case {"SGR/3{[0-7]}"}      {#local color[fg] {$token}};
-            #case {"SGR/4{[0-7]}"}      {#local color[bg] {$token}};
-            #case {"SGR/9{[0-7]}"}      {#local color[fg] {$token}};
-            #case {"SGR/10{[0-7]}"}     {#local color[bg] {$token}};
+            #case {"SGR/0"}             {#local color[fg] {}; #local color[bg] {}; #local color[attrs] {}};
+            #case {"SGR/1"}             {#local color[attrs][bold]      {1}};
+            #case {"SGR/2"}             {#local color[attrs][dim]       {1}};
+            #case {"SGR/3"}             {#local color[attrs][italic]    {1}};
+            #case {"SGR/4"}             {#local color[attrs][underline] {1}};
+            #case {"SGR/5"}             {#local color[attrs][blink]     {1}};
+            #case {"SGR/7"}             {#local color[attrs][reverse]   {1}};
+            #case {"SGR/3{[0-7]}"}      {#local color[fg] {$token}; #local color[attrs][fcolors] {8}};
+            #case {"SGR/4{[0-7]}"}      {#local color[bg] {$token}; #local color[attrs][bcolors] {8}};
+            #case {"SGR/9{[0-7]}"}      {#local color[fg] {$token}; #local color[attrs][fcolors] {16}};
+            #case {"SGR/10{[0-7]}"}     {#local color[bg] {$token}; #local color[attrs][bcolors] {16}};
             #case {"SGR/38"}            {#local mode {SGR38}};
-            #case {"SGR38/2"}           {#local mode {SGR382}};
-            #case {"SGR382/%+1..d"}     {#local mode {SGR}; #local color[fg] {$token}; #local color[attrs] {@sset.Add{{$color[attrs]};f256}}};
-            #case {"SGR38/5"}           {#local mode {SGR385}; #local color[fg] {}; #local color[attrs] {@sset.Add{{$color[attrs]};ftrue}}};
+            #case {"SGR38/2"}           {#local mode {SGR382}; #local color[fg] {}; #local color[attrs][fcolors] {256}};
+            #case {"SGR382/%+1..d"}     {#local mode {SGR}; #local color[fg] {$token}};
+            #case {"SGR38/5"}           {#local mode {SGR385}; #local color[fg] {}; #local color[attrs][fcolors] {true}};
             #case {"SGR385/%+1..d"}     {#local mode {SGR3851}; #local color[fg] {@slist.Append{{$color[fg]};$token}}};
             #case {"SGR3851/%+1..d"}    {#local mode {SGR3852}; #local color[fg] {@slist.Append{{$color[fg]};$token}}};
             #case {"SGR3852/%+1..d"}    {#local mode {SGR};     #local color[fg] {@slist.Append{{$color[fg]};$token}}};
             #case {"SGR/48"}            {#local mode {SGR48}};
-            #case {"SGR48/2"}           {#local mode {SGR482}};
-            #case {"SGR482/%+1..d"}     {#local mode {SGR}; #local color[bg] {$token}; #local color[attrs] {@sset.Add{{$color[attrs]};b256}}};
-            #case {"SGR48/5"}           {#local mode {SGR485}; #local color[bg] {}; #local color[attrs] {@sset.Add{{$color[attrs]};btrue}}};
+            #case {"SGR48/2"}           {#local mode {SGR482}; #local color[bg] {}; #local color[attrs][bcolors] {256}};
+            #case {"SGR482/%+1..d"}     {#local mode {SGR}; #local color[bg] {$token}};
+            #case {"SGR48/5"}           {#local mode {SGR485}; #local color[bg] {}; #local color[attrs][bcolors] {true}};
             #case {"SGR485/%+1..d"}     {#local mode {SGR4851}; #local color[bg] {@slist.Append{{$color[bg]};$token}}};
             #case {"SGR4851/%+1..d"}    {#local mode {SGR4852}; #local color[bg] {@slist.Append{{$color[bg]};$token}}};
             #case {"SGR4852/%+1..d"}    {#local mode {SGR};     #local color[bg] {@slist.Append{{$color[bg]};$token}}};
         };
     };
 
+    #local color {@raw.ParseFragments.buildColor{$color}};
+
     #if { "$str[text]" !== "" } {
         #local fragment[text] {$str[text]};
         #local fragment[color] {$color};
@@ -207,6 +281,40 @@ PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 
     };
 };
 
+#func {raw.ParseFragments.buildColor} {
+    #local color {%0};
+
+    #local attrs {$color[attrs]};
+    #local attr {};
+    #local newAttrs {};
+    #foreach {bold;dim;italic;underline;blink;reverse} {attr} {
+        #if { $attrs[$attr] } {
+            #cat newAttrs {;$attr};
+        };
+    };
+
+    #nop 前景色只能有一个系统,以最后出现的为准。;
+    #switch {"$color[attrs][fcolors]/@slist.Size{$color[fg]}"} {
+        #case {"8/1"}       {#cat newAttrs {;f16}};
+        #case {"16/1"}      {#cat newAttrs {;F16}};
+        #case {"256/1"}     {#cat newAttrs {;f256}};
+        #case {"true/3"}    {#cat newAttrs {;ftrue}};
+    };
+
+    #nop 背景色只能有一个系统,以最后出现的为准。;
+    #switch {"$color[attrs][bcolors]/@slist.Size{$color[bg]}"} {
+        #case {"8/1"}       {#cat newAttrs {;b16}};
+        #case {"16/1"}      {#cat newAttrs {;B16}};
+        #case {"256/1"}     {#cat newAttrs {;b256}};
+        #case {"true/3"}    {#cat newAttrs {;btrue}};
+    };
+
+    #replace newAttrs {^;} {};
+    #local color[attrs] {$newAttrs};
+
+    #return {$color};
+};
+
 #alias {raw.ParseFragments.nextToken} {
     #if { "$str" === "" } {
         #return;