A Neovim plugin enabling you to solve LeetCode problems.
feat: fold imports on `question_enter`
6 files changed, +82 -24
+55-21lua/leetcode-ui/question.lua
| @@ -51,6 +51,39 @@ function Question:create_file() | ||
| 51 | 51 | return self.file:absolute() |
| 52 | 52 | end |
| 53 | 53 | |
| 54 | +---@param new_tabp? boolean | |
| 55 | +---@return boolean was_loaded | |
| 56 | +function Question:create_buffer(new_tabp) | |
| 57 | + local file_name = self:create_file() | |
| 58 | + | |
| 59 | + local buf = vim.fn.bufadd(file_name) | |
| 60 | + assert(buf ~= 0, "Failed to create buffer") | |
| 61 | + | |
| 62 | + self.bufnr = buf | |
| 63 | + if vim.fn.bufloaded(self.bufnr) == 1 then | |
| 64 | + return true | |
| 65 | + else | |
| 66 | + vim.fn.bufload(self.bufnr) | |
| 67 | + end | |
| 68 | + | |
| 69 | + local cmd | |
| 70 | + if new_tabp then | |
| 71 | + cmd = ("$tabe %s"):format(file_name) | |
| 72 | + else | |
| 73 | + cmd = ("e %s"):format(file_name) | |
| 74 | + end | |
| 75 | + | |
| 76 | + local i = self:fold_range() | |
| 77 | + if i then cmd = cmd .. (" | %d,%dfold"):format(1, i) end | |
| 78 | + vim.api.nvim_exec2(cmd, {}) | |
| 79 | + | |
| 80 | + self.winid = vim.api.nvim_get_current_win() | |
| 81 | + | |
| 82 | + utils.exec_hook("question_enter", self) | |
| 83 | + | |
| 84 | + return false | |
| 85 | +end | |
| 86 | + | |
| 54 | 87 | ---@param before boolean |
| 55 | 88 | function Question:inject(before) |
| 56 | 89 | local inject = config.user.injector[self.lang] or {} |
| @@ -113,15 +146,8 @@ end | ||
| 113 | 146 | Question.unmount = vim.schedule_wrap(function(self, pre) self:_unmount(pre) end) |
| 114 | 147 | |
| 115 | 148 | function Question:handle_mount() |
| 116 | - vim.cmd("$tabe " .. self:create_file()) | |
| 117 | - | |
| 118 | - -- https://github.com/kawre/leetcode.nvim/issues/14 | |
| 119 | - if self.lang == "rust" then | |
| 120 | - pcall(function() require("rust-tools.standalone").start_standalone_client() end) | |
| 121 | - end | |
| 149 | + self:create_buffer(true) | |
| 122 | 150 | |
| 123 | - self.bufnr = vim.api.nvim_get_current_buf() | |
| 124 | - self.winid = vim.api.nvim_get_current_win() | |
| 125 | 151 | table.insert(_Lc_questions, self) |
| 126 | 152 | |
| 127 | 153 | vim.api.nvim_create_autocmd("QuitPre", { |
| @@ -133,8 +159,6 @@ function Question:handle_mount() | ||
| 133 | 159 | self.console = Console(self) |
| 134 | 160 | self.info = Info(self) |
| 135 | 161 | |
| 136 | - utils.exec_hook("question_enter", self) | |
| 137 | - | |
| 138 | 162 | return self |
| 139 | 163 | end |
| 140 | 164 | |
| @@ -180,6 +204,18 @@ function Question:range(inclusive) | ||
| 180 | 204 | return start_i, end_i, lines |
| 181 | 205 | end |
| 182 | 206 | |
| 207 | +function Question:fold_range() | |
| 208 | + local start_i, _, lines = self:range(true) | |
| 209 | + if start_i == nil or start_i <= 1 then return end | |
| 210 | + | |
| 211 | + local i = start_i - 1 | |
| 212 | + while lines[i] == "" do | |
| 213 | + i = i - 1 | |
| 214 | + end | |
| 215 | + | |
| 216 | + if 1 < i then return i end | |
| 217 | +end | |
| 218 | + | |
| 183 | 219 | ---@param submit boolean |
| 184 | 220 | ---@return string |
| 185 | 221 | function Question:lines(submit) |
| @@ -195,25 +231,23 @@ end | ||
| 195 | 231 | ---@param self lc.ui.Question |
| 196 | 232 | ---@param lang lc.lang |
| 197 | 233 | Question.change_lang = vim.schedule_wrap(function(self, lang) |
| 198 | - local old_lang = self.lang | |
| 234 | + local old_lang, old_bufnr = self.lang, self.bufnr | |
| 199 | 235 | self.lang = lang |
| 200 | 236 | |
| 201 | - local new_bufnr = vim.fn.bufadd(self:create_file()) | |
| 202 | - if new_bufnr ~= 0 then | |
| 203 | - local bufloaded = vim.fn.bufloaded(new_bufnr) | |
| 204 | - | |
| 205 | - vim.api.nvim_win_set_buf(self.winid, new_bufnr) | |
| 206 | - | |
| 207 | - vim.api.nvim_buf_set_option(self.bufnr, "buflisted", false) | |
| 208 | - vim.api.nvim_buf_set_option(new_bufnr, "buflisted", true) | |
| 237 | + local ok, was_loaded = pcall(Question.create_buffer, self) | |
| 238 | + if ok then | |
| 239 | + vim.api.nvim_buf_set_option(old_bufnr, "buflisted", false) | |
| 240 | + vim.api.nvim_buf_set_option(self.bufnr, "buflisted", true) | |
| 209 | 241 | |
| 210 | - self.bufnr = new_bufnr | |
| 211 | - if bufloaded == 0 then -- | |
| 242 | + if was_loaded then | |
| 243 | + vim.api.nvim_win_set_buf(self.winid, self.bufnr) | |
| 244 | + else | |
| 212 | 245 | utils.exec_hook("question_enter", self) |
| 213 | 246 | end |
| 214 | 247 | else |
| 215 | 248 | log.error("Changing language failed") |
| 216 | 249 | self.lang = old_lang |
| 250 | + self.bufnr = old_bufnr | |
| 217 | 251 | end |
| 218 | 252 | end) |
| 219 | 253 |
+12-0lua/leetcode/config/hooks.lua
| @@ -0,0 +1,12 @@ | ||
| 1 | +---@class lc.Hooks | |
| 2 | +local hooks = {} | |
| 3 | + | |
| 4 | +hooks["question_enter"] = { | |
| 5 | + function(q) | |
| 6 | + -- https://github.com/kawre/leetcode.nvim/issues/14 | |
| 7 | + if q.lang ~= "rust" then return end | |
| 8 | + pcall(function() require("rust-tools.standalone").start_standalone_client() end) | |
| 9 | + end, | |
| 10 | +} | |
| 11 | + | |
| 12 | +return hooks |
+1-0lua/leetcode/config/imports.lua
| @@ -68,6 +68,7 @@ imports["python"] = { | ||
| 68 | 68 | |
| 69 | 69 | imports["java"] = { |
| 70 | 70 | "import java.util.*;", |
| 71 | + "import java.math.*;", | |
| 71 | 72 | } |
| 72 | 73 | |
| 73 | 74 | return imports |
+1-0lua/leetcode/config/init.lua
| @@ -29,6 +29,7 @@ local config = { | ||
| 29 | 29 | sessions = require("leetcode.config.sessions"), |
| 30 | 30 | stats = require("leetcode.config.stats"), |
| 31 | 31 | imports = require("leetcode.config.imports"), |
| 32 | + hooks = require("leetcode.config.hooks"), | |
| 32 | 33 | |
| 33 | 34 | ---@type lc.UserStatus |
| 34 | 35 | auth = {}, ---@diagnostic disable-line |
+1-1lua/leetcode/config/template.lua
| @@ -102,7 +102,7 @@ local M = { | ||
| 102 | 102 | ["enter"] = {}, |
| 103 | 103 | |
| 104 | 104 | ---@type fun(question: lc.ui.Question)[] |
| 105 | - ["question_open"] = {}, | |
| 105 | + ["question_enter"] = {}, | |
| 106 | 106 | }, |
| 107 | 107 | |
| 108 | 108 | keys = { |
+12-2lua/leetcode/utils.lua
| @@ -72,11 +72,21 @@ function utils.get_lang_by_name(name) | ||
| 72 | 72 | end |
| 73 | 73 | |
| 74 | 74 | ---@param event lc.hook |
| 75 | -function utils.exec_hook(event, ...) | |
| 75 | +---@return fun()[]|nil | |
| 76 | +function utils.get_hooks(event) | |
| 77 | + local defaults = config.hooks[event] or {} | |
| 76 | 78 | local fns = config.user.hooks[event] |
| 77 | - if not fns then log.error("unknown hook event: " .. event) end | |
| 79 | + | |
| 80 | + if not fns then return end | |
| 78 | 81 | |
| 79 | 82 | if type(fns) == "function" then fns = { fns } end |
| 83 | + return vim.list_extend(defaults, fns) | |
| 84 | +end | |
| 85 | + | |
| 86 | +---@param event lc.hook | |
| 87 | +function utils.exec_hook(event, ...) | |
| 88 | + local fns = utils.get_hooks(event) | |
| 89 | + if not fns then return log.error("unknown hook event: " .. event) end | |
| 80 | 90 | |
| 81 | 91 | for i, fn in ipairs(fns) do |
| 82 | 92 | local ok, msg = pcall(vim.schedule_wrap(fn), ...) |