thor 1.1.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/thor/runner.rb CHANGED
@@ -1,13 +1,10 @@
1
1
  require_relative "../thor"
2
2
  require_relative "group"
3
3
 
4
- require "yaml"
5
- require "digest/md5"
4
+ require "digest/sha2"
6
5
  require "pathname"
7
6
 
8
- class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
9
- autoload :OpenURI, "open-uri"
10
-
7
+ class Thor::Runner < Thor #:nodoc:
11
8
  map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
12
9
 
13
10
  def self.banner(command, all = false, subcommand = false)
@@ -25,7 +22,7 @@ class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
25
22
  initialize_thorfiles(meth)
26
23
  klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
27
24
  self.class.handle_no_command_error(command, false) if klass.nil?
28
- klass.start(["-h", command].compact, :shell => shell)
25
+ klass.start(["-h", command].compact, shell: shell)
29
26
  else
30
27
  super
31
28
  end
@@ -40,30 +37,42 @@ class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
40
37
  klass, command = Thor::Util.find_class_and_command_by_namespace(meth)
41
38
  self.class.handle_no_command_error(command, false) if klass.nil?
42
39
  args.unshift(command) if command
43
- klass.start(args, :shell => shell)
40
+ klass.start(args, shell: shell)
44
41
  end
45
42
 
46
43
  desc "install NAME", "Install an optionally named Thor file into your system commands"
47
- method_options :as => :string, :relative => :boolean, :force => :boolean
48
- def install(name) # rubocop:disable MethodLength
44
+ method_options as: :string, relative: :boolean, force: :boolean
45
+ def install(name) # rubocop:disable Metrics/MethodLength
49
46
  initialize_thorfiles
50
47
 
51
- # If a directory name is provided as the argument, look for a 'main.thor'
52
- # command in said directory.
53
- begin
54
- if File.directory?(File.expand_path(name))
55
- base = File.join(name, "main.thor")
56
- package = :directory
57
- contents = open(base, &:read)
58
- else
59
- base = name
60
- package = :file
61
- contents = open(name, &:read)
48
+ is_uri = name =~ %r{^https?\://}
49
+
50
+ if is_uri
51
+ base = name
52
+ package = :file
53
+ require "open-uri"
54
+ begin
55
+ contents = URI.open(name, &:read)
56
+ rescue OpenURI::HTTPError
57
+ raise Error, "Error opening URI '#{name}'"
58
+ end
59
+ else
60
+ # If a directory name is provided as the argument, look for a 'main.thor'
61
+ # command in said directory.
62
+ begin
63
+ if File.directory?(File.expand_path(name))
64
+ base = File.join(name, "main.thor")
65
+ package = :directory
66
+ contents = File.open(base, &:read)
67
+ else
68
+ base = name
69
+ package = :file
70
+ require "open-uri"
71
+ contents = URI.open(name, &:read)
72
+ end
73
+ rescue Errno::ENOENT
74
+ raise Error, "Error opening file '#{name}'"
62
75
  end
63
- rescue OpenURI::HTTPError
64
- raise Error, "Error opening URI '#{name}'"
65
- rescue Errno::ENOENT
66
- raise Error, "Error opening file '#{name}'"
67
76
  end
68
77
 
69
78
  say "Your Thorfile contains:"
@@ -84,16 +93,16 @@ class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
84
93
  as = basename if as.empty?
85
94
  end
86
95
 
87
- location = if options[:relative] || name =~ %r{^https?://}
96
+ location = if options[:relative] || is_uri
88
97
  name
89
98
  else
90
99
  File.expand_path(name)
91
100
  end
92
101
 
93
102
  thor_yaml[as] = {
94
- :filename => Digest::MD5.hexdigest(name + as),
95
- :location => location,
96
- :namespaces => Thor::Util.namespaces_in_content(contents, base)
103
+ filename: Digest::SHA256.hexdigest(name + as),
104
+ location: location,
105
+ namespaces: Thor::Util.namespaces_in_content(contents, base)
97
106
  }
98
107
 
99
108
  save_yaml(thor_yaml)
@@ -154,14 +163,14 @@ class Thor::Runner < Thor #:nodoc: # rubocop:disable ClassLength
154
163
  end
155
164
 
156
165
  desc "installed", "List the installed Thor modules and commands"
157
- method_options :internal => :boolean
166
+ method_options internal: :boolean
158
167
  def installed
159
168
  initialize_thorfiles(nil, true)
160
169
  display_klasses(true, options["internal"])
161
170
  end
162
171
 
163
172
  desc "list [SEARCH]", "List the available thor commands (--substring means .*SEARCH)"
164
- method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean
173
+ method_options substring: :boolean, group: :string, all: :boolean, debug: :boolean
165
174
  def list(search = "")
166
175
  initialize_thorfiles
167
176
 
@@ -185,6 +194,7 @@ private
185
194
  def thor_yaml
186
195
  @thor_yaml ||= begin
187
196
  yaml_file = File.join(thor_root, "thor.yml")
197
+ require "yaml"
188
198
  yaml = YAML.load_file(yaml_file) if File.exist?(yaml_file)
189
199
  yaml || {}
190
200
  end
@@ -303,7 +313,7 @@ private
303
313
  say shell.set_color(namespace, :blue, true)
304
314
  say "-" * namespace.size
305
315
 
306
- print_table(list, :truncate => true)
316
+ print_table(list, truncate: true)
307
317
  say
308
318
  end
309
319
  alias_method :display_tasks, :display_commands
@@ -1,8 +1,10 @@
1
+ require_relative "column_printer"
2
+ require_relative "table_printer"
3
+ require_relative "wrapped_printer"
4
+
1
5
  class Thor
2
6
  module Shell
3
7
  class Basic
4
- DEFAULT_TERMINAL_WIDTH = 80
5
-
6
8
  attr_accessor :base
7
9
  attr_reader :padding
8
10
 
@@ -65,15 +67,15 @@ class Thor
65
67
  # Readline.
66
68
  #
67
69
  # ==== Example
68
- # ask("What is your name?")
70
+ # ask("What is your name?")
69
71
  #
70
- # ask("What is the planet furthest from the sun?", :default => "Pluto")
72
+ # ask("What is the planet furthest from the sun?", :default => "Neptune")
71
73
  #
72
- # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
74
+ # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
73
75
  #
74
- # ask("What is your password?", :echo => false)
76
+ # ask("What is your password?", :echo => false)
75
77
  #
76
- # ask("Where should the file be saved?", :path => true)
78
+ # ask("Where should the file be saved?", :path => true)
77
79
  #
78
80
  def ask(statement, *args)
79
81
  options = args.last.is_a?(Hash) ? args.pop : {}
@@ -91,7 +93,7 @@ class Thor
91
93
  # are passed straight to puts (behavior got from Highline).
92
94
  #
93
95
  # ==== Example
94
- # say("I know you knew that.")
96
+ # say("I know you knew that.")
95
97
  #
96
98
  def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
97
99
  return if quiet?
@@ -103,6 +105,23 @@ class Thor
103
105
  stdout.flush
104
106
  end
105
107
 
108
+ # Say (print) an error to the user. If the sentence ends with a whitespace
109
+ # or tab character, a new line is not appended (print + flush). Otherwise
110
+ # are passed straight to puts (behavior got from Highline).
111
+ #
112
+ # ==== Example
113
+ # say_error("error: something went wrong")
114
+ #
115
+ def say_error(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
116
+ return if quiet?
117
+
118
+ buffer = prepare_message(message, *color)
119
+ buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
120
+
121
+ stderr.print(buffer)
122
+ stderr.flush
123
+ end
124
+
106
125
  # Say a status with the given color and appends the message. Since this
107
126
  # method is used frequently by actions, it allows nil or false to be given
108
127
  # in log_status, avoiding the message from being shown. If a Symbol is
@@ -111,30 +130,31 @@ class Thor
111
130
  def say_status(status, message, log_status = true)
112
131
  return if quiet? || log_status == false
113
132
  spaces = " " * (padding + 1)
114
- color = log_status.is_a?(Symbol) ? log_status : :green
115
-
116
133
  status = status.to_s.rjust(12)
134
+ margin = " " * status.length + spaces
135
+
136
+ color = log_status.is_a?(Symbol) ? log_status : :green
117
137
  status = set_color status, color, true if color
118
138
 
119
- buffer = "#{status}#{spaces}#{message}"
120
- buffer = "#{buffer}\n" unless buffer.end_with?("\n")
139
+ message = message.to_s.chomp.gsub(/(?<!\A)^/, margin)
140
+ buffer = "#{status}#{spaces}#{message}\n"
121
141
 
122
142
  stdout.print(buffer)
123
143
  stdout.flush
124
144
  end
125
145
 
126
- # Make a question the to user and returns true if the user replies "y" or
146
+ # Asks the user a question and returns true if the user replies "y" or
127
147
  # "yes".
128
148
  #
129
149
  def yes?(statement, color = nil)
130
- !!(ask(statement, color, :add_to_history => false) =~ is?(:yes))
150
+ !!(ask(statement, color, add_to_history: false) =~ is?(:yes))
131
151
  end
132
152
 
133
- # Make a question the to user and returns true if the user replies "n" or
153
+ # Asks the user a question and returns true if the user replies "n" or
134
154
  # "no".
135
155
  #
136
156
  def no?(statement, color = nil)
137
- !!(ask(statement, color, :add_to_history => false) =~ is?(:no))
157
+ !!(ask(statement, color, add_to_history: false) =~ is?(:no))
138
158
  end
139
159
 
140
160
  # Prints values in columns
@@ -143,16 +163,8 @@ class Thor
143
163
  # Array[String, String, ...]
144
164
  #
145
165
  def print_in_columns(array)
146
- return if array.empty?
147
- colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2
148
- array.each_with_index do |value, index|
149
- # Don't output trailing spaces when printing the last column
150
- if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
151
- stdout.puts value
152
- else
153
- stdout.printf("%-#{colwidth}s", value)
154
- end
155
- end
166
+ printer = ColumnPrinter.new(stdout)
167
+ printer.print(array)
156
168
  end
157
169
 
158
170
  # Prints a table.
@@ -163,58 +175,11 @@ class Thor
163
175
  # ==== Options
164
176
  # indent<Integer>:: Indent the first column by indent value.
165
177
  # colwidth<Integer>:: Force the first column to colwidth spaces wide.
178
+ # borders<Boolean>:: Adds ascii borders.
166
179
  #
167
- def print_table(array, options = {}) # rubocop:disable MethodLength
168
- return if array.empty?
169
-
170
- formats = []
171
- indent = options[:indent].to_i
172
- colwidth = options[:colwidth]
173
- options[:truncate] = terminal_width if options[:truncate] == true
174
-
175
- formats << "%-#{colwidth + 2}s".dup if colwidth
176
- start = colwidth ? 1 : 0
177
-
178
- colcount = array.max { |a, b| a.size <=> b.size }.size
179
-
180
- maximas = []
181
-
182
- start.upto(colcount - 1) do |index|
183
- maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max
184
- maximas << maxima
185
- formats << if index == colcount - 1
186
- # Don't output 2 trailing spaces when printing the last column
187
- "%-s".dup
188
- else
189
- "%-#{maxima + 2}s".dup
190
- end
191
- end
192
-
193
- formats[0] = formats[0].insert(0, " " * indent)
194
- formats << "%s"
195
-
196
- array.each do |row|
197
- sentence = "".dup
198
-
199
- row.each_with_index do |column, index|
200
- maxima = maximas[index]
201
-
202
- f = if column.is_a?(Numeric)
203
- if index == row.size - 1
204
- # Don't output 2 trailing spaces when printing the last column
205
- "%#{maxima}s"
206
- else
207
- "%#{maxima}s "
208
- end
209
- else
210
- formats[index]
211
- end
212
- sentence << f % column.to_s
213
- end
214
-
215
- sentence = truncate(sentence, options[:truncate]) if options[:truncate]
216
- stdout.puts sentence
217
- end
180
+ def print_table(array, options = {}) # rubocop:disable Metrics/MethodLength
181
+ printer = TablePrinter.new(stdout, options)
182
+ printer.print(array)
218
183
  end
219
184
 
220
185
  # Prints a long string, word-wrapping the text to the current width of the
@@ -227,33 +192,8 @@ class Thor
227
192
  # indent<Integer>:: Indent each line of the printed paragraph by indent value.
228
193
  #
229
194
  def print_wrapped(message, options = {})
230
- indent = options[:indent] || 0
231
- width = terminal_width - indent
232
- paras = message.split("\n\n")
233
-
234
- paras.map! do |unwrapped|
235
- words = unwrapped.split(" ")
236
- counter = words.first.length
237
- words.inject do |memo, word|
238
- word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
239
- counter = 0 if word.include? "\n"
240
- if (counter + word.length + 1) < width
241
- memo = "#{memo} #{word}"
242
- counter += (word.length + 1)
243
- else
244
- memo = "#{memo}\n#{word}"
245
- counter = word.length
246
- end
247
- memo
248
- end
249
- end.compact!
250
-
251
- paras.each do |para|
252
- para.split("\n").each do |line|
253
- stdout.puts line.insert(0, " " * indent)
254
- end
255
- stdout.puts unless para == paras.last
256
- end
195
+ printer = WrappedPrinter.new(stdout, options)
196
+ printer.print(message)
257
197
  end
258
198
 
259
199
  # Deals with file collision and returns true if the file should be
@@ -271,7 +211,7 @@ class Thor
271
211
  loop do
272
212
  answer = ask(
273
213
  %[Overwrite #{destination}? (enter "h" for help) #{options}],
274
- :add_to_history => false
214
+ add_to_history: false
275
215
  )
276
216
 
277
217
  case answer
@@ -298,24 +238,11 @@ class Thor
298
238
 
299
239
  say "Please specify merge tool to `THOR_MERGE` env."
300
240
  else
301
- say file_collision_help
241
+ say file_collision_help(block_given?)
302
242
  end
303
243
  end
304
244
  end
305
245
 
306
- # This code was copied from Rake, available under MIT-LICENSE
307
- # Copyright (c) 2003, 2004 Jim Weirich
308
- def terminal_width
309
- result = if ENV["THOR_COLUMNS"]
310
- ENV["THOR_COLUMNS"].to_i
311
- else
312
- unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
313
- end
314
- result < 10 ? DEFAULT_TERMINAL_WIDTH : result
315
- rescue
316
- DEFAULT_TERMINAL_WIDTH
317
- end
318
-
319
246
  # Called if something goes wrong during the execution. This is used by Thor
320
247
  # internally and should not be used inside your scripts. If something went
321
248
  # wrong, you can always raise an exception. If you raise a Thor::Error, it
@@ -366,23 +293,28 @@ class Thor
366
293
  end
367
294
  end
368
295
 
369
- def file_collision_help #:nodoc:
370
- <<-HELP
296
+ def file_collision_help(block_given) #:nodoc:
297
+ help = <<-HELP
371
298
  Y - yes, overwrite
372
299
  n - no, do not overwrite
373
300
  a - all, overwrite this and all others
374
301
  q - quit, abort
375
- d - diff, show the differences between the old and the new
376
302
  h - help, show this help
377
- m - merge, run merge tool
378
303
  HELP
304
+ if block_given
305
+ help << <<-HELP
306
+ d - diff, show the differences between the old and the new
307
+ m - merge, run merge tool
308
+ HELP
309
+ end
310
+ help
379
311
  end
380
312
 
381
313
  def show_diff(destination, content) #:nodoc:
382
314
  diff_cmd = ENV["THOR_DIFF"] || ENV["RAILS_DIFF"] || "diff -u"
383
315
 
384
316
  require "tempfile"
385
- Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
317
+ Tempfile.open(File.basename(destination), File.dirname(destination), binmode: true) do |temp|
386
318
  temp.write content
387
319
  temp.rewind
388
320
  system %(#{diff_cmd} "#{destination}" "#{temp.path}")
@@ -393,46 +325,8 @@ class Thor
393
325
  mute? || (base && base.options[:quiet])
394
326
  end
395
327
 
396
- # Calculate the dynamic width of the terminal
397
- def dynamic_width
398
- @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
399
- end
400
-
401
- def dynamic_width_stty
402
- `stty size 2>/dev/null`.split[1].to_i
403
- end
404
-
405
- def dynamic_width_tput
406
- `tput cols 2>/dev/null`.to_i
407
- end
408
-
409
328
  def unix?
410
- RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris|irix|hpux)/i
411
- end
412
-
413
- def truncate(string, width)
414
- as_unicode do
415
- chars = string.chars.to_a
416
- if chars.length <= width
417
- chars.join
418
- else
419
- chars[0, width - 3].join + "..."
420
- end
421
- end
422
- end
423
-
424
- if "".respond_to?(:encode)
425
- def as_unicode
426
- yield
427
- end
428
- else
429
- def as_unicode
430
- old = $KCODE
431
- $KCODE = "U"
432
- yield
433
- ensure
434
- $KCODE = old
435
- end
329
+ Terminal.unix?
436
330
  end
437
331
 
438
332
  def ask_simply(statement, color, options)
@@ -478,16 +372,12 @@ class Thor
478
372
  Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp|
479
373
  temp.write content
480
374
  temp.rewind
481
- system %(#{merge_tool} "#{temp.path}" "#{destination}")
375
+ system(merge_tool, temp.path, destination)
482
376
  end
483
377
  end
484
378
 
485
379
  def merge_tool #:nodoc:
486
- @merge_tool ||= ENV["THOR_MERGE"] || git_merge_tool
487
- end
488
-
489
- def git_merge_tool #:nodoc:
490
- `git config merge.tool`.rstrip rescue ""
380
+ @merge_tool ||= ENV["THOR_MERGE"] || "git difftool --no-index"
491
381
  end
492
382
  end
493
383
  end
@@ -1,4 +1,5 @@
1
1
  require_relative "basic"
2
+ require_relative "lcs_diff"
2
3
 
3
4
  class Thor
4
5
  module Shell
@@ -6,6 +7,8 @@ class Thor
6
7
  # Thor::Shell::Basic to see all available methods.
7
8
  #
8
9
  class Color < Basic
10
+ include LCSDiff
11
+
9
12
  # Embed in a String to clear all previous ANSI sequences.
10
13
  CLEAR = "\e[0m"
11
14
  # The start of an ANSI bold sequence.
@@ -105,52 +108,7 @@ class Thor
105
108
  end
106
109
 
107
110
  def are_colors_disabled?
108
- !ENV['NO_COLOR'].nil?
109
- end
110
-
111
- # Overwrite show_diff to show diff with colors if Diff::LCS is
112
- # available.
113
- #
114
- def show_diff(destination, content) #:nodoc:
115
- if diff_lcs_loaded? && ENV["THOR_DIFF"].nil? && ENV["RAILS_DIFF"].nil?
116
- actual = File.binread(destination).to_s.split("\n")
117
- content = content.to_s.split("\n")
118
-
119
- Diff::LCS.sdiff(actual, content).each do |diff|
120
- output_diff_line(diff)
121
- end
122
- else
123
- super
124
- end
125
- end
126
-
127
- def output_diff_line(diff) #:nodoc:
128
- case diff.action
129
- when "-"
130
- say "- #{diff.old_element.chomp}", :red, true
131
- when "+"
132
- say "+ #{diff.new_element.chomp}", :green, true
133
- when "!"
134
- say "- #{diff.old_element.chomp}", :red, true
135
- say "+ #{diff.new_element.chomp}", :green, true
136
- else
137
- say " #{diff.old_element.chomp}", nil, true
138
- end
139
- end
140
-
141
- # Check if Diff::LCS is loaded. If it is, use it to create pretty output
142
- # for diff.
143
- #
144
- def diff_lcs_loaded? #:nodoc:
145
- return true if defined?(Diff::LCS)
146
- return @diff_lcs_loaded unless @diff_lcs_loaded.nil?
147
-
148
- @diff_lcs_loaded = begin
149
- require "diff/lcs"
150
- true
151
- rescue LoadError
152
- false
153
- end
111
+ !ENV["NO_COLOR"].nil? && !ENV["NO_COLOR"].empty?
154
112
  end
155
113
  end
156
114
  end
@@ -0,0 +1,29 @@
1
+ require_relative "terminal"
2
+
3
+ class Thor
4
+ module Shell
5
+ class ColumnPrinter
6
+ attr_reader :stdout, :options
7
+
8
+ def initialize(stdout, options = {})
9
+ @stdout = stdout
10
+ @options = options
11
+ @indent = options[:indent].to_i
12
+ end
13
+
14
+ def print(array)
15
+ return if array.empty?
16
+ colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2
17
+ array.each_with_index do |value, index|
18
+ # Don't output trailing spaces when printing the last column
19
+ if ((((index + 1) % (Terminal.terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
20
+ stdout.puts value
21
+ else
22
+ stdout.printf("%-#{colwidth}s", value)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+
@@ -1,4 +1,5 @@
1
1
  require_relative "basic"
2
+ require_relative "lcs_diff"
2
3
 
3
4
  class Thor
4
5
  module Shell
@@ -6,6 +7,8 @@ class Thor
6
7
  # Thor::Shell::Basic to see all available methods.
7
8
  #
8
9
  class HTML < Basic
10
+ include LCSDiff
11
+
9
12
  # The start of an HTML bold sequence.
10
13
  BOLD = "font-weight: bold"
11
14
 
@@ -64,7 +67,7 @@ class Thor
64
67
  # Ask something to the user and receives a response.
65
68
  #
66
69
  # ==== Example
67
- # ask("What is your name?")
70
+ # ask("What is your name?")
68
71
  #
69
72
  # TODO: Implement #ask for Thor::Shell::HTML
70
73
  def ask(statement, color = nil)
@@ -76,51 +79,6 @@ class Thor
76
79
  def can_display_colors?
77
80
  true
78
81
  end
79
-
80
- # Overwrite show_diff to show diff with colors if Diff::LCS is
81
- # available.
82
- #
83
- def show_diff(destination, content) #:nodoc:
84
- if diff_lcs_loaded? && ENV["THOR_DIFF"].nil? && ENV["RAILS_DIFF"].nil?
85
- actual = File.binread(destination).to_s.split("\n")
86
- content = content.to_s.split("\n")
87
-
88
- Diff::LCS.sdiff(actual, content).each do |diff|
89
- output_diff_line(diff)
90
- end
91
- else
92
- super
93
- end
94
- end
95
-
96
- def output_diff_line(diff) #:nodoc:
97
- case diff.action
98
- when "-"
99
- say "- #{diff.old_element.chomp}", :red, true
100
- when "+"
101
- say "+ #{diff.new_element.chomp}", :green, true
102
- when "!"
103
- say "- #{diff.old_element.chomp}", :red, true
104
- say "+ #{diff.new_element.chomp}", :green, true
105
- else
106
- say " #{diff.old_element.chomp}", nil, true
107
- end
108
- end
109
-
110
- # Check if Diff::LCS is loaded. If it is, use it to create pretty output
111
- # for diff.
112
- #
113
- def diff_lcs_loaded? #:nodoc:
114
- return true if defined?(Diff::LCS)
115
- return @diff_lcs_loaded unless @diff_lcs_loaded.nil?
116
-
117
- @diff_lcs_loaded = begin
118
- require "diff/lcs"
119
- true
120
- rescue LoadError
121
- false
122
- end
123
- end
124
82
  end
125
83
  end
126
84
  end