about summary refs log tree commit diff stats
path: root/src/teliva.c
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-01-03 23:36:44 -0800
committerKartik K. Agaram <vc@akkartik.com>2022-01-03 23:36:44 -0800
commit4018c2e8e2499c1a8a625ef717ae9dc242bd83e3 (patch)
tree430bbb12f66159f164b7f3090e36aa46fae42582 /src/teliva.c
parent7812ebc5f119cd4c47e6a91db0561008c7080bc5 (diff)
downloadteliva-4018c2e8e2499c1a8a625ef717ae9dc242bd83e3.tar.gz
when editing a function, show its callers
No way to select between them. That complicates the UI too much when we
do so much with the cursor. But it's still useful to suggest things to
type in after ctrl-g.
Diffstat (limited to 'src/teliva.c')
-rw-r--r--src/teliva.c56
1 files changed, 50 insertions, 6 deletions
diff --git a/src/teliva.c b/src/teliva.c
index 1dc68ae..b136f8d 100644
--- a/src/teliva.c
+++ b/src/teliva.c
@@ -301,11 +301,16 @@ void append_string_to_array(lua_State* L, int array_index, const char* s) {
   lua_rawseti(L, array_index, new_index);
 }
 
-void save_caller(lua_State* L, const char* name) {
+extern void save_caller_as(lua_State* L, const char* name, const char* caller_name);
+void save_caller(lua_State* L, const char* name, int call_graph_depth) {
   lua_Debug ar;
-  lua_getstack(L, 2, &ar);
+  lua_getstack(L, 1, &ar);
   lua_getinfo(L, "n", &ar);
-  if (!ar.name) return;
+  if (ar.name) save_caller_as(L, name, ar.name);
+  else if (call_graph_depth == 2) save_caller_as(L, name, "main");  // the way Teliva calls `main` messes with debug info
+}
+
+void save_caller_as(lua_State* L, const char* name, const char* caller_name) {
   // push table of caller tables
   luaL_newmetatable(L, "__teliva_caller");
   int ct = lua_gettop(L);
@@ -320,12 +325,28 @@ void save_caller(lua_State* L, const char* name) {
   lua_getfield(L, ct, name);  // new value = caller table
   int curr_caller_index = lua_gettop(L);
   lua_pushboolean(L, true);
-  lua_setfield(L, curr_caller_index, ar.name);
+  lua_setfield(L, curr_caller_index, caller_name);
   // clean up
   lua_pop(L, 1);  // caller table
   lua_pop(L, 1);  // table of caller tables
 }
 
+static void clear_caller(lua_State* L) {
+  int oldtop = lua_gettop(L);
+  luaL_newmetatable(L, "__teliva_caller");
+  int ct = lua_gettop(L);
+  lua_pushnil(L);
+  while (lua_next(L, ct) != 0) {
+    lua_pop(L, 1);  /* old value */
+    lua_pushvalue(L, -1);  /* duplicate key */
+    lua_pushnil(L);  /* new value */
+    lua_settable(L, ct);
+    /* one copy of key left for lua_next */
+  }
+  lua_pop(L, 1);
+  assert(lua_gettop(L) == oldtop);
+}
+
 /* return true if submitted */
 static int edit_current_definition(lua_State* L);
 static void recent_changes_view(lua_State* L);
@@ -583,6 +604,30 @@ int editor_view_in_progress(lua_State* L) {
   return result;
 }
 
+char Current_definition[CURRENT_DEFINITION_LEN+1] = {0};
+
+void draw_callers_of_current_definition(lua_State* L) {
+  int oldtop = lua_gettop(L);
+  luaL_newmetatable(L, "__teliva_caller");
+  int ct = lua_gettop(L);
+  lua_getfield(L, ct, Current_definition);
+  if (lua_isnil(L, -1)) {
+    lua_pop(L, 2);
+    assert(oldtop == lua_gettop(L));
+    return;
+  }
+  int ctc = lua_gettop(L);
+  attron(COLOR_PAIR(COLOR_PAIR_FADE));
+  mvaddstr(0, 0, "callers: ");
+  attroff(COLOR_PAIR(COLOR_PAIR_FADE));
+  for (lua_pushnil(L); lua_next(L, ctc) != 0; lua_pop(L, 1)) {
+    const char* caller_name = lua_tostring(L, -2);
+    draw_definition_name(caller_name);
+  }
+  lua_pop(L, 2);  // caller table, __teliva_caller
+  assert(oldtop == lua_gettop(L));
+}
+
 extern int load_editor_buffer_to_current_definition_in_image(lua_State* L);
 extern int resumeEdit(lua_State* L);
 extern int editFrom(lua_State* L, char* filename, int rowoff, int coloff, int cy, int cx);
@@ -648,8 +693,6 @@ void developer_mode(lua_State* L) {
   /* never returns */
 }
 
-char Current_definition[CURRENT_DEFINITION_LEN+1] = {0};
-
 extern int mkstemp(char* template);
 extern FILE* fdopen(int fd, const char* mode);
 void save_editor_state(int rowoff, int coloff, int cy, int cx) {
@@ -1539,6 +1582,7 @@ int handle_image(lua_State* L, char** argv, int n) {
   if (status != 0) return report_in_developer_mode(L, status);
   /* clear callgraph stats from running tests */
   clear_call_graph(L);
+  clear_caller(L);
   /* initialize permissions */
   load_permissions_from_user_configuration(L);
   /* call main() */