/* vifm * Copyright (C) 2020 xaizek. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #include "vifmtab.h" #include "../cfg/config.h" #include "../ui/tabs.h" #include "../ui/ui.h" #include "lua/lauxlib.h" #include "lua/lua.h" #include "api.h" #include "common.h" #include "vifmview.h" /* Pointer to a function used to traverse tabs. */ typedef int (*tab_search_f)(struct view_t *side, int idx, tab_info_t *tab_info); static int VLUA_API(vifmtab_getlayout)(lua_State *lua); static int VLUA_API(vifmtab_getname)(lua_State *lua); static int VLUA_API(vifmtab_getview)(lua_State *lua); static void find_tab(lua_State *lua, unsigned int id, tab_info_t *tab_info); static void find_side_tab(lua_State *lua, unsigned int id, tab_info_t *tab_info, view_t *side, tab_search_f tab_search); VLUA_DECLARE_SAFE(vifmtab_getlayout); VLUA_DECLARE_SAFE(vifmtab_getname); VLUA_DECLARE_SAFE(vifmtab_getview); /* Methods of VifmTab type. */ static const luaL_Reg vifmtab_methods[] = { { "getlayout", VLUA_REF(vifmtab_getlayout), }, { "getname", VLUA_REF(vifmtab_getname), }, { "getview", VLUA_REF(vifmtab_getview), }, { NULL, NULL } }; void vifmtab_init(lua_State *lua) { vlua_cmn_make_metatable(lua, "VifmTab"); luaL_setfuncs(lua, vifmtab_methods, 0); lua_pop(lua, 1); } int VLUA_API(vifmtab_new)(struct lua_State *lua) { view_t *side = curr_view; int index; int index_set = 0; if(!lua_isnoneornil(lua, 1)) { if(vlua_cmn_check_opt_field(lua, 1, "other", LUA_TBOOLEAN) && lua_toboolean(lua, -1)) { side = other_view; } if(vlua_cmn_check_opt_field(lua, 1, "index", LUA_TNUMBER)) { index = lua_tointeger(lua, -1) - 1; index_set = 1; } } if(!index_set) { index = tabs_current(side); } tab_info_t tab_info; if(!tabs_get(side, index, &tab_info)) { return luaL_error(lua, "No tab with index %d on %s side", index, side == curr_view ? "active" : "inactive"); } unsigned int *data = lua_newuserdatauv(lua, sizeof(*data), 0); *data = tab_info.id; luaL_getmetatable(lua, "VifmTab"); lua_setmetatable(lua, -2); return 1; } /* Method of `VifmTab` that retrieves its layout. Returns a table. */ static int VLUA_API(vifmtab_getlayout)(lua_State *lua) { const unsigned int *id = luaL_checkudata(lua, 1, "VifmTab"); tab_info_t tab_info; find_tab(lua, *id, &tab_info); lua_createtable(lua, /*narr=*/0, /*nrec=*/2); lua_pushboolean(lua, tab_info.layout.only_mode); lua_setfield(lua, -2, "only"); if(!tab_info.layout.only_mode) { lua_pushstring(lua, tab_info.layout.split == HSPLIT ? "h" : "v"); lua_setfield(lua, -2, "split"); } return 1; } /* Method of `VifmTab` that retrieves its name. Returns a string. */ static int VLUA_API(vifmtab_getname)(lua_State *lua) { const unsigned int *id = luaL_checkudata(lua, 1, "VifmTab"); tab_info_t tab_info; find_tab(lua, *id, &tab_info); lua_pushstring(lua, (tab_info.name == NULL ? "" : tab_info.name)); return 1; } /* Method of `VifmTab` that retrieves a view. Returns `VifmView`. */ static int VLUA_API(vifmtab_getview)(lua_State *lua) { const unsigned int *id = luaL_checkudata(lua, 1, "VifmTab"); /* Querying active pane of a global tab by default. */ view_t *side = curr_view; tab_search_f tab_search = tabs_get; if(vlua_cmn_check_opt_arg(lua, 2, LUA_TTABLE) && vlua_cmn_check_opt_field(lua, 2, "pane", LUA_TNUMBER)) { int pane = lua_tointeger(lua, -1); if(pane < 1 || pane > 2) { return luaL_error(lua, "%s", "pane field is not in the range [1; 2]"); } /* Querying specific side of a global tab. */ side = (pane == 1 ? &lwin : &rwin); tab_search = tabs_enum; } tab_info_t tab_info; if(cfg.pane_tabs) { find_tab(lua, *id, &tab_info); } else { find_side_tab(lua, *id, &tab_info, side, tab_search); } vifmview_new(lua, tab_info.view); return 1; } /* Find tab by its id. Returns the pointer or aborts (Lua does longjmp()) if * the tab doesn't exist anymore. */ static void find_tab(lua_State *lua, unsigned int id, tab_info_t *tab_info) { int i; for(i = 0; tabs_enum_all(i, tab_info); ++i) { if(tab_info->id == id) { return; } } luaL_error(lua, "%s", "Invalid VifmTab object (associated tab is dead)"); } /* Find global tab by its id and side (to get correct view). Returns the * pointer or aborts (Lua does longjmp()) if the tab doesn't exist anymore. */ static void find_side_tab(lua_State *lua, unsigned int id, tab_info_t *tab_info, view_t *side, tab_search_f tab_search) { int i; for(i = 0; tab_search(side, i, tab_info); ++i) { if(tab_info->id == id) { return; } } luaL_error(lua, "%s", "Invalid VifmTab object (associated tab is dead)"); } /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set cinoptions+=t0 : */