Sublime Text 用于自定义 Python 日志格式的语法高亮

huangapple go评论140阅读模式
英文:

Sublime Syntax Highlighting for Custom Python Logging Formatter

问题

I want to highlight my python log outputs with sublime syntax definitions according to my custom python logging formatter. I try below syntax definition but it did not work. I can't see this highlight on my sublime highlight list. Below is my python CustomFormatter class, sublime syntax definitions and example log. Can you give me any solution?

我的目标是使用Sublime的语法定义来突出显示我的Python日志输出,根据我的自定义Python日志格式化程序。我尝试了下面的语法定义,但它没有起作用。我无法在Sublime的高亮列表中看到此突出显示。下面是我的Python CustomFormatter类、Sublime的语法定义和示例日志。你能给我任何解决方案吗?

My syntax definition is:

我的语法定义如下:

  1. %YAML 1.2
  2. ---
  3. # See http://www.sublimetext.com/docs/syntax.html
  4. name: TBLog
  5. file_extensions:
  6. - tblog
  7. scope: source.tblog
  8. contexts:
  9. main:
  10. - match: '^\[.*\].*'
  11. captures:
  12. '0': { name: string.timestamp.tblog }
  13. '1': { name: string.loglevel.tblog }
  14. push: log_message
  15. log_message:
  16. - match: '$'
  17. pop: true
  18. - include: string.quoted.double
  19. - include: string.quoted.single
  20. - include: keyword.control
  21. - include: constant.numeric
  22. - include: string.timestamp
  23. string.timestamp:
  24. - match: '\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]'
  25. scope: string.timestamp.tblog
  26. string.quoted.double:
  27. - match: '"'
  28. scope: punctuation.definition.string.begin.tblog
  29. push:
  30. - meta_scope: string.quoted.double.tblog
  31. - match: '\\.'
  32. scope: constant.character.escape.tblog
  33. - match: '"'
  34. scope: punctuation.definition.string.end.tblog
  35. pop: true
  36. string.quoted.single:
  37. - match: '"'
  38. scope: punctuation.definition.string.begin.tblog
  39. push:
  40. - meta_scope: string.quoted.single.tblog
  41. - match: '\\.'
  42. scope: constant.character.escape.tblog
  43. - match: '"'
  44. scope: punctuation.definition.string.end.tblog
  45. pop: true
  46. keyword.control:
  47. - match: '\b(if|else|for|while)\b'
  48. scope: keyword.control.tblog
  49. constant.numeric:
  50. - match: '\b(-)?[0-9.]+\b'
  51. scope: constant.numeric.tblog
  52. string.loglevel:
  53. - match: '\[(WARNING|ERROR|CRITICAL|DEBUG|INFO)\]'
  54. captures:
  55. '0': { name: string.loglevel.tblog }
  56. scope: meta.loglevel.tblog
  57. push: log_message
  58. meta_scope:
  59. string.loglevel.tblog: 'meta.loglevel.tblog'

My custom python formatter is:

我的自定义Python格式化程序如下:

  1. class ColorFormatter(logging.Formatter):
  2. COLORS = {
  3. 'WARNING': colorama.Fore.YELLOW + colorama.Style.BRIGHT,
  4. 'ERROR': colorama.Fore.RED + colorama.Style.BRIGHT,
  5. 'CRITICAL': colorama.Fore.WHITE + colorama.Style.BRIGHT + colorama.Back.RED,
  6. 'DEBUG': colorama.Fore.BLUE + colorama.Style.BRIGHT,
  7. 'INFO': colorama.Fore.GREEN + colorama.Style.BRIGHT,
  8. 'DEFAULT': colorama.Fore.WHITE,
  9. }
  10. def __init__(self, fmt="[%(asctime)s][%(levelname).1s]%(message)s", datefmt="%Y-%m-%d %H:%M:%S"):
  11. logging.Formatter.__init__(self, fmt, datefmt)
  12. def format(self, record):
  13. color = self.COLORS.get(record.levelname, self.COLORS['DEFAULT'])
  14. message = logging.Formatter.format(self, record)
  15. return f"{color}{message}\033[0m"

Example log is:

示例日志如下:

  1. [2023-02-23 22:58:25,226][I]TC] Initializing the bot!
  2. [2023-02-23 22:58:25,241][D]EX] Creating exchange client.
  3. [2023-02-23 22:58:25,678][D]EX] Exchange client has been created!
  4. [2023-02-23 22:58:25,709][I]TC] Preparing bot to start trading!
  5. [2023-02-23 22:58:25,725][D]TC] Variables has been reset!
  6. [2023-02-23 22:58:26,023][D]TC] Server time has been updated! [ST (ms): 1677182307137]
  7. [2023-02-23 22:58:26,038][D]TC] Time difference has been updated! [TD (ms): 1114]
  8. [2023-02-23 22:58:26,337][D]TC] Account order asset balance has been updated! [B: 64.94 BUSD]
  9. [2023-02-23 22:58:26,353][D]TC] Buy order size has been updated! [BOS: 64 BUSD]
  10. [2023-02-23 22:58:26,385][I]TC] Scanning for potential entry opportunities!
英文:

I want to highlight my python log outputs with sublime syntax definitions according to my custom python logging formatter. I try below syntax definition but it did not work. I can't see this highlight on my sublime highlight list. Below is my python CustomFormatter class, sublime syntax definitions and example log. Can you give me any solution?

My syntax definition is:

  1. %YAML 1.2
  2. ---
  3. # See http://www.sublimetext.com/docs/syntax.html
  4. name: TBLog
  5. file_extensions:
  6. - tblog
  7. scope: source.tblog
  8. contexts:
  9. main:
  10. - match: '^\[.*\].*'
  11. captures:
  12. '0': { name: string.timestamp.tblog }
  13. '1': { name: string.loglevel.tblog }
  14. push: log_message
  15. log_message:
  16. - match: '$'
  17. pop: true
  18. - include: string.quoted.double
  19. - include: string.quoted.single
  20. - include: keyword.control
  21. - include: constant.numeric
  22. - include: string.timestamp
  23. string.timestamp:
  24. - match: '\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]'
  25. scope: string.timestamp.tblog
  26. string.quoted.double:
  27. - match: '"'
  28. scope: punctuation.definition.string.begin.tblog
  29. push:
  30. - meta_scope: string.quoted.double.tblog
  31. - match: '\\.'
  32. scope: constant.character.escape.tblog
  33. - match: '"'
  34. scope: punctuation.definition.string.end.tblog
  35. pop: true
  36. string.quoted.single:
  37. - match: "'"
  38. scope: punctuation.definition.string.begin.tblog
  39. push:
  40. - meta_scope: string.quoted.single.tblog
  41. - match: '\\.'
  42. scope: constant.character.escape.tblog
  43. - match: "'"
  44. scope: punctuation.definition.string.end.tblog
  45. pop: true
  46. keyword.control:
  47. - match: '\b(if|else|for|while)\b'
  48. scope: keyword.control.tblog
  49. constant.numeric:
  50. - match: '\b(-)?[0-9.]+\b'
  51. scope: constant.numeric.tblog
  52. string.loglevel:
  53. - match: '\[(WARNING|ERROR|CRITICAL|DEBUG|INFO)\]'
  54. captures:
  55. '0': { name: string.loglevel.tblog }
  56. scope: meta.loglevel.tblog
  57. push: log_message
  58. meta_scope:
  59. string.loglevel.tblog: 'meta.loglevel.tblog'

My custom python formatter is:

  1. class ColorFormatter(logging.Formatter):
  2. COLORS = {
  3. 'WARNING': colorama.Fore.YELLOW + colorama.Style.BRIGHT,
  4. 'ERROR': colorama.Fore.RED + colorama.Style.BRIGHT,
  5. 'CRITICAL': colorama.Fore.WHITE + colorama.Style.BRIGHT + colorama.Back.RED,
  6. 'DEBUG': colorama.Fore.BLUE + colorama.Style.BRIGHT,
  7. 'INFO': colorama.Fore.GREEN + colorama.Style.BRIGHT,
  8. 'DEFAULT': colorama.Fore.WHITE,
  9. }
  10. def __init__(self, fmt="[%(asctime)s][%(levelname).1s]%(message)s", datefmt="%Y-%m-%d %H:%M:%S"):
  11. logging.Formatter.__init__(self, fmt, datefmt)
  12. def format(self, record):
  13. color = self.COLORS.get(record.levelname, self.COLORS['DEFAULT'])
  14. message = logging.Formatter.format(self, record)
  15. return f"{color}{message}\033[0m"

Example log is:

  1. [2023-02-23 22:58:25,226][I]TC] Initializing the bot!
  2. [2023-02-23 22:58:25,241][D]EX] Creating exchange client.
  3. [2023-02-23 22:58:25,678][D]EX] Exchange client has been created!
  4. [2023-02-23 22:58:25,709][I]TC] Preparing bot to start trading!
  5. [2023-02-23 22:58:25,725][D]TC] Variables has been reset!
  6. [2023-02-23 22:58:26,023][D]TC] Server time has been updated! [ST (ms): 1677182307137]
  7. [2023-02-23 22:58:26,038][D]TC] Time difference has been updated! [TD (ms): 1114]
  8. [2023-02-23 22:58:26,337][D]TC] Account order asset balance has been updated! [B: 64.94 BUSD]
  9. [2023-02-23 22:58:26,353][D]TC] Buy order size has been updated! [BOS: 64 BUSD]
  10. [2023-02-23 22:58:26,385][I]TC] Scanning for potential entry opportunities!

答案1

得分: 1

不要回答我要翻译的问题。以下是要翻译的内容:

如果你打开Sublime Text控制台(视图菜单 -> 显示控制台),当你保存你的sublime-syntax文件时,你会看到一个错误消息:

> error parsing lexer: Packages/User/tblog.sublime-syntax: patterns must be a vector at line 67 column 5

第67行是在你的meta_scope上下文下面的那一行。

移除那个上下文,因为它没有被任何地方引用,会得到以下错误:

> error parsing lexer: Packages/User/tblog.sublime-syntax: capture scope must be a string at line 10 column 7

如果你查看文档中的示例捕获,你会看到它说明了你不应该在捕获组数字上使用字符串引号,它期望一个普通字符串而不是一个包含name:的映射。

修复了所有这些问题之后,它仍然不会像你期望的那样高亮显示,因为在main上下文中你在第一个匹配模式的末尾有一个.*。移除它会得到以下内容:

  1. %YAML 1.2
  2. ---
  3. # 详见http://www.sublimetext.com/docs/syntax.html
  4. name: TBLog
  5. file_extensions:
  6. - tblog
  7. scope: source.tblog
  8. contexts:
  9. main:
  10. - match: '^\[.*\]'
  11. captures:
  12. 0: string.timestamp.tblog
  13. 1: string.loglevel.tblog
  14. push: log_message
  15. log_message:
  16. - match: '$'
  17. pop: true
  18. - include: string.quoted.double
  19. - include: string.quoted.single
  20. - include: keyword.control
  21. - include: constant.numeric
  22. - include: string.timestamp
  23. string.timestamp:
  24. - match: '\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]'
  25. scope: string.timestamp.tblog
  26. string.quoted.double:
  27. - match: '"'
  28. scope: punctuation.definition.string.begin.tblog
  29. push:
  30. - meta_scope: string.quoted.double.tblog
  31. - match: '\\.'
  32. scope: constant.character.escape.tblog
  33. - match: '"'
  34. scope: punctuation.definition.string.end.tblog
  35. pop: true
  36. string.quoted.single:
  37. - match: "'"
  38. scope: punctuation.definition.string.begin.tblog
  39. push:
  40. - meta_scope: string.quoted.single.tblog
  41. - match: '\\.'
  42. scope: constant.character.escape.tblog
  43. - match: "'"
  44. scope: punctuation.definition.string.end.tblog
  45. pop: true
  46. keyword.control:
  47. - match: '\b(if|else|for|while)\b'
  48. scope: keyword.control.tblog
  49. constant.numeric:
  50. - match: '\b(-)?[0-9.]+\b'
  51. scope: constant.numeric.tblog
  52. string.loglevel:
  53. - match: '\[(WARNING|ERROR|CRITICAL|DEBUG|INFO)\]'
  54. captures:
  55. '0': string.loglevel.tblog
  56. scope: meta.loglevel.tblog
  57. push: log_message

然后在启用了TBLog语法的情况下,你的文本在Sublime Text中会看起来像这样:Sublime Text 用于自定义 Python 日志格式的语法高亮

英文:

If you open the Sublime Text console (View menu -> Show Console), you will see an error when you save your sublime-syntax file:

> error parsing lexer: Packages/User/tblog.sublime-syntax: patterns must be a vector at line 67 column 5

Line 67 is the line under your meta_scope context.

Removing that context, as it isn't referenced anywhere, gives us:

> error parsing lexer: Packages/User/tblog.sublime-syntax: capture scope must be a string at line 10 column 7

If you look at the example captures in the documentation, you'll see how you shouldn't string quote the capture group numbers and it expects a plain string instead of a map with a name:.

After fixing all that, it still won't highlight the way you might expect because of the .* you have at the end of your first match pattern in the main context. Removing that gives:

  1. %YAML 1.2
  2. ---
  3. # See http://www.sublimetext.com/docs/syntax.html
  4. name: TBLog
  5. file_extensions:
  6. - tblog
  7. scope: source.tblog
  8. contexts:
  9. main:
  10. - match: '^\[.*\]'
  11. captures:
  12. 0: string.timestamp.tblog
  13. 1: string.loglevel.tblog
  14. push: log_message
  15. log_message:
  16. - match: '$'
  17. pop: true
  18. - include: string.quoted.double
  19. - include: string.quoted.single
  20. - include: keyword.control
  21. - include: constant.numeric
  22. - include: string.timestamp
  23. string.timestamp:
  24. - match: '\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\]'
  25. scope: string.timestamp.tblog
  26. string.quoted.double:
  27. - match: '"'
  28. scope: punctuation.definition.string.begin.tblog
  29. push:
  30. - meta_scope: string.quoted.double.tblog
  31. - match: '\\.'
  32. scope: constant.character.escape.tblog
  33. - match: '"'
  34. scope: punctuation.definition.string.end.tblog
  35. pop: true
  36. string.quoted.single:
  37. - match: "'"
  38. scope: punctuation.definition.string.begin.tblog
  39. push:
  40. - meta_scope: string.quoted.single.tblog
  41. - match: '\\.'
  42. scope: constant.character.escape.tblog
  43. - match: "'"
  44. scope: punctuation.definition.string.end.tblog
  45. pop: true
  46. keyword.control:
  47. - match: '\b(if|else|for|while)\b'
  48. scope: keyword.control.tblog
  49. constant.numeric:
  50. - match: '\b(-)?[0-9.]+\b'
  51. scope: constant.numeric.tblog
  52. string.loglevel:
  53. - match: '\[(WARNING|ERROR|CRITICAL|DEBUG|INFO)\]'
  54. captures:
  55. '0': string.loglevel.tblog
  56. scope: meta.loglevel.tblog
  57. push: log_message

and then your text looks like this in ST with your TBLog syntax enabled:
Sublime Text 用于自定义 Python 日志格式的语法高亮

答案2

得分: 0

I used below YAML syntax code.

And below tmTheme.xml for colors.

And below is how its look like.

https://i.stack.imgur.com/T8iL7.jpg

英文:

I used below YAML syntax code.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

  1. %YAML 1.2
  2. ---
  3. # See http://www.sublimetext.com/docs/syntax.html
  4. name: TBLog
  5. file_extensions:
  6. - tblog
  7. scope: tb
  8. contexts:
  9. log_line:
  10. # data
  11. - match: &#39;\[([^\[\]]+)\]&#39;
  12. scope: tb.data
  13. push: log_line
  14. - match: &#39;$&#39;
  15. pop: true
  16. main:
  17. # debug
  18. - match: &#39;\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]\[D\]&#39;
  19. scope: tb.debug
  20. push: log_line
  21. # info
  22. - match: &#39;\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]\[I\]&#39;
  23. scope: tb.info
  24. push: log_line
  25. # warning
  26. - match: &#39;\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]\[W\]&#39;
  27. scope: tb.warning
  28. push: log_line
  29. # error
  30. - match: &#39;\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]\[E\]&#39;
  31. scope: tb.error
  32. push: log_line
  33. # critical
  34. - match: &#39;\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]\[C\]&#39;
  35. scope: tb.critical
  36. push: log_line
  37. # datetime
  38. - match: &#39;\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]&#39;
  39. scope: tb.datetime
  40. push:
  41. - match: &#39;\[D\]&#39;
  42. scope: tb.debug
  43. pop: true
  44. - match: &#39;\[I\]&#39;
  45. scope: tb.info
  46. pop: true
  47. - match: &#39;\[W\]&#39;
  48. scope: tb.warning
  49. pop: true
  50. - match: &#39;\[E\]&#39;
  51. scope: tb.error
  52. pop: true
  53. - match: &#39;\[C\]&#39;
  54. scope: tb.critical
  55. pop: true

<!-- end snippet -->

And below tmTheme.xml for colors.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-html -->

  1. &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
  2. &lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
  3. &lt;plist version=&quot;1.0&quot;&gt;
  4. &lt;dict&gt;
  5. &lt;key&gt;name&lt;/key&gt;
  6. &lt;string&gt;TBLog&lt;/string&gt;
  7. &lt;key&gt;settings&lt;/key&gt;
  8. &lt;array&gt;
  9. &lt;dict&gt;
  10. &lt;key&gt;settings&lt;/key&gt;
  11. &lt;dict&gt;
  12. &lt;key&gt;background&lt;/key&gt;
  13. &lt;string&gt;#272822&lt;/string&gt;
  14. &lt;key&gt;caret&lt;/key&gt;
  15. &lt;string&gt;#F8F8F0&lt;/string&gt;
  16. &lt;key&gt;foreground&lt;/key&gt;
  17. &lt;string&gt;#F8F8F2&lt;/string&gt;
  18. &lt;key&gt;invisibles&lt;/key&gt;
  19. &lt;string&gt;#5E5E5E&lt;/string&gt;
  20. &lt;key&gt;line_highlight&lt;/key&gt;
  21. &lt;string&gt;#3E3D32&lt;/string&gt;
  22. &lt;key&gt;selection&lt;/key&gt;
  23. &lt;string&gt;#49483E&lt;/string&gt;
  24. &lt;key&gt;findHighlightForeground&lt;/key&gt;
  25. &lt;string&gt;#000000&lt;/string&gt;
  26. &lt;key&gt;selectionBorder&lt;/key&gt;
  27. &lt;string&gt;#222218&lt;/string&gt;
  28. &lt;key&gt;activeGuide&lt;/key&gt;
  29. &lt;string&gt;#9D550FB0&lt;/string&gt;
  30. &lt;key&gt;bracketsForeground&lt;/key&gt;
  31. &lt;string&gt;#F8F8F2A5&lt;/string&gt;
  32. &lt;key&gt;bracketsOptions&lt;/key&gt;
  33. &lt;string&gt;underline&lt;/string&gt;
  34. &lt;key&gt;bracketsContentsForeground&lt;/key&gt;
  35. &lt;string&gt;#F8F8F2A5&lt;/string&gt;
  36. &lt;key&gt;bracketsContentsOptions&lt;/key&gt;
  37. &lt;string&gt;underline&lt;/string&gt;
  38. &lt;key&gt;tagsOptions&lt;/key&gt;
  39. &lt;string&gt;stippled_underline&lt;/string&gt;
  40. &lt;/dict&gt;
  41. &lt;/dict&gt;
  42. &lt;dict&gt;
  43. &lt;key&gt;name&lt;/key&gt;
  44. &lt;string&gt;Datetime&lt;/string&gt;
  45. &lt;key&gt;scope&lt;/key&gt;
  46. &lt;string&gt;tb.datetime&lt;/string&gt;
  47. &lt;key&gt;settings&lt;/key&gt;
  48. &lt;dict&gt;
  49. &lt;key&gt;foreground&lt;/key&gt;
  50. &lt;string&gt;#00B764&lt;/string&gt;
  51. &lt;/dict&gt;
  52. &lt;/dict&gt;
  53. &lt;dict&gt;
  54. &lt;key&gt;name&lt;/key&gt;
  55. &lt;string&gt;Data&lt;/string&gt;
  56. &lt;key&gt;scope&lt;/key&gt;
  57. &lt;string&gt;tb.data&lt;/string&gt;
  58. &lt;key&gt;settings&lt;/key&gt;
  59. &lt;dict&gt;
  60. &lt;key&gt;foreground&lt;/key&gt;
  61. &lt;string&gt;#FFA500&lt;/string&gt;
  62. &lt;/dict&gt;
  63. &lt;/dict&gt;
  64. &lt;dict&gt;
  65. &lt;key&gt;name&lt;/key&gt;
  66. &lt;string&gt;Debug&lt;/string&gt;
  67. &lt;key&gt;scope&lt;/key&gt;
  68. &lt;string&gt;tb.debug&lt;/string&gt;
  69. &lt;key&gt;settings&lt;/key&gt;
  70. &lt;dict&gt;
  71. &lt;key&gt;foreground&lt;/key&gt;
  72. &lt;string&gt;#16ACBA&lt;/string&gt;
  73. &lt;/dict&gt;
  74. &lt;/dict&gt;
  75. &lt;dict&gt;
  76. &lt;key&gt;name&lt;/key&gt;
  77. &lt;string&gt;Info&lt;/string&gt;
  78. &lt;key&gt;scope&lt;/key&gt;
  79. &lt;string&gt;tb.info&lt;/string&gt;
  80. &lt;key&gt;settings&lt;/key&gt;
  81. &lt;dict&gt;
  82. &lt;key&gt;foreground&lt;/key&gt;
  83. &lt;string&gt;#00B764&lt;/string&gt;
  84. &lt;/dict&gt;
  85. &lt;/dict&gt;
  86. &lt;dict&gt;
  87. &lt;key&gt;name&lt;/key&gt;
  88. &lt;string&gt;Warning&lt;/string&gt;
  89. &lt;key&gt;scope&lt;/key&gt;
  90. &lt;string&gt;tb.warning&lt;/string&gt;
  91. &lt;key&gt;settings&lt;/key&gt;
  92. &lt;dict&gt;
  93. &lt;key&gt;foreground&lt;/key&gt;
  94. &lt;string&gt;#EDD436&lt;/string&gt;
  95. &lt;/dict&gt;
  96. &lt;/dict&gt;
  97. &lt;dict&gt;
  98. &lt;key&gt;name&lt;/key&gt;
  99. &lt;string&gt;Error&lt;/string&gt;
  100. &lt;key&gt;scope&lt;/key&gt;
  101. &lt;string&gt;tb.error&lt;/string&gt;
  102. &lt;key&gt;settings&lt;/key&gt;
  103. &lt;dict&gt;
  104. &lt;key&gt;background&lt;/key&gt;
  105. &lt;string&gt;#FF0000&lt;/string&gt;
  106. &lt;key&gt;foreground&lt;/key&gt;
  107. &lt;string&gt;#FFFFFF&lt;/string&gt;
  108. &lt;/dict&gt;
  109. &lt;/dict&gt;
  110. &lt;dict&gt;
  111. &lt;key&gt;name&lt;/key&gt;
  112. &lt;string&gt;Critical&lt;/string&gt;
  113. &lt;key&gt;scope&lt;/key&gt;
  114. &lt;string&gt;tb.critical&lt;/string&gt;
  115. &lt;key&gt;settings&lt;/key&gt;
  116. &lt;dict&gt;
  117. &lt;key&gt;background&lt;/key&gt;
  118. &lt;string&gt;#FF0000&lt;/string&gt;
  119. &lt;key&gt;foreground&lt;/key&gt;
  120. &lt;string&gt;#FFFFFF&lt;/string&gt;
  121. &lt;/dict&gt;
  122. &lt;/dict&gt;
  123. &lt;/array&gt;
  124. &lt;/dict&gt;
  125. &lt;/plist&gt;

<!-- end snippet -->

And below is how its look like.

https://i.stack.imgur.com/T8iL7.jpg

huangapple
  • 本文由 发表于 2023年2月24日 05:06:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75550334.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定