howl.ui.Cursor

buffer = Buffer {}
editor = Editor buffer
cursor = editor.cursor
selection = editor.selection

before_each ->
  buffer.text = text
  cursor.pos = 1
  selection.persistent = false

.at_end_of_line returns true if cursor is at the end of the line

cursor.pos = 1
assert.is_false cursor.at_end_of_line
cursor.column = 15
assert.is_true cursor.at_end_of_line

down! moves the cursor one line down, respecting the current column

cursor.pos = 4
cursor\down!
assert.equal 2, 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

cursor.pos = 1
cursor\right!
assert.equal cursor.pos, 2

left! moves the cursor one char left

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

reading returns the current character position in one based index

editor.sci\goto_pos 4 -- raw zero-based sci 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 cursor.pos, 5
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

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

cursor.pos = 4
assert.equal cursor.column, 4

.column = <nr>

moves the cursor to the specified column

cursor.column = 2
assert.equal 2, 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

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 5, cursor.column
  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

adjusts the selection if it is persistent

buffer.text = 'åäö'
cursor.pos = 1
selection.persistent = true
cursor.column_index = 3
assert.equals 'åä', selection.text

.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
assert.equal 5, cursor.column

treats <nr> as a character offset

buffer.text = 'åäö\nåäö'
cursor.line = 2
cursor.column_index = 2
assert.equal 2, cursor.column_index
assert.equal 6, cursor.pos

(when passing true for extended_selection to movement commands)

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\n', sel.text