A Neovim plugin enabling you to solve LeetCode problems.
leetcode.nvim
๐ฅ Solve [LeetCode] problems within [Neovim] ๐ฅ
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)
- [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 = { resetpreviouscode = true, ---@type boolean fold_imports = true, ---@type boolean },
console = { openonruncode = 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"
See usage for more info
lang
Language to start your session with
---@type lc.lang
lang = "cpp"
available languages
| 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 |
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.listextend(defaultimports, { "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]
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 nvimsethl
---@type lc.highlights
theme = {
["alt"] = {
bg = "#FFFFFF",
},
["normal"] = {
fg = "#EA4AAA",
},
},
image support
[!NOTE]
Requires [image.nvim] v1.4.0+ which fixed text wrapping support (see https://github.com/3rd/image.nvim/pull/266)
---@type boolean
image_support = true,
๐ 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
toggle same as Leet desc
- stats toggle description stats visibility
cookie
update opens a prompt to enter a new cookie
- delete deletes stored cookie and logs out of [leetcode.nvim]
cache
update fetches 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 list
Leet list status=<status> difficulty=<difficulty>
Leet random
Leet random status=<status> difficulty=<difficulty> tags=<tags>
๐ Usage
This plugin can be initiated in two ways:
- To start [leetcode.nvim], simply pass
arg
nvim leetcode.nvim
- Use
:Leetcommand to open [leetcode.nvim]
non_standalone plugin.
Sign In
[!WARNING]
Be sure to copy theCookiefrom 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.
Switching between test cases
To switch between test cases, just press the number of the corresponding case: 1 for Case (1), 2 for Case (2), and so on.
Switching between questions
To switch between questions, use Leet tabs
I'm not getting LSP completions
Some languages require additional setup to get LSP completions. For example, Rust needs extra configuration โ see this issue.
๐ด Recipes
๐ค lazy loading with [lazy.nvim]
[!WARNING]
opting for either option makes the alternative
launch method unavailable due to lazy loading
- with
arg
local leet_arg = "leetcode.nvim"
{
"kawre/leetcode.nvim",
lazy = leet_arg ~= vim.fn.argv(0, -1),
opts = { arg = leet_arg },
}
- with
:Leet
{
"kawre/leetcode.nvim",
cmd = "Leet",
}
๐ช Windows
If you are using Windows, it is recommended to use Cygwin for a more consistent and Unix-like experience.
๐งฉ Plugins
Non-Standalone mode
To run [leetcode.nvim] in a non-standalone mode (i.e. not with argument or an empty Neovim session), enable the non_standalone plugin in your config:
plugins = {
non_standalone = true,
}
You can then exit [leetcode.nvim] using :Leet exit command