irongit

A Neovim plugin enabling you to solve LeetCode problems.

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