mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 13:04:30 -08:00
hotkey to select error origin
This commit is contained in:
@@ -145,8 +145,9 @@ export const find_node = (node, pred) => {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO refactor, have explicit information if node is error origin, without
|
||||
// guessing. See also color.js
|
||||
// TODO refactor, at eval.js we have explicit information if node is error
|
||||
// origin, without guessing. See also color.js
|
||||
// TODO result is ok, but value is rejected promise
|
||||
// TODO check if return result is null and throw early
|
||||
export const find_error_origin_node = node =>
|
||||
find_node(
|
||||
|
||||
@@ -836,6 +836,42 @@ const select_arguments = (state, with_focus = true) => {
|
||||
}
|
||||
}
|
||||
|
||||
const select_error = state => {
|
||||
const node = [
|
||||
state.current_calltree_node,
|
||||
state.active_calltree_node,
|
||||
root_calltree_node(state),
|
||||
// TODO deferred calls???
|
||||
].find(n => n != null && !n.ok)
|
||||
|
||||
if(node == null) {
|
||||
return {state, effects: [{type: 'set_status', args: ['no error found']}]}
|
||||
}
|
||||
|
||||
const error_origin = find_node(node, n =>
|
||||
!n.ok
|
||||
&& (
|
||||
n.children == null || n.children.every(c => c.ok)
|
||||
)
|
||||
)
|
||||
|
||||
if(error_origin == null) {
|
||||
throw new Error('illegal state: error origin not found')
|
||||
}
|
||||
|
||||
const next = expand_path(add_frame(state, error_origin), error_origin)
|
||||
const frame = active_frame(next)
|
||||
const error_node = find_error_origin_node(frame)
|
||||
|
||||
return {
|
||||
state: set_location(next, {
|
||||
module: calltree_node_loc(error_origin).module,
|
||||
index: error_node.index
|
||||
}),
|
||||
effects: {type: 'set_focus'}
|
||||
}
|
||||
}
|
||||
|
||||
const navigate_logs_increment = (state, increment) => {
|
||||
if(state.logs.logs.length == 0) {
|
||||
return {state}
|
||||
@@ -875,6 +911,7 @@ export const calltree_commands = {
|
||||
click,
|
||||
select_return_value,
|
||||
select_arguments,
|
||||
select_error,
|
||||
navigate_logs_position,
|
||||
navigate_logs_increment,
|
||||
}
|
||||
|
||||
@@ -39,6 +39,10 @@ export class CallTree {
|
||||
exec('calltree.select_arguments')
|
||||
}
|
||||
|
||||
if(e.key == 'e') {
|
||||
exec('calltree.select_error')
|
||||
}
|
||||
|
||||
if(e.key == 'r' || e.key == 'Enter') {
|
||||
exec('calltree.select_return_value')
|
||||
}
|
||||
|
||||
@@ -307,6 +307,7 @@ export class UI {
|
||||
['Step out of call', 'Ctrl-o', '\\o'],
|
||||
['When in call tree view, jump to return statement', 'Enter'],
|
||||
['When in call tree view, jump to function arguments', 'a'],
|
||||
['When in call tree view, jump to error origin', 'e'],
|
||||
['Clear IO trace', 'F6'],
|
||||
['(Re)open run window (F7)', 'F7'],
|
||||
]
|
||||
|
||||
18
test/test.js
18
test/test.js
@@ -2375,6 +2375,24 @@ const y = x()`
|
||||
assert_equal(s3.value_explorer.result, {ok: true, value: ["1"]})
|
||||
}),
|
||||
|
||||
test('select_error', () => {
|
||||
const code = `
|
||||
const deep = x => {
|
||||
if(x == 10) {
|
||||
throw new Error()
|
||||
} else {
|
||||
deep(x + 1)
|
||||
}
|
||||
}
|
||||
|
||||
deep(0)
|
||||
`
|
||||
const i = test_initial_state(code, code.indexOf('deep(x + 1)'))
|
||||
const {state: found_err_state, effects} = COMMANDS.calltree.select_error(i)
|
||||
assert_equal(found_err_state.active_calltree_node.args, [10])
|
||||
assert_equal(current_cursor_position(found_err_state), code.indexOf('throw'))
|
||||
}),
|
||||
|
||||
test('move_cursor arguments', () => {
|
||||
const code = `
|
||||
const x = (a, b) => { }
|
||||
|
||||
Reference in New Issue
Block a user