local M = {} local ListView = require "guihua.listview" local TextView = require "guihua.textview" local util = require "navigator.util" local log = require"navigator.util".log local trace = require"navigator.util".trace local api = vim.api local top_center = require"guihua.location".top_center local path_sep = require"navigator.util".path_sep() local path_cur = require"navigator.util".path_cur() function M._preview_location(opts) -- location, width, pos_x, pos_y local uri = opts.uri if uri == nil then log("invalid/nil uri ") return end local bufnr = vim.uri_to_bufnr(uri) if not api.nvim_buf_is_loaded(bufnr) then vim.fn.bufload(bufnr) end -- local display_range = opts.location.range -- if range.start == nil then -- print("error invalid range") -- return -- end -- if range.start.line == nil then -- range.start.line = range["end"].line - 1 -- opts.lnum = range["end"].line + 1 -- log(opts) -- end -- if range["end"].line == nil then -- range["end"].line = range.start.line + 1 -- opts.lnum = range.start.line + 1 -- log(opts) -- end -- TODO: preview height -- local contents = api.nvim_buf_get_lines(bufnr, range.start.line, range["end"].line, false) -- local syntax = api.nvim_buf_get_option(bufnr, "ft") if syntax == nil or #syntax < 1 then syntax = "c" end -- trace(syntax, contents) local win_opts = { syntax = syntax, width = opts.width, height = display_range['end'].line - display_range.start.line + 1, preview_height = opts.height or opts.preview_height, pos_x = opts.offset_x, pos_y = opts.offset_y, range = opts.range, display_range = display_range, uri = uri, allow_edit = opts.enable_edit } if _NgConfigValues.external then win_opts.external = true win_opts.relative = nil end -- win_opts.items = contents win_opts.hl_line = opts.lnum - display_range.start.line if win_opts.hl_line < 0 then win_opts.hl_line = 1 end trace(opts.lnum, opts.range.start.line, win_opts.hl_line) log(win_opts) local w = TextView:new({ loc = "offset_center", rect = { height = win_opts.height, -- opts.preview_heigh or 12, -- TODO 12 width = win_opts.width, pos_x = win_opts.pos_x, pos_y = win_opts.pos_y }, list_view_height = win_opts.height, -- data = display_data, relative = win_opts.relative, -- data = opts.items, -- either items or uri uri = win_opts.uri, syntax = win_opts.syntax, enter = win_opts.enter or false, range = win_opts.range, border = opts.border, display_range = win_opts.display_range, hl_line = win_opts.hl_line, allow_edit = win_opts.allow_edit, external = win_opts.external }) return w end function M.preview_uri(opts) -- uri, width, line, col, offset_x, offset_y -- local handle = vim.loop.new_async(vim.schedule_wrap(function() local line_beg = opts.lnum - 1 if line_beg >= _NgConfigValues.preview_lines_before then line_beg = line_beg - _NgConfigValues.preview_lines_before elseif line_beg >= 2 then line_beg = line_beg - 2 end local loc = {uri = opts.uri, range = {start = {line = line_beg}}} -- TODO: preview height loc.range["end"] = {line = opts.lnum + opts.preview_height} opts.location = loc trace("uri", opts.uri, opts.lnum, opts.location.range.start.line, opts.location.range['end'].line) return M._preview_location(opts) -- handle:close() -- end)) -- handle:send() end function M.new_list_view(opts) local config = require("navigator").config_values() local items = opts.items local data = {} local wwidth = api.nvim_get_option("columns") local loc = "top_center" local mwidth = _NgConfigValues.width local width = math.floor(wwidth * mwidth) if config.width ~= nil and config.width > 0.3 and config.width < 0.99 then width = math.floor(wwidth * config.width) end width = math.min(120, width, opts.width or 120) local wheight = math.floor( 1 + api.nvim_get_option("lines") * (_NgConfigValues.height + _NgConfigValues.preview_height)) local pheight = math.max(_NgConfigValues.preview_lines, math.floor(api.nvim_get_option("lines") * _NgConfigValues.preview_height)) local prompt = opts.prompt or false if opts.rawdata then data = items else trace(items) data = require"navigator.render".prepare_for_render(items, opts) end local border = _NgConfigValues.border or 'shadow' if not data or vim.tbl_isempty(data) then return end -- replace -- TODO: 10 vimrc opt if #data > 10 and opts.prompt == nil then loc = "top_center" prompt = true end local lheight = math.min(#data, math.floor(wheight * _NgConfigValues.height)) local r, _ = top_center(lheight, width) local offset_y = r + lheight -- style shadow took 1 lines if border ~= 'none' then if border == 'shadow' then offset_y = offset_y + 1 else offset_y = offset_y + 1 -- single? end end -- if border is not set, this should be r+lheigh if prompt then offset_y = offset_y + 1 -- need to check this out end local idx = require"guihua.util".fzy_idx local transparency = _NgConfigValues.transparency if transparency == 100 then transparency = nil end local ext = _NgConfigValues.external if ext then opts.relative = nil end return ListView:new({ loc = loc, prompt = prompt, relative = opts.relative, style = opts.style, api = opts.api, total = opts.total, rect = {height = lheight, width = width, pos_x = 0, pos_y = 0}, -- preview_height = pheight, ft = opts.ft or 'guihua', -- data = display_data, data = data, border = border, external = ext, on_confirm = opts.on_confirm or function(item, split_opts) log(split_opts) split_opts = split_opts or {} if item.filename ~= nil then log("openfile ", item.filename, item.lnum, item.col) util.open_file_at(item.filename, item.lnum, item.col, split_opts.split) end end, transparency = transparency, on_move = opts.on_move or function(item) trace("on move", item) trace("on move", item.text or item, item.uri, item.filename) -- todo fix if item.uri == nil then item.uri = "file:///" .. item.filename end return M.preview_uri({ uri = item.uri, width = width, height = lheight, -- this is to cal offset preview_height = pheight, lnum = item.lnum, col = item.col, range = item.range, offset_x = 0, offset_y = offset_y, border = border, external = ext, enable_edit = opts.enable_preview_edit or false }) end }) end return M -- Doc --[[ -- each item should look like this -- update if API changes { call_by = {