mux_tf 0.8.4 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21e0e5f58ecc6d306e555902ffe4db396a624dcd238cffd4ffa9f601baa44f8a
4
- data.tar.gz: 80cd848539404d195931669894311556df35b7a6949a3aaae61f5ee35c9c065b
3
+ metadata.gz: b79dc73fcdc056b82b415b35dbb624b69e70edf3bc6db7852d8e2ea06f95c1ce
4
+ data.tar.gz: 119261f6a5f86ff78319cf411d1f24ff35f2c13262a427d3dd3ec990bd4fbd09
5
5
  SHA512:
6
- metadata.gz: 9be81dd55dcc793400fddffc83af284893d71f02ce7462f7f7f10203114ba9260619887ecbdf92aeb35175f26334c40fef84e7d91e1bc380d0bf976ed7ecd561
7
- data.tar.gz: b16d3e6f1b3214912354ff6915e13c64542ed224b16e1ec7d40241218ab2effe292dda60bceb6b7ab8d71292e3cf99c057d14096b39628482e65430c704380f1
6
+ metadata.gz: dce2287920bef8ea5eafd6b8565b7c2a7b6799ceb4514739a3aa7d7dc5fe0bcb840275824faf824294309b929a40698dc6203ed2755071238ed9008409865277
7
+ data.tar.gz: 92da3b7540fee9234c8d2b9ecc2cb6b8a4027c8644549777417aff862a3babdb5f66deeb1bd815f7ef43abf256305f26602efe4c93308176a7023d92845125f2
data/exe/tf_current CHANGED
@@ -8,7 +8,7 @@ begin
8
8
  require "mux_tf"
9
9
 
10
10
  MuxTf::Cli.run(:current, ARGV)
11
- rescue Exception => e
11
+ rescue Exception => e # rubocop:disable Lint/RescueException
12
12
  warn e.full_message
13
13
  warn "<press enter>"
14
14
  $stdin.gets
data/exe/tf_mux CHANGED
@@ -8,7 +8,7 @@ begin
8
8
  require "mux_tf"
9
9
 
10
10
  MuxTf::Cli.run(:mux, ARGV)
11
- rescue Exception => e
11
+ rescue Exception => e # rubocop:disable Lint/RescueException
12
12
  warn e.full_message
13
13
  warn "<press enter>"
14
14
  $stdin.gets
data/exe/tf_plan_summary CHANGED
@@ -8,7 +8,7 @@ begin
8
8
  require "mux_tf"
9
9
 
10
10
  MuxTf::Cli.run(:plan_summary, ARGV)
11
- rescue Exception => e
11
+ rescue Exception => e # rubocop:disable Lint/RescueException
12
12
  warn e.full_message
13
13
  warn "<press enter>"
14
14
  $stdin.gets
data/lib/deps.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/inline"
2
4
 
3
5
  gemfile do
@@ -10,8 +10,6 @@ module MuxTf
10
10
  extend PiotrbCliUtils::CriCommandSupport
11
11
  extend PiotrbCliUtils::CmdLoop
12
12
 
13
- PLAN_FILENAME = "foo.tfplan"
14
-
15
13
  class << self
16
14
  def run(args)
17
15
  version_check
@@ -30,11 +28,11 @@ module MuxTf
30
28
  return launch_cmd_loop(:error) unless run_validate
31
29
 
32
30
  if ENV["TF_UPGRADE"]
33
- upgrade_status, upgrade_meta = run_upgrade
31
+ upgrade_status, _upgrade_meta = run_upgrade
34
32
  return launch_cmd_loop(:error) unless upgrade_status == :ok
35
33
  end
36
34
 
37
- plan_status, @plan_meta = create_plan(PLAN_FILENAME)
35
+ plan_status, @plan_meta = create_plan(plan_filename)
38
36
 
39
37
  case plan_status
40
38
  when :ok
@@ -44,7 +42,7 @@ module MuxTf
44
42
  launch_cmd_loop(plan_status)
45
43
  when :changes
46
44
  log "Printing Plan Summary ...", depth: 1
47
- pretty_plan_summary(PLAN_FILENAME)
45
+ pretty_plan_summary(plan_filename)
48
46
  launch_cmd_loop(plan_status)
49
47
  when :unknown
50
48
  launch_cmd_loop(plan_status)
@@ -59,17 +57,21 @@ module MuxTf
59
57
  exit 1
60
58
  end
61
59
 
60
+ def plan_filename
61
+ PlanFilenameGenerator.for_path
62
+ end
63
+
62
64
  private
63
65
 
64
66
  def version_check
65
- if VersionCheck.has_updates?
66
- log Paint["=" * 80, :yellow]
67
- log "New version of #{Paint["mux_tf", :cyan]} is available!"
68
- log "You are currently on version: #{Paint[VersionCheck.current_gem_version, :yellow]}"
69
- log "Latest version found is: #{Paint[VersionCheck.latest_gem_version, :green]}"
70
- log "Run `#{Paint["gem install mux_tf", :green]}` to update!"
71
- log Paint["=" * 80, :yellow]
72
- end
67
+ return unless VersionCheck.has_updates?
68
+
69
+ log Paint["=" * 80, :yellow]
70
+ log "New version of #{Paint['mux_tf', :cyan]} is available!"
71
+ log "You are currently on version: #{Paint[VersionCheck.current_gem_version, :yellow]}"
72
+ log "Latest version found is: #{Paint[VersionCheck.latest_gem_version, :green]}"
73
+ log "Run `#{Paint['gem install mux_tf', :green]}` to update!"
74
+ log Paint["=" * 80, :yellow]
73
75
  end
74
76
 
75
77
  def run_validate
@@ -176,7 +178,7 @@ module MuxTf
176
178
 
177
179
  def apply_cmd
178
180
  define_cmd("apply", summary: "Apply the current plan") do |_opts, _args, _cmd|
179
- status = tf_apply(filename: PLAN_FILENAME)
181
+ status = tf_apply(filename: plan_filename)
180
182
  if status.success?
181
183
  plan_status = run_plan
182
184
  throw :stop, :done if plan_status == :ok
@@ -190,7 +192,7 @@ module MuxTf
190
192
  define_cmd("shell", summary: "Open your default terminal in the current folder") do |_opts, _args, _cmd|
191
193
  log Paint["Launching shell ...", :yellow]
192
194
  log Paint["When it exits you will be back at this prompt.", :yellow]
193
- system ENV["SHELL"]
195
+ system ENV.fetch("SHELL")
194
196
  end
195
197
  end
196
198
 
@@ -208,11 +210,11 @@ module MuxTf
208
210
 
209
211
  if @plan_meta && @plan_meta["error"] == "lock"
210
212
  done = catch(:abort) {
211
- if @plan_meta["Operation"] != "OperationTypePlan"
212
- throw :abort unless prompt.yes?(
213
- "Are you sure you want to force unlock a lock for operation: #{@plan_meta["Operation"]}",
214
- default: false
215
- )
213
+ if @plan_meta["Operation"] != "OperationTypePlan" && !prompt.yes?(
214
+ "Are you sure you want to force unlock a lock for operation: #{@plan_meta['Operation']}",
215
+ default: false
216
+ )
217
+ throw :abort
216
218
  end
217
219
 
218
220
  throw :abort unless prompt.yes?(
@@ -259,17 +261,15 @@ module MuxTf
259
261
 
260
262
  def interactive_cmd
261
263
  define_cmd("interactive", summary: "Apply interactively") do |_opts, _args, _cmd|
262
- plan = PlanSummaryHandler.from_file(PLAN_FILENAME)
264
+ plan = PlanSummaryHandler.from_file(plan_filename)
263
265
  begin
264
- abort_message = catch :abort do
265
- plan.run_interactive
266
- end
266
+ abort_message = catch(:abort) { plan.run_interactive }
267
267
  if abort_message
268
268
  log Paint["Aborted: #{abort_message}", :red]
269
269
  else
270
270
  run_plan
271
271
  end
272
- rescue Exception => e
272
+ rescue Exception => e # rubocop:disable Lint/RescueException
273
273
  log e.full_message
274
274
  log "Interactive Apply Failed!"
275
275
  end
@@ -277,7 +277,7 @@ module MuxTf
277
277
  end
278
278
 
279
279
  def run_plan(targets: [])
280
- plan_status, @plan_meta = create_plan(PLAN_FILENAME, targets: targets)
280
+ plan_status, @plan_meta = create_plan(plan_filename, targets: targets)
281
281
 
282
282
  case plan_status
283
283
  when :ok
@@ -286,7 +286,7 @@ module MuxTf
286
286
  log "something went wrong", depth: 1
287
287
  when :changes
288
288
  log "Printing Plan Summary ...", depth: 1
289
- pretty_plan_summary(PLAN_FILENAME)
289
+ pretty_plan_summary(plan_filename)
290
290
  when :unknown
291
291
  # nothing
292
292
  end
@@ -13,7 +13,7 @@ module MuxTf
13
13
  backup = {}
14
14
  Bundler.with_original_env do
15
15
  ENV.keys.grep(/^(RBENV_|RUBYLIB)/).each do |key|
16
- backup[key] = ENV[key]
16
+ backup[key] = ENV.fetch(key)
17
17
  ENV.delete(key)
18
18
  end
19
19
  yield
@@ -104,7 +104,7 @@ module MuxTf
104
104
  ignored += ENV["MUX_IGNORE"].split(",") if ENV["MUX_IGNORE"]
105
105
 
106
106
  dirs = Dir["**/.terraform.lock.hcl"].map { |f| File.dirname(f) }
107
- dirs.reject! { |d| d.in?(ignored) }
107
+ dirs.reject! do |d| d.in?(ignored) end
108
108
 
109
109
  dirs
110
110
  end
@@ -23,23 +23,17 @@ module MuxTf
23
23
  end
24
24
  }.parse!(args)
25
25
 
26
- if options[:interactive]
27
- raise "must specify plan file in interactive mode" if args[0].blank?
28
- end
26
+ raise "must specify plan file in interactive mode" if options[:interactive] && args[0].blank?
29
27
 
30
28
  plan = if args[0]
31
- PlanSummaryHandler.from_file(args[0])
32
- else
33
- PlanSummaryHandler.from_data(JSON.parse(STDIN.read))
34
- end
29
+ PlanSummaryHandler.from_file(args[0])
30
+ else
31
+ PlanSummaryHandler.from_data(JSON.parse($stdin.read))
32
+ end
35
33
 
36
34
  if options[:interactive]
37
- abort_message = catch :abort do
38
- plan.run_interactive
39
- end
40
- if abort_message
41
- log Paint["Aborted: #{abort_message}", :red]
42
- end
35
+ abort_message = catch(:abort) { plan.run_interactive }
36
+ log Paint["Aborted: #{abort_message}", :red] if abort_message
43
37
  else
44
38
  if options[:hierarchy]
45
39
  plan.nested_summary.each do |line|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MuxTf
2
4
  class OnceHelper
3
5
  # once = OnceHelper.new
@@ -5,25 +7,21 @@ module MuxTf
5
7
 
6
8
  class StateEvaluator
7
9
  def initialize(once_helper, new_state)
8
- if once_helper.state != new_state
10
+ if once_helper.state == new_state
11
+ @path = :otherwise
12
+ else
9
13
  once_helper.state = new_state
10
14
  @path = :once
11
- else
12
- @path = :otherwise
13
15
  end
14
16
  end
15
17
 
16
- def once(&block)
17
- if @path == :then
18
- yield
19
- end
18
+ def once
19
+ yield if @path == :then
20
20
  self
21
21
  end
22
22
 
23
- def otherwise(&block)
24
- if @path == :otherwise
25
- yield
26
- end
23
+ def otherwise
24
+ yield if @path == :otherwise
27
25
  self
28
26
  end
29
27
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MuxTf
4
+ class PlanFilenameGenerator
5
+ def self.for_path(path = Dir.getwd)
6
+ folder_name = File.basename(path)
7
+ temp_dir = Dir.tmpdir
8
+ hash = Digest::MD5.hexdigest(path)
9
+ "#{temp_dir}/#{folder_name}-#{hash}.tfplan"
10
+ end
11
+ end
12
+ end
@@ -6,7 +6,7 @@ module MuxTf
6
6
  extend PiotrbCliUtils::Util
7
7
 
8
8
  class << self
9
- def pretty_plan(filename, targets: [])
9
+ def pretty_plan(filename, targets: []) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
10
10
  pastel = Pastel.new
11
11
 
12
12
  once = OnceHelper.new
@@ -15,11 +15,12 @@ module MuxTf
15
15
 
16
16
  parser = StatefulParser.new(normalizer: pastel.method(:strip))
17
17
  parser.state(:info, /^Acquiring state lock/)
18
- parser.state(:error, /(╷|Error locking state|Error:)/, %i[none blank info reading])
19
- parser.state(:reading, /: (Reading...|Read complete after)/, %i[none info reading])
18
+ parser.state(:error, /(╷|Error locking state|Error:)/, [:none, :blank, :info, :reading])
19
+ parser.state(:reading, /: (Reading...|Read complete after)/, [:none, :info, :reading])
20
20
  parser.state(:none, /^$/, [:reading])
21
- parser.state(:refreshing, /^.+: Refreshing state... \[id=/, %i[none info reading])
22
- parser.state(:refreshing, /Refreshing Terraform state in-memory prior to plan.../, %i[none blank info reading])
21
+ parser.state(:refreshing, /^.+: Refreshing state... \[id=/, [:none, :info, :reading])
22
+ parser.state(:refreshing, /Refreshing Terraform state in-memory prior to plan.../,
23
+ [:none, :blank, :info, :reading])
23
24
  parser.state(:refresh_done, /^----------+$/, [:refreshing])
24
25
  parser.state(:refresh_done, /^$/, [:refreshing])
25
26
  parser.state(:plan_info, /Terraform will perform the following actions:/, [:refresh_done, :none])
@@ -31,7 +32,7 @@ module MuxTf
31
32
  parser.state(:error_lock_info, /Lock Info/, [:error])
32
33
  parser.state(:error, /^$/, [:error_lock_info])
33
34
 
34
- parser.state(:plan_error, /^╷|Error: /, %i[refreshing refresh_done])
35
+ parser.state(:plan_error, /^╷|Error: /, [:refreshing, :refresh_done])
35
36
 
36
37
  status = tf_plan(out: filename, detailed_exitcode: true, compact_warnings: true, targets: targets) { |raw_line|
37
38
  parser.parse(raw_line.rstrip) do |state, line|
@@ -65,13 +66,11 @@ module MuxTf
65
66
  meta["error"] = "lock"
66
67
  log Paint[line, :red], depth: 2
67
68
  when :plan_error
68
- once.for(state).once { puts }
69
+ once.for(state).once do puts end
69
70
  meta["error"] = "refresh"
70
71
  log Paint[line, :red], depth: 2
71
72
  when :error_lock_info
72
- if line =~ /([A-Z]+[\S]+)+:\s+(.+)$/
73
- meta[$LAST_MATCH_INFO[1]] = $LAST_MATCH_INFO[2]
74
- end
73
+ meta[$LAST_MATCH_INFO[1]] = $LAST_MATCH_INFO[2] if line =~ /([A-Z]+\S+)+:\s+(.+)$/
75
74
  log Paint[line, :red], depth: 2
76
75
  when :refreshing
77
76
  once.for(state).once {
@@ -80,16 +79,16 @@ module MuxTf
80
79
  print "."
81
80
  }
82
81
  when :plan_legend
83
- once.for(state).once { puts }
82
+ once.for(state).once do puts end
84
83
  log line, depth: 2
85
84
  when :refresh_done
86
85
  once.for(state).once {
87
86
  puts
88
87
  }.otherwise {
89
- #nothing
88
+ # nothing
90
89
  }
91
- when :plan_info
92
- once.for(state).once { puts }
90
+ when :plan_info # rubocop:disable Lint/DuplicateBranch
91
+ once.for(state).once do puts end
93
92
  log line, depth: 2
94
93
  when :plan_summary
95
94
  log line, depth: 2
@@ -114,7 +113,7 @@ module MuxTf
114
113
  remedies
115
114
  end
116
115
 
117
- def run_tf_init(upgrade: nil, reconfigure: nil)
116
+ def run_tf_init(upgrade: nil, reconfigure: nil) # rubocop:disable Metrics/MethodLength
118
117
  pastel = Pastel.new
119
118
 
120
119
  phase = :init
@@ -145,7 +144,7 @@ module MuxTf
145
144
  case stripped_line
146
145
  when /^Downloading (?<repo>[^ ]+) (?<version>[^ ]+) for (?<module>[^ ]+)\.\.\./
147
146
  print "D"
148
- when /^Downloading (?<repo>[^ ]+) for (?<module>[^ ]+)\.\.\./
147
+ when /^Downloading (?<repo>[^ ]+) for (?<module>[^ ]+)\.\.\./ # rubocop:disable Lint/DuplicateBranch
149
148
  print "D"
150
149
  when /^- (?<module>[^ ]+) in (?<path>.+)$/
151
150
  print "."
@@ -166,7 +165,7 @@ module MuxTf
166
165
  print "."
167
166
  when /^Downloading (?<repo>[^ ]+) (?<version>[^ ]+) for (?<module>[^ ]+)\.\.\./
168
167
  print "D"
169
- when /^Downloading (?<repo>[^ ]+) for (?<module>[^ ]+)\.\.\./
168
+ when /^Downloading (?<repo>[^ ]+) for (?<module>[^ ]+)\.\.\./ # rubocop:disable Lint/DuplicateBranch
170
169
  print "D"
171
170
  when ""
172
171
  puts
@@ -183,7 +182,7 @@ module MuxTf
183
182
  case stripped_line
184
183
  when /^Successfully configured/
185
184
  log line, depth: 2
186
- when /unless the backend/
185
+ when /unless the backend/ # rubocop:disable Lint/DuplicateBranch
187
186
  log line, depth: 2
188
187
  when ""
189
188
  puts
@@ -205,28 +204,28 @@ module MuxTf
205
204
  case stripped_line
206
205
  when /^- Reusing previous version of (?<module>.+) from the dependency lock file$/
207
206
  info = $LAST_MATCH_INFO.named_captures
208
- log "- [FROM-LOCK] #{info["module"]}", depth: 2
207
+ log "- [FROM-LOCK] #{info['module']}", depth: 2
209
208
  when /^- (?<module>.+) is built in to Terraform$/
210
209
  info = $LAST_MATCH_INFO.named_captures
211
- log "- [BUILTIN] #{info["module"]}", depth: 2
210
+ log "- [BUILTIN] #{info['module']}", depth: 2
212
211
  when /^- Finding (?<module>[^ ]+) versions matching "(?<version>.+)"\.\.\./
213
212
  info = $LAST_MATCH_INFO.named_captures
214
- log "- [FIND] #{info["module"]} matching #{info["version"].inspect}", depth: 2
213
+ log "- [FIND] #{info['module']} matching #{info['version'].inspect}", depth: 2
215
214
  when /^- Finding latest version of (?<module>.+)\.\.\.$/
216
215
  info = $LAST_MATCH_INFO.named_captures
217
- log "- [FIND] #{info["module"]}", depth: 2
216
+ log "- [FIND] #{info['module']}", depth: 2
218
217
  when /^- Installing (?<module>[^ ]+) v(?<version>.+)\.\.\.$/
219
218
  info = $LAST_MATCH_INFO.named_captures
220
- log "- [INSTALLING] #{info["module"]} v#{info["version"]}", depth: 2
221
- when /^- Installed (?<module>[^ ]+) v(?<version>.+) \(signed by( a)? (?<signed>.+)\)$/
219
+ log "- [INSTALLING] #{info['module']} v#{info['version']}", depth: 2
220
+ when /^- Installed (?<module>[^ ]+) v(?<version>.+) \(signed by(?: a)? (?<signed>.+)\)$/
222
221
  info = $LAST_MATCH_INFO.named_captures
223
- log "- [INSTALLED] #{info["module"]} v#{info["version"]} (#{info["signed"]})", depth: 2
222
+ log "- [INSTALLED] #{info['module']} v#{info['version']} (#{info['signed']})", depth: 2
224
223
  when /^- Using previously-installed (?<module>[^ ]+) v(?<version>.+)$/
225
224
  info = $LAST_MATCH_INFO.named_captures
226
- log "- [USING] #{info["module"]} v#{info["version"]}", depth: 2
225
+ log "- [USING] #{info['module']} v#{info['version']}", depth: 2
227
226
  when /^- Downloading plugin for provider "(?<provider>[^"]+)" \((?<provider_path>[^)]+)\) (?<version>.+)\.\.\.$/
228
227
  info = $LAST_MATCH_INFO.named_captures
229
- log "- #{info["provider"]} #{info["version"]}", depth: 2
228
+ log "- #{info['provider']} #{info['version']}", depth: 2
230
229
  when "- Checking for available provider plugins..."
231
230
  # noop
232
231
  else
@@ -242,6 +241,7 @@ module MuxTf
242
241
  log Paint[line, :yellow], depth: 1
243
242
  when :none
244
243
  next if line == ""
244
+
245
245
  p [state, line]
246
246
  else
247
247
  p [state, line]
@@ -252,23 +252,21 @@ module MuxTf
252
252
  [status.status, meta]
253
253
  end
254
254
 
255
- def process_validation(info)
255
+ def process_validation(info) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
256
256
  remedies = Set.new
257
257
 
258
- if info["error_count"] > 0 || info["warning_count"] > 0
259
- log "Encountered #{Paint[info["error_count"], :red]} Errors and #{Paint[info["warning_count"], :yellow]} Warnings!", depth: 2
258
+ if (info["error_count"]).positive? || (info["warning_count"]).positive?
259
+ log "Encountered #{Paint[info['error_count'], :red]} Errors and #{Paint[info['warning_count'], :yellow]} Warnings!", depth: 2
260
260
  info["diagnostics"].each do |dinfo|
261
261
  color = dinfo["severity"] == "error" ? :red : :yellow
262
- log "#{Paint[dinfo["severity"].capitalize, color]}: #{dinfo["summary"]}", depth: 3
262
+ log "#{Paint[dinfo['severity'].capitalize, color]}: #{dinfo['summary']}", depth: 3
263
263
  if dinfo["detail"]&.include?("terraform init")
264
264
  remedies << :init
265
- elsif /there is no package for .+ cached in/.match?(dinfo["summary"])
265
+ elsif /there is no package for .+ cached in/.match?(dinfo["summary"]) # rubocop:disable Lint/DuplicateBranch
266
266
  remedies << :init
267
267
  else
268
268
  log dinfo["detail"], depth: 4 if dinfo["detail"]
269
- if dinfo["range"]
270
- log format_validation_range(dinfo["range"], color), depth: 4
271
- end
269
+ log format_validation_range(dinfo["range"], color), depth: 4 if dinfo["range"]
272
270
 
273
271
  remedies << :unknown if dinfo["severity"] == "error"
274
272
  end
@@ -280,7 +278,7 @@ module MuxTf
280
278
 
281
279
  private
282
280
 
283
- def format_validation_range(range, color)
281
+ def format_validation_range(range, color) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
284
282
  # filename: "../../../modules/pods/jane_pod/main.tf"
285
283
  # start:
286
284
  # line: 151
@@ -299,12 +297,17 @@ module MuxTf
299
297
  # on ../../../modules/pods/jane_pod/main.tf line 151, in module "jane":
300
298
  # 151: jane_resources_preset = var.jane_resources_presetx
301
299
  output = []
302
- lines_info = lines.size == 1 ? "#{lines.first}:#{columns.first}" : "#{lines.first}:#{columns.first} to #{lines.last}:#{columns.last}"
303
- output << "on: #{range["filename"]} line#{lines.size > 1 ? "s" : ""}: #{lines_info}"
300
+ lines_info = if lines.size == 1
301
+ "#{lines.first}:#{columns.first}"
302
+ else
303
+ "#{lines.first}:#{columns.first} to #{lines.last}:#{columns.last}"
304
+ end
305
+ output << "on: #{range['filename']} line#{lines.size > 1 ? 's' : ''}: #{lines_info}"
304
306
 
305
307
  if File.exist?(range["filename"])
306
308
  file_lines = File.read(range["filename"]).split("\n")
307
- extract_range = ([lines.first - context_lines, 0].max)..([lines.last + context_lines, file_lines.length - 1].min)
309
+ extract_range = (([lines.first - context_lines,
310
+ 0].max)..([lines.last + context_lines, file_lines.length - 1].min))
308
311
  file_lines.each_with_index do |line, index|
309
312
  if extract_range.cover?(index + 1)
310
313
  if lines.cover?(index + 1)
@@ -316,7 +319,7 @@ module MuxTf
316
319
  start_col = columns.last
317
320
  end
318
321
  painted_line = paint_line(line, color, start_col: start_col, end_col: end_col)
319
- output << "#{Paint[">", color]} #{index + 1}: #{painted_line}"
322
+ output << "#{Paint['>', color]} #{index + 1}: #{painted_line}"
320
323
  else
321
324
  output << " #{index + 1}: #{line}"
322
325
  end
@@ -330,7 +333,7 @@ module MuxTf
330
333
  def paint_line(line, *paint_options, start_col: 1, end_col: :max)
331
334
  end_col = line.length if end_col == :max
332
335
  prefix = line[0, start_col - 1]
333
- suffix = line[end_col..-1]
336
+ suffix = line[end_col..]
334
337
  middle = line[start_col - 1..end_col - 1]
335
338
  "#{prefix}#{Paint[middle, *paint_options]}#{suffix}"
336
339
  end