start showing call stack on errors

It turns out Lua has been providing us this information all along! I'd
just not created the space on screen to show it. Make it persist better.

Kilo now no longer tracks its own status messages, which is a regression
in a rare condition.
This commit is contained in:
Kartik K. Agaram 2021-12-04 14:11:44 -08:00
parent 810e160136
commit d9cf3433d9
7 changed files with 69 additions and 47 deletions

View File

@ -137,6 +137,7 @@ function init_colors()
curses.init_pair(13, 7, 5)
curses.init_pair(14, 7, 6)
curses.init_pair(15, -1, 15)
curses.init_pair(255, 15, 1) -- reserved for Teliva error messages
end]==],
},
{

View File

@ -219,6 +219,7 @@ function init_colors()
curses.init_pair(6, dark_piece, light_last_moved_square)
curses.init_pair(7, light_piece, dark_last_moved_square)
curses.init_pair(8, dark_piece, dark_last_moved_square)
curses.init_pair(255, 15, 1) -- reserved for Teliva error messages
end]==],
},
{

View File

@ -51,6 +51,7 @@ function main()
for i=1,7 do
curses.init_pair(i, 0, i)
end
curses.init_pair(255, 15, 1) -- reserved for Teliva error messages
while true do
render(window)

View File

@ -88,6 +88,7 @@ function main()
for i=1,7 do
curses.init_pair(i, 0, i)
end
curses.init_pair(255, 15, 1) -- reserved for Teliva error messages
while true do
render(window)

View File

@ -266,6 +266,7 @@ function main()
for i=1,7 do
curses.init_pair(i, i, -1)
end
curses.init_pair(255, 15, 1) -- reserved for Teliva error messages
-- initialize grid based on commandline args
if (#arg == 0) then

View File

@ -95,15 +95,11 @@ struct editorConfig {
erow *row; /* Rows */
int dirty; /* File modified but not saved. */
char *filename; /* Currently open filename */
char statusmsg[80];
time_t statusmsg_time;
struct editorSyntax *syntax; /* Current syntax highlight, or NULL. */
};
static struct editorConfig E;
static void editorSetStatusMessage(const char *fmt, ...);
/* =========================== Syntax highlights DB =========================
*
* In order to add a new syntax, define two arrays with a list of file name
@ -642,13 +638,16 @@ static int editorSaveToDisk(void) {
close(fd);
free(buf);
E.dirty = 0;
memset(E.statusmsg, '\0', 80);
return 0;
writeerr:
free(buf);
if (fd != -1) close(fd);
editorSetStatusMessage("Can't save! I/O error: %s",strerror(errno));
/* TODO: better error handling. */
/* I haven't gotten to this yet since we have version control. */
endwin();
printf("Can't save! I/O error: %s",strerror(errno));
exit(1);
return 1;
}
@ -720,6 +719,7 @@ static void editorGoMenu(void) {
attrset(A_NORMAL);
}
extern int render_previous_error();
static void editorRefreshScreen(void (*menu_func)(void)) {
int y;
erow *r;
@ -771,12 +771,9 @@ static void editorRefreshScreen(void (*menu_func)(void)) {
}
}
(*menu_func)();
render_previous_error();
attrset(A_REVERSE);
addstr(" ");
addstr(E.statusmsg);
attrset(A_NORMAL);
(*menu_func)();
/* Put cursor at its current position. Note that the horizontal position
* at which the cursor is displayed may be different compared to 'E.cx'
@ -795,16 +792,6 @@ static void editorRefreshScreen(void (*menu_func)(void)) {
curs_set(1);
}
/* Set an editor status message for the second line of the status, at the
* end of the screen. */
static void editorSetStatusMessage(const char *fmt, ...) {
va_list ap;
va_start(ap,fmt);
vsnprintf(E.statusmsg,sizeof(E.statusmsg),fmt,ap);
va_end(ap);
E.statusmsg_time = time(NULL);
}
/* =============================== Find mode ================================ */
#define KILO_QUERY_LEN 256
@ -843,7 +830,6 @@ static void editorFind() {
E.coloff = saved_coloff; E.rowoff = saved_rowoff;
}
FIND_RESTORE_HL;
editorSetStatusMessage("");
return;
} else if (c == CTRL_U) {
qlen = 0;
@ -1040,7 +1026,6 @@ static void editorGo(lua_State* L) {
if (c == KEY_BACKSPACE || c == DELETE || c == CTRL_H) {
if (qlen != 0) query[--qlen] = '\0';
} else if (c == CTRL_X || c == ENTER) {
editorSetStatusMessage("");
if (c == ENTER) {
save_to_current_definition_and_editor_buffer(L, query);
clearEditor();
@ -1182,12 +1167,11 @@ static void initEditor(void) {
}
/* return true if user chose to back into the big picture view */
int edit(lua_State* L, char* filename, const char* message) {
int edit(lua_State* L, char* filename) {
Quit = 0;
Back_to_big_picture = 0;
initEditor();
editorOpen(filename);
editorSetStatusMessage(message);
while(!Quit) {
editorRefreshScreen(editorMenu);
editorProcessKeypress(L);
@ -1196,7 +1180,7 @@ int edit(lua_State* L, char* filename, const char* message) {
}
/* return true if user chose to back into the big picture view */
int edit_from(lua_State* L, char* filename, const char* message, int rowoff, int coloff, int cy, int cx) {
int edit_from(lua_State* L, char* filename, int rowoff, int coloff, int cy, int cx) {
Quit = 0;
Back_to_big_picture = 0;
initEditor();
@ -1205,7 +1189,6 @@ int edit_from(lua_State* L, char* filename, const char* message, int rowoff, int
E.cy = cy;
E.cx = cx;
editorOpen(filename);
editorSetStatusMessage(message);
while(!Quit) {
editorRefreshScreen(editorMenu);
editorProcessKeypress(L);
@ -1216,7 +1199,6 @@ int edit_from(lua_State* L, char* filename, const char* message, int rowoff, int
int resumeEdit(lua_State* L) {
Quit = 0;
Back_to_big_picture = 0;
editorSetStatusMessage(Previous_error);
while(!Quit) {
editorRefreshScreen(editorMenu);
editorProcessKeypress(L);

View File

@ -81,21 +81,56 @@ static int report (lua_State *L, int status) {
}
char *strdup(const char *s);
extern void developer_mode (lua_State *L, const char *status_message);
/* return final y containing text */
static int render_wrapped_text (int y, int xmin, int xmax, const char *text) {
int x = xmin;
move(y, x);
for (int j = 0; j < strlen(text); ++j) {
char c = text[j];
if (c != '\n') {
addch(text[j]);
++x;
if (x >= xmax) {
++y;
x = xmin;
move(y, x);
}
}
else {
/* newline */
++y;
x = xmin;
move(y, x);
}
}
return y;
}
const char *Previous_error = NULL;
void render_previous_error (void) {
if (!Previous_error) return;
attrset(COLOR_PAIR(255));
render_wrapped_text(LINES-10, COLS/2, COLS, Previous_error);
attrset(A_NORMAL);
}
extern char *strdup(const char *s);
extern void developer_mode (lua_State *L);
static int report_in_developer_mode (lua_State *L, int status) {
if (status && !lua_isnil(L, -1)) {
const char *msg = strdup(lua_tostring(L, -1)); /* memory leak */
if (msg == NULL) msg = "(error object is not a string)";
Previous_error = strdup(lua_tostring(L, -1)); /* memory leak */
if (Previous_error == NULL) Previous_error = "(error object is not a string)";
lua_pop(L, 1);
for (int x = 0; x < COLS; ++x) {
mvaddch(LINES-2, x, ' ');
mvaddch(LINES-1, x, ' ');
}
mvaddstr(LINES-2, 0, msg);
render_previous_error();
mvaddstr(LINES-1, 0, "press any key to continue");
getch();
developer_mode(L, msg);
developer_mode(L);
}
return status;
}
@ -413,11 +448,10 @@ int load_editor_buffer_to_current_definition_in_image(lua_State *L) {
/* return true if user chose to back into the big picture view */
/* But only if there are no errors. Otherwise things can get confusing. */
const char *Previous_error = NULL;
extern int edit (lua_State *L, char *filename, const char *message);
extern int edit (lua_State *L, char *filename);
extern int resumeEdit (lua_State *L);
int edit_current_definition (lua_State *L) {
int back_to_big_picture = edit(L, "teliva_editor_buffer", /*status message*/ "");
int back_to_big_picture = edit(L, "teliva_editor_buffer");
// error handling
while (1) {
int status;
@ -482,7 +516,7 @@ static int render_wrapped_lua_text (int y, int xmin, int xmax, const char *text)
else {
/* newline */
++y;
x = 0;
x = xmin;
move(y, x);
attroff(FG(6));
}
@ -625,7 +659,7 @@ void recent_changes_view (lua_State *L) {
save_note_to_editor_buffer(L, cursor);
/* big picture hotkey unnecessarily available here */
/* TODO: go hotkey is misleading. edits will not be persisted until you return to recent changes */
edit(L, "teliva_editor_buffer", /*status message*/ "");
edit(L, "teliva_editor_buffer");
load_note_from_editor_buffer(L, cursor);
save_image(L);
break;
@ -697,7 +731,7 @@ void draw_definition_name (const char *definition_name) {
}
/* return true if submitted */
void big_picture_view (lua_State *L, const char *status_message) {
void big_picture_view (lua_State *L) {
restart:
clear();
luaL_newmetatable(L, "__teliva_call_graph_depth");
@ -804,7 +838,7 @@ restart:
}
lua_settop(L, 0);
mvprintw(LINES-3, 0, status_message);
render_previous_error();
char query[CURRENT_DEFINITION_LEN+1] = {0};
int qlen = 0;
@ -858,8 +892,8 @@ int editor_view_in_progress (lua_State *L) {
return result;
}
extern int edit_from(lua_State *L, char *filename, const char *message, int rowoff, int coloff, int cy, int cx);
int restore_editor_view (lua_State *L, const char *status_message) {
extern int edit_from(lua_State *L, char *filename, int rowoff, int coloff, int cy, int cx);
int restore_editor_view (lua_State *L) {
lua_getglobal(L, "__teliva_editor_state");
int editor_state_index = lua_gettop(L);
lua_getfield(L, editor_state_index, "definition");
@ -874,7 +908,7 @@ int restore_editor_view (lua_State *L, const char *status_message) {
lua_getfield(L, editor_state_index, "cx");
int cx = lua_tointeger(L, -1);
lua_settop(L, editor_state_index);
int back_to_big_picture = edit_from(L, "teliva_editor_buffer", status_message, rowoff, coloff, cy, cx);
int back_to_big_picture = edit_from(L, "teliva_editor_buffer", rowoff, coloff, cy, cx);
// error handling
while (1) {
int status;
@ -892,18 +926,19 @@ int restore_editor_view (lua_State *L, const char *status_message) {
char **Argv = NULL;
extern void cleanup_curses (void);
void developer_mode (lua_State *L, const char *status_message) {
void developer_mode (lua_State *L) {
/* clobber the app's ncurses colors; we'll restart the app when we rerun it. */
for (int i = 0; i < 8; ++i)
init_pair(i, i, 15);
for (int i = 0; i < 8; ++i)
init_pair(i+8, 0, i);
init_pair(255, /*white fg*/ 15, /*red bg*/ 1); /* for teliva error messages */
nodelay(stdscr, 0); /* make getch() block */
int switch_to_big_picture_view = 1;
if (editor_view_in_progress(L))
switch_to_big_picture_view = restore_editor_view(L, status_message);
switch_to_big_picture_view = restore_editor_view(L);
if (switch_to_big_picture_view)
big_picture_view(L, status_message);
big_picture_view(L);
cleanup_curses();
execv(Argv[0], Argv);
/* never returns */