fancy_irb 0.7.3 → 0.8.0

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