diff --git a/neovim.yml b/neovim.yml index d7bc811..4fddda8 100644 --- a/neovim.yml +++ b/neovim.yml @@ -1,31 +1,4 @@ - name: Install neovim from source hosts: odhosts - tasks: - - name: Clone neovim repository - ansible.builtin.git: - repo: https://github.com/neovim/neovim - dest: "{{ ansible_env.HOME }}/src/neovim" - version: v0.9.5 - - name: Install build dependencies - become: true - ansible.builtin.apt: - pkg: - - ninja-build - - gettext - - cmake - - unzip - - curl - - name: Build neovim - community.general.make: - chdir: "{{ ansible_env.HOME }}/src/neovim" - params: - CMAKE_BUILD_TYPE: Release - - name: Install neovim - become: true - community.general.make: - chdir: "{{ ansible_env.HOME }}/src/neovim" - target: install - - name: Clone my neovim configuration - ansible.builtin.git: - repo: https://github.com/ordinary-dev/ordinary-neovim - dest: "{{ ansible_env.HOME }}/.config/nvim" + roles: + - neovim diff --git a/roles/neovim/files/init.lua b/roles/neovim/files/init.lua new file mode 100644 index 0000000..f96d6e3 --- /dev/null +++ b/roles/neovim/files/init.lua @@ -0,0 +1,11 @@ +vim.g.mapleader = ' ' + +require('plugins') +require('lualine-cfg') +require('telescope-config') +require('treesitter-cfg') +require('lsp') +require('options') +require('git') +require('theme') +require('neo-tree-cfg') diff --git a/roles/neovim/files/lua/git.lua b/roles/neovim/files/lua/git.lua new file mode 100644 index 0000000..ed24c50 --- /dev/null +++ b/roles/neovim/files/lua/git.lua @@ -0,0 +1,18 @@ +-- Git decorations: signs for added, removed, and changed lines +local status, gitsigns = pcall(require, "gitsigns") +if (not status) then return end + +gitsigns.setup { + signcolumn = true, + on_attach = function(bufnr) + local gs = package.loaded.gitsigns + + vim.keymap.set('v', 'hs', function() + gs.stage_hunk { + vim.fn.line('.'), + vim.fn.line('v') + } + end, {}) + vim.keymap.set('n', 'tb', gs.toggle_current_line_blame, {}) + end +} diff --git a/roles/neovim/files/lua/lsp.lua b/roles/neovim/files/lua/lsp.lua new file mode 100644 index 0000000..c4f51d7 --- /dev/null +++ b/roles/neovim/files/lua/lsp.lua @@ -0,0 +1,84 @@ +local status, lspconfig = pcall(require, "lspconfig") +if not status then return end + +local util = require "lspconfig/util" + +local status, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") +if not status then return end + +local capabilities = cmp_nvim_lsp.default_capabilities() + +lspconfig.gopls.setup { + cmd = {"gopls", "serve"}, + filetypes = {"go", "gomod"}, + root_dir = util.root_pattern("go.work", "go.mod", ".git"), + settings = { + gopls = { + analyses = { + unusedparams = true, + }, + staticcheck = true, + }, + }, + capabilites = capabilites, +} + +lspconfig.rust_analyzer.setup { + -- Server-specific settings. See `:help lspconfig-setup` + settings = { + ['rust-analyzer'] = {}, + }, + capabilites = capabilites, +} + +lspconfig.tsserver.setup { +} + +vim.keymap.set('n', 'e', vim.diagnostic.open_float) +vim.keymap.set('n', '[d', vim.diagnostic.goto_prev) +vim.keymap.set('n', ']d', vim.diagnostic.goto_next) +vim.keymap.set('n', 'q', vim.diagnostic.setloclist) + +vim.api.nvim_create_autocmd('LspAttach', { + group = vim.api.nvim_create_augroup('UserLspConfig', {}), + callback = function(ev) + -- Enable completion triggered by + vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc' + + -- Buffer local mappings. + -- See `:help vim.lsp.*` for documentation on any of the below functions + local opts = { buffer = ev.buf } + vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, opts) + vim.keymap.set('n', 'gd', vim.lsp.buf.definition, opts) + vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts) + vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, opts) + vim.keymap.set('n', 'D', vim.lsp.buf.type_definition, opts) + vim.keymap.set('n', 'rn', vim.lsp.buf.rename, opts) + vim.keymap.set({ 'n', 'v' }, 'ca', vim.lsp.buf.code_action, opts) + vim.keymap.set('n', 'gr', vim.lsp.buf.references, opts) + end, +}) + +local status, lspsignature = pcall(require, "lsp_signature") +if not status then return end + +local cfg = {} +lspsignature.setup(cfg) + +local status, cmp = pcall(require, "cmp") +if not status then return end + +local status, luasnip = pcall(require, "luasnip") +if not status then return end + +cmp.setup { + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) + end, + }, + sources = { + { name = 'nvim_lsp' }, + { name = 'luasnip' }, + }, +} diff --git a/roles/neovim/files/lua/lualine-cfg.lua b/roles/neovim/files/lua/lualine-cfg.lua new file mode 100644 index 0000000..ab3ed03 --- /dev/null +++ b/roles/neovim/files/lua/lualine-cfg.lua @@ -0,0 +1,26 @@ +local status, lualine = pcall(require, "lualine") +if (not status) then return end + +lualine.setup { + options = { + icons_enabled = true, + theme = 'gruvbox_dark', + section_separators = '', + component_separators = '', + 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'} + }, +} diff --git a/roles/neovim/files/lua/neo-tree-cfg.lua b/roles/neovim/files/lua/neo-tree-cfg.lua new file mode 100644 index 0000000..9c6cab0 --- /dev/null +++ b/roles/neovim/files/lua/neo-tree-cfg.lua @@ -0,0 +1,15 @@ +local status, neotree = pcall(require, "neo-tree") +if not status then return end + +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"}) + +neotree.setup({ + close_if_last_window = true, + enable_git_status = false, +}) + +vim.keymap.set("n", "", ":Neotree reveal", {}) +vim.keymap.set("i", "", ":Neotree reveal", {}) diff --git a/roles/neovim/files/lua/options.lua b/roles/neovim/files/lua/options.lua new file mode 100644 index 0000000..f57bb54 --- /dev/null +++ b/roles/neovim/files/lua/options.lua @@ -0,0 +1,21 @@ +local options = { + clipboard = "unnamedplus", -- use system clipboard + wrap = true, -- wrap long lines + showmode = false, -- hide mode (-- INSERT --) + showmatch = true, -- show matching + ignorecase = true, -- case insensitive + hlsearch = true, -- highlight search + incsearch = true, -- incremental search + tabstop = 4, -- number of columns occupied by a tab + softtabstop = 4, -- see multiple spaces as tabstops so does the right thing + expandtab = true, -- converts tabs to white space + shiftwidth = 4, -- width for autoindents + autoindent = true, -- indent a new line the same amount as the line just typed + number = true, -- add line numbers + syntax = "enable", -- syntax highlighting + cursorline = true, -- highlight current cursorline +} + +for key, value in pairs(options) do + vim.opt[key] = value +end diff --git a/roles/neovim/files/lua/plugins.lua b/roles/neovim/files/lua/plugins.lua new file mode 100644 index 0000000..08e3abe --- /dev/null +++ b/roles/neovim/files/lua/plugins.lua @@ -0,0 +1,62 @@ +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) + +require("lazy").setup({ + -- Git + { 'lewis6991/gitsigns.nvim', tag = 'v0.6' }, + -- Lualine + { 'nvim-lualine/lualine.nvim' }, + -- Gruvbox theme + { 'ellisonleao/gruvbox.nvim' }, + + -- Telescope + { + 'nvim-telescope/telescope.nvim', + tag = '0.1.2', + dependencies = { + 'nvim-lua/plenary.nvim', + }, + }, + + -- Nvim-treesitter + { + 'nvim-treesitter/nvim-treesitter', + tag = 'v0.9.1', + init = function() + local ts_update = require('nvim-treesitter.install').update({ with_sync = true }) + ts_update() + end, + }, + + -- LSP + { 'neovim/nvim-lspconfig' }, + { 'ray-x/lsp_signature.nvim' }, + { + 'hrsh7th/nvim-cmp', + dependencies = { + 'hrsh7th/cmp-nvim-lsp', + { 'L3MON4D3/LuaSnip', version = "v2.*" }, + }, + }, + + -- Neo-tree + { + "nvim-neo-tree/neo-tree.nvim", + branch = "v3.x", + dependencies = { + 'nvim-lua/plenary.nvim', + 'nvim-tree/nvim-web-devicons', -- not strictly required, but recommended + 'MunifTanjim/nui.nvim', + }, + }, +}) diff --git a/roles/neovim/files/lua/telescope-config.lua b/roles/neovim/files/lua/telescope-config.lua new file mode 100644 index 0000000..6f8553a --- /dev/null +++ b/roles/neovim/files/lua/telescope-config.lua @@ -0,0 +1,30 @@ +local status, telescope = pcall(require, "telescope") +if not status then return end + +local telescopeConfig = require("telescope.config") + +-- Clone the default Telescope configuration +local vimgrep_arguments = { unpack(telescopeConfig.values.vimgrep_arguments) } + +-- I want to search in hidden/dot files. +table.insert(vimgrep_arguments, "--hidden") +-- I don't want to search in the `.git` directory. +table.insert(vimgrep_arguments, "--glob") +table.insert(vimgrep_arguments, "!**/.git/*") + +-- Keyboard shortcuts +vim.keymap.set("n", "", ":Telescope find_files", {}) +vim.keymap.set("i", "", ":Telescope find_files", {}) + +telescope.setup({ + defaults = { + -- `hidden = true` is not supported in text grep commands. + vimgrep_arguments = vimgrep_arguments, + }, + pickers = { + find_files = { + -- `hidden = true` will still show the inside of `.git/` as it's not `.gitignore`d. + find_command = { "rg", "--files", "--hidden", "--glob", "!**/.git/*" }, + }, + }, +}) diff --git a/roles/neovim/files/lua/theme.lua b/roles/neovim/files/lua/theme.lua new file mode 100644 index 0000000..7564d53 --- /dev/null +++ b/roles/neovim/files/lua/theme.lua @@ -0,0 +1,5 @@ +local status, gruvbox = pcall(require, "gruvbox") +if (not status) then return end + +vim.o.background = "dark" +vim.cmd([[colorscheme gruvbox]]) diff --git a/roles/neovim/files/lua/treesitter-cfg.lua b/roles/neovim/files/lua/treesitter-cfg.lua new file mode 100644 index 0000000..52801ed --- /dev/null +++ b/roles/neovim/files/lua/treesitter-cfg.lua @@ -0,0 +1,38 @@ +local status, configs = pcall(require, "nvim-treesitter.configs") +if not status then return end + +configs.setup { + ensure_installed = { + "bash", + "astro", + "c", + "dart", + "diff", + "dockerfile", + "dot", + "gdscript", + "gitcommit", "gitignore", "gitattributes", "git_rebase", "git_config", + "go", "gomod", + "graphql", + "html", "css", "scss", + "javascript", "typescript", "tsx", + "jsdoc", + "json", "json5", "jsonc", + "kotlin", + "lua", "luadoc", + "make", + "markdown", "markdown_inline", + "nix", + "python", + "ruby", + "rust", + "sql", + "vim", "vimdoc", + "yaml", "toml", "ini", + }, + sync_install = true, + highlight = { + enable = true, + additional_vim_regex_highlighting = false, + }, +} diff --git a/roles/neovim/tasks/main.yml b/roles/neovim/tasks/main.yml new file mode 100644 index 0000000..f1b85e1 --- /dev/null +++ b/roles/neovim/tasks/main.yml @@ -0,0 +1,47 @@ +- name: Check if neovim exists + stat: + path: /usr/local/bin/nvim + register: stat_result +- name: Clone neovim repository + when: not stat_result.stat.exists + ansible.builtin.git: + repo: https://github.com/neovim/neovim + dest: "{{ ansible_env.HOME }}/src/neovim" + version: v0.9.5 +- name: Install build dependencies + when: not stat_result.stat.exists + become: true + ansible.builtin.apt: + pkg: + - ninja-build + - gettext + - cmake + - unzip + - curl +- name: Build neovim + when: not stat_result.stat.exists + community.general.make: + chdir: "{{ ansible_env.HOME }}/src/neovim" + params: + CMAKE_BUILD_TYPE: Release +- name: Install neovim + when: not stat_result.stat.exists + become: true + community.general.make: + chdir: "{{ ansible_env.HOME }}/src/neovim" + target: install +- name: Create neovim config dir + ansible.builtin.file: + path: "{{ ansible_env.HOME }}/.config/nvim" + state: directory + mode: '1770' +- name: Copy init.lua + ansible.builtin.copy: + src: files/init.lua + dest: "{{ ansible_env.HOME }}/.config/nvim/init.lua" + mode: '0660' +- name: Copy the rest of neovim config + ansible.builtin.copy: + src: files/lua/ + dest: "{{ ansible_env.HOME }}/.config/nvim/lua/" + mode: '1770'