ruby - Composing slices of slices -
i've been thinking problem couple of days , can't find elegant solution life of me.
in app have text
class wrapper around string
:
class text < struct.new(:string, :style) def [](start, len) text.new(string[start, len], style) end def length string.length end def to_s case style when :bold "**" + string + "**" when :italic "_" + string +"_" else string end end def inspect "<[#{style}] #{string}>" end end
i have line
class array of text objects:
class line < struct.new(:texts) def [](start, len) # todo should return new line object. end def length texts.map(&:length).reduce(&:+) end def to_s texts.map(&:to_s).join end def inspect texts.map(&:inspect).join(" ") end end
the question is, how can implement #[]
in line
returns new line
object "correctly" slices contained text
objects?
the idea imitate slicing behavior of string
. example:
line = line.new([text.new("abcdef", :bold), text.new("ghijkl", :default)]) puts line[0, 2] # => **ab** p line[0, 2] # => "<[:bold] ab>" puts line[3, 6] # => **def**ghi p line[3, 6] # => "<[:bold] def> <[:default] ghi>"
keep in mind length of text
object length of string
member:
a = text.new("abc", :bold) puts # => **abc** puts a.length # => 3
and length of line
object sum of lengths of texts
:
line = line.new([text.new("abcdef", :bold), text.new("ghijkl", :default)]) puts line.length # => 12
everything i've tried involves stupid amount of complicated conditionals , convoluted temporary variables, , feel there's simpler solution lurking underneath all.
here's snippet may you:
class line def pos_to_index_and_offset(pos) raise argumenterror if !texts or texts.empty? index = 0 offset = pos while offset >= (size = texts[index].length) offset -= size index += 1 raise argumenterror if index > texts.length end return [index, offset] end end
Comments
Post a Comment