irt 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +26 -0
- data/LICENSE +20 -0
- data/README.markdown +589 -0
- data/Rakefile +60 -0
- data/VERSION +1 -0
- data/bin/irt +101 -0
- data/bin/irt_irb +4 -0
- data/bin/irt_rails2 +6 -0
- data/goodies/nano/README +6 -0
- data/goodies/nano/irt.nanorc +86 -0
- data/goodies/vi/README +5 -0
- data/irt.gemspec +29 -0
- data/irtrc +48 -0
- data/lib/irt.rb +143 -0
- data/lib/irt/commands/core.rb +52 -0
- data/lib/irt/commands/help.rb +111 -0
- data/lib/irt/commands/log.rb +52 -0
- data/lib/irt/commands/ri.rb +59 -0
- data/lib/irt/commands/system.rb +102 -0
- data/lib/irt/commands/test.rb +60 -0
- data/lib/irt/differ.rb +87 -0
- data/lib/irt/directives.rb +28 -0
- data/lib/irt/directives/test.rb +84 -0
- data/lib/irt/extensions/irb.rb +45 -0
- data/lib/irt/extensions/irb/commands.rb +42 -0
- data/lib/irt/extensions/irb/context.rb +147 -0
- data/lib/irt/extensions/kernel.rb +18 -0
- data/lib/irt/extensions/method.rb +36 -0
- data/lib/irt/extensions/object.rb +7 -0
- data/lib/irt/hunks.rb +111 -0
- data/lib/irt/init.rb +1 -0
- data/lib/irt/log.rb +94 -0
- data/lib/irt/session.rb +59 -0
- metadata +167 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
module IRT
|
2
|
+
module Commands
|
3
|
+
module Core
|
4
|
+
|
5
|
+
def irt(obj=nil)
|
6
|
+
irt_mode = context.irt_mode
|
7
|
+
to_mode = case obj
|
8
|
+
when nil
|
9
|
+
:interactive
|
10
|
+
when Binding
|
11
|
+
:binding
|
12
|
+
else
|
13
|
+
:inspect
|
14
|
+
end
|
15
|
+
raise IRT::SessionModeError, "You cannot pass binding in #{irt_mode} mode" \
|
16
|
+
if to_mode == :binding && (irt_mode == :binding || caller[0].match(/^\(/))
|
17
|
+
raise IRT::SessionModeError, "You cannot open another interactive session in #{irt_mode} mode" \
|
18
|
+
if to_mode == :interactive && irt_mode != :file
|
19
|
+
IRT::Session.enter to_mode, obj
|
20
|
+
end
|
21
|
+
alias_method :open_session, :irt # legacy method
|
22
|
+
|
23
|
+
%w[p y pp ap].each do |m|
|
24
|
+
define_method(m) do |*args|
|
25
|
+
args = [context.last_value] if args.empty?
|
26
|
+
super *args
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def vdiff(a,b)
|
31
|
+
puts IRT::Differ.new(a,b, :value, {:a_marker => 'a',
|
32
|
+
:b_marker => 'b',
|
33
|
+
:a_label => '',
|
34
|
+
:b_label => ''}).output
|
35
|
+
end
|
36
|
+
alias_method :vd, :vdiff
|
37
|
+
|
38
|
+
# rerun the same shell command
|
39
|
+
def rerun
|
40
|
+
ensure_session
|
41
|
+
IRB.irb_at_exit
|
42
|
+
str = "Rerunning: `#{ENV['IRT_COMMAND']}`"
|
43
|
+
puts
|
44
|
+
puts " #{str} ".error_color.bold.reversed.or("*** #{str} ***")
|
45
|
+
puts
|
46
|
+
exec ENV["IRT_COMMAND"]
|
47
|
+
end
|
48
|
+
alias_method :rr, :rerun
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module IRT
|
2
|
+
module Commands
|
3
|
+
module Help
|
4
|
+
|
5
|
+
def irt_help
|
6
|
+
ensure_session
|
7
|
+
puts %(
|
8
|
+
#{" NOTICE ".log_color.reversed.bold}
|
9
|
+
- The #{"Commands".interactive_color.bold} are methods generally available in any IRT session
|
10
|
+
- The #{"Directives".file_color.bold} are methods available in any file but not in IRT sessions
|
11
|
+
- The #{"Extensions".log_color.bold} are methods available anywhere
|
12
|
+
|
13
|
+
#{" Inspecting Commands ".interactive_color.reversed.bold}
|
14
|
+
irt object Opens an inspecting session into object
|
15
|
+
vdiff|vd obj_a, obj_b Prints the visual diff of the yaml dump of 2 objects
|
16
|
+
cat args Similar to system cat
|
17
|
+
ls args Similar to system ls
|
18
|
+
|
19
|
+
#{" Log Commands ".interactive_color.reversed.bold}
|
20
|
+
log|l [limit] Prints limit or 'tail_size' lines of the virtual log
|
21
|
+
full_log|ll Prints all the lines in the virtual log
|
22
|
+
print_lines|pl Prints the last lines of the current session
|
23
|
+
without numbers (for easy copying)
|
24
|
+
print_all_lines|pll Like print_line but prints all the sessions lines
|
25
|
+
|
26
|
+
#{" In Place Editing Commands ".interactive_color.reversed.bold}
|
27
|
+
(<editor> can be 'vi', 'nano|nn', 'edit|ed')
|
28
|
+
<editor> Uses <editor> to open the current evalued file at
|
29
|
+
the current evalued line for in place edit
|
30
|
+
<editor> file[, line] Uses <editor> to open file [at line] for in place
|
31
|
+
editing
|
32
|
+
<editor> hash Uses <editor> to open hash[:file] at the hash[:line]
|
33
|
+
<editor> array Uses <editor> to open array[0] at the array[1] line
|
34
|
+
<editor> traceline Uses <editor> to open the file at line in traceline
|
35
|
+
e.g.: nn "from /path/to/file.rb:34:in 'any_method'"
|
36
|
+
nn "a_gem (1.2.3) lib/file.rb:13:in 'a_meth'"
|
37
|
+
<editor> n Uses <editor> to open the backtraced file [n] at
|
38
|
+
the backtraced line
|
39
|
+
|
40
|
+
#{" Copy-Edit Commands ".interactive_color.reversed.bold + " (use copy_to_clipboard_command)".interactive_color.bold}
|
41
|
+
copy_lines|cl Copy the last session lines
|
42
|
+
copy_all_lines|cll Copy the lines of all the sessions
|
43
|
+
cnano|cnn Like nano, but copy the last session lines first
|
44
|
+
cvi Like vi, but copy the last session lines first
|
45
|
+
cedit|ced Like edit, but copy the last session lines first
|
46
|
+
|
47
|
+
#{" Test Commands ".interactive_color.reversed.bold + " (only available in interactive sessions)".interactive_color.bold}
|
48
|
+
add_desc|dd desc Adds a description for the test in the log
|
49
|
+
add_test|tt Adds a test in the log, checking the last value (_)
|
50
|
+
by automatically choosing the :_eql?, or :_yaml_eql?
|
51
|
+
method, depending on the type of the last value (_)
|
52
|
+
add_test|tt desc Like add_test but adds a 'desc' directive first'
|
53
|
+
save_as|sa path Saves the current irt file as path and runs it
|
54
|
+
|
55
|
+
#{" FileUtils Commands ".interactive_color.reversed.bold}
|
56
|
+
All the FileUtils methods are availabe as IRT Commands
|
57
|
+
(e.g. pwd, touch, mkdir, mv, cp, rm, rm_rf, compare_files, ...)
|
58
|
+
|
59
|
+
#{" Enhanced Commands ".interactive_color.reversed.bold}
|
60
|
+
p, pp, ap, y When invoked with no arguments print the last_value
|
61
|
+
(e.g. just type 'y' instead 'y _')
|
62
|
+
|
63
|
+
#{" Documentation Commands ".interactive_color.reversed.bold}
|
64
|
+
ri to_search Search the ri doc for to_search (no quotes needed)
|
65
|
+
ri obj.any_method Search the method.owner ri doc for of any_method
|
66
|
+
(no quotes needed, and completion available)
|
67
|
+
e.g.: ri "".eql? #=> ri doc for String#eql?
|
68
|
+
ri [].eql? #=> ri doc for Array#eql?
|
69
|
+
ri n Search the ri doc for the method n in a multiple
|
70
|
+
choices list
|
71
|
+
|
72
|
+
#{" Misc Commands ".interactive_color.reversed.bold}
|
73
|
+
x|q Aliases for exit (from the current session)
|
74
|
+
xx|qq Aliases for abort (abort the irt process)
|
75
|
+
status|ss Prints the session status line
|
76
|
+
rerun|rr Reruns the same file
|
77
|
+
irt_help|hh Shows this screen
|
78
|
+
|
79
|
+
#{" Session Directives ".file_color.reversed.bold}
|
80
|
+
irt Opens an interactive session which retains the
|
81
|
+
current variables and the last value (_)
|
82
|
+
irt binding Opens a binding session at the line of the call
|
83
|
+
|
84
|
+
#{" Test Directives ".file_color.reversed.bold + " (auto added by the Test Commands)".file_color.bold}
|
85
|
+
desc description Adds a description to the next test
|
86
|
+
_eql? val Runs a test checking _ == val
|
87
|
+
_yaml_eql? yaml_dump Runs a test checking y _ == yaml_dump
|
88
|
+
|
89
|
+
#{" Helper Directives ".file_color.reversed.bold}
|
90
|
+
insert_file file Evaluates file as it were inserted at that line
|
91
|
+
eval_file Alias for eval_file
|
92
|
+
irt_at_exit block Ensures execution of block at exit (useful for
|
93
|
+
cleanup of test env)
|
94
|
+
|
95
|
+
#{" Extensions ".log_color.reversed.bold}
|
96
|
+
Kernel#capture block Executes block and returns a string containing the
|
97
|
+
captured stdout
|
98
|
+
Object#own_methods Returns the methods implemented by the receiver
|
99
|
+
itself (not inherited)
|
100
|
+
Method#location When possible, it returns file and line where the
|
101
|
+
method is defined. It is uitable to be passed to the
|
102
|
+
in place editing commands.
|
103
|
+
Method#info Returns useful info about the method. It is suitable
|
104
|
+
to be passed to the in place editing commands.
|
105
|
+
)
|
106
|
+
end
|
107
|
+
alias_method :hh, :irt_help
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module IRT
|
2
|
+
module Commands
|
3
|
+
module Log
|
4
|
+
|
5
|
+
def log(limit=nil)
|
6
|
+
ensure_session
|
7
|
+
IRT.log.print limit || IRT.log.tail_size
|
8
|
+
IRT.log.print_status
|
9
|
+
end
|
10
|
+
alias_method :l, :log
|
11
|
+
|
12
|
+
def full_log
|
13
|
+
ensure_session
|
14
|
+
IRT.log.print
|
15
|
+
IRT.log.print_status
|
16
|
+
end
|
17
|
+
alias_method :ll, :full_log
|
18
|
+
|
19
|
+
def status
|
20
|
+
ensure_session
|
21
|
+
IRT.log.print_status
|
22
|
+
end
|
23
|
+
alias_method :ss, :status
|
24
|
+
|
25
|
+
def print_lines
|
26
|
+
ensure_session
|
27
|
+
lines_str = IRT.log.last.lines_str
|
28
|
+
return if lines_str.empty?
|
29
|
+
puts
|
30
|
+
puts lines_str
|
31
|
+
puts
|
32
|
+
end
|
33
|
+
alias_method :pl, :print_lines
|
34
|
+
|
35
|
+
def print_all_lines
|
36
|
+
ensure_session
|
37
|
+
lines = []
|
38
|
+
IRT.log.reject{|h| h.class == IRT::Log::FileHunk }.each do |h|
|
39
|
+
ls = h.lines_str
|
40
|
+
lines << ls unless ls.empty?
|
41
|
+
end
|
42
|
+
unless lines.empty?
|
43
|
+
puts
|
44
|
+
puts lines.join("\n\n")
|
45
|
+
puts
|
46
|
+
end
|
47
|
+
end
|
48
|
+
alias_method :pll, :print_all_lines
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module IRT
|
2
|
+
module Commands
|
3
|
+
module Ri
|
4
|
+
|
5
|
+
@@choices_map = {}
|
6
|
+
|
7
|
+
def self.reset_choices_map
|
8
|
+
@@choices_map = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def ri(arg)
|
12
|
+
ensure_session
|
13
|
+
raise IRT::NotImplementedError, "No available ri_command_format for this system." unless IRT.ri_command_format
|
14
|
+
case
|
15
|
+
when arg.nil?, arg.empty?
|
16
|
+
return puts('nil')
|
17
|
+
when arg.match(/^\d+$/)
|
18
|
+
if @@choices_map.key?(arg)
|
19
|
+
to_search = @@choices_map[arg]
|
20
|
+
else
|
21
|
+
raise IndexError, "No such method index -- [#{arg}]"
|
22
|
+
end
|
23
|
+
else
|
24
|
+
segm = arg.split('.')
|
25
|
+
to_search = segm.pop
|
26
|
+
unless segm.empty?
|
27
|
+
begin
|
28
|
+
meth = eval "#{segm.join('.')}.method(:#{to_search})", IRB.CurrentContext.workspace.binding
|
29
|
+
to_search = "#{meth.owner.name}##{meth.name}"
|
30
|
+
rescue
|
31
|
+
raise NoMethodError, %(undefined method "#{to_search}" for "#{segm.join('.')}")
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
process_ri to_search
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def process_ri(to_search)
|
41
|
+
ri = `#{sprintf(IRT.ri_command_format, to_search)}`
|
42
|
+
if m = ri.match(/^(-+.*Multiple choices:.*\n\n)(.+)/m)
|
43
|
+
output, methods = m.captures
|
44
|
+
IRT::Commands::Ri.reset_choices_map
|
45
|
+
fmt = "%+7s %s\n"
|
46
|
+
methods.gsub(/\s+/, '').split(',').each_with_index do |m, i|
|
47
|
+
@@choices_map[(i+1).to_s] = m
|
48
|
+
output << sprintf( fmt, "#{i+1}", m )
|
49
|
+
end
|
50
|
+
output << "\n"
|
51
|
+
else
|
52
|
+
output = ri
|
53
|
+
end
|
54
|
+
puts output
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module IRT
|
2
|
+
module Commands
|
3
|
+
module System
|
4
|
+
|
5
|
+
def cat(*args)
|
6
|
+
ensure_session
|
7
|
+
return system "cat #{context.file_line_pointers.first}" if args.empty?
|
8
|
+
system "cat #{args * ' '}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def ls(*args)
|
12
|
+
ensure_session
|
13
|
+
args = %w[.] if args.empty?
|
14
|
+
system "ls #{args * ' '}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def copy_lines
|
18
|
+
ensure_session
|
19
|
+
copy_to_clipboard :print_lines
|
20
|
+
end
|
21
|
+
alias_method :cl, :copy_lines
|
22
|
+
|
23
|
+
def copy_all_lines
|
24
|
+
ensure_session
|
25
|
+
copy_to_clipboard :print_all_lines
|
26
|
+
end
|
27
|
+
alias_method :cll, :copy_all_lines
|
28
|
+
|
29
|
+
%w[vi nano edit].each do |n|
|
30
|
+
eval <<-EOE, binding, __FILE__, __LINE__+1
|
31
|
+
def #{n}(*args)
|
32
|
+
ensure_session
|
33
|
+
run_editor(:#{n}, *args)
|
34
|
+
end
|
35
|
+
EOE
|
36
|
+
eval <<-EOE, binding, __FILE__, __LINE__+1
|
37
|
+
def c#{n}(*args)
|
38
|
+
ensure_session
|
39
|
+
copy_lines
|
40
|
+
#{n} *args
|
41
|
+
end
|
42
|
+
EOE
|
43
|
+
end
|
44
|
+
alias_method :nn, :nano
|
45
|
+
alias_method :ed, :edit
|
46
|
+
alias_method :cnn, :cnano
|
47
|
+
alias_method :ced, :cedit
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def run_editor(cmd, *args)
|
52
|
+
cmd_format = IRT.send("#{cmd}_command_format".to_sym)
|
53
|
+
raise IRT::NotImplementedError, "#{cmd}_command_format missing" unless cmd_format
|
54
|
+
arg = args.first if args.size == 1
|
55
|
+
file, line = case
|
56
|
+
when args.empty?
|
57
|
+
context.file_line_pointers
|
58
|
+
when arg.is_a?(Integer)
|
59
|
+
if context.backtrace_map.key?(arg)
|
60
|
+
context.backtrace_map[arg]
|
61
|
+
else
|
62
|
+
raise IRT::IndexError, "No such backtrace index -- [#{arg}]"
|
63
|
+
return
|
64
|
+
end
|
65
|
+
when arg.is_a?(Array)
|
66
|
+
arg
|
67
|
+
when arg.is_a?(Hash)
|
68
|
+
[arg[:file], arg[:line]]
|
69
|
+
when arg.is_a?(String) && m = arg.match(/(?:([\w]+) \(([\w.]+)\))? ?([+\w\/\n.-]+):(\d+)/m)
|
70
|
+
gem, vers, f, l = m.captures
|
71
|
+
if gem
|
72
|
+
Gem.path.each do |p|
|
73
|
+
gp = File.join(p, 'gems', "#{gem}-#{vers}", f)
|
74
|
+
break [gp, l] if File.exist?(gp)
|
75
|
+
end
|
76
|
+
else
|
77
|
+
[f.gsub("\n", ''), l]
|
78
|
+
end
|
79
|
+
else
|
80
|
+
args
|
81
|
+
end
|
82
|
+
system sprintf(cmd_format, file, line)
|
83
|
+
end
|
84
|
+
|
85
|
+
def copy_to_clipboard(cmd)
|
86
|
+
raise IRT::NotImplementedError, "No known copy_to_clipboard_command for this system." \
|
87
|
+
unless IRT.copy_to_clipboard_command
|
88
|
+
lines_str = capture { send(cmd) }
|
89
|
+
return unless lines_str.match(/\w/m)
|
90
|
+
begin
|
91
|
+
IO.popen(IRT.copy_to_clipboard_command, 'w') do |io|
|
92
|
+
io.puts lines_str.strip
|
93
|
+
end
|
94
|
+
print lines_str
|
95
|
+
rescue Exception
|
96
|
+
raise IRT::NotImplementedError, "This system does not appear to support the \`#{IRT.copy_to_clipboard_command}\` command."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module IRT
|
2
|
+
module Commands
|
3
|
+
module Test
|
4
|
+
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def add_desc(description)
|
8
|
+
mode = context.irt_mode
|
9
|
+
raise IRT::SessionModeError, "You cannot add a test description in #{mode} mode." unless mode == :interactive
|
10
|
+
desc_str = %(desc "#{description}")
|
11
|
+
context.current_line = desc_str
|
12
|
+
puts
|
13
|
+
puts desc_str.interactive_color
|
14
|
+
puts
|
15
|
+
end
|
16
|
+
alias_method :dd, :add_desc
|
17
|
+
|
18
|
+
def add_test(description='')
|
19
|
+
mode = context.irt_mode
|
20
|
+
raise IRT::SessionModeError, "You cannot add a test in #{mode} mode." unless mode == :interactive
|
21
|
+
last_value = context.last_value
|
22
|
+
begin
|
23
|
+
evaled = context.workspace.evaluate(self, last_value.inspect)
|
24
|
+
rescue Exception
|
25
|
+
end
|
26
|
+
# the eval of the last_value.inspect == the last_value
|
27
|
+
test_str = if evaled == last_value
|
28
|
+
# same as _? but easier to read for multiline strings
|
29
|
+
if last_value.is_a?(String) && last_value.match(/\n/)
|
30
|
+
str = last_value.split("\n").map{|l| l.inspect.sub(/^"(.*)"$/,'\1') }.join("\n")
|
31
|
+
last_value.match(/\n$/) ? "_eql? <<EOS\n#{str}\nEOS" : "_eql? %(#{str})"
|
32
|
+
else
|
33
|
+
"_eql?( #{last_value.inspect} )"
|
34
|
+
end
|
35
|
+
else # need YAML
|
36
|
+
"_yaml_eql? %(#{IRT.yaml_dump(last_value)})"
|
37
|
+
end
|
38
|
+
desc_str = description.empty? ? '' : %(desc "#{description}"\n)
|
39
|
+
str = desc_str + test_str
|
40
|
+
context.current_line = str
|
41
|
+
puts
|
42
|
+
puts str.interactive_color
|
43
|
+
puts
|
44
|
+
end
|
45
|
+
alias_method :tt, :add_test
|
46
|
+
|
47
|
+
def save_as(path)
|
48
|
+
path = File.expand_path(path)
|
49
|
+
if File.exists?(path)
|
50
|
+
return if IRT.prompter.no? %(Do you want to overwrite "#{path}"?), :hint => '[y|<enter=n]', :default => 'n'
|
51
|
+
end
|
52
|
+
cp IRT.irt_file, path
|
53
|
+
ENV['IRT_COMMAND'] = ENV['IRT_COMMAND'].sub(/#{Regexp.quote(IRT.irt_file)}/, path)
|
54
|
+
rerun
|
55
|
+
end
|
56
|
+
alias_method :sa, :save_as
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/irt/differ.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'differ'
|
2
|
+
module IRT
|
3
|
+
class Differ
|
4
|
+
|
5
|
+
def initialize(a, b, kind=:value, options={})
|
6
|
+
if kind == :value
|
7
|
+
a = IRT.yaml_dump a
|
8
|
+
b = IRT.yaml_dump b
|
9
|
+
end
|
10
|
+
@a = a
|
11
|
+
@b = b
|
12
|
+
@options = { :a_label => 'saved',
|
13
|
+
:b_label => 'actual',
|
14
|
+
:a_marker => '~',
|
15
|
+
:b_marker => '!' }.merge options
|
16
|
+
IRT::Differ::Format.options = @options
|
17
|
+
@diff = ::Differ.diff_by_line(@b, @a)
|
18
|
+
end
|
19
|
+
|
20
|
+
def output
|
21
|
+
out = "\n"
|
22
|
+
out << " = same ".reversed.bold.or('***** diff ')
|
23
|
+
out << " #{@options[:a_marker]} #{@options[:a_label]} ".diff_a_color.reversed.bold.
|
24
|
+
or(" (#{@options[:a_marker]} #{@options[:a_label]}) ")
|
25
|
+
out << " #{@options[:b_marker]} #{@options[:b_label]} ".diff_b_color.reversed.bold.
|
26
|
+
or(" (#{@options[:b_marker]} #{@options[:b_label]}) ")
|
27
|
+
out << "\n"
|
28
|
+
diff = @diff.format_as(IRT::Differ::Format)
|
29
|
+
out << diff.sub(/^\n/,'')
|
30
|
+
out << "\n"
|
31
|
+
out
|
32
|
+
end
|
33
|
+
|
34
|
+
module Format
|
35
|
+
extend self
|
36
|
+
|
37
|
+
attr_accessor :options
|
38
|
+
|
39
|
+
def format(change)
|
40
|
+
(change.is_a?(String) && as_same(change)) ||
|
41
|
+
(change.change? && as_change(change)) ||
|
42
|
+
(change.delete? && as_delete(change)) ||
|
43
|
+
(change.insert? && as_insert(change)) ||
|
44
|
+
''
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def process(string, mark='=', color=:null, bold=:null)
|
50
|
+
string.sub(/^\n/,'').split("\n").map do |s|
|
51
|
+
" #{mark} ".send(color).send(bold).reversed.or(" #{mark} ") + ' ' + s.send(color)
|
52
|
+
end.join("\n") + "\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
def as_same(string)
|
56
|
+
process string
|
57
|
+
end
|
58
|
+
|
59
|
+
def as_insert(change)
|
60
|
+
process(change.insert(), options[:b_marker], :diff_b_color, :bold)
|
61
|
+
end
|
62
|
+
|
63
|
+
def as_delete(change)
|
64
|
+
process(change.delete(), options[:a_marker], :diff_a_color, :bold)
|
65
|
+
end
|
66
|
+
|
67
|
+
def as_change(change)
|
68
|
+
as_delete(change) << as_insert(change)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
module Differ
|
76
|
+
class Diff
|
77
|
+
|
78
|
+
def format_as(f)
|
79
|
+
f = Differ.format_for(f)
|
80
|
+
@raw.inject('') do |sum, part|
|
81
|
+
part = f.format(part)
|
82
|
+
sum << part
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|