mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 21:14:28 -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
|
// TODO refactor, at eval.js we have explicit information if node is error
|
||||||
// guessing. See also color.js
|
// 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
|
// TODO check if return result is null and throw early
|
||||||
export const find_error_origin_node = node =>
|
export const find_error_origin_node = node =>
|
||||||
find_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) => {
|
const navigate_logs_increment = (state, increment) => {
|
||||||
if(state.logs.logs.length == 0) {
|
if(state.logs.logs.length == 0) {
|
||||||
return {state}
|
return {state}
|
||||||
@@ -875,6 +911,7 @@ export const calltree_commands = {
|
|||||||
click,
|
click,
|
||||||
select_return_value,
|
select_return_value,
|
||||||
select_arguments,
|
select_arguments,
|
||||||
|
select_error,
|
||||||
navigate_logs_position,
|
navigate_logs_position,
|
||||||
navigate_logs_increment,
|
navigate_logs_increment,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ export class CallTree {
|
|||||||
exec('calltree.select_arguments')
|
exec('calltree.select_arguments')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(e.key == 'e') {
|
||||||
|
exec('calltree.select_error')
|
||||||
|
}
|
||||||
|
|
||||||
if(e.key == 'r' || e.key == 'Enter') {
|
if(e.key == 'r' || e.key == 'Enter') {
|
||||||
exec('calltree.select_return_value')
|
exec('calltree.select_return_value')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ export class UI {
|
|||||||
['Step out of call', 'Ctrl-o', '\\o'],
|
['Step out of call', 'Ctrl-o', '\\o'],
|
||||||
['When in call tree view, jump to return statement', 'Enter'],
|
['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 function arguments', 'a'],
|
||||||
|
['When in call tree view, jump to error origin', 'e'],
|
||||||
['Clear IO trace', 'F6'],
|
['Clear IO trace', 'F6'],
|
||||||
['(Re)open run window (F7)', 'F7'],
|
['(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"]})
|
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', () => {
|
test('move_cursor arguments', () => {
|
||||||
const code = `
|
const code = `
|
||||||
const x = (a, b) => { }
|
const x = (a, b) => { }
|
||||||
|
|||||||
Reference in New Issue
Block a user