Well here it is, to answer my own question.
This is a demo with Ruby + solargraph and Go + gopls. Language with auto completion configured. This took me half a week, hopefully someone’d find it useful in the future, drop a reaction if you do.
(Sorry for inlining Lua configs, I am sure you can find a way to break it into multiple files)
home-manager.users.vee = { nixpkgs, pkgs, ... }: {
nixpkgs.config.allowUnfree = true;
home.packages = [
pkgs.google-chrome
pkgs.xclip
];
programs.bash.enable = true;
programs.git = {
enable = true;
userName = "Vee";
userEmail = "vee@gmail.com";
extraConfig = {
init.defaultBranch = "main";
};
};
# Neovim
programs.neovim = {
enable = true;
defaultEditor = true;
viAlias = true;
vimAlias = true;
plugins = with pkgs.vimPlugins; [
telescope-nvim
telescope-fzf-native-nvim
nvim-treesitter.withAllGrammars
harpoon
vim-fugitive
nvim-ufo
nvim-lspconfig
nvim-cmp
cmp-nvim-lsp
cmp-buffer
cmp-path
cmp-cmdline
];
extraPackages = with pkgs; [
# Ruby
ruby_3_4
rubyPackages_3_4.solargraph
# Go
# go
# gopls
];
extraLuaConfig = ''
-- Set
vim.opt.guicursor = ""
vim.opt.nu = true
vim.opt.relativenumber = true
vim.opt.tabstop = 2
vim.opt.softtabstop = 2
vim.opt.shiftwidth = 2
vim.opt.expandtab = true
vim.opt.autoindent = true
vim.opt.smartindent = true
-- vim.opt.tabstop = 4
-- vim.opt.softtabstop = 4
-- vim.opt.shiftwidth = 4
-- vim.opt.expandtab = false
-- vim.opt.autoindent = false
-- vim.opt.smartindent = false
-- vim.opt.wrap = false
-- vim.opt.swapfile = false
-- vim.opt.backup = false
-- vim.opt.undodir = os.getenv("HOME") .. "/.vim/undodir"
-- vim.opt.undofile = true
-- vim.opt.hlsearch = false
-- vim.opt.incsearch = true
-- vim.opt.termguicolors = true
vim.opt.scrolloff = 8
vim.opt.signcolumn = "yes"
vim.opt.isfname:append("@-@")
vim.opt.updatetime = 50
-- vim.opt.colorcolumn = "80"
-- Remap
vim.g.mapleader = " "
-- Open diagnostic (errors) floating window
vim.api.nvim_set_keymap('n', '<space>e', '<cmd>lua vim.diagnostic.open_float()<CR>',
{ noremap=true, silent=true }
)
-- Copy diagnostic (errors) into quickfix
vim.api.nvim_set_keymap('n', '<space>ce', '<cmd>lua vim.diagnostic.setqflist()<CR>', {})
-- Go back to the previous buffer
vim.keymap.set("n", "<leader>pb", "<C-^>")
-- Open the f*cking explorer
vim.keymap.set("n", "<leader>pv", vim.cmd.Ex)
-- Move the visually selected text down one line, reselect, and reindent
vim.keymap.set("v", "J", ":m '>+1<CR>gv=gv")
-- Move the visually selected text up two lines, reselect, and reindent
vim.keymap.set("v", "K", ":m '<-2<CR>gv=gv")
-- Move the current line down one position, reposition cursor, and reindent
vim.keymap.set("n", "J", "mzJ`z")
-- Scroll the view down by half the screen, keeping the cursor in the same position
vim.keymap.set("n", "<C-d>", "<C-d>zz")
-- Scroll the view up by half the screen, keeping the cursor in the same position
vim.keymap.set("n", "<C-u>", "<C-u>zz")
-- copy the selected text (visual mode)
-- then paste it multiple times!
vim.keymap.set("x", "<leader>p", [["_dP]])
-- copy the selected text (visual mode) into system clipboard
vim.keymap.set({"n", "v"}, "<leader>y", [["+y]])
-- copy the whole line (normal mode) into system clipboard
vim.keymap.set("n", "<leader>Y", [["+Y]])
-- Cutting text without being able to paste haha
vim.keymap.set({"n", "v"}, "<leader>d", [["_d]])
-- This is going to get me cancelled
vim.keymap.set("i", "<C-c>", "<Esc>")
vim.keymap.set("n", "Q", "<nop>")
vim.keymap.set("n", "<leader>f", vim.lsp.buf.format)
-- Search and replace in the entire file for the word under the cursor, case-insensitive
vim.keymap.set("n", "<leader>s", [[:%s/\<<C-r><C-w>\>/<C-r><C-w>/gI<Left><Left><Left>]])
-- Run the shell command "chmod +x" on the current file, and automatically save the changes
vim.keymap.set("n", "<leader>x", "<cmd>!chmod +x %<CR>", { silent = true })
-- ufo configurations
vim.o.foldcolumn = '1' -- '0' is not bad
vim.o.foldlevel = 99 -- Using ufo provider need a large value, feel free to decrease the value
vim.o.foldlevelstart = 99
vim.o.foldenable = true
-- Using ufo provider need remap `zR` and `zM`. If Neovim is 0.6.1, remap yourself
vim.keymap.set('n', 'zR', require('ufo').openAllFolds)
vim.keymap.set('n', 'zM', require('ufo').closeAllFolds)
-- kj movements
vim.keymap.set("n", "<C-k>", "<cmd>cnext<CR>zz")
vim.keymap.set("n", "<C-j>", "<cmd>cprev<CR>zz")
vim.keymap.set("n", "<leader>k", "<cmd>lnext<CR>zz")
vim.keymap.set("n", "<leader>j", "<cmd>lprev<CR>zz")
vim.keymap.set("n", "<leader><leader>", function()
vim.cmd("so")
end)
-- LSP keymap
vim.api.nvim_create_autocmd('LspAttach', {
callback = function(args)
local opts = {buffer = args.buf, remap = false}
vim.keymap.set("n", "gd", function() vim.lsp.buf.definition() end, opts)
vim.keymap.set("n", "K", function() vim.lsp.buf.hover() end, opts)
vim.keymap.set("n", "<leader>vws", function() vim.lsp.buf.workspace_symbol() end, opts)
vim.keymap.set("n", "<leader>vd", function() vim.diagnostic.open_float() end, opts)
vim.keymap.set("n", "[d", function() vim.diagnostic.goto_next() end, opts)
vim.keymap.set("n", "]d", function() vim.diagnostic.goto_prev() end, opts)
vim.keymap.set("n", "<leader>vca", function() vim.lsp.buf.code_action() end, opts)
vim.keymap.set("n", "<leader>vrr", function() vim.lsp.buf.references() end, opts)
vim.keymap.set("n", "<leader>vrn", function() vim.lsp.buf.rename() end, opts)
vim.keymap.set("i", "<C-h>", function() vim.lsp.buf.signature_help() end, opts)
vim.keymap.set({'n', 'x'}, "<leader>f", function()
vim.lsp.buf.format { async = true }
end, opts)
end
})
vim.diagnostic.config({
virtual_text = true
})
-- Completion
local cmp = require('cmp')
local cmp_select = {behavior = cmp.SelectBehavior.Select}
cmp.setup({
mapping = cmp.mapping.preset.insert({
['<C-p>'] = cmp.mapping.select_prev_item(cmp_select),
['<C-n>'] = cmp.mapping.select_next_item(cmp_select),
['<C-y>'] = cmp.mapping.confirm({ select = true }),
["<C-Space>"] = cmp.mapping.complete(),
['<Tab>'] = nil,
['<S-Tab>'] = nil
}),
sources = cmp.config.sources({
{ name = 'nvim_lsp' },
{ name = 'buffer' }
})
})
cmp.setup.cmdline(':', {
mapping = cmp.mapping.preset.cmdline(),
sources = cmp.config.sources({
{ name = 'path' },
{ name = 'cmdline' }
}),
matching = { disallow_symbol_nonprefix_matching = false }
})
-- LspConfig
-- local capabilities = require('cmp_nvim_lsp').default_capabilities()
local lspConfig = require('lspconfig')
lspConfig['solargraph'].setup {
capabilities = capabilities
}
-- lspConfig['gopls'].setup {
-- capabilities = capabilities
-- }
'';
};
# The state version is required and should stay at the version you
# originally installed.
home.stateVersion = "25.05";
};