howl.Scintilla

local sci

before_each ->
  sci = Scintilla!

character_count()

returns the number of characters in the document

sci\insert_text 0, '123'
assert.equal 3, sci\character_count!
sci\insert_text 0, 'HƏllo'
assert.equal 8, sci\character_count!

is_multibyte()

returns true when the document contains multibyte characters

assert.is_false sci\is_multibyte()
sci\insert_text 0, 'HƏllo'
assert.is_true sci\is_multibyte()
sci\delete_range 1, 4
assert.is_false sci\is_multibyte()

char_offset(byte_offset)

returns the char_offset for the given byte_offset

sci\insert_text 0, 'äåö'
for p in *{
  {0, 0},
  {2, 1},
  {4, 2},
  {6, 3},
}
  assert.equal p[2], sci\char_offset p[1]

byte_offset(char_offset)

returns byte offsets for all character offsets passed as parameters

sci\insert_text 0, 'äåö'
for p in *{
  {0, 0},
  {2, 1},
  {4, 2},
  {6, 3},
}
  assert.equal p[1], sci\byte_offset p[2]

(offset handling stress test)

returns the correct result as compared to ustring

build = {}
line = 'äåöLinƏΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣbutnowforsomesingleΤΥΦΧĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏ'
for i = 1,3000
  build[#build + 1] = line
s = table.concat build, '\n'
sci\insert_text 0, s

for i = 1, 3000 * line.ulen, 3007
  assert.equal s\byte_offset(i), sci\byte_offset(i - 1) + 1

for i = 1, 3000 * #line, 3007
  assert.equal s\char_offset(i), sci\char_offset(i - 1) + 1

for i = 2000 * #line, 100, -2003
  sci\delete_range i, 20
  sci\insert_text i, 'ordinary ascii text here'
  s = sci\get_text!
  c_offset = sci\char_offset(i + 100 - 1) + 1
  assert.equal s\char_offset(i + 100), c_offset
  assert.equal s\byte_offset(c_offset), sci\byte_offset(c_offset - 1) + 1

color handling

automatically converts between color values and strings

sci\style_set_fore 1, '#112233'
assert.equal sci\style_get_fore(1), '#112233'

colors can be specified by name

sci\style_set_fore 1, 'green'
assert.equal sci\style_get_fore(1), 'green'

.dispatch

calls handlers within a coroutine

in_coroutine = false
sci.listener = on_keypress: ->
  _, main = coroutine.running!
  in_coroutine = main == false
sci.dispatch sci.sci_ptr, 'key-press', {}
assert.is_true in_coroutine

returns the value returned by the handler

sci.listener = on_keypress: -> true
assert.is_true sci.dispatch sci.sci_ptr, 'key-press', {}

returns true to indicated handled if handler yields

sci.listener = on_keypress: -> coroutine.yield false
assert.is_true sci.dispatch sci.sci_ptr, 'key-press', {}

calls the on_error handler with the error if a handler raise one

sci.listener = {
  on_keypress: -> error 'BOOM!'
  on_error: spy.new -> nil
}
sci.dispatch sci.sci_ptr, 'key-press', {}
assert.spy(sci.listener.on_error).was_called_with('BOOM!')

(for key-press event)

calls the on_keypress handler if present

sci.listener = on_keypress: spy.new -> nil
sci.dispatch sci.sci_ptr, 'key-press', {}
assert.spy(sci.listener.on_keypress).was_called(1)