|
| 1 | +local logger = require("ledger.logger").get() |
| 2 | + |
| 3 | +local M = {} |
| 4 | + |
| 5 | +--- @enum HlGroups |
| 6 | +local HL_GROUPS = { |
| 7 | + LedgerReport = "LedgerReport", |
| 8 | +} |
| 9 | + |
| 10 | +--- @class ledger.TuiLayout |
| 11 | +--- @field previous_number boolean |
| 12 | +--- @field previous_relative boolean |
| 13 | +--- @field previous_signcolumn "no" | "yes" |
| 14 | +--- @field output_buf integer |
| 15 | +--- @field filters_buf integer |
| 16 | +--- @field reports_buf integer |
| 17 | +--- @field augroup integer |
| 18 | +local LedgerTuiLayout = {} |
| 19 | +LedgerTuiLayout.__index = LedgerTuiLayout |
| 20 | + |
| 21 | +function LedgerTuiLayout:set_window_options() |
| 22 | + if not self.previous_number then |
| 23 | + --- @type boolean |
| 24 | + self.previous_number = vim.api.nvim_get_option_value("number", {}) |
| 25 | + --- @type boolean |
| 26 | + self.previous_relative = vim.api.nvim_get_option_value("relativenumber", {}) |
| 27 | + --- @type "no" | "yes" |
| 28 | + self.previous_signcolumn = vim.api.nvim_get_option_value("signcolumn", {}) |
| 29 | + end |
| 30 | + vim.api.nvim_set_option_value("number", false, {}) |
| 31 | + vim.api.nvim_set_option_value("relativenumber", false, {}) |
| 32 | + vim.api.nvim_set_option_value("signcolumn", "no", {}) |
| 33 | +end |
| 34 | + |
| 35 | +function LedgerTuiLayout:restore_window_options() |
| 36 | + vim.api.nvim_set_option_value("number", self.previous_number, {}) |
| 37 | + vim.api.nvim_set_option_value("relativenumber", self.previous_relative, {}) |
| 38 | + vim.api.nvim_set_option_value("signcolumn", self.previous_signcolumn, {}) |
| 39 | +end |
| 40 | + |
| 41 | +local function set_buffer_options() |
| 42 | + vim.bo.buftype = "nofile" |
| 43 | + vim.bo.bufhidden = "wipe" |
| 44 | + vim.bo.swapfile = false |
| 45 | +end |
| 46 | + |
| 47 | +--- sets up all the windows for the tui layout, which consists |
| 48 | +--- of three buffers, one for the reports, one for the output |
| 49 | +--- and one for working with filters, which is supposed to look |
| 50 | +--- something like this: |
| 51 | +--- |
| 52 | +--- ┌───┬───────────┬───┐ |
| 53 | +--- │ │ │ │ |
| 54 | +--- │ R │ O │ F │ |
| 55 | +--- │ │ │ │ |
| 56 | +--- └───┴───────────┴───┘ |
| 57 | +--- R: Reports pane |
| 58 | +--- O: Outputs pane |
| 59 | +--- F: Filters pane |
| 60 | +function LedgerTuiLayout:setup_windows() |
| 61 | + vim.cmd("vsplit") |
| 62 | + local output_buf = vim.api.nvim_create_buf(false, true) |
| 63 | + vim.api.nvim_set_current_buf(output_buf) |
| 64 | + local output_width = math.ceil(vim.o.columns * 0.75) |
| 65 | + |
| 66 | + set_buffer_options() |
| 67 | + self:set_window_options() |
| 68 | + vim.cmd("vertical resize " .. output_width) |
| 69 | + vim.cmd("vsplit") |
| 70 | + |
| 71 | + local filters_buf = vim.api.nvim_create_buf(false, true) |
| 72 | + vim.api.nvim_set_current_buf(filters_buf) |
| 73 | + set_buffer_options() |
| 74 | + self:set_window_options() |
| 75 | + local filter_width = math.ceil(vim.o.columns * 0.15) |
| 76 | + |
| 77 | + vim.cmd("vertical resize " .. filter_width) |
| 78 | + vim.cmd("wincmd h") |
| 79 | + vim.cmd("wincmd h") |
| 80 | + |
| 81 | + local reports_buf = vim.api.nvim_create_buf(false, true) |
| 82 | + vim.api.nvim_set_current_buf(reports_buf) |
| 83 | + set_buffer_options() |
| 84 | + self:set_window_options() |
| 85 | + |
| 86 | + -- we defer locking the buffers to make sure their contents |
| 87 | + -- are completely written before doing so |
| 88 | + vim.defer_fn(function() |
| 89 | + vim.api.nvim_set_option_value("modifiable", false, { buf = output_buf }) |
| 90 | + vim.api.nvim_set_option_value("modifiable", false, { buf = filters_buf }) |
| 91 | + vim.api.nvim_set_option_value("modifiable", false, { buf = reports_buf }) |
| 92 | + end, 100) |
| 93 | + |
| 94 | + logger:info("initialized tui pane buffers") |
| 95 | + self.output_buf = output_buf |
| 96 | + self.filters_buf = filters_buf |
| 97 | + self.reports_buf = reports_buf |
| 98 | +end |
| 99 | + |
| 100 | +--- overrides the entire content of a given buffer with the provided |
| 101 | +--- content |
| 102 | +--- |
| 103 | +--- @param buffer integer |
| 104 | +--- @param content string[] |
| 105 | +function LedgerTuiLayout.set_buffer_content(buffer, content) |
| 106 | + vim.api.nvim_set_option_value("modifiable", true, { buf = buffer }) |
| 107 | + vim.api.nvim_buf_set_lines(buffer, 0, -1, false, content) |
| 108 | + vim.api.nvim_set_option_value("modifiable", false, { buf = buffer }) |
| 109 | +end |
| 110 | + |
| 111 | +local function setup_highlight_groups() |
| 112 | + vim.api.nvim_set_hl(0, HL_GROUPS.LedgerReport, { |
| 113 | + fg = "#F3F4F6", |
| 114 | + bg = "#8F2BF5", |
| 115 | + bold = true, |
| 116 | + }) |
| 117 | +end |
| 118 | + |
| 119 | +function LedgerTuiLayout:setup_aucmds() |
| 120 | + vim.api.nvim_create_autocmd("CursorMoved", { |
| 121 | + buffer = self.reports_buf, |
| 122 | + group = self.augroup, |
| 123 | + callback = function() |
| 124 | + local reports = require("ledger.tui.reports").get() |
| 125 | + reports:maybe_run_command() |
| 126 | + end, |
| 127 | + }) |
| 128 | +end |
| 129 | + |
| 130 | +--- @return ledger.TuiLayout |
| 131 | +function M.setup() |
| 132 | + local self = setmetatable({ |
| 133 | + augroup = vim.api.nvim_create_augroup("LedgerTui", {}), |
| 134 | + }, LedgerTuiLayout) |
| 135 | + setup_highlight_groups() |
| 136 | + return self |
| 137 | +end |
| 138 | + |
| 139 | +return M |
0 commit comments