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,28 @@
1
+ require 'irt/directives/test'
2
+
3
+ module IRT
4
+ module Directives
5
+
6
+ extend self
7
+ extend Test
8
+
9
+ # Evaluate a file as it were inserted at that line
10
+ # a relative file_path is considered to be relative to the including file
11
+ # i.e. '../file_in_the_same_dir.irt'
12
+ def eval_file(file_path)
13
+ parent_context = IRB.CurrentContext
14
+ new_io = IRB::FileInputMethod.new(File.expand_path(file_path, parent_context.io.file_name))
15
+ new_irb = IRB::Irb.new(parent_context.workspace, new_io)
16
+ new_irb.context.irb_name = File.basename(new_io.file_name)
17
+ new_irb.context.irb_path = new_io.file_name
18
+ IRT::Session.eval_input(new_irb.context, :file)
19
+ IRT::Session.exit
20
+ end
21
+ alias_method :insert_file, :eval_file
22
+
23
+ def irt_at_exit(&block)
24
+ IRB.conf[:AT_EXIT] << proc(&block)
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,84 @@
1
+ module IRT
2
+ module Directives
3
+ module Test
4
+ extend self
5
+
6
+ @@tests = 0
7
+ @@oks = 0
8
+ @@diffs = 0
9
+ @@errors = 0
10
+ @@last_desc = nil
11
+
12
+ def desc(description)
13
+ @@last_desc = description
14
+ end
15
+
16
+ def _eql?(saved)
17
+ actual = IRB.CurrentContext.last_value
18
+ run_test(saved, actual, :value)
19
+ end
20
+ alias_method :test_value_eql?, :_eql?
21
+ alias_method :last_value_eql?, :_eql?
22
+
23
+ def _yaml_eql?(saved)
24
+ actual = IRT.yaml_dump(IRB.CurrentContext.last_value)
25
+ run_test(saved, actual, :yaml)
26
+ end
27
+ alias_method :last_yaml_eql?, :_yaml_eql?
28
+ alias_method :test_yaml_eql?, :_yaml_eql?
29
+
30
+ def test_summary #:nodoc:
31
+ return unless @@tests > 0
32
+ if @@tests == @@oks
33
+ str = @@tests == 1 ? " The TEST is OK! " : " All #{@@tests} TESTs are OK! "
34
+ puts str.ok_color.bold
35
+ else
36
+ puts "#{@@tests} TEST#{'s' unless @@tests == 1}: ".bold +
37
+ "#{@@oks} OK#{'s' unless @@oks == 1}, ".ok_color.bold +
38
+ "#{@@diffs} DIFF#{'s' unless @@diffs == 1}, ".diff_color.bold +
39
+ "#{@@errors} ERROR#{'s' unless @@errors == 1}.".error_color.bold
40
+ end
41
+ end
42
+
43
+ def load_helper_files
44
+ return unless IRT.autoload_helper_files
45
+ irt_file_path = Pathname.new($0).realpath
46
+ container_path = Pathname.getwd.parent
47
+ down_path = irt_file_path.relative_path_from container_path
48
+ down_path.dirname.descend do |p|
49
+ helper_path = container_path.join(p, 'irt_helper.rb')
50
+ begin
51
+ require helper_path
52
+ rescue LoadError
53
+ end
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def run_test(saved, actual, kind)
60
+ context = IRB.CurrentContext
61
+ tno = '%3d' % @@tests += 1
62
+ d = @@last_desc || 'Test'
63
+ @@last_desc = nil
64
+ begin
65
+ if saved == actual
66
+ @@oks += 1
67
+ puts "#{tno}. OK!".ok_color.bold + " #{d}".ok_color
68
+ else
69
+ @@diffs += 1
70
+ puts "#{tno}. DIFFS!".diff_color.bold + %( #{d}\n ).diff_color +
71
+ %( at #{context.irb_path}: #{context.last_line_no} ).file_color.reversed.bold
72
+ puts IRT.differ.new(saved, actual, kind).output
73
+ IRT::Session.enter(:interactive) if IRT.irt_on_diffs
74
+ end
75
+ rescue Exception
76
+ @@errors += 1
77
+ puts "#{tno}. ERROR! ".error_color.bold + d.error_color
78
+ raise
79
+ end
80
+ end
81
+
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,45 @@
1
+ require 'irb'
2
+ require 'irt/extensions/irb/context'
3
+ require 'irt/extensions/irb/commands'
4
+
5
+ module IRB #:nodoc:
6
+
7
+ class << self
8
+ alias_method :irb_init_config, :init_config
9
+ alias_method :irb_setup, :setup
10
+ end
11
+
12
+ def IRB.setup(ap_path=nil)
13
+ irb_setup(ap_path)
14
+ IRT.init_files
15
+ end
16
+
17
+ def IRB.init_config(ap_path)
18
+ irb_init_config(ap_path)
19
+
20
+ @CONF[:AP_NAME] = 'irt'
21
+ @CONF[:PROMPT][:IRT] = { :PROMPT_I => "%02n >> ",
22
+ :PROMPT_S => ' "> ',
23
+ :PROMPT_C => "%02n ?> ",
24
+ :PROMPT_N => "%02n -> ",
25
+ :RETURN => " => %s\n" }
26
+ @CONF[:PROMPT_MODE] = :IRT
27
+ @CONF[:ECHO] = false
28
+ @CONF[:VERBOSE] = false
29
+ @CONF[:SAVE_HISTORY] = 100
30
+ @CONF[:HISTORY_FILE] = File.expand_path '~/.irt-history'
31
+ @CONF[:AT_EXIT] ||= []
32
+ @CONF[:AT_EXIT] << proc{ IRT::Session.enter(:interactive) if IRB.CurrentContext.irt_mode == :file } if !!ENV['IRT_INTERACTIVE_EOF']
33
+ @CONF[:AT_EXIT] << proc{ IRT::Directives.test_summary }
34
+ @CONF[:AT_EXIT] << proc{ print "\e[0m" if Colorer.color? } # reset colors
35
+ @CONF[:RC_NAME_GENERATOR] = proc {|rc| File.expand_path '~/.irtrc' }
36
+
37
+ IRT.init
38
+ end
39
+
40
+ def IRB.irb_exit(irb, ret)
41
+ IRT::Session.exit
42
+ throw :IRB_EXIT, ret
43
+ end
44
+
45
+ end
@@ -0,0 +1,42 @@
1
+ require 'irt/commands/log'
2
+ require 'irt/commands/test'
3
+ require 'irt/commands/system'
4
+ require 'irt/commands/core'
5
+ require 'irt/commands/help'
6
+ require 'irt/commands/ri'
7
+ require 'fileutils'
8
+
9
+ module IRB
10
+ module ExtendCommandBundle #:nodoc:
11
+
12
+ include IRT::Commands::Log
13
+ include IRT::Commands::Test
14
+ include IRT::Commands::System
15
+ include IRT::Commands::Core
16
+ include IRT::Commands::Help
17
+ include IRT::Commands::Ri
18
+ include FileUtils
19
+
20
+ alias_method :x, :irb_exit
21
+ alias_method :q, :irb_exit
22
+ alias_method :xx, :abort
23
+ alias_method :qq, :abort
24
+ alias_method :irb, :irt
25
+
26
+ def method_missing(method, *args, &block)
27
+ IRB.conf[:MAIN_CONTEXT] && IRB.conf[:MAIN_CONTEXT].irt_mode == :file && IRT::Directives.respond_to?(method) ?
28
+ IRT::Directives.send(method, *args, &block) :
29
+ super
30
+ end
31
+
32
+ private
33
+
34
+ def ensure_session
35
+ if context.irt_mode == :file
36
+ m = caller[0].match(/`(\w*)'$/).captures[0]
37
+ raise IRT::SessionModeError, "You cannot use the :#{m} method in #{context.irt_mode} mode."
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,147 @@
1
+ require 'irb/context'
2
+
3
+ module IRB
4
+ class Context #:nodoc:
5
+
6
+ attr_accessor :parent_context, :current_line, :binding_file, :binding_line_no, :backtrace_map
7
+ attr_reader :current_line_no, :last_line_no
8
+ attr_writer :irt_mode
9
+
10
+ def file_line_pointers
11
+ file = line = nil
12
+ c = self
13
+ until file
14
+ case c.irt_mode
15
+ when :binding
16
+ file = c.binding_file
17
+ line = c.binding_line_no
18
+ when :file
19
+ file = c.irb_path
20
+ line = c.last_line_no
21
+ end
22
+ c = c.parent_context
23
+ end
24
+ [file, line]
25
+ end
26
+
27
+ def irt_mode
28
+ @irt_mode ||= :file
29
+ end
30
+
31
+ alias_method :evaluate_and_set_last_value, :evaluate
32
+ def evaluate(line, line_no)
33
+ @current_line = line
34
+ @current_line_no = line_no + line.chomp.count("\n")
35
+ if @exception_raised
36
+ IRT::Session.enter(:interactive) if irt_mode == :file
37
+ @exception_raised = false
38
+ end
39
+ log_file_line(line_no) if irt_mode == :file
40
+ begin
41
+ # ri arg to string
42
+ if m = line.match(/^(\s*ri[ \t]+)(.+)$/)
43
+ pre, to_search = m.captures
44
+ line = "#{pre}#{to_search.inspect}" unless to_search.match(/^('|").+\1$/)
45
+ else
46
+ IRT::Commands::Ri.reset_choices_map
47
+ end
48
+ # skip setting last_value for non_setting_commands
49
+ if line =~ /^\s*(#{IRT.log.non_setting_commands * '|'})\b/
50
+ self.echo = false
51
+ res = @workspace.evaluate(self, line, irb_path, line_no)
52
+ if line =~ /^\s*(#{IRT.log.ignored_echo_commands * '|'})\b/
53
+ output_ignored_echo_value(res)
54
+ end
55
+ else
56
+ self.echo = irt_mode == :file ? false : true
57
+ evaluate_and_set_last_value(line, line_no)
58
+ end
59
+ rescue Exception => e
60
+ @exception_raised = true
61
+ process_exception(e)
62
+ print "\e[31m" if Colorer.color?
63
+ raise
64
+ else
65
+ log_session_line(line, line_no) unless irt_mode == :file
66
+ end
67
+ end
68
+
69
+ %w[prompt_i prompt_s prompt_c prompt_n].each do |m|
70
+ define_method(m) do
71
+ pr = instance_variable_get("@#{m}")
72
+ col_pr = pr.send "#{irt_mode}_color"
73
+ # workaround for Readline bug see http://www.ruby-forum.com/topic/213807
74
+ if IRT.fix_readline_prompt
75
+ col_pr.gsub(/^(.*)#{pr}(.*)$/, "\001\\1\002#{pr}\001\\2\002")
76
+ else
77
+ col_pr
78
+ end
79
+ end
80
+ end
81
+
82
+ def return_format(color=:actual_color, ignored=false)
83
+ ret = ignored ? @return_format.sub(/=/,'#') : @return_format
84
+ ret.send color
85
+ end
86
+
87
+ private
88
+
89
+ def process_exception(e)
90
+ return if IRT.debug
91
+ bktr = e.backtrace.reject {|m| File.expand_path(m).match(/^#{IRT.lib_path}/) || workspace.filter_backtrace(m).nil? }
92
+ e.set_backtrace( e.class.name.match(/^IRT::/) ? bktr : map_backtrace(bktr) )
93
+ end
94
+
95
+ def map_backtrace(bktr)
96
+ @backtrace_map = {}
97
+ mapped_bktr = []
98
+ reverted_error_colors = 'xxx'.error_color.match(/^(.*)xxx(.*)$/).captures.reverse
99
+ index_format = sprintf '%s%%s%s', *reverted_error_colors
100
+ bktr.each_with_index do |m, i|
101
+ unless i + 1 > back_trace_limit || m.match(/^\(.*\)/)
102
+ @backtrace_map[i] = m.split(':')[0..1]
103
+ index = sprintf index_format, " [#{i}]"
104
+ end
105
+ mapped_bktr << "#{m}#{index}"
106
+ end
107
+ mapped_bktr
108
+ end
109
+
110
+ def log_file_line(line_no)
111
+ log_lines(@current_line, line_no)
112
+ end
113
+
114
+ def log_session_line(line, line_no)
115
+ # @current_line might get changed by the IRT::Commands::Test methods,
116
+ # while the line arg is the original command
117
+ segments = line.chomp.split("\n", -1)
118
+ last_segment = segments.pop
119
+ if last_segment.match(/^[ \t]*(#{IRT::Commands::Test.own_methods * '|'})\b/)
120
+ log_lines segments.map{|s| "#{s}\n"}.join, line_no
121
+ @last_line_no = @last_line_no ? @last_line_no + 1 : line_no
122
+ @current_line.each_line do |l|
123
+ IRT.log.add_line l, @last_line_no
124
+ end
125
+ else
126
+ log_lines(@current_line, line_no)
127
+ end
128
+ end
129
+
130
+ def log_lines(str, line_no)
131
+ i = -1
132
+ str.each_line do |l|
133
+ @last_line_no = line_no + i+=1
134
+ IRT.log.add_line l, @last_line_no
135
+ end
136
+ end
137
+
138
+ def output_ignored_echo_value(value)
139
+ if inspect?
140
+ printf return_format(:ignored_color,false), value.inspect
141
+ else
142
+ printf return_format(:ignored_color,false), value
143
+ end
144
+ end
145
+
146
+ end
147
+ end
@@ -0,0 +1,18 @@
1
+ require 'stringio'
2
+ module Kernel
3
+
4
+ def capture
5
+ out = StringIO.new
6
+ $stdout = out
7
+ yield
8
+ return out.string
9
+ ensure
10
+ $stdout = STDOUT
11
+ end
12
+
13
+ def irt(bind)
14
+ raise IRT::ArgumentTypeError, "You must pass binding instead of #{bind.class.name} object" unless bind.is_a?(Binding)
15
+ IRT::Session.enter :binding, bind
16
+ end
17
+
18
+ end
@@ -0,0 +1,36 @@
1
+ class Method
2
+
3
+ def location
4
+ f = l = nil
5
+ n = case
6
+ when arity >= 0
7
+ arity
8
+ when arity == -1
9
+ 0
10
+ when arity < -1
11
+ arity.abs - 1
12
+ end
13
+ arr = Array.new(n)
14
+ set_trace_func proc{ |event, file, line, meth_name, binding, classname|
15
+ if event.eql?('call') && name.match(meth_name.to_s)
16
+ f = file
17
+ l = line
18
+ set_trace_func nil
19
+ throw :method_located
20
+ end
21
+ }
22
+ catch(:method_located) { call *arr }
23
+ set_trace_func nil
24
+ [f,l]
25
+ end
26
+
27
+ def info
28
+ file, line = location
29
+ { :name => name,
30
+ :class_name => owner.name,
31
+ :file => file,
32
+ :line => line,
33
+ :arity => arity }
34
+ end
35
+
36
+ end
@@ -0,0 +1,7 @@
1
+ class Object
2
+
3
+ def own_methods
4
+ methods - self.class.methods
5
+ end
6
+
7
+ end
data/lib/irt/hunks.rb ADDED
@@ -0,0 +1,111 @@
1
+ module IRT
2
+ class Log
3
+
4
+ class Hunk < Array
5
+
6
+ attr_reader :header, :color
7
+
8
+ def initialize(header)
9
+ @header = header
10
+ end
11
+
12
+ def add_line(content, line_no)
13
+ self << [content.chomp, line_no]
14
+ end
15
+
16
+ def render(wanted=nil)
17
+ return unless size > 0
18
+ Log.print_border
19
+ render_header
20
+ wanted ||= size
21
+ last(wanted).each do |content, line_no|
22
+ Log.print_border
23
+ render_line(content, line_no)
24
+ end
25
+ end
26
+
27
+ def lines_str
28
+ map{|content, line_no| content }.join("\n")
29
+ end
30
+
31
+ def last_line_no
32
+ last && last[1]
33
+ end
34
+
35
+ def header_name
36
+ @header
37
+ end
38
+
39
+ def render_header
40
+ puts " #{header_name} ".send(color).bold.reversed.or("***** #{header_name} *****")
41
+ end
42
+
43
+ def render_line(content, line_no)
44
+ lcontent = content.send(color)
45
+ lno = ('%3d ' % line_no).send(color).reversed
46
+ puts "#{lno} #{lcontent}"
47
+ end
48
+
49
+ def inspect
50
+ %(<#{self.class.name} #{header_name}>)
51
+ end
52
+
53
+ end
54
+
55
+
56
+ class FileHunk < Hunk
57
+
58
+ def initialize(header=nil)
59
+ @color = :file_color
60
+ @header = header || IRB.CurrentContext.irb_path
61
+ end
62
+
63
+ def header_name
64
+ File.basename(@header)
65
+ end
66
+
67
+ end
68
+
69
+
70
+ class InteractiveHunk < Hunk
71
+
72
+ def initialize
73
+ @color = :interactive_color
74
+ @header = IRB.CurrentContext.irb_name
75
+ end
76
+
77
+ def add_line(content, line_no)
78
+ ignored = IRT.log.ignored_commands + %w[_]
79
+ return if content.match(/^\s*(#{ignored * '|'})\b/)
80
+ super
81
+ end
82
+
83
+ end
84
+
85
+
86
+ class InspectHunk < InteractiveHunk
87
+
88
+ def initialize
89
+ super
90
+ @color = :inspect_color
91
+ end
92
+
93
+ def add_line(content, line_no)
94
+ end
95
+
96
+ end
97
+
98
+ class BindingHunk < InteractiveHunk
99
+
100
+ def initialize
101
+ super
102
+ @color = :binding_color
103
+ end
104
+
105
+ def add_line(content, line_no)
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+ end