------------------------------------------------------------------------------- -- Tools to deal with the board ------------------------------------------------------------------------------- local Board = { saved_state = nil, } local Util = require('oleoboard.util') ------------------------------------------------------------------------------- -- Internal Functions ------------------------------------------------------------------------------- local function get_directories(parent_path) local directories = {} local directory_iterator = vim.loop.fs_scandir(parent_path) if directory_iterator then while true do local name, type = vim.loop.fs_scandir_next(directory_iterator) if not name then break end if type == "directory" then table.insert(directories, 1, parent_path .. '/' .. name) end end else vim.api.nvim_err_writeln('Could not read directory ' .. parent_path) end return directories end local function save_state() local config_dir = vim.fn.stdpath('config') local session_file = config_dir .. '/oleoboard.saved' vim.cmd('mks! ' .. session_file) Board.saved_state = session_file end local function close_all_buffers() for _, window in ipairs(vim.api.nvim_list_wins()) do if window ~= vim.api.nvim_get_current_win() then vim.api.nvim_win_close(window, false) end end end local function restore_state() if Board.saved_state then local config_dir = vim.fn.stdpath('config') local session_file = config_dir .. '/oleoboard.saved' if vim.fn.filereadable(session_file) == 1 then vim.cmd('source ' .. session_file) vim.fn.delete(session_file) end Board.saved_state = nil end end local function find_left_neighbor(windows, current_window) local left_window = nil for _, window in ipairs(windows) do local window_position = vim.api.nvim_win_get_position(window) local current_position = vim.api.nvim_win_get_position(current_window) if Util.is_left_of(current_position, window_position) then if left_window then local candidate_position = vim.api.nvim_win_get_position(left_window) if Util.is_right_of(candidate_position, window_position) then left_window = window end else left_window = window end end end return left_window end local function find_right_neighbor(windows, current_window) local right_window = nil for _, window in ipairs(windows) do local window_position = vim.api.nvim_win_get_position(window) local current_position = vim.api.nvim_win_get_position(current_window) if Util.is_right_of(current_position, window_position) then right_window = window break end end return right_window end ------------------------------------------------------------------------------- -- Public Interface ------------------------------------------------------------------------------- --- Toggles the board function Board.toggle(directory) if Board.saved_state then Board.close() else Board.open(directory) end end --- Opens the board function Board.open(directory) if not directory or directory == '' then directory = vim.fn.getcwd() end local directories = get_directories(directory) if #directories > 0 then save_state() close_all_buffers() vim.api.nvim_command('enew') for i, directory in ipairs(directories) do if i > 1 then vim.api.nvim_command('vsplit') end vim.api.nvim_command('edit ' .. directory) vim.api.nvim_buf_set_var(0, 'is_oleoboard_column', true) end end end --- Closes the board function Board.close() for _, window in ipairs(vim.api.nvim_list_wins()) do local buffer = vim.api.nvim_win_get_buf(window) local ok, is_oleoboard_column = pcall(vim.api.nvim_buf_get_var, buffer, 'is_oleoboard_column') if ok and is_oleoboard_column then vim.api.nvim_buf_delete(buffer, {force = true}) end end restore_state() end --- Moves the entry under the cursor to the right function Board.move_entry_right() local current_window = vim.api.nvim_get_current_win() local windows = vim.api.nvim_tabpage_list_wins(0) local right_window = nil right_window = find_right_neighbor(windows, current_window) if right_window then local buffer = vim.api.nvim_win_get_buf(right_window) local ok, is_oleoboard_column = pcall(vim.api.nvim_buf_get_var, buffer, 'is_oleoboard_column') if ok and is_oleoboard_column then vim.cmd('normal! dd') vim.api.nvim_set_current_win(right_window) vim.cmd('normal! G') vim.cmd('normal! p') end end end --- Moves the entry under the cursor to the left function Board.move_entry_left() local current_window = vim.api.nvim_get_current_win() local windows = vim.api.nvim_tabpage_list_wins(0) local left_window = nil left_window = find_left_neighbor(windows, current_window) if left_window then local buffer = vim.api.nvim_win_get_buf(left_window) local ok, is_oleoboard_column = pcall(vim.api.nvim_buf_get_var, buffer, 'is_oleoboard_column') if ok and is_oleoboard_column then vim.cmd('normal! dd') vim.api.nvim_set_current_win(left_window) vim.cmd('normal! G') vim.cmd('normal! p') end end end --- Moves the active column to the right function Board.move_column_right() local current_window = vim.api.nvim_get_current_win() local windows = vim.api.nvim_tabpage_list_wins(0) local right_window = find_right_neighbor(windows, current_window) if right_window then local right_buffer = vim.api.nvim_win_get_buf(right_window) local current_buffer = vim.api.nvim_win_get_buf(current_window) local right_ok, right_is_oleoboard_column = pcall(vim.api.nvim_buf_get_var, right_buffer, 'is_oleoboard_column') local current_ok, current_is_oleoboard_column = pcall(vim.api.nvim_buf_get_var, current_buffer, 'is_oleoboard_column') if right_ok and right_is_oleoboard_column and current_ok and current_is_oleoboard_column then vim.api.nvim_win_set_buf(right_window, current_buffer) vim.api.nvim_win_set_buf(current_window, right_buffer) vim.api.nvim_set_current_win(right_window) end end end --- Moves the active column to the left function Board.move_column_left() local current_window = vim.api.nvim_get_current_win() local windows = vim.api.nvim_tabpage_list_wins(0) local left_window = find_left_neighbor(windows, current_window) if left_window then local left_buffer = vim.api.nvim_win_get_buf(left_window) local current_buffer = vim.api.nvim_win_get_buf(current_window) local left_ok, left_is_oleoboard_column = pcall(vim.api.nvim_buf_get_var, left_buffer, 'is_oleoboard_column') local current_ok, current_is_oleoboard_column = pcall(vim.api.nvim_buf_get_var, current_buffer, 'is_oleoboard_column') if left_ok and left_is_oleoboard_column and current_ok and current_is_oleoboard_column then vim.api.nvim_win_set_buf(left_window, current_buffer) vim.api.nvim_win_set_buf(current_window, left_buffer) vim.api.nvim_set_current_win(left_window) end end end return Board