narou 3.2.5.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of narou might be problematic. Click here for more details.

Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -5
  3. data/.haml-lint.yml +7 -0
  4. data/.rubocop.yml +23 -5
  5. data/.scss-lint.yml +9 -0
  6. data/ChangeLog.md +86 -0
  7. data/Gemfile.lock +35 -35
  8. data/README.md +80 -64
  9. data/lib/backtracer.rb +2 -2
  10. data/lib/color.rb +5 -1
  11. data/lib/command.rb +7 -2
  12. data/lib/command/alias.rb +3 -5
  13. data/lib/command/backup.rb +3 -5
  14. data/lib/command/browser.rb +3 -5
  15. data/lib/command/clean.rb +5 -1
  16. data/lib/command/console.rb +33 -0
  17. data/lib/command/convert.rb +143 -117
  18. data/lib/command/csv.rb +2 -1
  19. data/lib/command/diff.rb +20 -18
  20. data/lib/command/download.rb +25 -14
  21. data/lib/command/folder.rb +3 -5
  22. data/lib/command/freeze.rb +3 -5
  23. data/lib/command/help.rb +20 -18
  24. data/lib/command/init.rb +4 -3
  25. data/lib/command/inspect.rb +2 -1
  26. data/lib/command/list.rb +10 -8
  27. data/lib/command/list/novel_decorator.rb +2 -1
  28. data/lib/command/log.rb +100 -0
  29. data/lib/command/log/tail.rb +76 -0
  30. data/lib/command/mail.rb +20 -17
  31. data/lib/command/remove.rb +7 -6
  32. data/lib/command/send.rb +23 -20
  33. data/lib/command/setting.rb +74 -40
  34. data/lib/command/tag.rb +16 -15
  35. data/lib/command/trace.rb +2 -2
  36. data/lib/command/update.rb +78 -128
  37. data/lib/command/update/general_lastup_updater.rb +3 -2
  38. data/lib/command/update/hotentry_manager.rb +2 -1
  39. data/lib/command/update/interval.rb +2 -1
  40. data/lib/command/version.rb +2 -1
  41. data/lib/command/web.rb +17 -3
  42. data/lib/commandbase.rb +34 -7
  43. data/lib/commandline.rb +54 -35
  44. data/lib/converterbase.rb +21 -15
  45. data/lib/database.rb +3 -2
  46. data/lib/device.rb +5 -4
  47. data/lib/device/epub.rb +2 -1
  48. data/lib/device/ibooks.rb +2 -1
  49. data/lib/device/ibunko.rb +2 -1
  50. data/lib/device/kindle.rb +2 -1
  51. data/lib/device/kobo.rb +2 -1
  52. data/lib/device/library/cygwin.rb +2 -1
  53. data/lib/device/library/linux.rb +2 -1
  54. data/lib/device/library/mac.rb +2 -1
  55. data/lib/device/library/windows.rb +2 -1
  56. data/lib/device/library/windows/eject.rb +2 -1
  57. data/lib/device/reader.rb +2 -1
  58. data/lib/diffviewer.rb +8 -11
  59. data/lib/downloader.rb +159 -151
  60. data/lib/eventable.rb +2 -1
  61. data/lib/extension.rb +16 -14
  62. data/lib/extensions/jruby.rb +2 -1
  63. data/lib/extensions/monkey_patches.rb +7 -0
  64. data/lib/extensions/monkey_patches/pathname.rb +22 -0
  65. data/lib/extensions/windows.rb +2 -1
  66. data/lib/extensions/windows_write_color.rb +2 -1
  67. data/lib/helper.rb +35 -20
  68. data/lib/html.rb +2 -1
  69. data/lib/illustration.rb +2 -1
  70. data/lib/ini.rb +2 -1
  71. data/lib/input.rb +2 -1
  72. data/lib/inspector.rb +3 -2
  73. data/lib/inventory.rb +3 -3
  74. data/lib/mailer.rb +3 -2
  75. data/lib/mixin/all.rb +8 -0
  76. data/lib/mixin/locker.rb +40 -0
  77. data/lib/mixin/output_error.rb +28 -0
  78. data/lib/narou.rb +69 -51
  79. data/lib/narou/api.rb +2 -4
  80. data/lib/narou_logger.rb +236 -108
  81. data/lib/novelconverter.rb +77 -69
  82. data/lib/novelinfo.rb +4 -2
  83. data/lib/novelsetting.rb +15 -12
  84. data/lib/progressbar.rb +13 -9
  85. data/lib/sitesetting.rb +39 -18
  86. data/lib/template.rb +5 -4
  87. data/lib/version.rb +3 -2
  88. data/lib/web/all.rb +2 -1
  89. data/lib/web/appserver.rb +83 -65
  90. data/lib/web/helper4web.rb +10 -5
  91. data/lib/web/progressbar4web.rb +8 -4
  92. data/lib/web/public/resources/default-style.css +2 -3
  93. data/lib/web/public/resources/narou.library.js +86 -60
  94. data/lib/web/public/resources/narou.queue.js +24 -30
  95. data/lib/web/public/resources/narou.ui.js +22 -3
  96. data/lib/web/public/theme/Cerulean/style.css +5 -5
  97. data/lib/web/public/theme/Darkly/style.css +5 -5
  98. data/lib/web/public/theme/Readable/style.css +5 -5
  99. data/lib/web/public/theme/Slate/style.css +2 -3
  100. data/lib/web/public/theme/Superhero/style.css +2 -3
  101. data/lib/web/public/theme/United/style.css +5 -5
  102. data/lib/web/pushserver.rb +10 -7
  103. data/lib/web/server_helpers.rb +16 -1
  104. data/lib/web/settingmessages.rb +10 -7
  105. data/lib/web/streaminginput.rb +2 -1
  106. data/lib/web/streaminglogger.rb +45 -32
  107. data/lib/web/views/_about.haml +6 -3
  108. data/lib/web/views/_header.haml +2 -3
  109. data/lib/web/views/_move_to_top.haml +2 -0
  110. data/lib/web/views/_queue.haml +7 -0
  111. data/lib/web/views/bookmarklet/insert_button.js.erb +1 -1
  112. data/lib/web/views/index.haml +30 -27
  113. data/lib/web/views/layout.haml +2 -0
  114. data/lib/web/views/novels/setting.haml +3 -4
  115. data/lib/web/views/settings.haml +22 -8
  116. data/lib/web/views/style.scss +54 -3
  117. data/lib/web/views/widget/download.haml +9 -3
  118. data/lib/web/views/widget/drag_and_drop.haml +10 -4
  119. data/lib/web/web_worker.rb +132 -0
  120. data/lib/worker.rb +142 -0
  121. data/narou.gemspec +80 -45
  122. data/narou.rb +6 -4
  123. data/template/novel.txt.erb +1 -0
  124. data/webnovel/kakuyomu.jp.yaml +9 -13
  125. data/webnovel/ncode.syosetu.com.yaml +3 -1
  126. data/webnovel/novel18.syosetu.com.yaml +8 -1
  127. data/webnovel/syosetu.org.yaml +3 -1
  128. data/webnovel/www.akatsuki-novels.com.yaml +4 -2
  129. data/webnovel/www.mai-net.net.yaml +3 -1
  130. metadata +109 -48
  131. data/lib/web/worker.rb +0 -126
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -78,6 +79,7 @@ module Command
78
79
  end
79
80
 
80
81
  def execute(argv)
82
+ disable_logging
81
83
  short_number_option_parse(argv)
82
84
  super
83
85
  @options["number"] ||= 1
@@ -88,7 +90,7 @@ module Command
88
90
  @novel_data = latest
89
91
  else
90
92
  target = argv.shift
91
- @novel_data = Downloader.get_data_by_target(target)
93
+ @novel_data = Downloader.get_data_by_target(target) || {}
92
94
  id = @novel_data["id"]
93
95
  end
94
96
  unless id
@@ -134,13 +136,13 @@ module Command
134
136
 
135
137
  def clean_diff(id)
136
138
  cache_root_dir = Downloader.get_cache_root_dir(id)
137
- print @novel_data["title"] + " の"
139
+ stream_io.print @novel_data["title"] + " の"
138
140
  unless File.exist?(cache_root_dir)
139
- puts "差分はひとつもありません"
141
+ stream_io.puts "差分はひとつもありません"
140
142
  return
141
143
  end
142
144
  FileUtils.remove_entry_secure(cache_root_dir)
143
- puts "差分を削除しました"
145
+ stream_io.puts "差分を削除しました"
144
146
  end
145
147
 
146
148
  def exec_difftool(id)
@@ -148,7 +150,7 @@ module Command
148
150
  diff_cmd = create_difftool_command_string(*temp_paths.map { |temp|
149
151
  path = temp.path
150
152
  if Helper.os_windows?
151
- path.encode!(Encoding::Windows_31J)
153
+ path = path.encode(Encoding::Windows_31J)
152
154
  end
153
155
  %!"#{path}"!
154
156
  })
@@ -160,7 +162,7 @@ module Command
160
162
  ensure
161
163
  temp_paths.map(&:delete)
162
164
  end
163
- puts res[0] unless res[0].empty?
165
+ stream_io.puts res[0] unless res[0].empty?
164
166
  error res[1] unless res[1].empty?
165
167
  end
166
168
 
@@ -195,14 +197,14 @@ module Command
195
197
  cache_dir = list ? list[nth - 1] : nil
196
198
  end
197
199
  unless cache_dir
198
- puts "#{@novel_data["title"]} の差分データがありません"
200
+ stream_io.puts "#{@novel_data["title"]} の差分データがありません"
199
201
  return nil
200
202
  end
201
203
  cache_section_list = Dir.glob("#{cache_dir}/*.yaml").sort_by { |path|
202
204
  File.basename(path, ".yaml").split(" ", 2)[0].to_i
203
205
  }
204
206
  if cache_section_list.length == 0
205
- puts "#{@novel_data["title"]} は最新話のみのアップデートのようです"
207
+ stream_io.puts "#{@novel_data["title"]} は最新話のみのアップデートのようです"
206
208
  return nil
207
209
  end
208
210
  novel_dir = Downloader.get_novel_section_save_dir(Downloader.get_novel_data_dir_by_target(id))
@@ -273,19 +275,19 @@ module Command
273
275
 
274
276
  def display_diff_list(id)
275
277
  list = get_diff_list(id)
276
- print "#{list[:title]} の"
278
+ stream_io.print "#{list[:title]} の"
277
279
  if list[:list].empty?
278
- puts "差分はひとつもありません"
280
+ stream_io.puts "差分はひとつもありません"
279
281
  return
280
282
  end
281
- puts "差分一覧"
283
+ stream_io.puts "差分一覧"
282
284
  list[:list].each do |data|
283
- puts "<bold><yellow>#{data[:version_string]} -#{data[:number]}</yellow></bold>".termcolor
285
+ stream_io.puts "<bold><yellow>#{data[:version_string]} -#{data[:number]}</yellow></bold>".termcolor
284
286
  data[:objects].each do |object|
285
- puts " 第#{object[:index]}部分 #{object[:subtitle]}"
287
+ stream_io.puts " 第#{object[:index]}部分 #{object[:subtitle]}"
286
288
  end
287
289
  if data[:objects].empty?
288
- puts " (最新話のみのアップデート)"
290
+ stream_io.puts " (最新話のみのアップデート)"
289
291
  end
290
292
  end
291
293
  end
@@ -296,7 +298,7 @@ module Command
296
298
  cache_root_dir = Downloader.get_cache_root_dir(id)
297
299
  next unless File.exist?(cache_root_dir)
298
300
  FileUtils.remove_entry_secure(cache_root_dir)
299
- puts "#{data["title"]} の差分を削除しました"
301
+ stream_io.puts "#{data["title"]} の差分を削除しました"
300
302
  end
301
303
  end
302
304
 
@@ -306,8 +308,8 @@ module Command
306
308
  def display_diff_on_oneself(id)
307
309
  require_relative "../diffviewer"
308
310
  temp_paths = create_temp_files(id) or return
309
- puts "#{@novel_data["title"]} の差分を表示します"
310
- DiffViewer.new(*temp_paths).view
311
+ stream_io.puts "#{@novel_data["title"]} の差分を表示します"
312
+ stream_io.puts DiffViewer.new(*temp_paths).result
311
313
  ensure
312
314
  temp_paths.map(&:delete) if temp_paths
313
315
  end
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -11,6 +12,10 @@ module Command
11
12
  class Download < CommandBase
12
13
  SUPPORT_NOVEL_SITES = %w(小説家になろう(小説を読もう) ノクターンノベルズ ムーンライトノベルズ Arcadia ハーメルン 暁 カクヨム)
13
14
 
15
+ def self.oneline_help
16
+ "指定した小説をダウンロードします"
17
+ end
18
+
14
19
  def initialize
15
20
  super("[<target> <target2> ...] [options]")
16
21
  @opt.separator <<-EOS
@@ -138,8 +143,14 @@ module Command
138
143
  mistook_count += 1
139
144
  next
140
145
  end
141
- unless @options["no-convert"]
142
- convert_status = Convert.execute!(download_target)
146
+ if @options["no-convert"]
147
+ Narou.concurrency_call do
148
+ after_process(download_target)
149
+ end
150
+ else
151
+ convert_status = Convert.execute!(download_target) do
152
+ after_process(download_target)
153
+ end
143
154
  if convert_status > 0
144
155
  # 変換に失敗したか、中断された
145
156
  data = Downloader.get_data_by_target(download_target) # 新規はDL後に取得しないとデータが存在しない
@@ -148,26 +159,26 @@ module Command
148
159
  raise Interrupt if convert_status == Narou::EXIT_INTERRUPT
149
160
  end
150
161
  end
151
- if @options["mail"]
152
- Mail.execute!(download_target)
153
- end
154
- if @options["freeze"]
155
- Freeze.execute!(download_target)
156
- elsif @options["remove"]
157
- # --freeze オプションが指定された場合は --remove オプションは無視する
158
- Remove.execute!(download_target, "-y")
159
- end
160
162
  end
161
163
  exit mistook_count if mistook_count > 0
162
164
  rescue Interrupt
163
165
  puts "ダウンロードを中断しました"
166
+ Narou::Worker.cancel if Narou.concurrency_enabled?
164
167
  exit Narou::EXIT_INTERRUPT
165
168
  ensure
166
169
  Database.instance.save_database
167
170
  end
168
171
 
169
- def self.oneline_help
170
- "指定した小説をダウンロードします"
172
+ def after_process(target)
173
+ if @options["mail"]
174
+ Mail.execute!(target, io: $stdout2)
175
+ end
176
+ if @options["freeze"]
177
+ Freeze.execute!(target)
178
+ elsif @options["remove"]
179
+ # --freeze オプションが指定された場合は --remove オプションは無視する
180
+ Remove.execute!(target, "-y")
181
+ end
171
182
  end
172
183
  end
173
184
  end
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -27,10 +28,7 @@ module Command
27
28
 
28
29
  def execute(argv)
29
30
  super
30
- if argv.empty?
31
- puts @opt.help
32
- return
33
- end
31
+ display_help! if argv.empty?
34
32
  tagname_to_ids(argv)
35
33
  argv.each do |target|
36
34
  dir = Downloader.get_novel_data_dir_by_target(target)
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -46,10 +47,7 @@ module Command
46
47
 
47
48
  def execute(argv)
48
49
  super
49
- if argv.empty?
50
- puts @opt.help
51
- return
52
- end
50
+ display_help! if argv.empty?
53
51
  tagname_to_ids(argv)
54
52
  frozen_list = Inventory.load("freeze")
55
53
  argv.each do |target|
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -11,7 +12,8 @@ module Command
11
12
  "このヘルプを表示します"
12
13
  end
13
14
 
14
- def execute(argv)
15
+ def execute(_argv)
16
+ disable_logging
15
17
  if Narou.already_init?
16
18
  display_help
17
19
  else
@@ -20,23 +22,23 @@ module Command
20
22
  end
21
23
 
22
24
  def display_help
23
- puts <<-EOS.termcolor
24
- #{HEADER}
25
+ stream_io.puts(<<~HELP.termcolor)
26
+ #{HEADER}
25
27
 
26
- <bold><green>Usage: narou &lt;command&gt; [arguments...] [options...]
27
- [--no-color] [--multiple] [--time] [--backtrace]</green></bold>
28
+ <bold><green>Usage: narou &lt;command&gt; [arguments...] [options...]
29
+ [--no-color] [--multiple] [--time] [--backtrace]</green></bold>
28
30
 
29
- コマンドの簡単な説明:
30
- EOS
31
+ コマンドの簡単な説明:
32
+ HELP
31
33
  cmd_list = Command.get_list
32
34
  cmd_list.each do |key, command|
33
35
  oneline = command.oneline_help.split("\n")
34
- puts " <bold><green>#{key.ljust(12)}</green></bold> #{oneline.shift}".termcolor
36
+ stream_io.puts " <bold><green>#{key.ljust(12)}</green></bold> #{oneline.shift}".termcolor
35
37
  oneline.each do |h|
36
- puts " " * 16 + h
38
+ stream_io.puts " " * 16 + h
37
39
  end
38
40
  end
39
- puts <<-EOS.termcolor
41
+ stream_io.puts(<<-HELP.termcolor)
40
42
 
41
43
  各コマンドの詳細は narou &lt;command&gt; -h を参照してください。
42
44
  各コマンドは先頭の一文字か二文字でも指定できます。
@@ -47,18 +49,18 @@ module Command
47
49
  --multiple 引数の区切りにスペースの他に","も使えるようにする
48
50
  --time 実行時間表示
49
51
  --backtrace エラー発生時詳細情報を表示
50
- EOS
52
+ HELP
51
53
  end
52
54
 
53
55
  def display_help_first_time
54
- puts <<-EOS.termcolor
55
- #{HEADER}
56
+ stream_io.puts(<<~HELP.termcolor)
57
+ #{HEADER}
56
58
 
57
- <bold><green>Usage: narou init</green></bold>
59
+ <bold><green>Usage: narou init</green></bold>
58
60
 
59
- まだこのフォルダは初期化されていません。
60
- <bold><yellow>narou init</yellow></bold> コマンドを実行して初期化を行いましょう。
61
- EOS
61
+ まだこのフォルダは初期化されていません。
62
+ <bold><yellow>narou init</yellow></bold> コマンドを実行して初期化を行いましょう。
63
+ HELP
62
64
  end
63
65
  end
64
66
  end
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -111,7 +112,7 @@ module Command
111
112
 
112
113
  def rewrite_aozoraepub3_files(aozora_path, line_height)
113
114
  # chuki_tag.txt の書き換え
114
- custom_chuki_tag_path = File.join(Narou.get_preset_dir, "custom_chuki_tag.txt")
115
+ custom_chuki_tag_path = File.join(Narou.preset_dir, "custom_chuki_tag.txt")
115
116
  chuki_tag_path = File.join(aozora_path, "chuki_tag.txt")
116
117
  custom_chuki_tag = File.read(custom_chuki_tag_path, mode: "r:BOM|UTF-8")
117
118
  chuki_tag = File.read(chuki_tag_path, mode: "r:BOM|UTF-8")
@@ -130,7 +131,7 @@ module Command
130
131
  dst = ["AozoraEpub3.ini", "template/OPS/css_custom/vertical_font.css"]
131
132
  puts "(次のファイルをコピーor上書きしました)"
132
133
  src.size.times do |i|
133
- src_full_path = File.join(Narou.get_preset_dir, src[i])
134
+ src_full_path = File.join(Narou.preset_dir, src[i])
134
135
  dst_full_path = File.join(aozora_path, dst[i])
135
136
  Helper.erb_copy(src_full_path, dst_full_path, binding)
136
137
  puts dst_full_path
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -132,8 +133,8 @@ module Command
132
133
  when "nonfrozen"
133
134
  !frozen
134
135
  else
135
- error "不明なフィルターです(#{item})"
136
- warn "filters = #{filter_type_help}"
136
+ stream_io.error "不明なフィルターです(#{item})"
137
+ stream_io.puts "filters = #{filter_type_help}"
137
138
  exit Narou::EXIT_ERROR_CODE
138
139
  end
139
140
  sum + (apply ? 1 : 0)
@@ -203,19 +204,20 @@ module Command
203
204
 
204
205
  def output_lines(took_lines)
205
206
  if STDOUT.tty?
206
- puts header
207
- puts took_lines.values.join("\n").termcolor
207
+ stream_io.puts header
208
+ stream_io.puts took_lines.values.join("\n").termcolor
208
209
  elsif @options["echo"]
209
210
  # pipeにそのまま出力するときはansicolorコードが邪魔なので削除
210
- puts header
211
- puts TermColorLight.strip_tag(took_lines.values.join("\n"))
211
+ stream_io.puts header
212
+ stream_io.puts TermColorLight.strip_tag(took_lines.values.join("\n"))
212
213
  else
213
214
  # pipeに接続するときはIDを渡す
214
- puts took_lines.keys.join(" ")
215
+ stream_io.puts took_lines.keys.join(" ")
215
216
  end
216
217
  end
217
218
 
218
219
  def execute(argv)
220
+ disable_logging
219
221
  super
220
222
  database_values = Database.instance.get_object.values
221
223
  limit =
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
1
+ # frozen_string_literal: true
2
+
2
3
  #
3
4
  # Copyright 2013 whiteleaf. All rights reserved.
4
5
  #
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2013 whiteleaf. All rights reserved.
5
+ #
6
+
7
+ require_relative "log/tail"
8
+
9
+ module Command
10
+ class Log < CommandBase
11
+ NUM = 20
12
+
13
+ def self.oneline_help
14
+ "保存したログを表示します"
15
+ end
16
+
17
+ def initialize
18
+ super("[options] [<path>]")
19
+ @opt.separator <<~HELP
20
+
21
+ ・#{Narou.log_dir} に保存されたログを表示します。
22
+ ・logging 設定が有効な場合のみ、ログは保存されます。
23
+ ・<path> を指定しない場合、最新のログが表示されます。
24
+ ・デフォルトでは末尾#{NUM}行のログを表示します。
25
+
26
+ Examples:
27
+ narou s logging=true # ログの保存を有効にする
28
+
29
+ narou log
30
+ narou log -n 100 # 100行分のログを表示
31
+ narou log -t # tail -f オプションのようにログを流し続ける
32
+
33
+ narou log log/narou.txt # 直接ファイルを指定可能
34
+
35
+ # concurrency 設定(更新・変換同時実行)が有効時は変換ログが別ファイルに
36
+ # 分かれるので、変換ログを表示したい場合は -c オプションを付ける
37
+ # (指定しなかった場合は通常ログの方を表示)
38
+ narou log -c # 変換ログを表示
39
+
40
+ Options:
41
+ HELP
42
+ @opt.on("-n", "--num NUM", Integer, "表示する行数を指定する") do |num|
43
+ @options["num"] = num
44
+ end
45
+ @opt.on("-t", "--tail", "ログを流し続ける") do
46
+ @options["tail"] = true
47
+ end
48
+ @opt.on("-c", "--source-convert", "変換ログを表示する。<path> を直接指定した場合は無視") do
49
+ @options["source-convert"] = true
50
+ end
51
+ end
52
+
53
+ def execute(argv)
54
+ disable_logging
55
+ super
56
+ path = resolve_path(argv.first) || latest_log_path
57
+ unless path
58
+ error "表示できるログファイルが一つも見つかりませんでした"
59
+ exit Narou::EXIT_ERROR_CODE
60
+ end
61
+ stream_io.puts "<cyan>#{path}</cyan>".termcolor
62
+ tail = Tail.new(path, @options["num"] || NUM)
63
+ tail.stream_io = stream_io
64
+ if @options["tail"]
65
+ tail.stream
66
+ else
67
+ tail.display
68
+ end
69
+ rescue Interrupt
70
+ stream_io.puts
71
+ end
72
+
73
+ def latest_log_path
74
+ Narou.log_dir.glob("*").sort_by(&:mtime).reverse.find do |path|
75
+ path_matches_source?(path)
76
+ end
77
+ end
78
+
79
+ def path_matches_source?(path)
80
+ ext = path.extname
81
+ base = path.basename(ext)
82
+ ended_with_convert = base.to_s.end_with?("_convert")
83
+ if @options["source-convert"]
84
+ ended_with_convert
85
+ else
86
+ !ended_with_convert
87
+ end
88
+ end
89
+
90
+ def resolve_path(path)
91
+ return nil if path.blank?
92
+ fullpath = Pathname(path).expand_path
93
+ unless fullpath.exist?
94
+ error "#{path} が存在しません"
95
+ exit Narou::EXIT_ERROR_CODE
96
+ end
97
+ fullpath
98
+ end
99
+ end
100
+ end