irongit

A Neovim plugin enabling you to solve LeetCode problems.

feat: floating console

kawreauthored
parent 302c153commit 3f9f8b06761a71d610c9308fee713bd57bff20bbBrowse files

10 files changed, +234 -20

+11-2lua/leetcode-ui/layout.lua
@@ -1,4 +1,5 @@
11 local log = require("leetcode.logger")
2+local Line = require("nui.line")
23
34 ---@class lc-ui.Layout
45 ---@field contents lc-ui.Component[]
@@ -39,10 +40,18 @@ end
3940 ---@param fn function
4041 function layout:set_on_press(line, fn) self.on_presses[line] = fn end
4142
42----@param config lc-ui.Layout
43+---@param content lc-ui.Component
44+function layout:append(content)
45+ table.insert(self.contents, content)
46+ return self
47+end
48+
49+---@param config? lc-ui.Layout
4350 function layout:init(config)
51+ config = config or {}
52+
4453 local obj = setmetatable({
45- contents = config.contents,
54+ contents = config.contents or {},
4655 opts = config.opts or {},
4756 line_idx = 1,
4857 on_presses = {},
+6-0lua/leetcode/api/command/init.lua
@@ -3,6 +3,7 @@ local log = require("leetcode.logger")
33 local config = require("leetcode.config")
44 local question = require("leetcode.ui.components.question")
55 local Runner = require("leetcode.runner")
6+local Console = require("leetcode.ui.components.console")
67
78 local ui = require("leetcode.ui")
89 -- local dashboard = require("leetcode.ui.dashboard")
@@ -81,4 +82,9 @@ function cmd.run()
8182 runner:run()
8283 end
8384
85+function cmd.console()
86+ local console = Console:init()
87+ console:mount()
88+end
89+
8490 return cmd
+12-0lua/leetcode/config/template.lua
@@ -21,6 +21,18 @@ local M = {
2121
2222 ---@type boolean
2323 logging = true,
24+
25+ console = {
26+ size = {
27+ width = "75%", ---@type string | integer
28+ height = "75%", ---@type string | integer
29+ },
30+ dir = "col", ---@type "col" | "row"
31+ },
32+
33+ description = {
34+ width = "50%", ---@type string | integer
35+ },
2436 }
2537
2638 return M
+1-3lua/leetcode/logger/spinner.lua
@@ -49,9 +49,7 @@ end
4949
5050 function spinner:done()
5151 self:stop()
52- self:set_noti(nil, {
53- icon = "",
54- })
52+ self:set_noti(nil, { icon = "" })
5553 end
5654
5755 function spinner:stop() self.spinner = nil end
+68-2lua/leetcode/ui/components/console/init.lua
@@ -1,9 +1,75 @@
1+local Popup = require("nui.popup")
2+local Layout = require("leetcode-ui.layout")
3+local config = require("leetcode.config")
4+local Testcase = require("leetcode.ui.components.console.testcase")
5+local Text = require("leetcode-ui.component.text")
6+local Result = require("leetcode.ui.components.console.result")
7+
8+local NuiLine = require("nui.line")
9+local NuiText = require("nui.text")
10+local NuiLayout = require("nui.layout")
11+
112 ---@class lc.Console
13+---@field parent lc.Question
14+---@field layout NuiLayout
215 local console = {}
316 console.__index = console
417
5-function console:init()
6- local obj = setmetatable({}, self)
18+function console:mount()
19+ -- self.popup:mount()
20+ -- fsadf/
21+ -- self.testcase.layout:draw(self.popup)
22+ -- self.layout:append(self.testcase)
23+ self.layout:mount()
24+
25+ return self
26+end
27+
28+function console:open()
29+ -- fasdf/
30+end
31+
32+function console:hide()
33+ -- fasdf/
34+end
35+
36+---@private
37+function console.navbar()
38+ local testcase_text = NuiText(" (t) testcase ", "MasonHeader")
39+ local result_text = NuiText(" (r) result ", "MasonHeader")
40+ local run_text = NuiText(" (R) run ", "MasonHeader")
41+ local submit_text = NuiText(" (S) submit ", "MasonHeader")
42+
43+ local nui_line = NuiLine({
44+ -- testcase_text,
45+ -- NuiText("\t"),
46+ -- result_text,
47+ -- NuiText("\t"),
48+ })
49+
50+ return Text:init({
51+ lines = { nui_line },
52+ opts = { position = "center" },
53+ })
54+end
55+
56+---@param parent lc.Question
57+function console:init(parent)
58+ local obj = setmetatable({
59+ parent = parent,
60+ }, self)
61+
62+ obj.layout = NuiLayout(
63+ {
64+ relative = "editor",
65+ position = "50%",
66+ size = config.user.console.size,
67+ },
68+ NuiLayout.Box({
69+ NuiLayout.Box(Testcase:init(obj).popup, { size = "50%" }),
70+ NuiLayout.Box(Result:init(obj).popup, { size = "50%" }),
71+ }, { dir = config.user.console.dir })
72+ )
773
874 return obj
975 end
+55-0lua/leetcode/ui/components/console/result.lua
@@ -0,0 +1,55 @@
1+local Layout = require("leetcode-ui.layout")
2+local Text = require("leetcode-ui.component.text")
3+local NuiLine = require("nui.line")
4+local NuiPopup = require("nui.popup")
5+
6+---@class lc.Testcase
7+---@field popup NuiPopup
8+local result = {}
9+result.__index = result
10+
11+---@param parent lc.Console
12+function result:init(parent)
13+ local t = {}
14+ for _, case in ipairs(parent.parent.testcases) do
15+ for s in vim.gsplit(case, "\n", { trimempty = true }) do
16+ table.insert(t, s)
17+ end
18+ end
19+
20+ local popup = NuiPopup({
21+ border = {
22+ padding = {
23+ top = 1,
24+ bottom = 1,
25+ left = 3,
26+ right = 3,
27+ },
28+ style = "rounded",
29+ text = {
30+ top = " (r) Result ",
31+ top_align = "center",
32+ bottom = " (R) Run | (S) Submit ",
33+ bottom_align = "center",
34+ },
35+ },
36+ buf_options = {
37+ modifiable = false,
38+ readonly = true,
39+ },
40+ win_options = {
41+ -- winhighlight = "Normal:Normal,FloatBorder:FloatBorder",
42+ winhighlight = "Normal:NormalSB,FloatBorder:FloatBorder",
43+ },
44+ })
45+
46+ vim.api.nvim_buf_set_lines(popup.bufnr, 0, -1, false, t)
47+
48+ local obj = setmetatable({
49+ popup = popup,
50+ }, self)
51+
52+ return obj
53+end
54+
55+return result
+60-0lua/leetcode/ui/components/console/testcase.lua
@@ -0,0 +1,60 @@
1+local Layout = require("leetcode-ui.layout")
2+local Text = require("leetcode-ui.component.text")
3+local NuiLine = require("nui.line")
4+local NuiPopup = require("nui.popup")
5+
6+---@class lc.Testcase
7+---@field popup NuiPopup
8+local testcase = {}
9+testcase.__index = testcase
10+
11+---@param parent lc.Console
12+function testcase:init(parent)
13+ local t = {}
14+ for _, case in ipairs(parent.parent.testcases) do
15+ for s in vim.gsplit(case, "\n", { trimempty = true }) do
16+ table.insert(t, s)
17+ end
18+ end
19+
20+ local popup = NuiPopup({
21+ -- position = "50%",
22+ -- size = config.user.console.size,
23+ -- enter = true,
24+ -- focusable = true,
25+ -- zindex = 50,
26+ -- relative = "editor",
27+ border = {
28+ padding = {
29+ top = 1,
30+ bottom = 1,
31+ left = 3,
32+ right = 3,
33+ },
34+ style = "rounded",
35+ text = {
36+ top = " Console | (q) hide ",
37+ top_align = "center",
38+ bottom = " (t) Testcase ",
39+ bottom_align = "center",
40+ },
41+ },
42+ buf_options = {
43+ modifiable = true,
44+ readonly = false,
45+ },
46+ win_options = {
47+ winhighlight = "Normal:NormalSB,FloatBorder:FloatBorder",
48+ },
49+ })
50+
51+ vim.api.nvim_buf_set_lines(popup.bufnr, 0, -1, false, t)
52+
53+ local obj = setmetatable({
54+ popup = popup,
55+ }, self)
56+
57+ return obj
58+end
59+
60+return testcase
+8-2lua/leetcode/ui/components/description.lua
@@ -7,6 +7,7 @@ local Text = require("leetcode-ui.component.text")
77 local padding = require("leetcode-ui.component.padding")
88 local NuiText = require("nui.text")
99 local NuiLine = require("nui.line")
10+local config = require("leetcode.config")
1011
1112 ---@class lc.Description
1213 ---@field split NuiSplit
@@ -23,6 +24,8 @@ function description:mount()
2324 self:populate()
2425 self.split:mount()
2526 self:draw()
27+
28+ return self
2629 end
2730
2831 function description:draw() self.layout:draw(self.split) end
@@ -81,24 +84,27 @@ function description:init(parent)
8184 local split = Split({
8285 relative = "win",
8386 position = "left",
84- size = "50%",
87+ size = config.user.description.width,
8588 buf_options = {
8689 modifiable = true,
8790 readonly = false,
8891 filetype = "leetcode.nvim",
8992 swapfile = false,
9093 buftype = "nofile",
91- buflisted = false,
94+ buflisted = true,
9295 },
9396 win_options = {
9497 foldcolumn = "1",
9598 wrap = true,
9699 number = false,
97100 signcolumn = "no",
101+ -- winhighlight = "Normal:Normal,NormalNC:NormalNC",
102+ winhighlight = "Normal:NormalFloat,FloatBorder:FloatBorder",
98103 },
99104 enter = true,
100105 focusable = true,
101106 })
107+ vim.api.nvim_buf_set_name(split.bufnr, "Description")
102108
103109 local obj = setmetatable({
104110 split = split,
+13-4lua/leetcode/ui/components/question.lua
@@ -2,8 +2,9 @@ local Split = require("nui.split")
22 local path = require("plenary.path")
33 local config = require("leetcode.config")
44 local log = require("leetcode.logger")
5-local description = require("leetcode.ui.components.description")
5+local Description = require("leetcode.ui.components.description")
66 local gql = require("leetcode.graphql")
7+local Console = require("leetcode.ui.components.console")
78
89 ---@class lc.Question
910 ---@field file Path
@@ -11,6 +12,7 @@ local gql = require("leetcode.graphql")
1112 ---@field description lc.Description
1213 ---@field testcases string[]
1314 ---@field bufnr bufnr
15+---@field console lc.Console
1416 local question = {}
1517 question.__index = question
1618
@@ -46,12 +48,19 @@ function question:mount()
4648 vim.cmd("edit " .. self.file:absolute())
4749
4850 self.bufnr = vim.api.nvim_get_current_buf()
51+ curr_question = self.bufnr
4952 problems[self.bufnr] = self
5053
51- self.description = description:init(self)
52- self.description:mount()
54+ self.description = Description:init(self):mount()
55+ self.console = Console:init(self):mount()
56+end
5357
54- curr_question = self.bufnr
58+function question:run()
59+ -- fasdf//
60+end
61+
62+function question:submit()
63+ -- fasdf/
5564 end
5665
5766 ---@param problem lc.Problem
+0-7lua/leetcode/ui/init.lua
@@ -100,13 +100,6 @@ function Ui.testcase()
100100 },
101101 })
102102
103- local testcases = problems[curr_question].q.testcase_list
104- for i, t in ipairs(testcases) do
105- testcases[i] = t:gsub("\n", " ")
106- end
107-
108- vim.api.nvim_buf_set_lines(popup.bufnr, 0, -1, false, testcases)
109-
110103 popup:mount()
111104 end
112105