all the languages!

This commit is contained in:
RingOfStorms (Joshua Bell) 2024-05-03 18:56:57 -05:00
parent 1eb427a6dc
commit eb7f522795
14 changed files with 630 additions and 548 deletions

View file

@ -61,9 +61,7 @@ rm -rf ~/.local/state/nvim
## NOTES/TODOS ## NOTES/TODOS
- h/l movement broken in insert mode, probably due to cmp hotkeys - See what linters/formaters to add or are the LSP's enough?
- h/l in telescope
- arrows still work in insert mode and telescope, need to remove trying to break arrow key habit
FUTURE FUTURE

View file

@ -87,7 +87,14 @@
"nvim_plugin-saadparwaiz1/cmp_luasnip" = cmp_luasnip; "nvim_plugin-saadparwaiz1/cmp_luasnip" = cmp_luasnip;
"nvim_plugin-hrsh7th/cmp-nvim-lsp" = cmp-nvim-lsp; "nvim_plugin-hrsh7th/cmp-nvim-lsp" = cmp-nvim-lsp;
"nvim_plugin-hrsh7th/cmp-path" = cmp-path; "nvim_plugin-hrsh7th/cmp-path" = cmp-path;
"nvim_plugin-hrsh7th/cmp-buffer" = cmp-buffer;
"nvim_plugin-zbirenbaum/copilot-cmp" = copilot-cmp;
"nvim_plugin-zbirenbaum/copilot.lua" = copilot-lua;
"nvim_plugin-folke/neodev.nvim" = neodev-nvim; "nvim_plugin-folke/neodev.nvim" = neodev-nvim;
"nvim_plugin-mrcjkb/rustaceanvim" = rustaceanvim;
"nvim_plugin-Saecki/crates.nvim" = crates-nvim;
"nvim_plugin-lvimuser/lsp-inlayhints.nvim" = lsp-inlayhints-nvim;
"nvim_plugin-rafamadriz/friendly-snippets" = friendly-snippets;
}; };
# This will be how we put any nix related stuff into our lua config # This will be how we put any nix related stuff into our lua config
luaNixGlobal = luaNixGlobal =
@ -113,6 +120,11 @@
fzf # search fuzzy fzf # search fuzzy
tree-sitter tree-sitter
glow # markdown renderer glow # markdown renderer
# curl # http requests TODO
# nodePackages.cspell TODO
];
defaultRuntimeDependencies = with pkgs; [
# linters # linters
markdownlint-cli markdownlint-cli
luajitPackages.luacheck luajitPackages.luacheck
@ -121,14 +133,23 @@
stylua stylua
nixfmt-rfc-style nixfmt-rfc-style
nodePackages.prettier nodePackages.prettier
rustywind
markdownlint-cli2 markdownlint-cli2
# LSPs # LSPs
nil # nix
lua-language-server lua-language-server
vscode-langservers-extracted # HTML/CSS/JSON/ESLint
nodePackages.typescript-language-server nodePackages.typescript-language-server
tailwindcss-language-server
nodePackages.pyright nodePackages.pyright
rust-analyzer
# curl # http requests TODO marksman # markdown
# nodePackages.cspell TODO taplo #toml
yaml-language-server
lemminx # xml
# Other
# typescript
nodejs_20
]; ];
in in
{ {
@ -152,6 +173,11 @@
"PATH" "PATH"
":" ":"
"${lib.makeBinPath runtimeDependencies}" "${lib.makeBinPath runtimeDependencies}"
# Some we will suffix so we pick up the local dev shell intead and default to these otherwise
"--suffix"
"PATH"
":"
"${lib.makeBinPath defaultRuntimeDependencies}"
# Set the LAZY env path to the nix store, see init.lua for how it is used # Set the LAZY env path to the nix store, see init.lua for how it is used
"--set" "--set"
"LAZY" "LAZY"

View file

@ -45,6 +45,13 @@ local function getSpec()
-- Convert plugins to use nix store, this auto sets the `dir` property for us on all plugins. -- Convert plugins to use nix store, this auto sets the `dir` property for us on all plugins.
local function convertPluginToNixStore(plugin) local function convertPluginToNixStore(plugin)
local p = ensure_table(plugin) local p = ensure_table(plugin)
if U.isArray(p) and #p > 1 then
local plugins = {}
table.foreachi(p, function(i, inner)
table.insert(plugins, convertPluginToNixStore(inner))
end)
return plugins
end
if p.enabled == false then if p.enabled == false then
return plugin return plugin
end end
@ -69,14 +76,11 @@ local function getSpec()
local plugins_path = debug.getinfo(2, "S").source:sub(2):match("(.*/)") .. "lua/plugins" local plugins_path = debug.getinfo(2, "S").source:sub(2):match("(.*/)") .. "lua/plugins"
for _, file in ipairs(vim.fn.readdir(plugins_path, [[v:val =~ '\.lua$']])) do for _, file in ipairs(vim.fn.readdir(plugins_path, [[v:val =~ '\.lua$']])) do
local plugin = string.sub(file, 0, -5) local plugin = string.sub(file, 0, -5)
table.insert(plugins, convertPluginToNixStore(require("plugins." .. plugin))) local converted = convertPluginToNixStore(require("plugins." .. plugin))
table.insert(plugins, converted)
end end
return plugins return plugins
else else
-- TODO I want this to work in the nixos versionhttps://github.com/RingOfStorms/nvim/blob/nix-flake/init.lua#L39-L55
-- but it is not resolving properly to the nix store.
-- Will revisit at some point, instead we manually pull them
-- in above with a directory scan.
return { { import = "plugins" } } return { { import = "plugins" } }
end end
end end

View file

@ -1,58 +1,60 @@
local group = vim.api.nvim_create_augroup("myconfig-autocommands-group", { clear = true }); local group = vim.api.nvim_create_augroup("myconfig-autocommands-group", { clear = true })
-- Highlight when yanking (copying) text -- Highlight when yanking (copying) text
-- Try it with `yap` in normal mode -- Try it with `yap` in normal mode
-- See `:help vim.highlight.on_yank()` -- See `:help vim.highlight.on_yank()`
vim.api.nvim_create_autocmd("TextYankPost", { vim.api.nvim_create_autocmd("TextYankPost", {
group = group, group = group,
desc = "Highlight when yanking (copying) text", desc = "Highlight when yanking (copying) text",
callback = function() callback = function()
vim.highlight.on_yank({ timeout = 300 }) vim.highlight.on_yank({ timeout = 300 })
end, end,
}) })
-- TODO is there a better way for these? -- TODO is there a better way for these?
-- https://www.youtube.com/watch?v=NecszftvMFI vim.filetype.add
vim.api.nvim_create_autocmd("BufRead", { vim.api.nvim_create_autocmd("BufRead", {
group = group, group = group,
pattern = ".env*", pattern = ".env*",
command = "set filetype=sh", command = "set filetype=sh",
}) })
vim.api.nvim_create_autocmd("BufRead", { vim.api.nvim_create_autocmd("BufRead", {
group = group, group = group,
pattern = ".*rc", pattern = ".*rc",
command = "set filetype=sh", command = "set filetype=sh",
}) })
vim.api.nvim_create_autocmd("BufRead", { vim.api.nvim_create_autocmd("BufRead", {
group = group, group = group,
pattern = "Dockerfile.*", pattern = "Dockerfile.*",
command = "set filetype=dockerfile", command = "set filetype=dockerfile",
}) })
vim.api.nvim_create_autocmd("BufRead", { vim.api.nvim_create_autocmd("BufRead", {
group = group, group = group,
pattern = "*.http", pattern = "*.http",
command = "set filetype=http", command = "set filetype=http",
}) })
-- Auto exit insert mode whenever we switch screens -- Auto exit insert mode whenever we switch screens
vim.api.nvim_create_autocmd({ "BufEnter", "BufWinEnter" }, { vim.api.nvim_create_autocmd({ "BufEnter", "BufWinEnter" }, {
group = group, group = group,
callback = function() callback = function()
if vim.bo.filetype ~= "TelescopePrompt" and vim.bo.filetype ~= nil and vim.bo.filetype ~= "" then if vim.bo.filetype ~= "TelescopePrompt" and vim.bo.filetype ~= nil and vim.bo.filetype ~= "" then
vim.api.nvim_command("stopinsert") vim.api.nvim_command("stopinsert")
end end
end, end,
}) })
vim.api.nvim_create_autocmd("VimLeavePre", { vim.api.nvim_create_autocmd("VimLeavePre", {
group = group, group = group,
callback = function() callback = function()
vim.cmd("NvimTreeClose") vim.cmd("NvimTreeClose")
-- Close all buffers with the 'httpResult' type -- Close all buffers with the 'httpResult' type
local close_types = { "httpResult", "noice", "help" } local close_types = { "httpResult", "noice", "help" }
local buffers = vim.api.nvim_list_bufs() local buffers = vim.api.nvim_list_bufs()
for _, bufnr in ipairs(buffers) do for _, bufnr in ipairs(buffers) do
if U.table_contains(close_types, vim.bo[bufnr].filetype) then if U.table_contains(close_types, vim.bo[bufnr].filetype) then
vim.api.nvim_buf_delete(bufnr, { force = true }) vim.api.nvim_buf_delete(bufnr, { force = true })
end end
end end
end, end,
}) })

View file

@ -84,7 +84,7 @@ U.keymaps({
-- Editor -- Editor
{ "J", "mzJ`z", desc = "Move line below onto this line" }, { "J", "mzJ`z", desc = "Move line below onto this line" },
{ -- TODO stay here, are these already mapped? {
"]d", "]d",
vim.diagnostic.goto_next, vim.diagnostic.goto_next,
desc = "Go to next diagnostic message", desc = "Go to next diagnostic message",
@ -107,13 +107,12 @@ U.keymaps({
{ "<C-6>", "<Home>", mode = { "i", "c" }, desc = "Movements in insert/command mode" }, { "<C-6>", "<Home>", mode = { "i", "c" }, desc = "Movements in insert/command mode" },
-- Tabs -- Tabs
-- TODO revisit, do I even need these tab things?
{ "<leader>tn", "<cmd>tabnew<cr>", desc = "Create new tab", mode = nvx }, { "<leader>tn", "<cmd>tabnew<cr>", desc = "Create new tab", mode = nvx },
{ "<leader>tq", "<cmd>tabclose<cr>", desc = "Close current tab", mode = nvx }, { "<leader>tq", "<cmd>tabclose<cr>", desc = "Close current tab", mode = nvx },
{ "H", "<cmd>tabprevious<cr>", desc = "Move to previous tab" }, { "H", "<cmd>tabprevious<cr>", desc = "Move to previous tab" },
{ "L", "<cmd>tabnext<cr>", desc = "Move to next tab" }, { "L", "<cmd>tabnext<cr>", desc = "Move to next tab" },
-- LSP/IDE/etc TODO move to lsp config file -- LSP/IDE/
{ {
"<leader>ld", "<leader>ld",
vim.diagnostic.open_float, vim.diagnostic.open_float,

View file

@ -53,14 +53,12 @@ vim.opt.undofile = true
-- and `:help 'listchars'` -- and `:help 'listchars'`
vim.opt.list = true vim.opt.list = true
vim.opt.listchars = { tab = "", trail = "·", nbsp = "", eol = "" } vim.opt.listchars = { tab = "", trail = "·", nbsp = "", eol = "" }
-- TODO REVISIT IF I WANT THESE
-- Search settings -- Search settings
vim.opt.hlsearch = true vim.opt.hlsearch = true
vim.opt.incsearch = true vim.opt.incsearch = true
-- Preview substitutions live, as you type -- Preview substitutions live, as you type
-- TODO revisit, what does this actually do
vim.opt.inccommand = "split" vim.opt.inccommand = "split"
-- Show which line your cursor is on -- Show which line your cursor is on

View file

@ -1,103 +1,127 @@
return { return {
"hrsh7th/nvim-cmp", "hrsh7th/nvim-cmp",
event = "InsertEnter", event = "InsertEnter",
dependencies = { dependencies = {
-- Snippet Engine & its associated nvim-cmp source -- Snippet Engine & its associated nvim-cmp source
{ {
"L3MON4D3/LuaSnip", "L3MON4D3/LuaSnip",
dependencies = { dependencies = {
-- TODO use or remove this? {
-- `friendly-snippets` contains a variety of premade snippets. "rafamadriz/friendly-snippets",
-- See the README about individual language/framework/plugin snippets: config = function()
-- https://github.com/rafamadriz/friendly-snippets require("luasnip.loaders.from_vscode").lazy_load()
-- { end,
-- 'rafamadriz/friendly-snippets', },
-- config = function() },
-- require('luasnip.loaders.from_vscode').lazy_load() },
-- end, "saadparwaiz1/cmp_luasnip",
-- },
},
},
"saadparwaiz1/cmp_luasnip",
-- Adds other completion capabilities. -- Adds other completion capabilities.
-- nvim-cmp does not ship with all sources by default. They are split -- nvim-cmp does not ship with all sources by default. They are split
-- into multiple repos for maintenance purposes. -- into multiple repos for maintenance purposes.
"hrsh7th/cmp-nvim-lsp", "hrsh7th/cmp-nvim-lsp",
"hrsh7th/cmp-path", "hrsh7th/cmp-buffer",
}, "hrsh7th/cmp-path",
config = function() {
-- See `:help cmp` "zbirenbaum/copilot.lua",
local cmp = require("cmp") cmd = "Copilot",
local luasnip = require("luasnip") event = "InsertEnter",
luasnip.config.setup({}) opts = {
-- suggestion = { enabled = false, auto_trigger = false },
-- panel = { enabled = false, auto_trigger = false },
},
main = "copilot",
},
{ "zbirenbaum/copilot-cmp", opts = {}, main = "copilot_cmp" },
},
config = function()
-- See `:help cmp`
local cmp = require("cmp")
local luasnip = require("luasnip")
luasnip.config.setup({})
cmp.setup({ cmp.setup({
snippet = { snippet = {
expand = function(args) expand = function(args)
luasnip.lsp_expand(args.body) luasnip.lsp_expand(args.body)
end, end,
}, },
completion = { completeopt = "menu,menuone,noinsert" }, completion = { completeopt = "menu,menuone,noinsert" },
-- For an understanding of why these mappings were mapping = cmp.mapping.preset.insert({
-- chosen, you will need to read `:help ins-completion` -- Scroll the documentation window [b]ack / [f]orward
-- ["<C-u>"] = cmp.mapping.scroll_docs(-4),
-- No, but seriously. Please read `:help ins-completion`, it is really good! ["<C-d>"] = cmp.mapping.scroll_docs(4),
mapping = cmp.mapping.preset.insert({ ["<esc>"] = cmp.mapping(function(fallback)
-- Select the [n]ext item if cmp.visible() then
["<C-j>"] = cmp.mapping.select_next_item(), cmp.abort()
-- Select the [p]revious item fallback()
["<C-k>"] = cmp.mapping.select_prev_item(), else
fallback()
end
end),
-- Scroll the documentation window [b]ack / [f]orward -- Select the [n]ext item
["<C-u>"] = cmp.mapping.scroll_docs(-4), ["<C-j>"] = cmp.mapping(function(fallback)
["<C-d>"] = cmp.mapping.scroll_docs(4), if cmp.visible() then
cmp.select_next_item()
-- Accept ([y]es) the completion. -- elseif luasnip.expand_or_jumpable() then
-- This will auto-import if your LSP supports it. elseif luasnip.expand_or_locally_jumpable() then
-- This will expand snippets if the LSP sent a snippet. luasnip.expand_or_jump()
["<C-y>"] = cmp.mapping.confirm({ select = true }), else
fallback()
-- If you prefer more traditional completion keymaps, end
-- you can uncomment the following lines end, { "i", "s" }),
--['<CR>'] = cmp.mapping.confirm { select = true }, -- Select the [p]revious item
--['<Tab>'] = cmp.mapping.select_next_item(), ["<C-k>"] = cmp.mapping(function(fallback)
--['<S-Tab>'] = cmp.mapping.select_prev_item(), if cmp.visible() then
cmp.select_prev_item()
-- Manually trigger a completion from nvim-cmp. elseif luasnip.jumpable(-1) then
-- Generally you don't need this, because nvim-cmp will display luasnip.jump(-1)
-- completions whenever it has completion options available. else
["<C-c>"] = cmp.mapping.complete({}), fallback()
end
-- TODO remove these or make them soemthing else, this collided with my normal movements in insert mode end, { "i", "s" }),
-- Think of <c-l> as moving to the right of your snippet expansion. ["<C-y>"] = cmp.mapping.confirm({ select = true }),
-- So if you have a snippet that's like: ["<C-space>"] = cmp.mapping.complete({}),
-- function $name($args) }),
-- $body sources = {
-- end {
-- name = "copilot",
-- <c-l> will move you to the right of each of the expansion locations. priority = 9,
-- <c-h> is similar, except moving you backwards. keyword_length = 1,
-- ["<C-l>"] = cmp.mapping(function() filter = function(keyword)
-- if luasnip.expand_or_locally_jumpable() then -- Check if keyword length is some number and not just whitespace
-- luasnip.expand_or_jump() if #keyword < 2 or keyword:match("^%s*$") then
-- end return false
-- end, { "i", "s" }), end
-- ["<C-h>"] = cmp.mapping(function() return true
-- if luasnip.locally_jumpable(-1) then end,
-- luasnip.jump(-1) },
-- end { name = "nvim_lsp", priority = 8, max_item_count = 100 },
-- end, { "i", "s" }), { name = "luasnip", priority = 7 },
-- This source provides file path completions, helping you to complete file paths in your code
-- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: { name = "path", priority = 7 },
-- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps -- This source provides completion items from the current buffer, meaning it suggests words that have already been typed in the same file.
}), { name = "buffer", priority = 6 },
sources = { -- Rust crates.io integration
{ name = "nvim_lsp" }, { name = "crates" },
{ name = "luasnip" }, },
{ name = "path" }, -- TODO revisit if I want these or not
}, -- sorting = {
}) -- priority_weight = 1,
end, -- comparators = {
-- cmp.config.compare.locality,
-- cmp.config.compare.recently_used,
-- cmp.config.compare.score,
-- cmp.config.compare.offset,
-- cmp.config.compare.order,
-- },
-- },
-- window = { -- also? https://github.com/RingOfStorms/nvim/blob/master/lua/plugins/lsp.lua#L330-L347
-- completion = cmp.config.window.bordered(),
-- documentation = cmp.config.window.bordered(),
-- },
})
end,
} }

View file

@ -1,137 +1,133 @@
-- TODO checkout https://github.com/nvim-lua/lsp-status.nvim
-- https://www.reddit.com/r/neovim/comments/o4bguk/comment/h2kcjxa/
local function lsp_clients() local function lsp_clients()
local clients = {} local clients = {}
for _, client in pairs(vim.lsp.buf_get_clients(0)) do for _, client in pairs(vim.lsp.buf_get_clients(0)) do
local name = client.name clients[#clients + 1] = client.name
-- TODO revisit this doesn't work end
if not client.initialized then table.sort(clients)
name = name .. " (loading)" return table.concat(clients, ""), ""
end
clients[#clients + 1] = name
end
table.sort(clients)
return table.concat(clients, ""), ""
end end
local function langs() local function langs()
local l = {} local l = {}
for _, client in pairs(vim.lsp.buf_get_clients(0)) do for _, client in pairs(vim.lsp.buf_get_clients(0)) do
local out = nil local out = nil
if client.name == "pyright" then if client.name == "pyright" then
out = vim.fn.system({ "python", "-V" }) out = vim.fn.system({ "python", "-V" })
elseif client.name == "tsserver" then elseif client.name == "tsserver" then
out = "node " .. vim.fn.system({ "node", "--version" }) out = "node " .. vim.fn.system({ "node", "--version" })
end end
if out ~= nil and out ~= "" then if out ~= nil and out ~= "" then
l[#l + 1] = vim.trim(out) l[#l + 1] = vim.trim(out)
end end
end end
table.sort(l) table.sort(l)
return table.concat(l, ""), "" return table.concat(l, ""), ""
end end
local last_blame = nil local last_blame = nil
local last_blame_time = vim.loop.now() local last_blame_time = vim.loop.now()
local function gitblame() local function gitblame()
local d = vim.b.gitsigns_blame_line_dict local d = vim.b.gitsigns_blame_line_dict
if d then if d then
last_blame = d last_blame = d
last_blame_time = vim.loop.now() last_blame_time = vim.loop.now()
elseif vim.loop.now() - last_blame_time <= 2000 then elseif vim.loop.now() - last_blame_time <= 2000 then
d = last_blame d = last_blame
end end
if d then if d then
local ok, res = pcall(os.date, "%d %b %y", d.committer_time) local ok, res = pcall(os.date, "%d %b %y", d.committer_time)
return d.committer:sub(1, 12) .. " - " .. (ok and res or d.committer_time) return d.committer:sub(1, 12) .. " - " .. (ok and res or d.committer_time)
end end
return "" return ""
end end
return { return {
"nvim-lualine/lualine.nvim", "nvim-lualine/lualine.nvim",
dependencies = { { "folke/noice.nvim", optional = true } }, dependencies = { { "folke/noice.nvim", optional = true } },
lazy = false, lazy = false,
opts = function() opts = function()
return { return {
options = { options = {
theme = "codedark", theme = "codedark",
section_separators = { left = "", right = "" }, section_separators = { left = "", right = "" },
component_separators = "|", component_separators = "|",
}, },
sections = { sections = {
lualine_a = { "mode" }, lualine_a = { "mode" },
lualine_b = { "branch", "diff", "diagnostics" }, lualine_b = {
lualine_c = { "branch",
{ "filename", separator = { right = "" } }, "filename",
{ "reg_recording", icon = { "󰻃" }, color = { fg = "#D37676" } }, },
{ gitblame, color = { fg = "#696969" } }, lualine_c = {
}, "diff",
lualine_x = { "diagnostics",
lsp_clients, { "reg_recording", icon = { "󰻃" }, color = { fg = "#D37676" } },
langs, { gitblame, color = { fg = "#696969" } },
"encoding", },
"filetype", lualine_x = {
"filesize", lsp_clients,
}, langs,
lualine_y = { "searchcount", "selectioncount" }, "encoding",
lualine_z = { "location" }, "filetype",
}, "filesize",
winbar = { },
lualine_a = { lualine_y = { "searchcount", "selectioncount" },
{ lualine_z = { "location" },
"filename", },
symbols = { winbar = {
modified = "", -- Text to show when the file is modified. lualine_a = {
readonly = "[-]", -- Text to show when the file is non-modifiable or readonly. {
unnamed = "[No Name]", -- Text to show for unnamed buffers. "filename",
newfile = "[New]", -- Text to show for newly created file before first write symbols = {
}, modified = "", -- Text to show when the file is modified.
}, readonly = "[-]", -- Text to show when the file is non-modifiable or readonly.
}, unnamed = "[No Name]", -- Text to show for unnamed buffers.
lualine_b = { newfile = "[New]", -- Text to show for newly created file before first write
"mode", },
}, },
}, },
inactive_winbar = { lualine_b = {
lualine_a = { "mode",
{ },
"filename", },
symbols = { inactive_winbar = {
modified = "", -- Text to show when the file is modified. lualine_a = {
readonly = "[-]", -- Text to show when the file is non-modifiable or readonly. {
unnamed = "[No Name]", -- Text to show for unnamed buffers. "filename",
newfile = "[New]", -- Text to show for newly created file before first write symbols = {
}, modified = "", -- Text to show when the file is modified.
}, readonly = "[-]", -- Text to show when the file is non-modifiable or readonly.
}, unnamed = "[No Name]", -- Text to show for unnamed buffers.
}, newfile = "[New]", -- Text to show for newly created file before first write
} },
end, },
config = function(_, opts) },
require("lualine").setup(opts) },
}
end,
config = function(_, opts)
require("lualine").setup(opts)
local ref = function() local ref = function()
require("lualine").refresh({ require("lualine").refresh({
place = { "statusline" }, place = { "statusline" },
}) })
end end
local group = vim.api.nvim_create_augroup("myconfig-lua-line-group", { clear = true }) local group = vim.api.nvim_create_augroup("myconfig-lua-line-group", { clear = true })
vim.api.nvim_create_autocmd("RecordingEnter", { vim.api.nvim_create_autocmd("RecordingEnter", {
group = group, group = group,
callback = ref, callback = ref,
}) })
vim.api.nvim_create_autocmd("RecordingLeave", { vim.api.nvim_create_autocmd("RecordingLeave", {
group = group, group = group,
callback = function() callback = function()
local timer = vim.loop.new_timer() local timer = vim.loop.new_timer()
timer:start(50, 0, vim.schedule_wrap(ref)) timer:start(50, 0, vim.schedule_wrap(ref))
end, end,
}) })
end, end,
} }

View file

@ -7,11 +7,6 @@ return {
}, },
event = "VeryLazy", event = "VeryLazy",
opts = { opts = {
routes = {
-- I want telescope-ui-select to trigger here not noice
{ filter = { event = "lsp", kind = "search_count" }, opts = { skip = true } },
{ filter = { event = "lsp" }, opts = { skip = true } }, -- TODO come back to this, im having weird issues with insert mode getting broken.
},
messages = { messages = {
view = "mini", -- default view for messages view = "mini", -- default view for messages
view_error = "notify", -- view for errors view_error = "notify", -- view for errors
@ -26,6 +21,8 @@ return {
["vim.lsp.util.stylize_markdown"] = true, ["vim.lsp.util.stylize_markdown"] = true,
["cmp.entry.get_documentation"] = true, -- requires hrsh7th/nvim-cmp ["cmp.entry.get_documentation"] = true, -- requires hrsh7th/nvim-cmp
}, },
-- I had an issue with auto_open kicking me out of insert mode when entering insert mode
signature = { auto_open = { trigger = false } },
}, },
}, },
config = function(_, opts) config = function(_, opts)

View file

@ -1,36 +1,45 @@
local function formatCurrent(retry)
require("conform").format({ async = true, lsp_fallback = true }, function(err, edited)
if edited then
print("Formatted!")
elseif err then
-- Sometimes I am too fast and vim is saving from my InsertExit and this fails so
-- I give it one retry
if not retry and string.find(err, "concurrent modification") then
return formatCurrent(true)
end
print(err)
else
print("Nothing to format!")
end
end)
end
return { return {
"stevearc/conform.nvim", "stevearc/conform.nvim",
opts = { opts = {
-- https://github.com/stevearc/conform.nvim?tab=readme-ov-file#setup -- https://github.com/stevearc/conform.nvim?tab=readme-ov-file#setup
notify_on_error = true, notify_on_error = true,
-- Note that all these need to be available at runtime, add them to flake.nix#runtimeDependencies -- Note that all these need to be available at runtime, add them to flake.nix#runtimeDependencies
formatters_by_ft = { formatters_by_ft = {
lua = { "stylua" }, lua = { "stylua" },
nix = { "nixfmt" }, nix = { "nixfmt" },
typescript = { { "prettierd", "prettier" } }, typescript = { { "prettierd", "prettier" }, "rustywind" },
typescriptreact = { { "prettierd", "prettier" } }, typescriptreact = { { "prettierd", "prettier" }, "rustywind" },
javascript = { { "prettierd", "prettier" } }, javascript = { { "prettierd", "prettier" }, "rustywind" },
javascriptreact = { { "prettierd", "prettier" } }, javascriptreact = { { "prettierd", "prettier" }, "rustywind" },
-- TODO revisit these I'd like to use them but they are not in nixpkgs yet
-- https://nixos.org/guides/nix-pills/ -- TODO revisit these I'd like to use them but they are not in nixpkgs yet
-- markdown = { "mdslw", "mdsf"}, -- https://nixos.org/guides/nix-pills/
markdown = { "markdownlint-cli2" }, -- markdown = { "mdslw", "mdsf"},
markdown = { "markdownlint-cli2" },
-- rust = { "rustfmt" },
}, },
}, },
keys = { keys = {
{ {
"<leader>l<leader>", "<leader>l<leader>",
function() formatCurrent,
require("conform").format({ async = true, lsp_fallback = true }, function(err, edited)
if edited then
print("Formatted!")
elseif err then
print(err)
else
print("Nothing to format!")
end
end)
end,
mode = { "n", "v", "x" }, mode = { "n", "v", "x" },
desc = "Format buffer", desc = "Format buffer",
}, },

View file

@ -1,145 +1,176 @@
return { return {
"neovim/nvim-lspconfig", -- LSP helper plugins for various languages
event = "BufEnter", { "folke/neodev.nvim", event = { "BufRead *.lua", "BufRead *.vim" }, opts = {}, main = "neodev" },
dependencies = { { "mrcjkb/rustaceanvim", lazy = false }, -- uses ftplugins to enable itself lazily already
-- Automatically install LSPs and related tools to stdpath for Neovim -- TODO add some hotkeys for opening the popup menus on crates
{ "williamboman/mason.nvim", enabled = not NIX, config = true }, -- NOTE: Must be loaded before dependants { "Saecki/crates.nvim", event = "BufRead Cargo.toml", tag = "stable", opts = {}, main = "crates" },
{ "williamboman/mason-lspconfig.nvim", enabled = not NIX }, {
{ "WhoIsSethDaniel/mason-tool-installer.nvim", enabled = not NIX }, "neovim/nvim-lspconfig",
event = "BufEnter",
dependencies = {
{
"lvimuser/lsp-inlayhints.nvim",
init = function()
vim.api.nvim_create_augroup("LspAttach_inlayhints", { clear = true })
vim.api.nvim_create_autocmd("LspAttach", {
group = "LspAttach_inlayhints",
callback = function(args)
if not (args.data and args.data.client_id) then
return
end
-- TODO revisit if I want this or not, is this already solved? local bufnr = args.buf
-- Useful status updates for LSP. local client = vim.lsp.get_client_by_id(args.data.client_id)
-- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})` require("lsp-inlayhints").on_attach(client, bufnr)
-- { "j-hui/fidget.nvim", opts = {} }, end,
})
end,
opts = {
type_hints = { prefix = " ::" },
},
main = "lsp-inlayhints",
},
-- Automatically install LSPs and related tools to stdpath for Neovim
{ "williamboman/mason.nvim", enabled = not NIX, config = true }, -- NOTE: Must be loaded before dependants
{ "williamboman/mason-lspconfig.nvim", enabled = not NIX },
{ "WhoIsSethDaniel/mason-tool-installer.nvim", enabled = not NIX },
},
config = function()
vim.api.nvim_create_autocmd("LspAttach", {
group = vim.api.nvim_create_augroup("myconfig-lsp-attach", { clear = true }),
callback = function(event)
local map = function(keys, func, desc)
vim.keymap.set("n", keys, func, { buffer = event.buf, desc = "LSP: " .. desc })
end
map("gd", require("telescope.builtin").lsp_definitions, "Goto Definition")
map("gr", require("telescope.builtin").lsp_references, "Goto References")
map("gI", require("telescope.builtin").lsp_implementations, "Goto Implementation")
map("<leader>lr", vim.lsp.buf.rename, "Rename")
map("<leader>la", vim.lsp.buf.code_action, "Code Action")
map("K", vim.lsp.buf.hover, "Hover Documentation")
map("gD", vim.lsp.buf.declaration, "Goto Declaration")
end,
})
-- `neodev` configures Lua LSP for your Neovim config, runtime and plugins vim.api.nvim_create_autocmd("LspDetach", {
-- used for completion, annotations and signatures of Neovim apis group = vim.api.nvim_create_augroup("myconfig-lsp-detach", { clear = true }),
{ "folke/neodev.nvim", opts = {}, main = "neodev" }, callback = function(event)
}, vim.lsp.buf.clear_references()
config = function() vim.api.nvim_clear_autocmds({ group = "myconfig-lsp-highlight", buffer = event.buf })
vim.api.nvim_create_autocmd("LspAttach", { end,
group = vim.api.nvim_create_augroup("myconfig-lsp-attach", { clear = true }), })
callback = function(event)
local map = function(keys, func, desc)
vim.keymap.set("n", keys, func, { buffer = event.buf, desc = "LSP: " .. desc })
end
map("gd", require("telescope.builtin").lsp_definitions, "Goto Definition")
map("gr", require("telescope.builtin").lsp_references, "Goto References")
map("gI", require("telescope.builtin").lsp_implementations, "Goto Implementation")
-- TODO do I want these?
-- map("<leader>D", require("telescope.builtin").lsp_type_definitions, "Type Definition")
-- map("<leader>ds", require("telescope.builtin").lsp_document_symbols, "Document Symbols")
-- map("<leader>ws", require("telescope.builtin").lsp_dynamic_workspace_symbols, "Workspace Symbols")
map("<leader>lr", vim.lsp.buf.rename, "Rename")
map("<leader>la", vim.lsp.buf.code_action, "Code Action")
map("K", vim.lsp.buf.hover, "Hover Documentation")
map("gD", vim.lsp.buf.declaration, "Goto Declaration")
local client = vim.lsp.get_client_by_id(event.data.client_id) local capabilities = vim.lsp.protocol.make_client_capabilities()
if client and client.server_capabilities.inlayHintProvider and vim.lsp.inlay_hint then U.safeRequire("cmp_nvim_lsp", function(c)
map("<leader>lth", function() capabilities = vim.tbl_deep_extend("force", capabilities, c.default_capabilities())
vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) end)
end, "Toggle Inlay Hints")
end
end,
})
vim.api.nvim_create_autocmd("LspDetach", { -- TODO finish porting over lsp configs: https://github.com/RingOfStorms/nvim/blob/master/lua/plugins/lsp.lua
group = vim.api.nvim_create_augroup("myconfig-lsp-detach", { clear = true }), local servers = {
callback = function(event) -- Some languages (like typescript) have entire language plugins that can be useful:
vim.lsp.buf.clear_references() -- https://github.com/pmizio/typescript-tools.nvim
vim.api.nvim_clear_autocmds({ group = "myconfig-lsp-highlight", buffer = event.buf }) --
end, -- But for many setups, the LSP (`tsserver`) will work just fine
}) -- Note that `rust-analyzer` is done via mrcjkb/rustaceanvim plugin above, do not register it here.
lua_ls = {
local capabilities = vim.lsp.protocol.make_client_capabilities() settings = {
U.safeRequire("cmp_nvim_lsp", function(c) Lua = {
capabilities = vim.tbl_deep_extend("force", capabilities, c.default_capabilities()) runtime = {
end) -- Tell the language server which version of Lua you're using
-- (most likely LuaJIT in the case of Neovim)
-- TODO finish porting over lsp configs: https://github.com/RingOfStorms/nvim/blob/master/lua/plugins/lsp.lua version = "LuaJIT",
local servers = { },
-- clangd = {}, completion = {
-- gopls = {}, callSnippet = "Replace",
-- pyright = {}, },
-- rust_analyzer = {}, workspace = {
-- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs checkThirdParty = false,
-- library = {
-- Some languages (like typescript) have entire language plugins that can be useful: vim.env.VIMRUNTIME,
-- https://github.com/pmizio/typescript-tools.nvim vim.api.nvim_get_runtime_file("", true),
-- vim.fn.expand("$VIMRUNTIME/lua"),
-- But for many setups, the LSP (`tsserver`) will work just fine vim.fn.expand("$VIMRUNTIME/lua/vim/lsp"),
tsserver = { },
-- typescript/javascript telemetry = { enable = false },
implicitProjectConfiguration = { diagnostics = {
checkJs = true, globals = {
}, "vim",
}, "require",
pyright = { "NIX",
-- python "U",
}, -- Hammerspoon for macos
lua_ls = { "hs",
-- cmd = { ... }, },
-- filetypes = { ...}, },
-- capabilities = {}, },
settings = { },
Lua = { },
runtime = { },
-- Tell the language server which version of Lua you're using nil_ls = {},
-- (most likely LuaJIT in the case of Neovim) tsserver = {
version = "LuaJIT", -- typescript/javascript
}, implicitProjectConfiguration = {
completion = { checkJs = true,
callSnippet = "Replace", },
}, },
workspace = { tailwindcss = {
checkThirdParty = false, -- tailwind css
library = { -- https://www.tailwind-variants.org/docs/getting-started#intellisense-setup-optional
vim.env.VIMRUNTIME, tailwindCSS = {
vim.api.nvim_get_runtime_file("", true), experimental = {
vim.fn.expand("$VIMRUNTIME/lua"), classRegex = {
vim.fn.expand("$VIMRUNTIME/lua/vim/lsp"), { "tv\\((([^()]*|\\([^()]*\\))*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]" },
}, },
telemetry = { enable = false }, },
diagnostics = { },
globals = { },
"vim", cssls = {
"require", -- css
"NIX", },
"U", jsonls = {
-- Hammerspoon -- json
"hs", },
}, pyright = {
}, -- python
}, },
-- You can toggle below to ignore Lua_LS's noisy `missing-fields` warnings marksman = {
-- diagnostics = { disable = { 'missing-fields' } }, -- markdown
}, },
}, taplo = {
}, -- toml
} },
if NIX then yamlls = {
local servers = vim.tbl_keys(servers or {}) -- yaml
for _, server_name in ipairs(servers) do },
local server_opts = servers[server_name] or {} lemminx = {
require("lspconfig")[server_name].setup(server_opts) -- xml
end },
else }
require("mason").setup() if NIX then
local ensure_installed = vim.tbl_keys(servers or {}) local lsp_servers = vim.tbl_keys(servers or {})
vim.list_extend(ensure_installed, { for _, server_name in ipairs(lsp_servers) do
"stylua", -- Used to format Lua code TODO come back to this, more about linter/formatter configs local server_opts = servers[server_name] or {}
}) require("lspconfig")[server_name].setup(server_opts)
require("mason-tool-installer").setup({ ensure_installed = ensure_installed }) end
require("mason-lspconfig").setup({ else
handlers = { -- TODO test this out on a non nix setup...
function(server_name) require("mason").setup()
local server = servers[server_name] or {} local ensure_installed = vim.tbl_keys(servers or {})
server.capabilities = vim.tbl_deep_extend("force", {}, capabilities, server.capabilities or {}) vim.list_extend(ensure_installed, {
require("lspconfig")[server_name].setup(server) "stylua", -- Used to format Lua code TODO come back to this, more about linter/formatter configs
end, })
}, require("mason-tool-installer").setup({ ensure_installed = ensure_installed })
}) require("mason-lspconfig").setup({
end handlers = {
end, function(server_name)
local server = servers[server_name] or {}
server.capabilities =
vim.tbl_deep_extend("force", {}, capabilities, server.capabilities or {})
require("lspconfig")[server_name].setup(server)
end,
},
})
end
end,
},
} }

View file

@ -11,7 +11,6 @@ return {
"<leader>,c", "<leader>,c",
function() function()
if next(vim.lsp.get_active_clients()) ~= nil then if next(vim.lsp.get_active_clients()) ~= nil then
-- TODO test that this works
vim.cmd("TextCaseOpenTelescopeLSPChange") vim.cmd("TextCaseOpenTelescopeLSPChange")
else else
vim.cmd("TextCaseOpenTelescope") vim.cmd("TextCaseOpenTelescope")

View file

@ -15,15 +15,15 @@ return {
local wk = require("which-key") local wk = require("which-key")
wk.setup(opts) wk.setup(opts)
wk.register({ wk.register({
["<leader>b"] = { name = "Buffers", mode = { "n", "x", "v", "c" } }, ["<leader>b"] = { name = "Buffers", mode = { "n", "x", "v" } },
["<leader>t"] = { name = "Tabs", mode = { "n", "x", "v", "c" } }, ["<leader>t"] = { name = "Tabs", mode = { "n", "x", "v" } },
["<leader>,"] = { name = "Miscellaneous Tools", mode = { "n", "x", "v", "c" } }, ["<leader>,"] = { name = "Miscellaneous Tools", mode = { "n", "x", "v" } },
-- ["<leader>c"] = { name = "Copilot" }, -- ["<leader>c"] = { name = "Copilot" },
["<leader>f"] = { name = "Find [Telescope]", mode = { "n", "x", "v", "c" } }, ["<leader>f"] = { name = "Find [Telescope]", mode = { "n", "x", "v" } },
-- ["<leader>fs"] = { name = "Find in Scratches [Telescope]" }, -- ["<leader>fs"] = { name = "Find in Scratches [Telescope]" },
["<leader>g"] = { name = "Git", mode = { "n", "x", "v", "c" } }, ["<leader>g"] = { name = "Git", mode = { "n", "x", "v" } },
["<leader>l"] = { name = "LSP", mode = { "n", "x", "v", "c" } }, ["<leader>l"] = { name = "LSP", mode = { "n", "x", "v" } },
["<leader>lf"] = { name = "LSP Find", mode = { "n", "x", "v", "c" } }, ["<leader>lf"] = { name = "LSP Find", mode = { "n", "x", "v" } },
-- ["<leader>Q"] = { name = "+Q Quit and remove session" }, -- ["<leader>Q"] = { name = "+Q Quit and remove session" },
-- ["<leader>s"] = { name = "Scratch Files" }, -- ["<leader>s"] = { name = "Scratch Files" },
-- ["<leader>x"] = { name = "Generative AI, Ollama" }, -- ["<leader>x"] = { name = "Generative AI, Ollama" },

View file

@ -1,30 +1,41 @@
local M = {} local M = {}
function M.isArray(table)
local i = 0
for _ in pairs(table) do
i = i + 1
if table[i] == nil then
return false
end
end
return true
end
function M.cmd_executable(cmd, callback) function M.cmd_executable(cmd, callback)
local executable = vim.fn.executable(cmd) == 1 local executable = vim.fn.executable(cmd) == 1
-- Check if a callback is provided and it is a function -- Check if a callback is provided and it is a function
if executable and callback and type(callback) == "function" then if executable and callback and type(callback) == "function" then
callback() callback()
end end
-- Check if a callback is provided and it is a table -- Check if a callback is provided and it is a table
if type(callback) == "table" then if type(callback) == "table" then
if executable and (callback[1] or callback[true]) then if executable and (callback[1] or callback[true]) then
-- Call the function associated with key 1 or true if the command is executable -- Call the function associated with key 1 or true if the command is executable
local func = callback[1] or callback[true] local func = callback[1] or callback[true]
if type(func) == "function" then if type(func) == "function" then
func() func()
end end
elseif not executable and (callback[2] or callback[false]) then elseif not executable and (callback[2] or callback[false]) then
-- Call the function associated with key 2 or false if the command is not executable -- Call the function associated with key 2 or false if the command is not executable
local func = callback[2] or callback[false] local func = callback[2] or callback[false]
if type(func) == "function" then if type(func) == "function" then
func() func()
end end
end end
end end
return executable return executable
end end
-- [1]: (string) lhs (required) -- [1]: (string) lhs (required)
@ -33,127 +44,115 @@ end
-- ft: (string|string[]) filetype for buffer-local keymaps (optional) -- ft: (string|string[]) filetype for buffer-local keymaps (optional)
-- any other option valid for vim.keymap.set -- any other option valid for vim.keymap.set
function M.keymaps(keymaps) function M.keymaps(keymaps)
-- is not an array, will pass directly to keymaps -- is not an array, will pass directly to keymaps
if type(keymaps[1]) == "string" then if type(keymaps[1]) == "string" then
M.keymap(keymaps) M.keymap(keymaps)
else else
-- is array will iterate over -- is array will iterate over
for _, keymap in pairs(keymaps) do for _, keymap in pairs(keymaps) do
M.keymap(keymap) M.keymap(keymap)
end end
end end
end end
function M.keymap(keymap) function M.keymap(keymap)
local lhs = keymap[1] local lhs = keymap[1]
local rhs = keymap[2] local rhs = keymap[2]
local mode = keymap["mode"] or "n" local mode = keymap["mode"] or "n"
local opts = { silent = true } local opts = { silent = true }
for key, value in pairs(keymap) do for key, value in pairs(keymap) do
if type(key) ~= "number" and key ~= "mode" then if type(key) ~= "number" and key ~= "mode" then
opts[key] = value opts[key] = value
end end
end end
local status, err = pcall(function() local status, err = pcall(function()
vim.keymap.set(mode, lhs, rhs, opts) vim.keymap.set(mode, lhs, rhs, opts)
end) end)
if not status then if not status then
vim.notify("Failed to create keymap: " .. err, 3) vim.notify("Failed to create keymap: " .. err, 3)
end end
end end
-- spread({})({}) -- spread({})({})
function M.spread(template) function M.spread(template)
local result = {} local result = {}
for key, value in pairs(template) do for key, value in pairs(template) do
result[key] = value result[key] = value
end end
return function(table) return function(table)
for key, value in pairs(table) do for key, value in pairs(table) do
result[key] = value result[key] = value
end end
return result return result
end end
end end
-- assign({}, {}) -- assign({}, {})
function M.assign(obj, assign) function M.assign(obj, assign)
for key, value in pairs(assign) do for key, value in pairs(assign) do
obj[key] = value obj[key] = value
end end
return obj return obj
end end
function M.table_contains(table, element) function M.table_contains(table, element)
for _, value in pairs(table) do for _, value in pairs(table) do
if value == element then if value == element then
return true return true
end end
end end
return false return false
end end
-- From https://github.com/lukas-reineke/onedark.nvim/blob/master/lua/onedark.lua -- From https://github.com/lukas-reineke/onedark.nvim/blob/master/lua/onedark.lua
function M.highlight(group, options) function M.highlight(group, options)
local guifg = options.fg or "NONE" local guifg = options.fg or "NONE"
local guibg = options.bg or "NONE" local guibg = options.bg or "NONE"
local guisp = options.sp or "NONE" local guisp = options.sp or "NONE"
local gui = options.gui or "NONE" local gui = options.gui or "NONE"
local blend = options.blend or 0 local blend = options.blend or 0
local ctermfg = options.ctermfg or "NONE" local ctermfg = options.ctermfg or "NONE"
vim.cmd( vim.cmd(
string.format( string.format(
"highlight %s guifg=%s ctermfg=%s guibg=%s guisp=%s gui=%s blend=%d", "highlight %s guifg=%s ctermfg=%s guibg=%s guisp=%s gui=%s blend=%d",
group, group,
guifg, guifg,
ctermfg, ctermfg,
guibg, guibg,
guisp, guisp,
gui, gui,
blend blend
) )
) )
end end
function M.safeRequire(module, func, errorFunc) function M.safeRequire(module, func, errorFunc)
local ok, result = pcall(require, module) local ok, result = pcall(require, module)
if ok then if ok then
return func(result) return func(result)
elseif errorFunc then elseif errorFunc then
return errorFunc(result) return errorFunc(result)
end end
return nil return nil
end end
-- TODO remove if not needed
-- local startup_time = vim.loop.now()
-- function M.delayFromStartup(delay, func)
-- local current_time = vim.loop.now()
-- local diff = current_time - startup_time
-- if diff >= delay then
-- func()
-- else
-- vim.defer_fn(func, (delay - diff))
-- end
-- end
function M.fnFalse() function M.fnFalse()
return false return false
end end
function M.fnNil() function M.fnNil()
return nil return nil
end end
function M.fnEmptyStr() function M.fnEmptyStr()
return "" return ""
end end
function M.fnZero() function M.fnZero()
return 0 return 0
end end
return M return M