-- Map leader "Global Key" to space, so you can use it optionally like spacemacs etc. vim.g.mapleader = " " vim.g.maplocalleader = " " -- Beautifully cursed, let's rebind C-x to the leader key and other respective emacs keybindings vim.cmd("map ") vim.cmd("map ") vim.cmd("imap ") vim.cmd("lmap ") vim.cmd("map ") -- Terminal Config -- Exit terminal mode with Esc -- vim.cmd("tnoremap ") vim.cmd("tnoremap ") -- Autostart in Insert mode vim.cmd("startinsert") -- Link system and neovim clipboard vim.api.nvim_set_option("clipboard", "unnamedplus") -- Lazy plugin manager require("config.lazy") -- Enable line numbers vim.cmd("set number") -- Turn off highlighting after search completion vim.cmd("set nohlsearch") -- Colourscheme vim.o.background = "light" -- or "dark" for dark mode vim.cmd("colorscheme gruvbox") -- Telescope setup (Like emacs ivy-mode) require('telescope').setup{ defaults = { -- ... }, pickers = { find_files = { theme = "ivy", } }, extensions = { -- ... } } -- Custom statusline (modeline) require('mini.statusline').setup() -- Custom filetypes configuration vim.api.nvim_create_autocmd({ 'BufEnter', 'BufNewFile' }, { pattern = '*ansible*.yml', command = 'set filetype=yaml.ansible', }) vim.api.nvim_create_autocmd({ 'BufEnter', 'BufNewFile' }, { pattern = '*playbook*.yml', command = 'set filetype=yaml.ansible', }) vim.api.nvim_create_autocmd({ 'BufEnter', 'BufNewFile' }, { pattern = '*server*.yml', command = 'set filetype=yaml.ansible', }) vim.api.nvim_create_autocmd({ 'BufEnter', 'BufNewFile' }, { pattern = '*service*.yml', command = 'set filetype=yaml.ansible', }) vim.api.nvim_create_autocmd({ 'BufEnter', 'BufNewFile' }, { pattern = '*compose*.yml', command = 'set filetype=yaml.docker-compose', }) -- LSP Configuration local lsp_zero = require('lsp-zero') -- https://lsp-zero.netlify.app/v3.x/language-server-configuration.html#default-keybindings lsp_zero.on_attach(function(client, bufnr) lsp_zero.default_keymaps({ buffer = bufnr, preserve_mappings = false }) end) local lspconfig = require('lspconfig') lspconfig.lua_ls.setup({}) lspconfig.bashls.setup({}) lspconfig.clangd.setup({}) lspconfig.tsserver.setup({}) lspconfig.jedi_language_server.setup({}) lspconfig.nixd.setup({}) lspconfig.nginx_language_server.setup({}) lspconfig.docker_compose_language_service.setup({}) lspconfig.ansiblels.setup({}) -- lspconfig.yamlls.setup({ -- settings = { -- yaml = { -- schemas = { -- ["https://json.schemastore.org/github-workflow.json"] = "/.github/workflows/*", -- ["https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/ansible.json#/$defs/playbook"] = "**/*playbook*.yaml", -- ["https://raw.githubusercontent.com/ansible/ansible-lint/main/src/ansiblelint/schemas/inventory.json"] = "**/*hosts*.yaml", -- }, -- }, -- } -- }) lspconfig.emmet_language_server.setup({ filetypes = { "css", "eruby", "html", "javascript", "javascriptreact", "less", "sass", "scss", "pug", "typescriptreact" }, -- Read more about this options in the [vscode docs](https://code.visualstudio.com/docs/editor/emmet#_emmet-configuration). -- **Note:** only the options listed in the table are supported. init_options = { ---@type table includeLanguages = {}, --- @type string[] excludeLanguages = {}, --- @type string[] extensionsPath = {}, --- @type table [Emmet Docs](https://docs.emmet.io/customization/preferences/) preferences = {}, --- @type boolean Defaults to `true` showAbbreviationSuggestions = true, --- @type "always" | "never" Defaults to `"always"` showExpandedAbbreviation = "always", --- @type boolean Defaults to `false` showSuggestionsAsSnippets = false, --- @type table [Emmet Docs](https://docs.emmet.io/customization/syntax-profiles/) syntaxProfiles = {}, --- @type table [Emmet Docs](https://docs.emmet.io/customization/snippets/#variables) variables = {}, }, }) --Enable (broadcasting) snippet capability for completion local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities.textDocument.completion.completionItem.snippetSupport = true lspconfig.cssls.setup { capabilities = capabilities, } lspconfig.jsonls.setup { capabilities = capabilities, } local cmp = require('cmp') cmp.setup({ sources = { {name = 'nvim_lsp'}, }, mapping = { [''] = cmp.mapping.confirm({select = true}), [''] = cmp.mapping.abort(), [''] = cmp.mapping.select_prev_item({behavior = 'select'}), [''] = cmp.mapping.select_prev_item({behavior = 'select'}), [''] = cmp.mapping.select_next_item({behavior = 'select'}), [''] = cmp.mapping.select_next_item({behavior = 'select'}), [''] = cmp.mapping(function() if cmp.visible() then cmp.select_prev_item({behavior = 'insert'}) else cmp.complete() end end), [''] = cmp.mapping(function() if cmp.visible() then cmp.select_next_item({behavior = 'insert'}) else cmp.complete() end end), }, snippet = { expand = function(args) require('luasnip').lsp_expand(args.body) end, }, }) -- DAP Configuration local dap = require("dap") local dapwidgets = require("dap.ui.widgets") local dapwidgetscope = dapwidgets.sidebar(dapwidgets.scopes) local daprunning = false -- Functions to initialise Dap, open UI widgets and set helper keybindings local function dapInit() dap.repl.open() dapwidgetscope.open() daprunning = true -- Can't get these working! -- vim.keymap.del({"n", "v", "o"}, "") -- vim.keymap.set({"n", "v", "o"}, "", "ln") -- vim.keymap.set({"n", "v", "o"}, "", "ln") -- vim.keymap.set({"n", "v", "o"}, "", "ln") -- vim.keymap.set({"n", "v", "o"}, "", "ln") vim.cmd("unmap ") vim.cmd("map dn") vim.cmd("map di") vim.cmd("map dr") vim.cmd("map ds") print("Initialised debugger successfully") end local function dapCleanup() dap.repl.close() dapwidgetscope.close() daprunning = false vim.cmd("unmap ") vim.cmd("unmap ") vim.cmd("unmap ") vim.cmd("unmap ") vim.keymap.set({"n", "v", "o"}, '', 'Telescope live_grep') -- vim.keymap.del({"n", "v", "o"}, "") -- vim.keymap.del({"n", "v", "o"}, "") -- vim.keymap.del({"n", "v", "o"}, "") -- vim.keymap.del({"n", "v", "o"}, "") -- vim.keymap.set({"n", "v", "o"}, '', 'Telescope live_grep') print("Cleaned up debugger successfully") end -- DAP Server configurations -- C DAP Configuration dap.adapters.gdb = { type = "executable", command = "gdb", args = { "-i", "dap" } } dap.configurations.c = { { name = "Launch", type = "gdb", request = "launch", program = function() return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') end, cwd = "${workspaceFolder}", stopAtBeginningOfMainSubprogram = false, }, } -- Discord Rich Presence -- The setup config table shows all available config options with their default values: -- require("neocord").setup({ -- -- General options -- logo = "auto", -- "auto" or url -- logo_tooltip = nil, -- nil or string -- main_image = "language", -- "language" or "logo" -- client_id = "1157438221865717891", -- Use your own Discord application client id (not recommended) -- log_level = "debug", -- Log messages at or above this level (one of the following: "debug", "info", "warn", "error") -- debounce_timeout = 10, -- Number of seconds to debounce events (or calls to `:lua package.loaded.presence:update(, true)`) -- blacklist = {}, -- A list of strings or Lua patterns that disable Rich Presence if the current file name, path, or workspace matches -- file_assets = {}, -- Custom file asset definitions keyed by file names and extensions (see default config at `lua/presence/file_assets.lua` for reference) -- show_time = true, -- Show the timer -- global_timer = false, -- if set true, timer won't update when any event are triggered -- -- -- Rich Presence text options -- editing_text = "Editing %s", -- Format string rendered when an editable file is loaded in the buffer (either string or function(filename: string): string) -- file_explorer_text = "Browsing %s", -- Format string rendered when browsing a file explorer (either string or function(file_explorer_name: string): string) -- git_commit_text = "Committing changes", -- Format string rendered when committing changes in git (either string or function(filename: string): string) -- plugin_manager_text = "Managing plugins", -- Format string rendered when managing plugins (either string or function(plugin_manager_name: string): string) -- reading_text = "Reading %s", -- Format string rendered when a read-only or unmodifiable file is loaded in the buffer (either string or function(filename: string): string) -- workspace_text = "Working on %s", -- Format string rendered when in a git repository (either string or function(project_name: string|nil, filename: string): string) -- line_number_text = "Line %s out of %s", -- Format string rendered when `enable_line_number` is set to true (either string or function(line_number: number, line_count: number): string) -- terminal_text = "Using Terminal", -- Format string rendered when in terminal mode. -- }) -- Remake of emacs which-key mode, I'll add all custom keybinds here -- TODO: The DAP related functions should be moved into their own respective file/modularised better! require("which-key").add ({ { "", "Telescope live_grep" , desc = "Swiper", mode = "n" }, -- This does not allow you to make a new file only search existing, but good enough for now. { "", "Telescope find_files" , desc = "Find File", mode = "n" }, -- To properly remake the Emacs ivy buffer command, we should figure out how to combine Telescope buffers and Telescope oldfiles -- This is good enough for now { "b", "Telescope oldfiles" , desc = "Recently opened files", mode = "n" }, { "", "Telescope buffers" , desc = "Buffers", mode = "n" }, { "k", "bp|bd#" , desc = "Close current buffer", mode = "n" }, { "0", "close", desc = "Close focused window" }, { "2", "split", desc = "Split window horizontally" }, { "3", "vs", desc = "Split window vertically" }, { "o", "wincmd w", desc = "Switch to next window" }, { -- Nested mappings are allowed and can be added in any order -- Most attributes can be inherited or overridden on any level -- There's no limit to the depth of nesting mode = { "n", "v" }, -- NORMAL and VISUAL mode { "", "qa", desc = "Quit" }, { "", "w", desc = "Write" }, }, -- LSP/DAP Options { mode = { "n", "v" }, -- NORMAL and VISUAL mode { "db", function() dap.toggle_breakpoint() end, desc = "Debugger: Toggle breakpoint" }, { "dd", function() if daprunning == false then if pcall(function() dap.continue() end) then dapInit() else print("Debugger failed to start!") daprunning = false end else print("Debugger already running!") end end, desc = "Debugger: Run" }, { "dD", function() if daprunning == false then if pcall(function() dap.run_last() end) then dapInit() print("Started debugger from previous configuration successfully") else print("Debugger failed to start!") daprunning = false end else print("Debugger already running!") end end, desc = "Debugger: Run last configuration again" }, { "ds", function() if daprunning == true then if pcall(function() dap.terminate() end) then dapCleanup() print("Stopped debugger successfully") else daprunning = true end else print("Debugger is not running!") end end, desc = "Debugger: Stop" }, { "dr", function() if daprunning == true then if not pcall(function() dap.continue() end) then dapCleanup() end else print("Debugger is not running! Please run debugger first") end end, desc = "Debugger: Resume execution" }, { "dn", function() if daprunning == true then if not pcall(function() dap.step_over() end) then dapCleanup() end else print("Debugger is not running! Please run debugger first") end end, desc = "Debugger: Step over" }, { "di", function() if daprunning == true then if not pcall(function() dap.step_into() end) then dapCleanup() print("Debugger failed to continue!") end else print("Debugger is not running! Please run debugger first") end end, desc = "Debugger: Step into" }, } }) -- See :help terminal-events, we can use this to implement cd commands etc changing the working directory of the nvim host and other terminal app to nvim host ipc. -- sleep 5 && printf "\033]7;file://${PWD}/foo/bar\033\\" vim.api.nvim_create_autocmd({ 'TermRequest' }, { desc = 'Handles OSC 7 dir change requests', callback = function(ev) if string.sub(vim.v.termrequest, 1, 4) == '\x1b]7;' then local dir = string.gsub(vim.v.termrequest, '\x1b]7;file://[^/.]*', '') vim.cmd("cd " .. dir) end end })