irongit

A Neovim plugin enabling you to solve LeetCode problems.

leetcode.nvim/README.md
517 lines11 KBMarkdown
1<div align="center">
2
3# leetcode.nvim
4
5๐Ÿ”ฅ Solve [LeetCode] problems within [Neovim] ๐Ÿ”ฅ
6
7<!-- ๐Ÿ‡บ๐Ÿ‡ธ English, ๐Ÿ‡จ๐Ÿ‡ณ <a href="README.zh.md">็ฎ€ไฝ“ไธญๆ–‡</a> -->
8
9</div>
10
11https://github.com/kawre/leetcode.nvim/assets/69250723/aee6584c-e099-4409-b114-123cb32b7563
12
13## โœจ Features
14
15- ๐Ÿ“Œ an intuitive dashboard for effortless navigation within [leetcode.nvim]
16
17- ๐Ÿ˜ question description formatting for a better readability
18
19- ๐Ÿ“ˆ [LeetCode] profile statistics within [Neovim]
20
21- ๐Ÿ”€ support for daily and random questions
22
23- ๐Ÿ’พ caching for optimized performance
24
25## ๐Ÿ“ฌ Requirements
26
27- [Neovim] >= 0.9.0
28
29- [Picker]#picker
30
31- [plenary.nvim]
32
33- [nui.nvim]
34
35- [tree-sitter-html] _**(optional, but highly recommended)**_
36 used for formatting the question description.
37 Can be installed with [nvim-treesitter].
38
39- [Nerd Font][nerd-font] & [nvim-web-devicons] _**(optional)**_
40
41## ๐Ÿ“ฆ Installation
42
43- [lazy.nvim]
44
45```lua
46{
47 "kawre/leetcode.nvim",
48 build = ":TSUpdate html", -- if you have `nvim-treesitter` installed
49 dependencies = {
50 -- include a picker of your choice, see picker section for more details
51 "nvim-lua/plenary.nvim",
52 "MunifTanjim/nui.nvim",
53 },
54 opts = {
55 -- configuration goes here
56 },
57}
58```
59
60## ๐Ÿ› ๏ธ Configuration
61
62To see full configuration types see [template.lua]./lua/leetcode/config/template.lua
63
64### โš™๏ธ default configuration
65
66```lua
67{
68 ---@type string
69 arg = "leetcode.nvim",
70
71 ---@type lc.lang
72 lang = "cpp",
73
74 cn = { -- leetcode.cn
75 enabled = false, ---@type boolean
76 translator = true, ---@type boolean
77 translate_problems = true, ---@type boolean
78 },
79
80 ---@type lc.storage
81 storage = {
82 home = vim.fn.stdpath("data") .. "/leetcode",
83 cache = vim.fn.stdpath("cache") .. "/leetcode",
84 },
85
86 ---@type table<string, boolean>
87 plugins = {
88 non_standalone = false,
89 },
90
91 ---@type boolean
92 logging = true,
93
94 injector = {}, ---@type table<lc.lang, lc.inject>
95
96 cache = {
97 update_interval = 60 * 60 * 24 * 7, ---@type integer 7 days
98 },
99
100 console = {
101 open_on_runcode = true, ---@type boolean
102
103 dir = "row", ---@type lc.direction
104
105 size = { ---@type lc.size
106 width = "90%",
107 height = "75%",
108 },
109
110 result = {
111 size = "60%", ---@type lc.size
112 },
113
114 testcase = {
115 virt_text = true, ---@type boolean
116
117 size = "40%", ---@type lc.size
118 },
119 },
120
121 description = {
122 position = "left", ---@type lc.position
123
124 width = "40%", ---@type lc.size
125
126 show_stats = true, ---@type boolean
127 },
128
129 ---@type lc.picker
130 picker = { provider = nil },
131
132 hooks = {
133 ---@type fun()[]
134 ["enter"] = {},
135
136 ---@type fun(question: lc.ui.Question)[]
137 ["question_enter"] = {},
138
139 ---@type fun()[]
140 ["leave"] = {},
141 },
142
143 keys = {
144 toggle = { "q" }, ---@type string|string[]
145 confirm = { "<CR>" }, ---@type string|string[]
146
147 reset_testcases = "r", ---@type string
148 use_testcase = "U", ---@type string
149 focus_testcases = "H", ---@type string
150 focus_result = "L", ---@type string
151 },
152
153 ---@type lc.highlights
154 theme = {},
155
156 ---@type boolean
157 image_support = false,
158}
159```
160
161### arg
162
163Argument for [Neovim]
164
165```lua
166---@type string
167arg = "leetcode.nvim"
168```
169
170<small>See [usage]#-usage for more info</small>
171
172### lang
173
174Language to start your session with
175
176```lua
177---@type lc.lang
178lang = "cpp"
179```
180
181<details>
182 <summary>available languages</summary>
183
184| Language | lang |
185| ---------- | ---------- |
186| C++ | cpp |
187| Java | java |
188| Python | python |
189| Python3 | python3 |
190| C | c |
191| C# | csharp |
192| JavaScript | javascript |
193| TypeScript | typescript |
194| PHP | php |
195| Swift | swift |
196| Kotlin | kotlin |
197| Dart | dart |
198| Go | golang |
199| Ruby | ruby |
200| Scala | scala |
201| Rust | rust |
202| Racket | racket |
203| Erlang | erlang |
204| Elixir | elixir |
205| Bash | bash |
206
207</details>
208
209### cn
210
211Use [leetcode.cn] instead of [leetcode.com][leetcode]
212
213```lua
214cn = { -- leetcode.cn
215 enabled = false, ---@type boolean
216 translator = true, ---@type boolean
217 translate_problems = true, ---@type boolean
218},
219```
220
221### storage
222
223storage directories
224
225```lua
226---@type lc.storage
227storage = {
228 home = vim.fn.stdpath("data") .. "/leetcode",
229 cache = vim.fn.stdpath("cache") .. "/leetcode",
230},
231```
232
233### plugins
234
235[plugins list]#-plugins
236
237```lua
238---@type table<string, boolean>
239plugins = {
240 non_standalone = false,
241},
242```
243
244### logging
245
246Whether to log [leetcode.nvim] status notifications
247
248```lua
249---@type boolean
250logging = true
251```
252
253### injector
254
255Inject code before or after your solution, injected code won't be submitted or run.
256
257Imports will be injected at the top of the buffer, automatically
258folded by default.
259
260```lua
261injector = { ---@type table<lc.lang, lc.inject>
262 ["python3"] = {
263 imports = function(default_imports)
264 vim.list_extend(default_imports, { "from .leetcode import *" })
265 return default_imports
266 end,
267 after = { "def test():", " print('test')" },
268 },
269 ["cpp"] = {
270 imports = function()
271 -- return a different list to omit default imports
272 return { "#include <bits/stdc++.h>", "using namespace std;" }
273 end,
274 after = "int main() {}",
275 },
276},
277```
278
279### picker
280
281Supported picker providers are:
282
283- [`snacks-picker`][snacks.nvim]
284- [`fzf-lua`][fzf-lua]
285- [`telescope`][telescope.nvim]
286
287If `provider` is `nil`, [leetcode.nvim] will try to resolve the first
288available one in the order above.
289
290```lua
291---@type lc.picker
292picker = { provider = nil },
293```
294
295### hooks
296
297List of functions that get executed on specified event
298
299```lua
300hooks = {
301 ---@type fun()[]
302 ["enter"] = {},
303
304 ---@type fun(question: lc.ui.Question)[]
305 ["question_enter"] = {},
306
307 ---@type fun()[]
308 ["leave"] = {},
309},
310```
311
312### theme
313
314Override the [default theme]./lua/leetcode/theme/default.lua.
315
316Each value is the same type as val parameter in `:help nvim_set_hl`
317
318```lua
319---@type lc.highlights
320theme = {
321 ["alt"] = {
322 bg = "#FFFFFF",
323 },
324 ["normal"] = {
325 fg = "#EA4AAA",
326 },
327},
328```
329
330### image support
331
332Whether to render question description images using [image.nvim]
333
334> [!WARNING]
335> Enabling this will disable question description wrap,
336> because of https://github.com/3rd/image.nvim/issues/62#issuecomment-1778082534
337
338```lua
339---@type boolean
340image_support = false,
341```
342
343## ๐Ÿ“‹ Commands
344
345### `Leet` opens menu dashboard
346
347- `menu` same as `Leet`
348
349- `exit` close [leetcode.nvim]
350
351- `console` opens console pop-up for currently opened question
352
353- `info` opens a pop-up containing information about the currently opened question
354
355- `tabs` opens a picker with all currently opened question tabs
356
357- `yank` yanks the code section
358
359- `lang` opens a picker to change the language of the current question
360
361- `run` run currently opened question
362
363- `test` same as `Leet run`
364
365- `submit` submit currently opened question
366
367- `random` opens a random question
368
369- `daily` opens the question of today problem
370
371- `list` opens a picker with all available leetcode problems
372
373- `open` opens the current question in a default browser
374
375- `restore` try to restore default question layout
376
377- `last_submit` tries to replace the editor code section with the latest submitted code
378
379- `reset` resets editor code section to the default snippet
380
381- `inject` re-injects editor code, keeping the code section intact
382
383- `fold` applies folding to the current question imports section
384
385<!-- - `session` -->
386<!-- - `create` create a new session -->
387<!-- - `change` change the current session -->
388<!---->
389<!-- - `update` update the current session in case it went out of sync -->
390
391- `desc` toggle question description
392 - `toggle` same as `Leet desc`
393
394 - `stats` toggle description stats visibility
395
396- `cookie`
397 - `update` opens a prompt to enter a new cookie
398
399 - `delete` deletes stored cookie and logs out of [leetcode.nvim]
400
401- `cache`
402 - `update` fetches all available problems and updates the local cache of [leetcode.nvim]
403
404#### Some commands can take optional arguments. To stack argument values separate them by a `,`
405
406- `Leet list`
407
408 ```
409 Leet list status=<status> difficulty=<difficulty>
410 ```
411
412- `Leet random`
413
414 ```
415 Leet random status=<status> difficulty=<difficulty> tags=<tags>
416 ```
417
418## ๐Ÿš€ Usage
419
420This plugin can be initiated in two ways:
421
422- To start [leetcode.nvim], simply pass [`arg`]#arg
423 as the _first and **only**_ [Neovim] argument
424
425 ```
426 nvim leetcode.nvim
427 ```
428
429- Use `:Leet` command to open [leetcode.nvim]
430 within your preferred dashboard plugin. The only requirement is that [Neovim]
431 must not have any listed buffers open.
432 To bypass this requirement use [`non_standalone`]#non-standalone-mode plugin.
433
434### Switching between questions
435
436To switch between questions, use `Leet tabs`
437
438### Sign In
439
440> [!WARNING]
441> Be sure to copy the `Cookie` from request headers, not the `set-cookie` from
442> response headers.
443
444https://github.com/kawre/leetcode.nvim/assets/69250723/b7be8b95-5e2c-4153-8845-4ad3abeda5c3
445
446## ๐Ÿด Recipes
447
448### ๐Ÿ’ค lazy loading with [lazy.nvim]
449
450> [!WARNING]
451> opting for either option makes the alternative
452> launch method unavailable due to lazy loading
453
454- with [`arg`]#arg
455
456 ```lua
457 local leet_arg = "leetcode.nvim"
458 ```
459
460 ```lua
461 {
462 "kawre/leetcode.nvim",
463 lazy = leet_arg ~= vim.fn.argv(0, -1),
464 opts = { arg = leet_arg },
465 }
466 ```
467
468- with `:Leet`
469
470 ```lua
471 {
472 "kawre/leetcode.nvim",
473 cmd = "Leet",
474 }
475 ```
476
477### ๐ŸชŸ Windows
478
479If you are using Windows,
480it is recommended to use [Cygwin]https://www.cygwin.com/ for a more consistent and Unix-like experience.
481
482## ๐Ÿงฉ Plugins
483
484### Non-Standalone mode
485
486To run [leetcode.nvim] in a non-standalone mode (i.e. not with argument or an empty Neovim session),
487enable the `non_standalone` plugin in your config:
488
489```lua
490plugins = {
491 non_standalone = true,
492}
493```
494
495You can then exit [leetcode.nvim] using `:Leet exit` command
496
497## ๐Ÿ™Œ Credits
498
499- [Leetbuddy.nvim]https://github.com/Dhanus3133/Leetbuddy.nvim
500
501- [alpha-nvim]https://github.com/goolord/alpha-nvim
502
503[image.nvim]: https://github.com/3rd/image.nvim
504[lazy.nvim]: https://github.com/folke/lazy.nvim
505[leetcode]: https://leetcode.com
506[leetcode.cn]: https://leetcode.cn
507[leetcode.nvim]: https://github.com/kawre/leetcode.nvim
508[neovim]: https://github.com/neovim/neovim
509[nerd-font]: https://www.nerdfonts.com
510[nui.nvim]: https://github.com/MunifTanjim/nui.nvim
511[nvim-treesitter]: https://github.com/nvim-treesitter/nvim-treesitter
512[nvim-web-devicons]: https://github.com/nvim-tree/nvim-web-devicons
513[telescope.nvim]: https://github.com/nvim-telescope/telescope.nvim
514[fzf-lua]: https://github.com/ibhagwan/fzf-lua
515[snacks.nvim]: https://github.com/folke/snacks.nvim
516[tree-sitter-html]: https://github.com/tree-sitter/tree-sitter-html
517[plenary.nvim]: https://github.com/nvim-lua/plenary.nvim