diff --git a/lib/pry/code.rb b/lib/pry/code.rb index fd9e29c3..3734e40b 100644 --- a/lib/pry/code.rb +++ b/lib/pry/code.rb @@ -1,3 +1,6 @@ +require 'pry/code/loc' +require 'pry/code/code_range' + class Pry class << self # Convert the given object into an instance of `Pry::Code`, if it isn't @@ -26,154 +29,6 @@ class Pry # arbitrary chaining of formatting methods without mutating the original # object. class Code - # Represents a line of code. A line of code is a tuple, which consists of a - # line and a line number. A `LOC` object's state (namely, the line - # parameter) can be changed via instance methods. `Pry::Code` heavily uses - # this class. - # - # @api private - # @example - # loc = LOC.new("def example\n :example\nend", 1) - # puts loc.line - # def example - # :example - # end - # #=> nil - # - # loc.indent(3) - # loc.line #=> " def example\n :example\nend" - class LOC - - # @return [Array] - attr_accessor :tuple - - # @param [String] line The line of code. - # @param [Integer] lineno The position of the +line+. - def initialize(line, lineno) - @tuple = [line.chomp, lineno.to_i] - end - - def dup - self.class.new(line, lineno) - end - - # @return [String] - def line - tuple.first - end - - # @return [Integer] - def lineno - tuple.last - end - - # Paints the `line` of code. - # - # @param [Symbol] code_type - # @return [void] - def colorize(code_type) - tuple[0] = CodeRay.scan(line, code_type).term - end - - # Prepends the line number `lineno` to the `line`. - # - # @param [Integer] max_width - # @return [void] - def add_line_number(max_width = 0) - padded = lineno.to_s.rjust(max_width) - colorized_lineno = Pry::Helpers::BaseHelpers.colorize_code(padded) - tuple[0] = "#{ colorized_lineno }: #{ line }" - end - - # Prepends a marker "=>" or an empty marker to the +line+. - # - # @param [Integer] marker_lineno If it is equal to the `lineno`, then - # prepend a hashrocket. Otherwise, an empty marker. - # @return [void] - def add_marker(marker_lineno) - tuple[0] = - if lineno == marker_lineno - " => #{ line }" - else - " #{ line }" - end - end - - # Indents the `line` with +distance+ spaces. - # - # @param [Integer] distance - # @return [void] - def indent(distance) - tuple[0] = "#{ ' ' * distance }#{ line }" - end - end - - # Represents a range of lines in a code listing. - # - # @api private - class CodeRange - - # @param [Integer] start_line - # @param [Integer?] end_line - def initialize(start_line, end_line = nil) - @start_line = start_line - @end_line = end_line - force_set_end_line - end - - # @param [Array] lines - # @return [Range] - def indices_range(lines) - Range.new(*indices(lines)) - end - - private - - attr_reader :start_line, :end_line - - # If `end_line` is equal to `nil`, then calculate it from the first - # parameter, `start_line`. Otherwise, leave it as it is. - # @return [void] - def force_set_end_line - if start_line.is_a?(Range) - set_end_line_from_range - else - @end_line ||= start_line - end - end - - # Finds indices of `start_line` and `end_line` in the given Array of - # +lines+. - # - # @param [Array] lines - # @return [Array] - def indices(lines) - [find_start_index(lines), find_end_index(lines)] - end - - # @return [Integer] - def find_start_index(lines) - return start_line if start_line < 0 - lines.index { |loc| loc.lineno >= start_line } || lines.length - end - - # @return [Integer] - def find_end_index(lines) - return end_line if end_line < 0 - (lines.index { |loc| loc.lineno > end_line } || 0) - 1 - end - - # For example, if the range is 4..10, then `start_line` would be equal to - # 4 and `end_line` to 10. - # @return [void] - def set_end_line_from_range - @end_line = start_line.last - @end_line -= 1 if start_line.exclude_end? - @start_line = start_line.first - end - end - - class << self include MethodSource::CodeHelpers diff --git a/lib/pry/code/code_range.rb b/lib/pry/code/code_range.rb new file mode 100644 index 00000000..13ae2540 --- /dev/null +++ b/lib/pry/code/code_range.rb @@ -0,0 +1,70 @@ +class Pry + class Code + + # Represents a range of lines in a code listing. + # + # @api private + class CodeRange + + # @param [Integer] start_line + # @param [Integer?] end_line + def initialize(start_line, end_line = nil) + @start_line = start_line + @end_line = end_line + force_set_end_line + end + + # @param [Array] lines + # @return [Range] + def indices_range(lines) + Range.new(*indices(lines)) + end + + private + + attr_reader :start_line, :end_line + + # If `end_line` is equal to `nil`, then calculate it from the first + # parameter, `start_line`. Otherwise, leave it as it is. + # @return [void] + def force_set_end_line + if start_line.is_a?(Range) + set_end_line_from_range + else + @end_line ||= start_line + end + end + + # Finds indices of `start_line` and `end_line` in the given Array of + # +lines+. + # + # @param [Array] lines + # @return [Array] + def indices(lines) + [find_start_index(lines), find_end_index(lines)] + end + + # @return [Integer] + def find_start_index(lines) + return start_line if start_line < 0 + lines.index { |loc| loc.lineno >= start_line } || lines.length + end + + # @return [Integer] + def find_end_index(lines) + return end_line if end_line < 0 + (lines.index { |loc| loc.lineno > end_line } || 0) - 1 + end + + # For example, if the range is 4..10, then `start_line` would be equal to + # 4 and `end_line` to 10. + # @return [void] + def set_end_line_from_range + @end_line = start_line.last + @end_line -= 1 if start_line.exclude_end? + @start_line = start_line.first + end + end + + end +end diff --git a/lib/pry/code/loc.rb b/lib/pry/code/loc.rb new file mode 100644 index 00000000..7ef0a39f --- /dev/null +++ b/lib/pry/code/loc.rb @@ -0,0 +1,87 @@ +class Pry + class Code + + # Represents a line of code. A line of code is a tuple, which consists of a + # line and a line number. A `LOC` object's state (namely, the line + # parameter) can be changed via instance methods. `Pry::Code` heavily uses + # this class. + # + # @api private + # @example + # loc = LOC.new("def example\n :example\nend", 1) + # puts loc.line + # def example + # :example + # end + # #=> nil + # + # loc.indent(3) + # loc.line #=> " def example\n :example\nend" + class LOC + + # @return [Array] + attr_accessor :tuple + + # @param [String] line The line of code. + # @param [Integer] lineno The position of the +line+. + def initialize(line, lineno) + @tuple = [line.chomp, lineno.to_i] + end + + def dup + self.class.new(line, lineno) + end + + # @return [String] + def line + tuple.first + end + + # @return [Integer] + def lineno + tuple.last + end + + # Paints the `line` of code. + # + # @param [Symbol] code_type + # @return [void] + def colorize(code_type) + tuple[0] = CodeRay.scan(line, code_type).term + end + + # Prepends the line number `lineno` to the `line`. + # + # @param [Integer] max_width + # @return [void] + def add_line_number(max_width = 0) + padded = lineno.to_s.rjust(max_width) + colorized_lineno = Pry::Helpers::BaseHelpers.colorize_code(padded) + tuple[0] = "#{ colorized_lineno }: #{ line }" + end + + # Prepends a marker "=>" or an empty marker to the +line+. + # + # @param [Integer] marker_lineno If it is equal to the `lineno`, then + # prepend a hashrocket. Otherwise, an empty marker. + # @return [void] + def add_marker(marker_lineno) + tuple[0] = + if lineno == marker_lineno + " => #{ line }" + else + " #{ line }" + end + end + + # Indents the `line` with +distance+ spaces. + # + # @param [Integer] distance + # @return [void] + def indent(distance) + tuple[0] = "#{ ' ' * distance }#{ line }" + end + end + + end +end