fancy_irb 0.7.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e2fdffc1b6242172f062ba5594a0ac52d13206a8
4
+ data.tar.gz: 15bb12b8f67d46fedb9615579faf6d5d4619d855
5
+ SHA512:
6
+ metadata.gz: a70c8539226521749e6d394f66bfd898921181faa284632bb4e0cd5d7558e97c6395deea7f203f439674394beab43884126fdd1cd0c8fe4b60ec5a324a5d7712
7
+ data.tar.gz: 49958762080644102e8e0a4f1bf9568bf82527935422b692ebeb62a043e72b633bc03f91e9173f702254414267b811efdbd6fb26d499350eb090a7c1b9eb2cfc
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,14 @@
1
+ == 0.8.0
2
+ * Internals partly refactored
3
+ * Bump paint and unicode-display_width dependencies
4
+ * Drop official support for Ruby 1
5
+ * Don't depend on ansicon specifics for windows (use io/console)
6
+ * Also patch input methods for ARGF
7
+ * Don't try to catch exception when printing to stderr
8
+ * Remove [:colorizer][:output] option
9
+ * Not patching Kernel anymore
10
+ * Only path String if east_asian_width option is used
11
+
1
12
  == 0.7.3
2
13
  * Don't colorize stdout by default
3
14
  * Deactivate rocket for common system commands
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-2012 Jan Lelis
1
+ Copyright (c) 2010-2012, 2015 Jan Lelis
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.rdoc CHANGED
@@ -1,14 +1,9 @@
1
- FancyIrb patches your IRB to create a smooth output experience.
1
+ = FancyIrb
2
2
 
3
- == Features
4
- * Use fancy colors! You can colorize the prompts, irb errors, +stderr+ and +stdout+
5
- * Output evaluation results as Ruby comments (hash rocket)
6
- * Filter your output value using procs
3
+ * Colorizes prompts, errors, +stderr+ and +stdout+
4
+ * Uses Hash Rockets to display evaluation results
5
+ * Allows you to apply a proc before showing the result
7
6
 
8
- == Motivation
9
- I really like the {irb_rocket}[https://github.com/genki/irb_rocket] gem, which outputs Ruby results using a hash rocket and colorizes errors. Unfortunately, the implementation leads to bugs, because it tries to run the whole command before printing anything to +stdout+. For this reason, I've rewritten and extended it.
10
-
11
- This rubygem is compatible with other great irb gems like {hirb}[https://github.com/cldwalker/hirb], {interactive_editor}[https://github.com/jberkel/interactive_editor], etc.
12
7
 
13
8
  == Usage
14
9
 
@@ -17,40 +12,52 @@ This rubygem is compatible with other great irb gems like {hirb}[https://github.
17
12
 
18
13
  You can pass an options hash. These are the default values:
19
14
 
20
- default_options = {
15
+ DEFAULT_OPTIONS = {
21
16
  :rocket_mode => true, # activate or deactivate #=> rocket output
22
17
  :rocket_prompt => '#=> ', # prompt to use for the rocket
23
18
  :result_prompt => '=> ', # prompt to use for normal output
24
- :colorize => { # colors hash. Set to nil to deactivate colorizing
19
+ :result_proc => DEFAULT_RESULT_PROC, # how to get the output result from IRB
20
+ :output_procs => [DEFAULT_COLORIZER_PROC], # output formatter procs
21
+ :east_asian_width => false, # set to true if you have double-width characters (slower)
22
+ :colorize => { # colors hash. Set to nil to deactivate colors
25
23
  :rocket_prompt => [:blue],
26
24
  :result_prompt => [:blue],
27
25
  :input_prompt => nil,
28
- :irb_errors => [:red],
26
+ :irb_errors => [:red, :clean],
29
27
  :stderr => [:red, :bright],
30
28
  :stdout => nil,
31
29
  :input => nil,
32
- :output => true, # wirb's output colorization
33
30
  },
34
- :result_proc => default_result_proc, # how to get the output result (see below)
35
- :output_procs => [default_colorizer_proc], # you can modify/enhance/log your output
36
- :east_asian_width => false, # set to true if you have double-width characters (slower)
37
31
  }
38
32
 
39
- === Rocket mode
40
33
  Rocket mode means: Output result as comment if there is enough space left on the terminal line and +stdout+ does not output more than the current terminal height.
41
34
 
42
- === Wrong display widths?
43
- When using double-width unicode chars, you should set <tt>:east_asian_width</tt> to <tt>true</tt>. It is deactivated because of performance issues.
35
+ For more information on which colors can be used, see the {paint documentation}[https://github.com/janlelis/paint].
36
+
37
+
38
+ == Example configurations
39
+ === Default
40
+ FancyIrb.start
41
+
42
+ === No colorization
43
+ FancyIrb.start :colorize => nil
44
44
 
45
- === Customize colors
46
- See paint[https://github.com/janlelis/paint]
45
+ === Use awesome_print for inspecting
46
+ require 'ap'
47
+ FancyIrb.start :rocket_mode => false,
48
+ :colorize => { :output => false,
49
+ :result_prompt => :yellow },
50
+ :result_proc => proc{ |context|
51
+ context.last_value.awesome_inspect
52
+ }
47
53
 
48
- === Modify your IRB output
54
+
55
+ == Advanced: Hook into IRB
49
56
  You can modify how to get and display the input. The <tt>result_proc</tt> is a proc which takes the irb context object and should return the value. You can change it with <tt>FancyIrb.set_result_proc do (your code) end</tt>. After that, each proc in <tt>output_procs</tt> gets triggered. They take the value and can return a modified one. You can use the <tt>FancyIrb.add_output_proc</tt> method for adding new output filter procs.
50
57
 
51
- ===== default_result_proc
58
+ === Default result_proc
52
59
 
53
- default_result_proc = proc{ |context|
60
+ DEFAULT_RESULT_PROC = proc{ |context|
54
61
  if context.inspect?
55
62
  context.last_value.inspect
56
63
  else
@@ -58,57 +65,33 @@ You can modify how to get and display the input. The <tt>result_proc</tt> is a p
58
65
  end
59
66
  }
60
67
 
61
- ===== default_colorizer_proc
68
+ === Default colorizer_proc
62
69
 
63
- default_colorizer_proc = proc{ |value|
64
- FancyIrb.real_lengths[:output] = value.size
65
- if defined?(Wirb) && FancyIrb[:colorize, :output]
70
+ DEFAULT_COLORIZER_PROC = proc{ |value|
71
+ if defined?(Wirb)
66
72
  Wirb.colorize_result value
67
73
  else
68
- value
74
+ value
69
75
  end
70
76
  }
71
77
 
72
- == FancyIrb on Windows?
73
-
74
- You need ansicon[https://github.com/adoxa/ansicon] and everything will be fine :D
78
+ == Troubleshooting
79
+ === Windows Support
80
+ You will need ansicon[https://github.com/adoxa/ansicon].
75
81
 
76
- == Example configurations
77
-
78
- === Default
79
- FancyIrb.start
80
-
81
- === No colorization
82
- FancyIrb.start :colorize => nil
83
-
84
- === Use awesome_print for inspecting
85
- require 'ap'
86
- FancyIrb.start :rocket_mode => false,
87
- :colorize => { :output => false,
88
- :result_prompt => :yellow },
89
- :result_proc => proc{ |context|
90
- context.last_value.awesome_inspect
91
- }
92
-
93
- === Smileyfy output
94
- FancyIrb.start
95
- FancyIrb.add_output_proc do |value|
96
- value + ' :)'
97
- end
82
+ === Wrong display widths?
83
+ When using double-width unicode chars, you should set <tt>:east_asian_width</tt> to <tt>true</tt>. It is not activated by default, because of its performance impact.
98
84
 
99
- == TODO
100
85
  === Known bugs
101
- * Something is wrong with input-newline when colorizing input
102
- * Not all input methods are patched properly (to work with the rocket) --> focusing on the often used ones
86
+ Not all stdin methods are patched properly to work with the rocket: The gems focuses on the often used ones
103
87
 
104
- === Features, maybe
105
- * Count string lengths without ansi escape sequences (would be more flexible than remembering)
106
- * "Always rocket"-mode
107
88
 
108
- == Copyright / Credits
89
+ == TODO
90
+ * Refactor to modern code
91
+ * Just count string lengths without ansi escape sequences (would be more flexible than remembering)
109
92
 
110
- Inspired by the irb_rocket gem from genki.
111
93
 
112
- Copyright (c) 2010-2012 Jan Lelis <http://rbjl.net> released under the MIT license.
94
+ == J-_-L
95
+ Inspired by the irb_rocket gem by genki.
113
96
 
114
- J-_-L
97
+ Copyright (c) 2010-2012, 2015 Jan Lelis <http://janlelis.com> released under the MIT license.
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ end
15
15
 
16
16
  desc "Install the gem locally (without docs)"
17
17
  task :install => :gem do
18
- sh %{gem install pkg/#{gemspec.name}-#{gemspec.version} --no-rdoc --no-ri}
18
+ sh %{gem install pkg/#{gemspec.name}-#{gemspec.version}.gem --no-rdoc --no-ri --local}
19
19
  end
20
20
 
21
21
  desc "Generate the gemspec"
data/fancy_irb.gemspec CHANGED
@@ -1,39 +1,35 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require 'rubygems' unless defined? Gem
3
-
2
+
3
+ require File.dirname(__FILE__) + "/lib/fancy_irb/version"
4
+
4
5
  Gem::Specification.new do |s|
5
6
  s.name = "fancy_irb"
6
- s.version = File.read('VERSION').chomp
7
+ s.version = FancyIrb::VERSION
7
8
  s.authors = ["Jan Lelis"]
8
9
  s.email = "mail@janlelis.de"
9
10
  s.homepage = "http://github.com/janlelis/fancy_irb"
10
- s.summary = "FancyIrb patches your IRB to create a smooth output experience."
11
- s.description = "FancyIrb patches your IRB to create a smooth output experience. You can colorize the prompts, irb errors, stderr and stdout, output your result as #=> (hash rockets) and some other improvements."
12
- s.required_rubygems_version = '>= 1.3.6'
13
- s.required_ruby_version = '>= 1.8.7'
14
- s.extra_rdoc_files = ["README.rdoc", "LICENSE"]
11
+ s.summary = "FancyIrb makes IRB friendly."
12
+ s.description = "FancyIrb makes IRB # => friendly."
13
+ s.required_ruby_version = '>= 1.9.3'
15
14
  s.license = 'MIT'
16
- s.requirements = ['On Windows, you need ansicon: https://github.com/adoxa/ansicon']
17
- s.add_dependency('paint', '>= 0.8.1')
18
- s.add_dependency('unicode-display_width', ">= 0.1.1")
15
+ s.requirements = ['Windows: ansicon <https://github.com/adoxa/ansicon>']
16
+ s.add_dependency 'paint', '>= 0.9.0'
17
+ s.add_dependency 'unicode-display_width', ">= 0.2.0"
19
18
  s.files = [
20
- "LICENSE",
19
+ "MIT-LICENSE.txt",
21
20
  "README.rdoc",
22
21
  "Rakefile",
23
- "VERSION",
24
22
  "CHANGELOG.rdoc",
25
23
  "fancy_irb.gemspec",
26
24
  "lib/fancy_irb.rb",
27
- "lib/fancy_irb/irb_ext.rb"
25
+ "lib/fancy_irb/irb_ext.rb",
26
+ "lib/fancy_irb/terminal_info.rb",
27
+ "lib/fancy_irb/implementation.rb",
28
+ "lib/fancy_irb/size_detector.rb",
29
+ "lib/fancy_irb/error_capturer.rb",
30
+ "lib/fancy_irb/core_ext.rb",
31
+ "lib/fancy_irb/clean_up.rb",
32
+ "lib/fancy_irb/version.rb",
28
33
  ]
29
-
30
- len = s.homepage.size
31
- s.post_install_message = \
32
- (" ┌── " + "info ".ljust(len-2,'%') + "─┐\n" +
33
- " J-_-L │ " + s.homepage + " │\n" +
34
- " ├── " + "usage ".ljust(len-2,'%') + "─┤\n" +
35
- " │ " + "require 'fancy_irb'".ljust(len,' ') + " │\n" +
36
- " │ " + "FancyIrb.start".ljust(len,' ') + " │\n" +
37
- " └─" + '─'*len + "─┘").gsub('%', '─') # 1.8 workaround
38
34
  end
39
35
 
@@ -0,0 +1 @@
1
+ END{ print Paint::NOTHING }
@@ -0,0 +1,12 @@
1
+ # patch streams to track height & apply colors
2
+ FancyIrb.patch_stream $stdout, :stdout
3
+ FancyIrb.patch_stream $stderr, :stderr
4
+
5
+ # patch some $stdin methods to track height
6
+ FancyIrb.register_height_trackers $stdin, FancyIrb::TRACK_HEIGHT_INPUT_METHODS
7
+
8
+ # patch some ARGF methods to track height
9
+ FancyIrb.register_height_trackers $<, FancyIrb::TRACK_HEIGHT_INPUT_METHODS
10
+
11
+ # deactivate rocket for common system commands
12
+ FancyIrb.register_skipped_rockets Object, FancyIrb::SKIP_ROCKET_METHODS
@@ -0,0 +1,18 @@
1
+ require 'stringio'
2
+
3
+ module FancyIrb
4
+ class ErrorCapturer
5
+ def initialize
6
+ @original_stdout, $stdout = $stdout, StringIO.new
7
+ @fake_stdout = $stdout
8
+ end
9
+
10
+ def error_string
11
+ @fake_stdout.string
12
+ end
13
+
14
+ def restore_original_stdout
15
+ $stdout = @original_stdout
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,168 @@
1
+ module FancyIrb
2
+ class << self
3
+ attr_reader :options
4
+ attr_reader :error_capturer
5
+ attr_accessor :skip_next_rocket
6
+
7
+ def start(user_options = {})
8
+ set_defaults
9
+ apply_user_options(user_options)
10
+ reset_line!
11
+ extend!
12
+
13
+ true
14
+ end
15
+
16
+ # hook into IRB
17
+ def extend!
18
+ require 'unicode/display_size' if @options[:east_asian_width]
19
+ require_relative 'irb_ext'
20
+ require_relative 'core_ext'
21
+ require_relative 'clean_up'
22
+ end
23
+
24
+ def set_defaults
25
+ @skip_next_rocket = false
26
+ @real_lengths = { :output => 1, :input_prompt => Float::INFINITY }
27
+
28
+ @options = DEFAULT_OPTIONS.dup
29
+ @options[:colorize] = @options[:colorize].dup if @options[:colorize]
30
+ end
31
+
32
+ def apply_user_options(user_options)
33
+ DEFAULT_OPTIONS.each{ |key, value|
34
+ # (ugly) 1 level deep merge, maybe refactor
35
+ if key == :colorize
36
+ if user_options.has_key?(:colorize) && user_options[:colorize].nil?
37
+ @options[:colorize] = {}
38
+ else
39
+ value.each{ |key2, _|
40
+ if user_options[key] && user_options[key].has_key?(key2)
41
+ @options[:colorize][key2] = user_options[key][key2]
42
+ end
43
+ }
44
+ end
45
+ else
46
+ @options[key] =
47
+ user_options.has_key?(key) ? user_options[key] : DEFAULT_OPTIONS[key]
48
+ end
49
+ }
50
+ end
51
+
52
+ def [](key, key2 = nil)
53
+ if key2
54
+ @options[key][key2]
55
+ else
56
+ @options[key]
57
+ end
58
+ end
59
+
60
+ def add_output_proc(prepend = false, &proc)
61
+ action = prepend ? :unshift : :push
62
+ @options[:output_procs].send action, proc
63
+ end
64
+
65
+ def set_result_proc(&proc)
66
+ @options[:result_proc] = proc
67
+ end
68
+
69
+ def reset_line!
70
+ @height_counter = []
71
+ @indent = false
72
+ end
73
+
74
+ def track_indent!
75
+ @indent = true
76
+ end
77
+
78
+ def set_input_prompt_size(prompt, irb_scanner)
79
+ @real_lengths[:input_prompt] =
80
+ prompt.size + irb_scanner.indent * 2 + ( @indent ? 2 : 0 )
81
+ end
82
+
83
+ def track_height(data)
84
+ @height_counter << SizeDetector.height_of(data, TerminalInfo.cols)
85
+ end
86
+
87
+ def get_height
88
+ 1 + ( @height_counter == [0] ? 0 : @height_counter.reduce(:+) || 0 )
89
+ end
90
+
91
+ def colorize(string, colorize_key)
92
+ Paint::NOTHING + Paint[string, *Array(@options[:colorize][colorize_key])]
93
+ end
94
+
95
+ # Note: No reset, relies on next one
96
+ def append_input_color(string)
97
+ if input_color = @options[:colorize][:input]
98
+ string + Paint.color(*Array(input_color))
99
+ else
100
+ string
101
+ end
102
+ end
103
+
104
+ # get_result and pass it into every format_output_proc
105
+ def get_output_from_irb_context(irb_context)
106
+ result = @options[:result_proc][irb_context]
107
+ @real_lengths[:output] = result.size
108
+ Array(@options[:output_procs]).inject(
109
+ result
110
+ ){ |output, output_proc|
111
+ output_proc[output].to_s
112
+ }
113
+ end
114
+
115
+ def get_offset_from_irb_scanner(irb_scanner)
116
+ last_line = irb_scanner.instance_variable_get(:@line).split("\n").last
117
+ 1 + @real_lengths[:input_prompt] + (last_line ? SizeDetector.width_of(last_line) : 0)
118
+ end
119
+
120
+ def get_cols_to_show_from_offset(offset)
121
+ offset + @options[:rocket_prompt].size + @real_lengths[:output]
122
+ end
123
+
124
+ # TODO testing and improving, e.g. getc does not contain "\n"
125
+ def register_height_trackers(object, methods_)
126
+ methods_.each{ |method_|
127
+ if object.respond_to?(method_)
128
+ object.send :define_singleton_method, method_ do |*args|
129
+ res = super(*args)
130
+ FancyIrb.track_height(res)
131
+ res
132
+ end
133
+ end
134
+ }
135
+ end
136
+
137
+ def register_skipped_rockets(object_class, methods_)
138
+ methods_.each{ |method_|
139
+ object_class.send :define_method, method_ do |*args|
140
+ FancyIrb.skip_next_rocket = true
141
+ super(*args)
142
+ end
143
+ }
144
+ end
145
+
146
+ def patch_stream(object, stream_name)
147
+ object.define_singleton_method :write do |data|
148
+ FancyIrb.track_height data
149
+ super FancyIrb.colorize(data, stream_name)
150
+ end
151
+ end
152
+
153
+ def register_error_capturer!
154
+ @error_capturer = FancyIrb::ErrorCapturer.new
155
+ end
156
+
157
+ def present_and_clear_captured_error!
158
+ if @error_capturer
159
+ @error_capturer.restore_original_stdout
160
+ $stderr.puts colorize(
161
+ @error_capturer.error_string.chomp,
162
+ :irb_errors,
163
+ )
164
+ @error_capturer = nil
165
+ end
166
+ end
167
+ end
168
+ end
@@ -1,196 +1,62 @@
1
- if FancyIrb[:east_asian_width]
2
- require 'unicode/display_size'
3
- else
4
- class String
5
- alias display_size size
6
- end
7
- end
8
-
9
1
  module IRB
10
2
  class Irb
11
- if FancyIrb.win?
12
- TPUT = {
13
- :sc => "\e[s",
14
- :rc => "\e[u",
15
- :cuu1 => "\e[1A",
16
- :cuf1 => "\e[1C",
17
- }
18
- else
19
- TPUT = {
20
- :sc => `tput sc`,
21
- :rc => `tput rc`,
22
- :cuu1 => `tput cuu1`,
23
- :cuf1 => `tput cuf1`,
24
- }
25
- end
26
-
27
- def colorize(string, color)
28
- Paint[string, *Array(color)]
29
- end
30
-
31
3
  def output_value
32
- # prepare prompts
33
- rocket = colorize FancyIrb[:rocket_prompt], FancyIrb[:colorize, :rocket_prompt]
34
- no_rocket = colorize FancyIrb[:result_prompt], FancyIrb[:colorize, :result_prompt]
35
-
36
- # get_result and pass it into every format_output_proc
37
- result = FancyIrb[:result_proc][ @context ]
38
-
39
- output = Array( FancyIrb[:output_procs] ).
40
- inject( result.to_s ){ |output, formatter|
41
- formatter[ output ].to_s
42
- }
43
-
44
- # reset color
45
- print Paint::NOTHING
4
+ output = FancyIrb.get_output_from_irb_context(@context)
46
5
 
47
- # try to output in rocket mode (depending on rocket_mode setting)
48
6
  if FancyIrb[:rocket_mode] && !FancyIrb.skip_next_rocket
49
- # get lengths
50
- last_input = @scanner.instance_variable_get( :@line )
51
- last_line_without_prompt = last_input.split("\n").last
52
- offset = + FancyIrb.real_lengths[:input_prompt] + 1
53
- if last_line_without_prompt
54
- offset += last_line_without_prompt.display_size
55
- end
56
- screen_length = FancyIrb.current_length
57
- screen_lines = FancyIrb.current_lines
58
- output_length = FancyIrb.real_lengths[:output]
59
- rocket_length = FancyIrb[:rocket_prompt].size
60
- stdout_lines = FancyIrb.get_height
61
-
62
- # auto rocket mode
63
- if screen_length > offset + rocket_length + output_length &&
64
- stdout_lines < screen_lines
65
- print TPUT[:sc] + # save current cursor position
66
- TPUT[:cuu1]*stdout_lines + # move cursor upwards to the original input line
67
- TPUT[:cuf1]*offset + # move cursor rightwards to the original input offset
68
- rocket + # draw rocket prompt
69
- output + # draw output
70
- TPUT[:rc] # return to normal cursor position
7
+ offset = FancyIrb.get_offset_from_irb_scanner(@scanner)
8
+ cols_to_show = FancyIrb.get_cols_to_show_from_offset(offset)
9
+ lines_to_show = FancyIrb.get_height
10
+
11
+ if FancyIrb::TerminalInfo.lines > lines_to_show &&
12
+ FancyIrb::TerminalInfo.cols > cols_to_show
13
+ print \
14
+ Paint::NOTHING +
15
+ FancyIrb::TerminalInfo::TPUT[:sc] + # save current cursor position
16
+ FancyIrb::TerminalInfo::TPUT[:cuu1] * lines_to_show + # move cursor upwards to the original input line
17
+ FancyIrb::TerminalInfo::TPUT[:cuf1] * offset + # move cursor rightwards to the original input offset
18
+ FancyIrb.colorize(FancyIrb[:rocket_prompt], :rocket_prompt) + # draw rocket prompt
19
+ output + # draw output
20
+ FancyIrb::TerminalInfo::TPUT[:rc] # return to normal cursor position
71
21
  return
72
22
  end
73
23
  end
74
- # normal output mode
75
24
  FancyIrb.skip_next_rocket = false
76
- puts no_rocket + output
25
+ puts FancyIrb.colorize(FancyIrb[:result_prompt], :result_prompt) + output
77
26
  end
78
27
 
79
28
  # colorize prompt & input
80
29
  alias prompt_non_fancy prompt
81
30
  def prompt(*args, &block)
82
- print Paint::NOTHING
83
31
  prompt = prompt_non_fancy(*args, &block)
84
32
 
85
- # this is kinda hacky... but that's irb °_°
86
- indents = @scanner.indent*2
87
- FancyIrb.continue = true if args[0] == IRB.conf[:PROMPT][IRB.conf[:PROMPT_MODE]][:PROMPT_C]
88
- indents += 2 if FancyIrb.continue
89
- FancyIrb.real_lengths[:input_prompt] = prompt.size + indents
90
-
91
- colorized_prompt = colorize prompt, FancyIrb[:colorize, :input_prompt]
92
- if input_color = FancyIrb[:colorize, :input]
93
- colorized_prompt + Paint.color(*Array(input_color)) # NOTE: No reset, relies on next one
94
- else
95
- colorized_prompt
96
- end
33
+ FancyIrb.track_indent! if args[0] == IRB.conf[:PROMPT][IRB.conf[:PROMPT_MODE]][:PROMPT_C]
34
+ FancyIrb.set_input_prompt_size(prompt, @scanner)
35
+
36
+ FancyIrb.append_input_color(FancyIrb.colorize(prompt, :input_prompt))
97
37
  end
98
38
 
99
- # track height and capture irb errors (part 2)
39
+ # reset line and capture IRB errors (part 2)
100
40
  alias signal_status_non_fancy signal_status
101
41
  def signal_status(name, *args, &block)
102
- FancyIrb.continue = false
103
- FancyIrb.reset_height
42
+ FancyIrb.reset_line!
104
43
  signal_status_non_fancy(name, *args, &block)
105
44
  ensure
106
45
  if name == :IN_EVAL
107
- if FancyIrb.capture_irb_errors
108
- errors = FancyIrb.capture_irb_errors.string
109
-
110
- $stdout = FancyIrb.original_stdout
111
- FancyIrb.capture_irb_errors = nil
112
- FancyIrb.original_stdout = nil
113
-
114
- unless errors.empty?
115
- warn colorize( errors.chomp, FancyIrb[:colorize, :irb_errors] )
116
- end
117
- end
118
- end#if
119
- end#def
120
- end#class
46
+ FancyIrb.present_and_clear_captured_error!
47
+ end
48
+ end
49
+ end
121
50
 
122
51
  class Context
123
52
  alias evaluate_non_fancy evaluate
124
53
 
125
- # capture irb errors (part 1)
54
+ # capture IRB errors (part 1)
126
55
  def evaluate(*args)
127
- FancyIrb.stdout_colorful = true
128
56
  evaluate_non_fancy(*args)
129
- FancyIrb.stdout_colorful = false
130
- rescue Exception => err
131
- FancyIrb.stdout_colorful = false
132
- FancyIrb.capture_irb_errors = StringIO.new
133
- FancyIrb.original_stdout, $stdout = $stdout, FancyIrb.capture_irb_errors
134
- raise err
57
+ rescue Exception
58
+ FancyIrb.register_error_capturer!
59
+ raise
135
60
  end
136
61
  end
137
62
  end
138
-
139
- # hook into streams to count lines and colorize
140
- class << $stdout
141
- alias write_non_fancy write
142
- def write(data)
143
- FancyIrb.track_height data
144
- FancyIrb.write_stream $stdout, data, FancyIrb[:colorize, :stdout]
145
- end
146
- end
147
-
148
- class << $stderr
149
- alias write_non_fancy write
150
- def write(data)
151
- FancyIrb.track_height data
152
- FancyIrb.write_stream $stderr, data, FancyIrb[:colorize, :stderr]
153
- rescue Exception # catch fancy_irb errors
154
- write_non_fancy data
155
- end
156
- end
157
-
158
- # deactivate rocket for common system commands
159
- %w[system spawn].each{ |m|
160
- Object.send(:define_method, m.to_sym, &lambda{ |*args, &block|
161
- FancyIrb.skip_next_rocket = true
162
- super(*args, &block)
163
- })
164
- }
165
-
166
- # patch some input methods to track height
167
- alias gets_non_fancy gets
168
- def gets(*args)
169
- res = gets_non_fancy *args
170
- FancyIrb.track_height res
171
- res
172
- end
173
-
174
- # TODO testing and improving, e.g. getc does not contain "\n"
175
- class << $stdin
176
- stdin_hooks = %w[binread read gets getc getbyte readbyte readchar readline readlines readpartial sysread]
177
- # TODO: each_byte, each_char, each_codepoint, each
178
-
179
- stdin_hooks.each{ |m|
180
- msym = m.to_sym
181
- malias = (m+'_non_fancy').to_sym
182
-
183
- if $stdin.respond_to? msym
184
- alias_method malias, msym
185
- define_method msym do |*args|
186
- res = send malias, *args
187
- FancyIrb.track_height res
188
- res
189
- end
190
- end
191
- }
192
- end
193
-
194
- END{ print "\e[0m" } # reset colors when exiting
195
-
196
- # J-_-L
@@ -0,0 +1,20 @@
1
+ module FancyIrb
2
+ module SizeDetector
3
+ def self.width_of(data)
4
+ if FancyIrb[:east_asian_width]
5
+ data.display_size
6
+ else
7
+ data.size
8
+ end
9
+ end
10
+
11
+ def self.height_of(data, width)
12
+ data = Paint.unpaint(data.to_s)
13
+ lines = data.count("\n")
14
+ long_lines = data.split("\n").inject(0){ |sum, line|
15
+ sum + (width_of(line) / width)
16
+ }
17
+ lines + long_lines
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,29 @@
1
+ require 'io/console'
2
+
3
+ module FancyIrb
4
+ module TerminalInfo
5
+ def self.lines
6
+ STDIN.winsize[0]
7
+ end
8
+
9
+ def self.cols
10
+ STDIN.winsize[1]
11
+ end
12
+
13
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
14
+ TPUT = {
15
+ :sc => "\e[s",
16
+ :rc => "\e[u",
17
+ :cuu1 => "\e[1A",
18
+ :cuf1 => "\e[1C",
19
+ }
20
+ else
21
+ TPUT = {
22
+ :sc => `tput sc`,
23
+ :rc => `tput rc`,
24
+ :cuu1 => `tput cuu1`,
25
+ :cuf1 => `tput cuf1`,
26
+ }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module FancyIrb
2
+ VERSION = '0.8.0'.freeze
3
+ end
data/lib/fancy_irb.rb CHANGED
@@ -1,147 +1,66 @@
1
+ require_relative 'fancy_irb/version'
2
+
1
3
  require 'stringio'
2
4
  require 'paint'
3
5
 
4
- module FancyIrb
5
- VERSION = File.read( File.dirname(__FILE__) + '/../VERSION' ).chomp
6
- end
6
+ require_relative 'fancy_irb/terminal_info'
7
+ require_relative 'fancy_irb/size_detector'
8
+ require_relative 'fancy_irb/error_capturer'
9
+ require_relative 'fancy_irb/implementation'
7
10
 
8
- class << FancyIrb
9
- # setup instance variable accessors
10
- attr_accessor :options
11
- def [](key, key2 = nil)
12
- if key2
13
- @options[key][key2]
11
+ module FancyIrb
12
+ DEFAULT_RESULT_PROC = proc{ |context|
13
+ if context.inspect?
14
+ context.last_value.inspect
14
15
  else
15
- @options[key]
16
- end
17
- end
18
-
19
- attr_accessor :original_stdout
20
- attr_accessor :capture_irb_errors
21
- attr_accessor :real_lengths
22
- attr_accessor :continue
23
- attr_accessor :stdout_colorful
24
- attr_accessor :skip_next_rocket
25
-
26
- def start(user_options = {})
27
- # track some irb stuff
28
- @height_counter = []
29
- @real_lengths = { :output => 1, :input_prompt => 9999 } # or whatever
30
- @stdout_colorful = false
31
- @continue = false
32
- @skip_next_rocket = false
33
-
34
- # set defaults and parse user options
35
- default_result_proc = proc{ |context|
36
- if context.inspect?
37
- context.last_value.inspect
38
- else
39
- context.last_value
40
- end
41
- }
42
-
43
- default_colorizer_proc = proc{ |value|
44
- FancyIrb.real_lengths[:output] = value.size
45
- if defined?(Wirb) && FancyIrb[:colorize, :output]
46
- Wirb.colorize_result value
47
- else
48
- value
49
- end
50
- }
51
-
52
- default_options = {
53
- :rocket_mode => true, # activate or deactivate #=> rocket output
54
- :rocket_prompt => '#=> ', # prompt to use for the rocket
55
- :result_prompt => '=> ', # prompt to use for normal output
56
- :colorize => { # colors hash. Set to nil to deactivate colorizing
57
- :rocket_prompt => [:blue],
58
- :result_prompt => [:blue],
59
- :input_prompt => nil,
60
- :irb_errors => [:red],
61
- :stderr => [:red, :bright],
62
- :stdout => nil,
63
- :input => nil,
64
- :output => true, # wirb's output colorization
65
- },
66
- :result_proc => default_result_proc, # how to get the output result
67
- :output_procs => [default_colorizer_proc], # you can modify/enhance/log your output
68
- :east_asian_width => false, # set to true if you have double-width characters (slower)
69
- }
70
-
71
- @options = default_options
72
-
73
- default_options.each{ |key, value|
74
- # (ugly) 1 level deep merge, maybe refactor
75
- if key == :colorize
76
- if user_options.has_key?(:colorize) && user_options[:colorize].nil?
77
- @options[:colorize] = {}
78
- else
79
- value.each{ |key2, _|
80
- if user_options[key] && user_options[key].has_key?(key2)
81
- @options[:colorize][key2] = user_options[key][key2]
82
- end
83
- }
84
- end
85
- else
86
- @options[key] = user_options.has_key?(key) ? user_options[key] : default_options[key]
87
- end
88
- }
89
-
90
- # hook code into IRB
91
- require 'fancy_irb/irb_ext'
92
- true
93
- end
94
-
95
- def add_output_proc(prepend = false, &proc)
96
- action = prepend ? :unshift : :push
97
- @options[:output_procs].send action, proc
98
- end
99
-
100
- def set_result_proc(&proc)
101
- @options[:result_proc] = proc
102
- end
103
-
104
- def reset_height
105
- @height_counter = []
106
- end
107
-
108
- def track_height(data)
109
- data = Paint.unpaint(data.to_s)
110
- lines = data.count("\n")
111
- long_lines = data.split("\n").inject(0){ |sum, line|
112
- sum + (line.display_size / current_length)
113
- }
114
- @height_counter << lines + long_lines
115
- end
116
-
117
- def get_height
118
- 1 + ( @height_counter == [0] ? 0 : @height_counter.reduce(:+) || 0 )
119
- end
120
-
121
- def write_stream(stream, data, color = nil)
122
- stream.write_non_fancy( FancyIrb.stdout_colorful ? Paint[data, *Array(color)] : data.to_s )
123
- end
124
-
125
- def win?
126
- RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
127
- end
128
-
129
- if FancyIrb.win?
130
- raise LoadError, 'FancyIrb needs ansicon on windows, see https://github.com/adoxa/ansicon' unless ENV['ANSICON']
131
- def current_length
132
- ENV['ANSICON'][/\((.*)x/, 1].to_i
133
- end
134
-
135
- def current_lines
136
- ENV['ANSICON'][/\(.*x(.*)\)/, 1].to_i
137
- end
138
- else
139
- def current_length
140
- `tput cols`.to_i
16
+ context.last_value
141
17
  end
18
+ }
142
19
 
143
- def current_lines
144
- `tput lines`.to_i
20
+ DEFAULT_COLORIZER_PROC = proc{ |value|
21
+ if defined?(Wirb)
22
+ Wirb.colorize_result value
23
+ else
24
+ value
145
25
  end
146
- end
26
+ }
27
+
28
+ DEFAULT_OPTIONS = {
29
+ :rocket_mode => true, # activate or deactivate #=> rocket output
30
+ :rocket_prompt => '#=> ', # prompt to use for the rocket
31
+ :result_prompt => '=> ', # prompt to use for normal output
32
+ :result_proc => DEFAULT_RESULT_PROC, # how to get the output result from IRB
33
+ :output_procs => [DEFAULT_COLORIZER_PROC], # output formatter procs
34
+ :east_asian_width => false, # set to true if you have double-width characters (slower)
35
+ :colorize => { # colors hash. Set to nil to deactivate colors
36
+ :rocket_prompt => [:blue],
37
+ :result_prompt => [:blue],
38
+ :input_prompt => nil,
39
+ :irb_errors => [:red, :clean],
40
+ :stderr => [:red, :bright],
41
+ :stdout => nil,
42
+ :input => nil,
43
+ },
44
+ }
45
+
46
+ SKIP_ROCKET_METHODS = %w[
47
+ system
48
+ spawn
49
+ ].map(&:to_sym)
50
+
51
+ # TODO: each_byte, each_char, each_codepoint, each, etc
52
+ TRACK_HEIGHT_INPUT_METHODS = %w[
53
+ binread
54
+ read
55
+ gets
56
+ getc
57
+ getbyte
58
+ readbyte
59
+ readchar
60
+ readline
61
+ readlines
62
+ readpartial
63
+ sysread
64
+ ].map(&:to_sym)
147
65
  end
66
+
metadata CHANGED
@@ -1,94 +1,87 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fancy_irb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
5
- prerelease:
4
+ version: 0.8.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jan Lelis
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-11-30 00:00:00.000000000 Z
11
+ date: 2015-03-18 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: paint
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
- version: 0.8.1
19
+ version: 0.9.0
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: 0.8.1
26
+ version: 0.9.0
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: unicode-display_width
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
- version: 0.1.1
33
+ version: 0.2.0
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
- version: 0.1.1
46
- description: ! 'FancyIrb patches your IRB to create a smooth output experience. You
47
- can colorize the prompts, irb errors, stderr and stdout, output your result as #=>
48
- (hash rockets) and some other improvements.'
40
+ version: 0.2.0
41
+ description: 'FancyIrb makes IRB # => friendly.'
49
42
  email: mail@janlelis.de
50
43
  executables: []
51
44
  extensions: []
52
- extra_rdoc_files:
53
- - README.rdoc
54
- - LICENSE
45
+ extra_rdoc_files: []
55
46
  files:
56
- - LICENSE
47
+ - CHANGELOG.rdoc
48
+ - MIT-LICENSE.txt
57
49
  - README.rdoc
58
50
  - Rakefile
59
- - VERSION
60
- - CHANGELOG.rdoc
61
51
  - fancy_irb.gemspec
62
52
  - lib/fancy_irb.rb
53
+ - lib/fancy_irb/clean_up.rb
54
+ - lib/fancy_irb/core_ext.rb
55
+ - lib/fancy_irb/error_capturer.rb
56
+ - lib/fancy_irb/implementation.rb
63
57
  - lib/fancy_irb/irb_ext.rb
58
+ - lib/fancy_irb/size_detector.rb
59
+ - lib/fancy_irb/terminal_info.rb
60
+ - lib/fancy_irb/version.rb
64
61
  homepage: http://github.com/janlelis/fancy_irb
65
62
  licenses:
66
63
  - MIT
67
- post_install_message: ! " ┌── info ──────────────────────────────┐\n J-_-L │
68
- http://github.com/janlelis/fancy_irb │\n ├── usage ─────────────────────────────┤\n
69
- \ │ require 'fancy_irb' │\n │ FancyIrb.start │\n
70
- \ └──────────────────────────────────────┘"
64
+ metadata: {}
65
+ post_install_message:
71
66
  rdoc_options: []
72
67
  require_paths:
73
68
  - lib
74
69
  required_ruby_version: !ruby/object:Gem::Requirement
75
- none: false
76
70
  requirements:
77
- - - ! '>='
71
+ - - ">="
78
72
  - !ruby/object:Gem::Version
79
- version: 1.8.7
73
+ version: 1.9.3
80
74
  required_rubygems_version: !ruby/object:Gem::Requirement
81
- none: false
82
75
  requirements:
83
- - - ! '>='
76
+ - - ">="
84
77
  - !ruby/object:Gem::Version
85
- version: 1.3.6
78
+ version: '0'
86
79
  requirements:
87
- - ! 'On Windows, you need ansicon: https://github.com/adoxa/ansicon'
80
+ - 'Windows: ansicon <https://github.com/adoxa/ansicon>'
88
81
  rubyforge_project:
89
- rubygems_version: 1.8.24
82
+ rubygems_version: 2.4.5
90
83
  signing_key:
91
- specification_version: 3
92
- summary: FancyIrb patches your IRB to create a smooth output experience.
84
+ specification_version: 4
85
+ summary: FancyIrb makes IRB friendly.
93
86
  test_files: []
94
87
  has_rdoc:
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.7.3