Leetcode.nvim
A Neovim plugin enabling you to solve LeetCode problems.
Install / Use
/learn @kawre/Leetcode.nvimREADME
leetcode.nvim
🔥 Solve [LeetCode] problems within [Neovim] 🔥
<!-- 🇺🇸 English, 🇨🇳 <a href="README.zh.md">简体中文</a> --> </div>https://github.com/kawre/leetcode.nvim/assets/69250723/aee6584c-e099-4409-b114-123cb32b7563
✨ Features
-
📌 an intuitive dashboard for effortless navigation within [leetcode.nvim]
-
😍 question description formatting for a better readability
-
📈 [LeetCode] profile statistics within [Neovim]
-
🔀 support for daily and random questions
-
💾 caching for optimized performance
📬 Requirements
-
[Neovim] >= 0.9.0
-
[plenary.nvim]
-
[nui.nvim]
-
[tree-sitter-html] (optional, but highly recommended) used for formatting the question description. Can be installed with [nvim-treesitter].
-
[Nerd Font][nerd-font] & [nvim-web-devicons] (optional)
📦 Installation
- [lazy.nvim]
{
"kawre/leetcode.nvim",
build = ":TSUpdate html", -- if you have `nvim-treesitter` installed
dependencies = {
-- include a picker of your choice, see picker section for more details
"nvim-lua/plenary.nvim",
"MunifTanjim/nui.nvim",
},
opts = {
-- configuration goes here
},
}
🛠️ Configuration
To see full configuration types see template.lua
⚙️ default configuration
{
---@type string
arg = "leetcode.nvim",
---@type lc.lang
lang = "cpp",
cn = { -- leetcode.cn
enabled = false, ---@type boolean
translator = true, ---@type boolean
translate_problems = true, ---@type boolean
},
---@type lc.storage
storage = {
home = vim.fn.stdpath("data") .. "/leetcode",
cache = vim.fn.stdpath("cache") .. "/leetcode",
},
---@type table<string, boolean>
plugins = {
non_standalone = false,
},
---@type boolean
logging = true,
injector = {}, ---@type table<lc.lang, lc.inject>
cache = {
update_interval = 60 * 60 * 24 * 7, ---@type integer 7 days
},
editor = {
reset_previous_code = true, ---@type boolean
fold_imports = true, ---@type boolean
},
console = {
open_on_runcode = true, ---@type boolean
dir = "row", ---@type lc.direction
size = { ---@type lc.size
width = "90%",
height = "75%",
},
result = {
size = "60%", ---@type lc.size
},
testcase = {
virt_text = true, ---@type boolean
size = "40%", ---@type lc.size
},
},
description = {
position = "left", ---@type lc.position
width = "40%", ---@type lc.size
show_stats = true, ---@type boolean
},
---@type lc.picker
picker = { provider = nil },
hooks = {
---@type fun()[]
["enter"] = {},
---@type fun(question: lc.ui.Question)[]
["question_enter"] = {},
---@type fun()[]
["leave"] = {},
},
keys = {
toggle = { "q" }, ---@type string|string[]
confirm = { "<CR>" }, ---@type string|string[]
reset_testcases = "r", ---@type string
use_testcase = "U", ---@type string
focus_testcases = "H", ---@type string
focus_result = "L", ---@type string
},
---@type lc.highlights
theme = {},
---@type boolean
image_support = false,
}
arg
Argument for [Neovim]
---@type string
arg = "leetcode.nvim"
<small>See usage for more info</small>
lang
Language to start your session with
---@type lc.lang
lang = "cpp"
<details>
<summary>available languages</summary>
| Language | lang | | ---------- | ---------- | | C++ | cpp | | Java | java | | Python | python | | Python3 | python3 | | C | c | | C# | csharp | | JavaScript | javascript | | TypeScript | typescript | | PHP | php | | Swift | swift | | Kotlin | kotlin | | Dart | dart | | Go | golang | | Ruby | ruby | | Scala | scala | | Rust | rust | | Racket | racket | | Erlang | erlang | | Elixir | elixir | | Bash | bash |
</details>cn
Use [leetcode.cn] instead of [leetcode.com][leetcode]
cn = { -- leetcode.cn
enabled = false, ---@type boolean
translator = true, ---@type boolean
translate_problems = true, ---@type boolean
},
storage
storage directories
---@type lc.storage
storage = {
home = vim.fn.stdpath("data") .. "/leetcode",
cache = vim.fn.stdpath("cache") .. "/leetcode",
},
plugins
---@type table<string, boolean>
plugins = {
non_standalone = false,
},
logging
Whether to log [leetcode.nvim] status notifications
---@type boolean
logging = true
injector
Inject code before or after your solution, injected code won't be submitted or run.
Imports will be injected at the top of the buffer, automatically folded by default.
injector = { ---@type table<lc.lang, lc.inject>
["python3"] = {
imports = function(default_imports)
vim.list_extend(default_imports, { "from .leetcode import *" })
return default_imports
end,
after = { "def test():", " print('test')" },
},
["cpp"] = {
imports = function()
-- return a different list to omit default imports
return { "#include <bits/stdc++.h>", "using namespace std;" }
end,
after = "int main() {}",
},
},
picker
Supported picker providers are:
- [
snacks-picker][snacks.nvim] - [
fzf-lua][fzf-lua] - [
telescope][telescope.nvim] - [
mini-picker][mini-picker]
If provider is nil, [leetcode.nvim] will try to resolve the first
available one in the order above.
---@type lc.picker
picker = { provider = nil },
hooks
List of functions that get executed on specified event
hooks = {
---@type fun()[]
["enter"] = {},
---@type fun(question: lc.ui.Question)[]
["question_enter"] = {},
---@type fun()[]
["leave"] = {},
},
theme
Override the default theme.
Each value is the same type as val parameter in :help nvim_set_hl
---@type lc.highlights
theme = {
["alt"] = {
bg = "#FFFFFF",
},
["normal"] = {
fg = "#EA4AAA",
},
},
image support
Whether to render question description images using [image.nvim]
[!WARNING] Enabling this will disable question description wrap, because of https://github.com/3rd/image.nvim/issues/62#issuecomment-1778082534
---@type boolean
image_support = false,
📋 Commands
Leet opens menu dashboard
-
menusame asLeet -
exitclose [leetcode.nvim] -
consoleopens console pop-up for currently opened question -
infoopens a pop-up containing information about the currently opened question -
tabsopens a picker with all currently opened question tabs -
yankyanks the code section -
langopens a picker to change the language of the current question -
runrun currently opened question -
testsame asLeet run -
submitsubmit currently opened question -
randomopens a random question -
dailyopens the question of today problem -
listopens a picker with all available leetcode problems -
openopens the current question in a default browser -
restoretry to restore default question layout -
last_submittries to replace the editor code section with the latest submitted code -
resetresets editor code section to the default snippet -
injectre-injects editor code, keeping the code section intact -
foldapplies folding to the current question imports section
-
desctoggle question description-
togglesame asLeet desc -
statstoggle description stats visibility
-
-
cookie-
updateopens a prompt to enter a new cookie -
deletedeletes stored cookie and logs out of [leetcode.nvim]
-
-
cacheupdatefetches all available problems and updates the local cache of [leetcode.nvim]
Some commands can take optional arguments. To stack argument values separate them by a ,
-
Leet listLeet list status=<status> difficulty=<difficulty> -
Leet randomLeet random status=<status> difficulty=<difficulty> tags=<tags>
🚀 Usage
This plugin can be initiated in two ways:
-
To start [leetcode.nvim], simply pass
argas the first and only [Neovim] argumentnvim leetcode.nvim -
Use
:Leetcommand to open [leetcode.nvim] within your preferred dashboard plugin. The only requirement is that [Neovim] must not have any listed buffers open. To bypass this requirement usenon_standaloneplugin.
Sign In
[!WARNING] Be sure to copy the
Cookiefrom request headers, not theset-cookiefrom response headers.
[!WARNING] If you are using brave browser, see this issue
https://github.com/kawre/leetcode.nvim/assets/69250723/b7be8b95-5e2c-4153-8845-4ad3abeda5c3
❓ FAQ
I keep getting cookie expired error
If you keep getting Your cookie may have expired, or LeetCode has temporarily restricted API access, it most likely means that LeetCode website is under
heavy load and is restricting API access (mostly during contests).
All you can do is wait it out, try disabling a VPN if you’re using one, and if the problem is persistent, open an issue.
