doing 2.1.40 → 2.1.41

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/CHANGELOG.md +22 -0
  4. data/Gemfile.lock +1 -1
  5. data/Rakefile +4 -4
  6. data/bin/commands/changes.rb +1 -1
  7. data/bin/commands/tag_dir.rb +49 -15
  8. data/{Dockerfile → docker/Dockerfile} +3 -1
  9. data/{Dockerfile-2.6 → docker/Dockerfile-2.6} +2 -2
  10. data/{Dockerfile-2.7 → docker/Dockerfile-2.7} +2 -2
  11. data/{Dockerfile-3.0 → docker/Dockerfile-3.0} +2 -2
  12. data/{bash_profile → docker/bash_profile} +0 -0
  13. data/{inputrc → docker/inputrc} +0 -0
  14. data/docs/doc/Array.html +84 -2
  15. data/docs/doc/BooleanTermParser/Clause.html +1 -1
  16. data/docs/doc/BooleanTermParser/Operator.html +1 -1
  17. data/docs/doc/BooleanTermParser/Query.html +1 -1
  18. data/docs/doc/BooleanTermParser/QueryParser.html +1 -1
  19. data/docs/doc/BooleanTermParser/QueryTransformer.html +1 -1
  20. data/docs/doc/BooleanTermParser.html +1 -1
  21. data/docs/doc/Doing/ArrayNestedHash.html +198 -0
  22. data/docs/doc/Doing/ArrayTags.html +424 -0
  23. data/docs/doc/Doing/CSVExport.html +266 -0
  24. data/docs/doc/Doing/CalendarImport.html +232 -0
  25. data/docs/doc/Doing/Change.html +617 -0
  26. data/docs/doc/Doing/Changes.html +468 -0
  27. data/docs/doc/Doing/ChronifyArray.html +347 -0
  28. data/docs/doc/Doing/ChronifyNumeric.html +271 -0
  29. data/docs/doc/Doing/ChronifyString.html +682 -0
  30. data/docs/doc/Doing/Color.html +2 -2
  31. data/docs/doc/Doing/Completion/BashCompletions.html +445 -0
  32. data/docs/doc/Doing/Completion/FishCompletions.html +445 -0
  33. data/docs/doc/Doing/Completion/StringUtils.html +229 -0
  34. data/docs/doc/Doing/Completion/ZshCompletions.html +445 -0
  35. data/docs/doc/Doing/Completion.html +17 -3
  36. data/docs/doc/Doing/Configuration.html +1 -1
  37. data/docs/doc/Doing/DayOneRenderer.html +383 -0
  38. data/docs/doc/Doing/DayoneExport.html +290 -0
  39. data/docs/doc/Doing/DoingImport.html +391 -0
  40. data/docs/doc/Doing/Entry.html +381 -0
  41. data/docs/doc/Doing/Errors/DoingNoTraceError.html +1 -1
  42. data/docs/doc/Doing/Errors/DoingRuntimeError.html +1 -1
  43. data/docs/doc/Doing/Errors/DoingStandardError.html +1 -1
  44. data/docs/doc/Doing/Errors/EmptyInput.html +1 -1
  45. data/docs/doc/Doing/Errors/HistoryLimitError.html +1 -1
  46. data/docs/doc/Doing/Errors/InvalidPlugin.html +1 -1
  47. data/docs/doc/Doing/Errors/MissingBackupFile.html +1 -1
  48. data/docs/doc/Doing/Errors/NoResults.html +1 -1
  49. data/docs/doc/Doing/Errors/PluginException.html +1 -1
  50. data/docs/doc/Doing/Errors/UserCancelled.html +1 -1
  51. data/docs/doc/Doing/Errors/WrongCommand.html +1 -1
  52. data/docs/doc/Doing/Errors.html +1 -1
  53. data/docs/doc/Doing/HTMLExport.html +256 -0
  54. data/docs/doc/Doing/Hooks.html +1 -1
  55. data/docs/doc/Doing/Item.html +47 -3
  56. data/docs/doc/Doing/ItemDates.html +564 -0
  57. data/docs/doc/Doing/ItemQuery.html +614 -0
  58. data/docs/doc/Doing/ItemState.html +387 -0
  59. data/docs/doc/Doing/ItemTags.html +498 -0
  60. data/docs/doc/Doing/Items.html +460 -11
  61. data/docs/doc/Doing/JSONExport.html +222 -0
  62. data/docs/doc/Doing/Logger.html +1 -1
  63. data/docs/doc/Doing/MarkdownExport.html +266 -0
  64. data/docs/doc/Doing/MarkdownRenderer.html +383 -0
  65. data/docs/doc/Doing/Note.html +16 -3
  66. data/docs/doc/Doing/Pager.html +1 -1
  67. data/docs/doc/Doing/Plugins.html +1 -1
  68. data/docs/doc/Doing/Prompt.html +31 -682
  69. data/docs/doc/Doing/PromptChoose.html +484 -0
  70. data/docs/doc/Doing/PromptFZF.html +391 -0
  71. data/docs/doc/Doing/PromptInput.html +572 -0
  72. data/docs/doc/Doing/PromptSTD.html +293 -0
  73. data/docs/doc/Doing/PromptYN.html +237 -0
  74. data/docs/doc/Doing/Section.html +58 -2
  75. data/docs/doc/Doing/StringHighlight.html +533 -0
  76. data/docs/doc/Doing/StringNormalize.html +929 -0
  77. data/docs/doc/Doing/StringQuery.html +725 -0
  78. data/docs/doc/Doing/StringTags.html +884 -0
  79. data/docs/doc/Doing/StringTransform.html +565 -0
  80. data/docs/doc/Doing/StringTruncate.html +448 -0
  81. data/docs/doc/Doing/StringURL.html +409 -0
  82. data/docs/doc/Doing/SymbolNormalize.html +341 -0
  83. data/docs/doc/Doing/TaskPaperExport.html +222 -0
  84. data/docs/doc/Doing/TemplateExport.html +249 -0
  85. data/docs/doc/Doing/TemplateString.html +101 -2
  86. data/docs/doc/Doing/TimingImport.html +285 -0
  87. data/docs/doc/Doing/Types.html +1 -1
  88. data/docs/doc/Doing/Util/Backup.html +9 -7
  89. data/docs/doc/Doing/Util.html +2 -2
  90. data/docs/doc/Doing/Version.html +523 -0
  91. data/docs/doc/Doing/WWID/WWIDUtil.html +510 -0
  92. data/docs/doc/Doing/WWID.html +4377 -217
  93. data/docs/doc/Doing/WWIDDisplay.html +865 -0
  94. data/docs/doc/Doing/WWIDEditor.html +466 -0
  95. data/docs/doc/Doing/WWIDFileTools.html +359 -0
  96. data/docs/doc/Doing/WWIDFilter.html +466 -0
  97. data/docs/doc/Doing/WWIDGuess.html +299 -0
  98. data/docs/doc/Doing/WWIDInteractive.html +752 -0
  99. data/docs/doc/Doing/WWIDModify.html +1078 -0
  100. data/docs/doc/Doing/WWIDTags.html +302 -0
  101. data/docs/doc/Doing/WWIDTimers.html +359 -0
  102. data/docs/doc/Doing/WWIDUtil.html +510 -0
  103. data/docs/doc/Doing.html +9 -6
  104. data/docs/doc/FalseClass.html +1 -1
  105. data/docs/doc/GLI/Commands/Help.html +1 -1
  106. data/docs/doc/GLI/Commands/MarkdownDocumentListener.html +1 -1
  107. data/docs/doc/GLI/Commands.html +1 -1
  108. data/docs/doc/GLI.html +1 -1
  109. data/docs/doc/Hash.html +1 -1
  110. data/docs/doc/Numeric.html +23 -78
  111. data/docs/doc/Object.html +1 -1
  112. data/docs/doc/PhraseParser/Operator.html +1 -1
  113. data/docs/doc/PhraseParser/PhraseClause.html +1 -1
  114. data/docs/doc/PhraseParser/Query.html +1 -1
  115. data/docs/doc/PhraseParser/QueryParser.html +1 -1
  116. data/docs/doc/PhraseParser/QueryTransformer.html +1 -1
  117. data/docs/doc/PhraseParser/TermClause.html +1 -1
  118. data/docs/doc/PhraseParser.html +1 -1
  119. data/docs/doc/Status.html +1 -1
  120. data/docs/doc/String.html +58 -633
  121. data/docs/doc/Symbol.html +9 -224
  122. data/docs/doc/Time.html +119 -13
  123. data/docs/doc/TrueClass.html +1 -1
  124. data/docs/doc/_index.html +324 -8
  125. data/docs/doc/class_list.html +1 -1
  126. data/docs/doc/file.README.html +1 -1
  127. data/docs/doc/index.html +1 -1
  128. data/docs/doc/method_list.html +2326 -542
  129. data/docs/doc/top-level-namespace.html +2 -2
  130. data/doing.rdoc +13 -3
  131. data/lib/completion/_doing.zsh +1 -1
  132. data/lib/completion/doing.bash +2 -2
  133. data/lib/completion/doing.fish +3 -1
  134. data/lib/doing/array/array.rb +16 -12
  135. data/lib/doing/array/nested_hash.rb +1 -1
  136. data/lib/doing/array/tags.rb +6 -5
  137. data/lib/doing/changelog/changelog.rb +6 -0
  138. data/lib/doing/chronify/array.rb +1 -3
  139. data/lib/doing/chronify/chronify.rb +12 -0
  140. data/lib/doing/chronify/numeric.rb +3 -2
  141. data/lib/doing/chronify/string.rb +1 -1
  142. data/lib/doing/completion/completion_string.rb +25 -0
  143. data/lib/doing/completion.rb +1 -1
  144. data/lib/doing/good.rb +8 -0
  145. data/lib/doing/item/dates.rb +1 -1
  146. data/lib/doing/{item.rb → item/item.rb} +10 -5
  147. data/lib/doing/item/query.rb +1 -1
  148. data/lib/doing/item/state.rb +1 -1
  149. data/lib/doing/item/tags.rb +1 -1
  150. data/lib/doing/items/filter.rb +67 -0
  151. data/lib/doing/items/items.rb +57 -0
  152. data/lib/doing/items/modify.rb +36 -0
  153. data/lib/doing/items/sections.rb +83 -0
  154. data/lib/doing/items/util.rb +74 -0
  155. data/lib/doing/normalize.rb +10 -2
  156. data/lib/doing/plugins/export/markdown_export.rb +4 -2
  157. data/lib/doing/plugins/import/doing_import.rb +1 -1
  158. data/lib/doing/prompt/choose.rb +118 -0
  159. data/lib/doing/prompt/fzf.rb +84 -0
  160. data/lib/doing/prompt/input.rb +129 -0
  161. data/lib/doing/prompt/prompt.rb +41 -0
  162. data/lib/doing/prompt/std.rb +32 -0
  163. data/lib/doing/prompt/yn.rb +64 -0
  164. data/lib/doing/section.rb +4 -0
  165. data/lib/doing/string/highlight.rb +1 -1
  166. data/lib/doing/string/query.rb +1 -1
  167. data/lib/doing/string/string.rb +18 -7
  168. data/lib/doing/string/tags.rb +14 -3
  169. data/lib/doing/string/transform.rb +1 -1
  170. data/lib/doing/string/truncate.rb +1 -1
  171. data/lib/doing/string/url.rb +1 -1
  172. data/lib/doing/time.rb +19 -1
  173. data/lib/doing/util_backup.rb +2 -2
  174. data/lib/doing/version.rb +1 -1
  175. data/lib/doing/wwid/display.rb +357 -360
  176. data/lib/doing/wwid/editor.rb +173 -176
  177. data/lib/doing/wwid/filetools.rb +156 -159
  178. data/lib/doing/wwid/filter.rb +191 -183
  179. data/lib/doing/wwid/guess.rb +58 -60
  180. data/lib/doing/wwid/interactive.rb +332 -330
  181. data/lib/doing/wwid/modify.rb +509 -512
  182. data/lib/doing/wwid/tags.rb +38 -41
  183. data/lib/doing/wwid/timers.rb +293 -296
  184. data/lib/doing/{wwid.rb → wwid/wwid.rb} +32 -23
  185. data/lib/doing/wwid/wwidutil.rb +79 -82
  186. data/lib/doing.rb +5 -5
  187. data/lib/helpers/threaded_tests.rb +1 -0
  188. metadata +76 -14
  189. data/lib/doing/changelog.rb +0 -6
  190. data/lib/doing/completion/string.rb +0 -17
  191. data/lib/doing/items.rb +0 -221
  192. data/lib/doing/prompt.rb +0 -330
@@ -1,186 +1,183 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Doing
4
- # File methods for WWID class
5
4
  class WWID
6
- module FileTools
7
- ##
8
- ## Initializes the doing file.
9
- ##
10
- ## @param path [String] Override path to a doing file, optional
11
- ##
12
- def init_doing_file(path = nil)
13
- @doing_file = File.expand_path(Doing.setting('doing_file'))
14
-
15
- if path.nil?
16
- create(@doing_file) unless File.exist?(@doing_file)
17
- input = IO.read(@doing_file)
18
- input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
19
- logger.debug('Read:', "read file #{@doing_file}")
20
- elsif File.exist?(File.expand_path(path)) && File.file?(File.expand_path(path)) && File.stat(File.expand_path(path)).size.positive?
21
- @doing_file = File.expand_path(path)
22
- input = IO.read(File.expand_path(path))
23
- input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
24
- logger.debug('Read:', "read file #{File.expand_path(path)}")
25
- elsif path.length < 256
26
- @doing_file = File.expand_path(path)
27
- create(path)
28
- input = IO.read(File.expand_path(path))
29
- input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
30
- logger.debug('Read:', "read file #{File.expand_path(path)}")
31
- end
32
-
33
- @other_content_top = []
34
- @other_content_bottom = []
35
-
36
- section = nil
37
- lines = input.split(/[\n\r]/)
38
-
39
- lines.each do |line|
40
- next if line =~ /^\s*$/
41
-
42
- if line =~ /^(\S[\S ]+):\s*(@\S+\s*)*$/
43
- section = Regexp.last_match(1)
44
- @content.add_section(Section.new(section, original: line), log: false)
45
- elsif line =~ /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*)/
46
- if section.nil?
47
- section = 'Uncategorized'
48
- @content.add_section(Section.new(section, original: 'Uncategorized:'), log: false)
49
- end
50
-
51
- date = Regexp.last_match(1).strip
52
- title = Regexp.last_match(2).strip
53
- item = Item.new(date, title, section)
54
- @content.push(item)
55
- elsif @content.count.zero?
56
- # if content[section].items.length - 1 == current
57
- @other_content_top.push(line)
58
- elsif line =~ /^\S/
59
- @other_content_bottom.push(line)
60
- else
61
- prev_item = @content.last
62
- prev_item.note = Note.new unless prev_item.note
63
-
64
- prev_item.note.add(line)
65
- # end
66
- end
67
- end
68
-
69
- Hooks.trigger :post_read, self
70
- @initial_content = @content.clone
5
+ ##
6
+ ## Initializes the doing file.
7
+ ##
8
+ ## @param path [String] Override path to a doing file, optional
9
+ ##
10
+ def init_doing_file(path = nil)
11
+ @doing_file = File.expand_path(Doing.setting('doing_file'))
12
+
13
+ if path.nil?
14
+ create(@doing_file) unless File.exist?(@doing_file)
15
+ input = IO.read(@doing_file)
16
+ input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
17
+ logger.debug('Read:', "read file #{@doing_file}")
18
+ elsif File.exist?(File.expand_path(path)) && File.file?(File.expand_path(path)) && File.stat(File.expand_path(path)).size.positive?
19
+ @doing_file = File.expand_path(path)
20
+ input = IO.read(File.expand_path(path))
21
+ input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
22
+ logger.debug('Read:', "read file #{File.expand_path(path)}")
23
+ elsif path.length < 256
24
+ @doing_file = File.expand_path(path)
25
+ create(path)
26
+ input = IO.read(File.expand_path(path))
27
+ input = input.force_encoding('utf-8') if input.respond_to? :force_encoding
28
+ logger.debug('Read:', "read file #{File.expand_path(path)}")
71
29
  end
72
30
 
73
- ##
74
- ## Create a new doing file
75
- ##
76
- def create(filename = nil)
77
- filename = @doing_file if filename.nil?
78
- return if File.exist?(filename) && File.stat(filename).size.positive?
31
+ @other_content_top = []
32
+ @other_content_bottom = []
79
33
 
80
- FileUtils.mkdir_p(File.dirname(filename)) unless File.directory?(File.dirname(filename))
34
+ section = nil
35
+ lines = input.split(/[\n\r]/)
81
36
 
82
- File.open(filename, 'w+') do |f|
83
- f.puts "#{Doing.setting('current_section')}:"
84
- end
85
- end
37
+ lines.each do |line|
38
+ next if line =~ /^\s*$/
86
39
 
87
- ##
88
- ## Write content to file or STDOUT
89
- ##
90
- ## @param file [String] The filepath to write to
91
- ##
92
- def write(file = nil, backup: true)
93
- Hooks.trigger :pre_write, self, file
94
- output = combined_content
95
- if file.nil?
96
- $stdout.puts output
40
+ if line =~ /^(\S[\S ]+):\s*(@[\w\-_.]+\s*)*$/
41
+ section = Regexp.last_match(1)
42
+ @content.add_section(Section.new(section, original: line), log: false)
43
+ elsif line =~ /^\s*- (\d{4}-\d\d-\d\d \d\d:\d\d) \| (.*)/
44
+ if section.nil?
45
+ section = 'Uncategorized'
46
+ @content.add_section(Section.new(section, original: 'Uncategorized:'), log: false)
47
+ end
48
+
49
+ date = Regexp.last_match(1).strip
50
+ title = Regexp.last_match(2).strip
51
+ item = Item.new(date, title, section)
52
+ @content.push(item)
53
+ elsif @content.count.zero?
54
+ # if content[section].items.length - 1 == current
55
+ @other_content_top.push(line)
56
+ elsif line =~ /^\S/
57
+ @other_content_bottom.push(line)
97
58
  else
98
- Util.write_to_file(file, output, backup: backup)
99
- run_after if Doing.setting('run_after')
59
+ prev_item = @content.last
60
+ prev_item.note = Note.new unless prev_item.note
61
+
62
+ prev_item.note.add(line)
63
+ # end
100
64
  end
101
65
  end
102
66
 
103
- ##
104
- ## Rename doing file with date and start fresh one
105
- ##
106
- def rotate(opt)
107
- opt ||= {}
108
- keep = opt[:keep] || 0
109
- tags = []
110
- tags.concat(opt[:tag].split(/ *, */).map { |t| t.sub(/^@/, '').strip }) if opt[:tag]
111
- bool = opt[:bool] || :and
112
- sect = opt[:section] !~ /^all$/i ? guess_section(opt[:section]) : 'all'
113
-
114
- section = guess_section(sect)
115
-
116
- section_items = @content.in_section(section)
117
- max = section_items.count - keep.to_i
118
-
119
- counter = 0
120
- new_content = Items.new
121
-
122
- section_items.each do |item|
123
- break if counter >= max
124
- if opt[:before]
125
- time_string = opt[:before]
126
- cutoff = time_string.chronify(guess: :begin)
127
- end
67
+ Hooks.trigger :post_read, self
68
+ @initial_content = @content.clone
69
+ end
128
70
 
129
- unless ((!tags.empty? && !item.tags?(tags, bool)) || (opt[:search] && !item.search(opt[:search].to_s)) || (opt[:before] && item.date >= cutoff))
130
- new_item = @content.delete(item)
131
- Hooks.trigger :post_entry_removed, self, item.clone
132
- raise DoingRuntimeError, "Error deleting item: #{item}" if new_item.nil?
71
+ ##
72
+ ## Create a new doing file
73
+ ##
74
+ def create(filename = nil)
75
+ filename = @doing_file if filename.nil?
76
+ return if File.exist?(filename) && File.stat(filename).size.positive?
133
77
 
134
- new_content.add_section(new_item.section, log: false)
135
- new_content.push(new_item)
136
- counter += 1
137
- end
138
- end
78
+ FileUtils.mkdir_p(File.dirname(filename)) unless File.directory?(File.dirname(filename))
139
79
 
140
- if counter.positive?
141
- logger.count(:rotated,
142
- level: :info,
143
- count: counter,
144
- message: "Rotated %count %items")
145
- else
146
- logger.info('Skipped:', 'No items were rotated')
80
+ File.open(filename, 'w+') do |f|
81
+ f.puts "#{Doing.setting('current_section')}:"
82
+ end
83
+ end
84
+
85
+ ##
86
+ ## Write content to file or STDOUT
87
+ ##
88
+ ## @param file [String] The filepath to write to
89
+ ##
90
+ def write(file = nil, backup: true)
91
+ Hooks.trigger :pre_write, self, file
92
+ output = combined_content
93
+ if file.nil?
94
+ $stdout.puts output
95
+ else
96
+ Util.write_to_file(file, output, backup: backup)
97
+ run_after if Doing.setting('run_after')
98
+ end
99
+ end
100
+
101
+ ##
102
+ ## Rename doing file with date and start fresh one
103
+ ##
104
+ def rotate(opt)
105
+ opt ||= {}
106
+ keep = opt[:keep] || 0
107
+ tags = []
108
+ tags.concat(opt[:tag].split(/ *, */).map { |t| t.sub(/^@/, '').strip }) if opt[:tag]
109
+ bool = opt[:bool] || :and
110
+ sect = opt[:section] !~ /^all$/i ? guess_section(opt[:section]) : 'all'
111
+
112
+ section = guess_section(sect)
113
+
114
+ section_items = @content.in_section(section)
115
+ max = section_items.count - keep.to_i
116
+
117
+ counter = 0
118
+ new_content = Items.new
119
+
120
+ section_items.each do |item|
121
+ break if counter >= max
122
+ if opt[:before]
123
+ time_string = opt[:before]
124
+ cutoff = time_string.chronify(guess: :begin)
147
125
  end
148
126
 
149
- write(@doing_file)
127
+ unless ((!tags.empty? && !item.tags?(tags, bool)) || (opt[:search] && !item.search(opt[:search].to_s)) || (opt[:before] && item.date >= cutoff))
128
+ new_item = @content.delete(item)
129
+ Hooks.trigger :post_entry_removed, self, item.clone
130
+ raise DoingRuntimeError, "Error deleting item: #{item}" if new_item.nil?
150
131
 
151
- file = @doing_file.sub(/(\.\w+)$/, "_#{Time.now.strftime('%Y-%m-%d')}\\1")
152
- if File.exist?(file)
153
- init_doing_file(file)
154
- @content.concat(new_content).uniq!
155
- logger.warn('File update:', "added entries to existing file: #{file}")
156
- else
157
- @content = new_content
158
- logger.warn('File update:', "created new file: #{file}")
132
+ new_content.add_section(new_item.section, log: false)
133
+ new_content.push(new_item)
134
+ counter += 1
159
135
  end
136
+ end
160
137
 
161
- write(file, backup: false)
138
+ if counter.positive?
139
+ logger.count(:rotated,
140
+ level: :info,
141
+ count: counter,
142
+ message: "Rotated %count %items")
143
+ else
144
+ logger.info('Skipped:', 'No items were rotated')
162
145
  end
163
146
 
164
- private
165
-
166
- ##
167
- ## Wraps doing file content with additional
168
- ## header/footer content
169
- ##
170
- ## @return [String] concatenated content
171
- ## @api private
172
- def combined_content
173
- output = @other_content_top ? "#{@other_content_top.join("\n")}\n" : ''
174
- was_color = Color.coloring?
175
- Color.coloring = false
176
- @content.dedup!(match_section: true)
177
- output += @content.to_s
178
- output += @other_content_bottom.join("\n") unless @other_content_bottom.nil?
179
- # Just strip all ANSI colors from the content before writing to doing file
180
- Color.coloring = was_color
181
-
182
- output.uncolor
147
+ write(@doing_file)
148
+
149
+ file = @doing_file.sub(/(\.\w+)$/, "_#{Time.now.strftime('%Y-%m-%d')}\\1")
150
+ if File.exist?(file)
151
+ init_doing_file(file)
152
+ @content.concat(new_content).uniq!
153
+ logger.warn('File update:', "added entries to existing file: #{file}")
154
+ else
155
+ @content = new_content
156
+ logger.warn('File update:', "created new file: #{file}")
183
157
  end
158
+
159
+ write(file, backup: false)
160
+ end
161
+
162
+ private
163
+
164
+ ##
165
+ ## Wraps doing file content with additional
166
+ ## header/footer content
167
+ ##
168
+ ## @return [String] concatenated content
169
+ ## @api private
170
+ def combined_content
171
+ output = @other_content_top ? "#{@other_content_top.join("\n")}\n" : ''
172
+ was_color = Color.coloring?
173
+ Color.coloring = false
174
+ @content.dedup!(match_section: true)
175
+ output += @content.to_s
176
+ output += @other_content_bottom.join("\n") unless @other_content_bottom.nil?
177
+ # Just strip all ANSI colors from the content before writing to doing file
178
+ Color.coloring = was_color
179
+
180
+ output.uncolor
184
181
  end
185
182
  end
186
183
  end