Module: MGit::Output

Defined in:
lib/m-git/output/output.rb

Class Method Summary collapse

Class Method Details

.blue_message(str) ⇒ Object

青色提示信息



180
181
182
# File 'lib/m-git/output/output.rb', line 180

def blue_message(str)
  return "\033[36m#{str}\033[0m"
end

.calculate_table_info(list, head_separator, middle_separator, tail_separator, title: nil, fixed_width: -1)) ⇒ Objtct...

计算表格信息

Parameters:

  • list (Array)

    包含表格中显示内容

  • head_separator (String)

    表格头部分割线

  • middle_separator (String)

    表格中部分割线

  • tail_separator (String)

    表格尾部分割线

  • fixed_width (Number) (defaults to: -1))

    default: -1 可指定表格宽度,若指定宽度大于计算所得最大宽度,则使用该指定宽度

Returns:

  • (Objtct...)

    返回表格最大宽度,表格列数,表格中一个项目显示的最大长度



368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# File 'lib/m-git/output/output.rb', line 368

def calculate_table_info(list, head_separator, middle_separator, tail_separator, title:nil, fixed_width:-1)
  return nil if list.nil? || list.length == 0

  head_tail_padding = head_separator.length + tail_separator.length

  max_meta_display_length_by_ascii = -1
  list.each { |item|
    display_length = string_length_by_ascii(item)
    if max_meta_display_length_by_ascii < display_length
      max_meta_display_length_by_ascii = display_length
    end
  }

  # 终端宽度。
  # -1:减去最后一行"\n"
  screen_width = `tput cols`.to_i - 1
  if screen_width > 0 && screen_width > max_meta_display_length_by_ascii + head_tail_padding
    # 定义:
    # n:列数
    # a:单个item最大长度
    # b:分隔字符长度
    # l:表格宽度减去前后padding的长度
    # 如:| [abc]def | [def]abcd | [zz]asdf |
    # 有:  |<------------ l ------------>|
    #                 |<- a -->|
    # n=3,a=9,b=3(' | '.length == 3),l=31

    # 计算l
    raw_length = screen_width - head_tail_padding

    # 计算列数:n * a + (n - 1) * b = l => n = (l + b) / (a + b)
    column = (raw_length + middle_separator.length) / (max_meta_display_length_by_ascii + middle_separator.length)

    # 如果计算得到的列数小于item个数,那么取item个数为最大列数
    column = list.length if column > list.length

    # 计算一个item的平均长度“al”,由
    # 1. n * a + (n - 1) * b = l
    # 2. al = l / n
    # => al = (n * (a + b) - b) / n
    average_length = (column * (max_meta_display_length_by_ascii + middle_separator.length) - middle_separator.length) / column.to_f

    # 表格最大宽度为:n * al + head_tail_padding
    max_table_width = (column * average_length + head_tail_padding).ceil

    # 如果title最宽,则使用title宽度
    if !title.nil? && title.is_a?(String)
      title_length = string_length_by_ascii(head_separator + title + tail_separator)
      max_table_width = title_length if max_table_width < title_length && title_length < screen_width
    end

    # 如果指定了一个合理的宽度,则使用该宽度
    max_table_width = fixed_width if max_table_width < fixed_width && fixed_width <= screen_width

    return max_table_width, column, max_meta_display_length_by_ascii
  else
    return nil
  end
end

.continue_with_combined_interact_repos?(repos_array, msg, title: nil) ⇒ Boolean

Returns:

  • (Boolean)


114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/m-git/output/output.rb', line 114

def continue_with_combined_interact_repos?(repos_array, msg, title:nil)
  output = generate_table_combination(repos_array, title:title, separator:'|') + "\n"
  output += blue_message("[?] #{msg} Y/n")
  puts output
  MGit::DurationRecorder.pause
  input = nil
  loop do
    input = STDIN.gets.chomp.downcase
    if input == 'y' || input == 'yes' || input == 'n' || input == 'no'
      break
    end
    puts blue_message("[?] 输入不合法,#{msg} Y/n")
  end
  MGit::DurationRecorder.resume
  return input == 'y' || input == 'yes'
end

.continue_with_interact_repos?(repos, msg) ⇒ Boolean

Returns:

  • (Boolean)


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/m-git/output/output.rb', line 97

def continue_with_interact_repos?(repos, msg)
  output = generate_table(repos, separator:'|') + "\n"
  output += blue_message("[?] #{msg} Y/n")
  puts output
  MGit::DurationRecorder.pause
  input = nil
  loop do
    input = STDIN.gets.chomp.downcase
    if input == 'y' || input == 'yes' || input == 'n' || input == 'no'
      break
    end
    puts blue_message("[?] 输入不合法,#{msg} Y/n")
  end
  MGit::DurationRecorder.resume
  return input == 'y' || input == 'yes'
end

.continue_with_user_remind?(msg) ⇒ Boolean

— 交互式输出 —

Returns:

  • (Boolean)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/m-git/output/output.rb', line 82

def continue_with_user_remind?(msg)
  puts blue_message("[?] #{msg} Y/n")
  MGit::DurationRecorder.pause
  input = nil
  loop do
    input = STDIN.gets.chomp.downcase
    if input == 'y' || input == 'yes' || input == 'n' || input == 'no'
      break
    end
    puts blue_message("[?] 输入不合法,#{msg} Y/n")
  end
  MGit::DurationRecorder.resume
  return input == 'y' || input == 'yes'
end

.fail_message(str) ⇒ Object



162
163
164
# File 'lib/m-git/output/output.rb', line 162

def fail_message(str)
  return red_message("[✘] #{str}")
end

.generate_block(list, bottom_summary) ⇒ Object



225
226
227
228
229
230
231
# File 'lib/m-git/output/output.rb', line 225

def generate_block(list, bottom_summary)
  return '' if list.nil? || list.length == 0
  output = generate_table(list, separator:'|') + "\n"
  output += bottom_summary
  MGit::Loger.info(list)
  return output
end

.generate_fail_block(list, bottom_summary) ⇒ Object



213
214
215
216
217
# File 'lib/m-git/output/output.rb', line 213

def generate_fail_block(list, bottom_summary)
  msg = generate_block(list, fail_message(bottom_summary))
  MGit::Loger.info(bottom_summary)
  return msg
end

.generate_fail_combined_block(list_array, bottom_summary, title: nil) ⇒ Object

— 格式化输出生成器 —



200
201
202
203
204
205
# File 'lib/m-git/output/output.rb', line 200

def generate_fail_combined_block(list_array, bottom_summary, title:nil)
  return '' if list_array.nil? || list_array.length == 0
  output = generate_table_combination(list_array, title: title, separator:'|') + "\n"
  output += fail_message(bottom_summary)
  return output
end

.generate_processing_block(list, bottom_summary) ⇒ Object



219
220
221
222
223
# File 'lib/m-git/output/output.rb', line 219

def generate_processing_block(list, bottom_summary)
  msg = generate_block(list, processing_message(bottom_summary))
  MGit::Loger.info(bottom_summary)
  return msg
end

.generate_remind_block(list, bottom_summary) ⇒ Object



207
208
209
210
211
# File 'lib/m-git/output/output.rb', line 207

def generate_remind_block(list, bottom_summary)
  msg = generate_block(list, remind_message(bottom_summary))
  MGit::Loger.info(bottom_summary)
  return msg
end

.generate_table(list, title: nil, separator: '', fixed_width: -1,, hide_footer_line: false) ⇒ String

生成表格

Parameters:

  • list (Array)

    包含表格中显示内容

  • title (String) (defaults to: nil)

    default: nil 表格标题

  • separator (String) (defaults to: '')

    default: ” 表格内部分割线

  • fixed_width (Number) (defaults to: -1,)

    default: -1 可指定表格宽度,若指定宽度大于计算所得最大宽度,则使用该指定宽度

  • hide_footer_line (Boolean) (defaults to: false)

    default: false 隐藏底部分割线

Returns:

  • (String)

    已生成的表格字符串



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'lib/m-git/output/output.rb', line 300

def generate_table(list, title:nil, separator:'', fixed_width:-1, hide_footer_line:false)
  return '' if list.nil? || list.length == 0

  output = ''
  head_separator = "| "
  middle_separator = " #{separator} "
  tail_separator = " |"
  head_tail_padding = head_separator.length + tail_separator.length

  max_table_width, column, max_meta_display_length_by_ascii = calculate_table_info(list, head_separator, middle_separator, tail_separator, title:title, fixed_width:fixed_width)

  if !max_table_width.nil? && !column.nil? && !max_meta_display_length_by_ascii.nil?
    if !title.nil?
      title_length = string_length_by_ascii(title)
      title = head_separator + title + ' ' * secure(max_table_width - title_length - head_tail_padding) + tail_separator

      max_table_width = title_length + head_tail_padding if max_table_width < title_length + head_tail_padding
      output += '-' * max_table_width + "\n"
      output += title + "\n"

      # 处理标题下的分割线
      output += head_separator + '-' * title_length + ' ' * secure(max_table_width - head_tail_padding - title_length) + tail_separator + "\n"
    else
      output += '-' * max_table_width + "\n"
    end

    list.each_slice(column).to_a.each { |row|
      line = head_separator
      row.each_with_index { |item, idx|
        # 最大显示宽度由纯ascii字符个数度量,而输出时中文占2个ascii字符宽度
        # ljust方法以字符做计算,一个汉字会被认为是一个字符,但占了2单位宽度,需要把显示宽度根据汉字个数做压缩,如:
        # 最长显示字符(纯ascii字符):'abcdef1234', 字符长度10,占10个ascii字符显示宽度
        # 需要输出字符串:'[删除]abc',字符长度7,但有2个汉字,占9个ascii字符显示宽度
        # 因此,ljust接受宽度字符个数:10 - 2 = 8
        # 即对于'[删除]abc'这样的字符串,8个字符对应的ascii字符显示宽度('[删除]abc ', 注意8个字符宽度此时有一个空格)和'abcdef1234'显示宽度等长
        line += item.ljust(max_meta_display_length_by_char(item, max_meta_display_length_by_ascii))
        line += middle_separator if idx != row.length - 1
      }
      last_line_space = ' ' * secure(max_table_width - string_length_by_ascii(line) - tail_separator.length)
      line += last_line_space + tail_separator
      output += line + "\n"
    }
    output += '-' * max_table_width if !hide_footer_line
  else
    if list.length > 1
      output = list.join("\n")
    else
      output = list.first + "\n"
    end
  end

  return output
end

.generate_table_combination(list_array, title: nil, separator: '') ⇒ String

生成合成表格(将多个表格融合为一个)

Parameters:

  • list_array (Array<Array>)

    包含表格内容的数组,其中每个元素为数组,表示一张表格内容,list_array内容为:【【title1, list1】,【title2, list2】…】, title<String>为标题,list<Array>为单张表格元素数组,所有内容会被渲染为多张表格然后合并为一张

  • title (String) (defaults to: nil)

    default: nil 表格标题

  • separator (String) (defaults to: '')

    default: ” 表格内元素分割线

Returns:

  • (String)

    生成的合成表格



252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
# File 'lib/m-git/output/output.rb', line 252

def generate_table_combination(list_array, title:nil, separator:'')
  table_width = -1
  head_separator = "| "
  middle_separator = " #{separator} "
  tail_separator = " |"
  head_tail_padding = head_separator.length + tail_separator.length

  list_array.each { |list|
    items = list.last
    max_table_width, _, _ = calculate_table_info(items, head_separator, middle_separator, tail_separator, title:list.first)
    table_width = max_table_width if !max_table_width.nil? && max_table_width > table_width
  }

  output = ''
  if !title.nil? && table_width > 0

    title_length = string_length_by_ascii(title)
    table_width = title_length + head_tail_padding if table_width < title_length + head_tail_padding

    space = secure(table_width - head_tail_padding - title_length) / 2
    head_line = head_separator + ' ' * space +  title
    head_line = head_line + ' ' * secure(table_width - string_length_by_ascii(head_line) - tail_separator.length) + tail_separator + "\n"

    output += '-' * table_width + "\n"
    output += head_line
  end

  list_array.each_with_index { |list, idx|
    sub_title = list.first if !list.first.nil? && list.first != ''
    output += generate_table(list.last, title:sub_title, separator:separator, fixed_width:table_width, hide_footer_line:idx != list_array.length - 1)
  }
  return output
end

.generate_title_block(title, has_separator: true) ⇒ Object



233
234
235
236
237
238
239
240
# File 'lib/m-git/output/output.rb', line 233

def generate_title_block(title, has_separator:true)
  title = "--- #{title} ---"
  separator = ''
  separator = "\n" + '=' * string_length_by_ascii(title) if has_separator
  output = blue_message(title + separator) + "\n"
  output += yield(output)
  return output
end

.green_message(str) ⇒ Object

绿色提示信息



175
176
177
# File 'lib/m-git/output/output.rb', line 175

def green_message(str)
  return "\033[32m#{str}\033[0m"
end

.info_title(str) ⇒ Object



194
195
196
# File 'lib/m-git/output/output.rb', line 194

def info_title(str)
  return "\033[4m#{str}\033[0m"
end

.interact_with_multi_selection_combined_repos(list_array, msg, selection) {|input| ... } ⇒ Object

显示一组复合表格并显示多选项操作

Parameters:

  • list_array (Array<Array>)

    包含表格内容的数组,其中每个元素为数组,表示一张表格内容,list_array内容为:【【title1, list1】,【title2, list2】…】, title<String>为标题,list<Array>为单张表格元素数组,所有内容会被渲染为多张表格然后合并为一张

  • msg (string)

    交互消息

  • selection (Array)

    选型数组,如:【‘a: 跳过并继续’, ‘b: 强制执行’, ‘c: 终止’】

Yields:

  • (input)


139
140
141
142
143
144
145
146
# File 'lib/m-git/output/output.rb', line 139

def interact_with_multi_selection_combined_repos(list_array, msg, selection)
  puts generate_table_combination(list_array, separator:'|')
  puts blue_message("[?] #{msg},请选择操作:\n#{selection.join("\n")}")
  MGit::DurationRecorder.pause
  input = STDIN.gets.chomp
  MGit::DurationRecorder.resume
  yield(input) if block_given?
end

.max_meta_display_length_by_char(str, max_meta_display_length_by_ascii) ⇒ Object

输出时中文占2个字符宽度,根据字符串中的汉字个数重新计算最大显示字符长度(以包括汉字在内的字符作度量)



436
437
438
439
# File 'lib/m-git/output/output.rb', line 436

def max_meta_display_length_by_char(str, max_meta_display_length_by_ascii)
  chinese_chars = str.scan(/\p{Han}/)
  return max_meta_display_length_by_ascii - chinese_chars.length
end

.processing_message(str) ⇒ Object

— 特定消息生成器 —



150
151
152
# File 'lib/m-git/output/output.rb', line 150

def processing_message(str)
  return yellow_message("[~] #{str}")
end

.puts_cancel_messageObject

— 简单输出 —



11
12
13
# File 'lib/m-git/output/output.rb', line 11

def puts_cancel_message
  puts_fail_message("执行取消!")
end

.puts_fail_block(list, bottom_summary) ⇒ Object



56
57
58
# File 'lib/m-git/output/output.rb', line 56

def puts_fail_block(list, bottom_summary)
  puts generate_fail_block(list, bottom_summary)
end

.puts_fail_cmd(cmd) ⇒ Object



23
24
25
# File 'lib/m-git/output/output.rb', line 23

def puts_fail_cmd(cmd)
  puts_fail_message("指令[ mgit #{cmd} ]执行失败!")
end

.puts_fail_combined_block(list_array, bottom_summary, title: nil) ⇒ Object



68
69
70
# File 'lib/m-git/output/output.rb', line 68

def puts_fail_combined_block(list_array, bottom_summary, title:nil)
  puts generate_fail_combined_block(list_array, bottom_summary, title:title)
end

.puts_fail_message(str) ⇒ Object



46
47
48
49
# File 'lib/m-git/output/output.rb', line 46

def puts_fail_message(str)
  MGit::Loger.error(str)
  puts fail_message(str)
end

.puts_in_pager(output) ⇒ Object



72
73
74
75
76
77
78
# File 'lib/m-git/output/output.rb', line 72

def puts_in_pager(output)
  begin
    pager = TTY::Pager.new
    pager.page(output)
  rescue => _
  end
end

.puts_nothing_to_do_cmdObject



27
28
29
# File 'lib/m-git/output/output.rb', line 27

def puts_nothing_to_do_cmd
  puts_remind_message("没有仓库需要执行指令!")
end

.puts_processing_block(list, bottom_summary) ⇒ Object



64
65
66
# File 'lib/m-git/output/output.rb', line 64

def puts_processing_block(list, bottom_summary)
  puts generate_processing_block(list, bottom_summary)
end

.puts_processing_message(str) ⇒ Object



51
52
53
54
# File 'lib/m-git/output/output.rb', line 51

def puts_processing_message(str)
  MGit::Loger.info(str)
  puts processing_message(str)
end

.puts_remind_block(list, bottom_summary) ⇒ Object



60
61
62
# File 'lib/m-git/output/output.rb', line 60

def puts_remind_block(list, bottom_summary)
  puts generate_remind_block(list, bottom_summary)
end

.puts_remind_message(str) ⇒ Object



36
37
38
39
# File 'lib/m-git/output/output.rb', line 36

def puts_remind_message(str)
  MGit::Loger.info(str)
  puts remind_message(str)
end

.puts_start_cmdObject



19
20
21
# File 'lib/m-git/output/output.rb', line 19

def puts_start_cmd
  puts_processing_message("开始执行...")
end

.puts_succeed_cmd(cmd) ⇒ Object



15
16
17
# File 'lib/m-git/output/output.rb', line 15

def puts_succeed_cmd(cmd)
  puts_success_message("指令[ mgit #{cmd} ]执行成功!")
end

.puts_success_message(str) ⇒ Object



31
32
33
34
# File 'lib/m-git/output/output.rb', line 31

def puts_success_message(str)
  MGit::Loger.info(str.strip)
  puts success_message(str)
end

.puts_terminate_message(str, title: nil) ⇒ Object



41
42
43
44
# File 'lib/m-git/output/output.rb', line 41

def puts_terminate_message(str, title:nil)
  MGit::Loger.error("#{title}: #{str}")
  puts terminate_message(str, title:title)
end

.red_message(str) ⇒ Object

紫红色提示信息



185
186
187
# File 'lib/m-git/output/output.rb', line 185

def red_message(str)
  return "\033[31m#{str}\033[0m"
end

.remind_message(str) ⇒ Object



154
155
156
# File 'lib/m-git/output/output.rb', line 154

def remind_message(str)
  return blue_message("[!] #{str}")
end

.secure(num) ⇒ Object

保证数字大于0



442
443
444
# File 'lib/m-git/output/output.rb', line 442

def secure(num)
  return num > 0 ? num : 0
end

.string_length_by_ascii(str) ⇒ Object

输出时中文占2个字符宽度,根据字符串中的汉字个数重新计算字符串长度(以纯ascii字符作度量)



429
430
431
432
433
# File 'lib/m-git/output/output.rb', line 429

def string_length_by_ascii(str)
  chinese_chars = str.scan(/\p{Han}/)
  length = str.length + chinese_chars.length
  return length
end

.success_message(str) ⇒ Object



158
159
160
# File 'lib/m-git/output/output.rb', line 158

def success_message(str)
  return green_message("[✔] #{str}")
end

.terminate_message(str, title: nil) ⇒ Object



166
167
168
169
170
# File 'lib/m-git/output/output.rb', line 166

def terminate_message(str, title:nil)
  header = "执行终止"
  header = title if !title.nil?
  return red_message("[✘✘✘ #{header} ✘✘✘] #{str}")
end

.update_progress(totaltasks, finishtasks) ⇒ Object

— 进度条 —



448
449
450
451
452
453
454
455
456
457
458
# File 'lib/m-git/output/output.rb', line 448

def update_progress(totaltasks, finishtasks)
  totalmark = 30
  progress = totaltasks > 0 ? (finishtasks * 100.0 / totaltasks).round : 100
  progress_str = ''
  pre_num = (totalmark / 100.0 * progress).round
  progress_str += '#' * pre_num
  progress_str += ' ' * (totalmark - pre_num)
  bar = "\r[#{progress_str}] #{progress}%"
  bar += "\n" if progress == 100
  print bar
end

.yellow_message(str) ⇒ Object

黄色提示信息



190
191
192
# File 'lib/m-git/output/output.rb', line 190

def yellow_message(str)
  return "\033[33m#{str}\033[0m"
end