irt 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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