diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5d16d1c --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +update: + rm -rf ./nvim + mkdir nvim + cp -rf ~/.config/nvimexample/* ./nvim/ + diff --git a/README.md b/README.md index 29d6cc1..fbb4e22 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # Advent of `nvim` +Check the config in: `./nvim/` +- This should be versioned roughly by day, so you can go back and check how each day was made. +- You likely could copy this into `~/.config/` to get the same config as in the video, but I make no guarantees about that. + + 25 Mini Lessons to get started with Neovim. - We'll build a working configuration that resembles kickstart.nvim, but we'll do it completely from scratch. @@ -7,19 +12,22 @@ - [x] Tutor / Modal Editing - [x] Lua Configuration (Options / Keymaps) - [x] Plugin Manager -- `tree-sitter`, Colorschemes, and `statusline` -- LSP (Keymaps and Settings) +- [x] Filetype configuration +- `tree-sitter` +- [x] LSP (Keymaps and Settings) +- [x] Autoformat +- [x] Telescope +- [x] Advanced Telescope: multi-ripgrep +- [x] Window Navigation +- [x] Quickfix: `:cdo` and others +- [x] Terminal (Escape, Floating, Usages) +- [x] Autocomplete - LSP Installation / Management - Snippets -- Autoformat -- Autocomplete -- Telescope -- Quickfix: `:cdo` and others -- Oil.nvim - text-objects: `mini.*` - Tree-sitter: text-objects - Language Configuration -- Window Navigation - Clipboard -- Terminal (Escape, Floating, Usages) -- Advanced Telescope: multi-ripgrep +- Oil.nvim + - Already did a video: https://youtu.be/218PFRsvu2o?si=l8UFf2Z7YdUKU0KJ + - Not sure what else to say about it. diff --git a/XX - oil/Oil.md b/XX - oil/Oil.md new file mode 100644 index 0000000..e69de29 diff --git a/init.lua b/XX - oil/config/init.lua similarity index 100% rename from init.lua rename to XX - oil/config/init.lua diff --git a/XX - oil/config/lazy-lock.json b/XX - oil/config/lazy-lock.json new file mode 100644 index 0000000..e899446 --- /dev/null +++ b/XX - oil/config/lazy-lock.json @@ -0,0 +1,5 @@ +{ + "lazy.nvim": { "branch": "main", "commit": "7967abe55752aa90532e6bb4bd4663fe27a264cb" }, + "mini.nvim": { "branch": "main", "commit": "690a3b4c78c4956f7ecf770124b522d32084b872" }, + "tokyonight.nvim": { "branch": "main", "commit": "15d83cda572d7498b43bbdaa223bc75bf341183e" } +} diff --git a/XX - oil/config/lua/config/lazy.lua b/XX - oil/config/lua/config/lazy.lua new file mode 100644 index 0000000..2e0236a --- /dev/null +++ b/XX - oil/config/lua/config/lazy.lua @@ -0,0 +1,32 @@ +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local lazyrepo = "https://github.com/folke/lazy.nvim.git" + local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) + if vim.v.shell_error ~= 0 then + vim.api.nvim_echo({ + { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, + { out, "WarningMsg" }, + { "\nPress any key to exit..." }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end + +-- Hey! Put lazy into the runtimepath for neovim! +vim.opt.runtimepath:prepend(lazypath) + +-- Make sure to setup `mapleader` and `maplocalleader` before +-- loading lazy.nvim so that mappings are correct. +-- This is also a good place to setup other settings (vim.opt) +vim.g.mapleader = " " +vim.g.maplocalleader = "\\" + +-- Setup lazy.nvim +require("lazy").setup({ + spec = { + { "folke/tokyonight.nvim", config = function() vim.cmd.colorscheme "tokyonight" end }, + { import = "config.plugins" }, + }, +}) diff --git a/XX - oil/config/lua/config/plugins/mini.lua b/XX - oil/config/lua/config/plugins/mini.lua new file mode 100644 index 0000000..9f08259 --- /dev/null +++ b/XX - oil/config/lua/config/plugins/mini.lua @@ -0,0 +1,11 @@ +-- lua/custom/plugins/mini.lua +return { + { + 'echasnovski/mini.nvim', + enabled = true, + config = function() + local statusline = require 'mini.statusline' + statusline.setup { use_icons = true } + end + }, +} diff --git a/XX - oil/config/lua/config/plugins/oil.lua b/XX - oil/config/lua/config/plugins/oil.lua new file mode 100644 index 0000000..9f2ee38 --- /dev/null +++ b/XX - oil/config/lua/config/plugins/oil.lua @@ -0,0 +1,22 @@ +return { + { + "stevearc/oil.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = function() + require("oil").setup({ + columns = { "icon" }, + keymaps = { + [""] = false, + [""] = false, + [""] = false, + [""] = false, + [""] = "actions.select_split", + }, + view_options = { show_hidden = true }, + }) + + -- Open parent directory in current window + vim.keymap.set("n", "-", "Oil", { desc = "Open parent directory" }) + end, + }, +} diff --git a/nvim/after/ftplugin/lua.lua b/nvim/after/ftplugin/lua.lua new file mode 100644 index 0000000..c0e2391 --- /dev/null +++ b/nvim/after/ftplugin/lua.lua @@ -0,0 +1,5 @@ +local set = vim.opt_local + +set.shiftwidth = 2 +set.number = true +set.relativenumber = true diff --git a/nvim/init.lua b/nvim/init.lua new file mode 100644 index 0000000..0c8428e --- /dev/null +++ b/nvim/init.lua @@ -0,0 +1,59 @@ +print("advent of neovim") + +require("config.lazy") + +vim.opt.shiftwidth = 4 +vim.opt.clipboard = "unnamedplus" +vim.opt.number = true +vim.opt.relativenumber = true + +vim.keymap.set("n", "x", "source %") +vim.keymap.set("n", "x", ":.lua") +vim.keymap.set("v", "x", ":lua") + +vim.keymap.set("n", "", "cnext") +vim.keymap.set("n", "", "cprev") + +-- Highlight when yanking (copying) text +-- Try it with `yap` in normal mode +-- See `:help vim.highlight.on_yank()` +vim.api.nvim_create_autocmd("TextYankPost", { + desc = "Highlight when yanking (copying) text", + group = vim.api.nvim_create_augroup("kickstart-highlight-yank", { clear = true }), + callback = function() + vim.highlight.on_yank() + end, +}) + +vim.api.nvim_create_autocmd("TermOpen", { + group = vim.api.nvim_create_augroup("custom-term-open", { clear = true }), + callback = function() + vim.opt.number = false + vim.opt.relativenumber = false + end, +}) + +local job_id = 0 +vim.keymap.set("n", "to", function() + vim.cmd.vnew() + vim.cmd.term() + vim.cmd.wincmd("J") + vim.api.nvim_win_set_height(0, 5) + + job_id = vim.bo.channel +end) + +local current_command = "" +vim.keymap.set("n", "te", function() + current_command = vim.fn.input("Command: ") +end) + +vim.keymap.set("n", "tr", function() + if current_command == "" then + current_command = vim.fn.input("Command: ") + end + + vim.fn.chansend(job_id, { current_command .. "\r\n" }) +end) + +vim.keymap.set("n", "-", "Oil") diff --git a/nvim/lazy-lock.json b/nvim/lazy-lock.json new file mode 100644 index 0000000..769692b --- /dev/null +++ b/nvim/lazy-lock.json @@ -0,0 +1,15 @@ +{ + "blink.cmp": { "branch": "main", "commit": "ae5a4ce8f7e519e49de7ae6fcadd74547f820a52" }, + "friendly-snippets": { "branch": "main", "commit": "efff286dd74c22f731cdec26a70b46e5b203c619" }, + "lazy.nvim": { "branch": "main", "commit": "7e6c863bc7563efbdd757a310d17ebc95166cef3" }, + "lazydev.nvim": { "branch": "main", "commit": "f59bd14a852ca43db38e3662395354cb2a9b13e0" }, + "mini.icons": { "branch": "main", "commit": "44c0160526f7ae17ca8e8eab9ab235d047fcf7a6" }, + "mini.nvim": { "branch": "main", "commit": "7ebfab26d77a4b9b05aaae565907e7fa4b2ee154" }, + "nvim-lspconfig": { "branch": "master", "commit": "9f2c279cf9abe584f03bfeb37c6658d68e3ff49d" }, + "nvim-treesitter": { "branch": "master", "commit": "981ca7e353da6ea69eaafe4348fda5e800f9e1d8" }, + "oil.nvim": { "branch": "master", "commit": "dba037598843973b8c54bc5ce0318db4a0da439d" }, + "plenary.nvim": { "branch": "master", "commit": "2d9b06177a975543726ce5c73fca176cedbffe9d" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "dae2eac9d91464448b584c7949a31df8faefec56" }, + "telescope.nvim": { "branch": "master", "commit": "a0bbec21143c7bc5f8bb02e0005fa0b982edc026" }, + "tokyonight.nvim": { "branch": "main", "commit": "45d22cf0e1b93476d3b6d362d720412b3d34465c" } +} diff --git a/nvim/lua/config/lazy.lua b/nvim/lua/config/lazy.lua new file mode 100644 index 0000000..9178392 --- /dev/null +++ b/nvim/lua/config/lazy.lua @@ -0,0 +1,37 @@ +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local lazyrepo = "https://github.com/folke/lazy.nvim.git" + local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) + if vim.v.shell_error ~= 0 then + vim.api.nvim_echo({ + { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, + { out, "WarningMsg" }, + { "\nPress any key to exit..." }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end + +-- Hey! Put lazy into the runtimepath for neovim! +vim.opt.runtimepath:prepend(lazypath) + +-- Make sure to setup `mapleader` and `maplocalleader` before +-- loading lazy.nvim so that mappings are correct. +-- This is also a good place to setup other settings (vim.opt) +vim.g.mapleader = " " +vim.g.maplocalleader = "\\" + +-- Setup lazy.nvim +require("lazy").setup({ + spec = { + { "folke/tokyonight.nvim", config = function() vim.cmd.colorscheme "tokyonight" end }, + { import = "config.plugins" }, + }, + change_detection = { + -- automatically check for config file changes and reload the ui + enabled = false, + notify = false, -- get a notification when changes are found + }, +}) diff --git a/nvim/lua/config/plugins/completion.lua b/nvim/lua/config/plugins/completion.lua new file mode 100644 index 0000000..3f2e98b --- /dev/null +++ b/nvim/lua/config/plugins/completion.lua @@ -0,0 +1,19 @@ +return { + { + 'saghen/blink.cmp', + dependencies = 'rafamadriz/friendly-snippets', + + version = 'v0.*', + + opts = { + keymap = { preset = 'default' }, + + appearance = { + use_nvim_cmp_as_default = true, + nerd_font_variant = 'mono' + }, + + signature = { enabled = true } + }, + }, +} diff --git a/nvim/lua/config/plugins/lsp.lua b/nvim/lua/config/plugins/lsp.lua new file mode 100644 index 0000000..fcb5acd --- /dev/null +++ b/nvim/lua/config/plugins/lsp.lua @@ -0,0 +1,37 @@ +return { + { + "neovim/nvim-lspconfig", + dependencies = { + 'saghen/blink.cmp', + { + "folke/lazydev.nvim", + opts = { + library = { + { path = "${3rd}/luv/library", words = { "vim%.uv" } }, + }, + }, + }, + }, + config = function() + local capabilities = require('blink.cmp').get_lsp_capabilities() + require("lspconfig").lua_ls.setup { capabilites = capabilities } + + vim.api.nvim_create_autocmd('LspAttach', { + callback = function(args) + local c = vim.lsp.get_client_by_id(args.data.client_id) + if not c then return end + + if vim.bo.filetype == "lua" then + -- Format the current buffer on save + vim.api.nvim_create_autocmd('BufWritePre', { + buffer = args.buf, + callback = function() + vim.lsp.buf.format({ bufnr = args.buf, id = c.id }) + end, + }) + end + end, + }) + end, + } +} diff --git a/nvim/lua/config/plugins/mini.lua b/nvim/lua/config/plugins/mini.lua new file mode 100644 index 0000000..2640743 --- /dev/null +++ b/nvim/lua/config/plugins/mini.lua @@ -0,0 +1,11 @@ +-- lua/custom/plugins/mini.lua +return { + { + 'echasnovski/mini.nvim', + enabled = true, + config = function() + local statusline = require 'mini.statusline' + statusline.setup { use_icons = true } + end + }, +} diff --git a/nvim/lua/config/plugins/oil.lua b/nvim/lua/config/plugins/oil.lua new file mode 100644 index 0000000..5f8712a --- /dev/null +++ b/nvim/lua/config/plugins/oil.lua @@ -0,0 +1,11 @@ +return { + { + 'stevearc/oil.nvim', + ---@module 'oil' + ---@type oil.SetupOpts + opts = {}, + -- Optional dependencies + dependencies = { { "echasnovski/mini.icons", opts = {} } }, + -- dependencies = { "nvim-tree/nvim-web-devicons" }, -- use if prefer nvim-web-devicons + } +} diff --git a/nvim/lua/config/plugins/telescope.lua b/nvim/lua/config/plugins/telescope.lua new file mode 100644 index 0000000..ace4905 --- /dev/null +++ b/nvim/lua/config/plugins/telescope.lua @@ -0,0 +1,39 @@ +return { + { + 'nvim-telescope/telescope.nvim', + tag = '0.1.8', + dependencies = { + 'nvim-lua/plenary.nvim', + { 'nvim-telescope/telescope-fzf-native.nvim', build = 'make' } + }, + config = function() + require('telescope').setup { + pickers = { + find_files = { + theme = "ivy" + } + }, + extensions = { + fzf = {} + } + } + + require('telescope').load_extension('fzf') + + vim.keymap.set("n", "fh", require('telescope.builtin').help_tags) + vim.keymap.set("n", "fd", require('telescope.builtin').find_files) + vim.keymap.set("n", "en", function() + require('telescope.builtin').find_files { + cwd = vim.fn.stdpath("config") + } + end) + vim.keymap.set("n", "ep", function() + require('telescope.builtin').find_files { + cwd = vim.fs.joinpath(vim.fn.stdpath("data"), "lazy") + } + end) + + require "config.telescope.multigrep".setup() + end + } +} diff --git a/nvim/lua/config/plugins/treesitter.lua b/nvim/lua/config/plugins/treesitter.lua new file mode 100644 index 0000000..7323bfe --- /dev/null +++ b/nvim/lua/config/plugins/treesitter.lua @@ -0,0 +1,23 @@ +return { + { + "nvim-treesitter/nvim-treesitter", + build = ":TSUpdate", + config = function() + require'nvim-treesitter.configs'.setup { + ensure_installed = { "c", "lua", "vim", "vimdoc", "query", "markdown", "markdown_inline" }, + auto_install = false, + highlight = { + enable = true, + disable = function(lang, buf) + local max_filesize = 100 * 1024 -- 100 KB + local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf)) + if ok and stats and stats.size > max_filesize then + return true + end + end, + additional_vim_regex_highlighting = false, + }, + } + end, + } +} diff --git a/nvim/lua/config/telescope/multigrep.lua b/nvim/lua/config/telescope/multigrep.lua new file mode 100644 index 0000000..dd11bb8 --- /dev/null +++ b/nvim/lua/config/telescope/multigrep.lua @@ -0,0 +1,53 @@ +local pickers = require "telescope.pickers" +local finders = require "telescope.finders" +local make_entry = require "telescope.make_entry" +local conf = require "telescope.config".values + +local M = {} + +local live_multigrep = function(opts) + opts = opts or {} + opts.cwd = opts.cwd or vim.uv.cwd() + + local finder = finders.new_async_job { + command_generator = function(prompt) + if not prompt or prompt == "" then + return nil + end + + local pieces = vim.split(prompt, " ") + local args = { "rg" } + if pieces[1] then + table.insert(args, "-e") + table.insert(args, pieces[1]) + end + + if pieces[2] then + table.insert(args, "-g") + table.insert(args, pieces[2]) + end + + ---@diagnostic disable-next-line: deprecated + return vim.tbl_flatten { + args, + { "--color=never", "--no-heading", "--with-filename", "--line-number", "--column", "--smart-case" }, + } + end, + entry_maker = make_entry.gen_from_vimgrep(opts), + cwd = opts.cwd, + } + + pickers.new(opts, { + debounce = 100, + prompt_title = "Multi Grep", + finder = finder, + previewer = conf.grep_previewer(opts), + sorter = require("telescope.sorters").empty(), + }):find() +end + +M.setup = function() + vim.keymap.set("n", "fg", live_multigrep) +end + +return M diff --git a/nvim/plugin/floaterminal.lua b/nvim/plugin/floaterminal.lua new file mode 100644 index 0000000..53f7bdb --- /dev/null +++ b/nvim/plugin/floaterminal.lua @@ -0,0 +1,57 @@ +vim.keymap.set("t", "", "") + +local state = { + floating = { + buf = -1, + win = -1, + } +} + +local function create_floating_window(opts) + opts = opts or {} + local width = opts.width or math.floor(vim.o.columns * 0.8) + local height = opts.height or math.floor(vim.o.lines * 0.8) + + -- Calculate the position to center the window + local col = math.floor((vim.o.columns - width) / 2) + local row = math.floor((vim.o.lines - height) / 2) + + -- Create a buffer + local buf = nil + if vim.api.nvim_buf_is_valid(opts.buf) then + buf = opts.buf + else + buf = vim.api.nvim_create_buf(false, true) -- No file, scratch buffer + end + + -- Define window configuration + local win_config = { + relative = "editor", + width = width, + height = height, + col = col, + row = row, + style = "minimal", -- No borders or extra UI elements + border = "rounded", + } + + -- Create the floating window + local win = vim.api.nvim_open_win(buf, true, win_config) + + return { buf = buf, win = win } +end + +local toggle_terminal = function() + if not vim.api.nvim_win_is_valid(state.floating.win) then + state.floating = create_floating_window { buf = state.floating.buf } + if vim.bo[state.floating.buf].buftype ~= "terminal" then + vim.cmd.terminal() + end + else + vim.api.nvim_win_hide(state.floating.win) + end +end + +-- Example usage: +-- Create a floating window with default dimensions +vim.api.nvim_create_user_command("Floaterminal", toggle_terminal, {})