howl.ui.List
sci = Scintilla!
buf = ActionBuffer sci
sci.listener =
on_text_inserted: buf\_on_text_inserted
on_text_deleted: buf\_on_text_deleted
list = nil
before_each ->
buf.text = ''
list = List buf, 1
# returns the number of items
list.items = {'one', 'two', 'three'}
assert.equal #list, 3
.showing() returns true if the list is currently showing
assert.is_false list.showing
list.items = {'one'}
list\show!
assert.is_true list.showing
shows single column items each on one line
list.items = {'one', 'twö', 'three'}
list\show!
assert.equal 'one\ntwö\nthree\n', buf.text
allows items to be Chunks
source_buf = Buffer!
source_buf.text = 'source'
chunk = source_buf\chunk 1, 6
list.items = { chunk }
list\show!
assert.equal 'source\n', buf.text
shows multi column items each on one line, in separate columns
list.items = {
{'first', 'item one'},
{'second', 'item two'}
}
list\show!
assert.equal buf.text, [[
first item one
second item two
]]
shows nothing for an empty list
list.items = {}
list\show!
assert.equal buf.text, '\n'
skips the trailing newline if .trailing_newline is false
list.items = {'one', 'two'}
list.trailing_newline = false
list\show!
assert.equal buf.text, 'one\ntwo'
it is styled using the list_caption style
list.items = { { 'first' } }
list.caption = 'Caption'
list\show!
assert.equal style.at_pos(buf, 1), 'list_caption'
list.items = { {'first', 'item one'} }
list.headers = { 'Column 1', 'Column 2' }
list\show!
assert.equal buf.text, [[
Column 1 Column 2
first item one
]]
.offset is set to the index of the first item shown
list.items = {'one', 'two', 'three'}
list\show!
assert.equal list.offset, 1
.last_shown is set to the index of the last item shown
list.items = {'one', 'two', 'three'}
list\show!
assert.equal list.last_shown, 3
does not change the cursor position for the underlying scintilla
buf.text = 'hello'
l = List buf, 6
l.items = {'one', 'two'}
sci\set_current_pos 2
l\show!
assert.equal sci\get_current_pos!, 2
l = List buf, 1
l.items = {'one', 'two'}
sci\document_end!
l\show!
assert.equal sci\get_current_pos!, #buf.text
.nr_shown is set to the amount of items shown
list.items = {'one', 'two', 'three'}
list\show!
assert.equal 3, list.nr_shown
list.max_height = 2
list\show!
assert.equal 1, list.nr_shown
all properties can be changed after initial assignment
list.items = { 'one', 'two' }
list\show!
list.items = { 'three', 'four' }
list\show!
assert.equal buf.text, 'three\nfour\n'
list.headers = { 'Column 1', 'Column 2' }
list.items = { { 'three', 'four' } }
list\show!
assert.equal buf.text, [[
Column 1 Column 2
three four
]]
resets offset when items are reassigned
list.items = { 'one', 'two', 'three' }
list.max_height = 2
list\show!
list\next_page!
list.items = { 'one', 'two' }
list\show!
assert.match buf.text, '^one'
clear()
removes a rendered list from the buffer
buf.text = '||'
list = List buf, 2
list.items = {'one', 'two'}
list\show!
list\clear!
assert.equal '||', buf.text
does nothing if the list has not been rendered yet or was empty
buf.text = '||'
list = List buf, 2
list\clear!
assert.equal '||', buf.text
list.items = {}
list\show!
list\clear!
assert.equal '||', buf.text
(when .caption is set)
shows it above the items
list.items = { 'first' }
list.caption = 'This is a fine list:'
list\show!
assert.equal buf.text, [[
This is a fine list:
first
]]
(when .offset is set)
shows items starting from #offset
list.items = {'one', 'two', 'three'}
list.offset = 2
list\show!
assert.match buf.text, 'two\nthree'
assert.is_not.match buf.text, 'one'
(when .max_height is set)
with only .items set it shows only up to max_height lines
list.items = {'one', 'two', 'three'}
list.max_height = 2
list\show!
assert.match buf.text, 'one'
assert.is_not.match buf.text, 'two'
list.max_height = math.huge
list\show!
assert.equal 'one\ntwo\nthree\n', buf.text
it takes caption into account when set
list.items = {'one', 'two', 'three'}
list.caption = 'Two\nliner'
list.max_height = 4
list\show!
assert.match buf.text, 'one'
assert.is_not.match buf.text, 'two'
list.items = {'one', 'two'}
list.headers = { 'Takes up one line' }
list.max_height = 2
list\show!
assert.match buf.text, 'one'
assert.is_not.match buf.text, 'two'
displays info about the currently shown items
list.items = {'one', 'two', 'three'}
list.max_height = 2
list\show!
assert.match buf.text, 'showing 1 %- 1 out of 3'
(when .min_height is set)
is ignored when the list is bigger than the value
list.items = {'one', 'two', 'three'}
list.min_height = 2
list\show!
assert.equals 3, list.height
is ignored when .max_height is greater
list.items = {'one' }
list.min_height = 2
list.max_height = 1
list\show!
assert.equals 1, list.height
adds lines to ensure the given value
list.items = {'one' }
list.min_height = 3
list\show!
assert.equals 'one\n\n\n', buf.text
sets .filler_text for each filler line if specified
list.items = {'one' }
list.min_height = 2
list.filler_text = 'X'
list\show!
assert.equals 'one\nX\n', buf.text
.height
is set to the number of lines used for displaying the list
list.items = {'one', 'two', 'three'}
list\show!
assert.equal 3, list.height
list.items = {'one', 'two', 'three'}
list.headers = { 'Column 1' }
list\show!
assert.equal 4, list.height
includes caption
list.items = {'one', 'two'}
list.caption = 'This is a\nfine list:'
list\show!
assert.equal 4, list.height
accounts for a truncated list
list.items = {'one', 'two', 'three'}
list.max_height = 3
list\show!
assert.equal 3, list.height
(when items are not strings)
automatically converts items to strings using tostring before displaying
list.items = { 1, 2 }
list\show!
assert.equal buf.text, '1\n2\n'
the selection is still the raw item
list.selection_enabled = true
list.items = { 1, 2 }
list\show!
assert.equal list.selection, 1
styling
list.items = { { 'first' } }
list.headers = { 'Column 1' }
list\show!
assert.equal style.at_pos(buf, 1), 'list_header'
columns are styled using the styles specified in .column_styles
list.items = { { 'first', 'second' } }
list.column_styles = { 'whitespace', 'identifier' }
list\show!
assert.equal style.at_pos(buf, 1), 'whitespace'
assert.equal style.at_pos(buf, 7), 'identifier'
column styles default to List.column_styles
list.items = { { 'first', 'second' } }
list\show!
assert.equal style.at_pos(buf, 1), List.column_styles[1]
assert.equal style.at_pos(buf, 7), List.column_styles[2]
.column_styles can be customized for each instance
list.column_styles[1] = 'custom'
assert.not_equal 'custom', List.column_styles[1]
(when .column_styles is a function)
it is called with the item, row and column and the returned style is used
item = { 'first', 'item' }
style_func = (list_item, row, column) ->
assert.equal list_item, item
assert.equal row, 1
column == 1 and 'line_number' or 'bracelight'
list.items = { item }
list.column_styles = style_func
list\show!
assert.equal style.at_pos(buf, 5), 'line_number'
assert.equal style.at_pos(buf, 7), 'bracelight'
(when selection is enabled with .selection_enabled)
before_each ->
list.selection_enabled = true
list.items = { 'one', 'two', 'three' }
list\show!
selects the first item by default
assert.equal 'one', list.selection
.selection is nil for an empty list
list.items = {}
list\show!
assert.is_nil list.selection
highlights the selected item with list_selection
assert.same { 'list_selection' }, highlight.at_pos(buf, 1)
assert.same {}, highlight.at_pos(buf, buf.lines[2].start_pos)
assert.equal 5, #buf.lines[1]
assert.equal 5, #buf.lines[3]
.selection = <item>
causes <item> to be selected
list.selection = 'two'
assert.equal list.selection, 'two'
raises an error if <item> can not be found
assert.raises 'not found', -> list.selection = 'five'
can be set before the list shown
list\clear!
list.selection = 'two'
list\show!
assert.equal list.selection, 'two'
select(row)
selects the specified row
list\select 2
assert.equal list.selection, 'two'
highlights the new selection and clears any old highlight
list\select 2
assert.same highlight.at_pos(buf, 1), {}
assert.same highlight.at_pos(buf, buf.lines[2].start_pos), { 'list_selection' }
list.max_height = 2
list\show!
list\select 3
assert.match buf.text, 'three'
remembers the selected row if set before showing
list\clear!
list.max_height = 2
list\select 3
list\show!
assert.equal list.selection, 'three'
assert.match buf.text, 'three'
select_next()
selects the next item
list\select_next!
assert.equal list.selection, 'two'
selects the first item if at the end of the list
list\select 3
list\select_next!
assert.equal list.selection, 'one'
list.max_height = 2
list\show!
list\select_next!
assert.equal list.selection, 'two'
assert.equal list.offset, 2
select_prev()
selects the previous item
list\select 2
list\select_prev!
assert.equal list.selection, 'one'
selects the last item if at the start of the list
list\select_prev!
assert.equal list.selection, 'three'
list.items = { 'one', 'two', 'three', 'four' }
list.max_height = 3
list.offset = 3
list\show!
list\select 3
list\select_prev!
assert.equal list.selection, 'two'
assert.equal list.offset, 1
before_each -> list.items = {'one', 'two', 'three'}
does not change offset when all items are shown
list\show!
list\scroll_to 2
assert.match buf.text, 'one\ntwo\nthree\n'
changes the offset to start with <row> when all items are not shown
list.max_height = 2
list\show!
list\scroll_to 2
assert.match buf.text, 'two'
assert.match buf.text, 'showing 2 %- 2 out of 3'
selects <row> if selection is enabled
list.selection_enabled = true
list.max_height = 2
list\show!
list\scroll_to 3
assert.equal list.selection, 'three'
(when the remaining numbers are fewer than the max nr of visible items)
adjust the actual offset to always show the same number of items
list.max_height = 3
list\show!
list\scroll_to 3
assert.match buf.text, 'two\nthree'
list.headers = { 'foo' }
list.max_height = 3
list\show!
list\scroll_to 3
assert.match buf.text, '^foo\nthree'
next_page()
scrolls to the next page
list.items = {'one', 'two', 'three'}
list.max_height = 2
list\show!
list\next_page!
assert.equal 2, list.offset
scrolls to the first page if at the end of the list
list.items = {'one', 'two', 'three'}
list.max_height = 2
list\show!
list\scroll_to 3
list\next_page!
assert.equal 1, list.offset
prev_page()
scrolls to the previous page
list.items = {'one', 'two', 'three'}
list.max_height = 2
list\show!
list\scroll_to 3
list\prev_page!
assert.equal list.offset, 2
scrolls to the last page if at the start of the list
list.items = {'one', 'two', 'three'}
list.max_height = 2
list\show!
list\prev_page!
assert.equal list.offset, 3