Skip to content

Commit 536468c

Browse files
committed
feat: initial display of commands output
1 parent 690bf19 commit 536468c

File tree

7 files changed

+304
-73
lines changed

7 files changed

+304
-73
lines changed

lua/ledger/commands.lua

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ local M = {}
44

55
--- @class LedgerCommands
66
--- @field augroup integer
7-
--- @field tui_augroup integer
87
--- @field output_augroup integer
98
local LedgerCommands = {}
109
LedgerCommands.__index = LedgerCommands
@@ -14,7 +13,6 @@ local instance
1413

1514
function LedgerCommands:create_augroups()
1615
self.augroup = vim.api.nvim_create_augroup("Ledger", {})
17-
self.tui_augroup = vim.api.nvim_create_augroup("LedgerTui", {})
1816
self.output_augroup = vim.api.nvim_create_augroup("LedgerOutput", {})
1917
end
2018

@@ -113,10 +111,6 @@ function LedgerCommands:setup_autocommands()
113111
})
114112
end
115113

116-
function LedgerCommands:setup_tui_autocommands()
117-
self.tui_augroup = tui
118-
end
119-
120114
function M.setup()
121115
if not instance then
122116
instance = setmetatable({}, LedgerCommands)

lua/ledger/config.lua

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@ local M = {}
22

33
--- @class ledger.Tui
44
--- @field enabled boolean
5+
--- @field sections table<string, ledger.TuiSection>
6+
7+
--- @class ledger.TuiFilter
8+
--- @field flag string
9+
--- @field input boolean
10+
11+
--- @class ledger.TuiSection
12+
--- @field command string
13+
--- @field filters table<string, ledger.TuiFilter[]>
514

615
--- @class ledger.SnippetKeymaps
716
--- @field new_account string[]
@@ -53,6 +62,7 @@ local M = {}
5362
--- @field strict boolean
5463

5564
--- @class ledger.Config
65+
--- @field plugin_name string
5666
--- @field extensions string[]
5767
--- @field default_ignored_paths string[]
5868
--- @field completion ledger.Completion
@@ -125,6 +135,7 @@ end
125135
local function get_default_config()
126136
--- @type ledger.Config
127137
local default_config = {
138+
plugin_name = "ledger.nvim",
128139
extensions = {
129140
"ledger",
130141
"hledger",
@@ -160,6 +171,26 @@ local function get_default_config()
160171
},
161172
tui = {
162173
enabled = true,
174+
sections = {
175+
["Show Balance"] = {
176+
command = "ledger --strict -f main.ledger bal",
177+
filters = {
178+
["Period"] = {
179+
flag = "-p",
180+
input = true,
181+
},
182+
},
183+
},
184+
["Show Budget"] = {
185+
command = "ledger --strict -f main.ledger budget",
186+
filters = {
187+
["Period"] = {
188+
flag = "-p",
189+
input = true,
190+
},
191+
},
192+
},
193+
},
163194
},
164195
}
165196

lua/ledger/parser.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
local queries = require("ledger.queries")
22
local ts_utils = require("nvim-treesitter.ts_utils")
33

4+
--- @alias TSQueryIter fun(end_line: integer|nil):integer, TSNode, vim.treesitter.query.TSMetadata, TSQueryMatch
5+
46
--- @class ledger.parser
57
--- @field get_parser fun(source: string): TSSource
68
--- @field find_current_scope fun(): Scope
7-
--- @field query_iter fun(query: vim.treesitter.Query, node: TSNode, source: string): fun(end_line: integer|nil):integer, TSNode, vim.treesitter.query.TSMetadata, TSQueryMatch
9+
--- @field query_iter fun(query: vim.treesitter.Query, node: TSNode, source: string): TSQueryIter
810
--- @field get_account_names_from_source fun(node: TSNode, source: string, filename: string, ctx: ledger.Context)
911
--- @field get_commodities_from_source fun(node: TSNode, source: string, filename: string, ctx: ledger.Context)
1012
local M = {}

lua/ledger/tui/init.lua

Lines changed: 24 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,34 @@
1+
local layout = require("ledger.tui.layout")
2+
local logger = require("ledger.logger").get()
3+
local reports = require("ledger.tui.reports")
4+
15
local M = {}
26

3-
--- @class LedgerTui
7+
--- @class ledger.Tui
8+
--- @field layout ledger.TuiLayout
9+
--- @field reports ledger.TuiReports
10+
--- @field running boolean
411
local LedgerTui = {}
512
LedgerTui.__index = LedgerTui
613

7-
--- @class LedgerTui
14+
--- @class ledger.Tui
815
local instance
916

10-
function LedgerTui:set_autocmds() end
11-
12-
--- @param buffer integer
13-
function LedgerTui:set_buffer_options(buffer)
14-
vim.bo.buftype = "nofile"
15-
vim.bo.bufhidden = "wipe"
16-
vim.bo.swapfile = false
17-
vim.api.nvim_set_option_value("number", false, {})
18-
vim.api.nvim_set_option_value("relativenumber", false, {})
19-
vim.api.nvim_set_option_value("signcolumn", "no", {})
20-
end
21-
2217
function LedgerTui:setup()
23-
print("initializing")
24-
-- Create a vertical split (left: information buffer, right: output buffer)
25-
vim.cmd("vsplit")
26-
27-
-- Create an empty buffer for the output in the right window
28-
local output_buf = vim.api.nvim_create_buf(false, true)
29-
vim.api.nvim_set_current_buf(output_buf)
30-
31-
-- Set buffer options for output buffer
32-
self:set_buffer_options(output_buf)
33-
local output_width = math.ceil(vim.o.columns * 0.75)
34-
vim.cmd("vertical resize " .. output_width)
35-
36-
-- Create a horizontal split below the output buffer (filters buffer)
37-
vim.cmd("split")
38-
39-
-- Create an empty buffer for the filters in the bottom window
40-
local filters_buf = vim.api.nvim_create_buf(false, true)
41-
vim.api.nvim_set_current_buf(filters_buf)
42-
43-
-- Set buffer options for filters buffer
44-
self:set_buffer_options(filters_buf)
45-
local filter_height = math.ceil(vim.o.lines * 0.15)
46-
vim.cmd("horizontal resize " .. filter_height)
47-
48-
-- Move back to the original left split (information buffer)
49-
vim.cmd("wincmd h")
50-
51-
-- Create an empty buffer for the information in the left window
52-
local info_buf = vim.api.nvim_create_buf(false, true)
53-
vim.api.nvim_set_current_buf(info_buf)
54-
55-
-- Set buffer options for information buffer
56-
self:set_buffer_options(info_buf)
18+
if self.running then
19+
print("ledger.nvim already has the tui open")
20+
return
21+
end
5722

58-
-- Optionally set keymaps to close each buffer/window
59-
vim.api.nvim_buf_set_keymap(output_buf, "n", "q", ":q<CR>", { noremap = true, silent = true })
60-
vim.api.nvim_buf_set_keymap(filters_buf, "n", "q", ":q<CR>", { noremap = true, silent = true })
61-
vim.api.nvim_buf_set_keymap(info_buf, "n", "q", ":q<CR>", { noremap = true, silent = true })
23+
logger:info("initializing tui view")
24+
self.running = true
25+
self.layout:setup_windows()
26+
self.layout:setup_aucmds()
27+
self.reports:populate_reports()
6228
end
6329

6430
function LedgerTui:shutdown()
31+
self.layout:restore_window_options()
6532
print("shutting down")
6633
end
6734

@@ -85,7 +52,11 @@ end
8552

8653
function M.setup()
8754
if not instance then
88-
instance = setmetatable({}, LedgerTui)
55+
local layout_instance = layout.setup()
56+
instance = setmetatable({
57+
layout = layout_instance,
58+
reports = reports.setup(layout_instance),
59+
}, LedgerTui)
8960
end
9061
return instance
9162
end

lua/ledger/tui/layout.lua

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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

Comments
 (0)