option.tin 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. #nop vim: set filetype=tt:;
  2. /*
  3. 本文件属于 PaoTin++ 的一部分。
  4. PaoTin++ © 2020~2023 的所有版权均由担子炮(dzp <danzipao@gmail.com>) 享有并保留一切法律权利
  5. 你可以在遵照 GPLv3 协议的基础之上使用、修改及重新分发本程序。
  6. */
  7. #var lib_option[META] {
  8. {NAME} {全局选项管理}
  9. {DESC} {为全局选项提供了一个储存位置,并提供一些实用的 API。}
  10. {AUTHOR} {担子炮}
  11. };
  12. VAR {全局选项字典} gOptions {};
  13. load-lib storage;
  14. event.Define {option/changed} {无参} {$MODULE} {选项已更新。本事件只会唤醒和选项名称相对应的钩子};
  15. #func {lib_option.Init} {
  16. #var gOptions {@storage.GetGlobal{global-options}};
  17. #return {true};
  18. };
  19. ///=== {
  20. ///// 全局选项管理。
  21. /////
  22. ///// 全局选项本质上就是一些变量,这个模块主要是为了提供一些公共 API,和一个统
  23. ///// 一的管理方式,能够把散落在各处的选项集中管理。
  24. /////
  25. // ## option.Define <名称> <数据类型> <中文含义> [<默认值>]
  26. // 定义一个全局选项。选项被定义之后有一些公共 API 可供使用。
  27. // 选项必须经过定义之后才能使用。选项的名称按照大骆驼风格命名。
  28. // 目前仅支持 Bool 型选项。
  29. // };
  30. #alias {option.Define} {
  31. #local option {%1};
  32. #local type {%2};
  33. #local meaning {%3};
  34. #local default {%4};
  35. #if { "$option" == "" || "$type" == "" || "$meaning" == "" } {
  36. xtt.Usage option.Define;
  37. #return;
  38. };
  39. #if { "$gOptions[$option]" != "" } {
  40. #if { "$gOptions[$option][name]" != "$option"
  41. || "$gOptions[$option][type]" != "$type"
  42. || "$gOptions[$option][meaning]" != "$meaning"
  43. } {
  44. errLog 选项「$option」已存在,请检查代码。;
  45. };
  46. #return;
  47. };
  48. #if { ! @option.isValidValue{$type;{$default}} } {
  49. #return;
  50. };
  51. #var gOptions[$option] {
  52. {name} {$option}
  53. {type} {$type}
  54. {meaning} {$meaning}
  55. {value} {$default}
  56. };
  57. storage.SetGlobal {global-options} {$gOptions};
  58. };
  59. ///=== {
  60. // ## option.List
  61. // 列出所有的选项。
  62. // };
  63. #alias {option.List} {
  64. #echo {};
  65. #echo { <128>%-25s%-10s %-30s %+22s} {选项名称} {选项类型} {选项含义} {选项当前值};
  66. #draw Yellow scroll line 1 1 1 100;
  67. #local option {};
  68. #foreach {*gOptions[]} {option} {
  69. #local value {$gOptions[$option][value]};
  70. #if { "$gOptions[$option][type]" == "Time" } {
  71. #if { $value > 0 } {
  72. #format value {%t} {{%Y-%m-%d %H:%M:%S}{$value}};
  73. };
  74. };
  75. #echo { %-25s %-10s %-30s %+22s}
  76. {$gOptions[$option][name]}
  77. {$gOptions[$option][type]}
  78. {$gOptions[$option][meaning]}
  79. {{$value}};
  80. };
  81. #echo {};
  82. };
  83. ///=== {
  84. // #@ option.Get <选项名称>
  85. // 获取选项的当前值。
  86. // };
  87. #func {option.Get} {
  88. #local {option} {%1};
  89. #if { "$option" == "" } {
  90. xtt.Usage option.Get;
  91. #return {};
  92. };
  93. #if { "$gOptions[$option]" == "" } {
  94. errLog 不存在选项「$option」,请先定义后再使用。;
  95. #return {};
  96. };
  97. #return {$gOptions[$option][value]};
  98. };
  99. ///=== {
  100. // #@ option.Set <选项名称> <选项新值>
  101. // 设置选项的当前值,返回之前的旧值。
  102. // };
  103. #func {option.Set} {
  104. #local {option} {%1};
  105. #local {value} {%2};
  106. #if { "$option" == "" } {
  107. xtt.Usage option.Set;
  108. #return {};
  109. };
  110. #local old {$gOptions[$option]};
  111. #if { "$old" == "" } {
  112. errLog 不存在选项「$option」,请先定义后再使用。;
  113. #return {};
  114. };
  115. #if { ! @option.isValidValue{$gOptions[$option][type];{$value}} } {
  116. #return {};
  117. };
  118. #if { "$old[value]" !== "$value" } {
  119. #var {gOptions[$option][value]} {$value};
  120. storage.SetGlobal {global-options} {$gOptions};
  121. event.Emit {option/changed} {opt/$option/%*};
  122. };
  123. #return {$old[value]};
  124. };
  125. ///=== {
  126. // ## option.Set <选项名称> <选项值>
  127. // 设置选项的当前值。
  128. // };
  129. #alias {option.Set} {
  130. #local {option} {%1};
  131. #local {value} {%2};
  132. #local _ {@option.Set{$option;{$value}}};
  133. };
  134. ///=== {
  135. // ## option.Push <选项名称> <选项值>
  136. // 设置选项的当前值,并将旧值压入栈中。配合 option.Pop 可以实现选项值的回退。
  137. // };
  138. #alias {option.Push} {
  139. #local {option} {%1};
  140. #local {value} {%2};
  141. #if { "$option" == "" } {
  142. xtt.Usage option.Push;
  143. #return {};
  144. };
  145. #local old {$gOptions[$option]};
  146. #if { "$old" == "" } {
  147. errLog 不存在选项「$option」,请先定义后再使用。;
  148. #return;
  149. };
  150. #if { ! @option.isValidValue{$gOptions[$option][type];{$value}} } {
  151. #return;
  152. };
  153. #var {gOptions[$option][value]} {$value};
  154. #list gOptions[$option][stack] add {$old[value]};
  155. storage.SetGlobal {global-options} {$gOptions};
  156. event.Emit {option/changed} {opt/$option/%*};
  157. };
  158. ///=== {
  159. // ## option.Pop <选项名称> <选项值>
  160. // 从选项的历史值中按照后进先出的原则弹出一个值,使之成为当前值。配合 option.Push 可以实现选项值的回退。
  161. // };
  162. #alias {option.Pop} {
  163. #local {option} {%1};
  164. #if { "$option" == "" } {
  165. xtt.Usage option.Pop;
  166. #return {};
  167. };
  168. #local old {$gOptions[$option]};
  169. #if { "$old" == "" } {
  170. errLog 不存在选项「$option」,请先定义后再使用。;
  171. #return;
  172. };
  173. #if { &gOptions[$option][stack][] == 0 } {
  174. #return;
  175. };
  176. #var {gOptions[$option][value]} {$old[stack][-1]};
  177. #list gOptions[$option][stack] delete -1;
  178. storage.SetGlobal {global-options} {$gOptions};
  179. event.Emit {option/changed} {opt/$option/%*};
  180. };
  181. ///=== {
  182. // #@ option.IsEnable <选项名称>
  183. // 检查选项是否已被开启。
  184. // };
  185. #func {option.IsEnable} {
  186. #local option {%1};
  187. #if { "$option" == "" } {
  188. xtt.Usage option.IsEnable;
  189. #return {};
  190. };
  191. #if { "$gOptions[$option]" == "" } {
  192. errLog 不存在选项「$option」,请先定义后再使用。;
  193. #return {};
  194. };
  195. #if { "$gOptions[$option][type]" != "Bool" } {
  196. errLog 只有 Bool 型变量才支持这个 API。;
  197. #return {};
  198. };
  199. #local value {@option.Get{$option}};
  200. #return @isTrue{$value};
  201. };
  202. ///=== {
  203. // #@ option.IsDisable <选项名称>
  204. // 检查选项是否已被禁用。
  205. // };
  206. #func {option.IsDisable} {
  207. #local option {%1};
  208. #if { "$option" == "" } {
  209. xtt.Usage option.IsDisable;
  210. #return {};
  211. };
  212. #if { "$gOptions[$option]" == "" } {
  213. errLog 不存在选项「$option」,请先定义后再使用。;
  214. #return {};
  215. };
  216. #if { "$gOptions[$option][type]" != "Bool" } {
  217. errLog 只有 Bool 型变量才支持这个 API。;
  218. #return {};
  219. };
  220. #local value {@option.Get{$option}};
  221. #return @isFalse{$value};
  222. };
  223. ///=== {
  224. // #@ option.Toggle <选项名称>
  225. // 翻转选项的当前值。如果是启用则改为禁用;如果是禁用则改为启用。
  226. // 本函数将返回之前的值。
  227. // };
  228. #func {option.Toggle} {
  229. #local {option} {%1};
  230. #if { "$option" == "" } {
  231. xtt.Usage option.Toggle;
  232. #return {};
  233. };
  234. #if { "$gOptions[$option]" == "" } {
  235. errLog 不存在选项「$option」,请先定义后再使用。;
  236. #return {};
  237. };
  238. #if { "$gOptions[$option][type]" != "Bool" } {
  239. errLog 只有 Bool 型变量才支持这个 API。;
  240. #return {};
  241. };
  242. #local value {@option.Get{$option}};
  243. #if { "$value" == "true" } {
  244. option.Disable $option;
  245. infoLog <169>选项「<139>$gOptions[$option][meaning]($option)<169>」 <119>已禁用。<299>;
  246. };
  247. #elseif { "$value" == "false" } {
  248. option.Enable $option;
  249. infoLog <169>选项「<139>$gOptions[$option][meaning]($option)<169>」 <129>已启用。<299>;
  250. };
  251. #return {$value};
  252. };
  253. ///=== {
  254. // ## option.Toggle <选项名称>
  255. // 翻转选项的当前值。如果是启用则改为禁用;如果是禁用则改为启用。
  256. // };
  257. #alias {option.Toggle} {
  258. #local {option} {%1};
  259. #local _ {@option.Toggle{$option}};
  260. };
  261. ///=== {
  262. // ## option.Enable <选项名称>
  263. // 启用该选项。
  264. // };
  265. #alias {option.Enable} {
  266. #local {option} {%1};
  267. option.Set $option {true};
  268. };
  269. ///=== {
  270. // ## option.Disable <选项名称>
  271. // 禁用该选项。
  272. // };
  273. #alias {option.Disable} {
  274. #local {option} {%1};
  275. option.Set $option {false};
  276. };
  277. #func {@option.isValidValue} {
  278. #local type {%2};
  279. #local value {%3};
  280. #local types {Bool|String|Slist|Number|Time};
  281. #if { "$type" != "{$types}" } {
  282. errLog 不能识别的选项类型: 「$type」,目前仅支持选项类型:{$types};
  283. #return;
  284. };
  285. #if { "$type" == "Bool" && "$value" != "{true|false}" } {
  286. errLog Bool 型的选项值只能是 true 或者 false。;
  287. #return 0;
  288. };
  289. #else {
  290. #return 1;
  291. };
  292. };