howl.ui.Readline

window = Window!
local readline

before_each -> readline = Readline window

read(prompt, input)

suspends the current coroutine while waiting for submission

co = coroutine.create -> readline\read 'foo'
assert coroutine.resume co
assert.equals "suspended", coroutine.status co

resumes the coroutine upon submission, causing return of the chosen value

local value
coroutine.wrap(-> value = readline\read 'foo: ')!
readline.text = 'bar'
readline.keymap.return readline
assert.equals "bar", value

returns multiple values if the input's value_for does

local values
input = value_for: -> 1, nil, 2
coroutine.wrap(-> values = { readline\read 'foo: ', input } )!
readline.text = 'bar'
readline.keymap.return readline
assert.same { 1, nil, 2 }, values

returns nil upon cancel

local value
coroutine.wrap(-> value = readline\read 'foo: ')!
readline.text = 'bar'
readline.keymap.escape readline
assert.is_nil value

(keymap handling)

dispatches any key presses to the input's keymap if present

input = keymap: a: spy.new -> true
coroutine.wrap(-> readline\read 'foo: ', input)!
readline.sci.listener.on_keypress character: 'a', key_name: 'a', key_code: 65
assert.spy(input.keymap.a).was_called_with(input, readline, nil)

does not process the key press any further if the key was handled by the input

handled = true
input = keymap: backspace: spy.new -> handled
coroutine.wrap(-> readline\read 'foo: ', input)!
readline.text = 'foo'
backspace_event = character: '\8', key_name: 'backspace', key_code: 123
readline.sci.listener.on_keypress backspace_event
assert.equal 'foo', readline.text
handled = false
readline.sci.listener.on_keypress backspace_event
assert.equal 'fo', readline.text

complete(force = false)

raises an error if the readline is not showing

assert.raises 'hidden', -> readline\complete!