Neovim やる
プログラマの教養、Vimをやる。新しいものが好きなのでNeovimにする。
とりあえずLanguage Server Protocolに基づいた補完が出ないとどうにもならないのでLSP周りを調べていく。
Neovimにはbuilt-inでLSPクライアントが搭載されていて、neovim/nvim-lspconfigを入れるといい感じの設定が入るらしい。
パッケージマネージャを導入するのがめんどくさいなあ。標準でも特定のパスにパッケージをぶち込めばいけるらしい。~/.config/nvim/pack/xxx/
に入れればいけるっぽいね。:set packpath
で把握できる。
最強のインストールコマンド
gh repo clone neovim/nvim-lspconfig ~/.config/nvim/pack/nvim-lspconfig
なるほど?
やっぱりプラグインが増えてくるとコードとして管理したいのでパッケージマネージャ入れるか〜、いやもしくはhome-managerとかいう方法もあるわけだが。
補完を出すためにはさらにパッケージが必要らしい。
スニペットプラグインというのも必要らしい。
:command
を使って :Format
のようなコマンドを定義できる。キーバインドを当てるほどでもないけどいざ打つときに :lua vim.lsp.buf.hogehoge
とか打つのはめんどくさいというような操作に便利そう。
:Tutor
やってる。dw
を打つと次の単語まで削除、d$
を打つと行末まで削除になるが、これは d
(delete) というoperatorに w
$
というmotionを組み合わせたものと解される。また dd
はよく使うので特別に1行削除に割り当てられている。
u
でundo、<C-r>
でredo。
p
P
で前に削除したテキストを貼り付けできる。c
は文字を削除してインサートモードに入る。/
で前方、?
で後方に検索。%
で対応する括弧に飛べる。
:s/thee/the
で現在の行の最初の thee
を the
に置き換える。:s/thee/the/g
ですべて置き換え、:%s/thee/the/g
でファイル全体。
:!ls
のようにしてシェルコマンドを実行する。v
でビジュアル選択モードに移行、カーソルを動かすと選択できる。その状態で :w
するとそこだけ保存できる。
:r ファイル名
でファイルの内容を展開できる。:r !ls
のようにしてコマンドの結果を展開できる。
v
でよしなに選択して y
でヤンク (コピー)、p
P
でペースト。yw
とかも使える。
tree-sitterというやつでシンタックスハイライトをより強力にできる (標準のハイライトは正規表現ベースらしい)。
VS CodeではGitHub Dark Defaultを使っていたのだが、
を使えばNeovimでも同じようなテーマが使えることがわかった。tree-sitterに対応している上に各ターミナル向けの色設定まであって最高。
-- Packages
require('packer').startup(function(use)
use 'wbthomason/packer.nvim'
use 'neovim/nvim-lspconfig'
use 'hrsh7th/nvim-cmp'
use 'hrsh7th/cmp-nvim-lsp'
use 'L3MON4D3/LuaSnip'
use 'saadparwaiz1/cmp_luasnip'
use 'lambdalisue/fern.vim'
use 'antoinemadec/FixCursorHold.nvim'
use 'nvim-treesitter/nvim-treesitter'
use 'projekt0n/github-nvim-theme'
use {
'nvim-telescope/telescope.nvim',
requires = {{'nvim-lua/plenary.nvim'}}
}
use {
'jose-elias-alvarez/null-ls.nvim',
requires = {{'nvim-lua/plenary.nvim'}}
}
use 'ray-x/lsp_signature.nvim'
use {
"folke/trouble.nvim",
requires = "kyazdani42/nvim-web-devicons",
config = function()
require'trouble'.setup {}
end
}
use 'machakann/vim-sandwich'
use 'windwp/nvim-autopairs'
use {
'nvim-neo-tree/neo-tree.nvim',
branch = 'v2.x',
requires = {
'nvim-lua/plenary.nvim',
'kyazdani42/nvim-web-devicons',
'MunifTanjim/nui.nvim',
}
}
end)
vim.cmd([[let g:neo_tree_remove_legacy_commands = 1]])
vim.cmd([[
augroup packer_user_config
autocmd!
autocmd BufWritePost init.lua source <afile> | PackerCompile
augroup end
]])
-- Autopairs
require'nvim-autopairs'.setup {}
-- Completions
local cmp_autopairs = require'nvim-autopairs.completion.cmp'
local cmp = require'cmp'
cmp.event:on('confirm_done', cmp_autopairs.on_confirm_done { map_char = { tex = '' } })
cmp.setup({
snippet = {
expand = function(args)
require('luasnip').lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
['<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({ select = true }),
}),
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'luasnip' },
})
})
-- Ex Commands
vim.cmd('command! Format :lua vim.lsp.buf.formatting()')
vim.cmd('command! -nargs=* Terminal vsplit | wincmd j | vertical resize 80 | terminal <args>')
-- Keybindings
local opts = { noremap = true, silent = true }
vim.api.nvim_set_keymap('n', '<Space>p', '<cmd>Telescope fd<CR>', opts)
vim.keymap.set('n', '<Space>e', '<cmd>Fern . -drawer <CR>')
vim.keymap.set('n', '<Space>t', '<cmd>Terminal<CR>')
vim.keymap.set('n', '<Space>f', '<cmd>Format<CR>')
-- Move focus
vim.keymap.set('n', '<Space>j', '<C-w>w')
vim.keymap.set('n', '<Space>k', '<C-w>W')
-- Language servers
local lsp_set_keymap = function(client, bufnr)
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
end
local servers = { 'rust_analyzer', 'ocamllsp', 'eslint', 'prismals'}
for _, lsp in pairs(servers) do
require('lspconfig')[lsp].setup {
on_attach = function(client, bufnr)
lsp_set_keymap(client, bufnr)
end,
}
end
-- In some languages we prefer to use external formatters (i.e. Prettier) rather than ones servers provide
local formatting_disabled_servers = { 'jsonls', 'html', 'cssls', 'volar', 'graphql', 'tsserver' }
for _, lsp in pairs(formatting_disabled_servers) do
require('lspconfig')[lsp].setup {
on_attach = function(client, bufnr)
lsp_set_keymap(client, bufnr)
client.resolved_capabilities.document_formatting = false
end,
}
end
-- lsp_signature
require'lsp_signature'.setup {}
-- null-ls
local nullls = require'null-ls'
nullls.setup {
sources = {
nullls.builtins.formatting.prettier,
},
}
-- Tree-sitter
require'nvim-treesitter.configs'.setup {
highlight = {
enable = true,
disable = {},
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "gnn",
node_incremental = "grn",
node_decremental = "grm",
},
},
ensure_installed = {
'bash',
'c',
'clojure',
'cpp',
'css',
'dockerfile',
'go',
'html',
'javascript',
'json',
'jsonc',
'lua',
'make',
'nix',
'ocaml',
'ocaml_interface',
'prisma',
'rust',
'scheme',
'toml',
'typescript',
'vue',
'yaml',
},
}
-- Color theme
require'github-theme'.setup {
theme_style = 'dark_default',
}
-- General configurations
vim.wo.number = true
vim.o.expandtab = true
vim.o.tabstop = 2
vim.o.shiftwidth = 0
-- Open terminal in insert mode
vim.cmd('autocmd TermOpen * startinsert')