diff options
| author | Luc Sinet <[email protected]> | 2021-08-16 15:07:46 +0200 | 
|---|---|---|
| committer | GitHub <[email protected]> | 2021-08-16 16:07:46 +0300 | 
| commit | 9b36872d886c632ca93479321cde1e0f00629e3c (patch) | |
| tree | 25d1c27892f14d1029e9d5d97610878f60b73416 /lua/interface | |
| parent | 944dd4893508161d5477d1313d9e0c4368968653 (diff) | |
[Feature] Encapsulate interface logic (#1320)
* Provide a utility function for aligning text
* Replace lvim banner with one using only ASCII chars
* Use strings.format instead of .. operator
* Center text in the popup based on its dimentions
* Minor improvements
* Provide a popup factory function
* Add function documentation
* Improve text alignment
* Print marker only if provider list is not empty
* Format client capabilities as list
* Pretty format lsp client capabilities
* Add a metatable to popup.lua
* Improve rendering when no lsp is available
* Take cmdheight into acount when computing popup size and pos
Co-authored-by: kylo252 <[email protected]>
Diffstat (limited to 'lua/interface')
| -rw-r--r-- | lua/interface/popup.lua | 62 | ||||
| -rw-r--r-- | lua/interface/text.lua | 79 | 
2 files changed, 141 insertions, 0 deletions
| diff --git a/lua/interface/popup.lua b/lua/interface/popup.lua new file mode 100644 index 00000000..b628125c --- /dev/null +++ b/lua/interface/popup.lua @@ -0,0 +1,62 @@ +local Popup = {} + +--- Create a new floating window +-- @param config The configuration passed to vim.api.nvim_open_win +-- @param win_opts The options registered with vim.api.nvim_win_set_option +-- @param buf_opts The options registered with vim.api.nvim_buf_set_option +-- @return A new popup +function Popup:new(opts) +  opts = opts or {} +  opts.layout = opts.layout or {} +  opts.win_opts = opts.win_opts or {} +  opts.buf_opts = opts.buf_opts or {} + +  Popup.__index = Popup + +  local editor_layout = { +    height = vim.o.lines - vim.o.cmdheight - 2, -- Add margin for status and buffer line +    width = vim.o.columns, +  } +  local popup_layout = { +    relative = "editor", +    height = math.floor(editor_layout.height * 0.9), +    width = math.floor(editor_layout.width * 0.8), +    style = "minimal", +    border = "rounded", +  } +  popup_layout.row = math.floor((editor_layout.height - popup_layout.height) / 2) +  popup_layout.col = math.floor((editor_layout.width - popup_layout.width) / 2) + +  local obj = { +    buffer = vim.api.nvim_create_buf(false, true), +    layout = vim.tbl_deep_extend("force", popup_layout, opts.layout), +    win_opts = opts.win_opts, +    buf_opts = opts.buf_opts, +  } + +  setmetatable(obj, Popup) + +  return obj +end + +--- Display the popup with the provided content +-- @param content_provider A function accepting the popup's layout and returning the content to display +function Popup:display(content_provider) +  self.win_id = vim.api.nvim_open_win(self.buffer, true, self.layout) +  vim.lsp.util.close_preview_autocmd({ "BufHidden", "BufLeave" }, self.win_id) + +  local lines = content_provider(self.layout) +  vim.api.nvim_buf_set_lines(self.bufnr, 0, -1, false, lines) + +  -- window options +  for key, value in pairs(self.win_opts) do +    vim.api.nvim_win_set_option(self.win_id, key, value) +  end + +  -- buffer options +  for key, value in pairs(self.buf_opts) do +    vim.api.nvim_buf_set_option(self.buffer, key, value) +  end +end + +return Popup diff --git a/lua/interface/text.lua b/lua/interface/text.lua new file mode 100644 index 00000000..f68cc491 --- /dev/null +++ b/lua/interface/text.lua @@ -0,0 +1,79 @@ +local M = {} + +local function max_len_line(lines) +  local max_len = 0 + +  for _, line in ipairs(lines) do +    local line_len = line:len() +    if line_len > max_len then +      max_len = line_len +    end +  end + +  return max_len +end + +--- Center align lines relatively to the parent container +-- @param container The container where lines will be displayed +-- @param lines The text to align +-- @param alignment The alignment value, range: [0-1] +function M.align(container, lines, alignment) +  local max_len = max_len_line(lines) +  local indent_amount = math.ceil(math.max(container.width - max_len, 0) * alignment) +  return M.shift_left(lines, indent_amount) +end + +--- Shift lines by a given amount +-- @params lines The lines the shift +-- @param amount The amount of spaces to add +function M.shift_left(lines, amount) +  local output = {} +  local padding = string.rep(" ", amount) + +  for _, line in ipairs(lines) do +    table.insert(output, padding .. line) +  end + +  return output +end + +--- Pretty format tables +-- @param entries The table to format +-- @param col_count The number of column to span the table on +-- @param col_sep The separator between each colummn, default: " " +function M.format_table(entries, col_count, col_sep) +  col_sep = col_sep or " " + +  local col_rows = math.ceil(vim.tbl_count(entries) / col_count) +  local cols = {} +  local count = 0 + +  for i, entry in ipairs(entries) do +    if ((i - 1) % col_rows) == 0 then +      table.insert(cols, {}) +      count = count + 1 +    end +    table.insert(cols[count], entry) +  end + +  local col_max_len = {} +  for _, col in ipairs(cols) do +    table.insert(col_max_len, max_len_line(col)) +  end + +  local output = {} +  for i, col in ipairs(cols) do +    for j, entry in ipairs(col) do +      if not output[j] then +        output[j] = entry +      else +        local padding = string.rep(" ", col_max_len[i - 1] - cols[i - 1][j]:len()) +        output[j] = output[j] .. padding .. col_sep .. entry +      end +    end +  end + +  return output +end + +return M | 
