9 #include "text-motions.h"
13 void vis_lua_start(Vis
*vis
) { }
14 void vis_lua_quit(Vis
*vis
) { }
15 void vis_lua_file_open(Vis
*vis
, File
*file
) { }
16 void vis_lua_file_save(Vis
*vis
, File
*file
) { }
17 void vis_lua_file_close(Vis
*vis
, File
*file
) { }
18 void vis_lua_win_open(Vis
*vis
, Win
*win
) { }
19 void vis_lua_win_close(Vis
*vis
, Win
*win
) { }
20 bool vis_theme_load(Vis
*vis
, const char *name
) { return true; }
25 static void stack_dump_entry(lua_State
*L
, int i
) {
26 int t
= lua_type(L
, i
);
32 printf(lua_toboolean(L
, i
) ? "true" : "false");
34 case LUA_TLIGHTUSERDATA
:
35 printf("lightuserdata(%p)", lua_touserdata(L
, i
));
38 printf("%g", lua_tonumber(L
, i
));
41 printf("`%s'", lua_tostring(L
, i
));
45 lua_pushnil(L
); /* first key */
46 while (lua_next(L
, i
> 0 ? i
: i
- 1)) {
47 stack_dump_entry(L
, -2);
49 stack_dump_entry(L
, -1);
51 lua_pop(L
, 1); /* remove value, keep key */
56 printf("userdata(%p)", lua_touserdata(L
, i
));
58 default: /* other values */
59 printf("%s", lua_typename(L
, t
));
64 static void stack_dump(lua_State
*L
, const char *format
, ...) {
69 int top
= lua_gettop(L
);
70 for (int i
= 1; i
<= top
; i
++) {
72 stack_dump_entry(L
, i
);
81 static int error_function(lua_State
*L
) {
82 Vis
*vis
= lua_touserdata(L
, lua_upvalueindex(1));
84 const char *msg
= lua_tostring(L
, 1);
86 luaL_traceback(L
, L
, msg
, 1);
87 msg
= lua_tolstring(L
, 1, &len
);
88 vis_message_show(vis
, msg
);
92 static int pcall(Vis
*vis
, lua_State
*L
, int nargs
, int nresults
) {
93 /* insert a custom error function below all arguments */
94 int msgh
= lua_gettop(L
) - nargs
;
95 lua_pushlightuserdata(L
, vis
);
96 lua_pushcclosure(L
, error_function
, 1);
98 int ret
= lua_pcall(L
, nargs
, nresults
, msgh
);
103 /* expects a lua function at the top of the stack and stores a
104 * reference to it in the registry. The return value can be used
107 * registry["vis.functions"][(void*)(function)] = function
109 static const void *func_ref_new(lua_State
*L
) {
110 const void *addr
= lua_topointer(L
, -1);
111 if (!lua_isfunction(L
, -1) || !addr
)
113 lua_getfield(L
, LUA_REGISTRYINDEX
, "vis.functions");
114 lua_pushlightuserdata(L
, (void*)addr
);
115 lua_pushvalue(L
, -3);
121 /* retrieve function from registry and place it at the top of the stack */
122 static bool func_ref_get(lua_State
*L
, const void *addr
) {
123 lua_getfield(L
, LUA_REGISTRYINDEX
, "vis.functions");
124 lua_pushlightuserdata(L
, (void*)addr
);
127 if (!lua_isfunction(L
, -1)) {
134 static void *obj_new(lua_State
*L
, size_t size
, const char *type
) {
135 void *obj
= lua_newuserdata(L
, size
);
136 luaL_getmetatable(L
, type
);
137 lua_setmetatable(L
, -2);
139 lua_setuservalue(L
, -2);
143 /* returns registry["vis.objects"][addr] if it is of correct type */
144 static void *obj_ref_get(lua_State
*L
, void *addr
, const char *type
) {
145 lua_getfield(L
, LUA_REGISTRYINDEX
, "vis.objects");
146 lua_pushlightuserdata(L
, addr
);
149 if (lua_isnil(L
, -1)) {
153 return luaL_checkudata(L
, -1, type
);
156 /* expects a userdatum at the top of the stack and sets
158 * registry["vis.objects"][addr] = userdata
160 static void obj_ref_set(lua_State
*L
, void *addr
) {
161 lua_getfield(L
, LUA_REGISTRYINDEX
, "vis.objects");
162 lua_pushlightuserdata(L
, addr
);
163 lua_pushvalue(L
, -3);
168 /* invalidates an object reference
170 * registry["vis.objects"][addr] = nil
172 static void obj_ref_free(lua_State
*L
, void *addr
) {
174 obj_ref_set(L
, addr
);
177 /* creates a new object reference of given type if it does not
178 * already exist in the registry */
179 static void *obj_ref_new(lua_State
*L
, void *addr
, const char *type
) {
182 void **handle
= (void**)obj_ref_get(L
, addr
, type
);
184 handle
= obj_new(L
, sizeof(addr
), type
);
185 obj_ref_set(L
, addr
);
191 /* retrieve object stored in reference at stack location `idx' */
192 static void *obj_ref_check_get(lua_State
*L
, int idx
, const char *type
) {
193 void **addr
= luaL_checkudata(L
, idx
, type
);
194 if (!obj_ref_get(L
, *addr
, type
))
199 /* (type) check validity of object reference at stack location `idx' */
200 static void *obj_ref_check(lua_State
*L
, int idx
, const char *type
) {
201 void *obj
= obj_ref_check_get(L
, idx
, type
);
207 static int index_common(lua_State
*L
) {
208 lua_getmetatable(L
, 1);
211 if (lua_isnil(L
, -1)) {
212 lua_getuservalue(L
, 1);
219 static int newindex_common(lua_State
*L
) {
220 lua_getuservalue(L
, 1);
227 static const char *keymapping(Vis
*vis
, const char *keys
, const Arg
*arg
) {
228 lua_State
*L
= vis
->lua
;
229 if (!func_ref_get(L
, arg
->v
))
235 static int windows_iter(lua_State
*L
);
237 static int windows(lua_State
*L
) {
238 Vis
*vis
= obj_ref_check(L
, 1, "vis");
243 Win
**handle
= lua_newuserdata(L
, sizeof *handle
);
244 *handle
= vis
->windows
;
245 lua_pushcclosure(L
, windows_iter
, 1);
249 static int windows_iter(lua_State
*L
) {
250 Win
**handle
= lua_touserdata(L
, lua_upvalueindex(1));
253 Win
*win
= obj_ref_new(L
, *handle
, "vis.window");
260 static int files_iter(lua_State
*L
);
262 static int files(lua_State
*L
) {
263 Vis
*vis
= obj_ref_check(L
, 1, "vis");
268 File
**handle
= lua_newuserdata(L
, sizeof *handle
);
269 *handle
= vis
->files
;
270 lua_pushcclosure(L
, files_iter
, 1);
274 static int files_iter(lua_State
*L
) {
275 File
**handle
= lua_touserdata(L
, lua_upvalueindex(1));
278 File
*file
= obj_ref_new(L
, *handle
, "vis.file");
281 *handle
= file
->next
;
285 static int command(lua_State
*L
) {
286 Vis
*vis
= obj_ref_check(L
, 1, "vis");
291 const char *cmd
= luaL_checkstring(L
, 2);
292 bool ret
= vis_cmd(vis
, cmd
);
293 lua_pushboolean(L
, ret
);
297 static int info(lua_State
*L
) {
298 Vis
*vis
= obj_ref_check(L
, 1, "vis");
303 const char *msg
= luaL_checkstring(L
, 2);
304 vis_info_show(vis
, "%s", msg
);
308 static int open(lua_State
*L
) {
309 Vis
*vis
= obj_ref_check(L
, 1, "vis");
314 const char *name
= luaL_checkstring(L
, 2);
316 if (vis_window_new(vis
, name
))
317 file
= obj_ref_new(L
, vis
->win
->file
, "vis.file");
323 static int map(lua_State
*L
) {
324 Vis
*vis
= obj_ref_check(L
, 1, "vis");
329 KeyBinding
*binding
= NULL
;
330 KeyAction
*action
= NULL
;
332 int mode
= luaL_checkint(L
, 2);
333 const char *key
= luaL_checkstring(L
, 3);
335 if (!key
|| !lua_isfunction(L
, 4))
337 if (!(binding
= calloc(1, sizeof *binding
)) || !(action
= calloc(1, sizeof *action
)))
340 /* store reference to function in the registry */
342 const void *func
= func_ref_new(L
);
346 *action
= (KeyAction
){
355 binding
->action
= action
;
357 if (!vis_mode_map(vis
, mode
, key
, binding
))
360 lua_pushboolean(L
, true);
365 lua_pushboolean(L
, false);
369 static int motion(lua_State
*L
) {
370 Vis
*vis
= obj_ref_check(L
, 1, "vis");
371 enum VisMotion id
= luaL_checkunsigned(L
, 2);
372 // TODO handle var args?
373 lua_pushboolean(L
, vis
&& vis_motion(vis
, id
));
377 static size_t motion_lua(Vis
*vis
, Win
*win
, void *data
, size_t pos
) {
378 lua_State
*L
= vis
->lua
;
379 if (!func_ref_get(L
, data
) || !obj_ref_new(L
, win
, "vis.window"))
382 lua_pushunsigned(L
, pos
);
383 if (pcall(vis
, L
, 2, 1) != 0)
385 return luaL_checkunsigned(L
, -1);
388 static int motion_register(lua_State
*L
) {
391 Vis
*vis
= obj_ref_check(L
, 1, "vis");
392 if (!vis
|| !lua_isfunction(L
, 2) || !(func
= func_ref_new(L
)))
394 id
= vis_motion_register(vis
, 0, (void*)func
, motion_lua
);
396 lua_pushinteger(L
, id
);
400 static int textobject(lua_State
*L
) {
401 Vis
*vis
= obj_ref_check(L
, 1, "vis");
402 enum VisTextObject id
= luaL_checkunsigned(L
, 2);
403 lua_pushboolean(L
, vis
&& vis_textobject(vis
, id
));
408 static Filerange
textobject_lua(Vis
*vis
, Win
*win
, void *data
, size_t pos
) {
409 lua_State
*L
= vis
->lua
;
410 if (!func_ref_get(L
, data
) || !obj_ref_new(L
, win
, "vis.window"))
411 return text_range_empty();
412 lua_pushunsigned(L
, pos
);
413 if (pcall(vis
, L
, 2, 2) != 0)
414 return text_range_empty();
415 return text_range_new(luaL_checkunsigned(L
, -2), luaL_checkunsigned(L
, -1));
418 static int textobject_register(lua_State
*L
) {
421 Vis
*vis
= obj_ref_check(L
, 1, "vis");
422 if (!vis
|| !lua_isfunction(L
, 2) || !(func
= func_ref_new(L
)))
424 id
= vis_textobject_register(vis
, 0, (void*)func
, textobject_lua
);
426 lua_pushinteger(L
, id
);
430 static int vis_index(lua_State
*L
) {
431 Vis
*vis
= obj_ref_check(L
, 1, "vis");
437 if (lua_isstring(L
, 2)) {
438 const char *key
= lua_tostring(L
, 2);
439 if (strcmp(key
, "win") == 0) {
440 obj_ref_new(L
, vis
->windows
, "vis.window");
444 if (strcmp(key
, "MODE_NORMAL") == 0) {
445 lua_pushunsigned(L
, VIS_MODE_NORMAL
);
449 if (strcmp(key
, "MODE_OPERATOR_PENDING") == 0) {
450 lua_pushunsigned(L
, VIS_MODE_OPERATOR_PENDING
);
454 if (strcmp(key
, "MODE_VISUAL") == 0) {
455 lua_pushunsigned(L
, VIS_MODE_VISUAL
);
459 if (strcmp(key
, "MODE_VISUAL_LINE") == 0) {
460 lua_pushunsigned(L
, VIS_MODE_VISUAL_LINE
);
464 if (strcmp(key
, "MODE_INSERT") == 0) {
465 lua_pushunsigned(L
, VIS_MODE_INSERT
);
469 if (strcmp(key
, "MODE_REPLACE") == 0) {
470 lua_pushunsigned(L
, VIS_MODE_REPLACE
);
475 return index_common(L
);
478 static int vis_newindex(lua_State
*L
) {
479 Vis
*vis
= obj_ref_check(L
, 1, "vis");
482 return newindex_common(L
);
485 static const struct luaL_Reg vis_lua
[] = {
487 { "windows", windows
},
488 { "command", command
},
492 { "motion", motion
},
493 { "motion_register", motion_register
},
494 { "textobject", textobject
},
495 { "textobject_register", textobject_register
},
496 { "__index", vis_index
},
497 { "__newindex", vis_newindex
},
501 static int window_index(lua_State
*L
) {
502 Win
*win
= obj_ref_check(L
, 1, "vis.window");
508 if (lua_isstring(L
, 2)) {
509 const char *key
= lua_tostring(L
, 2);
510 if (strcmp(key
, "file") == 0) {
511 obj_ref_new(L
, win
->file
, "vis.file");
515 if (strcmp(key
, "cursor") == 0) {
516 obj_ref_new(L
, win
->view
, "vis.window.cursor");
520 if (strcmp(key
, "syntax") == 0) {
521 const char *syntax
= view_syntax_get(win
->view
);
523 lua_pushstring(L
, syntax
);
530 return index_common(L
);
533 static int window_newindex(lua_State
*L
) {
534 Win
*win
= obj_ref_check(L
, 1, "vis.window");
537 if (lua_isstring(L
, 2)) {
538 const char *key
= lua_tostring(L
, 2);
539 if (strcmp(key
, "syntax") == 0) {
540 const char *syntax
= luaL_checkstring(L
, 3);
541 view_syntax_set(win
->view
, syntax
);
545 return newindex_common(L
);
548 static const struct luaL_Reg window_funcs
[] = {
549 { "__index", window_index
},
550 { "__newindex", window_newindex
},
554 static int window_cursor_index(lua_State
*L
) {
555 View
*view
= obj_ref_check(L
, 1, "vis.window.cursor");
561 if (lua_isstring(L
, 2)) {
562 Text
*txt
= view_text(view
);
563 const char *key
= lua_tostring(L
, 2);
564 if (strcmp(key
, "pos") == 0) {
565 lua_pushunsigned(L
, view_cursor_get(view
));
569 if (strcmp(key
, "line") == 0) {
570 size_t pos
= view_cursor_get(view
);
571 size_t line
= text_lineno_by_pos(txt
, pos
);
572 lua_pushunsigned(L
, line
);
576 if (strcmp(key
, "col") == 0) {
577 size_t pos
= view_cursor_get(view
);
578 int col
= text_line_char_get(txt
, pos
);
579 lua_pushunsigned(L
, col
);
584 return index_common(L
);
587 static int window_cursor_newindex(lua_State
*L
) {
588 View
*view
= obj_ref_check(L
, 1, "vis.window.cursor");
591 if (lua_isstring(L
, 2)) {
592 const char *key
= lua_tostring(L
, 2);
593 if (strcmp(key
, "pos") == 0) {
594 size_t pos
= luaL_checkunsigned(L
, 3);
595 view_cursor_to(view
, pos
);
599 return newindex_common(L
);
602 static int window_cursor_to(lua_State
*L
) {
603 View
*view
= obj_ref_check(L
, 1, "vis.window.cursor");
605 Text
*txt
= view_text(view
);
606 size_t line
= luaL_checkunsigned(L
, 2);
607 size_t col
= luaL_checkunsigned(L
, 3);
608 size_t pos
= text_pos_by_lineno(txt
, line
);
609 pos
= text_line_char_set(txt
, pos
, col
);
610 view_cursor_to(view
, pos
);
615 static const struct luaL_Reg window_cursor_funcs
[] = {
616 { "__index", window_cursor_index
},
617 { "__newindex", window_cursor_newindex
},
618 { "to", window_cursor_to
},
622 static int file_index(lua_State
*L
) {
623 File
*file
= obj_ref_check(L
, 1, "vis.file");
629 if (lua_isstring(L
, 2)) {
630 const char *key
= lua_tostring(L
, 2);
631 if (strcmp(key
, "name") == 0) {
632 lua_pushstring(L
, file
->name
);
635 if (strcmp(key
, "lines") == 0) {
636 obj_ref_new(L
, file
->text
, "vis.file.text");
641 return index_common(L
);
644 static int file_newindex(lua_State
*L
) {
645 File
*file
= obj_ref_check(L
, 1, "vis.file");
648 return newindex_common(L
);
651 static int file_insert(lua_State
*L
) {
652 File
*file
= obj_ref_check(L
, 1, "vis.file");
654 size_t pos
= luaL_checkunsigned(L
, 2);
656 luaL_checkstring(L
, 3);
657 const char *data
= lua_tolstring(L
, 3, &len
);
658 bool ret
= text_insert(file
->text
, pos
, data
, len
);
659 lua_pushboolean(L
, ret
);
661 lua_pushboolean(L
, false);
666 static int file_delete(lua_State
*L
) {
667 File
*file
= obj_ref_check(L
, 1, "vis.file");
669 size_t pos
= luaL_checkunsigned(L
, 2);
670 size_t len
= luaL_checkunsigned(L
, 3);
671 bool ret
= text_delete(file
->text
, pos
, len
);
672 lua_pushboolean(L
, ret
);
674 lua_pushboolean(L
, false);
679 static int file_lines_iterator_it(lua_State
*L
);
681 static int file_lines_iterator(lua_State
*L
) {
682 /* need to check second parameter first, because obj_ref_check_get
683 * modifies the stack */
684 size_t line
= luaL_optunsigned(L
, 2, 1);
685 File
*file
= obj_ref_check_get(L
, 1, "vis.file");
686 size_t *pos
= lua_newuserdata(L
, sizeof *pos
);
687 *pos
= text_pos_by_lineno(file
->text
, line
);
688 lua_pushcclosure(L
, file_lines_iterator_it
, 2);
692 static int file_lines_iterator_it(lua_State
*L
) {
693 File
*file
= *(File
**)lua_touserdata(L
, lua_upvalueindex(1));
694 size_t *start
= lua_touserdata(L
, lua_upvalueindex(2));
695 if (*start
== text_size(file
->text
))
697 size_t end
= text_line_end(file
->text
, *start
);
698 size_t len
= end
- *start
;
699 char *buf
= malloc(len
);
702 len
= text_bytes_get(file
->text
, *start
, len
, buf
);
703 lua_pushlstring(L
, buf
, len
);
705 *start
= text_line_next(file
->text
, end
);
709 static const struct luaL_Reg file_funcs
[] = {
710 { "__index", file_index
},
711 { "__newindex", file_newindex
},
712 { "insert", file_insert
},
713 { "delete", file_delete
},
714 { "lines_iterator", file_lines_iterator
},
718 static int file_lines_index(lua_State
*L
) {
719 Text
*txt
= obj_ref_check(L
, 1, "vis.file.text");
722 size_t line
= luaL_checkunsigned(L
, 2);
723 size_t start
= text_pos_by_lineno(txt
, line
);
724 size_t end
= text_line_end(txt
, start
);
725 if (start
!= EPOS
&& end
!= EPOS
) {
726 size_t size
= end
- start
;
727 char *data
= malloc(size
);
730 size
= text_bytes_get(txt
, start
, size
, data
);
731 lua_pushlstring(L
, data
, size
);
740 static int file_lines_newindex(lua_State
*L
) {
741 Text
*txt
= obj_ref_check(L
, 1, "vis.file.text");
744 size_t line
= luaL_checkunsigned(L
, 2);
746 const char *data
= luaL_checklstring(L
, 3, &size
);
748 text_insert(txt
, 0, data
, size
);
749 text_insert_newline(txt
, size
);
752 size_t start
= text_pos_by_lineno(txt
, line
);
753 size_t end
= text_line_end(txt
, start
);
754 if (start
!= EPOS
&& end
!= EPOS
) {
755 text_delete(txt
, start
, end
- start
);
756 text_insert(txt
, start
, data
, size
);
757 if (text_size(txt
) == start
+ size
)
758 text_insert_newline(txt
, text_size(txt
));
763 static int file_lines_len(lua_State
*L
) {
764 Text
*txt
= obj_ref_check(L
, 1, "vis.file.text");
768 size_t size
= text_size(txt
);
770 lines
= text_lineno_by_pos(txt
, size
);
771 if (lines
> 1 && text_byte_get(txt
, size
-1, &lastchar
) && lastchar
== '\n')
774 lua_pushunsigned(L
, lines
);
778 static const struct luaL_Reg file_lines_funcs
[] = {
779 { "__index", file_lines_index
},
780 { "__newindex", file_lines_newindex
},
781 { "__len", file_lines_len
},
785 static void vis_lua_event(Vis
*vis
, const char *name
) {
786 lua_State
*L
= vis
->lua
;
787 lua_getglobal(L
, "vis");
788 lua_getfield(L
, -1, "events");
789 if (lua_istable(L
, -1)) {
790 lua_getfield(L
, -1, name
);
795 void vis_lua_start(Vis
*vis
) {
796 lua_State
*L
= luaL_newstate();
803 /* extends lua's package.path with:
804 * - $VIS_PATH/{,lexers}
805 * - $XDG_CONFIG_HOME/vis/{,lexers} (defaulting to $HOME/.config/vis/{,lexers})
806 * - /usr/local/share/vis/{,lexers}
807 * - /usr/share/vis/{,lexers}
808 * - package.path (standard lua search path)
811 lua_getglobal(L
, "package");
813 const char *vis_path
= getenv("VIS_PATH");
815 lua_pushstring(L
, vis_path
);
816 lua_pushstring(L
, "/?.lua;");
817 lua_pushstring(L
, vis_path
);
818 lua_pushstring(L
, "/lexers/?.lua;");
823 /* try to get users home directory */
824 const char *home
= getenv("HOME");
825 if (!home
|| !*home
) {
826 struct passwd
*pw
= getpwuid(getuid());
831 const char *xdg_config
= getenv("XDG_CONFIG_HOME");
833 lua_pushstring(L
, xdg_config
);
834 lua_pushstring(L
, "/vis/?.lua;");
835 lua_pushstring(L
, xdg_config
);
836 lua_pushstring(L
, "/vis/lexers/?.lua;");
839 } else if (home
&& *home
) {
840 lua_pushstring(L
, home
);
841 lua_pushstring(L
, "/.config/vis/?.lua;");
842 lua_pushstring(L
, home
);
843 lua_pushstring(L
, "/.config/vis/lexers/?.lua;");
848 lua_pushstring(L
, "/usr/local/share/vis/?.lua;/usr/local/share/vis/lexers/?.lua;");
849 lua_pushstring(L
, "/usr/share/vis/?.lua;/usr/share/vis/lexers/?.lua;");
850 lua_getfield(L
, -paths
, "path");
851 lua_concat(L
, paths
);
852 lua_setfield(L
, -2, "path");
853 lua_pop(L
, 1); /* package */
855 /* table in registry to track lifetimes of C objects */
857 lua_setfield(L
, LUA_REGISTRYINDEX
, "vis.objects");
858 /* table in registry to store references to Lua functions */
860 lua_setfield(L
, LUA_REGISTRYINDEX
, "vis.functions");
861 /* metatable used to type check user data */
862 luaL_newmetatable(L
, "vis.file");
863 luaL_setfuncs(L
, file_funcs
, 0);
864 luaL_newmetatable(L
, "vis.file.text");
865 luaL_setfuncs(L
, file_lines_funcs
, 0);
866 luaL_newmetatable(L
, "vis.window");
867 luaL_setfuncs(L
, window_funcs
, 0);
868 luaL_newmetatable(L
, "vis.window.cursor");
869 luaL_setfuncs(L
, window_cursor_funcs
, 0);
870 /* vis module table with up value as the C pointer */
871 luaL_newmetatable(L
, "vis");
872 luaL_setfuncs(L
, vis_lua
, 0);
873 obj_ref_new(L
, vis
, "vis");
874 lua_setglobal(L
, "vis");
876 lua_getglobal(L
, "require");
877 lua_pushstring(L
, "visrc");
879 vis_lua_event(vis
, "start");
880 if (lua_isfunction(L
, -1))
885 void vis_lua_quit(Vis
*vis
) {
886 lua_State
*L
= vis
->lua
;
889 vis_lua_event(vis
, "quit");
890 if (lua_isfunction(L
, -1))
896 void vis_lua_file_open(Vis
*vis
, File
*file
) {
900 void vis_lua_file_save(Vis
*vis
, File
*file
) {
904 void vis_lua_file_close(Vis
*vis
, File
*file
) {
905 lua_State
*L
= vis
->lua
;
906 vis_lua_event(vis
, "file_close");
907 if (lua_isfunction(L
, -1)) {
908 obj_ref_new(L
, file
, "vis.file");
911 obj_ref_free(L
, file
->text
);
912 obj_ref_free(L
, file
);
916 void vis_lua_win_open(Vis
*vis
, Win
*win
) {
917 lua_State
*L
= vis
->lua
;
918 vis_lua_event(vis
, "win_open");
919 if (lua_isfunction(L
, -1)) {
920 obj_ref_new(L
, win
, "vis.window");
926 void vis_lua_win_close(Vis
*vis
, Win
*win
) {
927 lua_State
*L
= vis
->lua
;
928 vis_lua_event(vis
, "win_close");
929 if (lua_isfunction(L
, -1)) {
930 obj_ref_new(L
, win
, "vis.window");
933 obj_ref_free(L
, win
->view
);
934 obj_ref_free(L
, win
);
938 bool vis_theme_load(Vis
*vis
, const char *name
) {
939 lua_State
*L
= vis
->lua
;
942 /* package.loaded['themes/'..name] = nil
943 * require 'themes/'..name */
944 lua_pushstring(L
, "themes/");
945 lua_pushstring(L
, name
);
947 lua_getglobal(L
, "package");
948 lua_getfield(L
, -1, "loaded");
949 lua_pushvalue(L
, -3);
953 lua_getglobal(L
, "require");
954 lua_pushvalue(L
, -2);
955 if (pcall(vis
, L
, 1, 0))
957 for (Win
*win
= vis
->windows
; win
; win
= win
->next
)
958 view_syntax_set(win
->view
, view_syntax_get(win
->view
));