Module: FancyIrb

Extended by:
SizeDetector
Defined in:
lib/fancy_irb.rb,
lib/fancy_irb/version.rb,
lib/fancy_irb/size_detector.rb,
lib/fancy_irb/terminal_info.rb,
lib/fancy_irb/error_capturer.rb,
lib/fancy_irb/implementation.rb

Defined Under Namespace

Modules: SizeDetector, TerminalInfo Classes: ErrorCapturer

Constant Summary collapse

DEFAULT_OPTIONS =
{
  :rocket_mode     => true,       # activate or deactivate #=> rocket output
  :rocket_prompt   => '#=> ',     # prompt to use for the rocket
  :result_prompt   => '=> ',      # prompt to use for normal output
  :unicode_display_width => true, # set to false if you don't want to check for proper
                                  # string width for better performance
  :colorize => {                  # colors hash. Set to nil to deactivate colors
    :rocket_prompt => [:blue],
    :result_prompt => [:blue],
    :input_prompt  => nil,
    :irb_errors    => [:red, :clean],
    :stderr        => [:red, :bright],
    :stdout        => nil,
    :input         => nil,
   },
}
SKIP_ROCKET_METHODS =
%w[
  system
  spawn
].map(&:to_sym)
TRACK_HEIGHT_INPUT_METHODS =

TODO: each_byte, each_char, each_codepoint, each, etc

%w[
  binread
  read
  gets
  getc
  getbyte
  readbyte
  readchar
  readline
  readlines
  readpartial
  sysread
].map(&:to_sym)
VERSION =
'1.4.3'

Class Attribute Summary collapse

Class Method Summary collapse

Methods included from SizeDetector

height_of, width_of

Class Attribute Details

.error_capturerObject (readonly)

Returns the value of attribute error_capturer.



7
8
9
# File 'lib/fancy_irb/implementation.rb', line 7

def error_capturer
  @error_capturer
end

.skip_next_rocketObject

Returns the value of attribute skip_next_rocket.



8
9
10
# File 'lib/fancy_irb/implementation.rb', line 8

def skip_next_rocket
  @skip_next_rocket
end

Class Method Details

.append_input_color(string) ⇒ Object

Note: No reset, relies on next one



79
80
81
82
83
84
85
# File 'lib/fancy_irb/implementation.rb', line 79

def append_input_color(string)
  if input_color = @options[:colorize][:input]
    string + Paint.color(*Array(input_color))
  else
    string
  end
end

.apply_user_options(user_options) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/fancy_irb/implementation.rb', line 33

def apply_user_options(user_options)
  DEFAULT_OPTIONS.each{ |key, value|
    # (ugly) 1 level deep merge, maybe refactor
    if key == :colorize
      if user_options.has_key?(:colorize) && user_options[:colorize].nil?
        @options[:colorize] = {}
      else
        value.each{ |key2, _|
          if user_options[key] && user_options[key].has_key?(key2)
            @options[:colorize][key2] = user_options[key][key2]
          end
        }
      end
    else
      @options[key] =
          user_options.has_key?(key) ? user_options[key] : DEFAULT_OPTIONS[key]
    end
  }
end

.colorize(string, colorize_key) ⇒ Object



74
75
76
# File 'lib/fancy_irb/implementation.rb', line 74

def colorize(string, colorize_key)
  Paint::NOTHING + Paint[string, *Array(@options[:colorize][colorize_key])]
end

.extend!Object

hook into IRB



19
20
21
22
23
# File 'lib/fancy_irb/implementation.rb', line 19

def extend!
  require_relative 'irb_ext'
  require_relative 'core_ext'
  require_relative 'clean_up'
end

.get_cols_to_show_from_output_and_offset(output, offset) ⇒ Object



118
119
120
# File 'lib/fancy_irb/implementation.rb', line 118

def get_cols_to_show_from_output_and_offset(output, offset)
  offset + width_of(@options[:rocket_prompt] + output)
end

.get_offset_from_irb_scanner(irb_scanner) ⇒ Object



113
114
115
116
# File 'lib/fancy_irb/implementation.rb', line 113

def get_offset_from_irb_scanner(irb_scanner)
  last_line = irb_scanner.instance_variable_get(:@line).split("\n").last
  1 + @current_indent + width_of(last_line)
end

.handle_prompt(prompt, scanner_indent, track_indent) ⇒ Object



63
64
65
66
67
68
# File 'lib/fancy_irb/implementation.rb', line 63

def handle_prompt(prompt, scanner_indent, track_indent)
  @tracked_indent = 2 if track_indent
  @current_indent = width_of(prompt) + scanner_indent + @tracked_indent

  append_input_color colorize(prompt, :input_prompt)
end

.output_value(context, scanner) ⇒ Object



87
88
89
# File 'lib/fancy_irb/implementation.rb', line 87

def output_value(context, scanner)
  show_output(context.inspect_last_value, scanner)
end

.patch_stream(object, stream_name) ⇒ Object



144
145
146
147
148
149
# File 'lib/fancy_irb/implementation.rb', line 144

def patch_stream(object, stream_name)
  object.define_singleton_method :write do |data|
    FancyIrb.track_height data
    super FancyIrb.colorize(data, stream_name)
  end
end

.present_and_clear_captured_error!Object



155
156
157
158
159
160
161
162
163
164
# File 'lib/fancy_irb/implementation.rb', line 155

def present_and_clear_captured_error!
  if @error_capturer
    @error_capturer.restore_original_stdout
    $stderr.puts colorize(
      @error_capturer.error_string.chomp,
      :irb_errors,
    )
    @error_capturer = nil
  end
end

.register_error_capturer!Object



151
152
153
# File 'lib/fancy_irb/implementation.rb', line 151

def register_error_capturer!
  @error_capturer = ErrorCapturer.new
end

.register_height_trackers(object, methods_) ⇒ Object

TODO testing and improving, e.g. getc does not contain ā€œnā€



123
124
125
126
127
128
129
130
131
132
133
# File 'lib/fancy_irb/implementation.rb', line 123

def register_height_trackers(object, methods_)
  methods_.each{ |method_|
    if object.respond_to?(method_)
      object.send :define_singleton_method, method_ do |*args|
        res = super(*args)
        FancyIrb.track_height(res)
        res
      end
    end
  }
end

.register_skipped_rockets(object_class, methods_) ⇒ Object



135
136
137
138
139
140
141
142
# File 'lib/fancy_irb/implementation.rb', line 135

def register_skipped_rockets(object_class, methods_)
  methods_.each{ |method_|
    object_class.send :define_method, method_ do |*args|
      FancyIrb.skip_next_rocket = true
      super(*args)
    end
  }
end

.reset_line!Object



58
59
60
61
# File 'lib/fancy_irb/implementation.rb', line 58

def reset_line!
  @tracked_height = 0
  @tracked_indent = 0
end

.set_defaultsObject



25
26
27
28
29
30
31
# File 'lib/fancy_irb/implementation.rb', line 25

def set_defaults
  @skip_next_rocket = false
  @current_indent = Float::INFINITY

  @options = DEFAULT_OPTIONS.dup
  @options[:colorize] = @options[:colorize].dup if @options[:colorize]
end

.show_output(output, scanner) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/fancy_irb/implementation.rb', line 91

def show_output(output, scanner)
  if @options[:rocket_mode] && !@skip_next_rocket && !output.include?("\n")
    offset = get_offset_from_irb_scanner(scanner)
    cols_to_show  = get_cols_to_show_from_output_and_offset(output, offset)
    lines_to_show = 1 + @tracked_height

    if TerminalInfo.lines > lines_to_show && TerminalInfo.cols > cols_to_show
      print \
        Paint::NOTHING +
        TerminalInfo::TPUT[:sc] +                    # save current cursor position
        TerminalInfo::TPUT[:cuu1] * lines_to_show +  # move cursor upwards    to the original input line
        TerminalInfo::TPUT[:cuf1] * offset +         # move cursor rightwards to the original input offset
        colorize(@options[:rocket_prompt], :rocket_prompt) +   # draw rocket prompt
        output +                                               # draw output
        TerminalInfo::TPUT[:rc]                      # return to normal cursor position
      return
    end
  end
  @skip_next_rocket = false
  puts colorize(@options[:result_prompt], :result_prompt) + output
end

.start(user_options = {}) ⇒ Object



10
11
12
13
14
15
16
# File 'lib/fancy_irb/implementation.rb', line 10

def start(user_options = {})
  set_defaults
  apply_user_options(user_options)
  reset_line!
  extend!
  true
end

.track_height(data) ⇒ Object



70
71
72
# File 'lib/fancy_irb/implementation.rb', line 70

def track_height(data)
  @tracked_height += height_of(data, TerminalInfo.cols)
end

.unicode_display_width?Boolean Also known as: east_asian_width?

Returns:

  • (Boolean)


53
54
55
# File 'lib/fancy_irb/implementation.rb', line 53

def unicode_display_width?
  @options[:unicode_display_width] || @options[:east_asian_width]
end