Files
atom/bundles/ruby-on-rails.tmbundle/Support/lib/rails/buffer.rb
2012-09-28 17:28:25 -06:00

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