mirror of
https://github.com/atom/atom.git
synced 2026-02-13 08:04:56 -05:00
117 lines
3.3 KiB
Ruby
Executable File
117 lines
3.3 KiB
Ruby
Executable File
# Copyright:
|
|
# (c) 2006 syncPEOPLE, LLC.
|
|
# Visit us at http://syncpeople.com/
|
|
# Author: Duane Johnson (duane.johnson@gmail.com)
|
|
# Description:
|
|
# Makes analyzing of a Rails path + filename easier.
|
|
|
|
require 'rails/text_mate'
|
|
require 'rails/misc'
|
|
|
|
# Stores lines of text
|
|
class Buffer
|
|
# The actual lines of the text file
|
|
attr_reader :lines
|
|
# State of caret positions (both 0-based indexes)
|
|
attr_accessor :line_number, :column_number
|
|
# Stack for remembering caret positions
|
|
attr_reader :stack
|
|
|
|
# Init from a String or Buffer object
|
|
def initialize(buffer, line_number = nil, column_number = nil)
|
|
self.text = buffer
|
|
@line_number = line_number || TextMate.line_number
|
|
@column_number = column_number || TextMate.column_number
|
|
@stack = []
|
|
end
|
|
|
|
# Init from a String (filename) or FilePath
|
|
def self.new_from_file(filepath, line_number = nil, column_number = nil)
|
|
# In case it's a RailsPath, get the string representing the filepath
|
|
filepath = filepath.filepath if filepath.respond_to?(:filepath)
|
|
new(IO.read(filepath, line_number, column_number))
|
|
end
|
|
|
|
def index
|
|
@lines.slice(0...line_number).join.length
|
|
end
|
|
|
|
def current_line
|
|
lines[line_number]
|
|
end
|
|
|
|
def push_position
|
|
@stack.push [@line_number, @column_number]
|
|
end
|
|
|
|
def pop_position
|
|
@line_number, @column_number = @stack.pop
|
|
end
|
|
|
|
def to_a
|
|
@lines
|
|
end
|
|
|
|
def text
|
|
@text ||= lines.join
|
|
end
|
|
|
|
def text=(buffer)
|
|
@text = buffer.gsub("\r\n", "\n")
|
|
@lines = @text.to_a
|
|
end
|
|
|
|
def =~(other)
|
|
text =~ other
|
|
end
|
|
|
|
# Searches a region of the buffer, lines :from to :to
|
|
# Accepts a block which can evaluate to either true/false indication of a line match,
|
|
# or a Regexp indicating that the line must match the regexp for the line to match.
|
|
# An optional :direction of :backward is also accepted if the search is to be reversed.
|
|
def find(options = {}, &block)
|
|
options = {:direction => :forward}.update(options)
|
|
|
|
# Use some sensible defaults if just a direction is given
|
|
if direction = options[:direction] == :forward
|
|
from = options[:from] || line_number
|
|
to = options[:to] || lines.size - 1
|
|
from, to = to, from if from > to
|
|
direction = 1
|
|
else
|
|
from = options[:from] || 0
|
|
to = options[:to] || line_number
|
|
from, to = to, from if from < to
|
|
direction = -1
|
|
end
|
|
|
|
from.step(to, direction) do |i|
|
|
value = yield(lines[i])
|
|
value = lines[i].scan(value) if value.is_a? Regexp
|
|
return [i, value].flatten.compact if value.first
|
|
end
|
|
return nil
|
|
end
|
|
|
|
# Search for the nearest "def [method]" declaration
|
|
def find_method(options = {})
|
|
options = {:direction => :backward}.update(options)
|
|
find(options) { %r{def\s+(\w+)} }
|
|
end
|
|
|
|
# Search for the nearest "wants." declaration within a "respond_to" section.
|
|
def find_respond_to_format
|
|
m = find_method
|
|
return nil if m.nil?
|
|
from, wants = find(:direction => :backward, :from => m.first) { %r{\brespond_to\s.+\|\s*(\w+)\s*\|} }
|
|
return nil if wants.nil?
|
|
options = {:direction => lines[from] == current_line ? :forward : :backward, :from => from}
|
|
find(options) { Regexp.new(wants + '\.(\w+)') }
|
|
end
|
|
|
|
def find_nearest_string_or_symbol(current_line = current_line)
|
|
current_line.find_nearest_string_or_symbol(column_number)
|
|
end
|
|
|
|
end
|