irongit

A Neovim plugin enabling you to solve LeetCode problems.

279 lines8.1 KBLua
1local Cases = require("leetcode-ui.group.cases")
2local Header = require("leetcode-ui.lines.header")
3local utils = require("leetcode.utils")
4local SimilarQuestions = require("leetcode-ui.group.similar-questions")
5
6local Renderer = require("leetcode-ui.renderer")
7local Pre = require("leetcode-ui.group.pre")
8local Input = require("leetcode-ui.group.pre.input")
9local Stdout = require("leetcode-ui.group.pre.stdout")
10local Case = require("leetcode-ui.group.case")
11
12local Line = require("leetcode-ui.line")
13local Lines = require("leetcode-ui.lines")
14
15local config = require("leetcode.config")
16local t = require("leetcode.translator")
17local log = require("leetcode.logger")
18
19---@class lc.ui.Result : lc.ui.Renderer
20---@field parent lc.ui.Console
21---@field group lc.ui.Group
22---@field cases lc.ui.Cases
23---@field case lc.ui.Case
24local ResultLayout = Renderer:extend("LeetResultLayout")
25
26function ResultLayout:handle_accepted(item)
27 self:set_opts({ spacing = 2 })
28
29 local function perc_hi(perc) --
30 if perc >= 50 then
31 return "leetcode_ok"
32 elseif perc >= 10 then
33 return nil
34 elseif perc >= 0 then
35 return "leetcode_error"
36 end
37 end
38
39 local header = Header(item)
40 self:insert(header)
41
42 --------------------------------------------
43 --- Runtime
44 --------------------------------------------
45 local runtime = Lines()
46 local runtime_ms = item.display_runtime or vim.split(item.status_runtime, " ")[1] or "NIL"
47 runtime:append(runtime_ms):append(" ms", "leetcode_alt")
48 runtime:endl()
49
50 runtime:append(
51 ("%s %.2f%% "):format(t("Beats"), item.runtime_percentile),
52 perc_hi(item.runtime_percentile)
53 )
54
55 local lang = utils.get_lang_by_name(item.pretty_lang)
56 local lang_text = { item.pretty_lang, "Structure" }
57 if lang then
58 lang_text = { lang.icon .. " " .. lang.lang, lang.hl or "Structure" }
59 end
60
61 if config.translator then
62 runtime
63 :append("使用 ", "leetcode_normal")
64 :append(unpack(lang_text))
65 :append(" 的用户", "leetcode_normal")
66 else
67 runtime:append("of users with ", "leetcode_normal"):append(unpack(lang_text))
68 end
69
70 local runtime_title = Line():append("󰓅 " .. t("Runtime"))
71 self:insert(Pre(runtime_title, runtime))
72
73 --------------------------------------------
74 --- Memory
75 --------------------------------------------
76 local memory = Lines()
77 item.status_memory = item.status_memory:gsub("(%d+)%s*(%a+)", "%1 %2")
78 local s_mem = vim.split(item.status_memory, " ")
79 memory:append(s_mem[1] .. " "):append(s_mem[2], "leetcode_alt")
80 memory:endl()
81
82 memory:append(
83 ("%s %.2f%% "):format(t("Beats"), item.memory_percentile),
84 perc_hi(item.memory_percentile)
85 )
86 if config.translator then
87 memory
88 :append("使用 ", "leetcode_normal")
89 :append(unpack(lang_text))
90 :append(" 的用户", "leetcode_normal")
91 else
92 memory:append("of users with ", "leetcode_normal"):append(unpack(lang_text))
93 end
94
95 local memory_title = Line():append("󰍛 " .. t("Memory"))
96 self:insert(Pre(memory_title, memory))
97
98 --------------------------------------------
99 --- More challenges
100 --------------------------------------------
101 if not vim.tbl_isempty(self.parent.question.q.similar or {}) then
102 local title_txt = (" %s"):format(t("More challenges"))
103 local more_title = Line():append(title_txt, "leetcode_normal")
104 local similar = SimilarQuestions(self.parent.question.q.similar)
105 self:insert(Pre(more_title, similar))
106 end
107end
108
109---@private
110---
111---@param item lc.runtime
112function ResultLayout:handle_runtime(item) -- status code = 10
113 if item._.submission then
114 return self:handle_accepted(item)
115 end
116
117 local header = Header(item)
118 self:insert(header)
119
120 local cases = Cases(item, self.parent)
121 self:insert(cases)
122end
123
124---@private
125---
126---@param item lc.submission
127function ResultLayout:handle_submission_error(item) -- status code = 11
128 local header = Header(item)
129 self:insert(header)
130
131 self:insert(Case({ ---@diagnostic disable-line
132 input = vim.split(item.input, "\n"),
133 raw_input = item.last_testcase,
134 output = item.code_output,
135 expected = item.expected_output,
136 std_output = item.std_output,
137 }, false, self.parent.question))
138end
139
140---@private
141---
142---@param item lc.limit_exceeded_error
143function ResultLayout:handle_limit_exceeded(item) -- status code = 12,13,14
144 local header = Header(item)
145 self:insert(header)
146
147 if item._.submission then
148 local input = Input(
149 (" %s"):format(t("Last Executed Input")),
150 vim.split(item.last_testcase, "\n"),
151 self.parent.question.q.meta_data.params
152 )
153 self:insert(input)
154
155 local stdout = Stdout(item.std_output or "")
156 self:insert(stdout)
157 elseif item.std_output_list then
158 local stdout = Stdout(item.std_output_list[#item.std_output_list])
159 self:insert(stdout)
160 end
161end
162
163---@private
164---
165---@param item lc.runtime_error
166function ResultLayout:handle_runtime_error(item) -- status code = 15
167 local header = Header(item)
168
169 local lines = Lines()
170 for line in vim.gsplit(item.full_runtime_error, "\n") do
171 lines:append(line, "leetcode_error"):endl()
172 end
173 self:insert(Pre(header, lines))
174
175 if item._.submission then
176 local pre_header = Line()
177 pre_header:append((" %s"):format(t("Last Executed Input")), "leetcode_normal")
178
179 local last_testcase = Line()
180 last_testcase:append(item.last_testcase:gsub("\n", " "), "leetcode_indent")
181
182 local last_exec = Pre(pre_header, last_testcase)
183 self:insert(last_exec)
184
185 local stdout = Stdout(item.std_output or "")
186 self:insert(stdout)
187 elseif item.std_output_list then
188 local stdout = Stdout(item.std_output_list[#item.std_output_list])
189 self:insert(stdout)
190 end
191end
192
193function ResultLayout:handle_internal_error(item) -- status code = 16
194 local header = Header(item)
195 self:insert(header)
196end
197
198---@private
199---
200---@param item lc.compile_error
201function ResultLayout:handle_compile_error(item) -- status code = 20
202 local header = Header(item)
203
204 local lines = Lines()
205 for line in vim.gsplit(item.full_compile_error, "\n") do
206 lines:append(line, "leetcode_error"):endl()
207 end
208
209 local pre = Pre(header, lines)
210 self:insert(pre)
211end
212
213---@param item lc.interpreter_response
214function ResultLayout:handle_res(item)
215 self:clear()
216 self:set_opts({ spacing = 1 })
217
218 local handlers = {
219 -- runtime
220 [10] = function()
221 self:handle_runtime(item --[[@as lc.runtime]])
222 end,
223 [11] = function()
224 self:handle_submission_error(item --[[@as lc.submission]])
225 end,
226
227 -- memory limit
228 [12] = function()
229 self:handle_limit_exceeded(item --[[@as lc.limit_exceeded_error]])
230 end,
231 -- time limit
232 [13] = function()
233 self:handle_limit_exceeded(item --[[@as lc.limit_exceeded_error]])
234 end,
235 -- output limit
236 [14] = function()
237 self:handle_limit_exceeded(item --[[@as lc.limit_exceeded_error]])
238 end,
239
240 -- runtime error
241 [15] = function()
242 self:handle_runtime_error(item --[[@as lc.runtime_error]])
243 end,
244
245 -- internal error
246 [16] = function()
247 self:handle_internal_error(item --[[@as lc.internal_error]])
248 end,
249
250 -- compiler
251 [20] = function()
252 self:handle_compile_error(item --[[@as lc.compile_error]])
253 end,
254
255 -- unknown
256 ["unknown"] = function()
257 log.error("unknown runner status code: " .. item.status_code)
258 end,
259 }
260
261 local handler = handlers[item.status_code]
262 if handler then
263 handler()
264 else
265 handlers["unknown"]()
266 end
267end
268
269---@param parent lc.ui.Console
270function ResultLayout:init(parent)
271 ResultLayout.super.init(self, {}, { spacing = 1 })
272
273 self.parent = parent
274end
275
276---@type fun(parent: lc.ui.Console): lc.ui.Result
277local LeetResultLayout = ResultLayout
278
279return LeetResultLayout