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
= NULL
;
541 if (!lua_isnil(L
, 3))
542 syntax
= luaL_checkstring(L
, 3);
543 view_syntax_set(win
->view
, syntax
);
547 return newindex_common(L
);
550 static const struct luaL_Reg window_funcs
[] = {
551 { "__index", window_index
},
552 { "__newindex", window_newindex
},
556 static int window_cursor_index(lua_State
*L
) {
557 View
*view
= obj_ref_check(L
, 1, "vis.window.cursor");
563 if (lua_isstring(L
, 2)) {
564 Text
*txt
= view_text(view
);
565 const char *key
= lua_tostring(L
, 2);
566 if (strcmp(key
, "pos") == 0) {
567 lua_pushunsigned(L
, view_cursor_get(view
));
571 if (strcmp(key
, "line") == 0) {
572 size_t pos
= view_cursor_get(view
);
573 size_t line
= text_lineno_by_pos(txt
, pos
);
574 lua_pushunsigned(L
, line
);
578 if (strcmp(key
, "col") == 0) {
579 size_t pos
= view_cursor_get(view
);
580 int col
= text_line_char_get(txt
, pos
);
581 lua_pushunsigned(L
, col
);
586 return index_common(L
);
589 static int window_cursor_newindex(lua_State
*L
) {
590 View
*view
= obj_ref_check(L
, 1, "vis.window.cursor");
593 if (lua_isstring(L
, 2)) {
594 const char *key
= lua_tostring(L
, 2);
595 if (strcmp(key
, "pos") == 0) {
596 size_t pos
= luaL_checkunsigned(L
, 3);
597 view_cursor_to(view
, pos
);
601 return newindex_common(L
);
604 static int window_cursor_to(lua_State
*L
) {
605 View
*view
= obj_ref_check(L
, 1, "vis.window.cursor");
607 Text
*txt
= view_text(view
);
608 size_t line
= luaL_checkunsigned(L
, 2);
609 size_t col
= luaL_checkunsigned(L
, 3);
610 size_t pos
= text_pos_by_lineno(txt
, line
);
611 pos
= text_line_char_set(txt
, pos
, col
);
612 view_cursor_to(view
, pos
);
617 static const struct luaL_Reg window_cursor_funcs
[] = {
618 { "__index", window_cursor_index
},
619 { "__newindex", window_cursor_newindex
},
620 { "to", window_cursor_to
},
624 static int file_index(lua_State
*L
) {
625 File
*file
= obj_ref_check(L
, 1, "vis.file");
631 if (lua_isstring(L
, 2)) {
632 const char *key
= lua_tostring(L
, 2);
633 if (strcmp(key
, "name") == 0) {
634 lua_pushstring(L
, file
->name
);
637 if (strcmp(key
, "lines") == 0) {
638 obj_ref_new(L
, file
->text
, "vis.file.text");
643 return index_common(L
);
646 static int file_newindex(lua_State
*L
) {
647 File
*file
= obj_ref_check(L
, 1, "vis.file");
650 return newindex_common(L
);
653 static int file_insert(lua_State
*L
) {
654 File
*file
= obj_ref_check(L
, 1, "vis.file");
656 size_t pos
= luaL_checkunsigned(L
, 2);
658 luaL_checkstring(L
, 3);
659 const char *data
= lua_tolstring(L
, 3, &len
);
660 bool ret
= text_insert(file
->text
, pos
, data
, len
);
661 lua_pushboolean(L
, ret
);
663 lua_pushboolean(L
, false);
668 static int file_delete(lua_State
*L
) {
669 File
*file
= obj_ref_check(L
, 1, "vis.file");
671 size_t pos
= luaL_checkunsigned(L
, 2);
672 size_t len
= luaL_checkunsigned(L
, 3);
673 bool ret
= text_delete(file
->text
, pos
, len
);
674 lua_pushboolean(L
, ret
);
676 lua_pushboolean(L
, false);
681 static int file_lines_iterator_it(lua_State
*L
);
683 static int file_lines_iterator(lua_State
*L
) {
684 /* need to check second parameter first, because obj_ref_check_get
685 * modifies the stack */
686 size_t line
= luaL_optunsigned(L
, 2, 1);
687 File
*file
= obj_ref_check_get(L
, 1, "vis.file");
688 size_t *pos
= lua_newuserdata(L
, sizeof *pos
);
689 *pos
= text_pos_by_lineno(file
->text
, line
);
690 lua_pushcclosure(L
, file_lines_iterator_it
, 2);
694 static int file_lines_iterator_it(lua_State
*L
) {
695 File
*file
= *(File
**)lua_touserdata(L
, lua_upvalueindex(1));
696 size_t *start
= lua_touserdata(L
, lua_upvalueindex(2));
697 if (*start
== text_size(file
->text
))
699 size_t end
= text_line_end(file
->text
, *start
);
700 size_t len
= end
- *start
;
701 char *buf
= malloc(len
);
704 len
= text_bytes_get(file
->text
, *start
, len
, buf
);
705 lua_pushlstring(L
, buf
, len
);
707 *start
= text_line_next(file
->text
, end
);
711 static int file_content(lua_State
*L
) {
712 File
*file
= obj_ref_check(L
, 1, "vis.file");
715 size_t pos
= luaL_checkunsigned(L
, 2);
716 size_t len
= luaL_checkunsigned(L
, 3);
717 char *data
= malloc(len
);
720 len
= text_bytes_get(file
->text
, pos
, len
, data
);
721 lua_pushlstring(L
, data
, len
);
729 static const struct luaL_Reg file_funcs
[] = {
730 { "__index", file_index
},
731 { "__newindex", file_newindex
},
732 { "insert", file_insert
},
733 { "delete", file_delete
},
734 { "lines_iterator", file_lines_iterator
},
735 { "content", file_content
},
739 static int file_lines_index(lua_State
*L
) {
740 Text
*txt
= obj_ref_check(L
, 1, "vis.file.text");
743 size_t line
= luaL_checkunsigned(L
, 2);
744 size_t start
= text_pos_by_lineno(txt
, line
);
745 size_t end
= text_line_end(txt
, start
);
746 if (start
!= EPOS
&& end
!= EPOS
) {
747 size_t size
= end
- start
;
748 char *data
= malloc(size
);
751 size
= text_bytes_get(txt
, start
, size
, data
);
752 lua_pushlstring(L
, data
, size
);
761 static int file_lines_newindex(lua_State
*L
) {
762 Text
*txt
= obj_ref_check(L
, 1, "vis.file.text");
765 size_t line
= luaL_checkunsigned(L
, 2);
767 const char *data
= luaL_checklstring(L
, 3, &size
);
769 text_insert(txt
, 0, data
, size
);
770 text_insert_newline(txt
, size
);
773 size_t start
= text_pos_by_lineno(txt
, line
);
774 size_t end
= text_line_end(txt
, start
);
775 if (start
!= EPOS
&& end
!= EPOS
) {
776 text_delete(txt
, start
, end
- start
);
777 text_insert(txt
, start
, data
, size
);
778 if (text_size(txt
) == start
+ size
)
779 text_insert_newline(txt
, text_size(txt
));
784 static int file_lines_len(lua_State
*L
) {
785 Text
*txt
= obj_ref_check(L
, 1, "vis.file.text");
789 size_t size
= text_size(txt
);
791 lines
= text_lineno_by_pos(txt
, size
);
792 if (lines
> 1 && text_byte_get(txt
, size
-1, &lastchar
) && lastchar
== '\n')
795 lua_pushunsigned(L
, lines
);
799 static const struct luaL_Reg file_lines_funcs
[] = {
800 { "__index", file_lines_index
},
801 { "__newindex", file_lines_newindex
},
802 { "__len", file_lines_len
},
806 static void vis_lua_event(Vis
*vis
, const char *name
) {
807 lua_State
*L
= vis
->lua
;
808 lua_getglobal(L
, "vis");
809 lua_getfield(L
, -1, "events");
810 if (lua_istable(L
, -1)) {
811 lua_getfield(L
, -1, name
);
816 void vis_lua_start(Vis
*vis
) {
817 lua_State
*L
= luaL_newstate();
824 /* extends lua's package.path with:
825 * - $VIS_PATH/{,lexers}
826 * - $XDG_CONFIG_HOME/vis/{,lexers} (defaulting to $HOME/.config/vis/{,lexers})
827 * - /usr/local/share/vis/{,lexers}
828 * - /usr/share/vis/{,lexers}
829 * - package.path (standard lua search path)
832 lua_getglobal(L
, "package");
834 const char *vis_path
= getenv("VIS_PATH");
836 lua_pushstring(L
, vis_path
);
837 lua_pushstring(L
, "/?.lua;");
838 lua_pushstring(L
, vis_path
);
839 lua_pushstring(L
, "/lexers/?.lua;");
844 /* try to get users home directory */
845 const char *home
= getenv("HOME");
846 if (!home
|| !*home
) {
847 struct passwd
*pw
= getpwuid(getuid());
852 const char *xdg_config
= getenv("XDG_CONFIG_HOME");
854 lua_pushstring(L
, xdg_config
);
855 lua_pushstring(L
, "/vis/?.lua;");
856 lua_pushstring(L
, xdg_config
);
857 lua_pushstring(L
, "/vis/lexers/?.lua;");
860 } else if (home
&& *home
) {
861 lua_pushstring(L
, home
);
862 lua_pushstring(L
, "/.config/vis/?.lua;");
863 lua_pushstring(L
, home
);
864 lua_pushstring(L
, "/.config/vis/lexers/?.lua;");
869 lua_pushstring(L
, "/usr/local/share/vis/?.lua;/usr/local/share/vis/lexers/?.lua;");
870 lua_pushstring(L
, "/usr/share/vis/?.lua;/usr/share/vis/lexers/?.lua;");
871 lua_getfield(L
, -paths
, "path");
872 lua_concat(L
, paths
);
873 lua_setfield(L
, -2, "path");
874 lua_pop(L
, 1); /* package */
876 /* table in registry to track lifetimes of C objects */
878 lua_setfield(L
, LUA_REGISTRYINDEX
, "vis.objects");
879 /* table in registry to store references to Lua functions */
881 lua_setfield(L
, LUA_REGISTRYINDEX
, "vis.functions");
882 /* metatable used to type check user data */
883 luaL_newmetatable(L
, "vis.file");
884 luaL_setfuncs(L
, file_funcs
, 0);
885 luaL_newmetatable(L
, "vis.file.text");
886 luaL_setfuncs(L
, file_lines_funcs
, 0);
887 luaL_newmetatable(L
, "vis.window");
888 luaL_setfuncs(L
, window_funcs
, 0);
889 luaL_newmetatable(L
, "vis.window.cursor");
890 luaL_setfuncs(L
, window_cursor_funcs
, 0);
891 /* vis module table with up value as the C pointer */
892 luaL_newmetatable(L
, "vis");
893 luaL_setfuncs(L
, vis_lua
, 0);
894 obj_ref_new(L
, vis
, "vis");
895 lua_setglobal(L
, "vis");
897 lua_getglobal(L
, "require");
898 lua_pushstring(L
, "visrc");
900 vis_lua_event(vis
, "start");
901 if (lua_isfunction(L
, -1))
906 void vis_lua_quit(Vis
*vis
) {
907 lua_State
*L
= vis
->lua
;
910 vis_lua_event(vis
, "quit");
911 if (lua_isfunction(L
, -1))
917 void vis_lua_file_open(Vis
*vis
, File
*file
) {
921 void vis_lua_file_save(Vis
*vis
, File
*file
) {
925 void vis_lua_file_close(Vis
*vis
, File
*file
) {
926 lua_State
*L
= vis
->lua
;
927 vis_lua_event(vis
, "file_close");
928 if (lua_isfunction(L
, -1)) {
929 obj_ref_new(L
, file
, "vis.file");
932 obj_ref_free(L
, file
->text
);
933 obj_ref_free(L
, file
);
937 void vis_lua_win_open(Vis
*vis
, Win
*win
) {
938 lua_State
*L
= vis
->lua
;
939 vis_lua_event(vis
, "win_open");
940 if (lua_isfunction(L
, -1)) {
941 obj_ref_new(L
, win
, "vis.window");
947 void vis_lua_win_close(Vis
*vis
, Win
*win
) {
948 lua_State
*L
= vis
->lua
;
949 vis_lua_event(vis
, "win_close");
950 if (lua_isfunction(L
, -1)) {
951 obj_ref_new(L
, win
, "vis.window");
954 obj_ref_free(L
, win
->view
);
955 obj_ref_free(L
, win
);
959 bool vis_theme_load(Vis
*vis
, const char *name
) {
960 lua_State
*L
= vis
->lua
;
963 /* package.loaded['themes/'..name] = nil
964 * require 'themes/'..name */
965 lua_pushstring(L
, "themes/");
966 lua_pushstring(L
, name
);
968 lua_getglobal(L
, "package");
969 lua_getfield(L
, -1, "loaded");
970 lua_pushvalue(L
, -3);
974 lua_getglobal(L
, "require");
975 lua_pushvalue(L
, -2);
976 if (pcall(vis
, L
, 1, 0))
978 for (Win
*win
= vis
->windows
; win
; win
= win
->next
)
979 view_syntax_set(win
->view
, view_syntax_get(win
->view
));