diff --git a/nvim b/nvim deleted file mode 160000 index 652e95b..0000000 --- a/nvim +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 652e95b4c17c4737ef6a214fbe4473e29342da9a diff --git a/nvim/.gitignore b/nvim/.gitignore new file mode 100644 index 0000000..f8e46c0 --- /dev/null +++ b/nvim/.gitignore @@ -0,0 +1,8 @@ +tags +en.utf-8.add.spl +*.exe +.netrwhist +*.log +.DS_Store +lazy-lock.json +.env* diff --git a/nvim/.stylua.toml b/nvim/.stylua.toml new file mode 100644 index 0000000..92bda2a --- /dev/null +++ b/nvim/.stylua.toml @@ -0,0 +1,8 @@ +# config for stylua, ref: https://github.com/JohnnyMorganz/StyLua +syntax = "Lua51" +column_width = 100 +line_endings = "Unix" +indent_type = "Spaces" +indent_width = 2 +quote_style = "AutoPreferDouble" +call_parentheses= "NoSingleTable" diff --git a/nvim/LICENSE b/nvim/LICENSE new file mode 100644 index 0000000..eebf2a3 --- /dev/null +++ b/nvim/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018-2023 jdhao + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/nvim/README.md b/nvim/README.md new file mode 100644 index 0000000..c836712 --- /dev/null +++ b/nvim/README.md @@ -0,0 +1,209 @@ +
+

+ + Linux + + + macOS + + + Windows + + + Neovim minimum version + + + Top languages + + + + + + + + + + + + License + + + deepwiki + +

+
+ +# Introduction + +This repo hosts my Nvim configuration for Linux, macOS, and Windows. +`init.lua` is the config entry point for terminal Nvim, +and `ginit.vim` is the additional config file for [GUI client of Nvim](https://github.com/neovim/neovim/wiki/Related-projects#gui). + +My configurations are heavily documented to make it as clear as possible. +While you can clone the whole repository and use it, it is not recommended though. +Good configurations are personal. Everyone should have his or her unique config file. +You are encouraged to copy from this repo the part you want and add it to your own config. + +To reduce the possibility of breakage, **this config is only maintained for [the latest nvim stable release](https://github.com/neovim/neovim/releases/tag/stable). +No effort is spent on maintaining backward compatibility.** + +# Install and setup + +See [doc here](docs/README.md) on how to install Nvim's dependencies, Nvim itself, +and how to set up on different platforms (Linux, macOS, and Windows). + +# Features # + ++ Plugin management via [Lazy.nvim](https://github.com/folke/lazy.nvim). ++ Code, snippet, word auto-completion via [nvim-cmp](https://github.com/hrsh7th/nvim-cmp). ++ Language server protocol (LSP) support via [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig). ++ Git integration via [vim-fugitive](https://github.com/tpope/vim-fugitive). ++ Better escaping from insert mode via [better-escape.vim](https://github.com/nvim-zh/better-escape.vim). ++ Ultra-fast project-wide fuzzy searching via [fzf-lua](https://github.com/ibhagwan/fzf-lua). ++ Faster code commenting via [vim-commentary](https://github.com/tpope/vim-commentary). ++ Faster matching pair insertion and jump via [nvim-autopairs](https://github.com/windwp/nvim-autopairs). ++ Smarter and faster matching pair management (add, replace or delete) via [vim-sandwich](https://github.com/machakann/vim-sandwich). ++ Fast buffer jump via [hop.nvim](https://github.com/smoka7/hop.nvim). ++ Powerful snippet insertion via [Ultisnips](https://github.com/SirVer/ultisnips). ++ Beautiful statusline via [lualine.nvim](https://github.com/nvim-lualine/lualine.nvim). ++ File tree explorer via [nvim-tree.lua](https://github.com/nvim-tree/nvim-tree.lua). ++ Better quickfix list with [nvim-bqf](https://github.com/kevinhwang91/nvim-bqf). ++ Show search index and count with [nvim-hlslens](https://github.com/kevinhwang91/nvim-hlslens). ++ User-defined mapping hint via [which-key.nvim](https://github.com/folke/which-key.nvim). ++ Asynchronous code execution via [asyncrun.vim](https://github.com/skywind3000/asyncrun.vim). ++ Code highlighting via [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter). ++ Code editing using true nvim inside browser via [firenvim](https://github.com/glacambre/firenvim). ++ Beautiful colorscheme via [sainnhe/gruvbox-material](https://github.com/sainnhe/gruvbox-material) and other colorschemes. ++ Markdown previewing via [render-markdown.nvim](https://github.com/MeanderingProgrammer/render-markdown.nvim) ++ LaTeX editing and previewing via [vimtex](https://github.com/lervag/vimtex) ++ Animated GUI style notification via [nvim-notify](https://github.com/rcarriga/nvim-notify). ++ Tags navigation via [vista](https://github.com/liuchengxu/vista.vim). ++ Code folding with [nvim-ufo](https://github.com/kevinhwang91/nvim-ufo) and [statuscol.nvim](https://github.com/luukvbaal/statuscol.nvim) ++ ...... + +# UI Demo + +For more UI demos, check [here](https://github.com/jdhao/nvim-config/issues/15). + +## Start screen with dashboard-nvim + +

+ +

+ +## File fuzzy finding using fzf-lua + +

+ +

+ +## Code autocompletion with nvim-cmp + +

+ +

+ +## Git add, commit and push via fugitive.vim + +

+ +

+ +## Tags + +

+ +

+ +## Cursor jump via hop.nvim + +Go to a string starting with `se` + +

+ +

+ +## GUI-style notification with nvim-notify + +

+ +

+ +## code folding with nvim-ufo and statuscol.nvim + +

+ +

+ +# Shortcuts + +Some of the shortcuts I use frequently are listed here. In the following shortcuts, `` represents ASCII character `,`. + +| Shortcut | Mode | platform | Description | +|-------------------|---------------|-----------------|--------------------------------------------------------------------------| +| `ff` | Normal | Linux/macOS/Win | Fuzzy file searching in a floating window | +| `fh` | Normal | Linux/macOS/Win | Fuzzy help file grepping in a floating window | +| `fg` | Normal | Linux/macOS/Win | Fuzzy project-wide grepping in a floating window | +| `ft` | Normal | Linux/macOS/Win | Fuzzy buffer tag searching in a floating window | +| `fb` | Normal | Linux/macOS/Win | Fuzzy buffer switching in a floating window | +| `` | Normal | Linux/macOS/Win | Remove trailing white spaces | +| `v` | Normal | Linux/macOS/Win | Reselect last pasted text | +| `ev` | Normal | Linux/macOS/Win | Edit Nvim config in a new tabpage | +| `sv` | Normal | Linux/macOS/Win | Reload Nvim config | +| `q` | Normal | Linux/macOS/Win | Quit current window | +| `Q` | Normal | Linux/macOS/Win | Quit all window and close Nvim | +| `w` | Normal | Linux/macOS/Win | Save current buffer content | +| `y` | Normal | Linux/macOS/Win | Copy the content of entire buffer to default register | +| `cl` | Normal | Linux/macOS/Win | Toggle cursor column | +| `cd` | Normal | Linux/macOS/Win | Change current working directory to to the dir of current buffer | +| `t` | Normal | Linux/macOS/Win | Toggle tag window (show project tags in the right window) | +| `gs` | Normal | Linux/macOS/Win | Show Git status result | +| `gw` | Normal | Linux/macOS/Win | Run Git add for current file | +| `gc` | Normal | Linux/macOS/Win | Run git commit | +| `gpl` | Normal | Linux/macOS/Win | Run git pull | +| `gpu` | Normal | Linux/macOS/Win | Run git push | +| `gbd` | Normal | Linux/macOS/Win | Delete a branch | +| `gbn` | Normal | Linux/macOS/Win | Create a new branch | +| `gl` | Normal/Visual | Linux/macOS/Win | Get perm link for current/visually-select lines | +| `gbr` | Normal | macOS | Browse current git repo in browser | +| `gb` | Visual | macOS | Blame current line | +| `` | Normal | Linux/macOS/Win | Compile&run current source file (for C++, LaTeX, Lua, Python) | +| `` | Normal | Linux/macOS/Win | Toggle spell checking | +| `` | Normal | Linux/macOS/Win | Toggle paste mode | +| `\x` | Normal | Linux/macOS/Win | Close location or quickfix window | +| `\d` | Normal | Linux/macOS/Win | Close current buffer and go to previous buffer | +| `{count}gb` | Normal | Linux/macOS/Win | Go to buffer `{count}` or next buffer in the buffer list. | +| `{operator}iB` | Normal | Linux/macOS/Win | Operate in the whole buffer, `{operator}` can be `v`, `y`, `c`, `d` etc. | +| `Alt-k` | Normal | Linux/macOS/Win | Move current line or selected lines up | +| `Alt-j` | Normal | Linux/macOS/Win | Move current line or selected lines down | +| `ctrl-u` | Insert | Linux/macOS/Win | Turn word under cursor to upper case | +| `ctrl-t` | Insert | Linux/macOS/Win | Turn word under cursor to title case | +| `jk` | Insert | Linux/macOS/Win | Return to Normal mode without lagging | +| `ZR` | Normal | Linux/macOS/Win | Restart nvim without quitting | + + +# Custom commands + +In addition to commands provided by various plugins, I have also created some custom commands for personal use. + +| command | description | example | +|--------------|-------------------------------------------------------------------------|--------------------------------| +| `Redir` | capture command output to a tabpage for easier inspection. | `Redir hi` | +| `Edit` | edit multiple files at the same time, supports globing | `Edit *.vim` | +| `Datetime` | print current date and time or convert Unix time stamp to date and time | `Datetime 12345` or `Datetime` | +| `JSONFormat` | format a JSON file | `JSONFormat` | +| `CopyPath` | copy current file path to clipboard | `CopyPath relative` | + +# Contributing + +If you find anything that needs improving, do not hesitate to point it out or create a PR. + +If you come across an issue, you can first use `:checkhealth` command provided by `nvim` to trouble-shoot yourself. +Please read carefully the messages provided by health check. + +If you still have an issue, [open a new issue](https://github.com/jdhao/nvim-config/issues). + +# Further readings + +Some of the resources that I find helpful in mastering Nvim is documented [here](docs/nvim_resources.md). +You may also be interested in my posts on configuring Nvim [here](https://jdhao.github.io/categories/Nvim/). diff --git a/nvim/_config.yml b/nvim/_config.yml new file mode 100644 index 0000000..9da9a02 --- /dev/null +++ b/nvim/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-dinky \ No newline at end of file diff --git a/nvim/after/ftplugin/cpp.vim b/nvim/after/ftplugin/cpp.vim new file mode 100644 index 0000000..2e1cde0 --- /dev/null +++ b/nvim/after/ftplugin/cpp.vim @@ -0,0 +1,36 @@ +set commentstring=//\ %s + +" Disable inserting comment leader after hitting o or O or +set formatoptions-=o +set formatoptions-=r + +nnoremap :call compile_run_cpp() + +function! s:compile_run_cpp() abort + let src_path = expand('%:p:~') + let src_noext = expand('%:p:~:r') + " The building flags + let _flag = '-Wall -Wextra -std=c++11 -O2' + + if executable('clang++') + let prog = 'clang++' + elseif executable('g++') + let prog = 'g++' + else + echoerr 'No C++ compiler found on the system!' + endif + call s:create_term_buf('h', 20) + execute printf('term %s %s %s -o %s && %s', prog, _flag, src_path, src_noext, src_noext) + startinsert +endfunction + +function s:create_term_buf(_type, size) abort + set splitbelow + set splitright + if a:_type ==# 'v' + vnew + else + new + endif + execute 'resize ' . a:size +endfunction diff --git a/nvim/after/ftplugin/gitconfig.vim b/nvim/after/ftplugin/gitconfig.vim new file mode 100644 index 0000000..9c2e80a --- /dev/null +++ b/nvim/after/ftplugin/gitconfig.vim @@ -0,0 +1 @@ +set commentstring=#\ %s diff --git a/nvim/after/ftplugin/go.lua b/nvim/after/ftplugin/go.lua new file mode 100644 index 0000000..d28b7db --- /dev/null +++ b/nvim/after/ftplugin/go.lua @@ -0,0 +1,20 @@ +local opt = vim.opt + +-- General tab settings +opt.tabstop = 4 -- Number of visual spaces per TAB +opt.softtabstop = 4 -- Number of spaces in tab when editing +opt.shiftwidth = 4 -- Number of spaces to use for autoindent +opt.expandtab = false -- Expand tab to spaces so that tabs are spaces + +-- gofumpt adds more rule to gofmt, and is compatible with gofmt, +-- so also https://github.com/mvdan/gofumpt +vim.keymap.set("n", "f", function() + vim.cmd([[silent !gofumpt -w %]]) +end, { buffer = true, silent = true }) + +vim.keymap.set("n", "", function() + vim.cmd([[!go run %]]) +end, { + buffer = true, + silent = true, +}) diff --git a/nvim/after/ftplugin/help.lua b/nvim/after/ftplugin/help.lua new file mode 100644 index 0000000..2422dc6 --- /dev/null +++ b/nvim/after/ftplugin/help.lua @@ -0,0 +1,9 @@ +local win_width = vim.api.nvim_win_get_width(0) + +-- do not change layout if the screen is not wide enough +if win_width < 200 then + return +end + +-- L means to put window to leftmost +vim.cmd.wincmd([[L]]) diff --git a/nvim/after/ftplugin/javascript.vim b/nvim/after/ftplugin/javascript.vim new file mode 100644 index 0000000..3e27ee8 --- /dev/null +++ b/nvim/after/ftplugin/javascript.vim @@ -0,0 +1,3 @@ +" Disable inserting comment leader after hitting o or O or +set formatoptions-=o +set formatoptions-=r diff --git a/nvim/after/ftplugin/json.lua b/nvim/after/ftplugin/json.lua new file mode 100644 index 0000000..3bcf705 --- /dev/null +++ b/nvim/after/ftplugin/json.lua @@ -0,0 +1,4 @@ +vim.keymap.set({ "n", "v" }, "f", ":JSONFormat", { + buffer = true, + silent = true, +}) diff --git a/nvim/after/ftplugin/lua.lua b/nvim/after/ftplugin/lua.lua new file mode 100644 index 0000000..ce4f180 --- /dev/null +++ b/nvim/after/ftplugin/lua.lua @@ -0,0 +1,11 @@ +-- Disable inserting comment leader after hitting o/O/ +vim.opt_local.formatoptions:remove { "o", "r" } + +vim.keymap.set("n", "", "luafile %", { + buffer = true, + silent = true, +}) +vim.keymap.set("n", "f", "silent !stylua %", { + buffer = true, + silent = true, +}) diff --git a/nvim/after/ftplugin/man.lua b/nvim/after/ftplugin/man.lua new file mode 100644 index 0000000..b4806d1 --- /dev/null +++ b/nvim/after/ftplugin/man.lua @@ -0,0 +1,4 @@ +-- q to quit quickly +vim.keymap.set("n", "q", "q", { + desc = "quit nvim", +}) diff --git a/nvim/after/ftplugin/markdown.lua b/nvim/after/ftplugin/markdown.lua new file mode 100644 index 0000000..6fb7463 --- /dev/null +++ b/nvim/after/ftplugin/markdown.lua @@ -0,0 +1,107 @@ +local function add_reference_at_end(label, url, title) + vim.schedule(function() + local bufnr = vim.api.nvim_get_current_buf() + local line_count = vim.api.nvim_buf_line_count(bufnr) + + -- Prepare reference definition + local ref_def = "[" .. label .. "]: " .. url + if title and title ~= "" then + ref_def = ref_def .. ' "' .. title .. '"' + end + + -- Check if references section exists + local buffer_lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false) + + local has_ref_section = false + for _, line in ipairs(buffer_lines) do + if line:match("^%s*[%s]*$") then + has_ref_section = true + break + end + end + + local lines_to_add = {} + -- Add references header if it doesn't exist + if not has_ref_section then + if #lines_to_add == 0 then + table.insert(lines_to_add, "") + end + table.insert(lines_to_add, "") + end + + table.insert(lines_to_add, ref_def) + + -- Insert at buffer end + vim.api.nvim_buf_set_lines(bufnr, line_count, line_count, false, lines_to_add) + end) +end + +local function get_ref_link_labels() + local labels = {} + local seen = {} -- To avoid duplicates + local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) + + for _, line in ipairs(lines) do + -- Pattern explanation: + -- %[.-%] matches [link text] (non-greedy) + -- %[(.-)%] matches [label] and captures the label content + local start_pos = 1 + while start_pos <= #line do + local match_start, match_end, label = string.find(line, "%[.-%]%[(.-)%]", start_pos) + if not match_start then + break + end + + -- Only add unique labels + if label and label ~= "" and not seen[label] then + table.insert(labels, label) + seen[label] = true + end + + start_pos = match_end + 1 + end + end + + return labels +end + +local function count_consecutive_spaces(str) + -- Remove leading spaces first + local trimmed = str:match("^%s*(.*)") + local count = 0 + + -- Count each sequence of one or more consecutive spaces + for spaces in trimmed:gmatch("%s+") do + count = count + 1 + end + return count +end + +vim.api.nvim_buf_create_user_command(0, "AddRef", function(opts) + local args = vim.split(opts.args, " ", { trimempty = true }) + + if #args < 2 then + vim.print("Usage: :AddRef