NeoVimのLUA化

カテゴリー:  Tech タグ:  editor vim

今更ですが、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のようなモダンな 印象になりました。

コメント

Comments powered by Disqus