howl.BufferLines
buffer = (text) ->
with Buffer {}
.text = text
# operator returns number of lines in the buffer
b = buffer 'hello\n world\nagain!'
assert.equal #b.lines, 3
delete(start, end) deletes the the lines [start, end]
b = buffer 'hellØ\nwØrld\nagain!'
b.lines\delete 1, 2
assert.equal b.text, 'again!'
at_pos(pos) returns the line at <pos>
lines = buffer('Øne\ntwØ\nthree').lines
line = lines\at_pos 5
assert.equal 'twØ', line.text
supports iterating using ipairs
b = buffer 'one\ntwo\nthree'
for i, line in ipairs b.lines
assert.equal line, b.lines[i]
supports iterating using pairs
b = buffer 'one\ntwo\nthree'
for i, line in pairs b.lines
assert.equal line, b.lines[i]
Line objects
buf = nil
lines = nil
before_each ->
buf = buffer 'hƏllØ\n wØrld\nagain!'
lines = buf.lines
.buffer points to the corresponding buffer
assert.same buf, lines[1].buffer
.nr holds the line number
assert.equal lines[1].nr, 1
.text returns the text of the specified line, sans linebreak
assert.equal lines[1].text, 'hƏllØ'
assert.equal lines[2].text, ' wØrld'
assert.equal lines[3].text, 'again!'
tostring(line) gives the same as .text
assert.equal tostring(lines[1]), lines[1].text
.indentation returns the indentation for the line
assert.equal lines[1].indentation, 0
assert.equal lines[2].indentation, 2
.indentation = <nr> set the indentation for the line to <nr>
lines[3].indentation = 4
assert.equal 'hƏllØ\n wØrld\n again!', buf.text
.start_pos returns the start position for line
assert.equal lines[2].start_pos, 7
buf.text = ''
assert.equal lines[1].start_pos, 1
.end_pos returns the end position for line, right before the newline
assert.equal lines[1].end_pos, 6
buf.text = ''
assert.equal lines[1].end_pos, 1
.byte_start_pos returns the byte start position for line
buf.text = 'åäö\nwØrld'
assert.equal lines[2].byte_start_pos, 8
buf.text = ''
assert.equal lines[1].byte_start_pos, 1
.byte_end_pos returns the byte end position for line
buf.text = 'åäö\nwØrld'
assert.equal lines[1].byte_end_pos, 7
buf.text = ''
assert.equal lines[1].byte_end_pos, 1
.previous returns the line above this one, or nil if none
assert.equal lines[2].previous, lines[1]
assert.is_nil lines[1].previous
.previous_non_blank returns the first preceding non-blank line, or nil if none
assert.is_nil lines[1].previous_non_blank
assert.equal lines[1], lines[2].previous_non_blank
lines\insert 3, ''
assert.equal lines[2], lines[4].previous_non_blank
.next_non_blank returns the first succeding non-blank line, or nil if none
assert.is_nil lines[3].next_non_blank
assert.equal lines[3], lines[2].next_non_blank
lines\insert 3, ''
assert.equal lines[4], lines[2].next_non_blank
.next returns the line below this one, or nil if none
assert.equal lines[1].next, lines[2]
assert.is_nil lines[3].next
.indent() indents the line by <config.indent>
config.indent = 2
buf.lines[1]\indent!
assert.equal ' hƏllØ\n wØrld\nagain!', buf.text
buf.config.indent = 1
buf.lines[3]\indent!
assert.equal ' hƏllØ\n wØrld\n again!', buf.text
.unindent() unindents the line by <config.indent>
buf.text = ' first\n second'
config.indent = 2
buf.lines[1]\unindent!
assert.equal buf.text, 'first\n second'
buf.config.indent = 1
buf.lines[2]\unindent!
assert.equal buf.text, 'first\n second'
#line returns the length of the line
assert.equal #lines[1], 5
lines are equal if they have the same text
lines[2] = 'hƏllØ'
assert.equal lines[1], lines[2]
string methods can be accessed directly on the object
buf.text = 'first line'
line = lines[1]
assert.equal 'fi', line\sub(1,2)
assert.equal 8, (line\find('in'))
assert.equal 'first win', (line\gsub('line', 'win'))
string properties can be accessed directly on the object
assert.is_false lines[1].is_empty
assert.is_false lines[1].is_blank
lines[1] = ''
assert.is_true lines[1].is_empty
assert.is_true lines[1].is_blank
.text = <content>
replaces the line text with <content>
lines[1].text = 'Hola'
assert.equal buf.text, 'Hola\n wØrld\nagain!'
raises an error if <content> is nil
assert.raises 'nil', -> lines[1].text = nil
.chunk
a Chunk object for the line, disregarding the newline
buf.text = 'hƏllØ\nbare'
chunk = lines[1].chunk
assert.equal 'Chunk', typeof chunk
assert.equal 'hƏllØ', chunk.text
assert.equal 1, chunk.start_pos
assert.equal 5, chunk.end_pos
chunk = lines[2].chunk
assert.equal 'bare', chunk.text
assert.equal 7, chunk.start_pos
assert.equal 10, chunk.end_pos
is an empty chunk for empty lines
buf.text = '\n'
chunk = lines[1].chunk
assert.equal '', chunk.text
assert.equal 1, chunk.start_pos
assert.equal 0, chunk.end_pos
chunk = lines[2].chunk
assert.equal '', chunk.text
assert.equal 2, chunk.start_pos
assert.equal 1, chunk.end_pos
[nr]
returns a line object for the specified line
lines = buffer('hello\n world\nagain!').lines
assert.equal lines[1].text, 'hello'
returns nil if the line number is invalid
lines = buffer('hello!').lines
assert.is_nil lines[2]
assert.is_nil lines[0]
[nr] = <value>
replaces the text of the specified line with <value>
b = buffer 'hellØ\nwØrld'
b.lines[1] = 'hØla'
assert.equal b.text, 'hØla\nwØrld'
removes the entire line if value is nil
b = buffer 'gØØdbye\ncruel\nwØrld'
b.lines[2] = nil
assert.equal 'gØØdbye\nwØrld', b.text
b.lines[1] = nil
assert.equal 'wØrld' ,b.text
raises an error if the line number is invalid
b = buffer 'hello!'
assert.raises 'Invalid index', -> b.lines['foo'] = 'bar'
range(start, end)
returns a table with lines [start, end]
lines = buffer('one\ntwo\nthree').lines
range = lines\range 1, 2
assert.same { lines[1], lines[2] }, range
start can be greater than end
lines = buffer('one\ntwo\nthree').lines
range = lines\range 2, 1
assert.same { lines[1], lines[2] }, range
for_text_range(start_pos, end_pos)
returns a table with lines between [start_pos, end_pos]
lines = buffer('one\ntwo\nthree').lines
range = lines\for_text_range 2, 6
assert.same { lines[1], lines[2] }, range
start_pos can be greater than end_pos
lines = buffer('one\ntwo\nthree').lines
range = lines\for_text_range 6, 1
assert.same { lines[1], lines[2] }, range
does not include lines only touched at the start or end positions
lines = buffer('one\ntwo\nthree').lines
range = lines\for_text_range lines[1].end_pos, lines[3].start_pos
assert.same { lines[2] }, range
append(text)
append(text) appends <text> with the necessary newlines
b = buffer 'one\ntwo'
b.lines\append 'three'
assert.equal b.text, 'one\ntwo\nthree\n'
b = buffer 'one\ntwo\n'
b.lines\append 'three'
assert.equal b.text, 'one\ntwo\nthree\n'
returns a line object for the newly appended line
b = buffer 'line'
line = b.lines\append 'omega'
assert.equal line, b.lines[2]
insert(line_nr, text)
inserts a new line at <nr> with <text>
b = buffer 'one\ntwo'
b.lines\insert 1, 'half'
assert.equal b.text, 'half\none\ntwo'
b.lines\insert 3, '1.5'
assert.equal b.text, 'half\none\n1.5\ntwo'
appends the line if line_nr is just beyond the last line
b = buffer 'first\nsecond'
b.lines\insert 3, 'foo'
assert.equal b.text, 'first\nsecond\nfoo\n'
raises an error if <line_nr> is invalid
b = buffer 'first\nsecond'
assert.raises 'Invalid', -> b.lines\insert 0, 'foo'
assert.raises 'Invalid', -> b.lines\insert 4, 'foo'
returns a line object for the newly inserted line
b = buffer 'line'
line = b.lines\insert 1, 'alpha'
assert.equal line, b.lines[1]