arrow keys in big picture view

This commit is contained in:
Kartik K. Agaram 2021-12-21 19:52:49 -08:00
parent 3a20c0e227
commit 577d47a6a7
2 changed files with 105 additions and 12 deletions

View File

@ -14,6 +14,7 @@ start -> big picture -> edit A -> move cursor -> run -> exit -> start -> ... ->
syntax highlighting for line comments syntax highlighting for line comments
syntax highlighting for multiline comments syntax highlighting for multiline comments
start -> big picture -> recent changes -> add note -> save | note visible start -> big picture -> recent changes -> add note -> save | note visible
start -> big picture -> arrow keys* | always exactly one definition highlighted
It's very important not to leak space on the Lua stack, particularly It's very important not to leak space on the Lua stack, particularly
proportionate to keypresses. That's a recipe for segfaults. proportionate to keypresses. That's a recipe for segfaults.

116
src/lua.c
View File

@ -776,6 +776,7 @@ static void big_picture_menu (void) {
extern int menu_column; extern int menu_column;
menu_column = 2; menu_column = 2;
draw_menu_item("^x", "go back"); draw_menu_item("^x", "go back");
draw_menu_item("^g", "go to highlight");
draw_menu_item("Enter", "submit"); draw_menu_item("Enter", "submit");
draw_menu_item("^h", "backspace"); draw_menu_item("^h", "backspace");
draw_menu_item("^u", "clear"); draw_menu_item("^u", "clear");
@ -816,6 +817,7 @@ static int is_current_definition(lua_State *L, const char *definition_name, int
void draw_definition_name (const char *definition_name) { void draw_definition_name (const char *definition_name) {
/* confusingly, unhighlighted definitions use COLOR_PAIR_HIGHLIGHT */
attron(COLOR_PAIR(COLOR_PAIR_HIGHLIGHT)); attron(COLOR_PAIR(COLOR_PAIR_HIGHLIGHT));
addstr(" "); addstr(" ");
addstr(definition_name); addstr(definition_name);
@ -824,8 +826,27 @@ void draw_definition_name (const char *definition_name) {
addstr(" "); addstr(" ");
} }
void draw_highlighted_definition_name (const char *definition_name) {
/* confusingly, highlighted definitions don't use COLOR_PAIR_HIGHLIGHT */
attron(A_REVERSE);
addstr(" ");
addstr(definition_name);
addstr(" ");
attroff(A_REVERSE);
addstr(" ");
}
/* return true if submitted */ /* return true if submitted */
void big_picture_view (lua_State *L) { void big_picture_view (lua_State *L) {
/* Without any intervening edits, big_picture_view always stably renders
* definitions in exactly the same spatial order, both in levels from top to
* bottom and in indexes within each level from left to right. */
int highlight_level = 0;
int highlight_index_within_level = 0;
int level_size[30] = {0}; /* number of indexes within each level */
char highlight[CURRENT_DEFINITION_LEN+1] = {0};
restart: restart:
clear(); clear();
luaL_newmetatable(L, "__teliva_call_graph_depth"); luaL_newmetatable(L, "__teliva_call_graph_depth");
@ -845,6 +866,9 @@ restart:
y += 2; y += 2;
mvaddstr(y, 0, "data: "); mvaddstr(y, 0, "data: ");
// first: data (non-functions) that's not the Teliva menu or curses variables // first: data (non-functions) that's not the Teliva menu or curses variables
if (highlight_level < 0) highlight_level = 0;
int level = 0;
int index_within_level = 0;
for (int i = history_array_size; i > 0; --i) { for (int i = history_array_size; i > 0; --i) {
lua_rawgeti(L, history_array, i); lua_rawgeti(L, history_array, i);
int t = lua_gettop(L); int t = lua_gettop(L);
@ -860,8 +884,15 @@ restart:
&& !is_userdata // including curses window objects && !is_userdata // including curses window objects
// (unlikely to have an interesting definition) // (unlikely to have an interesting definition)
) { ) {
if (is_current_definition(L, definition_name, i, history_array, history_array_size)) if (is_current_definition(L, definition_name, i, history_array, history_array_size)) {
draw_definition_name(definition_name); if (level == highlight_level && index_within_level == highlight_index_within_level) {
draw_highlighted_definition_name(definition_name);
strncpy(highlight, definition_name, CURRENT_DEFINITION_LEN);
} else {
draw_definition_name(definition_name);
}
++index_within_level;
}
} }
} }
lua_pop(L, 1); // history element lua_pop(L, 1); // history element
@ -880,20 +911,30 @@ restart:
if (strcmp(definition_name, "menu") == 0 if (strcmp(definition_name, "menu") == 0
|| is_userdata // including curses window objects || is_userdata // including curses window objects
) { ) {
if (is_current_definition(L, definition_name, i, history_array, history_array_size)) if (is_current_definition(L, definition_name, i, history_array, history_array_size)) {
draw_definition_name(definition_name); if (level == highlight_level && index_within_level == highlight_index_within_level) {
draw_highlighted_definition_name(definition_name);
strncpy(highlight, definition_name, CURRENT_DEFINITION_LEN);
} else {
draw_definition_name(definition_name);
}
++index_within_level;
}
} }
} }
lua_pop(L, 1); // history element lua_pop(L, 1); // history element
} }
level_size[level] = index_within_level;
level++;
// functions by level // functions by level
y += 2; y += 2;
mvprintw(y, 0, "functions: "); mvprintw(y, 0, "functions: ");
y++; y++;
for (int level = 1; ; ++level) { for (int depth = 1; ; ++depth) {
mvaddstr(y, 0, " "); mvaddstr(y, 0, " ");
bool drew_anything = false; bool drew_anything = false;
index_within_level = 0;
for (int i = history_array_size; i > 0; --i) { for (int i = history_array_size; i > 0; --i) {
lua_rawgeti(L, history_array, i); lua_rawgeti(L, history_array, i);
int t = lua_gettop(L); int t = lua_gettop(L);
@ -901,10 +942,17 @@ restart:
const char* definition_name = lua_tostring(L, -2); const char* definition_name = lua_tostring(L, -2);
if (is_special_history_key(definition_name)) continue; if (is_special_history_key(definition_name)) continue;
lua_getfield(L, cgt, definition_name); lua_getfield(L, cgt, definition_name);
int depth = lua_tointeger(L, -1); int definition_depth = lua_tointeger(L, -1);
if (depth == level) { if (definition_depth == depth) {
if (is_current_definition(L, definition_name, i, history_array, history_array_size)) if (is_current_definition(L, definition_name, i, history_array, history_array_size)) {
draw_definition_name(definition_name); if (level == highlight_level && index_within_level == highlight_index_within_level) {
draw_highlighted_definition_name(definition_name);
strncpy(highlight, definition_name, CURRENT_DEFINITION_LEN);
} else {
draw_definition_name(definition_name);
}
++index_within_level;
}
drew_anything = true; drew_anything = true;
} }
lua_pop(L, 1); // depth of value lua_pop(L, 1); // depth of value
@ -913,10 +961,14 @@ restart:
} }
y += 2; y += 2;
if (!drew_anything) break; if (!drew_anything) break;
level_size[level] = index_within_level;
level++;
} }
// unused functions // unused functions
mvaddstr(y, 0, " "); mvaddstr(y, 0, " ");
/* no need to level++ because the final iteration above didn't draw anything */
index_within_level = 0;
for (int i = history_array_size; i > 0; --i) { for (int i = history_array_size; i > 0; --i) {
lua_rawgeti(L, history_array, i); lua_rawgeti(L, history_array, i);
int t = lua_gettop(L); int t = lua_gettop(L);
@ -927,13 +979,23 @@ restart:
int is_function = lua_isfunction(L, -1); int is_function = lua_isfunction(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
lua_getfield(L, cgt, definition_name); lua_getfield(L, cgt, definition_name);
if (is_function && lua_isnoneornil(L, -1)) if (is_function && lua_isnoneornil(L, -1)) {
if (is_current_definition(L, definition_name, i, history_array, history_array_size)) if (is_current_definition(L, definition_name, i, history_array, history_array_size)) {
draw_definition_name(definition_name); if (level == highlight_level && index_within_level == highlight_index_within_level) {
draw_highlighted_definition_name(definition_name);
strncpy(highlight, definition_name, CURRENT_DEFINITION_LEN);
} else {
draw_definition_name(definition_name);
}
++index_within_level;
}
}
lua_pop(L, 1); // depth of value lua_pop(L, 1); // depth of value
} }
lua_pop(L, 1); // history element lua_pop(L, 1); // history element
} }
level_size[level] = index_within_level;
int max_level = level;
lua_settop(L, 0); lua_settop(L, 0);
render_previous_error(); render_previous_error();
@ -944,6 +1006,7 @@ restart:
big_picture_menu(); big_picture_menu();
for (int x = 0; x < COLS; ++x) for (int x = 0; x < COLS; ++x)
mvaddch(LINES-2, x, ' '); mvaddch(LINES-2, x, ' ');
//? mvprintw(20, 60, "%d %d\n", highlight_level, highlight_index_within_level);
mvprintw(LINES-2, 0, "Edit: %s", query); mvprintw(LINES-2, 0, "Edit: %s", query);
int c = getch(); int c = getch();
if (c == KEY_BACKSPACE || c == DELETE || c == CTRL_H) { if (c == KEY_BACKSPACE || c == DELETE || c == CTRL_H) {
@ -966,6 +1029,35 @@ restart:
query[qlen++] = c; query[qlen++] = c;
query[qlen] = '\0'; query[qlen] = '\0';
} }
} else if (c == KEY_LEFT) {
highlight_index_within_level--;
if (highlight_index_within_level < 0) highlight_index_within_level = 0;
goto restart;
} else if (c == KEY_RIGHT) {
highlight_index_within_level++;
if (highlight_index_within_level >= level_size[highlight_level])
highlight_index_within_level = level_size[highlight_level]-1;
if (highlight_index_within_level < 0) highlight_index_within_level = 0;
goto restart;
} else if (c == KEY_UP) {
highlight_level--;
if (highlight_level < 0) highlight_level = 0;
if (highlight_index_within_level >= level_size[highlight_level])
highlight_index_within_level = level_size[highlight_level]-1;
if (highlight_index_within_level < 0) highlight_index_within_level = 0;
goto restart;
} else if (c == KEY_DOWN) {
highlight_level++;
if (highlight_level > max_level) highlight_level = max_level;
if (highlight_index_within_level >= level_size[highlight_level])
highlight_index_within_level = level_size[highlight_level]-1;
if (highlight_index_within_level < 0) highlight_index_within_level = 0;
goto restart;
} else if (c == CTRL_G) {
save_to_current_definition_and_editor_buffer(L, highlight);
int back_to_big_picture = edit_current_definition(L);
if (back_to_big_picture) goto restart;
return;
} }
} }
/* never gets here */ /* never gets here */