NeoVimのLUA化
今更ですが、NeoVimをLUA化しました。
NeoVimのLUA対応とプラグイン見直し
ずっと放置していたのですが、NeoVimの設定を全面的にLUAに移行しました。 ついでに沢山抱えてたプラグインを整理することにしました。
移行は次のような方針で行いました。
- VimScriptを廃して、設定はLUAで行う。
- プラグインもゼロベースで見直し、基本的にLUAベースのプラグインに移行する。
真っ新から作るのは辛いので、 kickstart.nvim
を参考にしました。ただし、Cloneするのでなく参考に留めています。もっとも異なる点は、
kickstart.nvimのほうはきれいにモジュール化していますが、わたしはそこまで複雑に
ならない想定で1つのinit.lua
にすべてを収めています。
プラグイン・マネージャー
プラグイン・マネージャーはずっとdeinを 利用していましたが、LUA化ということで新し目のLazy に移行しました。
Lazy自体の初期設定は次のようにします。
-- ============================================================================= -- = Install pacakge manager -- ============================================================================= local lazypath = vim.fn.stdpath('data') .. '/lazy/lazy.nvim' if not vim.loop.fs_stat(lazypath) then vim.fn.system({ 'git', 'clone', '--filter=blob:none', 'https://github.com/folke/lazy.nvim.git', '--branch=stable', -- latest stable release lazypath, }) end vim.opt.rtp:prepend(lazypath)
管理するプラグインは次のようにして設定します。
-- ============================================================================= -- = Load and configure plugins -- ============================================================================= require('lazy').setup({ -- NOTE: Here is where you install plugins that don't require any configuration { 'windwp/nvim-autopairs', event = 'InsertEnter', 'kkharji/sqlite.lua', },
プラグイン
唯一LUA化しなかったプラグイン
編集したファイルに更新日付を自動挿入するプラグインvim-script/autodate.vim
は、昔から使っておりよい代替もなかったのでそのまま使っています。
表示関連プラグイン
ずっとGruvboxを使用していましたが、Sublime Textのカラースキームを Monokai-Proに変更したので、NeoVimもMonokai-proに移行しました。 またlightlineに変えて、LuaLineに移行しました。
{ -- Colorscheme Monokai.pro -- https://github.com/loctvl842/monokai-pro.nvim 'loctvl842/monokai-pro.nvim',dependencies = { 'MunifTanjim/nui.nvim' }, lazy = false, priority = 1000, opts = {}, config = function() require('monokai-pro').setup({ transparent_background = false, terminal_colors = true, devicons = true, -- highlight the icons of `nvim-web-devicons` styles = { comment = { italic = true }, keyword = { italic = true }, -- any other keyword type = { italic = true }, -- (preferred) int, long, char, etc storageclass = { italic = true }, -- static, register, volatile, etc structure = { italic = true }, -- struct, union, enum, etc parameter = { italic = true }, -- parameter pass in function annotation = { italic = true }, tag_attribute = { italic = true }, -- attribute of tag in reactjs }, filter = 'pro', -- classic | octagon | pro | machine | ristretto | spectrum -- Enable this will disable filter option day_night = { enable = true, -- turn off by default day_filter = 'pro', -- classic | octagon | pro | machine | ristretto | spectrum night_filter = 'spectrum', -- classic | octagon | pro | machine | ristretto | spectrum }, inc_search = 'background', -- underline | background background_clear = { 'float_win', 'toggleterm', 'telescope', 'which-key', 'renamer' },-- 'float_win', 'toggleterm', 'telescope', 'which-key', 'renamer', 'neo-tree' plugins = { bufferline = { underline_selected = false, underline_visible = false, }, indent_blankline = { context_highlight = 'default', -- default | pro context_start_underline = false, }, }, ---@param c Colorscheme override = function(c) end, }) vim.cmd([[colorscheme monokai-pro]]) end, }, { -- Set lualine as statsuline 'nvim-lualine/lualine.nvim', event = 'VeryLazy', dependencies = { 'nvim-tree/nvim-web-devicons', 'folke/tokyonight.nvim',opt = true}, config = function() require('lualine').setup { options = { icons_enabled = true, theme = 'monokai-pro', component_separators = { left = '', right = ''}, section_separators = { left = '', right = ''}, disabled_filetypes = { statusline = {}, winbar = {}, }, ignore_focus = {}, always_divide_middle = true, globalstatus = false, refresh = { statusline = 1000, tabline = 1000, winbar = 1000, } }, sections = { lualine_a = {'mode'}, lualine_b = {'branch', 'diff', 'diagnostics'}, lualine_c = {'filename'}, lualine_x = {'encoding', 'fileformat', 'filetype'}, lualine_y = {'progress'}, lualine_z = {'location'} }, inactive_sections = { lualine_a = {}, lualine_b = {}, lualine_c = {'filename'}, lualine_x = {'location'}, lualine_y = {}, lualine_z = {} }, tabline = {}, winbar = {}, inactive_winbar = {}, extensions = {} } end, },
また、インデントの対応を視覚的に表わしてくれる次のプラグインを 利用しています。
{ -- Add indentation guides even on blank lines 'lukas-reineke/indent-blankline.nvim', opts = { char = '┊', show_trainling_blankline_ident = true, show_end_of_line = true, }, },
シンタックス・ハイライト関連プラグイン
Vimのシンタックス・ハイライトを改善するnvim-treesitterを導入しています。
{ -- Highligh, edit, and navigate code 'nvim-treesitter/nvim-treesitter', dependencies = { 'nvim-treesitter/nvim-treesitter-textobjects', }, event = { 'BufNewFile' , 'BufRead' }, build = ':TSUpdate', config = function() require('nvim-treesitter.configs').setup { ensure_installed = { 'bash', 'css', 'comment', 'diff', 'gitignore', 'go', 'html', 'ini', 'java', 'javascript', 'json', 'lua', 'markdown_inline', 'mermaid', 'python', 'rst', 'rust', 'scss', 'toml', 'typescript', 'vim', 'vue', 'yaml', }, highlight = { enable = true, additional_vim_regex_highlighting = false, }, } end, }, { -- The Vim plugin displays the context of the visible buffer contents. 'nvim-treesitter/nvim-treesitter-context', dependencies = { { 'nvim-treesitter/nvim-treesitter' }}, event = 'VeryLazy', config = function() require'treesitter-context'.setup { enable = true, -- Enable(Can be enabled/disabled later via commands) max_lines = 0, -- How many lines the window should span. -- Values <= 0 mean no limit. min_window_height = 0, -- Minimum editor window height to enable context. -- Values <= 0 mean no limit. line_numbers = true, multiline_threshold = 20, -- Maximum number of lines to collapse -- for a single context line trim_scope = 'outer', -- Which context lines to discard if `max_lines` -- is exceeded. Choices: 'inner', 'outer' mode = 'cursor', -- Line used to calculate context. -- Choices: 'cursor', 'topline' -- Separator between context and content. -- Should be a single character string, like '-'. -- When separator is set, the context will only show up when there are -- at least 2 lines above cursorline. separator = '~', zindex = 20, -- The Z-index of the context window on_attach = nil, -- (fun(buf: integer): boolean) return false to -- disable attaching } end, }, { -- Add/delete/change surrounding pairs 'kylechui/nvim-surround', dependencies = { 'nvim-treesitter/nvim-treesitter' }, version = '*', -- use for stability; omit to use `main` branch for the latest features event = 'VeryLazy', config = function() require('nvim-surround').setup({ -- configuration here, or leave empty to use defaults }) end },
Telescope関連プラグイン
Telescopeはいわばdduの代替です。ファイラーやバッファー一覧、候補一覧など、あらゆるもの一覧を表示してくれる ものです。
{ -- Telescope 'nvim-telescope/telescope.nvim', cmd = 'Telescope', dependencies = { { 'nvim-lua/popup.nvim' }, { 'nvim-lua/plenary.nvim' } } }, { 'nvim-telescope/telescope-media-files.nvim', config = function() require('telescope').load_extension('media_files') end, }, { 'nvim-telescope/telescope-file-browser.nvim', dependencies = { 'nvim-telescope/telescope.nvim', 'nvim-lua/plenary.nvim' } }, { 'nvim-telescope/telescope-frecency.nvim', config = function() require('telescope').load_extension('frecency') vim.api.nvim_set_keymap("n", "<leader>fq", "<Cmd>lua require('telescope').extensions.frecency.frecency()<CR>", {noremap = true, silent = true}) end, requires = { 'kkharji/sqlite.lua' }, },
補完関連プラグイン
補完系プラグインはcmpを使用しています。 補完系プラグインに関してはまだ整理中なので、大きく変わるかもしれません。
{ -- A completion engine plugin for neovim written in Lua. 'hrsh7th/nvim-cmp', event = 'InsertEnter, CmdlineEnter', dependencies = { 'L3MON4D3/LuaSnip', 'saadparwaiz1/cmp_luasnip', 'hrsh7th/cmp-nvim-lsp','rafamadriz/friendly-snippets', } }, {'hrsh7th/cmp-nvim-lsp', event = 'InsertEnter'}, {'hrsh7th/cmp-buffer', event = 'InsertEnter'}, {'hrsh7th/cmp-path', event = 'InsertEnter'}, {'hrsh7th/cmp-vsnip', event = 'InsertEnter'}, {'hrsh7th/cmp-cmdline', event = 'ModeChanged'}, --これだけは'ModeChanged'でなければまともに動かなかった。 {'hrsh7th/cmp-nvim-lsp-signature-help', event = 'InsertEnter'}, {'hrsh7th/cmp-nvim-lsp-document-symbol', event = 'InsertEnter'}, {'hrsh7th/cmp-calc', event = 'InsertEnter'}, {'onsails/lspkind.nvim', event = 'InsertEnter'}, {'hrsh7th/vim-vsnip', event = 'InsertEnter'}, {'hrsh7th/vim-vsnip-integ', event = 'InsertEnter'}, {'rafamadriz/friendly-snippets', event = 'InsertEnter'}, { -- Github Copilot 'zbirenbaum/copilot-cmp' }, { 'zbirenbaum/copilot.lua', config = function() require('copilot').setup({ suggestion = {enabled = false}, panel = {enabled = false}, }) require('copilot_cmp').setup() end, }, 〜〜中略〜〜 -- ============================================================================= -- = Configuration for cmp -- ============================================================================= local cmp = require('cmp') local lspkind = require('lspkind') cmp.setup({ snippet = { expand = function(args) vim.fn['vsnip#anonymous'](args.body) end }, window = { completion = cmp.config.window.bordered({ border = 'rounded' }), documentation = cmp.config.window.bordered({ border = 'rounded' }), }, mapping = cmp.mapping.preset.insert({ ['<Tab>'] = cmp.mapping.select_next_item(), ['<S-Tab>'] = cmp.mapping.select_prev_item(), ['<C-b>'] = cmp.mapping.scroll_docs(-4), ['<C-f>'] = cmp.mapping.scroll_docs(4), ['<C-Space>'] = cmp.mapping.complete(), ['<C-e>'] = cmp.mapping.abort(), ['<CR>'] = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false, }), }), formatting = { format = lspkind.cmp_format({ mode = 'symbol', maxwidth = 50, ellipsis_char = '...', }) }, sources = cmp.config.sources({ { name = 'skkeleton' }, { name = 'copilot'}, { name = 'nvim_lsp' }, { name = 'vsnip' }, { name = 'nvim_lsp_signature_help' }, { name = 'calc' }, }, { { name = 'buffer', keyword_length = 2 }, }) }) cmp.setup.cmdline({ '/', '?' }, { mapping = cmp.mapping.preset.cmdline(), sources = cmp.config.sources({ { name = 'nvim_lsp_document_symbol' } }, { { name = 'buffer' } }) }) cmp.setup.cmdline(':', { mapping = cmp.mapping.preset.cmdline(), sources = cmp.config.sources({ { name = 'path' } }, { { name = 'cmdline', keyword_length = 2 } }) }) local capabilities = require('cmp_nvim_lsp').default_capabilities() vim.cmd('let g:vsnip_filetypes = {}')
オプション関連
Vimのオプション設定ですが、以前のinit.vimでは次のように設定していました。
set imdisable " 元は noimdisable set ruler "右下に行・列番号を表示 set cmdheight=2 "コマンドラインに使われる行数 set showcmd "入力中のコマンドをステータスに表示する set title "タイトルをウィンドウ枠に表示する set scrolloff=999 "スクロールするときタイプライター的 set laststatus=2 "エディタウィンドウに2行目にステータスラインを常時表示 set showtabline=2
LUAではいろいろ表記方法はありますが、次のような表記で統一しました。
-- Search options vim.opt.ignorecase = true vim.opt.smartcase = true vim.opt.wrapscan = true vim.opt.incsearch = true -- incremental search vim.opt.inccommand = split -- split the screen when replacing to check vim.opt.infercase = ture -- case insensitive completion vim.opt.hlsearch = true -- 検索結果をハイライト -- Splits vim.opt.splitbelow = true vim.opt.splitright = true
まとめ
LUA化しましたが、LUA化自体よりもそれによりプラグイン・マネージャーや プラグイン自体を最新のトレンドに合せたのでなんだかVS Codeのようなモダンな 印象になりました。