fancy_irb 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.swp
2
+ *~
3
+ doc
4
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Jan Lelis
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,114 @@
1
+ FancyIrb patches your IRB to create a smooth output experience.
2
+
3
+ == Features
4
+ * Use fancy colors! You can colorize the prompts, irb errors, +stderr+ and +stdout+
5
+ * Output results as Ruby comment
6
+ * Enhance your output value, using procs
7
+
8
+ == Motivation
9
+ I really like the {irb_rocket}[https://github.com/genki/irb_rocket] gem, which outputs the evaluation result as comment 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 plugin is compatible with other great gems like {hirb}[https://github.com/cldwalker/hirb], {interactive_editor}[https://github.com/jberkel/interactive_editor], etc.
12
+
13
+ == Usage
14
+
15
+ require 'fancy_irb'
16
+ FancyIrb.start
17
+
18
+ You can pass an options hash. These are the default values:
19
+
20
+ default_options = {
21
+ :rocket_mode => true, # activate or deactivate #=> rocket output
22
+ :rocket_prompt => '#=> ', # prompt to use for the rocket
23
+ :result_prompt => '=> ', # prompt to use for normal output
24
+ :colorize => { # colors hash. Set to nil to deactivate colorizing
25
+ :rocket_prompt => :blue,
26
+ :result_prompt => :blue,
27
+ :input_prompt => nil,
28
+ :irb_errors => :red,
29
+ :stderr => :light_red,
30
+ :stdout => :dark_gray,
31
+ :input => nil,
32
+ :output => true, # wirble's output colorization
33
+ },
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
+ }
37
+
38
+ === Rocket mode
39
+
40
+ Rocket mode means: Output result as comment if there is enough space left on the terminal line.
41
+
42
+ === Available colors
43
+ >> Wirble::Colorize::Color::COLORS.keys
44
+ => [:light_purple, :yellow, :light_gray, :white, :black, :dark_gray, :red, :green, :light_green, :brown, :light_blue, :light_red, :cyan, :blue, :light_cyan, :purple, :nothing]
45
+
46
+ === Modify your output
47
+
48
+ 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.
49
+
50
+ ===== default_result_proc
51
+
52
+ default_result_proc = proc{ |context|
53
+ if context.inspect?
54
+ context.last_value.inspect
55
+ else
56
+ context.last_value
57
+ end
58
+ }
59
+
60
+ ===== default_colorizer_proc
61
+
62
+ default_colorizer_proc = proc{ |value|
63
+ FancyIrb.real_lengths[:output] = value.size
64
+ if defined?(Wirble) && FancyIrb[:colorize, :output]
65
+ Wirble::Colorize.colorize value
66
+ else
67
+ value
68
+ end
69
+ }
70
+
71
+ == Example configurations
72
+
73
+ === Default
74
+ FancyIrb.start
75
+
76
+ === No colorization
77
+ FancyIrb.start :colorize => nil
78
+
79
+ === Use awesome_print for inspecting
80
+ require 'ap'
81
+ FancyIrb.start :rocket_mode => false,
82
+ :colorize => { :output => false,
83
+ :result_prompt => :yellow },
84
+ :result_proc => proc{ |context|
85
+ context.last_value.awesome_inspect
86
+ }
87
+
88
+ === Smileyfy output
89
+ FancyIrb.start
90
+ FancyIrb.add_output_proc do |value|
91
+ value + ' :)'
92
+ end
93
+
94
+ == TODO
95
+ === Known bugs
96
+ * If stdout of the current command scrolls, the rocket is displayed not higher than the first terminal line
97
+ * Something is wrong with input-newline when colorizing input
98
+ * Not all input methods are patched properly (to work with the rocket) --> focusing on the often used ones
99
+
100
+ === Features, maybe
101
+ * Count string lengths without ansi escape sequences (would be more flexible than remembering)
102
+ * "Always rocket"-mode
103
+ * Allow custom ansi escape strings
104
+ * Refactor some code duplications
105
+
106
+ Feel free to fix a bug or implement a todo ;)
107
+
108
+ == Copyright / Credits
109
+
110
+ Inspired by the irb_rocket gem from genki.
111
+
112
+ Copyright (c) 2010 Jan Lelis, http://rbjl.net, released under the MIT license.
113
+
114
+ J-_-L
data/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "fancy_irb"
8
+ gem.summary = %q{FancyIrb patches your IRB to create a smooth output experience.}
9
+ gem.description = %q{FancyIrb patches your IRB to create a smooth output experience.
10
+ * Use fancy colors! You can colorize the prompts, irb errors, +stderr+ and +stdout+
11
+ * Output results as Ruby comment #=> (rocket)
12
+ * Enhance your output value, using procs}
13
+ gem.email = "mail@janlelis.de"
14
+ gem.homepage = "http://github.com/janlelis/fancy_irb"
15
+ gem.authors = ["Jan Lelis"]
16
+ gem.add_dependency 'wirble'
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ require 'rake/rdoctask'
24
+ Rake::RDocTask.new do |rdoc|
25
+ version = File.exist?('VERSION') ? File.read('VERSION').chomp : ""
26
+
27
+ rdoc.rdoc_dir = 'doc'
28
+ rdoc.title = "FancyIrb #{version}"
29
+ rdoc.rdoc_files.include('README*')
30
+ rdoc.rdoc_files.include('lib/**/*.rb')
31
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.6.0
data/fancy_irb.gemspec ADDED
@@ -0,0 +1,51 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{fancy_irb}
8
+ s.version = "0.6.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Jan Lelis"]
12
+ s.date = %q{2010-11-10}
13
+ s.description = %q{FancyIrb patches your IRB to create a smooth output experience.
14
+ * Use fancy colors! You can colorize the prompts, irb errors, +stderr+ and +stdout+
15
+ * Output results as Ruby comment #=> (rocket)
16
+ * Enhance your output value, using procs}
17
+ s.email = %q{mail@janlelis.de}
18
+ s.extra_rdoc_files = [
19
+ "LICENSE",
20
+ "README"
21
+ ]
22
+ s.files = [
23
+ ".gitignore",
24
+ "LICENSE",
25
+ "README",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "fancy_irb.gemspec",
29
+ "lib/fancy_irb.rb",
30
+ "lib/fancy_irb/irb_ext.rb"
31
+ ]
32
+ s.homepage = %q{http://github.com/janlelis/fancy_irb}
33
+ s.rdoc_options = ["--charset=UTF-8"]
34
+ s.require_paths = ["lib"]
35
+ s.rubygems_version = %q{1.3.7}
36
+ s.summary = %q{FancyIrb patches your IRB to create a smooth output experience.}
37
+
38
+ if s.respond_to? :specification_version then
39
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
40
+ s.specification_version = 3
41
+
42
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
+ s.add_runtime_dependency(%q<wirble>, [">= 0"])
44
+ else
45
+ s.add_dependency(%q<wirble>, [">= 0"])
46
+ end
47
+ else
48
+ s.add_dependency(%q<wirble>, [">= 0"])
49
+ end
50
+ end
51
+
@@ -0,0 +1,163 @@
1
+ module IRB
2
+ class Irb
3
+ def colorize(string, color)
4
+ if defined?(Wirble) && color && color_string = Wirble::Colorize::Color.escape( color.to_sym )
5
+ color_string + string.to_s + Wirble::Colorize::Color.escape( :nothing )
6
+ else
7
+ # if defined? Wirble
8
+ # Wirble::Colorize::Color.escape( :nothing ) + string.to_s
9
+ # else
10
+ string.to_s
11
+ # end
12
+ end
13
+ end
14
+
15
+ def output_value
16
+ # prepare prompts
17
+ rocket = colorize FancyIrb[:rocket_prompt], FancyIrb[:colorize, :rocket_prompt]
18
+ no_rocket = colorize FancyIrb[:result_prompt], FancyIrb[:colorize, :result_prompt]
19
+
20
+ # get_result and pass it into every format_output_proc
21
+ result = FancyIrb[:result_proc][ @context ]
22
+
23
+ output = Array( FancyIrb[:output_procs] ).
24
+ inject( result.to_s ){ |output, formatter|
25
+ formatter[ output ].to_s
26
+ }
27
+
28
+ # reset color
29
+ print Wirble::Colorize::Color.escape( :nothing )
30
+
31
+ # try to output in rocket mode (depending on rocket_mode setting)
32
+ if FancyIrb[:rocket_mode]
33
+ # get lengths
34
+ last_input = @scanner.instance_variable_get( :@line )
35
+ last_line_without_prompt = last_input.split("\n").last
36
+ offset = last_line_without_prompt.size + FancyIrb.real_lengths[:input_prompt] + 1
37
+ screen_length = `tput cols`.to_i
38
+ output_length = FancyIrb.real_lengths[:output]
39
+ rocket_length = FancyIrb[:rocket_prompt].size
40
+ stdout_lines = FancyIrb.get_height
41
+
42
+ # auto rocket mode
43
+ if FancyIrb[:rocket_mode] && screen_length > offset + rocket_length + output_length
44
+ print `tput sc` + # save current cursor position
45
+ `tput cuu1`*stdout_lines + # move cursor upwards to the original input line
46
+ `tput cuf1`*offset + # move cursor rightwards to the original input offset
47
+ rocket + # draw rocket prompt
48
+ output + # draw output
49
+ `tput rc` # return to normal cursor position
50
+ return
51
+ end
52
+ end
53
+ # normal output mode
54
+ puts no_rocket + output
55
+ end
56
+
57
+ # colorize prompt & input
58
+ alias prompt_non_fancy prompt
59
+ def prompt(*args, &block)
60
+ print Wirble::Colorize::Color.escape(:nothing)
61
+
62
+ prompt = prompt_non_fancy(*args, &block)
63
+ FancyIrb.real_lengths[:input_prompt] = prompt.size
64
+ colorized_prompt = colorize prompt, FancyIrb[:colorize, :input_prompt]
65
+ if input_color = FancyIrb[:colorize, :input]
66
+ colorized_prompt + Wirble::Colorize::Color.escape( input_color ) # NOTE: No reset, relies on next one
67
+ # TODO buggy
68
+ else
69
+ colorized_prompt
70
+ end
71
+ end
72
+
73
+ # track height and capture irb errors (part 2)
74
+ alias signal_status_non_fancy signal_status
75
+ def signal_status(name, *args, &block)
76
+ FancyIrb.reset_height
77
+ signal_status_non_fancy(name, *args, &block)
78
+ ensure
79
+ if name == :IN_EVAL
80
+ if FancyIrb.capture_irb_errors
81
+ errors = FancyIrb.capture_irb_errors.string
82
+
83
+ $stdout = FancyIrb.original_stdout
84
+ FancyIrb.capture_irb_errors = nil
85
+ FancyIrb.original_stdout = nil
86
+
87
+ unless errors.empty?
88
+ warn colorize( errors.chomp, FancyIrb[:colorize, :irb_errors] )
89
+ end
90
+ end
91
+ end#if
92
+ end#def
93
+ end#class
94
+
95
+ class Context
96
+ alias evaluate_non_fancy evaluate
97
+
98
+ # capture irb errors (part 1)
99
+ def evaluate(*args)
100
+ FancyIrb.stdout_colorful = true
101
+ evaluate_non_fancy(*args)
102
+ FancyIrb.stdout_colorful = false
103
+ rescue Exception => err
104
+ FancyIrb.stdout_colorful = false
105
+ FancyIrb.capture_irb_errors = StringIO.new
106
+ FancyIrb.original_stdout, $stdout = $stdout, FancyIrb.capture_irb_errors
107
+ raise err
108
+ end
109
+ end
110
+ end
111
+
112
+ # hook into streams to count lines and colorize
113
+ class << $stdout
114
+ alias write_non_fancy write
115
+ def write(data)
116
+ FancyIrb.track_height data
117
+ FancyIrb.write_stream $stdout, data, FancyIrb[:colorize, :stdout]
118
+ end
119
+ end
120
+
121
+ class << $stderr
122
+ alias write_non_fancy write
123
+ def write(data)
124
+ FancyIrb.track_height data
125
+ FancyIrb.write_stream $stderr, data, FancyIrb[:colorize, :stderr]
126
+ rescue Exception # catch fancy_irb errors
127
+ write_non_fancy data
128
+ end
129
+ end
130
+
131
+
132
+ # patch some input methods to track height
133
+ alias gets_non_fancy gets
134
+ def gets(*args)
135
+ res = gets_non_fancy *args
136
+ FancyIrb.track_height res
137
+ res
138
+ end
139
+
140
+ # TODO testing and improving, e.g. getc does not contain "\n"
141
+ class << $stdin
142
+ stdin_hooks = %w[binread read gets getc getbyte readbyte readchar readline readlines readpartial sysread]
143
+ # TODO: each_byte, each_char, each_codepoint, each
144
+
145
+ stdin_hooks.each{ |m|
146
+ msym = m.to_sym
147
+ malias = (m+'_non_fancy').to_sym
148
+
149
+ if $stdin.respond_to? msym
150
+ alias_method malias, msym
151
+ define_method msym do |*args|
152
+ res = send malias, *args
153
+ FancyIrb.track_height res
154
+ res
155
+ end
156
+ end
157
+ }
158
+ end
159
+
160
+ # reset everything (e.g. colors) when exiting
161
+ END{
162
+ print `tput sgr0`
163
+ }
data/lib/fancy_irb.rb ADDED
@@ -0,0 +1,123 @@
1
+ require 'stringio'
2
+ require 'wirble'
3
+
4
+ module FancyIrb
5
+ VERSION = ( File.read File.expand_path( '../VERSION', File.dirname(__FILE__)) ).chomp
6
+ end
7
+
8
+ class << FancyIrb
9
+ # setup instance variable accessors
10
+ attr_reader :options
11
+ def [](key, key2 = nil)
12
+ if key2
13
+ @options[key][key2]
14
+ 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 :stdout_colorful
23
+
24
+ def start(user_options = {})
25
+ # track some irb stuff
26
+ @height_counter = []
27
+ @real_lengths = { :output => 1, :input_prompt => 9999 } # or whatever
28
+ @stdout_colorful = false
29
+
30
+ # set defaults and parse user options
31
+ default_result_proc = proc{ |context|
32
+ if context.inspect?
33
+ context.last_value.inspect
34
+ else
35
+ context.last_value
36
+ end
37
+ }
38
+
39
+ default_colorizer_proc = proc{ |value|
40
+ FancyIrb.real_lengths[:output] = value.size
41
+ if defined?(Wirble) && FancyIrb[:colorize, :output]
42
+ Wirble::Colorize.colorize value
43
+ else
44
+ value
45
+ end
46
+ }
47
+
48
+ default_options = {
49
+ :rocket_mode => true, # activate or deactivate #=> rocket output
50
+ :rocket_prompt => '#=> ', # prompt to use for the rocket
51
+ :result_prompt => '=> ', # prompt to use for normal output
52
+ :colorize => { # colors hash. Set to nil to deactivate colorizing
53
+ :rocket_prompt => :blue,
54
+ :result_prompt => :blue,
55
+ :input_prompt => nil,
56
+ :irb_errors => :red,
57
+ :stderr => :light_red,
58
+ :stdout => :dark_gray,
59
+ :input => nil,
60
+ :output => true, # wirble's output colorization
61
+ },
62
+ :result_proc => default_result_proc, # how to get the output result
63
+ :output_procs => [default_colorizer_proc], # you can modify/enhance/log your output
64
+ }
65
+
66
+ @options = default_options
67
+
68
+ default_options.each{ |key, value|
69
+ # (ugly) 1 level deep merge, maybe refactor
70
+ if key == :colorize
71
+ if user_options.has_key?(:colorize) && user_options[:colorize].nil?
72
+ @options[:colorize] = {}
73
+ else
74
+ value.each{ |key2, _|
75
+ if user_options[key] && user_options[key].has_key?(key2)
76
+ @options[:colorize][key2] = user_options[key][key2]
77
+ end
78
+ }
79
+ end
80
+ else
81
+ @options[key] = user_options.has_key?(key) ? user_options[key] : default_options[key]
82
+ end
83
+ }
84
+
85
+ # hook code into IRB
86
+ require 'fancy_irb/irb_ext'
87
+
88
+ "Enjoy your FancyIrb :)"
89
+ end
90
+
91
+ def add_output_proc(prepend = false, &proc)
92
+ action = prepend ? :unshift : :push
93
+ @options[:output_procs].send action, proc
94
+ end
95
+
96
+ def set_result_proc(&proc)
97
+ @options[:result_proc] = proc
98
+ end
99
+
100
+ def reset_height
101
+ @height_counter = []
102
+ end
103
+
104
+ def track_height(data)
105
+ lines = data.to_s.count("\n")
106
+ long_lines = data.to_s.split("\n").inject(0){ |sum, line| line.size / `tput cols`.to_i }
107
+ @height_counter << lines + long_lines
108
+ end
109
+
110
+ def get_height
111
+ 1 + ( @height_counter == [0] ? 0 : @height_counter.reduce(:+) || 0 )
112
+ end
113
+
114
+ def write_stream(stream, data, color = nil)
115
+ stream.write_non_fancy(
116
+ if defined?(Wirble) && FancyIrb.stdout_colorful && color
117
+ Wirble::Colorize::Color.escape( color ) + data.to_s + Wirble::Colorize::Color.escape(:nothing)
118
+ else
119
+ data.to_s
120
+ end
121
+ )
122
+ end
123
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fancy_irb
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 6
8
+ - 0
9
+ version: 0.6.0
10
+ platform: ruby
11
+ authors:
12
+ - Jan Lelis
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-10 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: wirble
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description: |-
34
+ FancyIrb patches your IRB to create a smooth output experience.
35
+ * Use fancy colors! You can colorize the prompts, irb errors, +stderr+ and +stdout+
36
+ * Output results as Ruby comment #=> (rocket)
37
+ * Enhance your output value, using procs
38
+ email: mail@janlelis.de
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - LICENSE
45
+ - README
46
+ files:
47
+ - .gitignore
48
+ - LICENSE
49
+ - README
50
+ - Rakefile
51
+ - VERSION
52
+ - fancy_irb.gemspec
53
+ - lib/fancy_irb.rb
54
+ - lib/fancy_irb/irb_ext.rb
55
+ has_rdoc: true
56
+ homepage: http://github.com/janlelis/fancy_irb
57
+ licenses: []
58
+
59
+ post_install_message:
60
+ rdoc_options:
61
+ - --charset=UTF-8
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirements: []
81
+
82
+ rubyforge_project:
83
+ rubygems_version: 1.3.7
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: FancyIrb patches your IRB to create a smooth output experience.
87
+ test_files: []
88
+