irt 1.1.1

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.
@@ -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