howl.ui.Cursor
buffer = Buffer howl.mode.by_name 'default' editor = Editor buffer cursor = editor.cursor selection = editor.selection window = Gtk.OffscreenWindow default_width: 800, default_height: 640 window\add editor\to_gobject! window\show_all! howl.app\pump_mainloop! before_each -> cursor.pos = 1 selection.persistent = false
.at_end_of_line returns true if cursor is at the end of the line
buffer.text = 'åäö' cursor.pos = 1 assert.is_false cursor.at_end_of_line cursor.column = 4 assert.is_true cursor.at_end_of_line
.at_start_of_line returns true if cursor is at the start of the line
buffer.text = 'åäö' cursor.pos = 1 assert.is_true cursor.at_start_of_line cursor.column = 2 assert.is_false cursor.at_start_of_line
.at_end_of_file returns true if cursor is at the end of the buffer
buffer.text = 'åäö' cursor.pos = 1 assert.is_false cursor.at_end_of_file cursor\eof! assert.is_true cursor.at_end_of_file
down() moves the cursor one line down, respecting the current column
buffer.text = 'hello\nmy\nworld' cursor.pos = 4 cursor\down! assert.equal 2, cursor.line assert.equal 3, cursor.column cursor\down! assert.equal 3, cursor.line assert.equal 4, cursor.column
up() moves the cursor one line up, respecting the current column
cursor.line = 2 cursor.column = 3 cursor\up! assert.equal 1, cursor.line assert.equal 3, cursor.column
right() moves the cursor one char right
buffer.text = 'åäö' cursor.pos = 1 cursor\right! assert.equal cursor.pos, 2
left() moves the cursor one char left
buffer.text = 'åäö' cursor.pos = 3 cursor\left! assert.equal cursor.pos, 2
.style
is "line" by default
assert.equal 'line', cursor.style
raises an error if set to anything else than "block" or "line"
cursor.style = 'block' cursor.style = 'line' assert.raises 'foo', -> cursor.style = 'foo'
.pos
before_each -> buffer.text = 'Liñe 1 ʘf tƏxt'
reading returns the current character position in one based index
editor.view.cursor.pos = 5 -- raw aullar access, really at 'e' assert.equal 4, cursor.pos
setting sets the current position
cursor.pos = 4 assert.equal cursor.pos, 4
setting adjusts the selection if it is persistent
selection\set 1, 2 selection.persistent = true cursor.pos = 5 assert.equal 5, cursor.pos assert.equals 'Liñe', selection.text
out-of-bounds values are automatically corrected
cursor.pos = 0 assert.equal 1, cursor.pos cursor.pos = -1 assert.equal 1, cursor.pos cursor.pos = math.huge assert.equal #buffer + 1, cursor.pos cursor.pos = #buffer + 2 assert.equal #buffer + 1, cursor.pos
.line
before_each -> buffer.text = [[ Liñe 1 ʘf tƏxt And hƏre's line twʘ ]]
returns the current line
cursor.pos = 1 assert.equal cursor.line, 1
setting moves the cursor to the first column of the specified line
cursor.line = 2 assert.equal cursor.pos, 16
assignment adjusts out-of-bounds values automatically
cursor.line = -1 assert.equal 1, cursor.pos cursor.line = 100 assert.equal #buffer + 1, cursor.pos
assignment adjusts the selection if it is persistent
cursor.pos = 1 selection.persistent = true cursor.line = 2 assert.equals 'Liñe 1 ʘf tƏxt\n', selection.text
.column
returns the current column
buffer.text = 'Liñe 1 ʘf tƏxt' cursor.pos = 4 assert.equal cursor.column, 4
takes tabs into account
buffer.config.tab_width = 4 buffer.text = '\tsome text after' cursor.pos = 2 assert.equal 5, cursor.column
.column = <nr>
moves the cursor to the specified column
buffer.text = 'Liñe 1 ʘf tƏxt' cursor.column = 4 assert.equal 4, cursor.pos cursor.column = 1 assert.equal 1, cursor.pos
takes tabs into account
buffer.config.tab_width = 4 buffer.text = '\tsome text after' cursor.pos = 1 cursor.column = 5 assert.equal 2, cursor.pos
adjusts the selection if it is persistent
buffer.text = 'Liñe 1 ʘf tƏxt' cursor.pos = 1 selection.persistent = true cursor.column = 5 assert.equals 'Liñe', selection.text
.column_index
returns the real column index for the current line disregarding tabs
buffer.config.tab_width = 4 buffer.text = '\tsome text' cursor.pos = 2 assert.equal 2, cursor.column_index
returns the column index as a character offset
buffer.text = 'åäö\nåäö' cursor.pos = 6 assert.equal 2, cursor.column_index
.column_index = <nr>
before_each -> buffer.config.tab_width = 4 buffer.text = '\tsome text after'
moves the cursor to the specified column index
cursor.column_index = 2 assert.equal 2, cursor.column_index
treats <nr> as a character offset
buffer.text = 'åäö\nåäö' cursor.line = 2 cursor.column_index = 2 assert.equal 2, cursor.column_index
adjusts the selection if it is persistent
buffer.text = 'åäö' cursor.pos = 1 selection.persistent = true cursor.column_index = 3 assert.equals 'åä', selection.text
move_to(opts = {})
moves the cursor to the specified line and column if given
buffer.text = 'hello\nworld' cursor\move_to line: 1, column: 3 assert.equal 3, cursor.pos cursor\move_to line: 2, column: 2 assert.equal 8, cursor.pos
moves the cursor to the specified pos if given
buffer.text = 'åäö' cursor\move_to pos: 2 assert.equal 2, cursor.pos
extends the selection if the <extend> option is truthy
buffer.text = 'hello\nworld' cursor.pos = 1 cursor\move_to line: 1, column: 3, extend: true assert.equal 3, cursor.pos assert.equal 'he', selection.text cursor\move_to pos: 8, extend: true assert.equal 8, cursor.pos assert.equal 'hello\nw', selection.text
considers <column> to be a virtual column
buffer.config.tab_width = 2 buffer.text = '\t23' cursor\move_to line: 1, column: 3 assert.equal 2, cursor.pos
accepts <column_index> as well, considering that a real column
buffer.config.tab_width = 2 buffer.text = '\t23' cursor\move_to line: 1, column_index: 3 assert.equal 3, cursor.pos
adjust out-of bound values
buffer.text = '123\n56789\n' cursor\move_to line: 100 assert.equal 3, cursor.line cursor\move_to line: 0 assert.equal 1, cursor.line cursor\move_to column: 10 assert.equal 4, cursor.column cursor\move_to column: 0 assert.equal 1, cursor.column
word_right
moves the cursor to the start of the following word
buffer.text = '12 xy 78' cursor.pos = 1 cursor\word_right! assert.equal 4, cursor.pos cursor\word_right! assert.equal 7, cursor.pos
handles punctuation
buffer.text = 'foo.bar' cursor.pos = 1 cursor\word_right! assert.equal 4, cursor.pos cursor\word_right! assert.equal 5, cursor.pos
handles tabs properly
buffer.config.tab_width = 2 buffer.text = '\t\tfoo_bar\txy' cursor.pos = 3 -- 'f' cursor\word_right! assert.equal 11, cursor.pos
moves to the end of the line if no further word is available
buffer.text = '{\n34' cursor.pos = 1 cursor\word_right! assert.equal 2, cursor.pos buffer.text = 'xy\n45' cursor.pos = 1 cursor\word_right! assert.equal 3, cursor.pos buffer.text = '12\n45' cursor.pos = 1 cursor\word_right! assert.equal 3, cursor.pos
handles unicode properly
buffer.text = 'LinƏ !!' cursor.pos = 1 cursor\word_right! assert.equal 6, cursor.pos cursor\word_right! assert.equal 8, cursor.pos
when at the end of the line
moves to the first non-blank on the next line
buffer.text = '123\n 78' cursor.pos = 4 cursor\word_right! assert.equal 7, cursor.pos buffer.text = '123\n56' cursor.pos = 4 cursor\word_right! assert.equal 5, cursor.pos
does nothing if at the end of file
buffer.text = '123' cursor.pos = 4 cursor\word_right! assert.equal 4, cursor.pos
leaves the cursor at end of file if no next word is present
buffer.text = '123' cursor.pos = 2 cursor\word_right! assert.equal 4, cursor.pos
word_right_end
moves the cursor to the end of the current word
buffer.text = 'foo bar 56 !' cursor.pos = 1 cursor\word_right_end! assert.equal 4, cursor.pos -- after 'foo' cursor\word_right_end! assert.equal 8, cursor.pos -- after 'bar' cursor\word_right_end! assert.equal 11, cursor.pos -- after '56'
handles punctuation
buffer.text = 'foo.bar' cursor.pos = 1 cursor\word_right_end! assert.equal 4, cursor.pos -- '.' cursor\word_right_end! assert.equal 8, cursor.pos
handles unicode properly
buffer.text = 'LinƏ !!' cursor.pos = 1 cursor\word_right_end! assert.equal 5, cursor.pos cursor\word_right_end! assert.equal 8, cursor.pos cursor.pos = 4 cursor\word_right_end! assert.equal 5, cursor.pos
handles single stand-alone punctuation
buffer.text = ' { foo' cursor.pos = 1 cursor\word_right_end! assert.equal 3, cursor.pos
handles tabs properly
buffer.config.tab_width = 2 buffer.text = '\t\tfoo_bar\txy' cursor.pos = 3 -- 'f' cursor\word_right_end! assert.equal 10, cursor.pos
when at the end of the line
moves to the first non-blank on the next line
buffer.text = '123\n 78' cursor.pos = 4 cursor\word_right_end! assert.equal 9, cursor.pos buffer.text = '123\n56' cursor.pos = 4 cursor\word_right_end! assert.equal 7, cursor.pos
does nothing if at the end of file
buffer.text = '123' cursor.pos = 4 cursor\word_right_end! assert.equal 4, cursor.pos
leaves the cursor at end of file if no next word is present
buffer.text = '12 ' cursor.pos = 3 cursor\word_right_end! assert.equal 5, cursor.pos
word_left
moves the cursor to the start of the following word
buffer.text = 'a b 12 0x !!' cursor.pos = 12 cursor\word_left! assert.equal 11, cursor.pos -- first '!' cursor\word_left! assert.equal 8, cursor.pos -- '0' cursor\word_left! assert.equal 5, cursor.pos cursor\word_left! assert.equal 3, cursor.pos
handles punctuation
buffer.text = '(foo .bar' cursor.pos = 10 cursor\word_left! assert.equal 7, cursor.pos cursor\word_left! assert.equal 6, cursor.pos cursor\word_left! assert.equal 2, cursor.pos cursor\word_left! assert.equal 1, cursor.pos
handles unicode properly
buffer.text = 'LinƏ åäö ' cursor.pos = 10 cursor\word_left! assert.equal 6, cursor.pos cursor\word_left! assert.equal 1, cursor.pos
handles numbers
buffer.text = ' x 2 ' cursor.pos = 5 cursor\word_left! assert.equal 4, cursor.pos cursor\word_left! assert.equal 2, cursor.pos
handles tabs properly
buffer.config.tab_width = 2 buffer.text = '\t\tfoo_bar\txy' cursor.pos = 5 cursor\word_left! assert.equal 3, cursor.pos
(when no further word is available)
moves to the end of the previous line
buffer.text = '12\n45' cursor.pos = 4 cursor\word_left! assert.equal 3, cursor.pos buffer.text = '12\n 56' cursor.pos = 5 cursor\word_left! assert.equal 3, cursor.pos buffer.text = 'xy\nz' cursor.pos = 4 cursor\word_left! assert.equal 3, cursor.pos
does nothing if at the start of file
buffer.text = '123' cursor.pos = 1 cursor\word_left! assert.equal 1, cursor.pos
moves to the start of the file if no previous line is available
buffer.text = ' 34' cursor.pos = 3 cursor\word_left! assert.equal 1, cursor.pos
word_left_end
moves the cursor to the end of the previous word
buffer.text = 'foo bar 56 !' cursor.pos = 13 cursor\word_left_end! assert.equal 11, cursor.pos -- end of '56' cursor\word_left_end! assert.equal 8, cursor.pos -- end of 'bar' cursor\word_left_end! assert.equal 4, cursor.pos -- end of 'foo'
handles punctuation
buffer.text = 'foo.bar' cursor.pos = 8 cursor\word_left_end! assert.equal 5, cursor.pos -- after '.' cursor\word_left_end! assert.equal 4, cursor.pos -- after 'foo'
handles single stand-alone punctuation
buffer.text = ' { foo' cursor.pos = 7 cursor\word_left_end! assert.equal 3, cursor.pos
handles unicode properly
buffer.text = 'LiñƏ åäö x' cursor.pos = 10 cursor\word_left_end! assert.equal 9, cursor.pos cursor\word_left_end! assert.equal 5, cursor.pos cursor\word_left_end! assert.equal 1, cursor.pos
handles tabs properly
buffer.config.tab_width = 2 buffer.text = 'foo\tbar' cursor.pos = 5 cursor\word_left_end! assert.equal 4, cursor.pos
(when no further word is available)
moves to the end of the previous line
buffer.text = '12\n45' cursor.pos = 4 cursor\word_left_end! assert.equal 3, cursor.pos buffer.text = '12\n 56' cursor.pos = 5 cursor\word_left_end! assert.equal 3, cursor.pos buffer.text = 'xy\nz' cursor.pos = 4 cursor\word_left_end! assert.equal 3, cursor.pos
does nothing if at the start of file
buffer.text = '123' cursor.pos = 1 cursor\word_left_end! assert.equal 1, cursor.pos
moves to the start of the file if no previous line is available
buffer.text = ' 34' cursor.pos = 3 cursor\word_left_end! assert.equal 1, cursor.pos
para_up
(when between paragraphs)
moves to the first previous blank line before the above paragraph
buffer.text = '12\n\n5\n7\n' cursor.pos = 9 cursor\para_up! assert.equal 2, cursor.line
moves to the start of the buffer if no previous paragraph exists
buffer.text = '12\n\n' cursor.pos = 5 cursor\para_up! assert.equal 1, cursor.pos
(when in the middle of a paragraph)
moves to the first previous blank line
buffer.text = '12\n\n56\n89' cursor.pos = 9 cursor\para_up! assert.equal 2, cursor.line
moves to the start of the buffer if no previous paragraph exists
buffer.text = '12\n45' cursor.pos = 5 cursor\para_up! assert.equal 1, cursor.pos
para_down
(when between paragraphs)
moves to the next blank line after the above paragraph
buffer.text = '12\n\n5\n7\n' cursor.pos = 4 cursor\para_down! assert.equal 5, cursor.line
moves to the end of the buffer if no subsequent paragraph exists
buffer.text = '12\n\n5' cursor.pos = 4 cursor\para_down! assert.equal 6, cursor.pos
(when in the middle of a paragraph)
moves to the next blank line
buffer.text = '12\n45\n\n89' cursor.pos = 1 cursor\para_down! assert.equal 3, cursor.line
moves to the end of the buffer if no subsequent paragraph exists
buffer.text = '12\n45' cursor.pos = 1 cursor\para_down! assert.equal 6, cursor.pos
home_indent
moves the cursor to the first non-blank column
buffer.text = ' 345' cursor.pos = 5 cursor\home_indent! assert.equal 3, cursor.pos
does nothing for an empty line
buffer.text = '\nsecond' cursor.pos = 1 cursor\home_indent! assert.equal 1, cursor.pos
handles tabs correctly
buffer.text = '\t 345' cursor.pos = 5 cursor\home_indent! assert.equal 3, cursor.pos
home_indent_auto
toggles the cursor between the first and the first non-blank column
buffer.text = ' 345' cursor.pos = 5 cursor\home_indent_auto! assert.equal 3, cursor.pos cursor\home_indent_auto! assert.equal 1, cursor.pos cursor\home_indent_auto! assert.equal 3, cursor.pos
(when passing true for extended_selection to movement commands)
before_each -> buffer.text = [[ Liñe 1 ʘf tƏxt And hƏre's line twʘ ]]
the selection is extended along with moving the cursor
sel = editor.selection cursor.pos = 1 cursor\right true assert.equal 'L', sel.text cursor\down true assert.equals 'Liñe 1 ʘf tƏxt\nA', sel.text cursor\left true assert.equals 'Liñe 1 ʘf tƏxt\n', sel.text cursor\up true assert.is_true sel.empty
(when the editor selection is marked as persistent)
the selection is extended along with moving the cursor
sel = editor.selection sel.persistent = true cursor.pos = 1 cursor\right! assert.equal 'L', sel.text cursor.line = 2 assert.equals 'Liñe 1 ʘf tƏxt\nA', sel.text