You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
2.8 KiB
Ruby
113 lines
2.8 KiB
Ruby
10 years ago
|
# This is a script for vim-ruby for sorting collections
|
||
|
#
|
||
|
# Author: Igor Vergeichik <iverg@mail.ru>
|
||
|
# Sponsor: Tom Sawyer <transami@transami.net>
|
||
|
# Copyright (c) 2002 Tom Saywer
|
||
|
|
||
|
class YCollection
|
||
|
def initialize(rule)
|
||
|
@buffer=VIM::Buffer.current
|
||
|
@window=VIM::Window.current
|
||
|
@lnum = @window.cursor[0]
|
||
|
@key=@buffer[@lnum].scan(/^([^:]+[^\s])\s*:/)
|
||
|
# Find collection bounds
|
||
|
r = bounds
|
||
|
# If collection found - resort it
|
||
|
replace(r, resort((parse r), rule)) if r[1]>0
|
||
|
end
|
||
|
|
||
|
# Detect bounds of YAML collection
|
||
|
# Input: no
|
||
|
# Output: Array - range of detected collection
|
||
|
def bounds
|
||
|
lnum = @lnum
|
||
|
# If line begins with a dash - this is one of collection items
|
||
|
if @buffer[lnum]=~/\s*-/
|
||
|
coll_bounds(lnum)
|
||
|
else
|
||
|
# otherwise we need to find parent item
|
||
|
ind = VIM::evaluate("indent(#{lnum})").to_i
|
||
|
while lnum>0
|
||
|
if VIM::evaluate("indent(#{lnum})").to_i<ind
|
||
|
return coll_bounds(lnum)
|
||
|
else lnum=lnum-1
|
||
|
end
|
||
|
end
|
||
|
# No parent item found - no collection detected
|
||
|
[0, 0]
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Detect bounds of YAML collection
|
||
|
# Called only for line which is a item of collection
|
||
|
# Input: line number
|
||
|
# Output: Array - range of detected collection
|
||
|
def coll_bounds(lnum)
|
||
|
ind = VIM::evaluate("indent(#{lnum})").to_i
|
||
|
start = fin = lnum
|
||
|
# Detect beginning of collection
|
||
|
ln = lnum - 1
|
||
|
while ln>0
|
||
|
curr_ind = VIM::evaluate("indent(#{ln})").to_i
|
||
|
break if curr_ind<ind || (curr_ind==ind && @buffer[ln]!~/\s*-/)
|
||
|
start = ln
|
||
|
ln = ln - 1
|
||
|
end
|
||
|
# Detect end of collection
|
||
|
ln = lnum + 1
|
||
|
while ln<=@buffer.count
|
||
|
curr_ind = VIM::evaluate("indent(#{ln})").to_i
|
||
|
break if curr_ind<ind || (curr_ind==ind && @buffer[ln]!~/\s*-/)
|
||
|
fin = ln
|
||
|
ln = ln + 1
|
||
|
end
|
||
|
[start,fin]
|
||
|
end
|
||
|
|
||
|
# Parse data in YAML collection to separate collection's items
|
||
|
# Input: range of lines of collection in document
|
||
|
# Output: Array, each element is weight and Array of lines
|
||
|
def parse(range)
|
||
|
idx = -1
|
||
|
data = Array.new
|
||
|
ind = VIM::evaluate("indent(#{range[0]})").to_i
|
||
|
range[0].upto(range[1]) do |x|
|
||
|
if VIM::evaluate("indent(#{x})").to_i==ind
|
||
|
idx = idx+1
|
||
|
data[idx]=Array.new
|
||
|
data[idx][0]=Array.new
|
||
|
data[idx][1]=@buffer[x].scan(/\s*(.*)\s*$/) if @key.empty?
|
||
|
end
|
||
|
data[idx][1]=@buffer[x].scan(/:(.*)$/) if @buffer[x]=~/^#{@key}\s*:/
|
||
|
data[idx][0].push @buffer[x]
|
||
|
end
|
||
|
data
|
||
|
end
|
||
|
|
||
|
# Sort collection.
|
||
|
# Input: parsed collection, sorting rule (lambda)
|
||
|
# Output: Sorted array of collection's lines
|
||
|
def resort(data, rule)
|
||
|
lines = Array.new
|
||
|
data.sort { |a,b|
|
||
|
if a[1].nil?
|
||
|
1
|
||
|
elsif b[1].nil?
|
||
|
-1
|
||
|
else
|
||
|
rule.call(a[1], b[1])
|
||
|
end
|
||
|
}.each { |x| x[0].each { |y| lines.push y }}
|
||
|
lines
|
||
|
end
|
||
|
|
||
|
# Replace lines of collection in document with sorted lines
|
||
|
def replace(range, lines)
|
||
|
range[0].upto(range[1]) {|x| @buffer[x] = lines[x-range[0]] }
|
||
|
end
|
||
|
end
|
||
|
|
||
|
# Init collection
|
||
|
#YCollection.new lambda {|a,b| b<=>a}
|
||
|
|