Class: Pindo::TaskSystem::MultiLineTaskDisplay
- Inherits:
-
Object
- Object
- Pindo::TaskSystem::MultiLineTaskDisplay
- Defined in:
- lib/pindo/module/task/output/multi_line_task_display.rb
Overview
单任务多行显示器管理单个任务的多行滚动显示,采用 FIFO 队列机制
Constant Summary collapse
- STATUS_RUNNING =
任务状态枚举
:running- STATUS_SUCCESS =
:success- STATUS_ERROR =
:error- STATUS_PENDING =
:pending
Instance Attribute Summary collapse
-
#lines ⇒ Object
readonly
Returns the value of attribute lines.
-
#status ⇒ Object
readonly
Returns the value of attribute status.
-
#task_id ⇒ Object
readonly
Returns the value of attribute task_id.
-
#task_name ⇒ Object
readonly
Returns the value of attribute task_name.
Instance Method Summary collapse
-
#add_line(message) ⇒ Object
添加新行(滚动) 新行添加到队列尾部,如果超过 max_lines,则移除最旧的行 支持多行消息自动拆分.
-
#initialize(task_id, task_name, max_lines: 5) ⇒ MultiLineTaskDisplay
constructor
初始化显示器.
-
#line_count ⇒ Integer
计算占用的行数.
-
#mark_error(message) ⇒ Object
标记任务失败.
-
#mark_success(message = nil) ⇒ Object
标记任务成功.
-
#render(max_lines: nil, max_width: nil) ⇒ String
渲染为终端字符串.
-
#update_last_line(message) ⇒ Object
更新最后一行(不滚动,用于进度百分比) 为了保证行数计算准确,这里强行将换行符替换为空格.
Constructor Details
#initialize(task_id, task_name, max_lines: 5) ⇒ MultiLineTaskDisplay
初始化显示器
20 21 22 23 24 25 26 27 28 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 20 def initialize(task_id, task_name, max_lines: 5) @task_id = task_id # 防止任务名称中有换行符破坏显示 @task_name = task_name.to_s.gsub("\n", " ") @max_lines = max_lines @status = STATUS_RUNNING @lines = [] # 滚动缓冲区(FIFO 队列) @mutex = Mutex.new end |
Instance Attribute Details
#lines ⇒ Object (readonly)
Returns the value of attribute lines.
8 9 10 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 8 def lines @lines end |
#status ⇒ Object (readonly)
Returns the value of attribute status.
8 9 10 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 8 def status @status end |
#task_id ⇒ Object (readonly)
Returns the value of attribute task_id.
8 9 10 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 8 def task_id @task_id end |
#task_name ⇒ Object (readonly)
Returns the value of attribute task_name.
8 9 10 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 8 def task_name @task_name end |
Instance Method Details
#add_line(message) ⇒ Object
添加新行(滚动)新行添加到队列尾部,如果超过 max_lines,则移除最旧的行支持多行消息自动拆分
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 34 def add_line() @mutex.synchronize do = Time.now.strftime('%H:%M:%S') # 处理包含换行符的消息,确保每一行都独立计数 = .to_s # 如果消息为空,至少添加一行空行(或者忽略,这里选择忽略空消息以保持整洁) return if .empty? = .split("\n") if .empty? # 处理仅包含换行符的情况 = [""] end .each do |msg| line = "#{} #{msg}" @lines << line # 保持最多 max_lines 行(FIFO) @lines.shift if @lines.size > @max_lines end end end |
#line_count ⇒ Integer
计算占用的行数
156 157 158 159 160 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 156 def line_count @mutex.synchronize do 1 + @lines.size # 任务名称行 + 消息行 end end |
#mark_error(message) ⇒ Object
标记任务失败
90 91 92 93 94 95 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 90 def mark_error() @mutex.synchronize do @status = STATUS_ERROR add_line_unsafe("错误: #{}") end end |
#mark_success(message = nil) ⇒ Object
标记任务成功
81 82 83 84 85 86 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 81 def mark_success( = nil) @mutex.synchronize do @status = STATUS_SUCCESS add_line_unsafe() if end end |
#render(max_lines: nil, max_width: nil) ⇒ String
渲染为终端字符串
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 101 def render(max_lines: nil, max_width: nil) @mutex.synchronize do lines_output = [] # 状态图标和颜色 icon = case @status when STATUS_RUNNING then '⣾' when STATUS_SUCCESS then '✔' when STATUS_ERROR then '✖' when STATUS_PENDING then '⊙' else '?' end color_code = case @status when STATUS_SUCCESS then "\e[32m" # 绿色 when STATUS_ERROR then "\e[31m" # 红色 when STATUS_PENDING then "\e[33m" # 黄色 else "\e[34m" # 蓝色(运行中) end # 任务名称行 # 截断任务名称(保留一些空间给图标) task_line = " #{color_code}#{icon} #{@task_name}\e[0m" lines_output << task_line # 消息行(树形结构) display_lines = max_lines ? @lines.last(max_lines) : @lines display_lines.each_with_index do |line, index| prefix = if index == display_lines.size - 1 '└─' # 最后一行 else '├─' # 中间行 end full_line = " #{prefix} #{line}" # 如果指定了最大宽度,进行截断 if max_width && max_width > 0 # 简单截断防止换行 # 注意:这里假设全角字符占2宽度的情况未被完美处理,但对于防止严重错乱已足够 if full_line.length > max_width # 保留最后 3 个字符为 "..." full_line = full_line[0, max_width - 3] + "..." end end lines_output << full_line end lines_output.join("\n") end end |
#update_last_line(message) ⇒ Object
更新最后一行(不滚动,用于进度百分比)为了保证行数计算准确,这里强行将换行符替换为空格
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/pindo/module/task/output/multi_line_task_display.rb', line 63 def update_last_line() @mutex.synchronize do = Time.now.strftime('%H:%M:%S') # 替换换行符,保证只占用一行 = .to_s.gsub("\n", " ") line = "#{} #{}" if @lines.empty? @lines << line else @lines[-1] = line end end end |