/ .config / nvim / init.lua
init.lua
   1  local vim = vim -- Hacky workaround for sumneko_lua being sorta dumb right now. I can fix it better later.
   2  -- copied from https://github.com/folke/lazy.nvim#-installation
   3  local lazypath = vim.fn.stdpath'data' .. "/lazy/lazy.nvim"
   4  -- TODO: mark PHP and composer as not needed?
   5  -- TODO: mark perl as not needed?
   6  -- TODO: these need to be marked as auto-install
   7  -- - prettier
   8  -- - stylelint
   9  -- - vint
  10  -- After that, tell efmls to not ask for them, if they can't be installed.
  11  if not vim.loop.fs_stat(lazypath) then
  12  	vim.fn.system{
  13  		"git",
  14  		"clone",
  15  		"--filter=blob:none",
  16  		"https://github.com/folke/lazy.nvim.git",
  17  		"--branch=stable", -- latest stable release
  18  		lazypath
  19  	}
  20  	local sitepath = vim.fn.stdpath'data' .. "/site"
  21  	local packer_compiled = vim.fn.stdpath'config' .. "/plugin/packer_compiled.lua"
  22  	local packer_install_path = sitepath .. "/pack/packer"
  23  	if vim.loop.fs_stat(sitepath) and vim.loop.fs_stat(packer_compiled) and vim.loop.fs_stat(packer_install_path) then
  24  		print"Migrating from packer..."
  25  		vim.cmd.sleep()
  26  		vim.fn.delete(sitepath)
  27  		vim.fn.delete(packer_compiled)
  28  	end
  29  end
  30  vim.opt.rtp:prepend(lazypath)
  31  
  32  -- TODO: proper git_dir stuff https://github.com/tpope/vim-fugitive/issues/2191
  33  
  34  -- if vim.env.VIMRUNNING == "1" then
  35  -- 	print("dummy! read before running (override by setting $VIMRUNNING to \"2\")")
  36  -- 	-- Lua never sleeps
  37  -- 	vim.cmd.sleep()
  38  -- 	-- and isn't a quitter
  39  -- 	vim.cmd.qall{ bang = true }
  40  -- 	-- So vim has to take care of it.
  41  -- elseif vim.env.VIMRUNNING ~= "2" then
  42  -- 	vim.env.VIMRUNNING = 1
  43  -- end
  44  
  45  local function configure_nvim_cmp()
  46  	local cmp = require'cmp'
  47  	vim.lsp.config('*', {
  48  		capabilities = require'cmp_nvim_lsp'.default_capabilities(),
  49  	})
  50  	--[[local function has_words_before()
  51  
  52  		return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
  53  	end]]
  54  
  55  	---@deprecated
  56  	local lsp_zero = require'lsp-zero'
  57  	local formatting = lsp_zero.cmp_format{} -- TODO: move away from lsp_zero here
  58  	do -- We still like lspkind in this house. format with zero, then lspkind. Best of both, hardly any manual config
  59  		local zero_format_fn = formatting.format
  60  		formatting.fields = { 'abbr', 'menu', 'icon', 'kind', }
  61  		formatting.format = require'lspkind'.cmp_format{
  62  			before = function (entry, vim_item)
  63  				-- lsp_zero tells us which completion plugin it is coming from
  64  				return zero_format_fn(entry, vim_item)
  65  			end
  66  		}
  67  	end
  68  
  69  	cmp.setup{
  70  		--Defaults:https://github.com/hrsh7th/nvim-cmp/blob/main/lua/cmp/config/default.lua
  71  		snippet = {
  72  			expand = function(args)
  73  				require'luasnip'.lsp_expand(args.body)
  74  			end,
  75  		},
  76  		mapping = {
  77  			['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
  78  			['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
  79  			['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
  80  			['<C-e>'] = cmp.mapping{
  81  				i = cmp.mapping.abort(),
  82  				c = cmp.mapping.close(),
  83  			},
  84  			-- https://github.com/hrsh7th/nvim-cmp/wiki/Example-mappings#luasnip
  85  			['<Tab>'] = cmp.mapping(function (fallback)
  86  				if cmp.visible() then
  87  					cmp.confirm{ select = true }
  88  				elseif require'luasnip'.expand_or_jumpable() then
  89  					require'luasnip'.expand_or_jump()
  90  				-- TODO: there's currently no way to tell if there's even a possible completion here. If there is, we should use
  91  				--  that, and use the fallback otherwise. See https://github.com/hrsh7th/nvim-cmp/issues/602
  92  				--elseif has_words_before() then
  93  				--	print"tabbed! has words before"
  94  				--	cmp.mapping.complete()
  95  				else
  96  					fallback()
  97  				end
  98  			end, { 'i', 's' }),
  99  			['<S-Tab>'] = cmp.mapping(function (fallback)
 100  				if cmp.visible() then
 101  					cmp.mapping.select_prev_item()
 102  				elseif require'luasnip'.jumpable(-1) then
 103  					require'luasnip'.jump(-1)
 104  				else
 105  					fallback()
 106  				end
 107  			end, { 'i', 's' }),
 108  			['<C-j>'] = cmp.mapping(cmp.mapping.select_next_item(), { 'i', 'c' }),
 109  			['<C-k>'] = cmp.mapping(cmp.mapping.select_prev_item(), { 'i', 'c' })
 110  		},
 111  		-- TODO: my method of lazy loading doesn't seem to work. It replaces all sources.
 112  		sources = cmp.config.sources({
 113  			{ name = 'nvim_lsp' }, -- can be lazy
 114  			{ name = 'luasnip' }, -- Cannot be lazy
 115  			{ name = 'latex_symbols' }, -- can be lazy
 116  			{ name = 'emoji', insert = true }, -- can be lazy
 117  		--}, {
 118  			{ name = "git" }, -- can be lazy loaded
 119  			{ name = "crates" }, -- can be lazy
 120  			{ name = 'npm', keyword_length = 4 }, -- can be lazy
 121  			{ name = 'nvim_lsp_document_symbol' }, -- can be lazy
 122  			{ name = "fish" }, -- can be lazy
 123  			{ name = "path" }, -- can be lazy
 124  			--{ name = "dictionary", keyword_length = 2 }, -- TODO: seems broken (switcher is deprecated)
 125  			{ name = 'nvim_lua' }, -- can be lazy
 126  		}, {
 127  			{ name = 'buffer' }, -- can be lazy
 128  			{ name = 'cmdline', keyword_length = 2 }, -- Can be lazy
 129  		}--[[, {
 130  			{ name = 'cmdline_history', options = { history_type = ':' } }, -- can be lazy
 131  		}]]),
 132  		sorting = {
 133  			comparators = {
 134  				cmp.config.compare.offset,
 135  				cmp.config.compare.exact,
 136  				cmp.config.compare.score,
 137  				cmp.config.compare.recently_used,
 138  				require'cmp-under-comparator'.under,
 139  				cmp.config.compare.kind,
 140  				cmp.config.compare.sort_text,
 141  				cmp.config.compare.length,
 142  				cmp.config.compare.order,
 143  			},
 144  		},
 145  		formatting = formatting
 146  	}
 147  	-- Use buffer source (then history) for `/` and `?` (if you enabled `native_menu`, this won't work anymore).
 148  	cmp.setup.cmdline({'/', '?'}, {
 149  		sources = cmp.config.sources(
 150  			{ { name = 'buffer' } }, -- can be lazy
 151  			{ { name = 'cmdline_history' } } -- can be lazy
 152  		)
 153  	})
 154  	-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
 155  	cmp.setup.cmdline(':', {
 156  		sources = cmp.config.sources(
 157  			{ { name = 'path' } }, -- can be lazy
 158  			{
 159  				{ name = 'cmdline' }, -- Can be lazy
 160  				{ name = 'cmdline_history' } -- can be lazy
 161  			}
 162  		)
 163  	})
 164  	cmp.setup.cmdline({'@', '='}, {
 165  		sources = { { name = 'cmdline_history' } } -- can be lazy
 166  	})
 167  end
 168  
 169  local has_the_command_that_some_call
 170  do
 171  	local theCommandsThatWeKnow = {}
 172  	function has_the_command_that_some_call(tim)
 173  		if theCommandsThatWeKnow[tim]~=nil then
 174  			return theCommandsThatWeKnow[tim]
 175  		end
 176  		local check_cmd = io.popen(string.format("command -v %s", tim))
 177  		local result = nil
 178  		if check_cmd then
 179  			local read_res = check_cmd:read"*all"
 180  			local val = ({check_cmd:close()})[3]
 181  			local it_has_it = #read_res > 0
 182  			theCommandsThatWeKnow[tim] = it_has_it
 183  			result =  it_has_it
 184  		else
 185  			theCommandsThatWeKnow[tim] = false
 186  			result =  false
 187  		end
 188  		if not result then
 189  			-- timmeh stuck in the well!
 190  			vim.notify(
 191  				string.format("the program '%s' is missing. Less functionality will be available.", tim),
 192  				--vim.log.levels.WARN
 193  				vim.log.levels.WARN
 194  			)
 195  		end
 196  		return result
 197  	end
 198  end
 199  
 200  -- only load things if npm, pnpm or yarn is present
 201  -- TODO: consider checking for npm, pnpm and  yarn.
 202  -- TODO: consider just checking for node
 203  local function has_npm()
 204  	return has_the_command_that_some_call"npm" and
 205  		has_the_command_that_some_call"node"
 206  end
 207  
 208  local function inside_neovimpager()
 209  	local result = pcall(function()
 210  		require'nvimpager'
 211  	end)
 212  	inside_neovimpager = function()
 213  		return result
 214  	end
 215  	return result
 216  end
 217  
 218  local function configure_lualine()
 219  	-- BUG: lualine or one of it's deps is using deprecated features
 220  	---@deprecated  TODO: lsp-zero is unmaintained
 221  	local lsp_zero = require'lsp-zero'
 222  	--                                        █ 🙽 🙼 🙿   🙾
 223  	-- https://github.com/ryanoasis/nerd-fonts/issues/1190
 224  	vim.opt.shortmess:append'S' -- Do not show search count message when searching e.g. '[1/5]'
 225  	local function filename_format(_--[[c]], filename, mod, filetype)
 226  		local icon, _--[[color]]= require'nvim-web-devicons'.get_icon_color(filetype)
 227  		-- icon = c:format_hl(color) .. icon .. c:get_default_hl() -- TODO: color lualine/components/filetype.lua
 228  		return (icon and  icon .. ' ' or '') .. filename .. (mod == 1 and ' ~' or '')
 229  	end
 230  	local custom_filename_component = {
 231  		'filename',
 232  		fmt = function (filename, c)
 233  			local mod = vim.bo.mod
 234  			local filetype = vim.bo.filetype
 235  			return filename_format(c, filename, mod, filetype)
 236  		end,
 237  	}
 238  	require'lualine'.setup{
 239  		options = {
 240  			component_separators = { left = '', right = ''},
 241  			section_separators = { left = ' ', right = ' '}
 242  		},
 243  		inactive_sections = {
 244  			lualine_c = { custom_filename_component }
 245  		},
 246  		sections = {
 247  			lualine_b = {
 248  				-- TODO: do this with mason
 249  				{
 250  					function () return require'lazy.status'.updates() end,
 251  					cond = function () return require'lazy.status'.has_updates() end
 252  				},
 253  				--'hostname',
 254  				'branch', 'diff', 'diagnostics'
 255  				-- TODO: todo count https://github.com/folke/todo-comments.nvim/issues/197
 256  			},
 257  			lualine_c = {
 258  				custom_filename_component,
 259  				'selectioncount',
 260  				function () return require'lsp-status'.status() end,
 261  				-- The below doesn't look good and provides nothing I need
 262  				--function () -- NOTE: this would also need to only load if treesitter is installed (in the system)
 263  				--	return vim.fn['nvim_treesitter#statusline']{indicator_size=20}
 264  				--end
 265  			},
 266  			lualine_y = {
 267  				{
 268  					function () return require'battery'.get_status_line() end,
 269  					cond = function ()
 270  						return vim.o.columns > 120
 271  					end
 272  				},
 273  				'searchcount',
 274  				'progress'
 275  			}
 276  		},
 277  		tabline = {
 278  			lualine_b = {{
 279  				'tabs',
 280  				mode = 1,
 281  				max_length = function () return vim.o.columns end,
 282  				fmt = function (filename, context)
 283  					-- Show ~ if buffer is modified in tab
 284  					local buflist = vim.fn.tabpagebuflist(context.tabnr)
 285  					local winnr = vim.fn.tabpagewinnr(context.tabnr)
 286  					local bufnr = buflist[winnr]
 287  					local mod = vim.fn.getbufvar(bufnr, '&mod')
 288  					local filetype = vim.fn.getbufvar(bufnr, '&filetype')
 289  
 290  					return filename_format(context, filename, mod, filetype)
 291  				end,
 292  				cond = function ()
 293  					return vim.fn.tabpagenr'$' > 1
 294  				end
 295  			}}
 296  		},
 297  		-- Each extension "changes statusline appearance for a window/buffer with specified filetypes"
 298  		extensions = { 'fugitive', 'lazy', 'neo-tree' }
 299  	}
 300  	vim.opt.showtabline = 1 --(visible if more than 1 tab)
 301  	-- Here we are getting the icons from the lualine default settings. If you change lualine's config, these icons will
 302  	-- not change with it.
 303  	-- This is horrible. Despicible. Don't do it. It WILL break.
 304  	lsp_zero.set_sign_icons(require"lualine.components.diagnostics.config".symbols.icons)
 305  end
 306  
 307  local function tbflatten(tb)
 308  	return vim.iter(tb):flatten():totable()
 309  end
 310  
 311  do -- Keymaps and the like
 312  	-- refer to https://github.com/nanotee/nvim-lua-guide
 313  
 314  	--vim.lsp.set_log_level("debug")
 315  
 316  	-- Which syntaxes would you like to enable highlighting for in vim files?
 317  	vim.g.vimsyn_embed = 'l'
 318  
 319  	-- see the docstrings for folded code
 320  	-- TODO: this looks typo-ed and is likely broken
 321  	vim.g.SimpylFold_docstring_preview = 1
 322  
 323  	--vim.keymap.set('n', '<Leader>d', vim.diagnostic.goto_next)
 324  
 325  	-- TODO: unless there's a conflict, learn the _actual_ shortcuts (and remove these)
 326  
 327  	vim.keymap.set('n', '<Leader><Leader>', '<c-^>', {desc="Go back one file in current buffer"})
 328  
 329  	-- Map <Esc> to exit terminal-mode (stolen from nvim's :help terminal-input then modified for lua)
 330  	vim.keymap.set('t', '<Esc>', '<C-\\><C-n>', {desc='exit terminal mode and convert it back into a buffer'})
 331  	-- Make it a tad easier to change the terminal back to a buffer
 332  	vim.keymap.set('', '<Leader>]', '<C-\\><C-n>', {desc='exit terminal mode and convert it back into a buffer'})
 333  
 334  	-- Keyboard shortcut to open nerd tree via currently disabled mod
 335  	--vim.keymap.set('', '<Leader>n', '<Plug>NERDTreeTabsToggle<CR>')
 336  
 337  	-- Reccomended keymaps from nvim-lspconfig
 338  	-- https://github.com/neovim/nvim-lspconfig#suggested-configuration
 339  	vim.keymap.set('n', '<space>e', vim.diagnostic.open_float, { noremap=true, silent=true, desc="diagnostic open float" })
 340  	vim.keymap.set('n', '<space>q', vim.diagnostic.setloclist, {
 341  		noremap=true,
 342  		silent=true,
 343  		desc="diagnostic add to locaction list"
 344  	})
 345  
 346  	-- Reccomended settings for nvim-cmp
 347  	vim.o.completeopt = 'menu,menuone,noselect'
 348  
 349  	vim.o.showmode = false -- Hide the default mode text (e.g. -- INSERT -- below the statusline)
 350  	-- print options
 351  	-- set printoptions=paper:letter
 352  
 353  	-- display line numbers
 354  	--  If this is used with [[relativenumber]], then it shows the current lineno on the current line (as opposed to `0`)
 355  	vim.o.number = true
 356  	vim.o.relativenumber = true
 357  
 358  	vim.o.wrap = true
 359  
 360  	vim.o.tabstop = 4
 361  	vim.o.shiftwidth = 4
 362  	vim.o.backspace = 'indent,eol,start'
 363  
 364  	-- Use sys clipboard (see osc52 for ssh clipboard)
 365  	vim.o.clipboard = 'unnamedplus'
 366  
 367  	-- Title magic.
 368  	vim.o.title = true
 369  
 370  	-- I don't like presssing more most of the time -- Breaks :map
 371  	--vim.o.more = false
 372  
 373  	-- This is the global vim refresh interval. Multiple tools, such as
 374  	-- gitgutter and coc reccomend turning this number down. It's measured in
 375  	-- milliseconds, and defaults to 4000
 376  	vim.o.updatetime = 1000
 377  
 378  	-- Enable folding (treesitter changes this)
 379  	vim.o.foldmethod = 'syntax'
 380  	----vim.o.foldmethod = 'indent'
 381  	vim.wo.foldlevel=99
 382  	vim.wo.foldminlines = 3
 383  
 384  	-- Load file automatically when changes happen
 385  	vim.o.autoread = true
 386  
 387  	-- Ensure that the cursor is this many chars at lowest from either end of each buffer
 388  	vim.o.scrolloff = 5
 389  	vim.o.sidescrolloff = 5
 390  
 391  	--enable syntax highlighting (optimised for dark backgrounds)
 392  	--vim.o.background='dark'
 393  
 394  	-- I needed a ruby nvim plugin awhile back. This fixes it.
 395  	-- TODO: instad, mark as not needed?
 396  	vim.g.ruby_host_prog = '~/.bin/neovim-ruby-host'
 397  
 398  	vim.api.nvim_create_autocmd("TextYankPost", {
 399  		pattern = "*",
 400  		callback = function()
 401  			-- TODO: deprecated
 402  			vim.highlight.on_yank()
 403  		end
 404  	})
 405  	-- Allow for syntax checking in racket. The catches: Security(?) and lag.
 406  	-- NOTE: LSP is better
 407  	--vim.g.syntastic_enable_racket_racket_checker = 1 -- I want it to check racket file syntax
 408  	vim.api.nvim_create_autocmd({ "BufNewFile", "BufRead" }, {
 409  		pattern = "*.rkt",
 410  		callback = function()
 411  			vim.o.tabstop = 2
 412  			vim.o.softtabstop = 2
 413  			vim.o.shiftwidth = 2
 414  			vim.o.textwidth = 79
 415  			vim.o.expandtab = true
 416  			vim.o.autoindent = true
 417  			vim.o.fileformat = "unix"
 418  			vim.o.lisp = true
 419  		end
 420  	})
 421  
 422  
 423  	-- godot support
 424  	do -- TODO: learn how to use vim.filetype.add
 425  		-- HACK: doesn't work in nvim at all ootb, but vim.filetype.add doesn't work for this
 426  		vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
 427  			pattern = "*.gd",
 428  			callback = function ()
 429  				vim.o.filetype = "gdscript"
 430  			end
 431  		})
 432  		-- HACK: gdresource is supported if opened from cli, this lets it work elsewhere. Same issue with vim.filetype.add.
 433  		vim.api.nvim_create_autocmd({"BufRead", "BufNewFile"}, {
 434  			pattern = "*.tscn",
 435  			callback = function ()
 436  				vim.o.filetype = "gdresource"
 437  			end
 438  		})
 439  	end
 440  	-- Disable numbers on terminal only.
 441  	--[[ TODO: This will need an autocommand for every buffer, since the setting is inherited when split
 442  	vim.api.nvim_create_autocmd({ "TermOpen" }, {
 443  		pattern = "*",
 444  		callback = function()
 445  			-- TODO: should this be something else? It errors for bo
 446  			vim.o.number = false
 447  			vim.o.relativenumber = false
 448  		end
 449  	})]]
 450  	-- Popup windows tend to be unreadable with a pink background
 451  	--vim.api.nvim_set_hl(0, "Pmenu", {})
 452  
 453  	--[[
 454  	-- TODO: if I uncomment this code, java code highlighting breaks
 455  	vim.api.nvim_create_autocmd({ "FileType" }, {
 456  		pattern = 'java',
 457  		callback = function()
 458  			assert(false)
 459  			require'jdtls'.start_or_attach(vim.tbl_extend(
 460  				'force',
 461  				require'lsp-zero.server'.default_config,
 462  				require'lspconfig'.jdtls.config_def.default_config
 463  			))
 464  		end
 465  	})
 466  	--]]
 467  end
 468  
 469  local lazy_config = { defaults = { lazy = true }, checker = { enabled = true, notify = false } }
 470  
 471  local lazy_plugins = {
 472  	-- Commenting
 473  	--Plug 'tpope/vim-commentary'
 474  	-- The looks of Powerline but faster than:
 475  	-- - Powerline
 476  	-- - Airline
 477  	-- - And the well-known, formerly first-place Lightline
 478  	{ 'nvim-lualine/lualine.nvim', config = configure_lualine, event = "BufEnter" },
 479  	-- The looks of Powerline, but faster
 480  	-- use{
 481  	-- 	'itchyny/lightline.vim',
 482  	-- 	disable = true,
 483  	-- 	--config = configure_lightline,
 484  	-- 	requires = {
 485  	-- 		'vim-fugitive',
 486  	-- 		'lsp-status.nvim'
 487  	-- 	}
 488  	-- }
 489  	-- Indent lines
 490  	{ 'lukas-reineke/indent-blankline.nvim',
 491  		event = "VeryLazy", -- TODO: better lazyness?
 492  		main = "ibl",
 493  		config = function ()
 494  			require"ibl".setup{
 495  				indent = { char = '│', tab_char = '│' },
 496  				scope = { show_start = false, show_end = false }
 497  			}
 498  			local hooks = require"ibl.hooks"
 499  			hooks.register(
 500  				hooks.type.ACTIVE,
 501  				function ()
 502  					-- Because we only set when ibl activiates, it doesn't run for buffers we don't edit.
 503  					-- This also ensures that list is set _after_ ibl makes rendering changes. This prevents clashes.
 504  					vim.opt.list = true
 505  					return true
 506  				end
 507  			)
 508  			-- Line indent markers
 509  			-- TODO: this is a bad place for this config stuff. It should work without IBL
 510  			vim.opt.listchars:append"lead:⋅"
 511  			vim.opt.listchars:append"nbsp:⚬"
 512  			vim.opt.listchars:append"tab:  " -- No > chars when ibl is slow
 513  			vim.opt.listchars:append"trail:─"
 514  		end
 515  	},
 516  	-- Super fancy coloring
 517  	--  A companion to windwp/nvim-autopairs that does xml
 518  	{ "windwp/nvim-ts-autotag",
 519  		event = "InsertEnter",
 520  		opts = {}
 521  	},
 522  	{ 'nvim-treesitter/nvim-treesitter',
 523  		-- TODO: only load this if tree-sitter is installed
 524  		--dependencies = "windwp/nvim-ts-autotag",
 525  		main = 'nvim-treesitter.configs',
 526  		branch = 'master', -- TODO: move to incompatible main branch
 527  		config = function ()
 528  			require'nvim-treesitter'.setup{
 529  				sync_install = true,
 530  				auto_install = true -- With this, I don't actually need any list. It lazy-installs this way.
 531  				-- TODO: require `tree-sitter` cli program
 532  			}
 533  			vim.wo.foldmethod= 'expr'
 534  			vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
 535  		end,
 536  		build = ':TSUpdateSync',
 537  		event = 'VeryLazy' -- TODO: better lazyness?
 538  	},
 539  	{ 'rebelot/kanagawa.nvim',
 540  		-- TODO: (low prio) match this and the cmd theme
 541  		lazy = false,
 542  		priority = 1000,
 543  		config = function ()
 544  			-- NOTE: when kanagawa is in use directly, it starts as dark, then auto detects the ideal theme. This is a bit slow, so there's a blink.
 545  			vim.cmd.colorscheme'kanagawa'
 546  			--vim.cmd.colorscheme'kanagawa-lotus'
 547  		end
 548  	},
 549  	{ 'ojroques/nvim-osc52',
 550  		-- Copy clipboard even if over ssh
 551  		config = function ()
 552  			require'osc52'.setup{}
 553  			-- Setup a few keymaps so I can copy even if the rest of this plugin is broken
 554  			vim.keymap.set('n', '<leader>c', require'osc52'.copy_operator, {expr = true, desc="osc52 copy operator"})
 555  			vim.keymap.set('n', '<leader>cc', '<leader>c_', {remap = true, desc="osc52 copy _"})
 556  			vim.keymap.set('n', '<leader>C', '<leader>c', {remap = true, desc="osc52 copy operator alt"})
 557  			vim.keymap.set('v', '<leader>c', require'osc52'.copy_visual, {desc="osc52 copy visual mode operator"})
 558  			vim.keymap.set('v', '<leader>C', '<leader>c', {remap = true, desc="osc52 copy visual mode operator alt"})
 559  			-- Copy text yanked into + (this does work, but hard to use)
 560  			--local function copy()
 561  			--	if vim.v.event.operator == 'y' and vim.v.event.regname == '+' then
 562  			--		require'osc52'.copy_register'+'
 563  			--	end
 564  			--end
 565  			--vim.api.nvim_create_autocmd('TextYankPost', {callback = copy})
 566  			-- Use this plugin as a clipboard provider TODO: doesn't seem to work
 567  			--local function copy(lines, _)
 568  			--	require'osc52'.copy(table.concat(lines, '\n'))
 569  			--end
 570  			--local function paste()
 571  			--	return {vim.fn.split(vim.fn.getreg'', '\n'), vim.fn.getregtype''}
 572  			--end
 573  			--vim.g.clipboard = {
 574  			--	name = 'osc52',
 575  			--	copy = {['+'] = copy, ['*'] = copy},
 576  			--	paste = {['+'] = paste, ['*'] = paste}
 577  			--}
 578  			--vim.keymap.set('n', '<leader>c', '"+y')
 579  			--vim.keymap.set('n', '<leader>cc', '"+yy')
 580  		end,
 581  		event = "BufEnter"
 582  	},
 583  
 584  	-- Git integration
 585  	--  Genral use
 586  	{ 'tpope/vim-fugitive', event = "VeryLazy" }, -- TODO: better lazyness?
 587  	--  Line-per-line indicators and chunk selection
 588  	{ 'lewis6991/gitsigns.nvim',
 589  		opts = {
 590  			on_attach = function(bufnr)
 591  				local gs = require'gitsigns'
 592  				local function map(mode, l, r, opts)
 593  					opts = opts or {}
 594  					opts.buffer = bufnr
 595  					vim.keymap.set(mode, l, r, opts)
 596  				end
 597  				-- Navigation
 598  				map('n', ']c', function()
 599  					if vim.wo.diff then
 600  						vim.cmd.normal{']c', bang = true}
 601  					else
 602  						gs.nav_hunk'next'
 603  					end
 604  				end, {desc="Git next hunk"})
 605  				map('n', '[c', function()
 606  					if vim.wo.diff then
 607  						vim.cmd.normal{'[c', bang = true}
 608  					else
 609  						gs.nav_hunk'prev'
 610  					end
 611  				end, {desc="Git prev hunk"})
 612  				-- Actions
 613  				map('n', '<leader>hs', gs.stage_hunk, {desc="Git stage hunk"})
 614  				map('n', '<leader>hr', gs.reset_hunk, {desc="Git reset hunk"})
 615  
 616  				map('v', '<leader>hs', function()
 617  					gs.stage_hunk {vim.fn.line("."), vim.fn.line("v")}
 618  				end, {desc="Git stage hunk visual"})
 619  
 620  				map('v', '<leader>hr', function()
 621  				  gs.reset_hunk{ vim.fn.line'.', vim.fn.line'v' }
 622  				end, {desc="Git reset hunk visual"})
 623  
 624  				map('n', '<leader>hS', gs.stage_buffer, {desc="Git stage buffer"})
 625  				map('n', '<leader>hR', gs.reset_buffer, {desc="Git reset buffer"})
 626  				map('n', '<leader>hp', gs.preview_hunk, {desc="Git preview hunk"})
 627  				map('n', '<leader>hi', gs.preview_hunk_inline, {desc="Git preview hunk inline"})
 628  
 629  				map('n', '<leader>hb', function()
 630  					gs.blame_line{full=true}
 631  				end, {desc="Git blame line"})
 632  
 633  				map('n', '<leader>hd', gs.diffthis, {desc="Git diff this"})
 634  
 635  				map('n', '<leader>hD', function()
 636  					gs.diffthis'~'
 637  				end, {desc="Git diff this ~"})
 638  
 639  				map('n', '<leader>hQ', function() gs.setqflist'all' end, {desc="Git quickfix all"})
 640  				map('n', '<leader>hq', gs.setqflist, {desc="Git quickfix"})
 641  
 642  				-- Toggles
 643  				map('n', '<leader>tb', gs.toggle_current_line_blame, {desc="Git toggle current line blame"})
 644  				map('n', '<leader>td', gs.toggle_deleted, {desc="Git toggle deleted"})
 645  				map('n', '<leader>tw', gs.toggle_word_diff, {desc="Git toggle word diff"})
 646  
 647  				-- Text object
 648  				map({'o', 'x'}, 'ih', ':<C-U>Gitsigns select_hunk<CR>', {desc="Git select hunk"})
 649  			end
 650  		},
 651  		event = "BufEnter"
 652  	},
 653  	"MunifTanjim/nui.nvim",
 654  	-- Even nicer file management
 655  	{ 'nvim-neo-tree/neo-tree.nvim',
 656  		--branch = "v3.x",
 657  		branch = "main",
 658  		dependencies = {
 659  			--"nvim-lua/plenary.nvim",
 660  			--"nvim-tree/nvim-web-devicons",
 661  			--"MunifTanjim/nui.nvim",
 662  			'vim-rooter'
 663  		},
 664  		init = function ()
 665  			vim.g.neo_tree_remove_legacy_commands = 1
 666  			vim.g.loaded_netrwPlugin = 1 -- Don't load both this and the builtin tree
 667  		end,
 668  		opts = { window = { position = "current" } },
 669  		lazy = false
 670  	},
 671  	{ 'justinhj/battery.nvim',
 672  		--dependencies = {'nvim-tree/nvim-web-devicons', 'nvim-lua/plenary.nvim'},
 673  		opts = {},
 674  		event = "VeryLazy" -- TODO: better lazyness?
 675  	},
 676  
 677  	-- Icons
 678  	'nvim-tree/nvim-web-devicons',
 679  	--  LSP breakdown icons and stuff
 680  	'onsails/lspkind-nvim',
 681  
 682  	--  This should work on all files (it's python support ain't great)
 683  	--Plug 'khzaw/vim-conceal'
 684  	--Plug 'jamestomasino-forks/vim-conceal' " This one has better javascript support
 685  	--Plug 'Lazerbeak12345/vim-conceal' " This is my blend of a bunch of stuff (my
 686  	--    fork of above)
 687  	-- Ease of use
 688  	{ 'vimlab/split-term.vim', cmd = { "Term", "VTerm", "TTerm" } },
 689  	-- un-recursor
 690  	{ "samjwill/nvim-unception",
 691  		-- BUG: if dbus doesn't know this user is logged in, this plugin breaks
 692  		init = function()
 693  			vim.g.unception_block_while_host_edits = 1
 694  			vim.g.unception_enable_flavor_text = 1
 695  		end,
 696  		lazy = false,
 697  	},
 698  	{ 'airblade/vim-rooter',
 699  		init = function ()
 700  			vim.g.rooter_change_directory_for_non_project_files = 'current'
 701  			vim.g.rooter_patterns = tbflatten{
 702  				has_the_command_that_some_call"git" and { '.git' } or {},
 703  				has_the_command_that_some_call"npm" and { 'package.json' } or {},
 704  				has_the_command_that_some_call"make" and { 'Makefile' } or {},
 705  				has_the_command_that_some_call"luanti" and {
 706  					'mod.conf',
 707  					'modpack.conf',
 708  					'game.conf',
 709  					'texture_pack.conf',
 710  				} or {},
 711  				has_the_command_that_some_call"godot" and {
 712  					"project.godot" -- I must have this one, at least.
 713  				} or {}
 714  			}
 715  		end,
 716  		cond = function ()
 717  			-- dont load if we are in neovimpager
 718  			return not inside_neovimpager()
 719  		end
 720  	},
 721  	--  Start Screen
 722  	{ 'goolord/alpha-nvim',
 723  		--dependencies = {
 724  		--	'nvim-tree/nvim-web-devicons',
 725  		--	'airblade/vim-rooter'
 726  		--},
 727  		lazy = false,
 728  		config = function ()
 729  			require'alpha'.setup(require'alpha.themes.startify'.config)
 730  		end
 731  	},
 732  
 733  
 734  	-- common dependencie of many nvim plugins
 735  	'nvim-lua/plenary.nvim',
 736  
 737  	-- default settings for efmls
 738  	'creativenull/efmls-configs-nvim', --version = 'v1.1.1', },
 739  	-- Interactive eval
 740  	-- use 'Olical/conjure'
 741  	--  TODO: configure this
 742  	--  this might be a problem 987632498629765296987492
 743  	--  This should be added after DAP (due to feature overlap and complexity)
 744  
 745  	-- Specific file type compat
 746  	--  General stuff (syntax, etc)
 747  	{ 'sheerun/vim-polyglot', event = "BufEnter" },
 748  	--  Eww's configuration language, yuck
 749  	{ 'elkowar/yuck.vim', event = "BufEnter" },
 750  	{ "folke/todo-comments.nvim",
 751  		-- TODO: is it possible to replace this with something that uses treesitter or LSP?
 752  		--dependencies = "plenary.nvim",
 753  		event = "VeryLazy", -- TODO: better lazyness?
 754  		config = function ()
 755  			local tc = require'todo-comments'
 756  			tc.setup{
 757  				keywords = {
 758  					-- matches the word, so break it on purpose
 759  					FIX = { icon = " " },
 760  					TODO = { icon = "" },
 761  					HACK = { icon = "" },
 762  					WARN = { icon = " " },
 763  					TEST = { icon = " " },
 764  					PERF = { icon = "󰓅 " },
 765  					NOTE = { icon = "󱇗" }
 766  				},
 767  				-- Allow omitting the semicolon
 768  				---- vim regex
 769  				--highlight = { after = "", pattern = [[.*<(KEYWORDS)\s*:?]] },
 770  				---- ripgrep regex
 771  				--search = { pattern = [[\b(KEYWORDS):?]] }, -- TODO: false positives. it it big enough of a problem? Fixable?
 772  			}
 773  			-- https://github.com/folke/todo-comments.nvim#jumping
 774  			vim.keymap.set("n", "]t", function()
 775  				tc.jump_next()
 776  			end, { desc = "Next todo comment" })
 777  
 778  			vim.keymap.set("n", "[t", function()
 779  				tc.jump_prev()
 780  			end, { desc = "Previous todo comment" })
 781  		end
 782  	},
 783  
 784  	-- Language-server protocol
 785  	-- Must be after language specific things
 786  	{ 'VonHeikemen/lsp-zero.nvim', --- TODO: migrate to 4.x
 787  		branch = 'v3.x',
 788  		init = function ()
 789  			-- Disable automatic setup, we are doing it manually
 790  			vim.g.lsp_zero_extend_cmp = false
 791  			vim.g.lsp_zero_extend_lspconfig = false
 792  		end,
 793  		lazy = true,
 794  		config = false
 795  	},
 796  	{ 'mason-org/mason.nvim',
 797  		lazy = false,
 798  		opts = {
 799  			max_concurrent_installers = require'luv'.available_parallelism(),
 800  			ui = {
 801  				icons = {
 802  					package_installed = "✓",
 803  					package_pending = "➜ ",
 804  					package_uninstalled = "✗"
 805  				}
 806  			}
 807  		}
 808  	},
 809  	{ 'WhoIsSethDaniel/mason-tool-installer.nvim', dependencies = 'mason.nvim' },
 810  	'mason-org/mason-lspconfig.nvim',
 811  	{ 'neovim/nvim-lspconfig',
 812  		event = {"BufReadPre", "BufNewFile"},
 813  		cmd = {"LspInfo", "LspInstall", "LspStart"},
 814  		dependencies = {
 815  			-- TODO: https://lazy.folke.io/developers#best-practices
 816  			--'VonHeikemen/lsp-zero.nvim',
 817  			--'hrsh7th/cmp-nvim-lsp',
 818  			--'mason-org/mason.nvim',
 819  			--'WhoIsSethDaniel/mason-tool-installer.nvim',
 820  			--'mason-org/mason-lspconfig.nvim',
 821  			--'creativenull/efmls-configs-nvim',
 822  			-- TODO: make these into soft dependencies
 823  			--'nvim-lua/lsp-status.nvim',
 824  			--'nvim-lualine/lualine.nvim',
 825  			--'airblade/vim-rooter',
 826  			--'pierreglaser/folding-nvim',
 827  		},
 828  		config = function()
 829  			---@deprecated lsp-zero is unmaintained
 830  			local lsp_zero = require'lsp-zero'
 831  
 832  			vim.api.nvim_create_autocmd('LspAttach', {
 833  				desc = 'LSP actions',
 834  				callback = function(event)
 835  					-- TODO: https://lsp-zero.netlify.app/v3.x/language-server-configuration.html#format-using-a-keybinding
 836  					vim.keymap.set('n', 'K', vim.lsp.buf.hover, { buffer = event.buf, desc = "LSP hover" })
 837  					vim.keymap.set('n', 'gd', vim.lsp.buf.definition, { buffer = event.buf, desc = "LSP definition" })
 838  					vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, { buffer = event.buf, desc = "LSP declaration" })
 839  					vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, { buffer = event.buf, desc = "LSP implementation" })
 840  					vim.keymap.set('n', 'go', vim.lsp.buf.type_definition, { buffer = event.buf, desc = "LSP type_definition" })
 841  					vim.keymap.set('n', 'gr', vim.lsp.buf.references, { buffer = event.buf, desc = "LSP references" })
 842  					vim.keymap.set('n', 'gs', vim.lsp.buf.signature_help, { buffer = event.buf, desc = "LSP signature_help" })
 843  					vim.keymap.set('n', '<F2>', vim.lsp.buf.rename, { buffer = event.buf, desc = "LSP rename" })
 844  					vim.keymap.set({'n', 'x'}, '<F3>', function ()
 845  						vim.lsp.buf.format{ async = true }
 846  					end, { buffer = event.buf, desc = "LSP format" })
 847  					vim.keymap.set('n', '<F4>', vim.lsp.buf.code_action, { buffer = event.buf, desc = "LSP code_action" })
 848  				end,
 849  			})
 850  
 851  			vim.lsp.config('*', {
 852  				--capabilities = require'lspconfig'.util.default_config
 853  				capabilities = lsp_zero.get_capabilities()
 854  			})
 855  
 856  			-- Installed manually in system.
 857  			vim.lsp.enable'racket_langserver'
 858  			do
 859  				vim.lsp.config('clangd', {
 860  					capabilities = {
 861  						handlers = require'lsp-status'.extensions.clangd.setup(),
 862  						init_options = { clangdFileStatus = true }
 863  					}
 864  				})
 865  				vim.lsp.enable'clangd'
 866  			end
 867  
 868  			-- Installed through mason
 869  			-- TODO: assert that all requirements in `:h mason-requirements` are met
 870  			-- https://github.com/nvimdev/guard.nvim -- Linter chains (for if efm doesn't work)
 871  			require'mason-tool-installer'.setup{
 872  				ensure_installed = tbflatten{
 873  					'rustfmt', -- WARNING: reccomends rustup instead of whatever it's doing now (deprecation)
 874  					-- For Java
 875  					--'vscode-java-decompiler',
 876  					--"google-java-format",
 877  					-- "java-debug-adapter"
 878  					--has_the_command_that_some_call"mvn" and {
 879  					--	-- TODO: Blocked by https://github.com/georgewfraser/java-language-server/issues/283
 880  					--	--"java-language-server",
 881  					--},
 882  					--"jdtls", -- developed by eclipse
 883  					--has_the_command_that_some_call"unzip" and {
 884  					--	"gradle_ls",
 885  					--} or {},
 886  
 887  					"checkstyle",
 888  					-- This is sumneko_lua. Not my favorite.
 889  					"lua_ls",
 890  					-- TODO: broken
 891  					"ruff", -- Super fast python linting & etc.
 892  					"mypy", -- python type linting
 893  					"django-template-lsp",
 894  					--"curlylint", -- django & etc html template linting
 895  					"djlint", -- django & etc html template linting
 896  					"rust_analyzer",
 897  					"taplo", -- For TOML
 898  					"marksman", -- For markdown
 899  					"efm",
 900  					has_npm() and {
 901  						"stylelint", "prettier",
 902  						"eslint",
 903  						"html",
 904  						"jsonls",
 905  						"yaml-language-server",
 906  						"ts_ls",
 907  						"pyright", -- Everything else python LSP
 908  						"svelte",
 909  						"vimls",
 910  						"ast-grep", -- Rewriting for lots of stuff
 911  						"css-lsp",
 912  						"css-variables-language-server", -- Till css-lsp supports variables, this is needed
 913  						"cssmodules-language-server", -- For when we import css files in react, etc.
 914  						"dot-language-server",
 915  						"vue-language-server", --"vue_ls",-- 
 916  					} or {},
 917  					has_the_command_that_some_call"unzip" and {
 918  						"stylua",
 919  						"selene"
 920  					} or {},
 921  					has_the_command_that_some_call"cargo" and {
 922  						'shellharden'
 923  					} or {},
 924  					has_the_command_that_some_call"luarocks" and {
 925  						'luacheck'
 926  					} or {},
 927  					has_the_command_that_some_call"godot" and {
 928  						"gdtoolkit" -- TODO: configure this
 929  					} or {}
 930  				},
 931  				auto_update = true,
 932  			}
 933  			-- python
 934  			vim.lsp.config('ruff', {
 935  				capabilities = {
 936  					-- disable in favor of pyright
 937  					hoverProvider = false
 938  				}
 939  			})
 940  			-- BUG: doesn't seem to start, these days
 941  			do
 942  				local function formater(name)
 943  					return require("efmls-configs.formatters." .. name)
 944  				end
 945  				local function linter(name)
 946  					return require("efmls-configs.linters." .. name)
 947  				end
 948  				local prettier = formater"prettier"
 949  				local css = { linter"stylelint", prettier }
 950  				local prettier_only = { prettier } -- eslint isn't needed - we have the lsp
 951  				local languages = {
 952  					css = css, less = css, scss = css, sass = css,
 953  					javascript = prettier_only, javascriptreact = prettier_only,
 954  					typescript = prettier_only, typescriptreact = prettier_only,
 955  					html = prettier_only,
 956  					lua = { linter"luacheck", formater"stylua"--[[, linter"selene"]] },
 957  					vim = { linter"vint" }, -- TODO: what does this require
 958  					rust = { formater"rustfmt" },
 959  					sh = { formater"shellharden" },
 960  					fish = { linter"fish", formater"fish_indent" },
 961  					python = { linter"mypy", linter"ruff", formater"ruff" },
 962  					htmldjango = { linter"djlint", formater"djlint" },
 963  					-- BUG: doesn't work. I don't think efm works at all right now, actually
 964  					--java = { formater"google_java_format" }
 965  				}
 966  				vim.lsp.config('efm', {
 967  					settings = {
 968  						-- This is, certianly, the way to go for other things, assuming this even works
 969  						-- TODO: modify rooter_patterns to be the union of all of these language root patterns?
 970  						rootMarkers = vim.g.rooter_patterns,
 971  						languages = languages
 972  					},
 973  					filetypes = vim.tbl_keys(languages)
 974  				})
 975  			end
 976  			-- lua
 977  			vim.lsp.config('lua_ls', lsp_zero.nvim_lua_ls())
 978  
 979  			require'mason-lspconfig'.setup {
 980  				automatic_enable = {
 981  					exclude = { "jdtls" }
 982  				},
 983  				-- if this is present, it fools this tool to automatic_enable anything
 984  				-- installed - even if it's installed by something else
 985  				ensure_installed = {},
 986  			}
 987  		end
 988  	},
 989  	{ 'nvim-lua/lsp-status.nvim',
 990  		--dependencies = 'onsails/lspkind-nvim',
 991  		config = function()
 992  			require'lsp-status'.config{
 993  				status_symbol = '', -- The default V breaks some layout stuff.  was the next I used, but it's not needed
 994  				show_filename = false, -- Takes up too much space, redundant
 995  				diagnostics = false, -- lualine actually already displays this information
 996  				kind_labels = require'lspkind'.symbol_map,
 997  			}
 998  			require'lsp-status'.register_progress()
 999  			vim.api.nvim_create_autocmd('LspAttach', {
1000  				callback = function(args)
1001  					local client = vim.lsp.get_client_by_id(args.data.client_id)
1002  					local bufnr = args.buf
1003  					require'lsp-status'.on_attach(client, bufnr)
1004  				end
1005  			})
1006  			vim.lsp.config('*', {
1007  				capabilities = require'lsp-status'.capabilities
1008  			})
1009  		end,
1010  		module = 'lsp-status'
1011  	},
1012  	-- Update command for mason
1013  	--  https://github.com/RubixDev/mason-update-all#updating-from-cli
1014  	{ 'RubixDev/mason-update-all',
1015  		opts = {},
1016  		cmd = "MasonUpdateAll",
1017  		dependencies = 'mason-org/mason.nvim'
1018  	},
1019  	-- Better folding
1020  	{ 'pierreglaser/folding-nvim',
1021  		-- TODO: this plugin makes use of deprecated functionality?
1022  		config = function()
1023  			vim.api.nvim_create_autocmd('LspAttach', {
1024  				callback = function(args)
1025  					local client = vim.lsp.get_client_by_id(args.data.client_id)
1026  					-- This is what it's doing internally. It's very dumb. TODO: it should be using capabilities
1027  					-- I have to do it this way otherwise it complains
1028  					if require'folding'.servers_supporting_folding[client.name] then
1029  						require'folding'.on_attach()
1030  					end
1031  				end
1032  			})
1033  		end,
1034  		event = "VeryLazy" -- TODO: better lazyness?
1035  	},
1036  
1037  	-- Completion details (uses LSP)
1038  	'rafamadriz/friendly-snippets',
1039  	{ 'L3MON4D3/LuaSnip',
1040  		config = function ()
1041  			-- Grab things from rafamadriz/friendly-snippets & etc.
1042  			require"luasnip.loaders.from_vscode".lazy_load()
1043  		end,
1044  		--  Pre-configured snippits
1045  		dependencies = 'friendly-snippets'
1046  	},
1047  	{ 'saadparwaiz1/cmp_luasnip',
1048  		-- Snippet source. (There's others out there too)
1049  		dependencies = 'LuaSnip',
1050  	},
1051  	{ 'uga-rosa/cmp-dictionary',
1052  		enabled = false,
1053  		config = function ()
1054  			local dict = require"cmp_dictionary"
1055  			dict.setup{ debug = true }
1056  			dict.switcher{ spelling = { en = "/usr/share/dict/words" } }
1057  		end
1058  	},
1059  	-- Lower the text sorting of completions starting with _
1060  	'lukas-reineke/cmp-under-comparator',
1061  	-- Use /usr/share/dict/words for completion
1062  	{ 'hrsh7th/nvim-cmp',
1063  		config = configure_nvim_cmp,
1064  		event = 'InsertEnter',
1065  		--dependencies  = {
1066  		--	'onsails/lspkind-nvim',
1067  		--	'nvim-lspconfig',
1068  		--	"nvim-lua/plenary.nvim",
1069  		--	'saadparwaiz1/cmp_luasnip',
1070  		--	-- Lower the text sorting of completions starting with _
1071  		--	'lukas-reineke/cmp-under-comparator',
1072  		--	-- Use /usr/share/dict/words for completion
1073  		--	'uga-rosa/cmp-dictionary'
1074  		--}
1075  	},
1076  	-- cmdline history completion
1077  	{ 'dmitmel/cmp-cmdline-history',
1078  		event = "VeryLazy", -- TODO: better lazyness?
1079  		dependencies = 'nvim-cmp',
1080  		enabled = false
1081  	},
1082  	-- Completion within this buffer
1083  	{ 'hrsh7th/cmp-buffer',
1084  		event = "VeryLazy", -- TODO: better lazyness?
1085  		dependencies = 'nvim-cmp'
1086  	},
1087  	-- Completion on the vim.lsp apis
1088  	{ 'hrsh7th/cmp-nvim-lua',
1089  		event = "VeryLazy", -- TODO: better lazyness?
1090  		dependencies = 'nvim-cmp'
1091  	},
1092  	-- Path completion
1093  	{ 'hrsh7th/cmp-path',
1094  		event = "VeryLazy", -- TODO: better lazyness?
1095  		dependencies = 'nvim-cmp'
1096  	},
1097  	-- VI : command completion
1098  	{ 'hrsh7th/cmp-cmdline',
1099  		event = "VeryLazy", -- TODO: better lazyness?
1100  		dependencies = 'nvim-cmp'
1101  	},
1102  	-- Use LSP symbols for buffer-style search
1103  	'hrsh7th/cmp-nvim-lsp',
1104  	{ 'hrsh7th/cmp-nvim-lsp-document-symbol',
1105  		event = "VeryLazy", -- TODO: better lazyness?
1106  		dependencies = { 'cmp-nvim-lsp', 'nvim-cmp' }
1107  	},
1108  	-- Git completion source
1109  	{ 'petertriho/cmp-git',
1110  		-- BUG: slows things down a ton when I type : in the commit box
1111  		event = "VeryLazy", -- TODO: better lazyness?
1112  		dependencies = 'nvim-cmp',
1113  		opts = {}
1114  		--[[config = function ()
1115  			require'cmp_git'.setup{}
1116  			-- TODO: this is per-buffer
1117  			--require'cmp'.setup.buffer{ sources = { { name = "git" } } }
1118  		end]]
1119  	},
1120  	-- crates.io completion source
1121  	{ 'saecki/crates.nvim',
1122  		dependencies = 'nvim-cmp',
1123  		event = "BufRead Cargo.toml",
1124  		config = function()
1125  			require'crates'.setup()
1126  			require'crates.completion.cmp'.setup()
1127  		end
1128  	},
1129  	-- package.json completion source
1130  	{ 'David-Kunz/cmp-npm',
1131  		dependencies = { 'plenary.nvim', 'nvim-cmp' },
1132  		event = "BufRead package.json",
1133  		cond = function  ()
1134  			return has_npm()
1135  		end,
1136  		opts = {}
1137  		--[[config = function ()
1138  			require'cmp-npm'.setup{}
1139  			-- TODO: this is per-buffer
1140  			--require'cmp'.setup.buffer{ sources = { { name = 'npm', keyword_length = 4 } } }
1141  		end]]
1142  	},
1143  	-- Fish completion
1144  	{ 'mtoohey31/cmp-fish',
1145  		ft = "fish", -- Only load on fish filetype
1146  		cond = function ()
1147  			-- Only load if fish is present
1148  			return has_the_command_that_some_call"fish"
1149  		end
1150  	},
1151  	-- Pandoc completion
1152  	-- Dude. I literally don't think I've ever used this.
1153  	--[[{
1154  		'jc-doyle/cmp-pandoc-references',
1155  		config = function ()
1156  			require'cmp'.setup.buffer{ sources = { { name = 'pandoc_references' } } }
1157  		end
1158  	},]]
1159  	-- latex symbol completion support (allows for inserting unicode)
1160  	{ 'kdheepak/cmp-latex-symbols',
1161  		event = "VeryLazy" -- TODO: better lazyness?
1162  	},
1163  	-- Emoji completion support
1164  	{ 'hrsh7th/cmp-emoji',
1165  		event = "VeryLazy" -- TODO: better lazyness?
1166  	},
1167  	-- conjure intractive eval completion
1168  	--use 'PaterJason/cmp-conjure' -- TODO: add this to cmp -- this might be a problem 987632498629765296987492
1169  	{ 'mfussenegger/nvim-dap',
1170  		config = function ()
1171  			vim.keymap.set('n', '<F5>', function()
1172  				require'dap'.continue()
1173  			end, {desc="DAP continue"})
1174  			vim.keymap.set('n', '<F10>', function()
1175  				require'dap'.step_over()
1176  			end, {desc="DAP step over"})
1177  			vim.keymap.set('n', '<F11>', function()
1178  				require'dap'.step_into()
1179  			end, {desc="DAP step into"})
1180  			vim.keymap.set('n', '<F12>', function()
1181  				require'dap'.step_out()
1182  			end, {desc="DAP step out"})
1183  			vim.keymap.set('n', '<Leader>b', function()
1184  				require'dap'.toggle_breakpoint()
1185  			end, {desc="DAP toggle breakpoint"})
1186  			vim.keymap.set('n', '<Leader>B', function()
1187  				require'dap'.set_breakpoint()
1188  			end, {desc="DAP set breakpoint"})
1189  			vim.keymap.set('n', '<Leader>lp', function()
1190  				require'dap'.set_breakpoint(nil, nil, vim.fn.input('Log point message: '))
1191  			end, {desc="DAP set logging breakpoint"})
1192  			vim.keymap.set('n', '<Leader>dr', function()
1193  				require'dap'.repl.open()
1194  			end, {desc="DAP open REPL"})
1195  			vim.keymap.set('n', '<Leader>dl', function()
1196  				require'dap'.run_last()
1197  			end, {desc="DAP run last"})
1198  			vim.keymap.set({'n', 'v'}, '<Leader>dh', function()
1199  				require'dap.ui.widgets'.hover()
1200  			end, {desc="DAP eval under the cursor into hover."})
1201  			vim.keymap.set({'n', 'v'}, '<Leader>dp', function()
1202  				require'dap.ui.widgets'.preview()
1203  			end, {desc="DAP eval under the cursor into window."})
1204  			vim.keymap.set('n', '<Leader>df', function()
1205  				local widgets = require'dap.ui.widgets'
1206  				widgets.centered_float(widgets.frames)
1207  			end, {desc='DAP view stack frames'})
1208  			vim.keymap.set('n', '<Leader>ds', function()
1209  				local widgets = require'dap.ui.widgets'
1210  				widgets.centered_float(widgets.scopes)
1211  			end, {desc='DAP view current scope'})
1212  
1213  			local dap = require"dap"
1214  			if has_the_command_that_some_call"godot" then
1215  				-- copied directly from
1216  				-- https://github.com/niscolas/nvim-godot/blob/main/nvim_config/lua/package_manager_config.lua
1217  				-- so this godot dap config is under MIT
1218  				dap.adapters.godot = {
1219  					type = "server",
1220  					host = "127.0.0.1",
1221  					port = 6006,
1222  				}
1223  				dap.configurations.gdscript = {
1224  					{
1225  						launch_game_instance = false,
1226  						launch_scene = false,
1227  						name = "Launch scene",
1228  						project = "${workspaceFolder}",
1229  						request = "launch",
1230  						type = "godot",
1231  					},
1232  				}
1233  			end
1234  		end
1235  	},
1236  	{ "jay-babu/mason-nvim-dap.nvim",
1237  		dependencies = {
1238  			'nvim-lspconfig', -- Mason needs to be setup first
1239  			'nvim-dap',
1240  		},
1241  		--event = 'BufEnter',
1242  		event = "VeryLazy", -- TODO: better lazyness?
1243  		config = function ()
1244  			require'mason-nvim-dap'.setup{
1245  				ensure_installed = tbflatten{
1246  					"js", "python",
1247  					-- TODO: this needs to be automatic
1248  					has_the_command_that_some_call"unzip" and {
1249  						"codelldb", "puppet", "cppdbg",
1250  						"bash",
1251  						-- For Java
1252  						--"javatest", "javadbj", -- java-debug-adapter
1253  					} or {},
1254  					has_npm() and {
1255  						"firefox", "chrome",
1256  						"node2",
1257  						"mock",
1258  					} or {}
1259  				},
1260  				automatic_installation = true,
1261  				handlers = {}
1262  			}
1263  		end
1264  	},
1265  	--{ 'mfussenegger/nvim-jdtls', ft = "java", dependencies = 'nvim-cmp' },
1266  	--[[{
1267  		-- This plugin does work, however it is made for modifying pairs in pre-exsisting code. Very nice, but doesn't do cmp
1268  		-- things.
1269  		"kylechui/nvim-surround",
1270  		version = "*", -- Omit to use `main` branch for latest features.
1271  		event = "VeryLazy", -- TODO: better lazyness?
1272  		config = function ()
1273  			require"nvim-surround".setup{
1274  			}
1275  		end
1276  	},]]
1277  	{ "windwp/nvim-autopairs",
1278  		-- Place pairs after typing, ex { causes } to appear.
1279  		event = "VeryLazy",
1280  		opts = {
1281  			fast_wrap = {
1282  				map = '<M-r>' -- <M-e> is to open the default GUI explorer in my WM
1283  			}
1284  		}
1285  	},
1286  	{
1287  		'brianhuster/live-preview.nvim',
1288  		event = "VeryLazy", -- TODO: better lazyness?
1289  		-- TODO: figure out pickers
1290  		---dependencies = {
1291  		---	-- You can choose one of the following pickers
1292  		---	'nvim-telescope/telescope.nvim',
1293  		---	'ibhagwan/fzf-lua',
1294  		---	'echasnovski/mini.pick',
1295  		---	'folke/snacks.nvim',
1296  		---},
1297  	},
1298  	--[[
1299  	{
1300  		-- TODO: could support more filetypes
1301  		"toppair/peek.nvim",
1302  		event = { "VeryLazy" },
1303  		build = "deno task --quiet build:fast",
1304  		config = function()
1305  			require"peek".setup()
1306  			vim.api.nvim_create_user_command("PeekOpen", require"peek".open, {})
1307  			vim.api.nvim_create_user_command("PeekClose", require"peek".close, {})
1308  		end,
1309  		cond = function () return has_the_command_that_some_call"deno" end
1310  	},]]
1311  	{ 'liuchengxu/graphviz.vim', lazy = false }, -- This package is already lazy
1312  }
1313  require"lazy".setup(lazy_plugins, lazy_config)
1314  -- vim.o.ambiwidth="double" -- use this if the arrows are cut off