❄️

【Neovim】2023年冬・使用しているNeovimプラグイン⛄️

2023/12/22に公開

こんにちは👋 daiki0381と申します!

私は普段コーディングのメインエディタとしてNeovimを使用しています。今回の記事では、私が使用しているNeovimプラグインを紹介したいと思います⛄️

https://github.com/daiki0381/dotfiles

ディレクトリ構造

📂 ~/.config/nvim
├── 📁 after
│  └── 📁 plugin
│     └── 🌑 alpha.rc.lua
│     └── 🌑 bufferline.rc.lua
│     └── 🌑 everforest.rc.lua
│     └── 🌑 git.rc.lua
│     └── 🌑 ibl.rc.lua
│     └── 🌑 lualine.rc.lua
│     └── 🌑 ibl.rc.lua
│     └── 🌑 noice.rc.lua
│     └── 🌑 ts-autotag.rc.lua
│     └── 🌑 autopairs.rc.lua
│     └── 🌑 cmp.rc.lua
│     └── 🌑 fidget.rc.lua
│     └── 🌑 gitsigns.rc.lua
│     └── 🌑 impatient.rc.lua
│     └── 🌑 neo-tree.rc.lua
│     └── 🌑 telescope.rc.lua
│     └── 🌑 treesitter.rc.lua
├── 📂 lua
│  └── 🌑 base.lua
│  └── 🌑 highlights.lua
│  └── 🌑 keymaps.lua
│  └── 🌑 plugins.lua
├── 📁 plugin
│  └── 🌑 lspconfig.rc.lua
│  └── 🌑 lspsaga.rc.lua     
│  └── 🌑 null-ls.rc.lua
│  └── 🌑 packer_compiled.lua
└── 🌑 init.lua

Neovim本体の設定

init.lua
require("base")
require("highlights")
require("keymaps")
require("plugins")
lua/base.lua
vim.cmd("autocmd!")
vim.cmd("syntax on")

vim.scriptencoding = "utf-8"
vim.opt.encoding = "utf-8"
vim.opt.fileencoding = "uft-8"

vim.wo.number = true
vim.wo.wrap = false

vim.opt.title = true
vim.opt.autoindent = true
vim.opt.hlsearch = true
vim.opt.backup = false
vim.opt.showcmd = true
vim.opt.cmdheight = 1
vim.opt.laststatus = 2
vim.opt.expandtab = true
vim.opt.scrolloff = 10
vim.opt.shell = "/bin/zsh"
vim.opt.backupskip = "/tmp/*,/private/tmp/*"
vim.opt.inccommand = "split"
vim.opt.ignorecase = true
vim.opt.smarttab = true
vim.opt.breakindent = true
vim.opt.shiftwidth = 2
vim.opt.tabstop = 2
vim.opt.ai = true
vim.opt.si = true
vim.opt.swapfile = false
vim.opt.clipboard = "unnamed"
vim.opt.backspace = "start,eol,indent"
vim.opt.path:append({ "**" })
vim.opt.formatoptions:append({ "r" })
vim.opt.wildignore:append({ "*/node_modules/*" })

vim.api.nvim_create_autocmd("InsertLeave", {
	pattern = "*",
	command = "set nopaste",
})
lua/highlights.lua
vim.opt.cursorline = true
vim.opt.termguicolors = true
vim.opt.winblend = 0
vim.opt.wildoptions = "pum"
vim.opt.pumblend = 5
vim.opt.background = "dark"
lua/keymaps.lua
local keymap = vim.keymap

keymap.set("i", "<C-j>", "<esc>")
keymap.set("v", "<C-j>", "<esc>")

keymap.set("n", "g[", ":vsplit<Return><C-w>w")
keymap.set("n", "g]", ":split<Return><C-w>w")
keymap.set("n", "gh", "<C-w>h")
keymap.set("n", "gj", "<C-w>j")
keymap.set("n", "gk", "<C-w>k")
keymap.set("n", "gl", "<C-w>l")
keymap.set("n", "rh", "<C-w><")
keymap.set("n", "rj", "<C-w>-")
keymap.set("n", "rk", "<C-w>+")
keymap.set("n", "rl", "<C-w>>")
keymap.set("n", "<C-e>", "<End>")
keymap.set("n", "<C-a>", "<Home>")

keymap.set("i", "<C-p>", "<Up>")
keymap.set("i", "<C-n>", "<Down>")
keymap.set("i", "<C-b>", "<Left>")
keymap.set("i", "<C-f>", "<Right>")
keymap.set("i", "<C-e>", "<End>")
keymap.set("i", "<C-a>", "<Home>")

keymap.set("v", "<C-e>", "<End>")
keymap.set("v", "<C-a>", "<Home>")
lua/plugins.lua
local status, packer = pcall(require, "packer")
if not status then
	return
end

vim.cmd([[packadd packer.nvim]])

packer.startup(function(use)
	-- plugin manager
	use("wbthomason/packer.nvim")
	-- startup screen
	use({
		"goolord/alpha-nvim",
		requires = "nvim-tree/nvim-web-devicons",
	})
	-- improve startup time
	use("lewis6991/impatient.nvim")
	-- color scheme
	use("neanias/everforest-nvim")
	-- status line
	use("hoob3rt/lualine.nvim")
	-- notice
	use({
		"folke/noice.nvim",
		requires = {
			"MunifTanjim/nui.nvim",
			"rcarriga/nvim-notify",
		},
	})
	-- indent highlight
	use("lukas-reineke/indent-blankline.nvim")
	-- syntax highlight
	use({
		"nvim-treesitter/nvim-treesitter",
		run = function()
			local ts_update = require("nvim-treesitter.install").update({ with_sync = true })
			ts_update()
		end,
	})
	-- git
	use("dinhhuy258/git.nvim")
	use("lewis6991/gitsigns.nvim")
	-- GitHub Copilot
	use("github/copilot.vim")
	-- auto pairs
	use("windwp/nvim-autopairs")
	-- auto tag
	use("windwp/nvim-ts-autotag")
	-- auto end
	use("RRethy/nvim-treesitter-endwise")
	-- tab
	use({
		"akinsho/bufferline.nvim",
		tag = "*",
		requires = "nvim-tree/nvim-web-devicons",
	})
	-- filer
	use({
		"nvim-neo-tree/neo-tree.nvim",
		branch = "v3.x",
		requires = {
			"nvim-lua/plenary.nvim",
			"nvim-tree/nvim-web-devicons",
			"MunifTanjim/nui.nvim",
			"3rd/image.nvim",
			{
				"s1n7ax/nvim-window-picker",
				version = "2.*",
			},
		},
	})
	-- fuzzy finder
	use({
		"nvim-telescope/telescope.nvim",
		tag = "0.1.5",
		requires = "nvim-lua/plenary.nvim",
	})
	-- LSP
	use({
		"williamboman/mason.nvim",
		"neovim/nvim-lspconfig",
		"williamboman/mason-lspconfig.nvim",
	})
	-- LSP completion
	use({
		"hrsh7th/nvim-cmp",
		"hrsh7th/cmp-nvim-lsp",
		"hrsh7th/cmp-buffer",
		"hrsh7th/cmp-path",
		"hrsh7th/cmp-cmdline",
		"hrsh7th/vim-vsnip",
		"hrsh7th/cmp-vsnip",
		"onsails/lspkind.nvim",
	})
	-- LSP UI
	use("nvimdev/lspsaga.nvim")
	-- LSP linter/formatter
	use("jay-babu/mason-null-ls.nvim")
	use({
		"nvimtools/none-ls.nvim",
		requires = "nvim-lua/plenary.nvim",
	})
end)

使用しているNeovimプラグイン

◯プラグインマネージャー : Packer.nvim

https://github.com/wbthomason/packer.nvim

lua/plugins.lua
local status, packer = pcall(require, "packer")
if not status then
	return
end

vim.cmd([[packadd packer.nvim]])

packer.startup(function(use)
  use 'wbthomason/packer.nvim'
  -- Your plugins go here
end)

下記のコマンドを実行することでプラグインをインストールすることができます。

:PackerInstall

◯起動画面 : alpha-nvim

https://github.com/goolord/alpha-nvim

after/plugin/alpha.rc.lua
local status, alpha = pcall(require, "alpha")
if not status then
	return
end

local dashboard = require("alpha.themes.dashboard")

-- Set header
dashboard.section.header.val = {
	"                                                     ",
	"  ███╗   ██╗███████╗ ██████╗ ██╗   ██╗██╗███╗   ███╗ ",
	"  ████╗  ██║██╔════╝██╔═══██╗██║   ██║██║████╗ ████║ ",
	"  ██╔██╗ ██║█████╗  ██║   ██║██║   ██║██║██╔████╔██║ ",
	"  ██║╚██╗██║██╔══╝  ██║   ██║╚██╗ ██╔╝██║██║╚██╔╝██║ ",
	"  ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ ",
	"  ╚═╝  ╚═══╝╚══════╝ ╚═════╝   ╚═══╝  ╚═╝╚═╝     ╚═╝ ",
	"                                                     ",
}

-- Set menu
dashboard.section.buttons.val = {
	dashboard.button("t", "  Neotree", ":Neotree toggle<Return>"),
	dashboard.button("n", "  New file", ":ene <BAR> startinsert <CR>"),
	dashboard.button("r", "  Recent file", ":Telescope oldfiles <CR>"),
	dashboard.button("f", "󰥨  Find file", ":Telescope find_files <CR>"),
	dashboard.button("g", "󰱼  Find text", ":Telescope live_grep <CR>"),
	dashboard.button("s", "  Settings", ":e $MYVIMRC | :cd %:p:h | split . | wincmd k | pwd<CR>"),
	dashboard.button("q", "  Quit", ":qa<CR>"),
}

-- Set footer
local function footer()
	local total_plugins = #vim.tbl_keys(packer_plugins)
	local datetime = os.date(" %Y-%m-%d   %H:%M:%S")
	local version = vim.version()
	local version_info = "   v" .. version.major .. "." .. version.minor .. "." .. version.patch
	return datetime .. "  ⚡" .. total_plugins .. " plugins" .. version_info
end
dashboard.section.footer.val = footer()

-- Send config to alpha
alpha.setup(dashboard.opts)

-- Disable folding on alpha buffer
vim.cmd([[autocmd FileType alpha setlocal nofoldenable]])

◯起動高速化 : impatient.nvim

https://github.com/lewis6991/impatient.nvim

after/plugin/impatient.rc.lua
local status, impatient = pcall(require, "impatient")
if not status then
	return
end

impatient.enable_profile()

下記のコマンドを実行して導入前と導入後の起動時間を計測してみます。

nvim --startuptime startup.log

導入前

startup.log
000.005  000.005: --- NVIM STARTING ---
000.077  000.073: event init
000.203  000.126: early init
000.697  000.494: locale set
... (略) ...
356.932  000.242  000.242: require('noice.ui.state')
357.580  000.609  000.609: require('noice.util.stats')
357.606  000.732: first screen update
357.607  000.001: --- NVIM STARTED ---

導入後

startup.log
000.005  000.005: --- NVIM STARTING ---
000.077  000.073: event init
000.203  000.126: early init
000.697  000.494: locale set
... (略) ...
192.968  000.050  000.050: require('noice.ui.state')
193.033  000.052  000.052: require('noice.util.stats')
193.041  000.566: first screen update
193.042  000.001: --- NVIM STARTED ---

◯カラースキーム : Everforest.nvim

https://github.com/neanias/everforest-nvim

after/plugin/everforest.rc.lua
vim.cmd([[colorscheme everforest]])

◯ステータスライン : lualine.nvim

https://github.com/nvim-lualine/lualine.nvim

after/plugin/lualine.rc.lua
local status, lualine = pcall(require, "lualine")
if not status then
	return
end

lualine.setup({
	options = {
		icons_enabled = true,
		theme = "everforest",
		section_separators = { left = "", right = "" },
		component_separators = { left = "", right = "" },
		disabled_filetypes = {},
	},
	sections = {
		lualine_a = { "mode" },
		lualine_b = { "branch" },
		lualine_c = { {
			"filename",
			file_status = true,
			path = 0,
		} },
		lualine_x = {
			{
				"diagnostics",
				sources = { "nvim_diagnostic" },
				symbols = { error = " ", warn = " ", info = " ", hint = " " },
			},
			"encoding",
			"filetype",
		},
		lualine_y = { "progress" },
		lualine_z = { "location" },
	},
	inactive_sections = {
		lualine_a = {},
		lualine_b = {},
		lualine_c = { {
			"filename",
			file_status = true,
			path = 1,
		} },
		lualine_x = { "location" },
		lualine_y = {},
		lualine_z = {},
	},
	tabline = {},
	extensions = { "fugitive" },
})

◯通知 : noice.nvim

https://github.com/folke/noice.nvim


Cmdline


Search


Message

after/plugin/noice.rc.lua
local status, noice = pcall(require, "noice")
if not status then
	return
end

noice.setup({
	lsp = {
		-- override markdown rendering so that **cmp** and other plugins use **Treesitter**
		override = {
			["vim.lsp.util.convert_input_to_markdown_lines"] = true,
			["vim.lsp.util.stylize_markdown"] = true,
			["cmp.entry.get_documentation"] = true,
		},
	},
	-- you can enable a preset for easier configuration
	presets = {
		bottom_search = false, -- use a classic bottom cmdline for search
		command_palette = false, -- position the cmdline and popupmenu together
		long_message_to_split = true, -- long messages will be sent to a split
		inc_rename = false, -- enables an input dialog for inc-rename.nvim
		lsp_doc_border = false, -- add a border to hover docs and signature help
	},
})

◯インデントハイライト : indent-blankline.nvim

https://github.com/lukas-reineke/indent-blankline.nvim

after/plugin/ibl.rc.lua
local status, ibl = pcall(require, "ibl")
if not status then
	return
end

local highlight = {
	"RainbowRed",
	"RainbowYellow",
	"RainbowBlue",
	"RainbowOrange",
	"RainbowGreen",
	"RainbowViolet",
	"RainbowCyan",
}

local hooks = require("ibl.hooks")
-- create the highlight groups in the highlight setup hook, so they are reset
-- every time the colorscheme changes
hooks.register(hooks.type.HIGHLIGHT_SETUP, function()
	vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#E06C75" })
	vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#E5C07B" })
	vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#61AFEF" })
	vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#D19A66" })
	vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#98C379" })
	vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C678DD" })
	vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#56B6C2" })
end)

ibl.setup({ indent = { highlight = highlight } })

◯構文ハイライト : nvim-treesitter

https://github.com/nvim-treesitter/nvim-treesitter


ruby


typescript

after/plugin/treesitter.rc.lua
local status, treesitter = pcall(require, "nvim-treesitter.configs")
if not status then
	return
end

treesitter.setup({
	highlight = {
		enable = true,
	},
	indent = {
		enable = true,
	},
	ensure_installed = "all",
})

下記のコマンドで構文ハイライトしたい言語をインストールします。

:TSInstall

◯Git : git.nvim/gitsigns.nvim

https://github.com/dinhhuy258/git.nvim
https://github.com/lewis6991/gitsigns.nvim


git.nvim


gitsigns.nvim

after/plugin/git.rc.lua
local status, git = pcall(require, "git")
if not status then
	return
end

git.setup({
	keymaps = {
		-- Open blame window
		blame = "gb",
		-- Close blame window
		quit_blame = "q",
		-- Open file/folder in git repository
		browse = "go",
		-- Opens a new diff that compares against the current index
		diff = "gd",
		-- Close git diff
		diff_close = "q",
	},
})
after/plugin/gitsigns.rc.lua
local status, gitsigns = pcall(require, "gitsigns")
if not status then
	return
end

gitsigns.setup({
	signs = {
		add = { text = "│" },
		change = { text = "│" },
		delete = { text = "_" },
		topdelete = { text = "‾" },
		changedelete = { text = "~" },
		untracked = { text = "┆" },
	},
	signcolumn = true, -- Toggle with `:Gitsigns toggle_signs`
	numhl = false, -- Toggle with `:Gitsigns toggle_numhl`
	linehl = false, -- Toggle with `:Gitsigns toggle_linehl`
	word_diff = false, -- Toggle with `:Gitsigns toggle_word_diff`
	watch_gitdir = {
		follow_files = true,
	},
	attach_to_untracked = true,
	current_line_blame = true, -- Toggle with `:Gitsigns toggle_current_line_blame`
	current_line_blame_opts = {
		virt_text = true,
		virt_text_pos = "eol", -- 'eol' | 'overlay' | 'right_align'
		delay = 1,
		ignore_whitespace = false,
		virt_text_priority = 100,
	},
	current_line_blame_formatter = "<author>, <author_time:%Y-%m-%d> - <summary>",
	sign_priority = 6,
	update_debounce = 100,
	status_formatter = nil, -- Use default
	max_file_length = 40000, -- Disable if file is longer than this (in lines)
	preview_config = {
		-- Options passed to nvim_open_win
		border = "single",
		style = "minimal",
		relative = "cursor",
		row = 0,
		col = 1,
	},
	yadm = {
		enable = false,
	},
})

◯GitHub Copilot : copilot.vim

https://github.com/github/copilot.vim

◯Auto Pairs : nvim-autopairs

https://github.com/windwp/nvim-autopairs

after/plugin/autopairs
local status, autopairs = pcall(require, "nvim-autopairs")
if not status then
	return
end

autopairs.setup({
	disable_filetype = { "TelescopePrompt" },
})

◯Auto Tag : nvim-ts-autotag

https://github.com/windwp/nvim-ts-autotag

after/plugin/ts-autotag.rc.lua
local status, autotag = pcall(require, "nvim-ts-autotag")
if not status then
	return
end

autotag.setup()
after/plugin/treesitter.rc.lua
local status, treesitter = pcall(require, "nvim-treesitter.configs")
if not status then
	return
end

treesitter.setup({
	highlight = {
		enable = true,
	},
	indent = {
		enable = true,
	},
	ensure_installed = "all",
	-- Add below
	autotag = {
		enable = true,
	},
})

◯Auto End : nvim-treesitter-endwise

https://github.com/RRethy/nvim-treesitter-endwise

after/plugin/treesitter.rc.lua
local status, treesitter = pcall(require, "nvim-treesitter.configs")
if not status then
	return
end

treesitter.setup({
	highlight = {
		enable = true,
	},
	indent = {
		enable = true,
	},
	ensure_installed = "all",
	-- Add below
	endwise = {
		enable = true,
	},
})

◯タブ : bufferline.nvim

https://github.com/akinsho/bufferline.nvim

after/plugin/bufferline.rc.lua
local status, bufferline = pcall(require, "bufferline")
if not status then
	return
end

bufferline.setup({
	options = {
		diagnostics = "nvim_lsp",
		offsets = {
			{
				filetype = "neo-tree",
				text = "󰥨 File Explorer",
				text_align = "left",
				separator = true,
			},
		},
	},
})

function close_current_buffer()
	local current_buffer_id = vim.fn.bufnr("%")
	vim.schedule(function()
		vim.cmd("bd " .. current_buffer_id)
	end)
end

vim.keymap.set("n", "<Tab>", "<Cmd>BufferLineCycleNext<CR>")
vim.keymap.set("n", "<C-x>", close_current_buffer)

◯ファイラ : Neo-tree.nvim

https://github.com/nvim-neo-tree/neo-tree.nvim

after/plugin/neo-tree.rc.lua
require("window-picker").setup({
	filter_rules = {
		include_current_win = false,
		autoselect_one = true,
		-- filter using buffer options
		bo = {
			-- if the file type is one of following, the window will be ignored
			filetype = { "neo-tree", "neo-tree-popup", "notify" },
			-- if the buffer type is one of following, the window will be ignored
			buftype = { "terminal", "quickfix" },
		},
	},
})

-- If you want icons for diagnostic errors, you'll need to define them somewhere:
vim.fn.sign_define("DiagnosticSignError", { text = " ", texthl = "DiagnosticSignError" })
vim.fn.sign_define("DiagnosticSignWarn", { text = " ", texthl = "DiagnosticSignWarn" })
vim.fn.sign_define("DiagnosticSignInfo", { text = " ", texthl = "DiagnosticSignInfo" })
vim.fn.sign_define("DiagnosticSignHint", { text = "󰌵", texthl = "DiagnosticSignHint" })

require("neo-tree").setup({
	close_if_last_window = false, -- Close Neo-tree if it is the last window left in the tab
	popup_border_style = "rounded",
	enable_git_status = true,
	enable_diagnostics = true,
	enable_normal_mode_for_inputs = false, -- Enable normal mode for input dialogs.
	open_files_do_not_replace_types = { "terminal", "trouble", "qf" }, -- when opening files, do not use windows containing these filetypes or buftypes
	sort_case_insensitive = false, -- used when sorting files and directories in the tree
	sort_function = nil, -- use a custom function for sorting files and directories in the tree
	-- sort_function = function (a,b)
	--       if a.type == b.type then
	--           return a.path > b.path
	--       else
	--           return a.type > b.type
	--       end
	--   end , -- this sorts files and directories descendantly
	default_component_configs = {
		container = {
			enable_character_fade = true,
		},
		indent = {
			indent_size = 2,
			padding = 1, -- extra padding on left hand side
			-- indent guides
			with_markers = true,
			indent_marker = "│",
			last_indent_marker = "└",
			highlight = "NeoTreeIndentMarker",
			-- expander config, needed for nesting files
			with_expanders = nil, -- if nil and file nesting is enabled, will enable expanders
			expander_collapsed = "",
			expander_expanded = "",
			expander_highlight = "NeoTreeExpander",
		},
		icon = {
			folder_closed = "",
			folder_open = "",
			folder_empty = "󰜌",
			-- The next two settings are only a fallback, if you use nvim-web-devicons and configure default icons there
			-- then these will never be used.
			default = "*",
			highlight = "NeoTreeFileIcon",
		},
		modified = {
			symbol = "[+]",
			highlight = "NeoTreeModified",
		},
		name = {
			trailing_slash = false,
			use_git_status_colors = true,
			highlight = "NeoTreeFileName",
		},
		git_status = {
			symbols = {
				-- Change type
				added = "✚", -- or "✚", but this is redundant info if you use git_status_colors on the name
				modified = "", -- or "", but this is redundant info if you use git_status_colors on the name
				deleted = "✖", -- this can only be used in the git_status source
				renamed = "󰁕", -- this can only be used in the git_status source
				-- Status type
				untracked = "",
				ignored = "",
				unstaged = "󰄱",
				staged = "",
				conflict = "",
			},
		},
		-- If you don't want to use these columns, you can set `enabled = false` for each of them individually
		file_size = {
			enabled = true,
			required_width = 64, -- min width of window required to show this column
		},
		type = {
			enabled = true,
			required_width = 122, -- min width of window required to show this column
		},
		last_modified = {
			enabled = true,
			required_width = 88, -- min width of window required to show this column
		},
		created = {
			enabled = true,
			required_width = 110, -- min width of window required to show this column
		},
		symlink_target = {
			enabled = false,
		},
	},
	-- A list of functions, each representing a global custom command
	-- that will be available in all sources (if not overridden in `opts[source_name].commands`)
	-- see `:h neo-tree-custom-commands-global`
	commands = {},
	window = {
		position = "left",
		width = 40,
		mapping_options = {
			noremap = true,
			nowait = true,
		},
		mappings = {
			["<space>"] = {
				"toggle_node",
				nowait = false, -- disable `nowait` if you have existing combos starting with this char that you want to use
			},
			["<2-LeftMouse>"] = "open",
			["<cr>"] = "open",
			["<esc>"] = "cancel", -- close preview or floating neo-tree window
			["P"] = { "toggle_preview", config = { use_float = true, use_image_nvim = true } },
			-- Read `# Preview Mode` for more information
			["l"] = "focus_preview",
			["S"] = "open_split",
			["s"] = "open_vsplit",
			-- ["S"] = "split_with_window_picker",
			-- ["s"] = "vsplit_with_window_picker",
			["t"] = "open_tabnew",
			-- ["<cr>"] = "open_drop",
			-- ["t"] = "open_tab_drop",
			["w"] = "open_with_window_picker",
			--["P"] = "toggle_preview", -- enter preview mode, which shows the current node without focusing
			["C"] = "close_node",
			-- ['C'] = 'close_all_subnodes',
			["z"] = "close_all_nodes",
			--["Z"] = "expand_all_nodes",
			["a"] = {
				"add",
				-- this command supports BASH style brace expansion ("x{a,b,c}" -> xa,xb,xc). see `:h neo-tree-file-actions` for details
				-- some commands may take optional config options, see `:h neo-tree-mappings` for details
				config = {
					show_path = "none", -- "none", "relative", "absolute"
				},
			},
			["A"] = "add_directory", -- also accepts the optional config.show_path option like "add". this also supports BASH style brace expansion.
			["d"] = "delete",
			["r"] = "rename",
			["y"] = "copy_to_clipboard",
			["x"] = "cut_to_clipboard",
			["p"] = "paste_from_clipboard",
			["c"] = "copy", -- takes text input for destination, also accepts the optional config.show_path option like "add":
			-- ["c"] = {
			--  "copy",
			--  config = {
			--    show_path = "none" -- "none", "relative", "absolute"
			--  }
			--}
			["m"] = "move", -- takes text input for destination, also accepts the optional config.show_path option like "add".
			["q"] = "close_window",
			["R"] = "refresh",
			["?"] = "show_help",
			["<"] = "prev_source",
			[">"] = "next_source",
			["i"] = "show_file_details",
		},
	},
	nesting_rules = {},
	filesystem = {
		filtered_items = {
			visible = false, -- when true, they will just be displayed differently than normal items
			hide_dotfiles = false,
			hide_gitignored = true,
			hide_hidden = true, -- only works on Windows for hidden files/directories
			hide_by_name = {
				--"node_modules"
			},
			hide_by_pattern = { -- uses glob style patterns
				--"*.meta",
				--"*/src/*/tsconfig.json",
			},
			always_show = { -- remains visible even if other settings would normally hide it
				--".gitignored",
			},
			never_show = { -- remains hidden even if visible is toggled to true, this overrides always_show
				--".DS_Store",
				--"thumbs.db"
			},
			never_show_by_pattern = { -- uses glob style patterns
				--".null-ls_*",
			},
		},
		follow_current_file = {
			enabled = true, -- This will find and focus the file in the active buffer every time
			--               -- the current file is changed while the tree is open.
			leave_dirs_open = false, -- `false` closes auto expanded dirs, such as with `:Neotree reveal`
		},
		group_empty_dirs = false, -- when true, empty folders will be grouped together
		hijack_netrw_behavior = "open_default", -- netrw disabled, opening a directory opens neo-tree
		-- in whatever position is specified in window.position
		-- "open_current",  -- netrw disabled, opening a directory opens within the
		-- window like netrw would, regardless of window.position
		-- "disabled",    -- netrw left alone, neo-tree does not handle opening dirs
		use_libuv_file_watcher = true, -- This will use the OS level file watchers to detect changes
		-- instead of relying on nvim autocmd events.
		window = {
			mappings = {
				["<bs>"] = "navigate_up",
				["."] = "set_root",
				["H"] = "toggle_hidden",
				["/"] = "fuzzy_finder",
				["D"] = "fuzzy_finder_directory",
				["#"] = "fuzzy_sorter", -- fuzzy sorting using the fzy algorithm
				-- ["D"] = "fuzzy_sorter_directory",
				["f"] = "filter_on_submit",
				["<c-x>"] = "clear_filter",
				["[g"] = "prev_git_modified",
				["]g"] = "next_git_modified",
				["o"] = { "show_help", nowait = false, config = { title = "Order by", prefix_key = "o" } },
				["oc"] = { "order_by_created", nowait = false },
				["od"] = { "order_by_diagnostics", nowait = false },
				["og"] = { "order_by_git_status", nowait = false },
				["om"] = { "order_by_modified", nowait = false },
				["on"] = { "order_by_name", nowait = false },
				["os"] = { "order_by_size", nowait = false },
				["ot"] = { "order_by_type", nowait = false },
			},
			fuzzy_finder_mappings = { -- define keymaps for filter popup window in fuzzy_finder_mode
				["<down>"] = "move_cursor_down",
				["<C-n>"] = "move_cursor_down",
				["<up>"] = "move_cursor_up",
				["<C-p>"] = "move_cursor_up",
			},
		},

		commands = {}, -- Add a custom command or override a global one using the same function name
	},
	buffers = {
		follow_current_file = {
			enabled = true, -- This will find and focus the file in the active buffer every time
			--              -- the current file is changed while the tree is open.
			leave_dirs_open = false, -- `false` closes auto expanded dirs, such as with `:Neotree reveal`
		},
		group_empty_dirs = true, -- when true, empty folders will be grouped together
		show_unloaded = true,
		window = {
			mappings = {
				["bd"] = "buffer_delete",
				["<bs>"] = "navigate_up",
				["."] = "set_root",
				["o"] = { "show_help", nowait = false, config = { title = "Order by", prefix_key = "o" } },
				["oc"] = { "order_by_created", nowait = false },
				["od"] = { "order_by_diagnostics", nowait = false },
				["om"] = { "order_by_modified", nowait = false },
				["on"] = { "order_by_name", nowait = false },
				["os"] = { "order_by_size", nowait = false },
				["ot"] = { "order_by_type", nowait = false },
			},
		},
	},
	git_status = {
		window = {
			position = "float",
			mappings = {
				["A"] = "git_add_all",
				["gu"] = "git_unstage_file",
				["ga"] = "git_add_file",
				["gr"] = "git_revert_file",
				["gc"] = "git_commit",
				["gp"] = "git_push",
				["gg"] = "git_commit_and_push",
				["o"] = { "show_help", nowait = false, config = { title = "Order by", prefix_key = "o" } },
				["oc"] = { "order_by_created", nowait = false },
				["od"] = { "order_by_diagnostics", nowait = false },
				["om"] = { "order_by_modified", nowait = false },
				["on"] = { "order_by_name", nowait = false },
				["os"] = { "order_by_size", nowait = false },
				["ot"] = { "order_by_type", nowait = false },
			},
		},
	},
})

package.path = package.path .. ";" .. vim.fn.expand("$HOME") .. "/.luarocks/share/lua/5.1/?/init.lua;"
package.path = package.path .. ";" .. vim.fn.expand("$HOME") .. "/.luarocks/share/lua/5.1/?.lua;"

require("image").setup({
  backend = "kitty",
  integrations = {
    markdown = {
      enabled = true,
      clear_in_insert_mode = false,
      download_remote_images = true,
      only_render_image_at_cursor = false,
      filetypes = { "markdown", "vimwiki" }, -- markdown extensions (ie. quarto) can go here
    },
    neorg = {
      enabled = true,
      clear_in_insert_mode = false,
      download_remote_images = true,
      only_render_image_at_cursor = false,
      filetypes = { "norg" },
    },
  },
  max_width = nil,
  max_height = nil,
  max_width_window_percentage = nil,
  max_height_window_percentage = 50,
  window_overlap_clear_enabled = false, -- toggles images when windows are overlapped
  window_overlap_clear_ft_ignore = { "cmp_menu", "cmp_docs", "" },
  editor_only_render_when_focused = false, -- auto show/hide images when the editor gains/looses focus
  tmux_show_only_in_active_window = false, -- auto show/hide images in the correct Tmux window (needs visual-activity off)
  hijack_file_patterns = { "*.png", "*.jpg", "*.jpeg", "*.gif", "*.webp" }, -- render image files as images when opened
})

vim.keymap.set("n", "<C-t>", ":Neotree toggle<Return>")
vim.keymap.set("v", "<C-t>", ":Neotree toggle<Return>")
vim.keymap.set("n", "<C-f>", ":Neotree focus<Return>")
vim.keymap.set("v", "<C-f>", ":Neotree focus<Return>")
vim.keymap.set("n", "gs", ":Neotree git_status<Return>")
vim.keymap.set("v", "gs", ":Neotree git_status<Return>")
vim.cmd([[nnoremap \ :Neotree reveal<cr>]])

◯Fuzzy Finder : telescope.nvim

https://github.com/nvim-telescope/telescope.nvim

after/plugin/telescope.rc.lua
local status, telescope = pcall(require, "telescope")
if not status then
	return
end

local actions = require("telescope.actions")
local builtin = require("telescope.builtin")

telescope.setup({
	defaults = {
		mappings = {
			n = {
				["<C-c>"] = actions.close,
			},
		},
	},
})

vim.keymap.set("n", ";f", function()
	builtin.find_files()
end)

vim.keymap.set("n", ";t", function()
	builtin.live_grep()
end)

vim.keymap.set("n", ";g", function()
	builtin.git_status()
end)

◯LSP (サーバー管理) : mason.nvim/nvim-lspconfig/mason-lspconfig.nvim

https://github.com/williamboman/mason.nvim
https://github.com/neovim/nvim-lspconfig
https://github.com/williamboman/mason-lspconfig.nvim


Mason (ダウンロードしているLSPサーバー一覧)

plugin/lspconfig
local status, lspconfig = pcall(require, "lspconfig")
if not status then
	return
end

lspconfig.flow.setup({})

local capabilities = require("cmp_nvim_lsp").default_capabilities()

require("mason").setup({
	ui = {
		border = "single",
	},
})
require("mason-lspconfig").setup()
require("mason-lspconfig").setup_handlers({
	function(server_name)
		lspconfig[server_name].setup({
			capabilities = capabilities,
		})
	end,
})

下記のコマンドでLSPサーバーをインストールします。

:MasonInstall

◯LSP (補完) : nvim-cmp/cmp-nvim-lsp/cmp-buffer/cmp-path/cmp-cmdline/vim-vsnip/cmp-vsnip/lspkind.nvim

https://github.com/hrsh7th/nvim-cmp
https://github.com/hrsh7th/cmp-nvim-lsp
https://github.com/hrsh7th/cmp-buffer
https://github.com/hrsh7th/cmp-path
https://github.com/hrsh7th/cmp-cmdline
https://github.com/hrsh7th/vim-vsnip
https://github.com/hrsh7th/cmp-vsnip
https://github.com/onsails/lspkind.nvim

after/plugin/cmp.rc.lua
local lspkind = require("lspkind")
local cmp = require("cmp")

cmp.setup({
	snippet = {
		expand = function(args)
			vim.fn["vsnip#anonymous"](args.body)
		end,
	},
	sources = {
		{ name = "nvim_lsp" },
		{ name = "vsnip" },
		{ name = "buffer" },
		{ name = "path" },
		{ name = "cmdline" },
	},
	window = {
		completion = cmp.config.window.bordered(),
		documentation = cmp.config.window.bordered(),
	},
	mapping = cmp.mapping.preset.insert({
		["<C-p>"] = cmp.mapping.select_prev_item(),
		["<C-n>"] = cmp.mapping.select_next_item(),
		["<C-l>"] = cmp.mapping.complete(),
		["<C-c>"] = cmp.mapping.abort(),
		["<C-y>"] = cmp.mapping.confirm({ select = true }),
	}),
	experimental = {
		ghost_text = false,
	},
	formatting = {
		format = lspkind.cmp_format({
			mode = "symbol",
			maxwidth = 50,
			ellipsis_char = "...",
		}),
	},
})

cmp.setup.cmdline("/", {
	mapping = cmp.mapping.preset.cmdline(),
	sources = {
		{ name = "buffer" },
	},
})

cmp.setup.cmdline(":", {
	mapping = cmp.mapping.preset.cmdline(),
	sources = {
		{ name = "path" },
		{ name = "cmdline" },
	},
})

◯LSP (UI) : lspsaga.nvim

https://github.com/nvimdev/lspsaga.nvim

plugin/lspsaga.rc.lua
local status, lspsaga = pcall(require, "lspsaga")
if not status then
	return
end

lspsaga.setup()

-- display variable/function information
vim.keymap.set("n", "K", "<Cmd>Lspsaga hover_doc<CR>")
-- go to function
vim.keymap.set("n", "gf", "<Cmd>Lspsaga goto_definition<CR>")
-- List variable/function
-- open keymap:'o'
vim.keymap.set("n", "fd", "<Cmd>Lspsaga finder tyd+ref+imp+def<CR>")

◯LSP (Linter/Formatter) : mason-null-ls.nvim/none-ls.nvim

https://github.com/jay-babu/mason-null-ls.nvim
https://github.com/nvimtools/none-ls.nvim

plugin/null-ls.rc.lua
require("mason-null-ls").setup({
	ensure_installed = { "stylua", "prettier" },
	handlers = {},
})

local status, null_ls = pcall(require, "null-ls")
if not status then
	return
end

null_ls.setup({
	sources = {
		null_ls.builtins.formatting.stylua,
		null_ls.builtins.diagnostics.eslint,
		null_ls.builtins.formatting.prettier.with({
			prefer_local = "node_modules/.bin",
		}),
	},
	debug = false,
})

vim.keymap.set("n", "ft", function()
	vim.lsp.buf.format({ async = true })
end)

styluaとprettierはMasonでインストールし、eslintは下記のコマンドでグローバルにインストールしています。

npm install -g eslint

Discussion