irongit

A Neovim plugin enabling you to solve LeetCode problems.

leetcode.nvim/README.md
547 lines12 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 editor = {
101 reset_previous_code = true, ---@type boolean
102 fold_imports = true, ---@type boolean
103 },
104
105 console = {
106 open_on_runcode = true, ---@type boolean
107
108 dir = "row", ---@type lc.direction
109
110 size = { ---@type lc.size
111 width = "90%",
112 height = "75%",
113 },
114
115 result = {
116 size = "60%", ---@type lc.size
117 },
118
119 testcase = {
120 virt_text = true, ---@type boolean
121
122 size = "40%", ---@type lc.size
123 },
124 },
125
126 description = {
127 position = "left", ---@type lc.position
128
129 width = "40%", ---@type lc.size
130
131 show_stats = true, ---@type boolean
132 },
133
134 ---@type lc.picker
135 picker = { provider = nil },
136
137 hooks = {
138 ---@type fun()[]
139 ["enter"] = {},
140
141 ---@type fun(question: lc.ui.Question)[]
142 ["question_enter"] = {},
143
144 ---@type fun()[]
145 ["leave"] = {},
146 },
147
148 keys = {
149 toggle = { "q" }, ---@type string|string[]
150 confirm = { "<CR>" }, ---@type string|string[]
151
152 reset_testcases = "r", ---@type string
153 use_testcase = "U", ---@type string
154 focus_testcases = "H", ---@type string
155 focus_result = "L", ---@type string
156 },
157
158 ---@type lc.highlights
159 theme = {},
160
161 ---@type boolean
162 image_support = false,
163}
164```
165
166### arg
167
168Argument for [Neovim]
169
170```lua
171---@type string
172arg = "leetcode.nvim"
173```
174
175<small>See [usage]#-usage for more info</small>
176
177### lang
178
179Language to start your session with
180
181```lua
182---@type lc.lang
183lang = "cpp"
184```
185
186<details>
187 <summary>available languages</summary>
188
189| Language | lang |
190| ---------- | ---------- |
191| C++ | cpp |
192| Java | java |
193| Python | python |
194| Python3 | python3 |
195| C | c |
196| C# | csharp |
197| JavaScript | javascript |
198| TypeScript | typescript |
199| PHP | php |
200| Swift | swift |
201| Kotlin | kotlin |
202| Dart | dart |
203| Go | golang |
204| Ruby | ruby |
205| Scala | scala |
206| Rust | rust |
207| Racket | racket |
208| Erlang | erlang |
209| Elixir | elixir |
210| Bash | bash |
211
212</details>
213
214### cn
215
216Use [leetcode.cn] instead of [leetcode.com][leetcode]
217
218```lua
219cn = { -- leetcode.cn
220 enabled = false, ---@type boolean
221 translator = true, ---@type boolean
222 translate_problems = true, ---@type boolean
223},
224```
225
226### storage
227
228storage directories
229
230```lua
231---@type lc.storage
232storage = {
233 home = vim.fn.stdpath("data") .. "/leetcode",
234 cache = vim.fn.stdpath("cache") .. "/leetcode",
235},
236```
237
238### plugins
239
240[plugins list]#-plugins
241
242```lua
243---@type table<string, boolean>
244plugins = {
245 non_standalone = false,
246},
247```
248
249### logging
250
251Whether to log [leetcode.nvim] status notifications
252
253```lua
254---@type boolean
255logging = true
256```
257
258### injector
259
260Inject code before or after your solution, injected code won't be submitted or run.
261
262Imports will be injected at the top of the buffer, automatically
263folded by default.
264
265```lua
266injector = { ---@type table<lc.lang, lc.inject>
267 ["python3"] = {
268 imports = function(default_imports)
269 vim.list_extend(default_imports, { "from .leetcode import *" })
270 return default_imports
271 end,
272 after = { "def test():", " print('test')" },
273 },
274 ["cpp"] = {
275 imports = function()
276 -- return a different list to omit default imports
277 return { "#include <bits/stdc++.h>", "using namespace std;" }
278 end,
279 after = "int main() {}",
280 },
281},
282```
283
284### picker
285
286Supported picker providers are:
287
288- [`snacks-picker`][snacks.nvim]
289- [`fzf-lua`][fzf-lua]
290- [`telescope`][telescope.nvim]
291
292If `provider` is `nil`, [leetcode.nvim] will try to resolve the first
293available one in the order above.
294
295```lua
296---@type lc.picker
297picker = { provider = nil },
298```
299
300### hooks
301
302List of functions that get executed on specified event
303
304```lua
305hooks = {
306 ---@type fun()[]
307 ["enter"] = {},
308
309 ---@type fun(question: lc.ui.Question)[]
310 ["question_enter"] = {},
311
312 ---@type fun()[]
313 ["leave"] = {},
314},
315```
316
317### theme
318
319Override the [default theme]./lua/leetcode/theme/default.lua.
320
321Each value is the same type as val parameter in `:help nvim_set_hl`
322
323```lua
324---@type lc.highlights
325theme = {
326 ["alt"] = {
327 bg = "#FFFFFF",
328 },
329 ["normal"] = {
330 fg = "#EA4AAA",
331 },
332},
333```
334
335### image support
336
337Whether to render question description images using [image.nvim]
338
339> [!WARNING]
340> Enabling this will disable question description wrap,
341> because of https://github.com/3rd/image.nvim/issues/62#issuecomment-1778082534
342
343```lua
344---@type boolean
345image_support = false,
346```
347
348## ๐Ÿ“‹ Commands
349
350### `Leet` opens menu dashboard
351
352- `menu` same as `Leet`
353
354- `exit` close [leetcode.nvim]
355
356- `console` opens console pop-up for currently opened question
357
358- `info` opens a pop-up containing information about the currently opened question
359
360- `tabs` opens a picker with all currently opened question tabs
361
362- `yank` yanks the code section
363
364- `lang` opens a picker to change the language of the current question
365
366- `run` run currently opened question
367
368- `test` same as `Leet run`
369
370- `submit` submit currently opened question
371
372- `random` opens a random question
373
374- `daily` opens the question of today problem
375
376- `list` opens a picker with all available leetcode problems
377
378- `open` opens the current question in a default browser
379
380- `restore` try to restore default question layout
381
382- `last_submit` tries to replace the editor code section with the latest submitted code
383
384- `reset` resets editor code section to the default snippet
385
386- `inject` re-injects editor code, keeping the code section intact
387
388- `fold` applies folding to the current question imports section
389
390<!-- - `session` -->
391<!-- - `create` create a new session -->
392<!-- - `change` change the current session -->
393<!---->
394<!-- - `update` update the current session in case it went out of sync -->
395
396- `desc` toggle question description
397 - `toggle` same as `Leet desc`
398
399 - `stats` toggle description stats visibility
400
401- `cookie`
402 - `update` opens a prompt to enter a new cookie
403
404 - `delete` deletes stored cookie and logs out of [leetcode.nvim]
405
406- `cache`
407 - `update` fetches all available problems and updates the local cache of [leetcode.nvim]
408
409#### Some commands can take optional arguments. To stack argument values separate them by a `,`
410
411- `Leet list`
412
413 ```
414 Leet list status=<status> difficulty=<difficulty>
415 ```
416
417- `Leet random`
418
419 ```
420 Leet random status=<status> difficulty=<difficulty> tags=<tags>
421 ```
422
423## ๐Ÿš€ Usage
424
425This plugin can be initiated in two ways:
426
427- To start [leetcode.nvim], simply pass [`arg`]#arg
428 as the _first and **only**_ [Neovim] argument
429
430 ```
431 nvim leetcode.nvim
432 ```
433
434- Use `:Leet` command to open [leetcode.nvim]
435 within your preferred dashboard plugin. The only requirement is that [Neovim]
436 must not have any listed buffers open.
437 To bypass this requirement use [`non_standalone`]#non-standalone-mode plugin.
438
439### Sign In
440
441> [!WARNING]
442> Be sure to copy the `Cookie` from request headers, not the `set-cookie` from
443> response headers.
444
445> [!WARNING]
446> If you are using **brave browser**, see [this
447> issue](https://github.com/kawre/leetcode.nvim/issues/160#issuecomment-2619611920)
448
449https://github.com/kawre/leetcode.nvim/assets/69250723/b7be8b95-5e2c-4153-8845-4ad3abeda5c3
450
451## โ“ FAQ
452
453### I keep getting `cookie expired` error
454
455If you keep getting `Your cookie may have expired, or LeetCode has temporarily
456restricted API access`, it most likely means that LeetCode website is under
457heavy load and is restricting API access (mostly during contests).
458
459All you can do is wait it out, try disabling a VPN if youโ€™re using one, and if
460the problem is persistent, open an issue.
461
462### Switching between test cases
463
464To switch between test cases, just press the number of the corresponding case:
465`1` for `Case (1)`, `2` for `Case (2)`, and so on.
466
467### Switching between questions
468
469To switch between questions, use `Leet tabs`
470
471### I'm not getting LSP completions
472
473Some languages require additional setup to get LSP completions.
474For example, Rust needs extra configuration โ€” see [this issue]https://github.com/kawre/leetcode.nvim/issues/86.
475
476## ๐Ÿด Recipes
477
478### ๐Ÿ’ค lazy loading with [lazy.nvim]
479
480> [!WARNING]
481> opting for either option makes the alternative
482> launch method unavailable due to lazy loading
483
484- with [`arg`]#arg
485
486 ```lua
487 local leet_arg = "leetcode.nvim"
488 ```
489
490 ```lua
491 {
492 "kawre/leetcode.nvim",
493 lazy = leet_arg ~= vim.fn.argv(0, -1),
494 opts = { arg = leet_arg },
495 }
496 ```
497
498- with `:Leet`
499
500 ```lua
501 {
502 "kawre/leetcode.nvim",
503 cmd = "Leet",
504 }
505 ```
506
507### ๐ŸชŸ Windows
508
509If you are using Windows,
510it is recommended to use [Cygwin]https://www.cygwin.com/ for a more consistent and Unix-like experience.
511
512## ๐Ÿงฉ Plugins
513
514### Non-Standalone mode
515
516To run [leetcode.nvim] in a non-standalone mode (i.e. not with argument or an empty Neovim session),
517enable the `non_standalone` plugin in your config:
518
519```lua
520plugins = {
521 non_standalone = true,
522}
523```
524
525You can then exit [leetcode.nvim] using `:Leet exit` command
526
527## ๐Ÿ™Œ Credits
528
529- [Leetbuddy.nvim]https://github.com/Dhanus3133/Leetbuddy.nvim
530
531- [alpha-nvim]https://github.com/goolord/alpha-nvim
532
533[image.nvim]: https://github.com/3rd/image.nvim
534[lazy.nvim]: https://github.com/folke/lazy.nvim
535[leetcode]: https://leetcode.com
536[leetcode.cn]: https://leetcode.cn
537[leetcode.nvim]: https://github.com/kawre/leetcode.nvim
538[neovim]: https://github.com/neovim/neovim
539[nerd-font]: https://www.nerdfonts.com
540[nui.nvim]: https://github.com/MunifTanjim/nui.nvim
541[nvim-treesitter]: https://github.com/nvim-treesitter/nvim-treesitter
542[nvim-web-devicons]: https://github.com/nvim-tree/nvim-web-devicons
543[telescope.nvim]: https://github.com/nvim-telescope/telescope.nvim
544[fzf-lua]: https://github.com/ibhagwan/fzf-lua
545[snacks.nvim]: https://github.com/folke/snacks.nvim
546[tree-sitter-html]: https://github.com/tree-sitter/tree-sitter-html
547[plenary.nvim]: https://github.com/nvim-lua/plenary.nvim