dotfiles/nvim/init.lua

398 lines
10 KiB
Lua

-- vim: fdm=marker
--[[
# My Neovim configuration
The basic settings were adapted from kickstart.nvim's init.lua[^1].
[^1]: https://github.com/nvim-lua/kickstart.nvim/blob/master/init.lua
--]]
-- Disable netrw
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
-- Use <space> as the leader key (must be done before loading plugins)
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '
--{{{ Options
-- Indent with two spaces by default
vim.o.tabstop = 2
vim.o.shiftwidth = 2
vim.o.expandtab = true
-- Enable hybrid line numbers (current line absolute, others relative)
vim.o.number = true
vim.o.relativenumber = true
-- Enable mouse mode (I don't normally use it, but can't hurt)
vim.o.mouse = 'a'
-- Indent wrapped lines to the same level as the parent
vim.o.breakindent = true
-- Save undo history
vim.o.undofile = true
-- Use smart case for search (insensitive unless \C or capital letters present)
vim.o.ignorecase = true
vim.o.smartcase = true
-- Always display the signcolumn
vim.o.signcolumn = 'yes'
-- Lower update time
vim.o.updatetime = 250
-- Lower timeout for key sequences
vim.o.timeoutlen = 300
-- Configure how new splits should be opened
vim.o.splitright = true -- Left/right splits open to right of current
vim.o.splitbelow = true -- Up/down splits open below current
-- Display certain whitespace characters
vim.o.list = true
vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '' }
-- Preview substitutions live, while typing
vim.o.inccommand = 'split'
-- Highlight the current line
vim.o.cursorline = true
-- Minimal number of context lines to keep on screen
vim.o.scrolloff = 15
-- Get confirmation for certain operations instead of failing
vim.o.confirm = true
--}}}
--{{{ Keymaps
-- Use <C-[hjkl]> to navigate between splits
vim.keymap.set('n', '<c-h>', '<c-w>h')
vim.keymap.set('n', '<c-j>', '<c-w>j')
vim.keymap.set('n', '<c-k>', '<c-w>k')
vim.keymap.set('n', '<c-l>', '<c-w>l')
-- Use <leader>-[y|p] to yank to or put from the system clipboard
vim.keymap.set('v', '<leader>y', '"+y', { desc = 'Yank to system clipboard' })
vim.keymap.set('n', '<leader>p', '"+p', { desc = 'Put from system clipboard' })
-- Use <esc> or <C-c> to clear search highlights
vim.keymap.set('n', '<esc>', '<cmd>nohlsearch<cr>', { desc = 'Clear search highlights' })
-- Quickfix list
vim.keymap.set('n', '<leader>co', '<cmd>copen<cr>', { desc = 'Open quickfix list' })
vim.keymap.set('n', '<leader>cc', '<cmd>cclose<cr>', { desc = 'Close quickfix list' })
-- Location list
vim.keymap.set('n', '<leader>ls', vim.diagnostic.setloclist, { desc = 'Set (populate) location list' })
vim.keymap.set('n', '<leader>lo', '<cmd>lopen<cr>', { desc = 'Open location list' })
vim.keymap.set('n', '<leader>lc', '<cmd>lclose<cr>', { desc = 'Close location list' })
-- Exit terminal mode; use <c-\><c-n> if not
vim.keymap.set('t', '<esc><esc>', '<c-\\><c-n>', { desc = 'Exit terminal mode' })
--}}}
--{{{ Autocommands
-- Highlight when yanking (copying) text
vim.api.nvim_create_autocmd('TextYankPost', {
desc = 'Highlight when yanking text',
group = vim.api.nvim_create_augroup('grillades-highlight-yank', { clear = true }),
callback = function()
vim.hl.on_yank()
end,
})
--}}}
--{{{ Plugins (lazy.nvim)
-- Bootstrap lazy.nvim
-- This will return something like $XDG_DATA_HOME/lazy/lazy.nvim or equivalent
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
vim.opt.rtp:prepend(lazypath)
-- Configure lazy.nvim
require('lazy').setup({
spec = {
{
'folke/tokyonight.nvim',
lazy = false,
priority = 1000,
config = function()
vim.cmd 'colorscheme tokyonight-night'
end
},
{ 'tpope/vim-surround' },
{ 'justinmk/vim-sneak' },
{ 'tpope/vim-repeat' },
{ 'tpope/vim-commentary' },
{
'nvim-telescope/telescope.nvim', tag = '0.1.8',
dependencies = {
'nvim-lua/plenary.nvim',
{
'nvim-telescope/telescope-fzf-native.nvim',
build = 'make',
cond = function() return vim.fn.executable('make') == 1 end,
},
},
config = function()
local telescope = require('telescope')
local builtin = require('telescope.builtin')
telescope.setup({
defaults = {
layout_config = { prompt_position = 'top' },
sorting_strategy = 'ascending',
},
extensions = {
fzf = {
fuzzy = true,
override_generic_sorter = true,
override_file_sorter = true,
},
},
})
pcall(telescope.load_extension, 'fzf')
-- Keymaps
vim.keymap.set('n', '<leader>f', builtin.find_files, { desc = 'Find files' })
vim.keymap.set('n', '<leader>s', builtin.live_grep, { desc = 'Search files' })
vim.keymap.set('n', '<leader>b', builtin.buffers, { desc = 'Find buffer' })
vim.keymap.set('n', '<leader>h', builtin.help_tags, { desc = 'Search help' })
end,
},
{
'nvim-tree/nvim-tree.lua',
dependencies = { 'nvim-tree/nvim-web-devicons' },
config = function()
require('nvim-tree').setup({
sync_root_with_cwd = true,
respect_buf_cwd = true,
update_focused_file = {
enable = true,
update_root = true,
},
view = { width = 30 },
filters = { dotfiles = false },
git = { enable = true },
actions = {
open_file = { quit_on_open = true },
},
})
vim.keymap.set('n', '<leader>e', '<cmd>NvimTreeToggle<cr>', { desc = 'Toggle file explorer' })
end,
},
{
'nvim-treesitter/nvim-treesitter',
dependencies = {
'nvim-treesitter/nvim-treesitter-textobjects',
'nvim-treesitter/nvim-treesitter-context',
},
build = ':TSUpdate',
config = function()
require('nvim-treesitter.configs').setup({
ensure_installed = { 'lua', 'vim', 'ruby', 'bash', 'html', 'javascript' },
highlight = { enable = true },
indent = { enable = true },
textobjects = {
select = {
enable = true,
lookahead = true,
keymaps = {
['af'] = '@function.outer',
['if'] = '@function.inner',
['ac'] = '@class.outer',
['ic'] = '@class.inner',
['ab'] = '@block.outer',
['ib'] = '@block.inner',
},
},
move = {
enable = true,
set_jumps = true,
goto_next_start = {
[']f'] = '@function.outer',
[']c'] = '@class.outer',
[']b'] = '@block.outer',
},
goto_previous_start = {
['[f'] = '@function.outer',
['[c'] = '@class.outer',
['[b'] = '@block.outer',
},
},
},
})
end,
},
{
'neovim/nvim-lspconfig',
dependencies = {
'hrsh7th/cmp-nvim-lsp',
},
config = function()
local lspconfig = require('lspconfig')
local capabilities = require('cmp_nvim_lsp').default_capabilities()
-- Ruby
lspconfig.ruby_lsp.setup({
capabilities = capabilities,
})
-- Lua
lspconfig.lua_ls.setup({
capabilities = capabilities,
settings = {
Lua = {
workspace = { checkThirdParty = false },
telemetry = { enable = false },
},
},
})
-- JavaScript/TypeScript
lspconfig.ts_ls.setup({
capabilities = capabilities,
})
end,
},
{ 'lewis6991/gitsigns.nvim' },
{
'ahmedkhalf/project.nvim',
config = function()
local project_nvim = require('project_nvim')
project_nvim.setup({})
local telescope = require('telescope')
telescope.load_extension('projects')
vim.keymap.set('n', '<leader>q', telescope.extensions.projects.projects, { desc = 'Find files' })
end,
},
{
'hrsh7th/nvim-cmp',
dependencies = {
'hrsh7th/cmp-vsnip',
'hrsh7th/vim-vsnip',
'hrsh7th/cmp-buffer',
'hrsh7th/cmp-path',
'hrsh7th/cmp-cmdline',
'hrsh7th/cmp-nvim-lsp',
},
config = function()
local cmp = require('cmp')
cmp.setup({
snippet = {
expand = function(args)
vim.fn['vsnip#anonymous'](args.body)
end,
},
window = {
completion = cmp.config.window.bordered(),
documentation = cmp.config.window.bordered(),
},
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 = 'vsnip' },
{ name = 'path' },
}, {
{ name = 'buffer' },
}),
})
cmp.setup.cmdline(':', {
mapping = cmp.mapping.preset.cmdline(),
sources = {
{ name = 'path' },
{ name = 'cmdline' },
},
})
end,
},
{
"folke/trouble.nvim",
opts = {},
cmd = "Trouble",
keys = {
{
"<leader>xx",
"<cmd>Trouble diagnostics toggle<cr>",
desc = "Diagnostics (Trouble)",
},
},
},
{
"nvim-lualine/lualine.nvim",
dependencies = { "nvim-tree/nvim-web-devicons", opt = true },
config = function()
local lualine = require("lualine")
lualine.setup({
options = {
theme = 'tokyonight'
}
})
end,
},
},
install = {
-- Install missing plugins on startup
missing = true,
},
})
--}}}